[
  {
    "path": ".ci/__init__.py",
    "content": ""
  },
  {
    "path": ".ci/bump_dev_version.py",
    "content": "import os\nimport time\n\n\ndef replace_in_file(file_path, search, replace):\n    with open(file_path, \"r\") as handle:\n        content = handle.read()\n        if search not in content:\n            raise Exception(\"Incorrect development version in conan/__init__.py\")\n    content = content.replace(search, replace)\n    content = content.encode(\"utf-8\")\n    with open(file_path, \"wb\") as handle:\n        handle.write(content)\n\ndef bump_dev():\n    vfile = os.path.join(os.path.dirname(os.path.abspath(__file__)), \"../conan/__init__.py\")\n    snapshot = \"%s\" % int(time.time())\n    replace_in_file(vfile, \"-dev'\", \"-dev%s'\" % snapshot)\n\n\nif __name__ == \"__main__\":\n    bump_dev()\n"
  },
  {
    "path": ".ci/docker/conan-tests",
    "content": "FROM ubuntu:24.04\n\nLABEL maintainer=\"Conan.io <info@conan.io>\"\n\nENV DEBIAN_FRONTEND=noninteractive\n\nENV PY37=3.7.9 \\\n    PY38=3.8.6 \\\n    PY39=3.9.2 \\\n    PY310=3.10.16 \\\n    PY312=3.12.3 \\\n    PY313=3.13.0 \\\n    PY314=3.14.0 \\\n    CMAKE_3_15=/usr/share/cmake-3.15.7/bin/cmake \\\n    CMAKE_3_16=/usr/share/cmake-3.16.9/bin/cmake \\\n    CMAKE_3_17=/usr/share/cmake-3.17.5/bin/cmake \\\n    CMAKE_3_19=/usr/share/cmake-3.19.7/bin/cmake \\\n    CMAKE_3_23=/usr/share/cmake-3.23.5/bin/cmake \\\n    CMAKE_3_27=/usr/share/cmake-3.27.9/bin/cmake \\\n    CMAKE_4_2=/usr/share/cmake-4.2.1/bin/cmake \\\n    GCC_9=/usr/bin/gcc-9 \\\n    GXX_9=/usr/bin/g++-9 \\\n    GCC_11=/usr/bin/gcc-11 \\\n    GXX_11=/usr/bin/g++-11 \\\n    CLANG_14=/usr/bin/clang-14 \\\n    CLANGXX_14=/usr/bin/clang++-14 \\\n    BAZEL_6=6.5.0 \\\n    BAZEL_7=7.6.2 \\\n    BAZEL_8=8.4.2 \\\n    EMSDK=4.0.22\n\nRUN apt-get update && \\\n    apt-get install -y --no-install-recommends \\\n        software-properties-common \\\n        build-essential \\\n        libtool \\\n        automake \\\n        autoconf \\\n        pkg-config \\\n        gettext \\\n        git \\\n        curl \\\n        make \\\n        libssl-dev \\\n        zlib1g-dev \\\n        libbz2-dev \\\n        libreadline-dev \\\n        libsqlite3-dev \\\n        wget \\\n        llvm \\\n        libncurses5-dev \\\n        libncursesw5-dev \\\n        xz-utils \\\n        tk-dev \\\n        libffi-dev \\\n        liblzma-dev \\\n        libzstd-dev \\\n        python3-openssl \\\n        ca-certificates \\\n        sudo \\\n        tar \\\n        linux-libc-dev \\\n        subversion \\\n        subversion-tools \\\n        ninja-build \\\n        gcc-9 \\\n        g++-9 \\\n        gcc-11 \\\n        g++-11 \\\n        clang-14 \\\n        clang++-14 \\\n        gcc-arm-linux-gnueabihf \\\n        g++-arm-linux-gnueabihf \\\n        unzip \\\n        apt-transport-https \\\n        gnupg-agent \\\n        gcc-9-multilib \\\n        g++-9-multilib \\\n        gcc-11-multilib \\\n        g++-11-multilib \\\n        scons && \\\n    # fix: asm/errno.h: No such file or directory\n    ln -s /usr/include/asm-generic/ /usr/include/asm && \\\n    add-apt-repository -y ppa:ubuntu-toolchain-r/test && \\\n    apt-get update && \\\n    curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - && \\\n    add-apt-repository \"deb [arch=amd64] https://download.docker.com/linux/ubuntu jammy stable\" && \\\n    apt-get update && \\\n    apt-get install -y --no-install-recommends docker-ce docker-ce-cli containerd.io && \\\n    rm -rf /var/lib/apt/lists/*\n\nRUN useradd -m -s /bin/bash conan && \\\n    echo 'conan ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers\n\nENV HOME /home/conan\nENV PYENV_ROOT $HOME/.pyenv\nENV PATH $PYENV_ROOT/bin:$PYENV_ROOT/shims:/usr/bin:/bin:$PATH\n\nRUN curl https://pyenv.run | bash && \\\n    pyenv install $PY37 && \\\n    pyenv install $PY38 && \\\n    pyenv install $PY39 && \\\n    pyenv install $PY310 && \\\n    pyenv install $PY312 && \\\n    pyenv install $PY314 && \\\n    pyenv global $PY39 && \\\n    curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py && \\\n    python get-pip.py && \\\n    rm get-pip.py\n\nRUN chown -R conan:conan $HOME\n\nUSER root\n\nRUN wget https://github.com/Kitware/CMake/releases/download/v3.15.7/cmake-3.15.7-Linux-x86_64.tar.gz && \\\n    tar -xvzf cmake-3.15.7-Linux-x86_64.tar.gz && mv cmake-3.15.7-Linux-x86_64 /usr/share/cmake-3.15.7  && \\\n    wget https://github.com/Kitware/CMake/releases/download/v3.16.9/cmake-3.16.9-Linux-x86_64.tar.gz   && \\\n    tar -xvzf cmake-3.16.9-Linux-x86_64.tar.gz && mv cmake-3.16.9-Linux-x86_64 /usr/share/cmake-3.16.9 && \\\n    wget https://github.com/Kitware/CMake/releases/download/v3.17.5/cmake-3.17.5-Linux-x86_64.tar.gz   && \\\n    tar -xvzf cmake-3.17.5-Linux-x86_64.tar.gz && mv cmake-3.17.5-Linux-x86_64 /usr/share/cmake-3.17.5 && \\\n    wget https://github.com/Kitware/CMake/releases/download/v3.19.7/cmake-3.19.7-Linux-x86_64.tar.gz   && \\\n    tar -xvzf cmake-3.19.7-Linux-x86_64.tar.gz && mv cmake-3.19.7-Linux-x86_64 /usr/share/cmake-3.19.7 && \\\n    wget https://github.com/Kitware/CMake/releases/download/v3.23.5/cmake-3.23.5-Linux-x86_64.tar.gz   && \\\n    tar -xvzf cmake-3.23.5-Linux-x86_64.tar.gz && mv cmake-3.23.5-linux-x86_64/ /usr/share/cmake-3.23.5 && \\\n    wget https://github.com/Kitware/CMake/releases/download/v3.27.9/cmake-3.27.9-Linux-x86_64.tar.gz   && \\\n    tar -xvzf cmake-3.27.9-Linux-x86_64.tar.gz && mv cmake-3.27.9-linux-x86_64/ /usr/share/cmake-3.27.9 && \\\n    wget https://cmake.org/files/v4.2/cmake-4.2.1-linux-x86_64.tar.gz   && \\\n    tar -xvzf cmake-4.2.1-linux-x86_64.tar.gz && mv cmake-4.2.1-linux-x86_64/ /usr/share/cmake-4.2.1 && \\\n    update-alternatives --install /usr/bin/cmake cmake $CMAKE_3_15 10 && \\\n    update-alternatives --install /usr/bin/cmake cmake $CMAKE_3_16 20 && \\\n    update-alternatives --install /usr/bin/cmake cmake $CMAKE_3_17 30 && \\\n    update-alternatives --install /usr/bin/cmake cmake $CMAKE_3_19 40 && \\\n    update-alternatives --install /usr/bin/cmake cmake $CMAKE_3_23 50 && \\\n    update-alternatives --install /usr/bin/cmake cmake $CMAKE_3_27 60 && \\\n    update-alternatives --install /usr/bin/cmake cmake $CMAKE_4_2 70 && \\\n    # set CMake 3.15 as default\n    update-alternatives --set cmake $CMAKE_3_15\n\nRUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 10 && \\\n    update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-11 30 && \\\n    update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-9 10 && \\\n    update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-11 30 && \\\n    update-alternatives --install /usr/bin/clang clang /usr/bin/clang-14 10 && \\\n    update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-14 10 && \\\n    update-alternatives --set gcc /usr/bin/gcc-9 && \\\n    update-alternatives --set g++ /usr/bin/g++-9 && \\\n    update-alternatives --set clang /usr/bin/clang-14 && \\\n    update-alternatives --set clang++ /usr/bin/clang++-14\n\nRUN mkdir -p /usr/share/bazel-$BAZEL_6/bin && \\\n    wget https://github.com/bazelbuild/bazel/releases/download/${BAZEL_6}/bazel-${BAZEL_6}-linux-x86_64 && \\\n    chmod +x bazel-${BAZEL_6}-linux-x86_64 && \\\n    mv bazel-${BAZEL_6}-linux-x86_64 /usr/share/bazel-$BAZEL_6/bin/bazel && \\\n    mkdir -p /usr/share/bazel-$BAZEL_7/bin && \\\n    wget https://github.com/bazelbuild/bazel/releases/download/${BAZEL_7}/bazel-${BAZEL_7}-linux-x86_64 && \\\n    chmod +x bazel-${BAZEL_7}-linux-x86_64 && \\\n    mv bazel-${BAZEL_7}-linux-x86_64 /usr/share/bazel-$BAZEL_7/bin/bazel && \\\n    mkdir -p /usr/share/bazel-$BAZEL_8/bin && \\\n    wget https://github.com/bazelbuild/bazel/releases/download/${BAZEL_8}/bazel-${BAZEL_8}-linux-x86_64 && \\\n    chmod +x bazel-${BAZEL_8}-linux-x86_64 && \\\n    mv bazel-${BAZEL_8}-linux-x86_64 /usr/share/bazel-$BAZEL_8/bin/bazel\n\nRUN wget https://github.com/premake/premake-core/releases/download/v5.0.0-beta4/premake-5.0.0-beta4-linux.tar.gz && \\\n    tar -xvzf premake-5.0.0-beta4-linux.tar.gz && chmod +x premake5 && mkdir /usr/share/premake && \\\n    mv premake5 /usr/share/premake\n\nRUN cd /tmp && \\\n    mkdir qbs && \\\n    cd qbs && \\\n    curl -L https://download.qt.io/official_releases/qbs/2.6.0/qbs-linux-x86_64-2.6.0.tar.gz > qbs-linux-x86_64-2.6.0.tar.gz && \\\n    tar -xzf qbs-linux-x86_64-2.6.0.tar.gz && \\\n    mv qbs-linux-x86_64-2.6.0 /usr/share/qbs && \\\n    rm qbs-linux-x86_64-2.6.0.tar.gz\n\nRUN cd /tmp && \\\n    wget https://github.com/emscripten-core/emsdk/archive/refs/tags/${EMSDK}.tar.gz && \\\n    tar xzf ${EMSDK}.tar.gz --directory /usr/share && \\\n    cd /usr/share/emsdk-${EMSDK} && \\\n    pyenv local 3.12 && \\\n    ./emsdk update && \\\n    ./emsdk install latest && \\\n    ./emsdk activate latest --permanent && \\\n    . /usr/share/emsdk-${EMSDK}/emsdk_env.sh && \\\n    embuilder build MINIMAL && \\\n    embuilder build MINIMAL --wasm64\n    # echo \"EMSDK_QUIET=1 . /usr/share/emsdk-${EMSDK}/emsdk_env.sh\" >> /etc/bash.bashrc\n# Manually add the emsdk binaries to the PATH and set emcc cache directory to a writable location\nENV PATH=\"/usr/share/emsdk-$EMSDK:/usr/share/emsdk-$EMSDK/upstream/emscripten:/usr/share/emsdk-$EMSDK/node/22.16.0_64bit/bin:$PATH\" \\\n    EM_CACHE=$HOME/.emscripten_cache\n\nRUN echo \"export QT_NO_GLIB=1\" >> /etc/profile.d/qt.sh\n\nUSER conan\nWORKDIR $HOME\n\nCMD [\"/bin/bash\"]\n"
  },
  {
    "path": ".editorconfig",
    "content": "# https://editorconfig.org/\n\nroot = true\n\n[*]\nindent_style = space\nindent_size = 4\ninsert_final_newline = true\ntrim_trailing_whitespace = true\nend_of_line = lf\ncharset = utf-8\n\n# Docstrings and comments use max_line_length = 79\n[*.py]\nmax_line_length = 101\n"
  },
  {
    "path": ".github/CONTRIBUTING.md",
    "content": "Contributing to Conan\n=====================\n\nThe following summarizes the process for contributing to the Conan project.\n\nCommunity\n---------\n\nConan is an Open Source MIT licensed project.\nConan is developed by the Conan maintainers and a great community of contributors.\n\nDev-flow & Pull Requests\n------------------------\n\nConan follows the [\"GitFlow\"](https://datasift.github.io/gitflow/IntroducingGitFlow.html) branching model.\nIssues are triaged and categorized mainly by type (feature, bug...) complexity (high, medium...) and priority (high, medium...) using GitHub\n labels. Then they are moved to a stage called \"queue\" when they are considered to be ready for implementation.\n\nTo contribute follow the next steps:\n\n1. Comment in the corresponding issue that you want to contribute the feature/fix proposed. If there is no open issue, we strongly suggest\n   to open one to gather feedback.\n2. Check that the issue has been staged to \"queue\" or ask @conan-io/barbarians to do it. This helps in terms of validation and discussion of\n   possible implementation of the feature/fix.\n3. Fork the [Conan main repository](https://github.com/conan-io/conan) and create a `feature/xxx` branch from the `develop2` branch and develop\n   your fix/feature as discussed in previous step.\n4. Try to keep your branch updated with the `develop2` branch to avoid conflicts.\n5. Run the ``test/unittest`` and ``test/integration`` test suite locally, as described in [Conan tests guidelines section](https://github.com/conan-io/conan/blob/develop2/test/README.md). If you are doing changes to a build system integration, locate the respective folder for that integration in ``test/functional`` and run the tests of that folder. It is not expected that contributors have to run the full test suite locally, as it requires too many external tools.\n6. Open a pull request, and select `develop2` as the base branch. Never open a pull request to ``release/xxx`` branches, unless the branch is to be part of the next 2.X.Y patch. In that case, the PR should be targeted to ``release/2.X``.\n7. Add the text (besides other comments): \"fixes #IssueNumber\" in the body of the PR, referring to the issue of step 1.\n8. Submit a PR to the Conan documentation about the changes done providing examples if needed.\n\nThe ``conan-io`` organization maintainers will review and help with the coding of tests. Finally it will be assigned to milestone.\n\nEach milestone corresponds to a Conan release, a branch `release/xxx` will be opened from the `develop2` branch.\nWhen the branch is ready, a tag corresponding to the version will be pushed and it will be merged into `develop2` branch.\n\nThe release plan is done monthly but dates are not fixed, the ``conan-io`` organization maintainers reserve the right of altering the issues\nof each milestone as well as the release dates.\n\nIssues\n------\n\nIf you think you found a bug in Conan open an issue indicating the following:\n\n- Explain the Conan version, Operating System, compiler and any other tool that could be related to the issue.\n- Explain, as detailed as possible, how to reproduce the issue. Use git repos to contain code/recipes to reproduce issues.\n- Include the expected behavior as well as what actually happened.\n- Provide output captures (as text).\n- Feel free to attach a screenshot or video illustrating the issue if you think it will be helpful.\n\nFor any suggestion, feature request or question open an issue indicating the following:\n\n- Questions and support requests are always welcome.\n- Use the [question] or [suggestion] tags in the title.\n- Try to explain the motivation, what are you trying to do, what is the pain it tries to solve.\n- What do you expect from Conan.\n\nWe use the following tags to control the status of the issues:\n\n- **triaging**: Issue is being considered or under discussion. Maintainers are trying to understand the use case or gathering the necessary\n  information.\n- **queue**: Issue has been categorized and is ready to be done in a following release (not necessarily in the next one).\n- **in-progress**: A milestone has previously been assigned to the issue and is now under development.\n- **review**: Issue has a PR associated that solves it (remember to use the GitHub keywords \"closes #IssueNumber\", \"fixes #IssueNumber\"...\n  in the description of the PR).\n- **closed via PR**: A PR with the fix or new feature has been merged to `develop2` and the issue will be fixed in the next monthly release.\n\nCode of conduct\n---------------\n\nTry to be polite, Conan maintainers and contributors are really willing to help and we enjoy it.\n\nPlease keep in mind these points:\n\n- There are limited resources/time and not all issues/pull requests can be considered as well as we would like.\n- ``conan-io`` maintainers can tag/close/modify any opened issue and it should not be interpreted as a rude or disrespectful action. It\n  **always** responds to organizational purposes. A closed issue can be perfectly reopened or further commented.\n- It is very hard to keep the project in good health in terms of technical debt, usability, serviceability, etc. If the proposed feature is\n  not clearly stated, enough information is not provided or it is not sure that would be a good feature for the future development of the project, it won't be accepted. The community plays a very important role during this discussion so it strongly encouraged to\n  explain the value of a feature for the community, the needed documentation and its use cases.\n  - Backwards compatibility and not breaking users' packages is very important and it won't be done unless there are very good reasons.\n- You should not get bothered if you feel unattended, Conan is an Open Source project, not a commercial product. Try to explain what you\n  really need and we will try to help you.\n- The Conan maintainers won't tolerate harassment or abuse.\n\nIf a user is not following the code of conduct:\n\n   - We will contact the user to remind the rules.\n   - If the misconduct continues, they will be banned from the repository for one week.\n   - After that, any other code of conduct transgression will carry the permanent ban from all the conan-io organization repositories.\n\nCode style\n----------\n\n- In general, follow [pep8](https://www.python.org/dev/peps/pep-0008/)\n- Limit all lines to a maximum of 101 characters (`Right margin` setting in PyCharm)\n- Specify imports in the following order: system, `blank line`, 3rd-party, `blank line`, own; all sorted alphabetically:\n```\nimport os\nimport platform\nimport shutil\n\nfrom tqdm import tqdm\n\nfrom conan.tools.cmake import CMakeToolchain\nfrom conan.tools.files import save, load\n```\n- Write tests, if possible\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug.yml",
    "content": "name: Bug Report\ndescription: Report a bug, something does not work as it's supposed to\ntitle: '[bug]'\nbody:\n  - type: textarea\n    id: description\n    attributes:\n      label: Describe the bug\n      description: Include the bug description and environment details\n      placeholder: |\n        Environment details: OS, compiler, Conan version, Conan profiles, etc.\n        Description: xxxx\n    validations:\n      required: false\n  - type: textarea\n    id: steps\n    attributes:\n      label: How to reproduce it\n      description: It would be great to know how to reproduce it locally\n      placeholder: |\n        Commands to reproduce it, remote repository to use it locally, etc. Every detail is more than welcome!\n    validations:\n      required: false\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.yml",
    "content": "name: Feature Request\ndescription: Request a new feature or suggest a change\ntitle: '[feature] SHORT DESCRIPTION'\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Thanks for taking the time to submit a request. \n        **Please don't forget to update the issue title.**\n  - type: textarea\n    id: suggestion\n    attributes:\n      label: What is your suggestion?\n      description: Please be as specific as possible!\n      placeholder: Hi! I would like for conan to be able to ...\n    validations:\n      required: true\n  - type: checkboxes\n    id: contributing\n    attributes:\n      label: Have you read the CONTRIBUTING guide?\n      description: It can be found in [CONTRIBUTING.md](https://github.com/conan-io/conan/blob/develop/.github/CONTRIBUTING.md)\n      options:\n        - label: I've read the CONTRIBUTING guide\n    validations:\n      required: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/question.yml",
    "content": "name: Question\ndescription: If something needs clarification\ntitle: '[question] SHORT DESCRIPTION'\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Thanks for taking the time to fill your question. \n        **Please don't forget to update the issue title.**\n  - type: textarea\n    id: question\n    attributes:\n      label: What is your question?\n      description: Please be as specific as possible!\n      placeholder: Hi! I have a question regarding ...\n    validations:\n      required: true\n  - type: checkboxes\n    id: contributing\n    attributes:\n      label: Have you read the CONTRIBUTING guide?\n      description: It can be found in [CONTRIBUTING.md](https://github.com/conan-io/conan/blob/develop/.github/CONTRIBUTING.md)\n      options:\n        - label: I've read the CONTRIBUTING guide\n    validations:\n      required: true\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "Changelog: (Feature | Fix | Bugfix): Describe here your pull request\nDocs: https://github.com/conan-io/docs/pull/XXXX\n\n- [ ] Refer to the issue that supports this Pull Request.\n- [ ] If the issue has missing info, explain the purpose/use case/pain/need that covers this Pull Request.\n- [ ] I've read the [Contributing guide](https://github.com/conan-io/conan/blob/develop2/.github/CONTRIBUTING.md).\n- [ ] I've followed the PEP8 style guides for Python code.\n- [ ] I've opened another PR in the Conan docs repo to the ``develop`` branch, documenting this one.\n"
  },
  {
    "path": ".github/actions/test-coverage/action.yml",
    "content": "\ndescription: 'Run tests enabling coverage in certain conditions and upload coverage artifacts for later process'\n\ninputs:\n  python-version:\n    description: 'Python version in which the tests was ran'\n    required: true\n\n  test-type:\n    description: 'Test suite name'\n    required: true\n\n  duration:\n    description: 'Show N slowest test durations (N=0 for all)'\n    required: true\n    default: '10'\n\n  tests:\n    description: 'Tests folder and options to run'\n    required: false\n\n  workers:\n    description: 'Number of workers to run tests'\n    default: auto\n\nruns:\n  using: 'composite'\n  steps:\n      - name: Run tests with coverage\n        if: ${{ inputs.tests }}\n        shell: ${{ runner.os == 'Windows' && 'pwsh' || 'bash' }}\n        run: |\n          pytest ${{ inputs.tests }} --durations=${{ inputs.duration }} -n ${{ inputs.workers }} ${{ github.ref == 'refs/heads/develop2' && '--cov=conan --cov=conans --cov=test --cov-report=' || '' }}\n\n      - name: Rename coverage file\n        if: github.ref == 'refs/heads/develop2'\n        shell: bash\n        run: mv .coverage .coverage.${{ runner.os }}-${{ inputs.python-version }}-${{ inputs.test-type }}\n\n      - name: Upload coverage artifact\n        if: github.ref == 'refs/heads/develop2'\n        uses: actions/upload-artifact@v4\n        with:\n          name: .coverage.${{ runner.os }}-${{ inputs.python-version }}-${{ inputs.test-type }}\n          path: .coverage.${{ runner.os }}-${{ inputs.python-version }}-${{ inputs.test-type }}\n          include-hidden-files: true\n"
  },
  {
    "path": ".github/workflows/build-binaries.yml",
    "content": "name: Build Conan Binaries\nrun-name: Build Conan Binaries - v${{ inputs.conan_version }} - ${{ inputs.target_sha }} - ${{ inputs.request_id }}\n\non:\n  workflow_dispatch:\n    inputs:\n      conan_version: { description: Conan version to package, required: true, type: string }\n      target_sha:    { description: Git SHA to package,       required: true, type: string }\n      request_id:    { description: ID to identify run,       required: true, type: string }\n\npermissions:\n  contents: read\n\njobs:\n  package:\n    name: Package for ${{ matrix.platform }}/${{ matrix.arch }}\n    strategy:\n      fail-fast: false\n      matrix:\n        include:\n          - { platform: Linux,   arch: x86_64, runner: ubuntu-24.04 }\n          - { platform: Windows, arch: x86_64, runner: windows-2022 }\n          - { platform: Windows, arch: i686,   runner: windows-2022 }\n          - { platform: Windows, arch: arm64,  runner: windows-11-arm }\n          - { platform: Macos,   arch: arm64,  runner: macos-14 }\n          - { platform: Macos,   arch: x86_64, runner: macos-14 }\n          - { platform: Linux,   arch: arm64,  runner: ubuntu-24.04-arm }\n    runs-on: ${{ matrix.runner }}\n\n    steps:\n      - name: Show inputs\n        shell: bash\n        run: |\n          echo \"conan_version=${{ inputs.conan_version }}\"\n          echo \"target_sha=${{ inputs.target_sha }}\"\n          echo \"request_id=${{ inputs.request_id }}\"\n\n      - name: Generate Read-Only App Token\n        id: generate_token\n        uses: actions/create-github-app-token@v2\n        with:\n          app-id: ${{ secrets.GH_APP_RELEASE_ID }}\n          private-key: ${{ secrets.GH_APP_RELEASE_PRIVATE_KEY }}\n          permission-contents: read\n          owner: conan-io\n          repositories: |\n            conan\n            release-tools\n\n      - name: Checkout release-tools\n        uses: actions/checkout@v4\n        with:\n          repository: conan-io/release-tools\n          token: ${{ steps.generate_token.outputs.token }}\n\n      - name: Build packages\n        shell: bash\n        env:\n          PLATFORM: ${{ matrix.platform }}\n          ARCH: ${{ matrix.arch }}\n        run: |\n          ./jenkins/build_packages.sh \"${{ inputs.conan_version }}\" \"${{ inputs.target_sha }}\"\n\n      - name: Upload artifacts\n        uses: actions/upload-artifact@v4\n        with:\n          name: conan-${{ inputs.conan_version }}-${{ inputs.target_sha }}-${{ matrix.platform }}-${{ matrix.arch }}-${{ inputs.request_id }}\n          path: dist/*\n"
  },
  {
    "path": ".github/workflows/linux-tests.yml",
    "content": "name: Linux tests\n\non:\n  workflow_call:\n    inputs:\n      python-versions:\n        required: true\n        type: string\n      run-slow-tests:\n        required: false\n        default: 'false'\n        type: string\n\njobs:\n  build_container:\n    runs-on: ubuntu-latest\n    name: Build Linux container\n    outputs:\n      image_tag: ${{ steps.dockerfile_hash.outputs.tag }}\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v4\n\n      - name: Log in to GitHub Container Registry\n        uses: docker/login-action@v3\n        with:\n          registry: ghcr.io\n          username: ${{ github.actor }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n\n      - name: Calculate Dockerfile checksum\n        id: dockerfile_hash\n        run: |\n          DOCKERFILE_HASH=$(find ./.ci/docker/conan-tests -type f -exec sha256sum {} \\; | sha256sum | cut -d' ' -f1)\n          echo \"tag=$DOCKERFILE_HASH\" >> $GITHUB_OUTPUT\n\n      - name: Check if image exists\n        id: check_image\n        run: |\n          if docker manifest inspect ghcr.io/${{ github.repository_owner }}/conan-tests:${{ steps.dockerfile_hash.outputs.tag }} > /dev/null 2>&1; then\n            echo \"status=exists\" >> $GITHUB_OUTPUT\n          else\n            echo \"status=no-image\" >> $GITHUB_OUTPUT\n          fi\n\n      - name: Build and push image if not exists\n        if: steps.check_image.outputs.status == 'no-image'\n        run: |\n          docker build -t ghcr.io/${{ github.repository_owner }}/conan-tests:${{ steps.dockerfile_hash.outputs.tag }} -f ./.ci/docker/conan-tests .\n          docker push ghcr.io/${{ github.repository_owner }}/conan-tests:${{ steps.dockerfile_hash.outputs.tag }}\n\n  linux_tests:\n    needs: build_container\n    runs-on: ubuntu-latest\n    container:\n      image: ghcr.io/${{ github.repository_owner }}/conan-tests:${{ needs.build_container.outputs.image_tag }}\n      options: --user conan\n    strategy:\n      matrix:\n        python-version: ${{ fromJson(inputs.python-versions) }}\n        test-type: [unittests, integration, functional]\n        include:\n        - test-type: unittests\n          test-name: Unit\n        - test-type: integration\n          test-name: Integration\n        - test-type: functional\n          test-name: Functional\n    name: ${{ matrix.test-name }} Tests (${{ matrix.python-version }})\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v4\n\n      - name: Set up Python ${{ matrix.python-version }}\n        run: |\n          pyenv global ${{ matrix.python-version }}\n          python --version\n\n      - name: Cache pip\n        uses: actions/cache@v4\n        with:\n          path: ~/.cache/pip\n          key: ${{ runner.os }}-pip-${{ matrix.python-version }}-${{ hashFiles('**/requirements*.txt') }}\n\n      - name: Install dependencies\n        run: |\n          pip install --upgrade pip\n          pip install -r conans/requirements.txt\n          pip install -r conans/requirements_dev.txt\n          pip install -r conans/requirements_server.txt\n          pip install meson\n\n      - name: Run tests\n        uses: ./.github/actions/test-coverage\n        with:\n          python-version: ${{ matrix.python-version }}\n          test-type: ${{ matrix.test-type }}\n          tests: ${{ matrix.test-type == 'functional' && (inputs.run-slow-tests == 'true' && 'test/functional' || 'test/functional -m \"not slow\"') || format('test/{0}', matrix.test-type) }}\n\n  linux_runner_tests:\n    needs: build_container\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        # Use modern versions due to docker incompatibility with python <3.8\n        python-version: ${{ github.event_name != 'pull_request' && fromJson('[\"3.13\", \"3.9\"]') || fromJson('[\"3.10\"]') }}\n\n    name: Runner Tests (${{ matrix.python-version }})\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v4\n\n      - name: Set up Python ${{ matrix.python-version }}\n        uses: actions/setup-python@v5\n        with:\n          python-version: ${{ matrix.python-version }}\n\n      - name: Cache pip\n        uses: actions/cache@v4\n        with:\n          path: ~/.cache/pip\n          key: ${{ runner.os }}-pip-${{ matrix.python-version }}-${{ hashFiles('**/requirements_runner*.txt') }}\n\n      - name: Install dependencies\n        run: |\n          pip install --upgrade pip\n          pip install -r conans/requirements.txt\n          pip install -r conans/requirements_dev.txt\n          pip install -r conans/requirements_server.txt\n          pip install -r conans/requirements_runner.txt\n\n      - name: Run runner tests\n        uses: ./.github/actions/test-coverage\n        with:\n          python-version: ${{ matrix.python-version }}\n          test-type: runners\n          tests: '-m docker_runner -rs'\n          workers: 1\n"
  },
  {
    "path": ".github/workflows/main.yml",
    "content": "name: Main Workflow\non:\n  push:\n    branches:\n      - develop2\n      - release/*\n      - '*'\n  pull_request:\n    branches:\n      - '*'\n      - 'release/*'\n  workflow_dispatch:\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}\n  cancel-in-progress: true\n\njobs:\n  ensure_latest_tag_merged:\n    runs-on: ubuntu-latest\n    name: Ensure latest release is merged in develop2 branch\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          fetch-depth: 0\n      - shell: bash\n        run: |\n          git fetch --tags --prune\n          latest_tag=$(git tag -l --sort=-v:refname | head -n1)\n          echo \"Checking that branch 'develop2' contains the latest release tag: $latest_tag\"\n          git merge-base --is-ancestor \"$latest_tag\" origin/develop2\n\n  set_python_versions:\n    runs-on: ubuntu-latest\n    outputs:\n      python_versions_linux_windows: ${{ steps.set_versions.outputs.python_versions_linux_windows }}\n      python_versions_macos: ${{ steps.set_versions.outputs.python_versions_macos }}\n      run_slow_tests: ${{ steps.set_versions.outputs.run_slow_tests }}\n    name: Determine Python versions\n    steps:\n      - name: Fetch current PR body and check for slow-tests marker\n        if: github.event_name == 'pull_request'\n        id: fetch_pr\n        run: |\n          BODY=$(curl -s -H \"Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}\" \\\n            \"https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}\" \\\n            | jq -r '.body // \"\"')\n          if echo \"$BODY\" | grep -Fq '$runslowtests'; then\n            echo \"run_slow_tests=true\" >> $GITHUB_OUTPUT\n          else\n            echo \"run_slow_tests=false\" >> $GITHUB_OUTPUT\n          fi\n\n      - name: Determine Python versions\n        id: set_versions\n        run: |\n          if [[ \"${{ github.ref }}\" == \"refs/heads/develop2\" || \"${{ github.ref }}\" == refs/heads/release/* ]]; then\n            echo \"python_versions_linux_windows=['3.14', '3.7']\" >> $GITHUB_OUTPUT\n            echo \"python_versions_macos=['3.14', '3.8']\" >> $GITHUB_OUTPUT\n          else\n            echo \"python_versions_linux_windows=['3.10']\" >> $GITHUB_OUTPUT\n            echo \"python_versions_macos=['3.10']\" >> $GITHUB_OUTPUT\n          fi\n\n          # Run slow tests on develop2, or when PR description contains $runslowtests (checked in fetch_pr step)\n          if [[ \"${{ github.ref }}\" == \"refs/heads/develop2\" ]]; then\n            echo \"run_slow_tests=true\" >> $GITHUB_OUTPUT\n          elif [[ \"${{ github.event_name }}\" == \"pull_request\" ]]; then\n            echo \"run_slow_tests=${{ steps.fetch_pr.outputs.run_slow_tests }}\" >> $GITHUB_OUTPUT\n          else\n            echo \"run_slow_tests=false\" >> $GITHUB_OUTPUT\n          fi\n\n  linux_suite:\n    needs: [ensure_latest_tag_merged, set_python_versions]\n    uses: ./.github/workflows/linux-tests.yml\n    name: Linux test suite\n    with:\n      python-versions: ${{ needs.set_python_versions.outputs.python_versions_linux_windows }}\n      run-slow-tests: ${{ needs.set_python_versions.outputs.run_slow_tests }}\n\n  osx_suite:\n    needs: [ensure_latest_tag_merged, set_python_versions]\n    uses: ./.github/workflows/osx-tests.yml\n    name: OSX test suite\n    with:\n      python-versions: ${{ needs.set_python_versions.outputs.python_versions_macos }}\n      run-slow-tests: ${{ needs.set_python_versions.outputs.run_slow_tests }}\n\n  windows_suite:\n    needs: [ensure_latest_tag_merged, set_python_versions]\n    uses: ./.github/workflows/win-tests.yml\n    name: Windows test suite\n    with:\n      python-versions: ${{ needs.set_python_versions.outputs.python_versions_linux_windows }}\n      run-slow-tests: ${{ needs.set_python_versions.outputs.run_slow_tests }}\n\n  code_coverage:\n    runs-on: ubuntu-latest\n    name: Code coverage\n    if: github.ref == 'refs/heads/develop2'         # Only measure code coverage on main branch\n    needs: [linux_suite, osx_suite, windows_suite]\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v4\n\n      - name: Download coverage artifacts\n        uses: actions/download-artifact@v4\n        with:\n          merge-multiple: true\n\n      - name: Merge coverage reports\n        run: |\n          pip install coverage\n          coverage combine\n          coverage report\n          coverage xml\n\n      - name: Code coverage\n        uses: codecov/codecov-action@v5\n        with:\n          token: ${{ secrets.CODECOV_TOKEN }}\n\n      - uses: geekyeggo/delete-artifact@v5\n        with:\n          name: |\n            .coverage.*\n\n  deploy_to_pypi_test:\n    runs-on: ubuntu-latest\n    name: Deploy to TestPyPI\n    if: github.ref == 'refs/heads/develop2'\n    needs: [linux_suite, osx_suite, windows_suite]\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v4\n\n      - name: Set up Python\n        uses: actions/setup-python@v5\n        with:\n          python-version: 3.9\n\n      - name: Install dependencies\n        run: |\n          pip install --upgrade pip\n          pip install twine\n\n      - name: Bump Dev Version\n        run: |\n          python .ci/bump_dev_version.py\n\n      - name: Build Package\n        run: |\n          python setup.py sdist\n\n      - name: Upload to TestPyPI\n        env:\n          TWINE_USERNAME: ${{ secrets.TEST_PYPI_USERNAME }}\n          TWINE_PASSWORD: ${{ secrets.TEST_PYPI_PASSWORD }}\n        run: |\n          python -m twine upload --verbose --repository-url https://test.pypi.org/legacy/ dist/*\n\n      - name: Deploy conan-server to TestPyPI\n        env:\n          TWINE_USERNAME: ${{ secrets.TEST_PYPI_SERVER_USERNAME }}\n          TWINE_PASSWORD: ${{ secrets.TEST_PYPI_SERVER_PASSWORD }}\n        run: |\n          rm -rf dist/\n          mv setup_server.py setup.py\n          python setup.py sdist\n          python -m twine upload --verbose --repository-url https://test.pypi.org/legacy/ dist/*\n"
  },
  {
    "path": ".github/workflows/osx-tests.yml",
    "content": "name: OSX Tests\n\non:\n  workflow_call:\n    inputs:\n      python-versions:\n        required: true\n        type: string\n      run-slow-tests:\n        required: false\n        default: 'false'\n        type: string\n\njobs:\n  osx_setup:\n    runs-on: macos-15\n    name: Setup and Cache Dependencies\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v4\n\n      - name: Set up Python\n        uses: actions/setup-python@v5\n        with:\n          python-version: '3.10'\n\n      - name: Install Python requirements\n        run: |\n          pip install --upgrade pip\n          pip install -r conans/requirements.txt\n          pip install -r conans/requirements_server.txt\n          pip install -r conans/requirements_dev.txt\n          pip install meson\n\n      - name: Uninstall default CMake\n        run: brew uninstall --formula cmake || true\n\n      - name: Cache Homebrew packages\n        id: cache-brew\n        uses: actions/cache@v4\n        with:\n          path: ~/Library/Caches/Homebrew\n          key: ${{ runner.os }}-brew\n\n      - name: Install homebrew dependencies\n        run: |\n          brew install xcodegen make libtool zlib autoconf automake ninja emscripten\n\n      - name: Cache CMake and Bazel installations\n        id: cache-tools\n        uses: actions/cache@v4\n        with:\n          path: |\n            ~/Applications/CMake/3.15.7\n            ~/Applications/CMake/3.19.7\n            ~/Applications/CMake/3.23.5\n            ~/Applications/CMake/3.27.9\n            ~/Applications/CMake/4.2.1\n            ~/Applications/bazel/6.5.0\n            ~/Applications/bazel/7.6.2\n            ~/Applications/bazel/8.4.2\n          key: ${{ runner.os }}-conan-tools-cache\n\n      - name: Build CMake old versions not available for ARM\n        if: steps.cache-tools.outputs.cache-hit != 'true'\n        run: |\n          set -e\n          CMAKE_BUILD_VERSIONS=(\"3.15.7\")\n          for version in \"${CMAKE_BUILD_VERSIONS[@]}\"; do\n            echo \"Compiling CMake version ${version} from source for ARM...\"\n            wget -q --no-check-certificate https://cmake.org/files/v${version%.*}/cmake-${version}.tar.gz\n            tar -xzf cmake-${version}.tar.gz\n            cd cmake-${version}\n            mkdir build && cd build\n            ../bootstrap --prefix=${HOME}/Applications/CMake/${version} -- -DCMAKE_USE_OPENSSL=ON\n            make -j$(sysctl -n hw.ncpu)\n            make install\n            ${HOME}/Applications/CMake/${version}/bin/cmake --version\n            cd ../../\n            rm -rf cmake-${version} cmake-${version}.tar.gz\n          done\n\n      - name: Install universal CMake versions\n        if: steps.cache-tools.outputs.cache-hit != 'true'\n        run: |\n          set -e\n          CMAKE_PRECOMP_VERSIONS=(\"3.19.7\" \"3.23.5\" \"3.27.9\" \"4.2.1\")\n          for version in \"${CMAKE_PRECOMP_VERSIONS[@]}\"; do\n            echo \"Downloading and installing precompiled universal CMake version ${version}...\"\n            wget -q --no-check-certificate https://cmake.org/files/v${version%.*}/cmake-${version}-macos-universal.tar.gz\n            tar -xzf cmake-${version}-macos-universal.tar.gz \\\n              --exclude=CMake.app/Contents/bin/cmake-gui \\\n              --exclude=CMake.app/Contents/doc/cmake \\\n              --exclude=CMake.app/Contents/share/cmake-${version%.*}/Help \\\n              --exclude=CMake.app/Contents/share/vim\n            mkdir -p ${HOME}/Applications/CMake/${version}\n            cp -fR cmake-${version}-macos-universal/CMake.app/Contents/* ${HOME}/Applications/CMake/${version}\n            ${HOME}/Applications/CMake/${version}/bin/cmake --version\n            rm -rf cmake-${version}-macos-universal\n            rm cmake-${version}-macos-universal.tar.gz\n          done\n\n      - name: Install Bazel versions\n        if: steps.cache-tools.outputs.cache-hit != 'true'\n        run: |\n          set -e\n          for version in 6.5.0 7.6.2 8.4.2; do\n            mkdir -p ${HOME}/Applications/bazel/${version}\n            wget -q -O ${HOME}/Applications/bazel/${version}/bazel https://github.com/bazelbuild/bazel/releases/download/${version}/bazel-${version}-darwin-arm64\n            chmod +x ${HOME}/Applications/bazel/${version}/bazel\n          done\n\n  osx_tests:\n    needs: osx_setup\n    runs-on: macos-15\n    strategy:\n      fail-fast: true\n      matrix:\n        python-version: ${{ fromJson(inputs.python-versions) }}\n        test-type: [unittests, integration, functional]\n        include:\n        - test-type: unittests\n          test-name: Unit\n        - test-type: integration\n          test-name: Integration\n        - test-type: functional\n          test-name: Functional\n    name: ${{ matrix.test-name }} Tests (${{ matrix.python-version }})\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v4\n\n      - name: Restore tools cache\n        uses: actions/cache@v4\n        with:\n          path: |\n            ~/Applications/CMake/3.15.7\n            ~/Applications/CMake/3.19.7\n            ~/Applications/CMake/3.23.5\n            ~/Applications/CMake/3.27.9\n            ~/Applications/CMake/4.2.1\n            ~/Applications/bazel/6.5.0\n            ~/Applications/bazel/7.6.2\n            ~/Applications/bazel/8.4.2\n          key: ${{ runner.os }}-conan-tools-cache\n\n      - name: Select Xcode 16.4\n        run: |\n          sudo xcode-select -s /Applications/Xcode_16.4.app\n          xcodebuild -version\n          xcrun --sdk macosx --show-sdk-version\n          clang --version\n\n      # Install system dependencies BEFORE setting up the matrix Python.\n      # This prevents Emscripten (which requires Python 3.10+) from crashing\n      # when trying to use Python 3.8 from the matrix.\n      - name: Install homebrew dependencies\n        run: |\n          brew update\n          brew install xcodegen make libtool zlib autoconf automake ninja emscripten\n          export PATH=${HOME}/Applications/CMake/3.15.7/bin:$PATH:/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin\n          emcc --version\n          cmake --version\n          bazel --version\n\n      - name: Set up Python ${{ matrix.python-version }}\n        uses: actions/setup-python@v5\n        with:\n          python-version: ${{ matrix.python-version }}\n\n      - name: Install Python Dependencies\n        run: |\n          pip install --upgrade pip\n          pip install -r conans/requirements.txt\n          pip install -r conans/requirements_server.txt\n          pip install -r conans/requirements_dev.txt\n          pip install meson\n\n      - name: Run tests\n        uses: ./.github/actions/test-coverage\n        with:\n          python-version: ${{ matrix.python-version }}\n          test-type: ${{ matrix.test-type }}\n          tests: ${{ matrix.test-type == 'functional' && (inputs.run-slow-tests == 'true' && 'test/functional' || 'test/functional -m \"not slow\"') || format('test/{0}', matrix.test-type) }}\n"
  },
  {
    "path": ".github/workflows/win-tests.yml",
    "content": "name: Windows Tests\n\non:\n  workflow_call:\n    inputs:\n      python-versions:\n        required: true\n        type: string\n      run-slow-tests:\n        required: false\n        default: 'false'\n        type: string\n\njobs:\n  unit_integration_tests:\n    runs-on: windows-2022\n    strategy:\n      matrix:\n        python-version: ${{ fromJson(inputs.python-versions) }}\n    name: Unit & Integration Tests (${{ matrix.python-version }})\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v4\n\n      - name: Set up Python ${{ matrix.python-version }}\n        uses: actions/setup-python@v5\n        with:\n          python-version: ${{ matrix.python-version }}\n\n      - name: Install Visual Studio Build Tools\n        run: |\n          Invoke-WebRequest -Uri \"https://aka.ms/vs/15/release/vs_buildtools.exe\" -OutFile \"vs_buildtools15.exe\"\n          Start-Process -FilePath \".\\vs_buildtools15.exe\" -ArgumentList `\n            \"--quiet\",  \"--wait\", \"--norestart\", \"--nocache\", `\n            \"--add\", \"Microsoft.VisualStudio.Component.VC.Tools.x86.x64\", `\n            \"--add\", \"Microsoft.Component.MSBuild\" -WindowStyle Hidden -Wait\n\n      - name: Determine pip cache directory\n        id: pip-cache-dir\n        shell: pwsh\n        run: echo \"PIP_CACHE_DIR=$(pip cache dir)\" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append\n\n      - name: Cache pip packages\n        uses: actions/cache@v4\n        with:\n          path: ${{ env.PIP_CACHE_DIR }}\n          key: pip-packages-${{ runner.os }}-${{ matrix.python-version }}-${{ hashFiles('**/requirements*.txt') }}\n          restore-keys: |\n            pip-packages-${{ runner.os }}-${{ matrix.python-version }}-\n\n      - name: Install Python requirements\n        run: |\n          pip install --upgrade pip\n          pip install -r conans/requirements.txt\n          pip install -r conans/requirements_dev.txt\n          pip install -r conans/requirements_server.txt\n          git config --global core.autocrlf false\n\n      - name: Run Unit & Integration Tests\n        uses: ./.github/actions/test-coverage\n        with:\n          python-version: ${{ matrix.python-version }}\n          test-type: unit-integration\n          tests: test/unittests test/integration\n\n  functional_tests:\n    runs-on: windows-2022\n    strategy:\n      matrix:\n        python-version: ${{ fromJson(inputs.python-versions) }}\n    name: Functional Tests (${{ matrix.python-version }})\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v4\n\n      - name: Set up Python ${{ matrix.python-version }}\n        uses: actions/setup-python@v5\n        with:\n          python-version: ${{ matrix.python-version }}\n\n      - name: Install MSVC v14.38 Toolset\n        run: |\n          Start-Process -Wait \"${env:ProgramFiles(x86)}\\Microsoft Visual Studio\\Installer\\vs_installer.exe\" -ArgumentList {`\n            modify `\n            --quiet `\n            --installPath \"C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\" `\n            --add `\n            Microsoft.VisualStudio.Component.VC.14.38.17.8.x86.x64 `\n          }\n\n      - name: Verify MSVC v14.38 toolset installation\n        run: dir \"C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Tools\\MSVC\"\n\n      - name: Install Visual Studio Build Tools\n        run: |\n          Invoke-WebRequest -Uri \"https://aka.ms/vs/15/release/vs_buildtools.exe\" -OutFile \"vs_buildtools15.exe\"\n          Start-Process -FilePath \".\\vs_buildtools15.exe\" -ArgumentList `\n            \"--quiet\",  \"--wait\", \"--norestart\", \"--nocache\", `\n            \"--add\", \"Microsoft.VisualStudio.Component.VC.Tools.x86.x64\", `\n            \"--add\", \"Microsoft.VisualStudio.Component.Windows81SDK\", `\n            \"--add\", \"Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core\", `\n            \"--add\", \"Microsoft.Component.MSBuild\", `\n            \"--add\", \"Microsoft.VisualStudio.Component.VC.140\" -WindowStyle Hidden -Wait\n\n      - name: Determine pip cache directory\n        id: pip-cache-dir\n        shell: pwsh\n        run: echo \"PIP_CACHE_DIR=$(pip cache dir)\" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append\n\n\n      - name: Cache pip packages\n        uses: actions/cache@v4\n        with:\n          path: ${{ env.PIP_CACHE_DIR }}\n          key: pip-packages-${{ runner.os }}-${{ matrix.python-version }}-${{ hashFiles('**/requirements*.txt') }}\n          restore-keys: |\n            pip-packages-${{ runner.os }}-${{ matrix.python-version }}-\n\n      - name: Install Python requirements\n        run: |\n          pip install --upgrade pip\n          pip install -r conans/requirements.txt\n          pip install -r conans/requirements_server.txt\n          pip install -r conans/requirements_dev.txt\n          pip install meson\n\n      - name: \"Set choco cache\"\n        run: choco config set cacheLocation C:\\choco-cache\n\n      - uses: actions/cache@v4\n        with:\n          path: C:\\choco-cache\n          key: choco-cache\n\n      - name: Install Chocolatey packages\n        run: |\n          choco install pkgconfiglite --version 0.28\n          choco install ninja --version 1.10.2\n          choco install mingw\n          # mirrors.kernel.org/sourceware/cygwin returns 404; use alternative mirror from this list: https://cygwin.com/mirrors.html\n          choco install cygwin --execution-timeout=300 --package-parameters=\"'/Site:https://mirror.clarkson.edu/cygwin/'\"\n          choco install cyg-get\n          cyg-get automake gcc-g++ make binutils --verbose\n\n      - uses: msys2/setup-msys2@v2\n        id: msys2-setup\n        with:\n            update: true\n            # It's important that the default environment that is used is MSYS\n            # we check this default in a test\n            msystem: MSYS\n            install: >-\n                mingw-w64-x86_64-toolchain\n                mingw-w64-i686-toolchain\n                mingw-w64-ucrt-x86_64-toolchain\n                mingw-w64-clang-x86_64-toolchain\n                base-devel\n                gcc\n                autoconf-wrapper\n                automake\n                libtool\n\n      - name: Cache CMake and Bazel installations\n        id: cache-tools\n        uses: actions/cache@v4\n        with:\n          path: |\n            C:\\tools\\cmake\\3.15.7\n            C:\\tools\\cmake\\3.19.7\n            C:\\tools\\cmake\\3.23.5\n            C:\\tools\\cmake\\3.27.9\n            C:\\tools\\cmake\\4.2.1\n            C:\\tools\\bazel\\6.5.0\n            C:\\tools\\bazel\\7.6.2\n            C:\\tools\\bazel\\8.4.2\n          key: ${{ runner.os }}-conan-tools-cache\n\n      - name: Install CMake versions\n        if: steps.cache-tools.outputs.cache-hit != 'true'\n        run: |\n          $CMAKE_BUILD_VERSIONS = \"3.15.7\", \"3.19.7\", \"3.23.5\", \"3.27.9\", \"4.2.1\"\n          foreach ($version in $CMAKE_BUILD_VERSIONS) {\n            Write-Host \"Downloading CMake version $version for Windows...\"\n            $destination = \"C:\\tools\\cmake\\$version\"\n            if (-not (Test-Path $destination)) {\n                New-Item -Path $destination -ItemType Directory\n            }\n            $major_minor_version = ($version -split '\\.')[0..1] -join '.'\n            if ( $major_minor_version -eq \"3.15\" -or $major_minor_version -eq \"3.19\" ) {\n                $arch = \"win64-x64\"\n            } else {\n                $arch = \"windows-x86_64\"\n            }\n            $url = \"https://cmake.org/files/v$major_minor_version/cmake-$version-$arch.zip\"\n            $zipFile = \"cmake-$version-windows-x86_64.zip\"\n            Invoke-WebRequest -Uri $url -OutFile $zipFile\n            Expand-Archive -Path $zipFile -DestinationPath $destination -Force\n            Remove-Item $zipFile\n          }\n\n      - name: Install Bazel versions\n        if: steps.cache-tools.outputs.cache-hit != 'true'\n        run: |\n          $BAZEL_BUILD_VERSIONS = \"6.5.0\", \"7.6.2\", \"8.4.2\"\n          foreach ($version in $BAZEL_BUILD_VERSIONS) {\n              Write-Host \"Downloading Bazel version $version for Windows...\"\n              $destination = \"C:\\tools\\bazel\\$version\"\n              if (-not (Test-Path $destination)) {\n                  New-Item -Path $destination -ItemType Directory\n              }\n              $major_minor_version = ($version -split '\\.')[0..1] -join '.'\n              $url = \"https://github.com/bazelbuild/bazel/releases/download/$version/bazel-$version-windows-x86_64.zip\"\n              $zipFile = \"bazel-$version-windows-x86_64.zip\"\n              Invoke-WebRequest -Uri $url -OutFile $zipFile\n              Expand-Archive -Path $zipFile -DestinationPath $destination -Force\n              Remove-Item $zipFile\n          }\n\n      - name: Prepare environment for functional tests\n        run: |\n          git config --global core.autocrlf false\n\n          $pathsToRemove = @()\n          $pathsToRemove += \"C:\\mingw64\\bin\"                # To avoid that CMake finds gcc there\n          $pathsToRemove += \"C:\\Strawberry\\c\\bin\"\n          $pathsToRemove += \"C:\\Program Files\\CMake\\bin\"    # Remove the default CMake version\n          $pathsToRemove += \"C:\\Program Files\\Git\\usr\\bin\"  # To avoid using uname and other tools from there\n          foreach ($dir in $pathsToRemove) {\n              $newPath = ($env:PATH -split \";\") -ne $dir -join \";\"\n              [System.Environment]::SetEnvironmentVariable('PATH', $newPath)\n              Write-Host \"$dir removed from PATH. Current PATH: $env:PATH\"\n          }\n\n          # Check GCC is not in Path\n          $gccPath = Get-Command gcc.exe -ErrorAction SilentlyContinue\n          if ($null -ne $gccPath) {\n              Write-Host \"GCC found in PATH at: $($gccPath.Path)\"\n          } else {\n              Write-Host \"GCC not found in PATH.\"\n          }\n\n          $shortGuid = [System.Guid]::NewGuid().ToString().Substring(0, 4)\n          $randomFolder = [System.IO.Path]::Combine(\"D:\\\\\", \"tmp_tests\", $shortGuid)\n          New-Item -ItemType Directory -Force -Path $randomFolder\n          $env:CONAN_TEST_FOLDER = $randomFolder\n          $env:Path = \"C:\\tools\\cmake\\3.15.7\\cmake-3.15.7-win64-x64\\bin;\" + $env:Path\n\n          $msys2Path = '${{ steps.msys2-setup.outputs.msys2-location }}'\n          [System.Environment]::SetEnvironmentVariable('MSYS2_PATH', $msys2Path, [System.EnvironmentVariableTarget]::Process)\n          Write-Host \"Added MSYS2_PATH environment variable: $msys2Path\"\n\n          # Export variables so they persist in the next steps\n          echo \"PATH=$env:Path\" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append\n          echo \"CONAN_TEST_FOLDER=$env:CONAN_TEST_FOLDER\" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append\n          echo \"MSYS2_PATH=$msys2Path\" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append\n\n      - name: Run Functional Tests\n        uses: ./.github/actions/test-coverage\n        with:\n          python-version: ${{ matrix.python-version }}\n          test-type: functional\n          tests: ${{ inputs.run-slow-tests == 'true' && 'test/functional' || 'test/functional -m \"not slow\"' }}\n"
  },
  {
    "path": ".gitignore",
    "content": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n\n# C extensions\n*.so\n\n# Distribution / packaging\n.Python\nbuild/\ndevelop-eggs/\ndist/\ndownloads/\neggs/\n.eggs/\nlib/\nlib64/\nparts/\nsdist/\nvar/\nvenv/\n.venv/\n*.egg-info/\n.installed.cfg\n*.egg\npip-wheel-metadata/\n\n# PyInstaller\n#  Usually these files are written by a python script from a template\n#  before PyInstaller builds the exe, so as to inject date/other infos into it.\n*.manifest\n*.spec\n\n# Installer logs\npip-log.txt\npip-delete-this-directory.txt\n\n# Unit test / coverage reports\nhtmlcov/\n.tox/\n.coverage\n.coverage.*\n.cache\nnosetests.xml\ncoverage.xml\n*,cover\n.pytest_cache/\n\n# Translations\n*.mo\n*.pot\n\n# Django stuff:\n*.log\n\n# Sphinx documentation\ndocs/_build/\n\n# PyBuilder\ntarget/\n\n\n# OS generated files #\n######################\n.DS_Store\n.DS_Store?\n._*\n.Spotlight-V100\n.Trashes\nIcon?\nehthumbs.db\nThumbs.db\n\n.pydev*\n.project\n\n# IDEs #\n########\n.metadata\n.idea\n.history/\n\nconan.conf\n*default_package_folder\n\n#Eclipse folder\n.settings\n\n#VScode folder\n.vscode\n\n#Generated certificate file\ncacert.pem\n\n#linux backup and vim files\n*~\n.*.sw?\nSession.vim\n\n#Pyinstaller generated binaries\n/pyinstaller\n\n# Run tests in docker in current dir\n.bash_history\n.conan_server/\n.sudo_as_admin_successful\n.noseids\n\n# add excluded\n!conans/client/build\n!conan/tools/build\n!test/unittests/client/build\n!test/unittests/tools/build\n"
  },
  {
    "path": "LICENSE.md",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2019 JFrog LTD\n\n\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\n\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\n\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n"
  },
  {
    "path": "MANIFEST.in",
    "content": "include LICENSE.md"
  },
  {
    "path": "README.md",
    "content": "<picture>\n  <!-- These are also used for https://github.com/conan-io/.github/blob/main/profile/README.md -->\n  <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/conan-io/conan/develop2/.github/conan2-logo-for-dark.svg\">\n  <source media=\"(prefers-color-scheme: light)\" srcset=\"https://raw.githubusercontent.com/conan-io/conan/develop2/.github/conan2-logo-for-light.svg\">\n  <img alt=\"JFrog | Conan 2.0 Logo\" src=\"https://raw.githubusercontent.com/conan-io/conan/develop2/.github/conan2-logo-with-bg.svg\">\n</picture>\n\n# Conan\n\nDecentralized, open-source (MIT), C/C++ package manager.\n\n- Homepage: https://conan.io/\n- Github: https://github.com/conan-io/conan\n- Docs: https://docs.conan.io\n- Slack: https://cpplang.slack.com (#conan channel. Please, click [here](https://cppalliance.org/slack/#cpp-slack) to get an invitation)\n- Twitter: https://twitter.com/conan_io\n- Blog: https://blog.conan.io\n- Security reports: https://jfrog.com/trust/report-vulnerability\n\n\nConan is a package manager for C and C++ developers:\n\n- It is fully decentralized. Users can host their packages on their servers, privately. Integrates with Artifactory and Bintray.\n- Portable. Works across all platforms, including Linux, OSX, Windows (with native and first-class support, WSL, MinGW),\n  Solaris, FreeBSD, embedded and cross-compiling, docker, WSL\n- Manage binaries. It can create, upload and download binaries for any configuration and platform,\n  even cross-compiling, saving lots of time in development and continuous integration. The binary compatibility can be configured\n  and customized. Manage all your artifacts in the same way on all platforms.\n- Integrates with any build system, including any proprietary and custom one. Provides tested support for major build systems\n  (CMake, MSBuild, Makefiles, Meson, etc).\n- Extensible: Its Python-based recipes, together with extension points allow for great power and flexibility.\n- Large and active community, especially in GitHub (https://github.com/conan-io/conan) and Slack (https://cppalliance.org/slack/ #conan channel).\n  This community also creates and maintains packages in ConanCenter and Bincrafters repositories in Bintray.\n- Stable. Used in production by many companies, since 1.0 there is a commitment not to break package recipes and documented behavior.\n\n\nThis is the **developer/maintainer** documentation. For user documentation, go to https://docs.conan.io\n\n\n## Setup\n\nYou can run Conan from source in Windows, MacOS, and Linux:\n\n- **Install pip following** [pip docs](https://pip.pypa.io/en/stable/installation/).\n\n- **Clone Conan repository:**\n\n  ```bash\n  $ git clone https://github.com/conan-io/conan.git conan-io\n  ```\n\n  > **Note**: repository directory name matters, some directories are known to be problematic to run tests (e.g. `conan`). `conan-io` directory name was tested and guaranteed to be working.\n\n- **Install in editable mode**\n\n  ```bash\n  $ cd conan-io && sudo pip install -e .\n  ```\n\n  If you are in Windows, using ``sudo`` is not required. Some Linux distros won't allow you to put Python packages in editable mode in the root Python installation, and creating a virtual environment ``venv`` first, is mandatory.\n\n- **You are ready, try to run Conan:**\n\n  ```bash\n  $ conan --help\n\n  Consumer commands\n    install    Installs the requirements specified in a recipe (conanfile.py or conanfile.txt).\n    ...\n\n    Conan commands. Type \"conan <command> -h\" for help\n  ```\n\n## Contributing to the project\n\n\nFeedback and contribution are always welcome in this project.\nPlease read our [contributing guide](https://github.com/conan-io/conan/blob/develop2/.github/CONTRIBUTING.md).\nAlso, if you plan to contribute, please add some testing for your changes. You can read the [Conan\ntests guidelines section](https://github.com/conan-io/conan/blob/develop2/test/README.md) for\nsome advice on how to write tests for Conan.\n\n### Running the tests\n\n\n**Install Python requirements**\n\n```bash\n$ python -m pip install -r conans/requirements.txt\n$ python -m pip install -r conans/requirements_server.txt\n$ python -m pip install -r conans/requirements_dev.txt\n```\n\nIf you are not on Windows and you are not using a Python virtual environment, you will need to run these\ncommands using `sudo`.\n\nBefore you can run the tests, you need to set a few environment variables first.\n\n```bash\n$ export PYTHONPATH=$PYTHONPATH:$(pwd)\n```\n\nOn Windows it would be (while being in the Conan root directory):\n\n```bash\n$ set PYTHONPATH=.\n```\n\nConan test suite defines and configures some required tools (CMake, Ninja, etc) in the\n``conftest.py`` and allows to define a custom ``conftest_user.py``.\nSome specific versions, like cmake>=3.15 are necessary.\n\n\nYou can run the tests like this:\n\n```bash\n$ python -m pytest .\n```\n\nA few minutes later it should print ``OK``:\n\n```bash\n............................................................................................\n----------------------------------------------------------------------\nRan 146 tests in 50.993s\n\nOK\n```\n\nTo run specific tests, you can specify the test name too, something like:\n\n```bash\n$ python -m pytest test/functional/command/export_test.py::TestRevisionModeSCM::test_revision_mode_scm -s\n```\n\nThe `-s` argument can be useful to see some output that otherwise is captured by *pytest*.\n\nAlso, you can run tests against an instance of Artifactory. Those tests should add the attribute\n`artifactory_ready`.\n\n```bash\n$ python -m pytest . -m artifactory_ready\n```\n\nSome environment variables have to be defined to run them. For example, for an\nArtifactory instance that is running on the localhost with default user and password configured, the\nvariables could take the values:\n\n```bash\n$ export CONAN_TEST_WITH_ARTIFACTORY=1\n$ export ARTIFACTORY_DEFAULT_URL=http://localhost:8081/artifactory\n$ export ARTIFACTORY_DEFAULT_USER=admin\n$ export ARTIFACTORY_DEFAULT_PASSWORD=password\n```\n\n`ARTIFACTORY_DEFAULT_URL` is the base URL for the Artifactory repo, not one for a specific\nrepository. Running the tests with a real Artifactory instance will create repos on the fly so please\nuse a separate server for testing purposes.\n\n## License\n\n[MIT LICENSE](LICENSE.md)\n"
  },
  {
    "path": "codecov.yml",
    "content": "comment: false # Disable codecov PR comments -> leave only the checks\ncoverage:\n    status:\n        project:\n            default:\n                # https://docs.codecov.com/docs/commit-status#informational\n                # Avoids failing on coverage decrease\n                informational: true\n        patch:\n            default:\n                informational: true\nignore:\n  - \"test/performance\"\n"
  },
  {
    "path": "conan/__init__.py",
    "content": "from conan.internal.model.conan_file import ConanFile\nfrom conan.internal.model.workspace import Workspace\nfrom conan.internal.model.version import Version\n\n__version__ = '2.27.0-dev'\nconan_version = Version(__version__)\n"
  },
  {
    "path": "conan/api/__init__.py",
    "content": ""
  },
  {
    "path": "conan/api/conan_api.py",
    "content": "import os\nimport sys\n\nfrom conan.api.output import init_colorama\nfrom conan.api.subapi.audit import AuditAPI\nfrom conan.api.subapi.cache import CacheAPI\nfrom conan.api.subapi.command import CommandAPI\nfrom conan.api.subapi.local import LocalAPI\nfrom conan.api.subapi.lockfile import LockfileAPI\nfrom conan.api.subapi.report import ReportAPI\nfrom conan.api.subapi.workspace import WorkspaceAPI\nfrom conan.api.subapi.config import ConfigAPI\nfrom conan.api.subapi.download import DownloadAPI\nfrom conan.api.subapi.export import ExportAPI\nfrom conan.api.subapi.install import InstallAPI\nfrom conan.api.subapi.graph import GraphAPI\nfrom conan.api.subapi.new import NewAPI\nfrom conan.api.subapi.profiles import ProfilesAPI\nfrom conan.api.subapi.list import ListAPI\nfrom conan.api.subapi.remotes import RemotesAPI\nfrom conan.api.subapi.remove import RemoveAPI\nfrom conan.api.subapi.upload import UploadAPI\nfrom conan.errors import ConanException\nfrom conan.internal.api.remotes.localdb import LocalDB\nfrom conan.internal.cache.cache import PkgCache\nfrom conan.internal.cache.home_paths import HomePaths\nfrom conan.internal.hook_manager import HookManager\nfrom conan.internal.model.conf import load_global_conf, ConfDefinition, CORE_CONF_PATTERN\nfrom conan.internal.model.settings import load_settings_yml\nfrom conan.internal.paths import get_conan_user_home\nfrom conan.internal.api.migrations import ClientMigrator\nfrom conan.internal.model.version_range import validate_conan_version\nfrom conan.internal.rest.auth_manager import ConanApiAuthManager\nfrom conan.internal.rest.conan_requester import ConanRequester\nfrom conan.internal.rest.remote_manager import RemoteManager\n\n\nclass ConanAPI:\n    \"\"\"\n    This is the main object to interact with the Conan API. It provides all the subapis to work with\n    recipes, packages, remotes, etc., which are exposed as attributes of this class, and should\n    not be created directly.\n    \"\"\"\n    def __init__(self, cache_folder=None):\n        \"\"\"\n        :param cache_folder: Conan cache/home folder. It will have less priority than the\n                             ``\"home_folder\"`` defined in a Workspace.\n        \"\"\"\n\n        version = sys.version_info\n        if version.major == 2 or version.minor < 7:\n            raise ConanException(\"Conan needs Python >= 3.7\")\n        if cache_folder is not None and not os.path.isabs(cache_folder):\n            raise ConanException(\"cache_folder has to be an absolute path\")\n\n        init_colorama(sys.stderr)\n        # Deprecated, but still used internally, prefer home_folder\n        self.cache_folder = cache_folder or get_conan_user_home()\n        self._home_folder = self.cache_folder\n        self._api_helpers = self._ApiHelpers(self)\n        self.migrate()\n\n        #: Used to interact with the local Conan configuration\n        self.config: ConfigAPI = ConfigAPI(self, self._api_helpers)\n        #: Used to interact with remotes\n        self.remotes: RemotesAPI = RemotesAPI(self, self._api_helpers)\n        self.command = CommandAPI(self)\n        #: Used to get latest refs and list refs of recipes and packages\n        self.list: ListAPI = ListAPI(self, self._api_helpers)\n        self.profiles = ProfilesAPI(self, self._api_helpers)\n        #: Used to install binaries, sources, deploy packages and more\n        self.install: InstallAPI = InstallAPI(self, self._api_helpers)\n        self.graph = GraphAPI(self, self._api_helpers)\n        #: Used to export recipes and pre-compiled package binaries to the Conan cache\n        self.export: ExportAPI = ExportAPI(self, self._api_helpers)\n        self.remove = RemoveAPI(self, self._api_helpers)\n        self.new = NewAPI(self)\n        #: Used to upload recipes and packages to remotes\n        self.upload: UploadAPI = UploadAPI(self, self._api_helpers)\n        #: Used to download recipes and packages from remotes\n        self.download: DownloadAPI = DownloadAPI(self, self._api_helpers)\n        #: Used to interact wit the packages storage cache\n        self.cache: CacheAPI = CacheAPI(self, self._api_helpers)\n        #: Used to read and manage lockfile files\n        self.lockfile: LockfileAPI = LockfileAPI(self)\n        #: Local flow helpers for developer \"source\", \"build\", \"editable\" commands\n        self.local: LocalAPI = LocalAPI(self, self._api_helpers)\n        #: Used to check vulnerabilities of dependencies\n        self.audit: AuditAPI = AuditAPI(self)\n        #: Used to manage workspaces\n        self.workspace: WorkspaceAPI = WorkspaceAPI(self)\n        self.report: ReportAPI = ReportAPI(self, self._api_helpers)\n\n    @property\n    def home_folder(self) -> str:\n        \"\"\" Where the Conan user home is located. Read only.\n        Can be modified by the ``CONAN_HOME`` environment variable or by the\n        ``.conanrc`` file in the current directory or any parent directory\n        when Conan is called.\n        \"\"\"\n        return self._home_folder\n\n    def reinit(self):\n        \"\"\"\n        Reinitialize the Conan API. This is useful when the configuration changes.\n        \"\"\"\n        self._api_helpers.reinit()\n        self.local.reinit()\n\n    def migrate(self):\n        # Migration system\n        # TODO: A prettier refactoring of migrators would be nice\n        from conan import conan_version\n        migrator = ClientMigrator(self._home_folder, conan_version)\n        migrator.migrate()\n\n    class _ApiHelpers:\n        # This is an internal implementation detail of Conan, DO NOT USE\n        def __init__(self, conan_api):\n            self._conan_api = conan_api\n            self._cli_core_confs = None\n            self._init_global_conf()\n            # TODO: Make uniform lazy vs non lazy collaborators\n            self.hook_manager = HookManager(HomePaths(self._conan_api.home_folder).hooks_path)\n            # Wraps an http_requester to inject proxies, certs, etc\n            self._requester = ConanRequester(self.global_conf, self._conan_api.home_folder)\n            self.cache = PkgCache(self._conan_api.home_folder, self.global_conf)\n            self._settings_yml = None\n            self._remote_manager = None\n\n        def set_core_confs(self, core_confs):\n            confs = ConfDefinition()\n            for c in core_confs:\n                if not CORE_CONF_PATTERN.match(c):\n                    raise ConanException(f\"Only core. values are allowed in --core-conf. Got {c}\")\n            confs.loads(\"\\n\".join(core_confs))\n            confs.validate()\n            self._cli_core_confs = confs\n            # Last but not least, apply the new configuration\n            # This will in turn call ApiHelpers.reinit() as the very first thing\n            self._conan_api.reinit()\n\n        def _init_global_conf(self):\n            self.global_conf = load_global_conf(self._conan_api.home_folder)\n            if self._cli_core_confs:\n                self.global_conf.update_conf_definition(self._cli_core_confs)\n            required_range_new = self.global_conf.get(\"core:required_conan_version\")\n            if required_range_new:\n                validate_conan_version(required_range_new)\n\n        def reinit(self):\n            self._init_global_conf()\n            self.hook_manager.reinit()\n            self._requester = ConanRequester(self.global_conf, self._conan_api.home_folder)\n            self._settings_yml = None\n            self.cache = PkgCache(self._conan_api.home_folder, self.global_conf)\n            self._remote_manager = None\n\n        @property\n        def settings_yml(self):\n            if self._settings_yml is None:\n                self._settings_yml = load_settings_yml(self._conan_api.home_folder)\n            return self._settings_yml\n\n        @property\n        def remote_manager(self):\n            if self._remote_manager is None:\n                home_folder = self._conan_api.home_folder\n                localdb = LocalDB(home_folder)\n                requester = self._conan_api._api_helpers.requester  # noqa\n                auth_manager = ConanApiAuthManager(requester, self._conan_api.home_folder, localdb,\n                                                   self.global_conf)\n                self._remote_manager = RemoteManager(self.cache, auth_manager, home_folder)\n            return self._remote_manager\n\n        @property\n        def requester(self):\n            return self._requester\n"
  },
  {
    "path": "conan/api/input.py",
    "content": "import getpass\nimport sys\n\nfrom conan.errors import ConanException\n\n\nclass UserInput:\n    \"\"\"Class to interact with the user, used to show messages and ask for information\"\"\"\n\n    def __init__(self, non_interactive):\n        \"\"\"\n        Params:\n            ins: input stream\n            out: ConanOutput, should have \"write\" method\n        \"\"\"\n        self._ins = sys.stdin\n        # FIXME: circular include, move \"color_enabled\" function to better location\n        from conan.api.output import ConanOutput\n        self._out = ConanOutput()\n        self._interactive = not non_interactive\n\n    def _raise_if_non_interactive(self):\n        if not self._interactive:\n            raise ConanException(\"Conan interactive mode disabled\")\n\n    def raw_input(self):\n        self._raise_if_non_interactive()\n        return input()\n\n    def request_login(self, remote_name, username=None):\n        \"\"\"Request user to input their name and password\n        :param remote_name:\n        :param username If username is specified it only request password\"\"\"\n        self._raise_if_non_interactive()\n        if not username:\n            self._out.login_msg(f\"Remote '{remote_name}' username: \")\n            username = self.get_username()\n\n        self._out.login_msg(\"Please enter a password for \"\n                            f\"user '{username}' on remote '{remote_name}': \")\n        try:\n            pwd = self.get_password()\n        except ConanException:\n            raise\n        except Exception as e:\n            raise ConanException('Cancelled pass %s' % e)\n        return username, pwd\n\n    def get_username(self):\n        \"\"\"Overridable for testing purpose\"\"\"\n        return self.raw_input()\n\n    @staticmethod\n    def get_password():\n        \"\"\"Overridable for testing purpose\"\"\"\n        try:\n            return getpass.getpass(\"\")\n        except BaseException:  # For KeyboardInterrupt too\n            raise ConanException(\"Interrupted interactive password input\")\n\n    def request_string(self, msg, default_value=None):\n        \"\"\"Request user to input a msg\n        :param default_value:\n        :param msg Name of the msg\n        \"\"\"\n        self._raise_if_non_interactive()\n\n        if default_value:\n            self._out.write('%s (%s): ' % (msg, default_value))\n        else:\n            self._out.write('%s: ' % msg)\n        s = self._ins.readline().replace(\"\\n\", \"\")\n        if default_value is not None and s == '':\n            return default_value\n        return s\n\n    def request_boolean(self, msg, default_option=None):\n        \"\"\"Request user to input a boolean\"\"\"\n        ret = None\n        while ret is None:\n            if default_option:\n                s = self.request_string(\"%s (YES/no)\" % msg)\n            elif default_option is False:\n                s = self.request_string(\"%s (NO/yes)\" % msg)\n            else:\n                s = self.request_string(\"%s (yes/no)\" % msg)\n            if default_option is not None and s == '':\n                return default_option\n            if s.lower() in ['yes', 'y']:\n                ret = True\n            elif s.lower() in ['no', 'n']:\n                ret = False\n            else:\n                self._out.error(f\"{s} is not a valid answer\")\n        return ret\n"
  },
  {
    "path": "conan/api/model/__init__.py",
    "content": "from conan.api.model.remote import Remote, LOCAL_RECIPES_INDEX\nfrom conan.api.model.refs import RecipeReference, PkgReference\nfrom conan.api.model.list import PackagesList, MultiPackagesList, ListPattern\n"
  },
  {
    "path": "conan/api/model/list.py",
    "content": "import copy\nimport fnmatch\nimport json\nimport os\nfrom json import JSONDecodeError\nfrom typing import Iterable, Tuple, Dict\n\nfrom conan.api.model import RecipeReference, PkgReference\nfrom conan.api.output import ConanOutput\nfrom conan.errors import ConanException\nfrom conan.internal.errors import NotFoundException\nfrom conan.internal.model.version_range import VersionRange\nfrom conan.internal.graph.graph import RECIPE_EDITABLE, RECIPE_CONSUMER, RECIPE_PLATFORM, \\\n    RECIPE_VIRTUAL, BINARY_SKIP, BINARY_MISSING, BINARY_INVALID\nfrom conan.internal.util.files import load\n\n\nclass MultiPackagesList:\n    \"\"\" A collection of PackagesList by remote name.\"\"\"\n    def __init__(self):\n        self.lists = {}\n\n    def __getitem__(self, name):\n        try:\n            return self.lists[name]\n        except KeyError:\n            raise ConanException(f\"'{name}' doesn't exist in package list\")\n\n    def add(self, name, pkg_list):\n        self.lists[name] = pkg_list\n\n    def add_error(self, remote_name, error):\n        self.lists[remote_name] = {\"error\": error}\n\n    def serialize(self):\n        \"\"\" Serialize object to a dictionary.\"\"\"\n        return {k: v.serialize() if isinstance(v, PackagesList) else v\n                for k, v in self.lists.items()}\n\n    def merge(self, other):\n        for k, v in other.lists.items():\n            self.lists.setdefault(k, PackagesList()).merge(v)\n\n    @staticmethod\n    def load(file):\n        \"\"\" Create an instance of the class from a serialized JSON file path pointed by ``file``.\"\"\"\n        try:\n            content = json.loads(load(file))\n        except JSONDecodeError as e:\n            raise ConanException(f\"Package list file invalid JSON: {file}\\n{e}\")\n        except Exception as e:\n            raise ConanException(f\"Package list file missing or broken: {file}\\n{e}\")\n        # Check if input json is not a graph file\n        if \"graph\" in content:\n            base_path = os.path.basename(file)\n            raise ConanException(\n                'Expected a package list file but found a graph file. You can create a \"package list\" JSON file by running:\\n\\n'\n                f\"\\tconan list --graph {base_path} --format=json > pkglist.json\\n\\n\"\n                \"More Info at 'https://docs.conan.io/2/examples/commands/pkglists.html\"\n            )\n        result = {}\n        for remote, pkglist in content.items():\n            if \"error\" in pkglist:\n                result[remote] = pkglist\n            else:\n                result[remote] = PackagesList.deserialize(pkglist)\n        pkglist = MultiPackagesList()\n        pkglist.lists = result\n        return pkglist\n\n    @staticmethod\n    def load_graph(graphfile, graph_recipes=None, graph_binaries=None, context=None):\n        \"\"\" Create an instance of the class from a graph file path, which is\n        the json format returned by a few commands\n        like ``conan graph info`` or ``conan create/install.``\n\n        :parameter str graphfile: Path to the graph file\n        :parameter list[str] graph_recipes: List for kinds of recipes to return.\n            For example ``\"cache\"`` will return only recipes in the local cache,\n            ``\"download\"`` will return only recipes that have been downloaded,\n            and passing ``\"*\"`` will return all recipes.\n        :parameter list[str] graph_binaries: List for kinds of binaries to return.\n            For example ``\"cache\"`` will return only binaries in the local cache,\n            ``\"download\"`` will return only binaries that have been downloaded,\n            ``\"build\"`` will return only binaries that are built,\n            ``\"missing\"`` will return only binaries that are missing,\n            ``\"invalid\"`` will return only binaries that are invalid,\n            and passing ``\"*\"`` will return all binaries.\n        :parameter str context: Context to filter the graph,\n            can be ``\"host\"``, ``\"build\"``, ``\"host-only\"`` or ``\"build-only\"``\n        \"\"\"\n        if not os.path.isfile(graphfile):\n            raise ConanException(f\"Graph file not found: {graphfile}\")\n        try:\n            graph = json.loads(load(graphfile))\n            # Check if input json is a graph file\n            if \"graph\" not in graph:\n                raise ConanException(\n                    'Expected a graph file but found an unexpected JSON file format. You can create a \"graph\" JSON file by running:\\n\\n'\n                    f\"\\tconan [ graph-info | create | export-pkg | install | test ] --format=json > graph.json\\n\\n\"\n                    \"More Info at 'https://docs.conan.io/2/reference/commands/formatters/graph_info_json_formatter.html\"\n                )\n\n            mpkglist = MultiPackagesList._define_graph(graph, graph_recipes, graph_binaries,\n                                                       context=context)\n            return mpkglist\n        except JSONDecodeError as e:\n            raise ConanException(f\"Graph file invalid JSON: {graphfile}\\n{e}\")\n        except KeyError as e:\n            raise ConanException(f'Graph file {graphfile} is missing the required \"{e}\" key in its contents.\\n'\n                                 \"Note that the graph file should not be filtered \"\n                                 \"if you expect to use it with the list command.\")\n        except ConanException as e:\n            raise e\n        except Exception as e:\n            raise ConanException(f\"Graph file broken: {graphfile}\\n{e}\")\n\n    @staticmethod\n    def _define_graph(graph, graph_recipes=None, graph_binaries=None, context=None):\n        base_context = context.split(\"-\")[0] if context else None\n        pkglist = MultiPackagesList()\n        cache_list = PackagesList()\n        if graph_recipes is None and graph_binaries is None:\n            recipes = [\"*\"]\n            binaries = [\"*\"]\n        else:\n            recipes = [r.lower() for r in graph_recipes or []]\n            binaries = [b.lower() for b in graph_binaries or []]\n\n        pkglist.lists[\"Local Cache\"] = cache_list\n        for node in graph[\"graph\"][\"nodes\"].values():\n            if base_context and node['context'] != base_context:\n                continue\n\n            # We need to add the python_requires too\n            python_requires = node.get(\"python_requires\")\n            if python_requires is not None:\n                for pyref, pyreq in python_requires.items():\n                    pyrecipe = pyreq[\"recipe\"]\n                    if pyrecipe == RECIPE_EDITABLE:\n                        continue\n                    pyref = RecipeReference.loads(pyref)\n                    if any(r == \"*\" or r == pyrecipe for r in recipes):\n                        cache_list.add_ref(pyref)\n                    pyremote = pyreq[\"remote\"]\n                    if pyremote:\n                        remote_list = pkglist.lists.setdefault(pyremote, PackagesList())\n                        remote_list.add_ref(pyref)\n\n            recipe = node[\"recipe\"]\n            if recipe in (RECIPE_EDITABLE, RECIPE_CONSUMER, RECIPE_VIRTUAL, RECIPE_PLATFORM):\n                continue\n\n            ref = node[\"ref\"]\n            ref = RecipeReference.loads(ref)\n            ref.timestamp = node[\"rrev_timestamp\"]\n            recipe = recipe.lower()\n            if any(r == \"*\" or r == recipe for r in recipes):\n                cache_list.add_ref(ref)\n\n            remote = node[\"remote\"]\n            if remote:\n                remote_list = pkglist.lists.setdefault(remote, PackagesList())\n                remote_list.add_ref(ref)\n            pref = PkgReference(ref, node[\"package_id\"], node[\"prev\"], node[\"prev_timestamp\"])\n            binary_remote = node[\"binary_remote\"]\n            if binary_remote:\n                remote_list = pkglist.lists.setdefault(binary_remote, PackagesList())\n                remote_list.add_ref(ref)  # Binary listed forces recipe listed\n                remote_list.add_pref(pref)\n\n            binary = node[\"binary\"]\n            if binary in (BINARY_SKIP, BINARY_INVALID, BINARY_MISSING):\n                continue\n\n            binary = binary.lower()\n            if any(b == \"*\" or b == binary for b in binaries):\n                cache_list.add_ref(ref)  # Binary listed forces recipe listed\n                cache_list.add_pref(pref, node[\"info\"])\n        # Now filter possible exclusive contexts once that we know how they are distributed\n        MultiPackagesList._filter_exclusive_context(pkglist, graph, context)\n        return pkglist\n\n    @staticmethod\n    def _filter_exclusive_context(mpkglist, graph, context):\n        if context not in (\"host-only\", \"build-only\"):\n            return\n\n        pref_contexts = {}\n        for node in graph[\"graph\"][\"nodes\"].values():\n            if (node[\"recipe\"] not in (RECIPE_CONSUMER, RECIPE_VIRTUAL)\n                and node[\"ref\"] and node[\"package_id\"]):\n                pref = node[\"ref\"] + \":\" + node[\"package_id\"]\n                pref_contexts.setdefault(pref, set()).add(node['context'])\n\n        opposite_context = \"build\" if context == \"host-only\" else \"host\"\n        for remote, pkglist in mpkglist.lists.items():\n            for pref, contexts in pref_contexts.items():\n                if opposite_context in contexts:\n                    pref = PkgReference.loads(pref)\n                    if pkglist.has_rref(pref.ref):\n                        rev_dict = pkglist.recipe_dict(pref.ref)\n                        rev_dict.get(\"packages\", {}).pop(pref.package_id, None)\n                        if len(rev_dict.get(\"packages\", {})) == 0:\n                            pkglist._data.pop(str(pref.ref), None)\n\n\nclass PackagesList:\n    \"\"\" A collection of recipes, revisions and packages.\"\"\"\n    def __init__(self):\n        self._data = {}\n\n    def __bool__(self):\n        \"\"\" Whether the package list contains any recipe\"\"\"\n        return bool(self._data)\n\n    def merge(self, other):\n        assert isinstance(other, PackagesList)\n\n        def recursive_dict_update(d, u):  # TODO: repeated from conandata.py\n            for k, v in u.items():\n                if isinstance(v, dict):\n                    d[k] = recursive_dict_update(d.get(k, {}), v)\n                else:\n                    d[k] = v\n            return d\n        recursive_dict_update(self._data, other._data)\n\n    def split(self):\n        \"\"\"\n        Returns a list of PackageList, split one per reference.\n        This can be useful to parallelize things like upload, parallelizing per-reference\n        \"\"\"\n        result = []\n        for r, content in self._data.items():\n            subpkglist = PackagesList()\n            subpkglist._data[r] = content\n            result.append(subpkglist)\n        return result\n\n    def only_recipes(self) -> None:\n        \"\"\" Filter out all the packages and package revisions, keep only the recipes and\n            recipe revisions in self._data.\n        \"\"\"\n        for ref, ref_dict in self._data.items():\n            for rrev_dict in ref_dict.get(\"revisions\", {}).values():\n                rrev_dict.pop(\"packages\", None)\n\n    def add_refs(self, refs):\n        ConanOutput().warning(\"PackagesLists.add_refs() non-public, non-documented method will be \"\n                              \"removed, use .add_ref() instead\", warn_tag=\"deprecated\")\n        # RREVS alreday come in ASCENDING order, so upload does older revisions first\n        for ref in refs:\n            self.add_ref(ref)\n\n    def add_ref(self, ref: RecipeReference) -> None:\n        \"\"\"\n        Adds a new RecipeReference to a package list\n        \"\"\"\n        ref_dict = self._data.setdefault(str(ref), {})\n        if ref.revision:\n            revs_dict = ref_dict.setdefault(\"revisions\", {})\n            rev_dict = revs_dict.setdefault(ref.revision, {})\n            if ref.timestamp:\n                rev_dict[\"timestamp\"] = ref.timestamp\n\n    def add_prefs(self, rrev, prefs):\n        ConanOutput().warning(\"PackageLists.add_prefs() non-public, non-documented method will be \"\n                              \"removed, use .add_pref() instead\", warn_tag=\"deprecated\")\n        # Prevs already come in ASCENDING order, so upload does older revisions first\n        for p in prefs:\n            self.add_pref(p)\n\n    def add_pref(self, pref: PkgReference, pkg_info: dict = None) -> None:\n        \"\"\"\n        Add a PkgReference to an already existing RecipeReference inside a package list\n        \"\"\"\n        # Prevs already come in ASCENDING order, so upload does older revisions first\n        rev_dict = self.recipe_dict(pref.ref)\n        packages_dict = rev_dict.setdefault(\"packages\", {})\n        package_dict = packages_dict.setdefault(pref.package_id, {})\n        if pref.revision:\n            prevs_dict = package_dict.setdefault(\"revisions\", {})\n            prev_dict = prevs_dict.setdefault(pref.revision, {})\n            if pref.timestamp:\n                prev_dict[\"timestamp\"] = pref.timestamp\n        if pkg_info is not None:\n            package_dict[\"info\"] = pkg_info\n\n    def add_configurations(self, confs):\n        ConanOutput().warning(\"PackageLists.add_configurations() non-public, non-documented method \"\n                              \"will be removed, use .add_pref() instead\",\n                              warn_tag=\"deprecated\")\n        for pref, conf in confs.items():\n            rev_dict = self.recipe_dict(pref.ref)\n            try:\n                rev_dict[\"packages\"][pref.package_id][\"info\"] = conf\n            except KeyError:  # If package_id does not exist, do nothing, only add to existing prefs\n                pass\n\n    def refs(self):\n        ConanOutput().warning(\"PackageLists.refs() non-public, non-documented method will be \"\n                              \"removed, use .items() instead\", warn_tag=\"deprecated\")\n        result = {}\n        for ref, ref_dict in self._data.items():\n            for rrev, rrev_dict in ref_dict.get(\"revisions\", {}).items():\n                t = rrev_dict.get(\"timestamp\")\n                recipe = RecipeReference.loads(f\"{ref}#{rrev}\")  # TODO: optimize this\n                if t is not None:\n                    recipe.timestamp = t\n                result[recipe] = rrev_dict\n        return result\n\n    def items(self) -> Iterable[Tuple[RecipeReference, Dict[PkgReference, Dict]]]:\n        \"\"\" Iterate the contents of the package list.\n\n        The first dictionary is the information directly belonging to the recipe-revision.\n        The second dictionary contains PkgReference as keys, and a dictionary with the values\n        belonging to that specific package reference (settings, options, etc.).\n        \"\"\"\n        for ref, ref_dict in self._data.items():\n            for rrev, rrev_dict in ref_dict.get(\"revisions\", {}).items():\n                recipe = RecipeReference.loads(f\"{ref}#{rrev}\")  # TODO: optimize this\n                t = rrev_dict.get(\"timestamp\")\n                if t is not None:\n                    recipe.timestamp = t\n                packages = {}\n                for package_id, pkg_info in rrev_dict.get(\"packages\", {}).items():\n                    prevs = pkg_info.get(\"revisions\", {})\n                    for prev, prev_info in prevs.items():\n                        t = prev_info.get(\"timestamp\")\n                        pref = PkgReference(recipe, package_id, prev, t)\n                        packages[pref] = prev_info\n                yield recipe, packages\n\n    def recipe_dict(self, ref: RecipeReference):\n        \"\"\" Gives read/write access to the dictionary containing a specific RecipeReference\n        information.\n        \"\"\"\n        return self._data[str(ref)][\"revisions\"][ref.revision]\n\n    def has_rref(self, ref: RecipeReference) -> bool:\n        # Checks if the PackagesList contains the given RecipeReference.\n        return str(ref) in self._data and ref.revision in self._data[str(ref)].get(\"revisions\", {})\n\n    def package_dict(self, pref: PkgReference):\n        \"\"\" Gives read/write access to the dictionary containing a specific PkgReference\n        information\n        \"\"\"\n        ref_dict = self.recipe_dict(pref.ref)\n        return ref_dict[\"packages\"][pref.package_id][\"revisions\"][pref.revision]\n\n    @staticmethod\n    def prefs(ref, recipe_bundle):\n        ConanOutput().warning(\"PackageLists.prefs() non-public, non-documented method will be \"\n                              \"removed, use .items() instead\", warn_tag=\"deprecated\")\n        result = {}\n        for package_id, pkg_bundle in recipe_bundle.get(\"packages\", {}).items():\n            prevs = pkg_bundle.get(\"revisions\", {})\n            for prev, prev_bundle in prevs.items():\n                t = prev_bundle.get(\"timestamp\")\n                pref = PkgReference(ref, package_id, prev, t)\n                result[pref] = prev_bundle\n        return result\n\n    def serialize(self):\n        \"\"\" Serialize the instance to a dictionary.\"\"\"\n        return copy.deepcopy(self._data)\n\n    @staticmethod\n    def deserialize(data):\n        \"\"\" Loads the data from a serialized dictionary.\"\"\"\n        result = PackagesList()\n        result._data = copy.deepcopy(data)\n        return result\n\n\nclass ListPattern:\n    \"\"\" Object holding a pattern that matches recipes, revisions and packages.\"\"\"\n\n    def __init__(self, expression, rrev=\"latest\", package_id=None, prev=\"latest\", only_recipe=False):\n        \"\"\"\n        :param expression: The pattern to match, e.g. ``\"name/*:*\"``\n        :param rrev: The recipe revision to match, defaults to ``\"latest\"``,\n                     can also be ``\"!latest\"`` or ``\"~latest\"`` to match all but the latest revision,\n                     a pattern like ``\"1234*\"`` to match a specific revision,\n                     or a specific revision like ``\"1234\"``.\n        :param package_id: The package ID to match, defaults to ``None``, which matches all package IDs.\n        :param prev: The package revision to match, defaults to ``\"latest\"``,\n                     can also be ``\"!latest\"`` or ``\"~latest\"`` to match all but the latest revision,\n                     a pattern like ``\"1234*\"`` to match a specific revision,\n                     or a specific revision like ``\"1234\"``.\n        :param only_recipe: If ``True``, only the recipe part of the expression is parsed,\n                            ignoring ``package_id`` and ``prev``. This is useful for commands that\n                            only operate on recipes, like ``conan search``.\n        \"\"\"\n        def split(s, c, default=None):\n            if not s:\n                return None, default\n            tokens = s.split(c, 1)\n            if len(tokens) == 2:\n                return tokens[0], tokens[1] or default\n            return tokens[0], default\n\n        recipe, package = split(expression, \":\")\n        self.raw = expression\n        self.ref, rrev = split(recipe, \"#\", rrev)\n        ref, user_channel = split(self.ref, \"@\")\n        self.name, self.version = split(ref, \"/\")\n        self.user, self.channel = split(user_channel, \"/\")\n        self.rrev, _ = split(rrev, \"%\")\n        self.package_id, prev = split(package, \"#\", prev)\n        self.prev, _ = split(prev, \"%\")\n        if only_recipe:\n            if self.package_id:\n                raise ConanException(\"Do not specify 'package_id' with 'only-recipe'\")\n        else:\n            self.package_id = self.package_id or package_id\n\n    @staticmethod\n    def _only_latest(rev):\n        return rev in [\"!latest\", \"~latest\"]\n\n    @property\n    def search_ref(self):\n        vrange = self._version_range\n        if vrange:\n            return str(RecipeReference(self.name, \"*\", self.user, self.channel))\n        if \"*\" in self.ref or not self.version or (self.package_id is None and self.rrev is None):\n            return self.ref\n\n    @property\n    def _version_range(self):\n        if self.version and self.version.startswith(\"[\") and self.version.endswith(\"]\"):\n            return VersionRange(self.version[1:-1])\n\n    def filter_versions(self, refs, resolve_prereleases=None):\n        vrange = self._version_range\n        if vrange:\n            refs = [r for r in refs if vrange.contains(r.version, resolve_prereleases)]\n        return refs\n\n    @property\n    def is_latest_rrev(self):\n        return self.rrev == \"latest\"\n\n    @property\n    def is_latest_prev(self):\n        return self.prev == \"latest\"\n\n    def check_refs(self, refs):\n        if not refs and self.ref and \"*\" not in self.ref:\n            raise NotFoundException(f\"Recipe '{self.ref}' not found\")\n\n    def filter_rrevs(self, rrevs):\n        if self._only_latest(self.rrev):\n            return rrevs[1:]\n        rrevs = [r for r in rrevs if fnmatch.fnmatch(r.revision, self.rrev)]\n        if not rrevs:\n            refs_str = f'{self.ref}#{self.rrev}'\n            if \"*\" not in refs_str:\n                raise ConanException(f\"Recipe revision '{refs_str}' not found\")\n        return rrevs\n\n    def filter_prefs(self, prefs):\n        prefs = [p for p in prefs if fnmatch.fnmatch(p.package_id, self.package_id)]\n        if not prefs:\n            refs_str = f'{self.ref}#{self.rrev}:{self.package_id}'\n            if \"*\" not in refs_str:\n                raise ConanException(f\"Package ID '{self.raw}' not found\")\n        return prefs\n\n    def filter_prevs(self, prevs):\n        if self._only_latest(self.prev):\n            return prevs[1:]\n        prevs = [p for p in prevs if fnmatch.fnmatch(p.revision, self.prev)]\n        if not prevs:\n            refs_str = f'{self.ref}#{self.rrev}:{self.package_id}#{self.prev}'\n            if \"*\" not in refs_str:\n                raise ConanException(f\"Package revision '{self.raw}' not found\")\n        return prevs\n"
  },
  {
    "path": "conan/api/model/refs.py",
    "content": "\nimport fnmatch\nimport re\nfrom functools import total_ordering\n\nfrom conan.errors import ConanException\nfrom conan.internal.model.version import Version\nfrom conan.internal.util.dates import timestamp_to_str\n\n\n@total_ordering\nclass RecipeReference:\n    \"\"\" An exact (no version-range, no alias) reference of a recipe,\n    it represents a reference of the form ``name/version[@user/channel][#revision][%timestamp]``.\n    Should be enough to locate a recipe in the cache or in a server, and\n    validation will be external to this class, at specific points (export, api, etc).\n    \"\"\"\n\n    def __init__(self, name=None, version=None, user=None, channel=None, revision=None,\n                 timestamp=None):\n        \"\"\" The attributes should be regarded as immutable, and should not be modified by the user.\"\"\"\n        #: Name of the reference\n        self.name: str = name\n        if version is not None and not isinstance(version, Version):\n            version = Version(version)\n        #: Version of the reference\n        self.version: Version = version  # This MUST be a version if we want to be able to order\n        #: User of the reference, if any\n        self.user = user\n        #: Channel of the reference, if any\n        self.channel = channel\n        #: Revision of the reference, if any\n        self.revision = revision\n        #: Timestamp of the reference, if any\n        self.timestamp = timestamp\n\n    def copy(self):\n        # Used for creating copy in lockfile-overrides mechanism\n        return RecipeReference(self.name, self.version, self.user, self.channel, self.revision,\n                               self.timestamp)\n\n    def __repr__(self):\n        \"\"\" long repr like pkg/0.1@user/channel#rrev%timestamp \"\"\"\n        result = self.repr_notime()\n        if self.timestamp is not None:\n            result += \"%{}\".format(self.timestamp)\n        return result\n\n    def repr_notime(self):\n        result = self.__str__()\n        if self.revision is not None:\n            result += \"#{}\".format(self.revision)\n        return result\n\n    def repr_humantime(self):\n        result = self.repr_notime()\n        assert self.timestamp\n        result += \" ({})\".format(timestamp_to_str(self.timestamp))\n        return result\n\n    def __str__(self):\n        \"\"\" shorter representation, excluding the revision and timestamp \"\"\"\n        if self.name is None:\n            return \"\"\n        result = \"/\".join([self.name, str(self.version)])\n        if self.user:\n            result += \"@{}\".format(self.user)\n        if self.channel:\n            assert self.user\n            result += \"/{}\".format(self.channel)\n        return result\n\n    def __lt__(self, ref):\n        # The timestamp goes before the revision for ordering revisions chronologically\n        # In theory this is enough for sorting\n        # When no timestamp is given, it will always have lower priority, to avoid comparison\n        # errors float <> None\n        return (self.name, self.version, self.user or \"\", self.channel or \"\", self.timestamp or 0,\n                self.revision or \"\") \\\n               < (ref.name, ref.version, ref.user or \"\", ref.channel or \"\", ref.timestamp or 0,\n                  ref.revision or \"\")\n\n    def __eq__(self, ref):\n        # Timestamp doesn't affect equality.\n        # This is necessary for building an ordered list of UNIQUE recipe_references for Lockfile\n        if ref is None:\n            return False\n        # If one revision is not defined, they are equal\n        if self.revision is not None and ref.revision is not None:\n            return (self.name, self.version, self.user, self.channel, self.revision) == \\\n                   (ref.name, ref.version, ref.user, ref.channel, ref.revision)\n        return (self.name, self.version, self.user, self.channel) == \\\n               (ref.name, ref.version, ref.user, ref.channel)\n\n    def __hash__(self):\n        # This is necessary for building an ordered list of UNIQUE recipe_references for Lockfile\n        return hash((self.name, self.version, self.user, self.channel))\n\n    @staticmethod\n    def loads(rref):\n        \"\"\" Instantiates an object from a string, in the form:\n        ``name/version[@user/channel][#revision][%timestamp]``\"\"\"\n        try:\n            # timestamp\n            tokens = rref.rsplit(\"%\", 1)\n            text = tokens[0]\n            timestamp = float(tokens[1]) if len(tokens) == 2 else None\n\n            # revision\n            tokens = text.split(\"#\", 1)\n            ref = tokens[0]\n            revision = tokens[1] if len(tokens) == 2 else None\n\n            # name, version always here\n            tokens = ref.split(\"@\", 1)\n            name, version = tokens[0].split(\"/\", 1)\n            assert name and version\n            # user and channel\n            if len(tokens) == 2 and tokens[1]:\n                tokens = tokens[1].split(\"/\", 1)\n                user = tokens[0] if tokens[0] else None\n                channel = tokens[1] if len(tokens) == 2 else None\n            else:\n                user = channel = None\n            return RecipeReference(name, version, user, channel, revision, timestamp)\n        except Exception:\n            from conan.errors import ConanException\n            raise ConanException(\n                f\"{rref} is not a valid recipe reference, provide a reference\"\n                f\" in the form name/version[@user/channel]\")\n\n    def validate_ref(self, allow_uppercase=False):\n        \"\"\" Check that the reference is valid, and raise a ``ConanException`` if not.\n        \"\"\"\n        from conan.api.output import ConanOutput\n        self_str = str(self)\n        if self_str != self_str.lower():\n            if not allow_uppercase:\n                raise ConanException(f\"Conan packages names '{self_str}' must be all lowercase\")\n            else:\n                ConanOutput().warning(f\"Package name '{self_str}' has uppercase, and has been \"\n                                      \"allowed by temporary config. This will break in later 2.X\")\n        if len(self_str) > 200:\n            raise ConanException(f\"Package reference too long >200 {self_str}\")\n        if \":\" in repr(self):\n            raise ConanException(f\"Invalid recipe reference '{repr(self)}' is a package reference\")\n        if not allow_uppercase:\n            validation_pattern = re.compile(r\"^[a-z0-9_][a-z0-9_+.-]{1,100}\\Z\")\n        else:\n            validation_pattern = re.compile(r\"^[a-zA-Z0-9_][a-zA-Z0-9_+.-]{1,100}\\Z\")\n        if validation_pattern.match(self.name) is None:\n            raise ConanException(f\"Invalid package name '{self.name}'\")\n        if validation_pattern.match(str(self.version)) is None:\n            raise ConanException(f\"Invalid package version '{self.version}'\")\n        if self.user and validation_pattern.match(self.user) is None:\n            raise ConanException(f\"Invalid package user '{self.user}'\")\n        if self.channel and validation_pattern.match(self.channel) is None:\n            raise ConanException(f\"Invalid package channel '{self.channel}'\")\n\n        # Warn if they use .+ in the name/user/channel, as it can be problematic for generators\n        pattern = re.compile(r'[.+]')\n        if pattern.search(self.name):\n            ConanOutput().warning(f\"Name containing special chars is discouraged '{self.name}'\")\n        if self.user and pattern.search(self.user):\n            ConanOutput().warning(f\"User containing special chars is discouraged '{self.user}'\")\n        if self.channel and pattern.search(self.channel):\n            ConanOutput().warning(f\"Channel containing special chars is discouraged \"\n                                  f\"'{self.channel}'\")\n\n    def matches(self, pattern, is_consumer):\n        \"\"\" fnmatches the reference against the provided pattern.\n\n        :parameter str pattern: the pattern to match against, it can contain wildcards,\n            and can start with ``!`` or ``~`` to negate the match.\n            A special value of ``&`` will return a match only of ``is_consumer`` is ``True``\n        :parameter bool is_consumer: if ``True``, the pattern ``&`` will match this reference.\n        \"\"\"\n        negate = False\n        if pattern.startswith(\"!\") or pattern.startswith(\"~\"):\n            pattern = pattern[1:]\n            negate = True\n\n        no_user_channel = False\n        if pattern.endswith(\"@\"):  # it means we want to match only without user/channel\n            pattern = pattern[:-1]\n            no_user_channel = True\n        elif \"@#\" in pattern:\n            pattern = pattern.replace(\"@#\", \"#\")\n            no_user_channel = True\n\n        condition = ((pattern == \"&\" and is_consumer) or\n                     fnmatch.fnmatchcase(str(self), pattern) or\n                     fnmatch.fnmatchcase(self.repr_notime(), pattern))\n        if no_user_channel:\n            condition = condition and not self.user and not self.channel\n        if negate:\n            return not condition\n        return condition\n\n    def partial_match(self, pattern):\n        # Finds if pattern matches any of partial sums of tokens of conan reference\n        tokens = [self.name, \"/\", str(self.version)]\n        if self.user:\n            tokens += [\"@\", self.user]\n        if self.channel:\n            tokens += [\"/\", self.channel]\n        if self.revision:\n            tokens += [\"#\", self.revision]\n        partial = \"\"\n        for token in tokens:\n            partial += token\n            if pattern.match(partial):\n                return True\n\n\nclass PkgReference:\n\n    def __init__(self, ref=None, package_id=None, revision=None, timestamp=None):\n        self.ref = ref\n        self.package_id = package_id\n        self.revision = revision\n        self.timestamp = timestamp  # float, Unix seconds UTC\n\n    def __repr__(self):\n        \"\"\" long repr like pkg/0.1@user/channel#rrev%timestamp \"\"\"\n        if self.ref is None:\n            return \"\"\n        result = repr(self.ref)\n        if self.package_id:\n            result += \":{}\".format(self.package_id)\n        if self.revision is not None:\n            result += \"#{}\".format(self.revision)\n        if self.timestamp is not None:\n            result += \"%{}\".format(self.timestamp)\n        return result\n\n    def repr_notime(self):\n        if self.ref is None:\n            return \"\"\n        result = self.ref.repr_notime()\n        if self.package_id:\n            result += \":{}\".format(self.package_id)\n        if self.revision is not None:\n            result += \"#{}\".format(self.revision)\n        return result\n\n    def repr_humantime(self):\n        result = self.repr_notime()\n        assert self.timestamp\n        result += \" ({})\".format(timestamp_to_str(self.timestamp))\n        return result\n\n    def __str__(self):\n        \"\"\" shorter representation, excluding the revision and timestamp \"\"\"\n        if self.ref is None:\n            return \"\"\n        result = str(self.ref)\n        if self.package_id:\n            result += \":{}\".format(self.package_id)\n        return result\n\n    def __lt__(self, ref):\n        # The timestamp goes before the revision for ordering revisions chronologically\n        raise Exception(\"WHO IS COMPARING PACKAGE REFERENCES?\")\n        # return (self.name, self.version, self.user, self.channel, self.timestamp, self.revision) \\\n        #       < (ref.name, ref.version, ref.user, ref.channel, ref._timestamp, ref.revision)\n\n    def __eq__(self, other):\n        # TODO: In case of equality, should it use the revision and timestamp?\n        # Used:\n        #    at \"graph_binaries\" to check: cache_latest_prev != pref\n        #    at \"installer\" to check: if pkg_layout.reference != pref (probably just optimization?)\n        #    at \"revisions_test\"\n        return self.ref == other.ref and self.package_id == other.package_id and \\\n               self.revision == other.revision\n\n    def __hash__(self):\n        # Used in dicts of PkgReferences as keys like the cached nodes in the graph binaries\n        return hash((self.ref, self.package_id, self.revision))\n\n    @staticmethod\n    def loads(pkg_ref):  # TODO: change this default to validate only on end points\n        try:\n            tokens = pkg_ref.split(\":\", 1)\n            assert len(tokens) == 2\n            ref, pkg_id = tokens\n\n            ref = RecipeReference.loads(ref)\n\n            # timestamp\n            tokens = pkg_id.rsplit(\"%\", 1)\n            text = tokens[0]\n            timestamp = float(tokens[1]) if len(tokens) == 2 else None\n\n            # revision\n            tokens = text.split(\"#\", 1)\n            package_id = tokens[0]\n            revision = tokens[1] if len(tokens) == 2 else None\n\n            return PkgReference(ref, package_id, revision, timestamp)\n        except Exception:\n            raise ConanException(\n                f\"{pkg_ref} is not a valid package reference, provide a reference\"\n                f\" in the form name/version[@user/channel:package_id]\")\n"
  },
  {
    "path": "conan/api/model/remote.py",
    "content": "LOCAL_RECIPES_INDEX = \"local-recipes-index\"\n\n\nclass Remote:\n    \"\"\"\n    The ``Remote`` class represents a remote registry of packages.\n    \"\"\"\n    def __init__(self, name, url, verify_ssl=True, disabled=False, allowed_packages=None,\n                 remote_type=None, recipes_only=False):\n        \"\"\" A Remote object can be constructed to be passed as an argument to\n        RemotesAPI methods. When possible, it is better to use Remote objects returned by the API,\n        but for the ``RemotesAPI.add()`` method, for which a new constructed object is necessary.\n        It is recommended to use named arguments like ``Remote(..., verify_ssl=False)`` in\n        the constructor.\n        :param name: The name of the remote.\n        :param url: The URL of the remote repository (or local folder for \"local-recipes-index\").\n        :param verify_ssl: Enable SSL Certificate validation.\n        :param disabled: Disable the remote repository.\n        :param allowed_packages: List of patterns of allowed packages from this remote\n        :param remote_type: Type of the remote repository, use \"local-recipes-index\" or ``None``\n        :param recipes_only: If True, binaries form this remote will be ignored and never used\n        \"\"\"\n        self.name = name  # Read only, is the key\n        self.url = url\n        self.verify_ssl = verify_ssl\n        self.disabled = disabled\n        self.allowed_packages = allowed_packages\n        self.recipes_only = recipes_only\n        self.remote_type = remote_type\n        self._caching = {}\n\n    def __eq__(self, other):\n        if other is None:\n            return False\n        return (self.name == other.name and self.url == other.url and\n                self.verify_ssl == other.verify_ssl and self.disabled == other.disabled)\n\n    def __str__(self):\n        allowed_msg = \"\"\n        if self.allowed_packages:\n            allowed_msg = \", Allowed packages: {}\".format(\", \".join(self.allowed_packages))\n        if self.recipes_only:\n            allowed_msg += \", Recipes only\"\n        if self.remote_type == LOCAL_RECIPES_INDEX:\n            return \"{}: {} [{}, Enabled: {}{}]\".format(self.name, self.url, LOCAL_RECIPES_INDEX,\n                                                       not self.disabled, allowed_msg)\n        return \"{}: {} [Verify SSL: {}, Enabled: {}{}]\".format(self.name, self.url, self.verify_ssl,\n                                                               not self.disabled, allowed_msg)\n\n    def __repr__(self):\n        return str(self)\n\n    def invalidate_cache(self):\n        \"\"\" If external operations might have modified the remote since it was instantiated,\n        this method can be called to invalidate the cache.\n        Note that this is done automatically when the remote is used in any operation by Conan,\n        such as uploading packages, so this method is not usually needed when only interacting\n        with the Conan API\"\"\"\n        self._caching = {}\n"
  },
  {
    "path": "conan/api/output.py",
    "content": "import fnmatch\nimport os\nimport sys\nimport time\nfrom threading import Lock\n\nimport colorama\nfrom colorama import Fore, Style\n\nfrom conan.errors import ConanException\n\nLEVEL_QUIET = 80  # -q\nLEVEL_ERROR = 70  # Errors\nLEVEL_WARNING = 60  # Warnings\nLEVEL_NOTICE = 50  # Important messages to attract user attention.\nLEVEL_STATUS = 40  # Default - The main interesting messages that users might be interested in.\nLEVEL_VERBOSE = 30  # -v  Detailed informational messages.\nLEVEL_DEBUG = 20  # -vv Closely related to internal implementation details\nLEVEL_TRACE = 10  # -vvv Fine-grained messages with very low-level implementation details\n\n\nclass Color:\n    \"\"\" Wrapper around colorama colors that are undefined in importing\n    \"\"\"\n    RED = Fore.RED  # @UndefinedVariable\n    WHITE = Fore.WHITE  # @UndefinedVariable\n    CYAN = Fore.CYAN  # @UndefinedVariable\n    GREEN = Fore.GREEN  # @UndefinedVariable\n    MAGENTA = Fore.MAGENTA  # @UndefinedVariable\n    BLUE = Fore.BLUE  # @UndefinedVariable\n    YELLOW = Fore.YELLOW  # @UndefinedVariable\n    BLACK = Fore.BLACK  # @UndefinedVariable\n\n    BRIGHT_RED = Style.BRIGHT + Fore.RED  # @UndefinedVariable\n    BRIGHT_BLUE = Style.BRIGHT + Fore.BLUE  # @UndefinedVariable\n    BRIGHT_YELLOW = Style.BRIGHT + Fore.YELLOW  # @UndefinedVariable\n    BRIGHT_GREEN = Style.BRIGHT + Fore.GREEN  # @UndefinedVariable\n    BRIGHT_CYAN = Style.BRIGHT + Fore.CYAN  # @UndefinedVariable\n    BRIGHT_WHITE = Style.BRIGHT + Fore.WHITE  # @UndefinedVariable\n    BRIGHT_MAGENTA = Style.BRIGHT + Fore.MAGENTA  # @UndefinedVariable\n\n\nif os.environ.get(\"CONAN_COLOR_DARK\"):\n    Color.WHITE = Fore.BLACK\n    Color.CYAN = Fore.BLUE\n    Color.YELLOW = Fore.MAGENTA\n    Color.BRIGHT_WHITE = Fore.BLACK\n    Color.BRIGHT_CYAN = Fore.BLUE\n    Color.BRIGHT_YELLOW = Fore.MAGENTA\n    Color.BRIGHT_GREEN = Fore.GREEN\n\n\ndef init_colorama(stream):\n    import colorama\n    if _color_enabled(stream):\n        if os.getenv(\"CLICOLOR_FORCE\", \"0\") != \"0\":\n            # Otherwise it is not really forced if colorama doesn't feel it\n            colorama.init(strip=False, convert=False)\n        else:\n            colorama.init()\n\n\ndef _color_enabled(stream):\n    \"\"\"\n    NO_COLOR: No colors\n\n    https://no-color.org/\n\n    Command-line software which adds ANSI color to its output by default should check for the\n    presence of a NO_COLOR environment variable that, when present (**regardless of its value**),\n    prevents the addition of ANSI color.\n\n    CLICOLOR_FORCE: Force color\n\n    https://bixense.com/clicolors/\n    \"\"\"\n\n    if os.getenv(\"CLICOLOR_FORCE\", \"0\") != \"0\":\n        # CLICOLOR_FORCE != 0, ANSI colors should be enabled no matter what.\n        return True\n\n    if os.getenv(\"NO_COLOR\") is not None:\n        return False\n    return hasattr(stream, \"isatty\") and stream.isatty()\n\n\nclass ConanOutput:\n    \"\"\" A singleton class to handle output messages in Conan.\n\n    Recipes should only access this class through the ``self.output`` attribute of the recipe,\n    but custom commands or tools can instantiate it directly, where doing so for each message is\n    a valid practice.\n\n    It provides methods to write messages at different levels of verbosity, such as debug, info,\n    warning, and error. The output level can be controlled by the user through command-line options\n    or environment variables.\n\n    The output methods return the instance itself, so different methods can be chained together.\n    \"\"\"\n    # Singleton\n    _conan_output_level = LEVEL_STATUS\n    _silent_warn_tags = []\n    _warnings_as_errors = []\n    lock = Lock()\n\n    def __init__(self, scope: str = \"\"):\n        \"\"\" Initialize the ConanOutput instance.\n\n        :parameter scope: A string that represents the scope of the output. This is usually the\n            reference of the recipe being executed, like ``pkg/1.0@user/channel`` and is prefixed\n            to the output messages. If not provided, it defaults to an empty string.\n        \"\"\"\n        self.stream = sys.stderr\n        self._scope = scope\n        # FIXME:  This is needed because in testing we are redirecting the sys.stderr to a buffer\n        #         stream to capture it, so colorama is not there to strip the color bytes\n        self._color = _color_enabled(self.stream)\n\n    @classmethod\n    def define_silence_warnings(cls, warnings):\n        cls._silent_warn_tags = warnings\n\n    @classmethod\n    def set_warnings_as_errors(cls, value):\n        cls._warnings_as_errors = value\n\n    @classmethod\n    def get_output_level(cls):\n        return cls._conan_output_level\n\n    @classmethod\n    def set_output_level(cls, level):\n        cls._conan_output_level = level\n\n    @classmethod\n    def valid_log_levels(cls):\n        return {\"quiet\": LEVEL_QUIET,  # -vquiet 80\n                \"error\": LEVEL_ERROR,  # -verror 70\n                \"warning\": LEVEL_WARNING,  # -vwaring 60\n                \"notice\": LEVEL_NOTICE,  # -vnotice 50\n                \"status\": LEVEL_STATUS,  # -vstatus 40\n                None: LEVEL_VERBOSE,  # -v 30\n                \"verbose\": LEVEL_VERBOSE,  # -vverbose 30\n                \"debug\": LEVEL_DEBUG,  # -vdebug 20\n                \"v\": LEVEL_DEBUG,  # -vv 20\n                \"trace\": LEVEL_TRACE,  # -vtrace 10\n                \"vv\": LEVEL_TRACE  # -vvv 10\n                }\n\n    @classmethod\n    def define_log_level(cls, v):\n        env_level = os.getenv(\"CONAN_LOG_LEVEL\")\n        v = env_level or v\n        levels = cls.valid_log_levels()\n        try:\n            level = levels[v]\n        except KeyError:\n            msg = \" defined in CONAN_LOG_LEVEL environment variable\" if env_level else \"\"\n            vals = \"quiet, error, warning, notice, status, verbose, debug(v), trace(vv)\"\n            raise ConanException(f\"Invalid argument '-v{v}'{msg}.\\nAllowed values: {vals}\")\n        else:\n            cls.set_output_level(level)\n\n    @classmethod\n    def level_allowed(cls, level):\n        return cls._conan_output_level <= level\n\n    @property\n    def color(self):\n        return self._color\n\n    @property\n    def scope(self):\n        return self._scope\n\n    @scope.setter\n    def scope(self, out_scope):\n        self._scope = out_scope\n\n    @property\n    def is_terminal(self):\n        return hasattr(self.stream, \"isatty\") and self.stream.isatty()\n\n    def writeln(self, data, fg=None, bg=None):\n        return self.write(data, fg, bg, newline=True)\n\n    def write(self, data, fg=None, bg=None, newline=False):\n        if self._conan_output_level > LEVEL_NOTICE:\n            return self\n        if self._color and (fg or bg):\n            data = \"%s%s%s%s\" % (fg or '', bg or '', data, Style.RESET_ALL)\n\n        if newline:\n            data = \"%s\\n\" % data\n\n        with self.lock:\n            self.stream.write(data)\n            self.stream.flush()\n\n        return self\n\n    def box(self, msg: str):\n        \"\"\" Draw a box around the message, useful for important messages\"\"\"\n        color = Color.BRIGHT_GREEN\n        self.writeln(\"\\n**************************************************\", fg=color)\n        self.writeln(f'*{msg: ^48}*', fg=color)\n        self.writeln(f\"**************************************************\\n\", fg=color)\n        return self\n\n    def login_msg(self, msg, newline=False):\n        # unconditional to the error level, this has to show always\n        self._write_message(msg, newline=newline)\n        return self\n\n    def _write_message(self, msg, fg=None, bg=None, newline=True):\n        if isinstance(msg, dict):\n            # For traces we can receive a dict already, we try to transform then into more natural\n            # text\n            msg = \", \".join([f\"{k}: {v}\" for k, v in msg.items()])\n            msg = \"=> {}\".format(msg)\n            # msg = json.dumps(msg, sort_keys=True, default=json_encoder)\n\n        if self._scope:\n            if self._color:\n                ret = f\"{fg or ''}{bg or ''}{self._scope}: {msg}{Style.RESET_ALL}\"\n            else:\n                ret = f\"{self._scope}: {msg}\"\n        else:\n            if self._color:\n                ret = f\"{fg or ''}{bg or ''}{msg}{Style.RESET_ALL}\"\n            else:\n                ret = msg\n\n        if newline:\n            ret = f\"{ret}\\n\"\n\n        with self.lock:\n            self.stream.write(ret)\n            self.stream.flush()\n\n    def trace(self, msg: str):\n        \"\"\" This is the most extreme level of detail.\n\n        Trace messages log every little step the system takes, including function entries and exits,\n        variable changes, and other very specific events.\n\n        This message won't be printed unless the user has set the log level to trace\n        (e.g., using the ``-vvv`` option in the command line).\n\n        It’s used when full visibility of everything happening in the system is required,\n        but should be used carefully due to the large amount of information it can generate.\"\"\"\n        if self._conan_output_level <= LEVEL_TRACE:\n            self._write_message(msg, fg=Color.BLUE)\n        return self\n\n    def debug(self, msg: str, fg: str = Color.MAGENTA, bg: str = None):\n        \"\"\" With a high level of detail, it is mainly used for debugging code.\n\n        This message won't be printed unless the user has set the log level to debug\n        (e.g., using the ``-vv`` option in the command line).\n\n        These messages provide useful information for developers, such as variable values\n        or execution flow details, to trace errors or analyze the program's behavior.\"\"\"\n        if self._conan_output_level <= LEVEL_DEBUG:\n            self._write_message(msg, fg=fg, bg=bg)\n        return self\n\n    def verbose(self, msg: str, fg: str = None, bg: str = None):\n        \"\"\" Displays additional and detailed information that, while not critical,\n        can be useful for better understanding how the system is working.\n\n        This message won't be printed unless the user has set the log level to verbose\n        (e.g., using the ``-v`` option in the command line).\n\n        It’s appropriate for gaining more context without overloading the logs with\n        excessive detail. Useful when more clarity is needed than a simple info.\"\"\"\n        if self._conan_output_level <= LEVEL_VERBOSE:\n            self._write_message(msg, fg=fg, bg=bg)\n        return self\n\n    def status(self, msg: str, fg: str = None, bg: str = None, newline: bool = True):\n        \"\"\" Provides general information about the system or ongoing operations.\n\n        Info messages are basic and used to inform about common events,\n        like the start or completion of processes, without implying specific problems or achievements.\"\"\"\n        if self._conan_output_level <= LEVEL_STATUS:\n            self._write_message(msg, fg=fg, bg=bg, newline=newline)\n        return self\n\n    info = status\n\n    def title(self, msg: str):\n        \"\"\" Draws a title around the message, useful for important messages\"\"\"\n        if self._conan_output_level <= LEVEL_NOTICE:\n            self._write_message(\"\\n======== {} ========\".format(msg),\n                                fg=Color.BRIGHT_MAGENTA)\n        return self\n\n    def subtitle(self, msg: str):\n        \"\"\" Draws a subtitle around the message, useful for important messages\"\"\"\n        if self._conan_output_level <= LEVEL_NOTICE:\n            self._write_message(\"\\n-------- {} --------\".format(msg),\n                                fg=Color.BRIGHT_MAGENTA)\n        return self\n\n    def highlight(self, msg: str):\n        \"\"\" Marks or emphasizes important events or processes that need to stand out but don’t necessarily\n        indicate success or error.\n\n        These messages draw attention to key points that may be relevant for the user or administrator.\"\"\"\n        if self._conan_output_level <= LEVEL_NOTICE:\n            self._write_message(msg, fg=Color.BRIGHT_MAGENTA)\n        return self\n\n    def success(self, msg: str):\n        \"\"\" Shows that an operation has been completed successfully.\n\n        This type of message is useful to confirm that key processes or tasks have finished correctly,\n        which is essential for good application monitoring.\"\"\"\n        if self._conan_output_level <= LEVEL_NOTICE:\n            self._write_message(msg, fg=Color.BRIGHT_GREEN)\n        return self\n\n    @staticmethod\n    def _warn_tag_matches(warn_tag, patterns):\n        lookup_tag = warn_tag or \"unknown\"\n        return any(fnmatch.fnmatch(lookup_tag, pattern) for pattern in patterns)\n\n    def warning(self, msg: str, warn_tag: str = None):\n        \"\"\" Highlights a potential issue that, while not stopping the system,\n        could cause problems in the future or under certain conditions.\n\n        Warnings signal abnormal situations that should be\n        reviewed but don’t necessarily cause an immediate halt in operations.\n        Notice that if the tag matches the pattern in the ``core:warnings_as_errors`` configuration,\n        and is not skipped, this will be upgraded to an error, and raise an exception\n        when the output is printed, so that the error does not pass unnoticed.\"\"\"\n        _treat_as_error = self._warn_tag_matches(warn_tag, self._warnings_as_errors)\n        if (self._conan_output_level <= LEVEL_WARNING or\n                (_treat_as_error and self._conan_output_level <= LEVEL_ERROR)):\n            if self._warn_tag_matches(warn_tag, self._silent_warn_tags):\n                return self\n            warn_tag_msg = \"\" if warn_tag is None else f\"{warn_tag}: \"\n            output = f\"{warn_tag_msg}{msg}\"\n\n            if _treat_as_error:\n                self.error(output)\n            else:\n                self._write_message(f\"WARN: {output}\", Color.YELLOW)\n        return self\n\n    def error(self, msg: str, error_type: str = None):\n        \"\"\" Indicates that a serious issue has occurred that prevents the system\n        or application from continuing to function correctly.\n\n        Typically, this represents a failure in the normal flow of execution,\n        such as a service crash or a critical exception.\n        Notice that if the user has set the ``core:warnings_as_errors`` configuration,\n        this will raise an exception when the output is printed,\n        so that the error does not pass unnoticed.\"\"\"\n        if self._warnings_as_errors and error_type != \"exception\":\n            raise ConanException(msg)\n        if self._conan_output_level <= LEVEL_ERROR:\n            self._write_message(\"ERROR: {}\".format(msg), Color.RED)\n        return self\n\n    def flush(self):\n        self.stream.flush()\n\n\ndef cli_out_write(data, fg=None, bg=None, endline=\"\\n\", indentation=0):\n    \"\"\"\n    Output to be used by formatters to dump information to stdout\n    \"\"\"\n    if (fg or bg) and _color_enabled(sys.stdout):  # need color\n        data = f\"{' ' * indentation}{fg or ''}{bg or ''}{data}{Style.RESET_ALL}{endline}\"\n        sys.stdout.write(data)\n    else:\n        data = f\"{' ' * indentation}{data}{endline}\"\n        if sys.stdout.isatty():\n            # https://github.com/conan-io/conan/issues/17245 avoid colorama crash and overhead\n            # skip deinit/reinit if stdout is not a TTY to preserve redirected output to file\n            colorama.deinit()\n            sys.stdout.write(data)\n            colorama.reinit()\n        else:\n            sys.stdout.write(data)\n\n\nclass TimedOutput:\n    def __init__(self, interval, out=None, msg_format=None):\n        self._interval = interval\n        self._msg_format = msg_format\n        self._t = time.time()\n        self._out = out or ConanOutput()\n\n    def info(self, msg, *args, **kwargs):\n        t = time.time()\n        if t - self._t > self._interval:\n            self._t = t\n            if self._msg_format:\n                msg = self._msg_format(msg, *args, **kwargs)\n            self._out.info(msg)\n"
  },
  {
    "path": "conan/api/subapi/__init__.py",
    "content": ""
  },
  {
    "path": "conan/api/subapi/audit.py",
    "content": "import binascii\nimport json\nimport os\nimport base64\n\nfrom conan.internal.api.audit.providers import ConanCenterProvider, PrivateProvider\nfrom conan.errors import ConanException\nfrom conan.internal.api.remotes.encrypt import encode, decode\nfrom conan.internal.model.recipe_ref import RecipeReference\nfrom conan.internal.util.files import save, load\n\nCONAN_CENTER_AUDIT_PROVIDER_NAME = \"conancenter\"\nCYPHER_KEY = \"private\"\n\n\nclass AuditAPI:\n    \"\"\"\n    This class provides the functionality to scan references for vulnerabilities.\n    \"\"\"\n\n    def __init__(self, conan_api):\n        self._conan_api = conan_api\n        self._home_folder = conan_api.home_folder\n        self._providers_path = os.path.join(self._home_folder, \"audit_providers.json\")\n        self._provider_cls = {\n            \"conan-center-proxy\": ConanCenterProvider,\n            \"private\": PrivateProvider,\n        }\n\n    @staticmethod\n    def scan(deps_graph, provider, context=None):\n        \"\"\"\n        Scan a given recipe for vulnerabilities in its dependencies.\n        \"\"\"\n        refs = sorted(set(RecipeReference.loads(f\"{node.ref.name}/{node.ref.version}\")\n                          for node in deps_graph.nodes[1:]\n                          if context is None or node.context == context),\n                      key=lambda ref: ref.name)\n        return provider.get_cves(refs)\n\n    @staticmethod\n    def list(references, provider):\n        \"\"\"\n        List the vulnerabilities of the given reference.\n        \"\"\"\n        refs = [RecipeReference.loads(ref) for ref in references]\n        for ref in refs:\n            ref.validate_ref()\n        return provider.get_cves(refs)\n\n    def get_provider(self, provider_name):\n        \"\"\"\n        Get the provider by name.\n        \"\"\"\n        # TODO: More work remains to be done here, hardcoded for now for testing\n        providers = _load_providers(self._providers_path)\n        if provider_name not in providers:\n            add_arguments = (\n                \"--url=https://audit.conan.io/ --type=conan-center-proxy\"\n                if provider_name == CONAN_CENTER_AUDIT_PROVIDER_NAME\n                else \"--url=<url> --type=<type>\"\n            )\n\n            register_message = (\n                f\"If you don't have a valid token, register at: https://audit.conan.io/register.\"\n                if provider_name == CONAN_CENTER_AUDIT_PROVIDER_NAME\n                else \"\"\n            )\n\n            raise ConanException(\n                f\"Provider '{provider_name}' not found. Please specify a valid provider name or add \"\n                f\"it using: 'conan audit provider add {provider_name} {add_arguments} \"\n                f\"--token=<token>'\\n{register_message}\"\n            )\n\n        provider_data = providers[provider_name]\n        safe_provider_name = provider_name.replace(\"-\", \"_\")\n        env_token = os.getenv(f\"CONAN_AUDIT_PROVIDER_TOKEN_{safe_provider_name.upper()}\")\n\n        if env_token:\n            # Always override the token with the environment variable\n            provider_data[\"token\"] = env_token\n        elif \"token\" in provider_data:\n            try:\n                enc_token = base64.standard_b64decode(provider_data[\"token\"]).decode()\n                provider_data[\"token\"] = decode(enc_token, CYPHER_KEY)\n            except binascii.Error:\n                raise ConanException(f\"Invalid token format for provider '{provider_name}'. \"\n                                     f\"The token might be corrupt.\")\n\n        provider_cls = self._provider_cls.get(provider_data[\"type\"])\n\n        return provider_cls(self._conan_api, provider_name, provider_data)\n\n    def list_providers(self):\n        \"\"\"\n        Get all available providers.\n        \"\"\"\n        providers = _load_providers(self._providers_path)\n        result = []\n        for name, provider_data in providers.items():\n            provider_cls = self._provider_cls.get(provider_data[\"type\"])\n            result.append(provider_cls(self._conan_api, name, provider_data))\n        return result\n\n    def add_provider(self, name, url, provider_type):\n        \"\"\"\n        Add a provider.\n        \"\"\"\n        providers = _load_providers(self._providers_path)\n        if name in providers:\n            raise ConanException(f\"Provider '{name}' already exists\")\n\n        if provider_type not in self._provider_cls:\n            raise ConanException(f\"Provider type '{provider_type}' not found\")\n\n        providers[name] = {\n            \"name\": name,\n            \"url\": url,\n            \"type\": provider_type\n        }\n\n        _save_providers(self._providers_path, providers)\n\n    def remove_provider(self, provider_name):\n        \"\"\"\n        Remove a provider.\n        \"\"\"\n        providers = _load_providers(self._providers_path)\n        if provider_name not in providers:\n            raise ConanException(f\"Provider '{provider_name}' not found\")\n\n        del providers[provider_name]\n\n        _save_providers(self._providers_path, providers)\n\n    def auth_provider(self, provider, token):\n        \"\"\"\n        Authenticate a provider.\n        \"\"\"\n        if not provider:\n            raise ConanException(\"Provider not found\")\n\n        providers = _load_providers(self._providers_path)\n\n        assert provider.name in providers\n        encode_token = encode(token, CYPHER_KEY).encode()\n        providers[provider.name][\"token\"] = base64.standard_b64encode(encode_token).decode()\n        setattr(provider, \"token\", token)\n        _save_providers(self._providers_path, providers)\n\n\ndef _load_providers(providers_path):\n    if not os.path.exists(providers_path):\n        default_providers = {\n            CONAN_CENTER_AUDIT_PROVIDER_NAME: {\n                \"url\": \"https://audit.conan.io/\",\n                \"type\": \"conan-center-proxy\"\n            }\n        }\n        save(providers_path, json.dumps(default_providers, indent=4))\n\n    return json.loads(load(providers_path))\n\n\ndef _save_providers(providers_path, providers):\n    save(providers_path, json.dumps(providers, indent=4))\n    # Make readable & writeable only by current user\n    os.chmod(providers_path, 0o600)\n"
  },
  {
    "path": "conan/api/subapi/cache.py",
    "content": "import json\nimport os\nimport shutil\nimport tarfile\nimport tempfile\n\nfrom conan.api.model import PackagesList\nfrom conan.api.output import ConanOutput\nfrom conan.internal.api.uploader import compress_files, get_compress_level\nfrom conan.internal.cache.cache import PkgCache\nfrom conan.internal.cache.conan_reference_layout import (EXPORT_SRC_FOLDER, EXPORT_FOLDER,\n                                                         SRC_FOLDER, METADATA,\n                                                         DOWNLOAD_EXPORT_FOLDER)\nfrom conan.internal.cache.home_paths import HomePaths\nfrom conan.internal.cache.integrity_check import IntegrityChecker\nfrom conan.internal.paths import COMPRESSIONS\nfrom conan.internal.rest.download_cache import DownloadCache\nfrom conan.errors import ConanException\nfrom conan.api.model import PkgReference\nfrom conan.api.model import RecipeReference\nfrom conan.internal.api.uploader import PackagePreparator\nfrom conan.internal.conan_app import ConanApp\nfrom conan.internal.rest.pkg_sign import PkgSignaturesPlugin\nfrom conan.internal.util.dates import revision_timestamp_now\nfrom conan.internal.util.files import rmdir, mkdir, remove, save\n\n\nclass CacheAPI:\n    \"\"\" This CacheAPI is used to interact with the packages storage cache\n\n    Note that the Conan packages cache is exclusively **read-only** for user code. Only Conan\n    can write or modify the folders and files in the Conan cache. In general, when a method\n    returns a folder, it is mostly for debugging purposes and read-only access, but never to\n    modify the contents of the cache.\n    \"\"\"\n\n    def __init__(self, conan_api, api_helpers):\n        self._conan_api = conan_api\n        self._api_helpers = api_helpers\n\n    def export_path(self, ref: RecipeReference):\n        \"\"\"Returns the path of the recipe conanfile and exported files in the Conan cache\n\n        This folder is exclusively for **read-only** access, typically for debugging purposes,\n        it is completely forbidden to modify any of its contents.\n\n        :param ref: RecipeReference. If it includes recipe revision, that exact revision will be\n           returned, if it doesn't include recipe revision, it will return the latest revision one.\n        :return: path to the folder, as a string\n        :raises: ConanExcepcion if the folder doesn't exist\n        \"\"\"\n\n        cache = PkgCache(self._conan_api.cache_folder, self._api_helpers.global_conf)\n        ref = _resolve_latest_ref(cache, ref)\n        ref_layout = cache.recipe_layout(ref)\n        return _check_folder_existence(ref, \"export\", ref_layout.export())\n\n    def recipe_metadata_path(self, ref: RecipeReference):\n        \"\"\"Returns the path of the recipe metadata files in the Conan cache\n\n        Exceptionally, adding or modifying the files within this folder is allowed, as\n        the metadata files are not taken into account into the computation of the recipe hash\n        (recipe revision).\n\n        :param ref: RecipeReference. If it includes recipe revision, that exact revision will be\n           returned, if it doesn't include recipe revision, it will return the latest revision one.\n        :return: path to the folder, as a string\n        :raises: ConanExcepcion if the folder doesn't exist\n        \"\"\"\n        cache = PkgCache(self._conan_api.cache_folder, self._api_helpers.global_conf)\n        ref = _resolve_latest_ref(cache, ref)\n        ref_layout = cache.recipe_layout(ref)\n        return _check_folder_existence(ref, \"metadata\", ref_layout.metadata())\n\n    def export_source_path(self, ref: RecipeReference):\n        \"\"\"Returns the path of the exported sources in the Conan cache\n\n        Note that the exported sources only exist in the cache when the package has been created\n        locally or built from source.\n\n        This folder is exclusively for **read-only** access, typically for debugging purposes,\n        it is completely forbidden to modify any of its contents.\n\n        :param ref: RecipeReference. If it includes recipe revision, that exact revision will be\n           returned, if it doesn't include recipe revision, it will return the latest revision one.\n        :return: path to the folder, as a string\n        :raises: ConanExcepcion if the folder doesn't exist\n        \"\"\"\n        cache = PkgCache(self._conan_api.cache_folder, self._api_helpers.global_conf)\n        ref = _resolve_latest_ref(cache, ref)\n        ref_layout = cache.recipe_layout(ref)\n        return _check_folder_existence(ref, \"export_sources\", ref_layout.export_sources())\n\n    def source_path(self, ref: RecipeReference):\n        \"\"\"Returns the path of the temporary source folder in the Conan cache\n\n        Note that the source folder only exist in the cache when the package has been created\n        locally or built from source.\n\n        This folder is exclusively for **read-only** access, typically for debugging purposes,\n        it is completely forbidden to modify any of its contents.\n\n        :param ref: RecipeReference. If it includes recipe revision, that exact revision will be\n           returned, if it doesn't include recipe revision, it will return the latest revision one.\n        :return: path to the folder, as a string\n        :raises: ConanExcepcion if the folder doesn't exist\n        \"\"\"\n        cache = PkgCache(self._conan_api.cache_folder, self._api_helpers.global_conf)\n        ref = _resolve_latest_ref(cache, ref)\n        ref_layout = cache.recipe_layout(ref)\n        return _check_folder_existence(ref, \"source\", ref_layout.source())\n\n    def build_path(self, pref: PkgReference):\n        \"\"\"Returns the path of the temporary build folder in the Conan cache\n\n        Note that the build folder only exist in the cache when the package has been created\n        locally or built from source.\n\n        This folder is exclusively for **read-only** access, typically for debugging purposes,\n        it is completely forbidden to modify any of its contents.\n\n        :param pref: PkgReference. If it includes recipe revision, that exact revision will be\n           returned, if it doesn't include recipe revision, it will return the latest revision one.\n           Exactly same behavior for the package revision.\n        :return: path to the folder, as a string\n        :raises: ConanExcepcion if the folder doesn't exist\n        \"\"\"\n        cache = PkgCache(self._conan_api.cache_folder, self._api_helpers.global_conf)\n        pref = _resolve_latest_pref(cache, pref)\n        ref_layout = cache.pkg_layout(pref)\n        return _check_folder_existence(pref, \"build\", ref_layout.build())\n\n    def package_metadata_path(self, pref: PkgReference):\n        \"\"\"Returns the path of the package metadata folder in the Conan cache\n\n        Exceptionally, adding or modifying the files within this folder is allowed, as\n        the metadata files are not taken into account into the computation of the package hash\n        (package revision).\n\n       :param pref: PkgReference. If it includes recipe revision, that exact revision will be\n           returned, if it doesn't include recipe revision, it will return the latest revision one.\n           Exactly same behavior for the package revision.\n       :return: path to the folder, as a string\n       :raises: ConanExcepcion if the folder doesn't exist\n        \"\"\"\n        cache = PkgCache(self._conan_api.cache_folder, self._api_helpers.global_conf)\n        pref = _resolve_latest_pref(cache, pref)\n        ref_layout = cache.pkg_layout(pref)\n        return _check_folder_existence(pref, \"metadata\", ref_layout.metadata())\n\n    def package_path(self, pref: PkgReference):\n        \"\"\"Returns the path of the package folder in the Conan cache\n\n        This folder is exclusively for **read-only** access, typically for debugging purposes,\n        it is completely forbidden to modify any of its contents.\n\n        :param pref: PkgReference. If it includes recipe revision, that exact revision will be\n           returned, if it doesn't include recipe revision, it will return the latest revision one.\n           Exactly same behavior for the package revision.\n        :return: path to the folder, as a string\n        :raises: ConanExcepcion if the folder doesn't exist\n        \"\"\"\n        cache = PkgCache(self._conan_api.cache_folder, self._api_helpers.global_conf)\n        pref = _resolve_latest_pref(cache, pref)\n        ref_layout = cache.pkg_layout(pref)\n        if os.path.exists(ref_layout.finalize()):\n            return ref_layout.finalize()\n        return _check_folder_existence(pref, \"package\", ref_layout.package())\n\n    def check_integrity(self, package_list, return_pkg_list=False):\n        \"\"\"\n        Check if the recipes and packages are corrupted\n\n        :param package_list: PackagesList to check\n        :param return_pkg_list: If True, return a PackagesList with corrupted artifacts\n        :return: PackagesList with corrupted artifacts if return_pkg_list is True\n        :raises: ConanExcepcion if there are corrupted artifacts and return_pkg_list is False\n        \"\"\"\n        cache = PkgCache(self._conan_api.cache_folder, self._api_helpers.global_conf)\n        checker = IntegrityChecker(cache)\n        corrupted_pkg_list = checker.check(package_list)\n        if return_pkg_list:\n            return corrupted_pkg_list\n        if corrupted_pkg_list:\n            raise ConanException(\"There are corrupted artifacts, check the error logs\")\n\n    def sign(self, package_list):\n        \"\"\"Sign packages with the package signing plugin\"\"\"\n        cache = PkgCache(self._conan_api.cache_folder, self._api_helpers.global_conf)\n        pkg_signer = PkgSignaturesPlugin(cache, self._conan_api.home_folder)\n        if not pkg_signer.is_sign_configured:\n            raise ConanException(\n                \"The sign() function in the package sign plugin is not defined. For more \"\n                \"information on how to configure the plugin, please read the documentation at \"\n                \"https://docs.conan.io/2/reference/extensions/package_signing.html.\")\n\n        app = ConanApp(self._conan_api)\n        preparator = PackagePreparator(app, self._api_helpers.cache,\n                                       self._api_helpers.remote_manager,\n                                       self._api_helpers.global_conf)\n        # Some packages can have missing sources/exports_sources\n        enabled_remotes = self._conan_api.remotes.list()\n        preparator.prepare(package_list, enabled_remotes, None, force=True)\n\n        for rref, packages in package_list.items():\n            recipe_bundle = package_list.recipe_dict(rref)\n            rref_folder = cache.recipe_layout(rref).download_export()\n            try:\n                pkg_signer.sign_pkg(rref, recipe_bundle.get(\"files\", {}), rref_folder)\n            except Exception as e:\n                recipe_bundle[\"pkgsign_error\"] = str(e)\n            for pref in packages:\n                pkg_bundle = package_list.package_dict(pref)\n                if pkg_bundle:\n                    pref_folder = cache.pkg_layout(pref).download_package()\n                    try:\n                        pkg_signer.sign_pkg(pref, pkg_bundle.get(\"files\", {}), pref_folder)\n                    except Exception as e:\n                        pkg_bundle[\"pkgsign_error\"] = str(e)\n        return package_list\n\n    def verify(self, package_list):\n        \"\"\"Verify packages with the package signing plugin\"\"\"\n        cache = PkgCache(self._conan_api.cache_folder, self._api_helpers.global_conf)\n        pkg_signer = PkgSignaturesPlugin(cache, self._conan_api.home_folder)\n        if not pkg_signer.is_verify_configured:\n            raise ConanException(\n                \"The verify() function in the package sign plugin is not defined. For more \"\n                \"information on how to configure the plugin, please read the documentation at \"\n                \"https://docs.conan.io/2/reference/extensions/package_signing.html.\")\n\n        for rref, packages in package_list.items():\n            recipe_bundle = package_list.recipe_dict(rref)\n            layout = cache.recipe_layout(rref)\n            rref_folder = layout.download_export()\n            files = {file: os.path.join(rref_folder, file) for file in\n                     sorted(os.listdir(rref_folder)) if not file.startswith(METADATA)}\n            recipe_bundle[\"files\"] = files\n            try:\n                pkg_signer.verify(rref, rref_folder, layout.metadata(), files)\n            except Exception as e:\n                recipe_bundle[\"pkgsign_error\"] = str(e)\n            for pref in packages:\n                pkg_bundle = package_list.package_dict(pref)\n                if pkg_bundle:\n                    layout = cache.pkg_layout(pref)\n                    pref_folder = layout.download_package()\n                    files = {file: os.path.join(pref_folder, file) for file in\n                             sorted(os.listdir(pref_folder)) if not file.startswith(METADATA)}\n                    pkg_bundle[\"files\"] = files\n                    try:\n                        pkg_signer.verify(pref, pref_folder, layout.metadata(), files)\n                    except Exception as e:\n                        pkg_bundle[\"pkgsign_error\"] = str(e)\n        return package_list\n\n    def clean(self, package_list, source=True, build=True, download=True, temp=True,\n              backup_sources=False) -> None:\n        \"\"\"\n        Remove non critical folders from the cache, like source, build and download (.tgz store)\n        folders.\n\n        :param package_list: the package lists that should be cleaned\n        :param source: boolean, remove the \"source\" folder if True\n        :param build: boolean, remove the \"build\" folder if True\n        :param download: boolean, remove the \"download (.tgz)\" folder if True\n        :param temp: boolean, remove the temporary folders\n        :param backup_sources: boolean, remove the \"source\" folder if True\n        :return:\n        \"\"\"\n\n        cache = PkgCache(self._conan_api.cache_folder, self._api_helpers.global_conf)\n        if temp:\n            rmdir(cache.temp_folder)\n            # Clean those build folders that didn't succeed to create a package and wont be in DB\n            builds_folder = cache.builds_folder\n            if os.path.isdir(builds_folder):\n                ConanOutput().verbose(f\"Cleaning temporary folders\")\n                for subdir in os.listdir(builds_folder):\n                    folder = os.path.join(builds_folder, subdir)\n                    manifest = os.path.join(folder, \"p\", \"conanmanifest.txt\")\n                    info = os.path.join(folder, \"p\", \"conaninfo.txt\")\n                    if not os.path.exists(manifest) or not os.path.exists(info):\n                        rmdir(folder)\n\n        if backup_sources:\n            backup_files = self._conan_api.cache.get_backup_sources(package_list, exclude=False,\n                                                                    only_upload=False)\n            ConanOutput().verbose(f\"Cleaning {len(backup_files)} backup sources\")\n            for f in backup_files:\n                remove(f)\n\n        for ref, packages in package_list.items():\n            ConanOutput(ref.repr_notime()).verbose(\"Cleaning recipe cache contents\")\n            ref_layout = cache.recipe_layout(ref)\n            if source:\n                rmdir(ref_layout.source())\n            if download:\n                rmdir(ref_layout.download_export())\n            for pref in packages:\n                ConanOutput(pref).verbose(\"Cleaning package cache contents\")\n                pref_layout = cache.pkg_layout(pref)\n                if build:\n                    rmdir(pref_layout.build())\n                    # It is important to remove the \"build_id\" identifier if build-folder is removed\n                    cache.remove_build_id(pref)\n                if download:\n                    rmdir(pref_layout.download_package())\n\n    def save(self, package_list: PackagesList, path, no_source=False) -> None:\n        \"\"\"Create a compressed archive with recipes and packages from the Conan cache that\n        can be later restored in another cache.\n\n        Do not manipulate the contents of the resulting archive, as it also contains metadata,\n        and modifying the contents would be equivalent to modify the Conan package cache, which\n        is forbidden.\n\n        :param package_list: PackagesList containing the recipes and packages to add\n           to the compressed archive\n        :param path: The archive file to generate. Based on the extension of the file, different\n           compression formats can be used (.tgz, .txz and .tzst, the latter only for Python>=3.14).\n        :param no_source: If True, the source folders in the cache will not be added to the archive.\n        :return:\n        \"\"\"\n        global_conf = self._api_helpers.global_conf\n        cache = PkgCache(self._conan_api.cache_folder, global_conf)\n        cache_folder = cache.store  # Note, this is not the home, but the actual package cache\n        out = ConanOutput()\n        mkdir(os.path.dirname(path))\n        tgz_name = os.path.basename(path)\n        compressformat = next((e for e in COMPRESSIONS if tgz_name.endswith(e)), None)\n        if not compressformat:\n            raise ConanException(f\"Unsupported compression format for {tgz_name}\")\n        compresslevel = get_compress_level(compressformat, global_conf)\n        tar_files: dict[str, str] = {}  # {path_in_tar: abs_path}\n\n        for ref, packages in package_list.items():\n            ref_layout = cache.recipe_layout(ref)\n            recipe_folder = os.path.relpath(ref_layout.base_folder, cache_folder)\n            recipe_folder = recipe_folder.replace(\"\\\\\", \"/\")  # make win paths portable\n            ref_bundle = package_list.recipe_dict(ref)\n            ref_bundle[\"recipe_folder\"] = recipe_folder\n            out.info(f\"Saving {ref}: {recipe_folder}\")\n            # Package only selected folders, not DOWNLOAD one\n            for f in (EXPORT_FOLDER, EXPORT_SRC_FOLDER, SRC_FOLDER):\n                if f == SRC_FOLDER and no_source:\n                    continue\n                cachepath = os.path.join(cache_folder, recipe_folder, f)\n                if os.path.exists(cachepath):\n                    tar_files[f\"{recipe_folder}/{f}\"] = cachepath\n            cachepath = os.path.join(cache_folder, recipe_folder, DOWNLOAD_EXPORT_FOLDER, METADATA)\n            if os.path.exists(cachepath):\n                tar_files[f\"{recipe_folder}/{DOWNLOAD_EXPORT_FOLDER}/{METADATA}\"] = cachepath\n\n            for pref in packages:\n                pref_layout = cache.pkg_layout(pref)\n                pkg_folder = pref_layout.package()\n                folder = os.path.relpath(pkg_folder, cache_folder)\n                folder = folder.replace(\"\\\\\", \"/\")  # make win paths portable\n                pkg_dict = package_list.package_dict(pref)\n                pkg_dict[\"package_folder\"] = folder\n                out.info(f\"Saving {pref}: {folder}\")\n                tar_files[folder] = os.path.join(cache_folder, folder)\n\n                if os.path.exists(pref_layout.metadata()):\n                    metadata_folder = os.path.relpath(pref_layout.metadata(), cache_folder)\n                    metadata_folder = metadata_folder.replace(\"\\\\\", \"/\")  # make paths portable\n                    pkg_dict[\"metadata_folder\"] = metadata_folder\n                    out.info(f\"Saving {pref} metadata: {metadata_folder}\")\n                    tar_files[metadata_folder] = os.path.join(cache_folder, metadata_folder)\n\n        # Create a temporary file in order to reuse compress_files functionality\n        serialized = json.dumps(package_list.serialize(), indent=2)\n        pkglist_path = os.path.join(tempfile.gettempdir(), \"pkglist.json\")\n        save(pkglist_path, serialized)\n        tar_files[\"pkglist.json\"] = pkglist_path\n        compress_files(tar_files, tgz_name, os.path.dirname(path), compresslevel, recursive=True)\n        remove(pkglist_path)\n        ConanOutput().success(f\"Created cache save file: {path}\")\n\n    def restore(self, path) -> PackagesList:\n        \"\"\"Restore a compressed archive with recipes and packages previously saved from another\n        Conan cache into the currently active Conan cache.\n\n        :param path: The archive file to restore. Based on the extension of the file, different\n           compression formats can be used (.tgz, .txz and .tzst, the latter only for Python>=3.14).\n        :return: a PackageLists with the recipes and packages that have been restored to the cache\n        \"\"\"\n        if not os.path.isfile(path):\n            raise ConanException(f\"Restore archive doesn't exist in {path}\")\n\n        cache = PkgCache(self._conan_api.cache_folder, self._api_helpers.global_conf)\n        cache_folder = cache.store  # Note, this is not the home, but the actual package cache\n\n        with open(path, mode='rb') as file_handler:\n            the_tar = tarfile.open(fileobj=file_handler)\n            fileobj = the_tar.extractfile(\"pkglist.json\")\n            pkglist = fileobj.read()\n            the_tar.extraction_filter = (lambda member, _: member)  # fully_trusted (Py 3.14)\n            the_tar.extractall(path=cache_folder)\n            the_tar.close()\n\n        # After unzipping the files, we need to update the DB that references these files\n        out = ConanOutput()\n        package_list = PackagesList.deserialize(json.loads(pkglist))\n        for ref, packages in package_list.items():\n            ref_bundle = package_list.recipe_dict(ref)\n            ref.timestamp = revision_timestamp_now()\n            ref_bundle[\"timestamp\"] = ref.timestamp\n            try:\n                recipe_layout = cache.recipe_layout(ref)\n            except ConanException:\n                recipe_layout = cache.create_ref_layout(ref)  # new DB folder entry\n            recipe_folder = ref_bundle[\"recipe_folder\"]\n            rel_path = os.path.relpath(recipe_layout.base_folder, cache_folder)\n            rel_path = rel_path.replace(\"\\\\\", \"/\")\n            # In the case of recipes, they are always \"in place\", so just checking it\n            assert rel_path == recipe_folder, f\"{rel_path}!={recipe_folder}\"\n            out.info(f\"Restore: {ref} in {recipe_folder}\")\n            for pref in packages:\n                pref.timestamp = revision_timestamp_now()\n                pref_bundle = package_list.package_dict(pref)\n                pref_bundle[\"timestamp\"] = pref.timestamp\n                try:\n                    pkg_layout = cache.pkg_layout(pref)\n                except ConanException:\n                    pkg_layout = cache.create_pkg_layout(pref)  # DB Folder entry\n                # FIXME: This is not taking into account the existence of previous package\n                unzipped_pkg_folder = pref_bundle[\"package_folder\"]\n                out.info(f\"Restore: {pref} in {unzipped_pkg_folder}\")\n                # If the DB folder entry is different to the disk unzipped one, we need to move it\n                # This happens for built (not downloaded) packages in the source \"conan cache save\"\n                db_pkg_folder = os.path.relpath(pkg_layout.package(), cache_folder)\n                db_pkg_folder = db_pkg_folder.replace(\"\\\\\", \"/\")\n                if db_pkg_folder != unzipped_pkg_folder:\n                    # If a previous package exists, like a previous restore, then remove it\n                    if os.path.exists(pkg_layout.package()):\n                        shutil.rmtree(pkg_layout.package())\n                    shutil.move(os.path.join(cache_folder, unzipped_pkg_folder),\n                                pkg_layout.package())\n                    pref_bundle[\"package_folder\"] = db_pkg_folder\n                unzipped_metadata_folder = pref_bundle.get(\"metadata_folder\")\n                if unzipped_metadata_folder:\n                    # FIXME: Restore metadata is not incremental, but destructive\n                    out.info(f\"Restore: {pref} metadata in {unzipped_metadata_folder}\")\n                    db_metadata_folder = os.path.relpath(pkg_layout.metadata(), cache_folder)\n                    db_metadata_folder = db_metadata_folder.replace(\"\\\\\", \"/\")\n                    if db_metadata_folder != unzipped_metadata_folder:\n                        # We need to put the package in the final location in the cache\n                        if os.path.exists(pkg_layout.metadata()):\n                            shutil.rmtree(pkg_layout.metadata())\n                        shutil.move(os.path.join(cache_folder, unzipped_metadata_folder),\n                                    pkg_layout.metadata())\n                        pref_bundle[\"metadata_folder\"] = db_metadata_folder\n\n        return package_list\n\n    def get_backup_sources(self, package_list=None, exclude=True, only_upload=True):\n        \"\"\"Get list of backup source files currently present in the cache,\n        either all of them if no argument, or filtered by those belonging to the references\n        in the package_list\n\n        :param package_list: a PackagesList object to filter backup files from (The files should\n          have been downloaded form any of the references in the package_list)\n        :param exclude: if True, exclude the sources that come from URLs present the\n          core.sources:exclude_urls global conf\n        :param only_upload: if True, only return the files for packages that are set to be uploaded\n        :return: A list of files that need to be uploaded\n        \"\"\"\n        config = self._api_helpers.global_conf\n        download_cache_path = config.get(\"core.sources:download_cache\")\n        download_cache_path = download_cache_path or HomePaths(\n            self._conan_api.cache_folder).default_sources_backup_folder\n        excluded_urls = config.get(\"core.sources:exclude_urls\",\n                                   check_type=list, default=[]) if exclude else []\n        download_cache = DownloadCache(download_cache_path)\n        return download_cache.get_backup_sources_files(excluded_urls, package_list, only_upload)\n\n    def path_to_ref(self, path):\n        # This method is explicitly not publicly documented, as mostly a command helper for\n        # debugging, it shouldn't be used in any real API usage\n        cache = PkgCache(self._conan_api.cache_folder, self._api_helpers.global_conf)\n        result = cache.path_to_ref(path)\n        if result is None:\n            base, folder = os.path.split(path)\n            result = cache.path_to_ref(base)\n        return result\n\n\ndef _resolve_latest_ref(cache, ref):\n    if ref.revision is None or ref.revision == \"latest\":\n        ref.revision = None\n        result = cache.get_latest_recipe_revision(ref)\n        if result is None:\n            raise ConanException(f\"'{ref}' not found in cache\")\n        ref = result\n    return ref\n\n\ndef _resolve_latest_pref(cache, pref):\n    pref.ref = _resolve_latest_ref(cache, pref.ref)\n    if pref.revision is None or pref.revision == \"latest\":\n        pref.revision = None\n        result = cache.get_latest_package_revision(pref)\n        if result is None:\n            raise ConanException(f\"'{pref.repr_notime()}' not found in cache\")\n        pref = result\n    return pref\n\n\ndef _check_folder_existence(ref, folder_name, folder_path):\n    if not os.path.exists(folder_path):\n        raise ConanException(f\"'{folder_name}' folder does not exist for the reference {ref}\")\n    return folder_path\n"
  },
  {
    "path": "conan/api/subapi/command.py",
    "content": "import os\nimport shlex\n\nfrom conan.api.output import ConanOutput\nfrom conan.errors import ConanException\n\n\nclass CommandAPI:\n\n    def __init__(self, conan_api):\n        self._conan_api = conan_api\n        self.cli = None\n\n    def run(self, cmd):\n        if isinstance(cmd, str):\n            cmd = shlex.split(cmd)\n        if isinstance(cmd, list):\n            current_cmd = cmd[0]\n            args = cmd[1:]\n        else:\n            raise ConanException(\"Input of conan_api.command.run() should be a list or a string\")\n        commands = getattr(self.cli, \"_commands\")  # to no make it public to users of Cli class\n        try:\n            command = commands[current_cmd]\n        except KeyError:\n            raise ConanException(f\"Command {current_cmd} does not exist\")\n        # Conan has some global state in the ConanOutput class that\n        # get redefined when running a command and leak to the calling scope\n        # if running from a custom command.\n        # Store the old one and restore it after the command execution as a workaround.\n        _conan_output_level = ConanOutput._conan_output_level  # noqa\n        _silent_warn_tags = ConanOutput._silent_warn_tags  # noqa\n        _warnings_as_errors = ConanOutput._warnings_as_errors  # noqa\n\n        try:\n            result = command.run_cli(self._conan_api, args)\n        finally:\n            ConanOutput._conan_output_level = _conan_output_level\n            ConanOutput._silent_warn_tags = _silent_warn_tags\n            ConanOutput._warnings_as_errors = _warnings_as_errors\n        return result\n\n    @staticmethod\n    def get_runner(profile_host):\n        if profile_host.runner and not os.environ.get(\"CONAN_RUNNER_ENVIRONMENT\"):\n            from conan.internal.runner.docker import DockerRunner\n            from conan.internal.runner.ssh import SSHRunner\n            from conan.internal.runner.wsl import WSLRunner\n            try:\n                runner_type = profile_host.runner['type'].lower()\n            except KeyError:\n                raise ConanException(f\"Invalid runner configuration. 'type' must be defined\")\n            runner_instances_map = {\n                'docker': DockerRunner,\n                # 'ssh': SSHRunner,\n                # 'wsl': WSLRunner,\n            }\n            try:\n                runner_instance = runner_instances_map[runner_type]\n            except KeyError:\n                raise ConanException(f\"Invalid runner type '{runner_type}'. \"\n                                     f\"Allowed values: {', '.join(runner_instances_map.keys())}\")\n            return runner_instance\n"
  },
  {
    "path": "conan/api/subapi/config.py",
    "content": "import os\n\nfrom conan.api.output import ConanOutput\n\nfrom conan.internal.cache.home_paths import HomePaths\nfrom conan.internal.conan_app import ConanApp\nfrom conan.internal.graph.graph import CONTEXT_HOST, RECIPE_VIRTUAL, Node\nfrom conan.internal.graph.graph_builder import DepsGraphBuilder\nfrom conan.internal.graph.profile_node_definer import consumer_definer\nfrom conan.errors import ConanException\n\nfrom conan.internal.model.conanconfig import loadconanconfig, saveconanconfig, loadconanconfig_yml\nfrom conan.internal.model.conf import BUILT_IN_CONFS\nfrom conan.internal.model.pkg_type import PackageType\nfrom conan.api.model import RecipeReference, Remote\nfrom conan.internal.util.files import rmdir, remove\n\n\nclass ConfigAPI:\n    \"\"\" This API provides methods to manage the Conan configuration in the Conan home folder.\n    It allows installing configurations from various sources, retrieving global configuration\n    values, and listing available configurations. It also provides methods to clean the\n    Conan home folder, resetting it to a clean state.\n    \"\"\"\n\n    def __init__(self, conan_api, helpers):\n        self._conan_api = conan_api\n        self._helpers = helpers\n\n    def home(self):\n        \"\"\" return the current Conan home folder containing the configuration files like\n        remotes, settings, profiles, and the packages cache. It is provided for debugging\n        purposes. Recall that it is not allowed to write, modify or remove packages in the\n        packages cache, and that to automate tasks that uses packages from the cache Conan\n        provides mechanisms like deployers or custom commands.\n        \"\"\"\n        return self._conan_api.cache_folder\n\n    def install(self, path_or_url: str, verify_ssl, config_type=None, args=None,\n                source_folder=None, target_folder=None) -> None:\n        \"\"\" install Conan configuration from a git repo, from a zip file in an http server\n        or a local folder\n\n        Calling this method will cause a reinitilization of the full ConanAPI, with possible\n        invalidation of cached information, and references to objects from the ConanAPI might\n        become dangling or outdated.\n\n        :param path_or_url: path or url to install. It can be a http://.../somefile.zip, a\n            git repository URL, or a local folder\n        :param verify_ssl: Argument passed to python-requests library for SSL verification\n        :param config_type: type of configuration to install: \"git\", \"dir\", \"file\", \"url\"\n        :param args: additional arguments to pass to git repositories cloning\n        :param source_folder: If specified, install files from that folder of the origin only\n        :param target_folder: If the files are to be installed in a specific folder in the Conan\n            home. For example, if it is desired to install only profiles from a configuration and\n            using source_folder=\"profiles\", it might be expected to use target_folder=\"profiles\"\n            to keep the correct profile files location in the local home.\n        \"\"\"\n        from conan.internal.api.config.config_installer import configuration_install\n        cache_folder = self._conan_api.cache_folder\n        requester = self._helpers.requester\n        configuration_install(cache_folder, requester, path_or_url, verify_ssl,\n                              config_type=config_type, args=args,\n                              source_folder=source_folder, target_folder=target_folder)\n        self._conan_api.reinit()\n\n    def install_package(self, require, lockfile=None, force=False, remotes=None, profile=None):\n        \"\"\" install Conan configuration from a Conan package\n\n        Calling this method will cause a reinitilization of the full ConanAPI, with possible\n        invalidation of cached information, and references to objects from the ConanAPI might\n        become dangling or outdated.\n\n        :param require: The package requirement to be installed. It can contain version range\n            expressions. If the revision is not specified, as a recipe ``requires``, it will\n            also resolve to the latest recipe-revision\n        :param lockfile: Lockfile to be used to constrain and lock the versions and recipe-revisions\n            from the input requirements, to the exact versions and revisions specified in the\n            lockfile\n        :param force: If the package has already been installed, nothing will be done unless\n            force is True\n        :param remotes: Remotes to look for the configuration package\n        :param profile: If specified, use that profile to resolve for profile-specific different\n            configurations, like depending on different settings.\n        :return: list of RecipeReferences of the installed configuration packages\n        \"\"\"\n        ConanOutput().warning(\"The 'conan config install-pkg' is experimental\",\n                              warn_tag=\"experimental\")\n        require = RecipeReference.loads(require)\n        required_pkgs = self.fetch_packages([require], lockfile, remotes, profile)\n        installed_refs = self._install_pkgs(required_pkgs, force)\n        self._conan_api.reinit()\n        return installed_refs\n\n    @staticmethod\n    def load_conanconfig(path, remotes):\n        # Internal, do not document yet.\n        if os.path.isdir(path):\n            path = os.path.join(path, \"conanconfig.yml\")\n        requested_requires, urls = loadconanconfig_yml(path)\n        if urls:\n            new_remotes = [Remote(f\"config_install_url{'_' + str(i)}\", url=url)\n                           for i, url in enumerate(urls)]\n            remotes = remotes or []\n            remotes += new_remotes\n        return requested_requires, remotes\n\n    def install_conanconfig(self, path, lockfile=None, force=False, remotes=None, profile=None):\n        \"\"\" install Conan configuration from a Conan \"conanconfig.yml\" file\n\n        Calling this method will cause a reinitilization of the full ConanAPI, with possible\n        invalidation of cached information, and references to objects from the ConanAPI might\n        become dangling or outdated.\n\n        :param path: Path to the conanconfig.yml file containing the configuration packages\n            requirement definitions\n        :param lockfile: Lockfile to be used to constrain and lock the versions and recipe-revisions\n            from the input requirements, to the exact versions and revisions specified in the\n            lockfile\n        :param force: If the package has already been installed, nothing will be done unless\n            force is True\n        :param remotes: Remotes to look for the configuration package\n        :param profile: If specified, use that profile to resolve for profile-specific different\n            configurations, like depending on different settings.\n        :return: list of RecipeReferences of the installed configuration packages\n        \"\"\"\n        ConanOutput().warning(\"The 'conan config install-pkg' is experimental\",\n                              warn_tag=\"experimental\")\n        requested_requires, remotes = self.load_conanconfig(path, remotes)\n        required_pkgs = self.fetch_packages(requested_requires, lockfile, remotes, profile)\n        installed_refs = self._install_pkgs(required_pkgs, force)\n        self._conan_api.reinit()\n        return installed_refs\n\n    def _install_pkgs(self, required_pkgs, force):\n        out = ConanOutput()\n        out.title(\"Configuration packages to install\")\n        config_version_file = HomePaths(self._conan_api.home_folder).config_version_path\n        if not os.path.exists(config_version_file):\n            config_versions = []\n        else:\n            ConanOutput().info(f\"Reading existing config-versions file: {config_version_file}\")\n            config_versions = loadconanconfig(config_version_file)\n        config_versions_dict = {r.name: r for r in config_versions}\n        if len(config_versions_dict) < len(config_versions):\n            raise ConanException(\"There are multiple requirements for the same package \"\n                                 f\"with different versions: {config_version_file}\")\n\n        new_config = config_versions_dict.copy()\n        for required_pkg in required_pkgs:\n            new_config.pop(required_pkg.ref.name, None)  # To ensure new order\n            new_config[required_pkg.ref.name] = required_pkg.ref\n        final_config_refs = [r for r in new_config.values()]\n\n        prev_refs = \"\\n\\t\".join(repr(r) for r in config_versions)\n        out.info(f\"Previously installed configuration packages:\\n\\t{prev_refs}\")\n\n        new_refs = \"\\n\\t\".join(r.repr_notime() for r in final_config_refs)\n        out.info(f\"New configuration packages to install:\\n\\t{new_refs}\")\n\n        if list(config_versions_dict) == list(new_config)[:len(config_versions_dict)]:\n            # There is no conflict in order, can be done safely\n            if final_config_refs == config_versions:\n                if force:\n                    out.warning(\"The requested configurations are identical to the already \"\n                                \"installed ones, but forcing re-installation because --force\")\n                    to_install = required_pkgs\n                else:\n                    out.info(\"The requested configurations are identical to the already \"\n                             \"installed ones, skipping re-installation\")\n                    to_install = []\n            else:\n                out.info(\"Installing new or updating configuration packages\")\n                to_install = required_pkgs\n        else:\n            # Change in order of existing configuration\n            if force:\n                out.warning(\"Installing these configuration packages will break the \"\n                            \"existing order, with possible side effects. \"\n                            \"Forcing the installation because --force was defined\", warn_tag=\"risk\")\n                to_install = required_pkgs\n            else:\n                msg = (\"Installing these configuration packages will break the \"\n                       \"existing order, with possible side effects, like breaking 'package_ids'.\\n\"\n                       \"If you still want to enforce this configuration you can:\\n\"\n                       \"   Use 'conan config clean' first to fully reset your configuration.\\n\"\n                       \"   Or use 'conan config install-pkg --force' to force installation.\")\n                raise ConanException(msg)\n\n        out.title(\"Installing configuration from packages\")\n        # install things and update the Conan cache \"config_versions.json\" file\n        from conan.internal.api.config.config_installer import configuration_install\n        cache_folder = self._conan_api.cache_folder\n        requester = self._helpers.requester\n        for pkg in to_install:\n            out.info(f\"Installing configuration from {pkg.ref}\")\n            configuration_install(cache_folder, requester, uri=pkg.conanfile.package_folder,\n                                  verify_ssl=False, config_type=\"dir\",\n                                  ignore=[\"conaninfo.txt\", \"conanmanifest.txt\"])\n\n        saveconanconfig(config_version_file, final_config_refs)\n        return final_config_refs\n\n    def fetch_packages(self, requires, lockfile=None, remotes=None, profile=None):\n        \"\"\" get and download configuration packages into the Conan cache, without installing\n        such configuration in the current Conan home.\n\n        This shouldn't be necessary for regular Conan configuration, and used at the moment\n        exclusively for the \"conan lock upgrade-config\" experimental command.\n        \"\"\"\n        conan_api = self._conan_api\n        remotes = conan_api.remotes.list() if remotes is None else remotes\n        profile_host = profile_build = profile or conan_api.profiles.get_profile([])\n\n        app = ConanApp(self._conan_api)\n        cache = self._helpers.cache\n\n        ConanOutput().title(\"Fetching requested configuration packages\")\n        result = []\n        for ref in requires:\n            # Computation of a very simple graph that requires \"ref\"\n            # Need to convert input requires to RecipeReference\n            conanfile = app.loader.load_virtual(requires=[ref])\n            consumer_definer(conanfile, profile_host, profile_build)\n            root_node = Node(ref=None, conanfile=conanfile, context=CONTEXT_HOST,\n                             recipe=RECIPE_VIRTUAL)\n            root_node.is_conf = True\n            update = [\"*\"]\n            builder = DepsGraphBuilder(app.proxy, app.loader, app.range_resolver, cache, remotes,\n                                       update, update, self._helpers.global_conf)\n            deps_graph = builder.load_graph(root_node, profile_host, profile_build, lockfile)\n\n            # Basic checks of the package: correct package_type and no-dependencies\n            deps_graph.report_graph_error()\n            pkg = deps_graph.root.edges[0].dst\n            ConanOutput().info(f\"Configuration from package: {pkg}\")\n            if pkg.conanfile.package_type is not PackageType.CONF:\n                raise ConanException(f'{pkg.conanfile} is not of package_type=\"configuration\"')\n            if pkg.edges:\n                raise ConanException(f\"Configuration package {pkg.ref} cannot have dependencies\")\n\n            # The computation of the \"package_id\" and the download of the package is done as usual\n            # By default we allow all remotes, and build_mode=None, always updating\n            conan_api.graph.analyze_binaries(deps_graph, None, remotes, update=update,\n                                             lockfile=lockfile)\n            conan_api.install.install_binaries(deps_graph=deps_graph, remotes=remotes)\n            result.append(pkg)\n        return result\n\n    def get(self, name, default=None, check_type=None):\n        \"\"\" get the value of a global.conf item\n\n        :param name: configuration value to return\n        :param default: default value to return if the configuration doesn't contain a value\n        :param check_type: check if value is of type check_type, only if the value is defined\n        \"\"\"\n        return self._helpers.global_conf.get(name, default=default, check_type=check_type)\n\n    def show(self, pattern) -> dict:\n        \"\"\" get the values of global.conf for those configurations that matches the pattern\n        that have an actual user definition.\n\n        Values with no user definitions will be skipped from the returned value,\n        defaults for those confs won't be shown.\n\n        :param pattern: pattern to match against\n        :return: dict of configuration values\n        \"\"\"\n        return self._helpers.global_conf.show(pattern)\n\n    @staticmethod\n    def conf_list() -> dict:\n        \"\"\" list all the available built-in configurations\n\n        :return: A sorted dictionary with all possible built-in configurations\n        \"\"\"\n        return BUILT_IN_CONFS.copy()\n\n    def clean(self) -> None:\n        \"\"\" reset the Conan home folder to a clean state, removing all the user\n        custom configuration, custom files, and resetting modified files\n        \"\"\"\n        contents = os.listdir(self.home())\n        packages_folder = (self._helpers.global_conf.get(\"core.cache:storage_path\") or\n                           os.path.join(self.home(), \"p\"))\n        for content in contents:\n            content_path = os.path.join(self.home(), content)\n            if content_path == packages_folder:\n                continue\n            ConanOutput().debug(f\"Removing {content_path}\")\n            if os.path.isdir(content_path):\n                rmdir(content_path)\n            else:\n                remove(content_path)\n        self._conan_api.reinit()\n        # CHECK: This also generates a remotes.json that is not there after a conan profile show?\n        self._conan_api.migrate()\n\n    @property\n    def settings_yml(self):\n        \"\"\" Get the contents of the settings.yml and user_settings.yml files,\n        which define the possible values for settings.\n\n        Note that this is different from the settings present in a conanfile,\n        which represent the actual values for a specific package, while this\n        property represents the possible values for each setting.\n\n        This is intended to be a **read-only** value, do not try to attempt to modify,\n        inject or remove settings with this attribute.\n\n        :returns: A read-only object representing the settings scheme, with a\n            ``possible_values()`` method that returns a dictionary with the possible\n            values for each setting, and a ``fields`` property that returns an ordered\n            list with the fields of each setting.\n            Note that it's possible to access nested settings using attribute access,\n            such as ``settings_yml.compiler.possible_values()``.\n        \"\"\"\n\n        class SettingsYmlInterface:\n            def __init__(self, settings):\n                self._settings = settings\n\n            def possible_values(self):\n                \"\"\" returns a dict with the possible values for each setting \"\"\"\n                return self._settings.possible_values()\n\n            @property\n            def fields(self):\n                \"\"\" returns a dict with the fields of each setting \"\"\"\n                return self._settings.fields\n\n            def __getattr__(self, item):\n                return SettingsYmlInterface(getattr(self._settings, item))\n\n            def __str__(self):\n                return str(self._settings)\n\n        return SettingsYmlInterface(self._helpers.settings_yml)\n"
  },
  {
    "path": "conan/api/subapi/download.py",
    "content": "import time\nfrom multiprocessing.pool import ThreadPool\nfrom typing import Optional, List\n\nfrom conan.api.model import Remote, PackagesList\nfrom conan.api.output import ConanOutput\nfrom conan.errors import ConanException\nfrom conan.api.model import PkgReference\nfrom conan.api.model import RecipeReference\n\n\nclass DownloadAPI:\n    \"\"\" This API is used to download recipes and packages from a remote server.\"\"\"\n\n    def __init__(self, conan_api, api_helpers):\n        self._conan_api = conan_api\n        self._api_helpers = api_helpers\n\n    def recipe(self, ref: RecipeReference, remote: Remote, metadata: Optional[List[str]] = None):\n        \"\"\"Download the recipe specified in the ref from the remote.\n        If the recipe is already in the cache it will be skipped,\n        but the specified metadata will be downloaded.\"\"\"\n        output = ConanOutput()\n        assert ref.revision, f\"Reference '{ref}' must have revision\"\n        try:\n            recipe_layout = self._api_helpers.cache.recipe_layout(ref)  # raises if not found\n        except ConanException:\n            pass\n        else:\n            output.info(f\"Skip recipe {ref.repr_notime()} download, already in cache\")\n            if metadata:\n                self._api_helpers.remote_manager.get_recipe_metadata(recipe_layout, ref, remote,\n                                                                     metadata)\n            return False\n\n        output.info(f\"Downloading recipe '{ref.repr_notime()}'\")\n        if ref.timestamp is None:  # we didnt obtain the timestamp before (in general it should be)\n            # Respect the timestamp of the server, the ``get_recipe()`` doesn't do it internally\n            # Best would be that ``get_recipe()`` returns the timestamp in the same call\n            server_ref = self._api_helpers.remote_manager.get_recipe_revision(ref, remote)\n            assert server_ref == ref\n            ref.timestamp = server_ref.timestamp\n        recipe_layout = self._api_helpers.remote_manager.get_recipe(ref, remote, metadata)\n\n        # Download the sources too, don't be lazy\n        output.info(f\"Downloading '{str(ref)}' sources\")\n        self._api_helpers.remote_manager.get_recipe_sources(ref, recipe_layout, remote)\n        return True\n\n    def package(self, pref: PkgReference, remote: Remote, metadata: Optional[List[str]] = None):\n        \"\"\"Download the package specified in the pref from the remote.\n        The recipe for this package binary must already exist in the cache.\n        If the package is already in the cache it will be skipped,\n        but the specified metadata will be downloaded.\"\"\"\n        output = ConanOutput()\n\n        try:\n            self._api_helpers.cache.recipe_layout(pref.ref)  # raises if not found\n        except ConanException:\n            raise ConanException(\"The recipe of the specified package \"\n                                 \"doesn't exist, download it first\")\n\n        skip_download = self._api_helpers.cache.exists_prev(pref)\n        if skip_download:\n            output.info(f\"Skip package {pref.repr_notime()} download, already in cache\")\n            if metadata:\n                self._api_helpers.remote_manager.get_package_metadata(pref, remote, metadata)\n            return False\n\n        if pref.timestamp is None:  # we didn't obtain the timestamp before (in general it should be)\n            # Respect the timestamp of the server\n            server_pref = self._api_helpers.remote_manager.get_package_revision(pref, remote)\n            assert server_pref == pref\n            pref.timestamp = server_pref.timestamp\n\n        output.info(f\"Downloading package '{pref.repr_notime()}'\")\n        self._api_helpers.remote_manager.get_package(pref, remote, metadata)\n        return True\n\n    def download_full(self, package_list: PackagesList, remote: Remote,\n                      metadata: Optional[List[str]] = None):\n        \"\"\"Download the recipes and packages specified in the ``package_list`` from the remote,\n        parallelized based on ``core.download:parallel``\"\"\"\n        def _download_pkglist(pkglist):\n            for ref, packages in pkglist.items():\n                self.recipe(ref, remote, metadata)\n                ref_dict = pkglist.recipe_dict(ref)\n                ref_dict.pop(\"files\", None)\n                ref_dict.pop(\"upload-urls\", None)\n                for pref in packages:\n                    self.package(pref, remote, metadata)\n                    pkg_dict = pkglist.package_dict(pref)\n                    pkg_dict.pop(\"files\", None)\n                    pkg_dict.pop(\"upload-urls\", None)\n\n        t = time.time()\n        parallel = self._api_helpers.global_conf.get(\"core.download:parallel\", default=1,\n                                                     check_type=int)\n        thread_pool = ThreadPool(parallel) if parallel > 1 else None\n        if not thread_pool or len(package_list._data) <= 1:  # FIXME: Iteration when multiple rrevs\n            _download_pkglist(package_list)\n        else:\n            ConanOutput().subtitle(f\"Downloading with {parallel} parallel threads\")\n            thread_pool.map(_download_pkglist, package_list.split())\n\n        if thread_pool:\n            thread_pool.close()\n            thread_pool.join()\n\n        elapsed = time.time() - t\n        ConanOutput().success(f\"Download completed in {int(elapsed)}s\\n\")\n"
  },
  {
    "path": "conan/api/subapi/export.py",
    "content": "import os\nfrom typing import List, Tuple\n\nfrom conan import ConanFile\nfrom conan.api.output import ConanOutput\nfrom conan.cli.printers.graph import print_graph_basic\nfrom conan.internal.cache.cache import PkgCache\nfrom conan.internal.conan_app import ConanApp\nfrom conan.internal.api.export import cmd_export\nfrom conan.internal.methods import run_package_method\nfrom conan.internal.graph.graph import BINARY_BUILD, RECIPE_INCACHE\nfrom conan.api.model import PkgReference, Remote, RecipeReference\nfrom conan.internal.util.files import mkdir\n\n\nclass ExportAPI:\n    \"\"\" This API provides methods to export artifacts, both recipes and pre-compiled package\n    binaries from user folders to the Conan cache, as Conan recipes and Conan package binaries\n    \"\"\"\n\n    def __init__(self, conan_api, helpers):\n        self._conan_api = conan_api\n        self._helpers = helpers\n\n    def export(self, path, name: str = None, version: str = None, user: str = None,\n               channel: str = None, lockfile=None,\n               remotes: List[Remote] = None) -> Tuple[RecipeReference, ConanFile]:\n        \"\"\" Exports a ``conanfile.py`` recipe, together with its associated files to the Conan cache.\n        A \"recipe-revision\" will be computed and assigned.\n\n        :param path: Path to the conanfile to be exported\n        :param name: Optional package name. Typically not necessary as it is defined by the recipe\n            attribute or dynamically with the ``set_name()`` method.\n            If it is defined in recipe and as an argument, but they don't match, an error will be raised.\n        :param version: Optional version. It can be defined in the recipe with the version\n            attribute or dynamically with the 'set_version()' method.\n            If it is defined in recipe and as an argument, but they don't match, an error will be raised.\n        :param user: Optional user. Can be defined by recipe attribute.\n            If it is defined in recipe and as an argument, but they don't match, an error will be raised.\n        :param channel: Optional channel. Can be defined by recipe attribute.\n            If it is defined in recipe and as an argument, but they don't match, an error will be raised.\n        :param lockfile: Optional, only relevant if the recipe has 'python-requires' to be locked\n        :param remotes: Optional, only relevant to resolve 'python-requires' in remotes\n        :return: A tuple of the exported RecipeReference and a ConanFile object\n        \"\"\"\n        ConanOutput().title(\"Exporting recipe to the cache\")\n        app = ConanApp(self._conan_api)\n        hook_manager = self._helpers.hook_manager\n        return cmd_export(app.loader,self._helpers.cache, hook_manager, self._helpers.global_conf, path,\n                          name, version, user, channel, graph_lock=lockfile, remotes=remotes)\n\n    def export_pkg_graph(self, path, ref: RecipeReference, profile_host, profile_build,\n                         remotes: List[Remote], lockfile=None, is_build_require=False,\n                         skip_binaries=False, output_folder=None):\n        \"\"\"Computes a dependency graph for a given configuration, for an already existing (previously\n        exported) recipe in the Conan cache. This method computes the full dependency graph, using\n        the profiles, lockfile and remotes information as any other install/graph/create command.\n        This is necessary in order to compute the \"package_id\" of the binary being exported\n        into the Conan cache.\n        The resulting dependency graph can be passed to ``export_pkg()`` method\n\n        :param path: Path to the conanfile.py in the user folder\n        :param ref: full RecipeReference, including recipe-revision\n        :param profile_host: Profile for the host context\n        :param profile_build: Profile for the build context\n        :param lockfile: Optional lockfile\n        :param remotes: List of Remotes\n        :param is_build_require: In case a package intended to be used as a tool-requires\n        :param skip_binaries:\n        :param output_folder: The folder containing output files, like potential environment scripts\n        :return: A Graph object that can be passed to ``export_pkg()`` method\n        \"\"\"\n        assert ref.revision, \"ref argument must have recipe-revision defined\"\n        conan_api = self._conan_api\n        deps_graph = conan_api.graph.load_graph_consumer(path,\n                                                         ref.name, str(ref.version), ref.user,\n                                                         ref.channel,\n                                                         profile_host=profile_host,\n                                                         profile_build=profile_build,\n                                                         lockfile=lockfile, remotes=remotes,\n                                                         update=None,\n                                                         is_build_require=is_build_require)\n\n        print_graph_basic(deps_graph)\n        deps_graph.report_graph_error()\n        conan_api.graph.analyze_binaries(deps_graph, build_mode=[ref.name], lockfile=lockfile,\n                                         remotes=remotes)\n        deps_graph.report_graph_error()\n\n        root_node = deps_graph.root\n        root_node.ref = ref  # Make sure the root node revision is well defined\n\n        if not skip_binaries:\n            # unless the user explicitly opts-out with --skip-binaries, it is necessary to install\n            # binaries, in case there are build_requires necessary like tool-requires=cmake\n            # and package() method doing ``cmake.install()``\n            # for most cases, deps will be in cache already because of a previous \"conan install\"\n            # but if it is not the case, the binaries from remotes will be downloaded\n            conan_api.install.install_binaries(deps_graph=deps_graph, remotes=remotes)\n        source_folder = os.path.dirname(path)\n        conan_api.install.install_consumer(deps_graph=deps_graph, source_folder=source_folder,\n                                           output_folder=output_folder)\n        return deps_graph\n\n    def export_pkg(self, graph, output_folder=None) -> None:\n        \"\"\"Executes the ``package()`` method of the exported recipe in order to copy the artifacts\n        from user folder to the Conan cache package folder\n\n        :param graph: A Graph object\n        :param output_folder: Optional folder where generated files like environment scripts\n            of dependencies have been installed\n        \"\"\"\n        cache = PkgCache(self._conan_api.cache_folder, self._helpers.global_conf)\n        hook_manager = self._helpers.hook_manager\n\n        # The graph has to be loaded with build_mode=[ref.name], so that node is not tried\n        # to be downloaded from remotes\n        # passing here the create_reference=ref argument is useful so the recipe is in \"develop\",\n        # because the \"package()\" method is in develop=True already\n        pkg_node = graph.root\n        ref = pkg_node.ref\n        source_folder = os.path.dirname(pkg_node.path)\n        out = ConanOutput(scope=pkg_node.conanfile.display_name)\n        out.info(\"Exporting binary from user folder to Conan cache\")\n        conanfile = pkg_node.conanfile\n\n        package_id = pkg_node.package_id\n        assert package_id is not None\n        out.info(\"Packaging to %s\" % package_id)\n        pref = PkgReference(ref, package_id)\n        pkg_layout = cache.create_build_pkg_layout(pref)\n\n        conanfile.folders.set_base_folders(source_folder, output_folder)\n        dest_package_folder = pkg_layout.package()\n        conanfile.folders.set_base_package(dest_package_folder)\n        mkdir(pkg_layout.metadata())\n        conanfile.folders.set_base_pkg_metadata(pkg_layout.metadata())\n\n        with pkg_layout.set_dirty_context_manager():\n            prev = run_package_method(conanfile, package_id, hook_manager, ref)\n\n        pref = PkgReference(pref.ref, pref.package_id, prev)\n        pkg_layout.reference = pref\n        cache.assign_prev(pkg_layout)\n        pkg_node.prev = prev\n        pkg_node.pref_timestamp = pref.timestamp  # assigned by assign_prev\n        pkg_node.recipe = RECIPE_INCACHE\n        pkg_node.binary = BINARY_BUILD\n        # Make sure folder is updated\n        final_folder = pkg_layout.package()\n        conanfile.folders.set_base_package(final_folder)\n        out.info(f\"Package folder {final_folder}\")\n        out.success(\"Exported package binary\")\n"
  },
  {
    "path": "conan/api/subapi/graph.py",
    "content": "from conan.api.output import ConanOutput\nfrom conan.internal.conan_app import ConanApp\nfrom conan.internal.model.recipe_ref import ref_matches\nfrom conan.internal.graph.graph import Node, RECIPE_CONSUMER, CONTEXT_HOST, RECIPE_VIRTUAL, \\\n    CONTEXT_BUILD, BINARY_MISSING, DepsGraph\nfrom conan.internal.graph.graph_binaries import GraphBinariesAnalyzer\nfrom conan.internal.graph.graph_builder import DepsGraphBuilder\nfrom conan.internal.graph.install_graph import InstallGraph, ProfileArgs\nfrom conan.internal.graph.profile_node_definer import initialize_conanfile_profile, consumer_definer\nfrom conan.errors import ConanException\nfrom conan.api.model import RecipeReference\n\n\nclass GraphAPI:\n\n    def __init__(self, conan_api, helpers):\n        self._conan_api = conan_api\n        self._helpers = helpers\n\n    def _load_root_consumer_conanfile(self, path, profile_host, profile_build,\n                                      name=None, version=None, user=None, channel=None,\n                                      update=None, remotes=None, lockfile=None,\n                                      is_build_require=False):\n        app = ConanApp(self._conan_api)\n\n        if path.endswith(\".py\"):\n            conanfile = app.loader.load_consumer(path,\n                                                 name=name,\n                                                 version=version,\n                                                 user=user,\n                                                 channel=channel,\n                                                 graph_lock=lockfile,\n                                                 remotes=remotes,\n                                                 update=update)\n            ref = RecipeReference(conanfile.name, conanfile.version,\n                                  conanfile.user, conanfile.channel)\n            context = CONTEXT_BUILD if is_build_require else CONTEXT_HOST\n            # Here, it is always the \"host\" context because it is the base, not the current node one\n            initialize_conanfile_profile(conanfile, profile_build, profile_host, CONTEXT_HOST,\n                                         is_build_require, ref)\n            if ref.name:\n                profile_host.options.scope(ref)\n            root_node = Node(ref, conanfile, context=context, recipe=RECIPE_CONSUMER, path=path)\n            root_node.should_build = True  # It is a consumer, this is something we are building\n        else:\n            conanfile = app.loader.load_conanfile_txt(path)\n            consumer_definer(conanfile, profile_host, profile_build)\n            root_node = Node(None, conanfile, context=CONTEXT_HOST, recipe=RECIPE_CONSUMER,\n                             path=path)\n        return root_node\n\n    def load_root_test_conanfile(self, path, tested_reference, profile_host, profile_build,\n                                 update=None, remotes=None, lockfile=None,\n                                 tested_python_requires=None):\n        \"\"\" Create and initialize a root node from a test_package/conanfile.py consumer\n\n        :param tested_python_requires: the reference of the ``python_require`` to be tested\n        :param lockfile: Might be good to lock python-requires, build-requires\n        :param path: The full path to the test_package/conanfile.py being used\n        :param tested_reference: The full RecipeReference of the tested package\n        :param profile_host:\n        :param profile_build:\n        :param update:\n        :param remotes:\n        :return: a graph Node, recipe=RECIPE_CONSUMER\n        \"\"\"\n\n        app = ConanApp(self._conan_api)\n        # necessary for correct resolution and update of remote python_requires\n\n        loader = app.loader\n        profile_host.options.scope(tested_reference)\n\n        # do not try apply lock_python_requires for test_package/conanfile.py consumer\n        conanfile = loader.load_consumer(path, user=tested_reference.user,\n                                         channel=tested_reference.channel,\n                                         graph_lock=lockfile, remotes=remotes,\n                                         tested_python_requires=tested_python_requires,\n                                         update=update)\n        initialize_conanfile_profile(conanfile, profile_build, profile_host, CONTEXT_HOST, False)\n        conanfile.display_name = \"%s (test package)\" % str(tested_reference)\n        conanfile.output.scope = conanfile.display_name\n        conanfile.tested_reference_str = repr(tested_reference)\n\n        ref = RecipeReference(conanfile.name, conanfile.version, tested_reference.user,\n                              tested_reference.channel)\n        root_node = Node(ref, conanfile, recipe=RECIPE_CONSUMER, context=CONTEXT_HOST, path=path)\n        return root_node\n\n    def _load_root_virtual_conanfile(self, profile_host, profile_build, requires, tool_requires,\n                                     lockfile, remotes, update, check_updates=False,\n                                     python_requires=None):\n        if not python_requires and not requires and not tool_requires:\n            raise ConanException(\"Provide requires or tool_requires\")\n        app = ConanApp(self._conan_api)\n        conanfile = app.loader.load_virtual(requires=requires,\n                                            tool_requires=tool_requires,\n                                            python_requires=python_requires,\n                                            graph_lock=lockfile, remotes=remotes,\n                                            update=update, check_updates=check_updates)\n\n        consumer_definer(conanfile, profile_host, profile_build)\n        root_node = Node(ref=None, conanfile=conanfile, context=CONTEXT_HOST, recipe=RECIPE_VIRTUAL)\n        return root_node\n\n    @staticmethod\n    def _scope_options(profile, requires, tool_requires):\n        \"\"\"\n        Command line helper to scope options when ``command -o myoption=myvalue`` is used,\n        that needs to be converted to \"-o pkg:myoption=myvalue\". The \"pkg\" value will be\n        computed from the given requires/tool_requires\n\n        This is legacy, as options should always be scoped now\n        \"\"\"\n        if requires and len(requires) == 1 and not tool_requires:\n            ref = requires[0]\n            if str(ref.version).startswith(\"[\"):\n                ref = ref.copy()\n                ref.version = \"*\"\n            profile.options.scope(ref)\n\n    def load_graph_requires(self, requires, tool_requires, profile_host, profile_build,\n                            lockfile, remotes, update, check_updates=False, python_requires=None):\n        requires = [RecipeReference.loads(r) if isinstance(r, str) else r for r in requires] \\\n            if requires else None\n        tool_requires = [RecipeReference.loads(r) if isinstance(r, str) else r\n                         for r in tool_requires] if tool_requires else None\n\n        self._scope_options(profile_host, requires=requires, tool_requires=tool_requires)\n        root_node = self._load_root_virtual_conanfile(requires=requires, tool_requires=tool_requires,\n                                                      profile_host=profile_host,\n                                                      profile_build=profile_build,\n                                                      lockfile=lockfile, remotes=remotes,\n                                                      update=update,\n                                                      python_requires=python_requires)\n\n        if not requires and not tool_requires and python_requires is not None:\n            # This only happens at `conan create` for python-requires, the graph is not needed\n            # in fact, it can cause errors, if tool-requires injected\n            dep_graph = DepsGraph()\n            dep_graph.add_node(root_node)\n            return dep_graph\n        # check_updates = args.check_updates if \"check_updates\" in args else False\n        deps_graph = self.load_graph(root_node, profile_host=profile_host,\n                                     profile_build=profile_build,\n                                     lockfile=lockfile,\n                                     remotes=remotes,\n                                     update=update,\n                                     check_update=check_updates)\n        return deps_graph\n\n    def load_graph_consumer(self, path, name, version, user, channel,\n                            profile_host, profile_build, lockfile, remotes, update,\n                            check_updates=False, is_build_require=False):\n        root_node = self._load_root_consumer_conanfile(path, profile_host, profile_build,\n                                                       name=name, version=version, user=user,\n                                                       channel=channel, lockfile=lockfile,\n                                                       remotes=remotes, update=update,\n                                                       is_build_require=is_build_require)\n\n        deps_graph = self.load_graph(root_node, profile_host=profile_host,\n                                     profile_build=profile_build, lockfile=lockfile,\n                                     remotes=remotes, update=update, check_update=check_updates)\n        return deps_graph\n\n    def load_graph(self, root_node, profile_host, profile_build, lockfile=None, remotes=None,\n                   update=None, check_update=False):\n        \"\"\" Compute the dependency graph, starting from a root package, evaluation the graph with\n        the provided configuration in profile_build, and profile_host. The resulting graph is a\n        graph of recipes, but packages are not computed yet (package_ids) will be empty in the\n        result. The result might have errors, like version or configuration conflicts, but it is\n        still possible to inspect it. Only trying to install such graph will fail\n\n        :param root_node: the starting point, an already initialized Node structure, as\n            returned by the \"load_root_node\" api\n        :param profile_host: The host profile\n        :param profile_build: The build profile\n        :param lockfile: A valid lockfile (None by default, means no locked)\n        :param remotes: list of remotes we want to check\n        :param update: (False by default), if Conan should look for newer versions or\n            revisions for already existing recipes in the Conan cache\n        :param check_update: For \"graph info\" command, check if there are recipe updates\n        \"\"\"\n        ConanOutput().title(\"Computing dependency graph\")\n        app = ConanApp(self._conan_api)\n\n        assert profile_host is not None\n        assert profile_build is not None\n\n        remotes = remotes or []\n        cache = self._conan_api._api_helpers.cache # noqa\n        builder = DepsGraphBuilder(app.proxy, app.loader, app.range_resolver, cache, remotes,\n                                   update, check_update, self._conan_api._api_helpers.global_conf)\n        deps_graph = builder.load_graph(root_node, profile_host, profile_build, lockfile)\n        return deps_graph\n\n    def analyze_binaries(self, graph, build_mode=None, remotes=None, update=None,\n                         lockfile=None, build_modes_test=None, tested_graph=None):\n        \"\"\" Given a dependency graph, will compute the package_ids of all recipes in the graph, and\n        evaluate if they should be built from sources, downloaded from a remote server, of if the\n        packages are already in the local Conan cache\n\n        :param lockfile:\n        :param graph: a Conan dependency graph, as returned by \"load_graph()\"\n        :param build_mode: TODO: Discuss if this should be a BuildMode object or list of arguments\n        :param remotes: list of remotes\n        :param update: (``False`` by default), if Conan should look for newer versions or\n            revisions for already existing recipes in the Conan cache. It also accepts an array of\n            reference patterns to limit the update to those references if any of the items match.\n            Eg. ``False``, ``None`` or ``[]`` *means no update*,\n            ``True`` or ``[\"*\"]`` *means update all*,\n            and ``[\"pkgA/*\", \"pkgB/1.0@user/channel\"]`` *means to update only specific packages*.\n        :param build_modes_test: the --build-test argument\n        :param tested_graph: In case of a \"test_package\", the graph being tested\n        \"\"\"\n        ConanOutput().title(\"Computing necessary packages\")\n        binaries_analyzer = GraphBinariesAnalyzer(self._helpers.cache,\n                                                  self._helpers.remote_manager,\n                                                  self._conan_api.home_folder,\n                                                  self._helpers.global_conf,\n                                                  self._helpers.hook_manager)\n        binaries_analyzer.evaluate_graph(graph, build_mode, lockfile, remotes, update,\n                                         build_modes_test, tested_graph)\n\n    @staticmethod\n    def find_first_missing_binary(graph, missing=None):\n        \"\"\" (Experimental) Given a dependency graph, will return the first node with a\n        missing binary package\n        \"\"\"\n        for node in graph.ordered_iterate():\n            if ((not missing and node.binary == BINARY_MISSING)  # First missing binary or specified\n                    or (missing and ref_matches(node.ref, missing, is_consumer=None))):\n                return node.ref, node.conanfile.info\n        raise ConanException(\"There is no missing binary\")\n\n    @staticmethod\n    def build_order(deps_graph, order_by=\"recipe\", reduce=False, profile_args=None):\n        install_graph = InstallGraph(deps_graph, order_by=order_by,\n                                     profile_args=ProfileArgs.from_args(profile_args))\n        if reduce:\n            if order_by is None:\n                raise ConanException(\"--reduce needs --order-by argument defined\")\n            install_graph.reduce()\n        return install_graph\n\n    @staticmethod\n    def build_order_merge(files, reduce=False):\n        result = InstallGraph.load(files[0])\n        if result.reduced:\n            raise ConanException(f\"Reduced build-order file cannot be merged: {files[0]}\")\n        for f in files[1:]:\n            install_graph = InstallGraph.load(f)\n            if install_graph.reduced:\n                raise ConanException(f\"Reduced build-order file cannot be merged: {f}\")\n            result.merge(install_graph)\n        if reduce:\n            result.reduce()\n        return result\n"
  },
  {
    "path": "conan/api/subapi/install.py",
    "content": "import os\nfrom typing import List\n\nfrom conan.api.model import Remote\nfrom conan.internal.api.install.generators import write_generators\nfrom conan.internal.conan_app import ConanBasicApp\nfrom conan.internal.deploy import do_deploys\n\nfrom conan.internal.graph.install_graph import InstallGraph\nfrom conan.internal.graph.installer import BinaryInstaller\nfrom conan.errors import ConanInvalidConfiguration, ConanException\n\n\nclass InstallAPI:\n    \"\"\" This is the InstallAPI.\n\n    It provides methods to install binaries, sources,\n    prepare the consumer folder with generators and deploy, etc., all of them\n    based on an already resolved dependency graph.\n    \"\"\"\n\n    def __init__(self, conan_api, helpers):\n        self._conan_api = conan_api\n        self._helpers = helpers\n\n    def install_binaries(self, deps_graph, remotes: List[Remote] = None, return_install_error=False):\n        \"\"\" Install binaries of a dependency graph.\n\n        This is the equivalent to the ``conan install`` command, but working with an already\n        resolved dependency graph, usually obtained from the corresponding ``GraphAPI`` methods.\n\n        It will download the available packages from the given remotes,\n        and then build the ones that were marked for build from source.\n\n        System requirements will be installed as well, taking into account the\n        ``tools.system.package_manager:mode`` conf to determine whether to install, check or skip them.\n\n        :param deps_graph: Dependency graph to install packages for\n        :param remotes: List of remotes to fetch packages from if necessary.\n        :param return_install_error: If ``True``, do not raise an exception, but return it\n        \"\"\"\n        app = ConanBasicApp(self._conan_api)\n        installer = BinaryInstaller(self._conan_api, self._helpers.global_conf, app.editable_packages,\n                                    self._helpers.hook_manager)\n        install_graph = InstallGraph(deps_graph)\n        install_graph.raise_errors()\n        install_order = install_graph.install_order()\n        installer.install_system_requires(deps_graph, install_order=install_order)\n        try:  # To be able to capture the output, report or save graph.json, then raise later\n            installer.install(deps_graph, remotes, install_order=install_order)\n        except ConanException as e:\n            # If true, allows to return the exception, so progress can be reported like the\n            # already built binaries to upload them\n            if not return_install_error:\n                raise\n            return e\n\n    def install_system_requires(self, graph, only_info=False):\n        \"\"\" Install only the system requirements of a dependency graph.\n\n        This is a subset of ``install_binaries`` which only deals with system requirements\n        of an already resolved dependency graph,\n        usually obtained from the corresponding ``GraphAPI`` methods.\n\n        The ``tools.system.package_manager:mode`` conf will be taken into account to\n        determine whether to install, check or skip system requirements.\n\n        :param graph: Dependency graph to install system requirements for\n        :param only_info: If ``True``, only reporting and checking of whether the system requirements are installed is performed.\n        \"\"\"\n        app = ConanBasicApp(self._conan_api)\n        installer = BinaryInstaller(self._conan_api, self._helpers.global_conf, app.editable_packages,\n                                    self._helpers.hook_manager)\n        installer.install_system_requires(graph, only_info)\n\n    def install_sources(self, graph, remotes: List[Remote]):\n        \"\"\" Download sources in the given dependency graph.\n\n        If the ``tools.build:download_source`` conf is ``True``, sources will be downloaded for\n        every package in the graph, otherwise only the packages marked for build from source will\n        have their sources downloaded.\n\n        ``tools.build:download_source=True`` is useful when users want to inspect the source code\n        of all dependencies, even the ones that are not built from source.\n\n        After this method, the ``conanfile.source_folder`` on each node of the dependency graph\n        for which the sources have been downloaded will be set to the folder where sources have been downloaded.\n\n        :param remotes: List of remotes where the ``exports_sources`` of the packages might be located\n        :param graph: Dependency graph to download sources from\n        \"\"\"\n        app = ConanBasicApp(self._conan_api)\n        installer = BinaryInstaller(self._conan_api, self._helpers.global_conf, app.editable_packages,\n                                    self._helpers.hook_manager)\n        installer.install_sources(graph, remotes)\n\n    def install_consumer(self, deps_graph, generators: List[str] = None, source_folder=None,\n                         output_folder=None, deploy=False, deploy_package: List[str] = None,\n                         deploy_folder=None, envs_generation=None):\n        \"\"\" Prepare the folder of the root consumer of a dependency graph after installation\n        of the dependencies.\n\n        This ensures that the requested generators are created in the consumer folder,\n        and also handles deployment if requested.\n\n        :param deps_graph: Dependency graph whose root is the consumer we want to prepare\n        :param generators: List of generators to be used in addition to the ones defined in the root conanfile, if any\n        :param source_folder: Source folder of the consumer\n        :param output_folder: Output folder of the consumer\n        :param deploy: Deployer or list of deployers to be used for deployment\n        :param deploy_package: Only deploy the packages matching these patterns (``None`` or empty for all)\n        :param deploy_folder: Folder where to deploy, by default the build folder\n        :param envs_generation: Anything other than ``None`` will activate the generation of virtual environment files for the root conanfile\n        \"\"\"\n        root_node = deps_graph.root\n        conanfile = root_node.conanfile\n\n        if conanfile.info is not None and conanfile.info.invalid:\n            binary, reason = \"Invalid\", conanfile.info.invalid\n            msg = \"{}: Invalid ID: {}: {}\".format(conanfile, binary, reason)\n            raise ConanInvalidConfiguration(msg)\n\n        if conanfile.info is not None and conanfile.info.cant_build and root_node.should_build:\n            binary, reason = \"Cannot build for this configuration\", conanfile.info.cant_build\n            msg = \"{}: {}: {}\".format(conanfile, binary, reason)\n            raise ConanInvalidConfiguration(msg)\n\n        conanfile.folders.set_base_folders(source_folder, output_folder)\n\n        # The previous .set_base_folders has already decided between the source_folder and output\n        if deploy or deploy_package:\n            # Issue related: https://github.com/conan-io/conan/issues/16543\n            base_folder = os.path.abspath(deploy_folder) if deploy_folder \\\n                else conanfile.folders.base_build\n            do_deploys(self._conan_api.home_folder, deps_graph, deploy, deploy_package, base_folder)\n\n        final_generators = []\n        # Don't use set for uniqueness because order matters\n        for gen in conanfile.generators:\n            if gen not in final_generators:\n                final_generators.append(gen)\n        for gen in (generators or []):\n            if gen not in final_generators:\n                final_generators.append(gen)\n        conanfile.generators = final_generators\n        hook_manager = self._helpers.hook_manager\n        write_generators(conanfile, hook_manager, self._conan_api.home_folder,\n                         envs_generation=envs_generation)\n\n    def deploy(self, graph, deployer: List[str], deploy_package: List[str]=None,\n               deploy_folder=None) -> None:\n        \"\"\" Run the given deployer in the dependency graph.\n\n        No checks are performed in the graph, it is assumed to be already resolved\n        and in a valid state to be deployed from.\n\n        :param graph: The dependency graph to deploy\n        :param deployer: List of deployers to be used\n        :param deploy_package: Only deploy the packages matching these patterns (``None`` or empty for all)\n        :param deploy_folder: Folder where to deploy, by default the build folder\n        \"\"\"\n        return do_deploys(self._conan_api.home_folder, graph, deployer,\n                          deploy_package=deploy_package, deploy_folder=deploy_folder)\n"
  },
  {
    "path": "conan/api/subapi/list.py",
    "content": "import os\nfrom collections import OrderedDict\nfrom typing import Dict\n\nfrom conan.api.model import PackagesList, MultiPackagesList, ListPattern, Remote\nfrom conan.api.output import ConanOutput, TimedOutput\nfrom conan.internal.api.list.query_parse import filter_package_configs\nfrom conan.internal.model.recipe_ref import ref_matches\nfrom conan.internal.paths import CONANINFO\nfrom conan.internal.errors import NotFoundException\nfrom conan.errors import ConanException\nfrom conan.internal.model.info import load_binary_info\nfrom conan.api.model import PkgReference\nfrom conan.api.model import RecipeReference\nfrom conan.internal.util.dates import timestamp_now\nfrom conan.internal.util.files import load\n\n\ndef _timelimit(expression):\n    \"\"\" convert an expression like \"2d\" (2 days) or \"3h\" (3 hours) to a timestamp in the past\n    with respect to current time\n    \"\"\"\n    time_value = expression[:-1]\n    try:\n        time_value = int(time_value)\n    except TypeError:\n        raise ConanException(f\"Time value '{time_value}' must be an integer\")\n    time_units = expression[-1]\n    units = {\"y\": 365 * 24 * 60 * 60,\n             \"M\": 30 * 24 * 60 * 60,\n             \"w\": 7 * 24 * 60 * 60,\n             \"d\": 24 * 60 * 60,\n             \"h\": 60 * 60,\n             \"m\": 60,\n             \"s\": 1}\n    try:\n        lru_value = time_value * units[time_units]\n    except KeyError:\n        raise ConanException(f\"Unrecognized time unit: '{time_units}'. Use: {list(units)}\")\n\n    limit = timestamp_now() - lru_value\n    return limit\n\n\nclass ListAPI:\n    \"\"\" Get references from the recipes and packages in the cache or a remote\n    \"\"\"\n\n    def __init__(self, conan_api, api_helpers):\n        self._conan_api = conan_api\n        self._api_helpers = api_helpers\n\n    def latest_recipe_revision(self, ref: RecipeReference, remote: Remote = None):\n        \"\"\" For a given recipe reference, return the latest revision of the recipe in the remote,\n        or in the local cache if no remote is specified, or ``None`` if the recipe does not exist.\"\"\"\n        assert ref.revision is None, \"latest_recipe_revision: ref already have a revision\"\n        if remote:\n            ret = self._api_helpers.remote_manager.get_latest_recipe_revision(ref, remote=remote)\n        else:\n            ret = self._api_helpers.cache.get_latest_recipe_revision(ref)\n\n        return ret\n\n    def recipe_revisions(self, ref: RecipeReference, remote: Remote = None):\n        \"\"\" For a given recipe reference, return all the revisions of the recipe in the remote,\n        or in the local cache if no remote is specified\"\"\"\n        assert ref.revision is None, \"recipe_revisions: ref already have a revision\"\n        if remote:\n            results = self._api_helpers.remote_manager.get_recipe_revisions(ref, remote=remote)\n        else:\n            results = self._api_helpers.cache.get_recipe_revisions(ref)\n\n        return results\n\n    def latest_package_revision(self, pref: PkgReference, remote=None):\n        # TODO: This returns None if the given package_id is not existing. It should probably\n        #  raise NotFound, but to keep aligned with the above ``latest_recipe_revision`` which\n        #  is used as an \"exists\" check too in other places, lets respect the None return\n        assert pref.revision is None, \"latest_package_revision: ref already have a revision\"\n        assert pref.package_id is not None, \"package_id must be defined\"\n        if remote:\n            ret = self._api_helpers.remote_manager.get_latest_package_revision(pref, remote=remote)\n        else:\n            ret = self._api_helpers.cache.get_latest_package_revision(pref)\n        return ret\n\n    def package_revisions(self, pref: PkgReference, remote=None):\n        assert pref.ref.revision is not None, \"package_revisions requires a recipe revision, \" \\\n                                              \"check latest first if needed\"\n        if remote:\n            results = self._api_helpers.remote_manager.get_package_revisions(pref, remote=remote)\n        else:\n            results = self._api_helpers.cache.get_package_revisions(pref)\n        return results\n\n    def _packages_configurations(self, ref: RecipeReference,\n                                 remote=None) -> Dict[PkgReference, dict]:\n        assert ref.revision is not None and ref.revision != \"latest\", \\\n            \"packages: ref should have a revision. Check latest if needed.\"\n        if not remote:\n            prefs = self._api_helpers.cache.get_package_references(ref)\n            packages = _get_cache_packages_binary_info(self._api_helpers.cache, prefs)\n        else:\n            packages = self._api_helpers.remote_manager.search_packages(remote, ref)\n        return packages\n\n    @staticmethod\n    def _filter_packages_configurations(pkg_configurations, query):\n        \"\"\"\n        :param pkg_configurations: Dict[PkgReference, PkgConfiguration]\n        :param query: str like \"os=Windows AND (arch=x86 OR compiler=gcc)\"\n        :return: Dict[PkgReference, PkgConfiguration]\n        \"\"\"\n        try:\n            if \"!\" in query:\n                raise ConanException(\"'!' character is not allowed\")\n            if \"~\" in query:\n                raise ConanException(\"'~' character is not allowed\")\n            if \" not \" in query or query.startswith(\"not \"):\n                raise ConanException(\"'not' operator is not allowed\")\n            return filter_package_configs(pkg_configurations, query)\n        except Exception as exc:\n            raise ConanException(\"Invalid package query: %s. %s\" % (query, exc))\n\n    @staticmethod\n    def _filter_packages_profile(packages, profile, ref):\n        result = {}\n        profile_settings = profile.processed_settings.serialize()\n        # Options are those for dependencies, like *:shared=True\n        profile_options = profile.options._deps_package_options\n        for pref, data in packages.items():\n            settings = data.get(\"settings\", {})\n            settings_match = options_match = True\n            for k, v in settings.items():  # Only the defined settings that don't match\n                value = profile_settings.get(k)\n                if value is not None and value != v:\n                    settings_match = False\n                    break\n            options = data.get(\"options\", {})\n            for k, v in options.items():\n                for pattern, pattern_options in profile_options.items():\n                    # Accept &: as referring to the current package being listed,\n                    # even if it's not technically a \"consumer\"\n                    if ref_matches(ref, pattern, True):\n                        value = pattern_options.get_safe(k)\n                        if value is not None and value != v:\n                            options_match = False\n                            break\n\n            if settings_match and options_match:\n                result[pref] = data\n\n        return result\n\n    def select(self, pattern: ListPattern, package_query=None, remote: Remote = None, lru=None,\n               profile=None) -> PackagesList:\n        \"\"\"For a given pattern, return a list of recipes and packages matching the provided filters.\n\n        :parameter ListPattern pattern: Search criteria\n        :parameter str package_query: When returning packages, expression of the form\n            ``\"os=Windows AND (arch=x86 OR compiler=gcc)\"`` to filter packages by.\n            If ``None``, all packages will be returned if requested.\n        :parameter Remote remote: Remote to search in,\n            if ``None``, it will search in the local cache.\n        :parameter str lru: If set, it will filter the results to only include\n            packages/binaries that have been used in the last 'lru' time.\n            It can be a string like ``\"2d\"`` (2 days) or ``\"3h\"`` (3 hours).\n        :parameter Profile profile: Profile to filter the packages by settings and options.\n        \"\"\"\n        # TODO: Implement better error forwarding for \"list\" command that captures Exceptions\n        if package_query and pattern.package_id and \"*\" not in pattern.package_id:\n            raise ConanException(\"Cannot specify '-p' package queries, \"\n                                 \"if 'package_id' is not a pattern\")\n        if remote and lru:\n            raise ConanException(\"'--lru' cannot be used in remotes, only in cache\")\n\n        select_bundle = PackagesList()\n        # Avoid doing a ``search`` of recipes if it is an exact ref and it will be used later\n        search_ref = pattern.search_ref\n        cache = self._api_helpers.cache\n        limit_time = _timelimit(lru) if lru else None\n        out = ConanOutput()\n        remote_name = \"local cache\" if not remote else remote.name\n        if search_ref:\n            refs = _search_recipes(self._api_helpers, search_ref, remote=remote)\n            global_conf = self._api_helpers.global_conf  # noqa\n            resolve_prereleases = global_conf.get(\"core.version_ranges:resolve_prereleases\")\n            refs = pattern.filter_versions(refs, resolve_prereleases)\n            pattern.check_refs(refs)\n            out.info(f\"Found {len(refs)} pkg/version recipes matching {search_ref} in {remote_name}\")\n        else:\n            refs = [RecipeReference(pattern.name, pattern.version, pattern.user, pattern.channel)]\n\n        # Show only the recipe references\n        if pattern.package_id is None and pattern.rrev is None:\n            for r in refs:\n                select_bundle.add_ref(r)\n            return select_bundle\n\n        def msg_format(msg, item, total):\n            return msg + f\" ({total.index(item)}/{len(total)})\"\n\n        trefs = TimedOutput(5, msg_format=msg_format)\n        for r in refs:  # Older versions first\n            trefs.info(f\"Listing revisions of {r} in {remote_name}\", r, refs)\n            if pattern.is_latest_rrev or pattern.rrev is None:\n                rrev = self.latest_recipe_revision(r, remote)\n                if rrev is None:\n                    raise NotFoundException(f\"Recipe '{r}' not found\")\n                rrevs = [rrev]\n            else:\n                rrevs = self.recipe_revisions(r, remote)\n                rrevs = pattern.filter_rrevs(rrevs)\n                rrevs = list(reversed(rrevs))  # Order older revisions first\n\n            if lru and pattern.package_id is None:  # Filter LRUs\n                rrevs = [r for r in rrevs if cache.get_recipe_lru(r) < limit_time]\n\n            for rr in rrevs:\n                select_bundle.add_ref(rr)\n\n            if pattern.package_id is None:  # Stop if not displaying binaries\n                continue\n\n            trrevs = TimedOutput(5, msg_format=msg_format)\n            for rrev in rrevs:\n                trrevs.info(f\"Listing binaries of {rrev.repr_notime()} in {remote_name}\", rrev, rrevs)\n                prefs = []\n                if \"*\" not in pattern.package_id and pattern.prev is not None:\n                    prefs.append(PkgReference(rrev, package_id=pattern.package_id))\n                    packages = {}\n                else:\n                    packages = self._packages_configurations(rrev, remote)\n                    if package_query is not None:\n                        packages = self._filter_packages_configurations(packages, package_query)\n                    if profile is not None:\n                        packages = self._filter_packages_profile(packages, profile, rrev)\n                    prefs = packages.keys()\n                    prefs = pattern.filter_prefs(prefs)\n                    packages = {pref: conf for pref, conf in packages.items() if pref in prefs}\n\n                if pattern.prev is not None:\n                    new_prefs = []\n                    for pref in prefs:\n                        # Maybe the package_configurations returned timestamp\n                        if pattern.is_latest_prev or pattern.prev is None:\n                            prev = self.latest_package_revision(pref, remote)\n                            if prev is None:\n                                raise NotFoundException(f\"Binary package not found: '{pref}\")\n                            new_prefs.append(prev)\n                        else:\n                            prevs = self.package_revisions(pref, remote)\n                            prevs = pattern.filter_prevs(prevs)\n                            prevs = list(reversed(prevs))  # Older revisions first\n                            new_prefs.extend(prevs)\n                    prefs = new_prefs\n\n                if lru:  # Filter LRUs\n                    prefs = [r for r in prefs if cache.get_package_lru(r) < limit_time]\n\n                # Packages dict has been listed, even if empty\n                select_bundle.recipe_dict(rrev)[\"packages\"] = {}\n                for p in prefs:\n                    # the \"packages\" dict is not using the package-revision\n                    pkg_info = packages.get(PkgReference(p.ref, p.package_id))\n                    select_bundle.add_pref(p, pkg_info)\n        return select_bundle\n\n    def explain_missing_binaries(self, ref, conaninfo, remotes):\n        \"\"\" (Experimental) Explain why a binary is missing in the cache\n        \"\"\"\n        ConanOutput().info(f\"Missing binary: {ref}\")\n        ConanOutput().info(f\"With conaninfo.txt (package_id):\\n{conaninfo.dumps()}\")\n        conaninfo = load_binary_info(conaninfo.dumps())\n        # Collect all configurations\n        candidates = []\n        ConanOutput().info(f\"Finding binaries in the cache\")\n        pkg_configurations = self._packages_configurations(ref)\n        candidates.extend(_BinaryDistance(pref, data, conaninfo)\n                          for pref, data in pkg_configurations.items())\n\n        for remote in remotes:\n            try:\n                ConanOutput().info(f\"Finding binaries in remote {remote.name}\")\n                pkg_configurations = self._packages_configurations(ref, remote=remote)\n            except Exception as e:\n                ConanOutput().error(f\"Error in remote '{remote.name}': {e}\")\n            else:\n                candidates.extend(_BinaryDistance(pref, data, conaninfo, remote)\n                                  for pref, data in pkg_configurations.items())\n\n        candidates.sort()\n        pkglist = PackagesList()\n        pkglist.add_ref(ref)\n        # Return the closest matches, stop adding when distance is increased\n        candidate_distance = None\n        for candidate in candidates:\n            if candidate_distance and candidate.distance != candidate_distance:\n                break\n            candidate_distance = candidate.distance\n            pref = candidate.pref\n            pkglist.add_pref(pref, candidate.binary_config)\n            # Add the diff data\n            rev_dict = pkglist.recipe_dict(ref)\n            rev_dict[\"packages\"][pref.package_id][\"diff\"] = candidate.serialize()\n            remote = candidate.remote.name if candidate.remote else \"Local Cache\"\n            rev_dict[\"packages\"][pref.package_id][\"remote\"] = remote\n        return pkglist\n\n    def find_remotes(self, package_list, remotes):\n        \"\"\"\n        (Experimental) Find the remotes where the current package lists can be found\n        \"\"\"\n        result = MultiPackagesList()\n        remote_manager = self._api_helpers.remote_manager\n        for r in remotes:\n            result_pkg_list = PackagesList()\n            for ref, ref_contents in package_list.serialize().items():\n                ref = RecipeReference.loads(ref)\n                try:\n                    remote_rrevs = remote_manager.get_recipe_revisions(ref, remote=r)\n                except NotFoundException:\n                    continue\n                revisions = ref_contents.get(\"revisions\")\n                if revisions is None:  # This is a package list just with name/version\n                    if remote_rrevs:\n                        result_pkg_list.add_ref(ref)\n                    continue\n\n                for revision, rev_content in revisions.items():\n                    ref.revision = revision\n                    # We look for the value of revision in server, to return timestamp too\n                    found = next((r for r in remote_rrevs if r == ref), None)\n                    if not found:\n                        continue\n                    result_pkg_list.add_ref(found)\n                    packages = rev_content.get(\"packages\")\n                    if packages is None:\n                        continue\n                    for pkgid, pkgcontent in packages.items():\n                        pref = PkgReference(ref, pkgid)\n                        try:\n                            remote_prefs = remote_manager.get_package_revisions(pref, remote=r)\n                        except NotFoundException:\n                            continue\n                        pkg_revisions = pkgcontent.get(\"revisions\")\n                        if pkg_revisions is None:  # This is a package_id, no prevs\n                            if remote_prefs:\n                                result_pkg_list.add_pref(pref, pkgcontent.get(\"info\"))\n                            continue\n                        for pkg_revision, prev_content in pkg_revisions.items():\n                            pref.revision = pkg_revision\n                            # We look for the value of revision in server, to return timestamp too\n                            pfound = next((r for r in remote_prefs if r == pref), None)\n                            if not pfound:\n                                continue\n                            result_pkg_list.add_pref(pfound, pkgcontent.get(\"info\"))\n\n            if result_pkg_list:\n                result.add(r.name, result_pkg_list)\n        return result\n\n    def outdated(self, deps_graph, remotes):\n        # DO NOT USE YET\n        # Data structure to store info per library\n        dependencies = deps_graph.nodes[1:]\n        dict_nodes = {}\n\n        # When there are no dependencies command should stop\n        if len(dependencies) == 0:\n            return dict_nodes\n\n        ConanOutput().title(\"Checking remotes\")\n\n        for node in dependencies:\n            dict_nodes.setdefault(node.name, {\"cache_refs\": set(), \"version_ranges\": [],\n                                              \"latest_remote\": None})[\"cache_refs\"].add(node.ref)\n\n        for version_range in deps_graph.resolved_ranges.keys():\n            dict_nodes[version_range.name][\"version_ranges\"].append(version_range)\n\n        # find in remotes\n        for node_name, node_info in dict_nodes.items():\n            ref_pattern = ListPattern(node_name, rrev=None, prev=None)\n            for remote in remotes:\n                try:\n                    remote_ref_list = self.select(ref_pattern, package_query=None, remote=remote)\n                except NotFoundException:\n                    continue\n                if not remote_ref_list:\n                    continue\n                str_latest_ref = list(remote_ref_list.serialize().keys())[-1]\n                recipe_ref = RecipeReference.loads(str_latest_ref)\n                if (node_info[\"latest_remote\"] is None\n                        or node_info[\"latest_remote\"][\"ref\"] < recipe_ref):\n                    node_info[\"latest_remote\"] = {\"ref\": recipe_ref, \"remote\": remote.name}\n\n        # Filter nodes with no outdated versions\n        filtered_nodes = {}\n        for node_name, node in dict_nodes.items():\n            if node['latest_remote'] is not None and sorted(list(node['cache_refs']))[0] < \\\n                    node['latest_remote']['ref']:\n                filtered_nodes[node_name] = node\n\n        return filtered_nodes\n\n\nclass _BinaryDistance:\n    def __init__(self, pref, binary, expected, remote=None):\n        self.remote = remote\n        self.pref = pref\n        self.binary_config = binary\n\n        # Settings, special handling for os/arch\n        binary_settings = binary.get(\"settings\", {})\n        expected_settings = expected.get(\"settings\", {})\n\n        platform = {k: v for k, v in binary_settings.items() if k in (\"os\", \"arch\")}\n        expected_platform = {k: v for k, v in expected_settings.items() if k in (\"os\", \"arch\")}\n        self.platform_diff = self._calculate_diff(platform, expected_platform)\n\n        binary_settings = {k: v for k, v in binary_settings.items() if k not in (\"os\", \"arch\")}\n        expected_settings = {k: v for k, v in expected_settings.items() if k not in (\"os\", \"arch\")}\n        self.settings_diff = self._calculate_diff(binary_settings, expected_settings)\n\n        self.settings_target_diff = self._calculate_diff(binary, expected, \"settings_target\")\n        self.options_diff = self._calculate_diff(binary, expected, \"options\")\n        self.deps_diff = self._requirement_diff(binary, expected, \"requires\")\n        self.build_requires_diff = self._requirement_diff(binary, expected, \"build_requires\")\n        self.python_requires_diff = self._requirement_diff(binary, expected, \"python_requires\")\n        self.confs_diff = self._calculate_diff(binary,  expected, \"conf\")\n\n    @staticmethod\n    def _requirement_diff(binary_requires, expected_requires, item):\n        binary_requires = binary_requires.get(item, {})\n        expected_requires = expected_requires.get(item, {})\n        output = {}\n        binary_requires = [RecipeReference.loads(r) for r in binary_requires]\n        expected_requires = [RecipeReference.loads(r) for r in expected_requires]\n        binary_requires = {r.name: r for r in binary_requires}\n        for r in expected_requires:\n            existing = binary_requires.get(r.name)\n            if not existing or r != existing:\n                output.setdefault(\"expected\", []).append(repr(r))\n                output.setdefault(\"existing\", []).append(repr(existing))\n        expected_requires = {r.name: r for r in expected_requires}\n        for r in binary_requires.values():\n            existing = expected_requires.get(r.name)\n            if not existing or r != existing:\n                if repr(existing) not in output.get(\"expected\", ()):\n                    output.setdefault(\"expected\", []).append(repr(existing))\n                if repr(r) not in output.get(\"existing\", ()):\n                    output.setdefault(\"existing\", []).append(repr(r))\n        return output\n\n    @staticmethod\n    def _calculate_diff(binary_confs, expected_confs, item=None):\n        if item is not None:\n            binary_confs = binary_confs.get(item, {})\n            expected_confs = expected_confs.get(item, {})\n        output = {}\n        for k, v in expected_confs.items():\n            value = binary_confs.get(k)\n            if value != v:\n                output.setdefault(\"expected\", []).append(f\"{k}={v}\")\n                output.setdefault(\"existing\", []).append(f\"{k}={value}\")\n        for k, v in binary_confs.items():\n            value = expected_confs.get(k)\n            if value != v:\n                if f\"{k}={value}\" not in output.get(\"expected\", ()):\n                    output.setdefault(\"expected\", []).append(f\"{k}={value}\")\n                if f\"{k}={v}\" not in output.get(\"existing\", ()):\n                    output.setdefault(\"existing\", []).append(f\"{k}={v}\")\n        return output\n\n    def __lt__(self, other):\n        return self.distance < other.distance\n\n    def explanation(self):\n        if self.platform_diff:\n            return \"This binary belongs to another OS or Architecture, highly incompatible.\"\n        if self.settings_diff:\n            return \"This binary was built with different settings.\"\n        if self.settings_target_diff:\n            return \"This binary was built with different settings_target.\"\n        if self.options_diff:\n            return \"This binary was built with the same settings, but different options\"\n        if self.deps_diff:\n            return \"This binary has same settings and options, but different dependencies\"\n        if self.build_requires_diff:\n            return \"This binary has same settings, options and dependencies, but different build_requires\"\n        if self.python_requires_diff:\n            return \"This binary has same settings, options and dependencies, but different python_requires\"\n        if self.confs_diff:\n            return \"This binary has same settings, options and dependencies, but different confs\"\n        return \"This binary is an exact match for the defined inputs\"\n\n    @property\n    def distance(self):\n        return (len(self.platform_diff.get(\"expected\", [])),\n                len(self.settings_diff.get(\"expected\", [])),\n                len(self.settings_target_diff.get(\"expected\", [])),\n                len(self.options_diff.get(\"expected\", [])),\n                len(self.deps_diff.get(\"expected\", [])),\n                len(self.build_requires_diff.get(\"expected\", [])),\n                len(self.python_requires_diff.get(\"expected\", [])),\n                len(self.confs_diff.get(\"expected\", [])))\n\n    def serialize(self):\n        return {\"platform\": self.platform_diff,\n                \"settings\": self.settings_diff,\n                \"settings_target\": self.settings_target_diff,\n                \"options\": self.options_diff,\n                \"dependencies\": self.deps_diff,\n                \"build_requires\": self.build_requires_diff,\n                \"python_requires\": self.python_requires_diff,\n                \"confs\": self.confs_diff,\n                \"explanation\": self.explanation()}\n\n\ndef _get_cache_packages_binary_info(cache, prefs) -> Dict[PkgReference, dict]:\n    \"\"\"\n    param package_layout: Layout for the given reference\n    \"\"\"\n\n    result = OrderedDict()\n\n    for pref in prefs:\n        latest_prev = cache.get_latest_package_revision(pref)\n        pkg_layout = cache.pkg_layout(latest_prev)\n\n        # Read conaninfo\n        info_path = os.path.join(pkg_layout.package(), CONANINFO)\n        if not os.path.exists(info_path):\n            ConanOutput().error(f\"Corrupted package '{pkg_layout.reference}' \"\n                                f\"without conaninfo.txt in: {info_path}\")\n            info = {}\n        else:\n            conan_info_content = load(info_path)\n            info = load_binary_info(conan_info_content)\n        pref = pkg_layout.reference\n        # The key shoudln't have the latest package revision, we are asking for package configs\n        pref.revision = None\n        result[pkg_layout.reference] = info\n\n    return result\n\n\ndef _search_recipes(api_helpers, query: str, remote=None):\n    only_none_user_channel = False\n    if query and query.endswith(\"@\"):\n        only_none_user_channel = True\n        query = query[:-1]\n\n    if remote:\n        refs = api_helpers.remote_manager.search_recipes(remote, query)\n    else:\n        refs = api_helpers.cache.search_recipes(query)\n    ret = []\n    for r in refs:\n        if not only_none_user_channel or (r.user is None and r.channel is None):\n            ret.append(r)\n    return sorted(ret)\n"
  },
  {
    "path": "conan/api/subapi/local.py",
    "content": "import os\nfrom typing import List\n\nfrom conan.cli import make_abs_path\nfrom conan.internal.conan_app import ConanApp\nfrom conan.internal.api.local.editable import EditablePackages\nfrom conan.internal.methods import run_build_method, run_source_method\nfrom conan.internal.graph.graph import CONTEXT_HOST\nfrom conan.internal.graph.profile_node_definer import initialize_conanfile_profile\nfrom conan.internal.errors import conanfile_exception_formatter\nfrom conan.errors import ConanException\nfrom conan.api.model import RecipeReference, Remote\nfrom conan.internal.util.files import chdir\n\n\nclass LocalAPI:\n    \"\"\" This ``LocalAPI`` contains several helpers related to the local development flow, i.e.,\n    locally calling ``source()`` or ``build()`` methods, or adding and removing editable packages\n    \"\"\"\n\n    def __init__(self, conan_api, helpers):\n        self._conan_api = conan_api\n        self._helpers = helpers\n        self.editable_packages = EditablePackages(conan_api.home_folder)\n\n    @staticmethod\n    def get_conanfile_path(path, cwd, py):\n        \"\"\" Obtain the full path to a conanfile file, either .txt or .py, from the current\n        working directory.\n\n        If both ``conanfile.py`` and a ``conanfile.txt`` are present, it will raise an error.\n\n        :param path: Relative path to look for the file. Can be a folder or a file.\n        :param cwd: The current working directory.\n        :param py: If True, a conanfile.py must exist, a .txt is not valid in this case\n        \"\"\"\n        path = make_abs_path(path, cwd)\n\n        if os.path.isdir(path):  # Can be a folder\n            path_py = os.path.join(path, \"conanfile.py\")\n            if py:\n                path = path_py\n            else:\n                path_txt = os.path.join(path, \"conanfile.txt\")\n                if os.path.isfile(path_py) and os.path.isfile(path_txt):\n                    raise ConanException(\"Ambiguous command, both conanfile.py and \"\n                                         \"conanfile.txt exist\")\n                path = path_py if os.path.isfile(path_py) else path_txt\n\n        if not os.path.isfile(path):  # Must exist\n            raise ConanException(\"Conanfile not found at %s\" % path)\n\n        if py and not path.endswith(\".py\"):\n            raise ConanException(\"A conanfile.py is needed, \" + path + \" is not acceptable\")\n\n        return path\n\n    def editable_add(self, path, name=None, version=None, user=None, channel=None, cwd=None,\n                     output_folder=None, remotes: List[Remote] = None) -> RecipeReference:\n        \"\"\" Add the conanfile in the given path as an editable package\n\n        Note that for automation over editables it might be recommended to use the ``WorkspacesAPI``\n        instead of this API.\n\n        :param path: Relative path to look for it. Can be a folder or a file.\n        :param name: The name of the package. If not defined, it is taken from conanfile\n        :param version: The version of the package. If not defined, it is taken from conanfile\n        :param user: The user of the package. If not defined, it is taken from conanfile\n        :param channel: The channel of the package. If not defined, it is taken from conanfile\n        :param cwd: The current working directory\n        :param output_folder: The output folder. If not defined, the recipe layout will be used.\n        :param remotes: The remotes to resolve possible ``python-requires`` for this recipe if needed.\n        :return: RecipeReference of the added package\n        \"\"\"\n        path = self.get_conanfile_path(path, cwd, py=True)\n        app = ConanApp(self._conan_api)\n        conanfile = app.loader.load_named(path, name, version, user, channel, remotes=remotes)\n        if conanfile.name is None or conanfile.version is None:\n            raise ConanException(\"Editable package recipe should declare its name and version\")\n        ref = RecipeReference(conanfile.name, conanfile.version, conanfile.user, conanfile.channel)\n        # Retrieve conanfile.py from target_path\n        target_path = self.get_conanfile_path(path=path, cwd=cwd, py=True)\n        output_folder = make_abs_path(output_folder) if output_folder else None\n        # Check the conanfile is there, and name/version matches\n        self.editable_packages.add(ref, target_path, output_folder=output_folder)\n        return ref\n\n    def editable_remove(self, path=None, requires=None, cwd=None):\n        \"\"\" Remove an editable package from the given path\n\n        Note that for automation over editables it might be recommended to use the ``WorkspacesAPI``\n        instead of this API.\n\n        :param path: Relative path to look for it. Can be a folder or a file.\n        :param requires: Remove these requirements from editables (instead of by path)\n        :param cwd: The current working directory\n        :return: RecipeReference of the added package\n        \"\"\"\n        if path:\n            path = make_abs_path(path, cwd)\n            path = os.path.join(path, \"conanfile.py\")\n        return self.editable_packages.remove(path, requires)\n\n    def editable_list(self):\n        return self.editable_packages.edited_refs\n\n    def source(self, path, name=None, version=None, user=None, channel=None,\n               remotes: List[Remote] = None):\n        \"\"\" Calls the ``source()`` method of the current (user folder) ``conanfile.py``\n\n        This method does not require computing a dependency graph, because the ``source()``\n        method is assumed to be invariant with respect to settings, options and dependencies.\n\n        :param path: Relative path to look for the conanfile. Can be a folder or a file.\n        :param name: The name of the package. If not defined, it is taken from conanfile\n        :param version: The version of the package. If not defined, it is taken from conanfile\n        :param user: The user of the package. If not defined, it is taken from conanfile\n        :param channel: The channel of the package. If not defined, it is taken from conanfile\n        :param remotes: The remotes to resolve possible ``python-requires`` for this recipe if needed.\n        \"\"\"\n        app = ConanApp(self._conan_api)\n        conanfile = app.loader.load_consumer(path, name=name, version=version,\n                                             user=user, channel=channel, graph_lock=None,\n                                             remotes=remotes)\n        # This profile is empty, but with the conf from global.conf\n        profile = self._conan_api.profiles.get_profile([])\n        initialize_conanfile_profile(conanfile, profile, profile, CONTEXT_HOST, False)\n        # This is important, otherwise the ``conan source`` doesn't define layout and fails\n        if hasattr(conanfile, \"layout\"):\n            with conanfile_exception_formatter(conanfile, \"layout\"):\n                conanfile.layout()\n\n        folder = conanfile.recipe_folder if conanfile.folders.root is None else \\\n            os.path.normpath(os.path.join(conanfile.recipe_folder, conanfile.folders.root))\n\n        conanfile.folders.set_base_source(folder)\n        conanfile.folders.set_base_export_sources(folder)\n        conanfile.folders.set_base_recipe_metadata(os.path.join(folder, \"metadata\"))\n        # The generators are needed for the \"conan source\" local case with tool-requires\n        conanfile.folders.set_base_generators(folder)\n        conanfile.folders.set_base_build(None)\n        conanfile.folders.set_base_package(None)\n\n        hook_manager = self._helpers.hook_manager\n        run_source_method(conanfile, hook_manager)\n\n    def build(self, conanfile) -> None:\n        \"\"\" Calls the ``build()`` method of the current (user folder) ``conanfile.py``\n\n        This method does require computing a dependency graph, because the ``build()`` method\n        needs all dependencies and transitive dependencies. Then, the ``conanfile`` argument\n        must be the one obtaind from a full dependency graph install operation, including both\n        the graph comptutation and the binary installation.\n\n        :param conanfile: ``Conanfile`` object representing the \"root\" node in the dependency graph,\n          corresponding to a ``conanfile.py`` in the user folder, containing the ``build()`` method to\n          be called. This ``conanfile`` object must have all of its dependencies computed and\n          installed in the current Conan package cache to work.\n        \"\"\"\n        hook_manager = self._helpers.hook_manager\n        conanfile.folders.set_base_package(conanfile.folders.base_build)\n        conanfile.folders.set_base_pkg_metadata(os.path.join(conanfile.build_folder, \"metadata\"))\n        run_build_method(conanfile, hook_manager)\n\n    @staticmethod\n    def test(conanfile) -> None:\n        \"\"\" Calls the ``test()`` method of the current (user folder) ``test_package/conanfile.py``\n\n        This method does require computing a dependency graph, because the ``test()`` method\n        needs all dependencies and transitive dependencies. Then, the ``conanfile`` argument\n        must be the one obtaind from a full dependency graph install operation, including both\n        the graph comptutation and the binary installation.\n\n        Typically called after a ``build()`` one.\n\n        :param conanfile: ``Conanfile`` object representing the \"root\" node in the dependency graph,\n          corresponding to a conanfile.py in the user \"test_package\" folder, containing the ``test()``\n          method to be called. This ``conanfile`` object must have all of its dependencies computed\n          and installed in the current Conan package cache to work.\n        \"\"\"\n        with conanfile_exception_formatter(conanfile, \"test\"):\n            with chdir(conanfile.build_folder):\n                conanfile.test()\n\n    def inspect(self, conanfile_path, remotes, lockfile, name=None, version=None, user=None,\n                channel=None):\n        app = ConanApp(self._conan_api)\n        conanfile = app.loader.load_named(conanfile_path, name=name, version=version, user=user,\n                                          channel=channel, remotes=remotes, graph_lock=lockfile)\n        return conanfile\n\n    def reinit(self):\n        self.editable_packages = EditablePackages(self._conan_api.home_folder)\n"
  },
  {
    "path": "conan/api/subapi/lockfile.py",
    "content": "import os\n\nfrom conan.api.output import ConanOutput\nfrom conan.cli import make_abs_path\nfrom conan.internal.graph.graph import Overrides\nfrom conan.errors import ConanException\nfrom conan.internal.model.lockfile import Lockfile, LOCKFILE\n\n\nclass LockfileAPI:\n\n    def __init__(self, conan_api):\n        self._conan_api = conan_api\n\n    @staticmethod\n    def get_lockfile(lockfile=None, conanfile_path=None, cwd=None, partial=False,\n                     overrides=None) -> Lockfile:\n        \"\"\" obtain a lockfile, following this logic:\n\n        If lockfile is explicitly defined, it would be either absolute or relative to cwd and\n        the lockfile file must exist. If lockfile=\"\" (empty string) the default \"conan.lock\"\n        lockfile will not be automatically used even if it is present.\n\n        If lockfile is not defined, it will still look for a default conan.lock:\n\n         - if conanfile_path is defined, it will be besides it\n         - if conanfile_path is not defined, the default conan.lock should be in cwd\n         - if the default conan.lock cannot be found, it is not an error\n\n\n        :param partial: If the obtained lockfile will allow partial resolving\n        :param cwd: the current working dir, if None, os.getcwd() will be used\n        :param conanfile_path: The full path to the conanfile, if existing\n        :param lockfile: the name of the lockfile file\n        :param overrides: Dictionary of overrides {overriden: [new_ref1, new_ref2]}\n        \"\"\"\n        if lockfile == \"\":\n            # Allow a way with ``--lockfile=\"\"`` to optout automatic usage of conan.lock\n            return\n\n        cwd = cwd or os.getcwd()\n        if lockfile is None:  # Look for a default \"conan.lock\"\n            # if path is defined, take it as reference\n            base_path = os.path.dirname(conanfile_path) if conanfile_path else cwd\n            lockfile_path = make_abs_path(LOCKFILE, base_path)\n            if not os.path.isfile(lockfile_path):\n                if overrides:\n                    raise ConanException(\"Cannot define overrides without a lockfile\")\n                return\n        else:  # explicit lockfile given\n            lockfile_path = make_abs_path(lockfile, cwd)\n            if not os.path.isfile(lockfile_path):\n                raise ConanException(\"Lockfile doesn't exist: {}\".format(lockfile_path))\n\n        graph_lock = Lockfile.load(lockfile_path)\n        graph_lock.partial = partial\n\n        if overrides:\n            graph_lock._overrides = Overrides.deserialize(overrides)\n        ConanOutput().info(\"Using lockfile: '{}'\".format(lockfile_path))\n        return graph_lock\n\n    def update_lockfile_export(self, lockfile, conanfile, ref, is_build_require=False):\n        # The package_type is not fully processed at export\n        is_python_require = conanfile.package_type == \"python-require\"\n        is_require = not is_python_require and not is_build_require\n        if hasattr(conanfile, \"python_requires\"):\n            python_requires = conanfile.python_requires.all_refs()\n        else:\n            python_requires = []\n        python_requires = python_requires + ([ref] if is_python_require else [])\n        new_lock = self.add_lockfile(lockfile,\n                                     requires=[ref] if is_require else None,\n                                     python_requires=python_requires,\n                                     build_requires=[ref] if is_build_require else None)\n        if lockfile is None:  # If there was no lockfile, it is a partial one to lock export\n            new_lock.partial = True\n        return new_lock\n\n    @staticmethod\n    def update_lockfile(lockfile, graph, lock_packages=False, clean=False):\n        if lockfile is None or clean:\n            lockfile = Lockfile(graph, lock_packages)\n        else:\n            lockfile.update_lock(graph, lock_packages)\n        return lockfile\n\n    @staticmethod\n    def merge_lockfiles(lockfiles):\n        result = Lockfile()\n        for lockfile in lockfiles:\n            lockfile = make_abs_path(lockfile)\n            graph_lock = Lockfile.load(lockfile)\n            result.merge(graph_lock)\n        return result\n\n    @staticmethod\n    def add_lockfile(lockfile=None, requires=None, build_requires=None, python_requires=None,\n                     config_requires=None):\n        if lockfile is None:\n            lockfile = Lockfile()  # create a new lockfile\n\n        lockfile.add(requires=requires, build_requires=build_requires,\n                     python_requires=python_requires, config_requires=config_requires)\n        return lockfile\n\n    @staticmethod\n    def remove_lockfile(lockfile, requires=None, build_requires=None, python_requires=None,\n                        config_requires=None):\n        lockfile.remove(requires=requires, build_requires=build_requires,\n                        python_requires=python_requires, config_requires=config_requires)\n        return lockfile\n\n    @staticmethod\n    def save_lockfile(lockfile, lockfile_out, path=None):\n        if lockfile_out is not None:\n            lockfile_out = make_abs_path(lockfile_out, path)\n            lockfile.save(lockfile_out)\n            ConanOutput().info(f\"Generated lockfile: {lockfile_out}\")\n"
  },
  {
    "path": "conan/api/subapi/new.py",
    "content": "import fnmatch\nimport os\nimport shutil\n\nfrom jinja2 import Template, StrictUndefined, UndefinedError, Environment, meta\n\nfrom conan.api.output import ConanOutput\nfrom conan.errors import ConanException\nfrom conan.internal.util.files import load, save\nfrom conan import __version__\n\n\nclass NewAPI:\n    _NOT_TEMPLATES = \"not_templates\"  # Filename containing filenames of files not to be rendered\n\n    def __init__(self, conan_api):\n        self._conan_api = conan_api\n\n    def save_template(self, template, defines=None, output_folder=None, force=False):\n        \"\"\"\n        Save the 'template' files in the output_folder, replacing the template variables\n        with the 'defines'\n        :param template: The name of the template to use\n        :param defines: A list with the 'k=v' variables to replace in the template\n        :param output_folder: The folder where the template files will be saved, cwd if None\n        :param force: If True, overwrite the files if they already exist, otherwise raise an error\n        \"\"\"\n        # Manually parsing the remainder\n        definitions = {}\n        for u in defines or []:\n            try:\n                k, v = u.split(\"=\", 1)\n            except ValueError:\n                raise ConanException(f\"Template definitions must be 'key=value', received '{u}'\")\n            k = k.replace(\"-\", \"\")  # Remove possible \"--name=value\"\n            # For variables that only show up once, no need for list to keep compatible behaviour\n            if k in definitions:\n                if isinstance(definitions[k], list):\n                    definitions[k].append(v)\n                else:\n                    definitions[k] = [definitions[k], v]\n            else:\n                definitions[k] = v\n\n        files = self.get_template(template)  # First priority: user folder\n        is_builtin = False\n        if not files:  # then, try the templates in the Conan home\n            files = self.get_home_template(template)\n        if files:\n            template_files, non_template_files = files\n        else:\n            template_files = self.get_builtin_template(template)\n            non_template_files = {}\n            is_builtin = True\n\n        if not template_files and not non_template_files:\n            raise ConanException(f\"Template doesn't exist or not a folder: {template}\")\n\n        if is_builtin and template == \"workspace\":  # hardcoded for the workspace special case\n            definitions[\"name\"] = \"liba\"\n        template_files = self.render(template_files, definitions)\n\n        # Saving the resulting files\n        output = ConanOutput()\n        output_folder = output_folder or os.getcwd()\n        # Making sure they don't overwrite existing files\n        for f, v in sorted(template_files.items()):\n            path = os.path.join(output_folder, f)\n            if os.path.exists(path) and not force:\n                raise ConanException(f\"File '{f}' already exists, and --force not defined, aborting\")\n            save(path, v)\n            output.success(\"File saved: %s\" % f)\n\n        # copy non-templates\n        for f, v in sorted(non_template_files.items()):\n            path = os.path.join(output_folder, f)\n            if os.path.exists(path) and not force:\n                raise ConanException(f\"File '{f}' already exists, and --force not defined, aborting\")\n            shutil.copy2(v, path)\n            output.success(\"File saved: %s\" % f)\n\n    @staticmethod\n    def get_builtin_template(template_name):\n        from conan.internal.api.new.basic import basic_file, basic_default_file\n        from conan.internal.api.new.alias_new import alias_file\n        from conan.internal.api.new.cmake_exe import cmake_exe_files\n        from conan.internal.api.new.cmake_lib import cmake_lib_files\n        from conan.internal.api.new.header_lib import header_only_lib_files\n        from conan.internal.api.new.meson_lib import meson_lib_files\n        from conan.internal.api.new.meson_exe import meson_exe_files\n        from conan.internal.api.new.msbuild_lib import msbuild_lib_files\n        from conan.internal.api.new.msbuild_exe import msbuild_exe_files\n        from conan.internal.api.new.bazel_lib import bazel_lib_files\n        from conan.internal.api.new.bazel_exe import bazel_exe_files\n        from conan.internal.api.new.bazel_7_lib import bazel_lib_files_7\n        from conan.internal.api.new.bazel_7_exe import bazel_exe_files_7\n        from conan.internal.api.new.autotools_lib import autotools_lib_files\n        from conan.internal.api.new.autoools_exe import autotools_exe_files\n        from conan.internal.api.new.premake_lib import premake_lib_files\n        from conan.internal.api.new.premake_exe import premake_exe_files\n        from conan.internal.api.new.local_recipes_index import local_recipes_index_files\n        from conan.internal.api.new.qbs_lib import qbs_lib_files\n        from conan.internal.api.new.workspace import workspace_files\n        if not template_name:\n            return basic_default_file\n        new_templates = {\"basic\": basic_file,\n                         \"cmake_lib\": cmake_lib_files,\n                         \"cmake_exe\": cmake_exe_files,\n                         \"header_lib\": header_only_lib_files,\n                         \"meson_lib\": meson_lib_files,\n                         \"meson_exe\": meson_exe_files,\n                         \"msbuild_lib\": msbuild_lib_files,\n                         \"msbuild_exe\": msbuild_exe_files,\n                         # TODO: Rename xxx_7 to xxx when dropped Bazel 6.x compatibility\n                         \"bazel_lib\": bazel_lib_files,\n                         \"bazel_exe\": bazel_exe_files,\n                         \"bazel_7_lib\": bazel_lib_files_7,\n                         \"bazel_7_exe\": bazel_exe_files_7,\n                         \"autotools_lib\": autotools_lib_files,\n                         \"autotools_exe\": autotools_exe_files,\n                         \"premake_lib\": premake_lib_files,\n                         \"premake_exe\": premake_exe_files,\n                         \"alias\": alias_file,\n                         \"local_recipes_index\": local_recipes_index_files,\n                         \"qbs_lib\": qbs_lib_files,\n                         \"workspace\": workspace_files}\n        template_files = new_templates.get(template_name)\n        return template_files\n\n    def get_template(self, template_folder):\n        \"\"\" Load a template from a user absolute folder\n        \"\"\"\n        if os.path.isdir(template_folder):\n            return self._read_files(template_folder)\n\n    def get_home_template(self, template_name):\n        \"\"\" Load a template from the Conan home templates/command/new folder\n        \"\"\"\n        folder_template = os.path.join(self._conan_api.home_folder, \"templates\", \"command/new\",\n                                       template_name)\n        if os.path.isdir(folder_template):\n            return self._read_files(folder_template)\n\n    def _read_files(self, template_folder):\n        template_files, non_template_files = {}, {}\n        excluded = os.path.join(template_folder, self._NOT_TEMPLATES)\n        if os.path.exists(excluded):\n            excluded = load(excluded)\n            excluded = [] if not excluded else [s.strip() for s in excluded.splitlines() if\n                                                s.strip()]\n        else:\n            excluded = []\n\n        for d, _, fs in os.walk(template_folder):\n            for f in fs:\n                if f == self._NOT_TEMPLATES:\n                    continue\n                rel_d = os.path.relpath(d, template_folder) if d != template_folder else \"\"\n                rel_f = os.path.join(rel_d, f)\n                path = os.path.join(d, f)\n                if not any(fnmatch.fnmatch(rel_f, exclude) for exclude in excluded):\n                    template_files[rel_f] = load(path)\n                else:\n                    non_template_files[rel_f] = path\n\n        return template_files, non_template_files\n\n    @staticmethod\n    def render(template_files, definitions):\n        result = {}\n        name = definitions.get(\"name\", \"mypkg\")\n        if isinstance(name, list):\n            raise ConanException(f\"name argument can't be multiple: {name}\")\n        if name != name.lower():\n            raise ConanException(f\"name argument must be lowercase: {name}\")\n        definitions[\"conan_version\"] = __version__\n\n        def ensure_list(key):\n            value = definitions.get(key)  # Convert to list, and forget about it\n            if value:\n                definitions[key] = [value] if isinstance(value, str) else value\n\n        ensure_list(\"requires\")\n        ensure_list(\"tool_requires\")\n\n        def as_package_name(n):\n            return n.replace(\"-\", \"_\").replace(\"+\", \"_\")\n\n        def as_name(ref):\n            ref = as_package_name(ref)\n            if '/' in ref:\n                ref = ref[0:ref.index('/')]\n            return ref\n\n        definitions[\"package_name\"] = as_package_name(name).replace(\".\", \"_\")\n        definitions[\"as_name\"] = as_name\n        definitions[\"names\"] = lambda x: \", \".join(r.split(\"/\", 1)[0] for r in x)\n        if \"name\" not in definitions:\n            definitions[\"name\"] = \"mypkg\"\n        if \"version\" not in definitions:\n            definitions[\"version\"] = \"0.1\"\n        version = definitions.get(\"version\")\n        if isinstance(version, list):\n            raise ConanException(f\"version argument can't be multiple: {version}\")\n\n        try:\n            for k, v in template_files.items():\n                k = Template(k, keep_trailing_newline=True, undefined=StrictUndefined).render(\n                    **definitions)\n                v = Template(v, keep_trailing_newline=True, undefined=StrictUndefined).render(\n                    **definitions)\n                if v:\n                    result[k] = v\n        except UndefinedError:\n            template_vars = []\n            for templ_str in template_files.values():\n                env = Environment()\n                ast = env.parse(templ_str)\n                template_vars.extend(meta.find_undeclared_variables(ast))\n\n            injected_vars = {\"conan_version\", \"package_name\", \"as_name\"}\n            optional_vars = {\"requires\", \"tool_requires\", \"output_root_dir\"}\n            template_vars = list(set(template_vars) - injected_vars - optional_vars)\n            template_vars.sort()\n\n            raise ConanException(\"Missing definitions for the template. \"\n                                 \"Required definitions are: {}\"\n                                 .format(\", \".join(\"'{}'\".format(var) for var in template_vars)))\n        return result\n"
  },
  {
    "path": "conan/api/subapi/profiles.py",
    "content": "import os\n\nfrom conan.api.output import ConanOutput\nfrom conan.internal.cache.home_paths import HomePaths\n\nfrom conan.internal.loader import load_python_file\nfrom conan.internal.api.profile.profile_loader import ProfileLoader\nfrom conan.internal.errors import scoped_traceback\nfrom conan.errors import ConanException\nfrom conan.internal.model.profile import Profile\n\nDEFAULT_PROFILE_NAME = \"default\"\n\n\nclass ProfilesAPI:\n\n    def __init__(self, conan_api, api_helpers):\n        self._conan_api = conan_api\n        self._api_helpers = api_helpers\n        self._home_paths = HomePaths(conan_api.home_folder)\n\n    def get_default_host(self):\n        \"\"\"\n        :return: the path to the default \"host\" profile, either in the cache or as defined\n            by the user in configuration\n        \"\"\"\n        default_profile = os.environ.get(\"CONAN_DEFAULT_PROFILE\")\n        if default_profile is None:\n            global_conf = self._api_helpers.global_conf\n            default_profile = global_conf.get(\"core:default_profile\", default=DEFAULT_PROFILE_NAME)\n\n        default_profile = os.path.join(self._home_paths.profiles_path, default_profile)\n        if not os.path.exists(default_profile):\n            msg = (\"The default host profile '{}' doesn't exist.\\n\"\n                   \"You need to create a default profile (type 'conan profile detect' command)\\n\"\n                   \"or specify your own profile with '--profile:host=<myprofile>'\")\n            # TODO: Add detailed instructions when cli is improved\n            raise ConanException(msg.format(default_profile))\n        return default_profile\n\n    def get_default_build(self):\n        \"\"\"\n        :return: the path to the default \"build\" profile, either in the cache or as\n            defined by the user in configuration\n        \"\"\"\n        default_profile = os.environ.get(\"CONAN_DEFAULT_BUILD_PROFILE\")\n        if default_profile is None:\n            global_conf = self._api_helpers.global_conf\n            default_profile = global_conf.get(\"core:default_build_profile\",\n                                              default=DEFAULT_PROFILE_NAME)\n        default_profile = os.path.join(self._home_paths.profiles_path, default_profile)\n        if not os.path.exists(default_profile):\n            msg = (\"The default build profile '{}' doesn't exist.\\n\"\n                   \"You need to create a default profile (type 'conan profile detect' command)\\n\"\n                   \"or specify your own profile with '--profile:build=<myprofile>'\")\n            # TODO: Add detailed instructions when cli is improved\n            raise ConanException(msg.format(default_profile))\n        return default_profile\n\n    def get_profiles_from_args(self, args):\n        build_profiles = args.profile_build or [self.get_default_build()]\n        host_profiles = args.profile_host or [self.get_default_host()]\n\n        global_conf = self._api_helpers.global_conf\n        global_conf.validate()  # TODO: Remove this from here\n        cache_settings = self._api_helpers.settings_yml\n        profile_plugin = self._load_profile_plugin()\n        cwd = os.getcwd()\n        profile_build = self._get_profile(build_profiles, args.settings_build, args.options_build,\n                                          args.conf_build, cwd, cache_settings,\n                                          profile_plugin, global_conf, context=\"build\")\n        profile_host = self._get_profile(host_profiles, args.settings_host, args.options_host, args.conf_host,\n                                         cwd, cache_settings, profile_plugin, global_conf, context=\"host\")\n        return profile_host, profile_build\n\n    def get_profile(self, profiles, settings=None, options=None, conf=None, cwd=None, context=None):\n        \"\"\" Computes a Profile as the result of aggregating all the user arguments, first it\n        loads the \"profiles\", composing them in order (last profile has priority), and\n        finally adding the individual settings, options (priority over the profiles)\n        \"\"\"\n        assert isinstance(profiles, list), \"Please provide a list of profiles\"\n        global_conf = self._api_helpers.global_conf\n        global_conf.validate()  # TODO: Remove this from here\n        cache_settings = self._api_helpers.settings_yml\n        profile_plugin = self._load_profile_plugin()\n\n        profile = self._get_profile(profiles, settings, options, conf, cwd, cache_settings,\n                                    profile_plugin, global_conf, context=context)\n        return profile\n\n    def _get_profile(self, profiles, settings, options, conf, cwd, cache_settings,\n                     profile_plugin, global_conf, context):\n        loader = ProfileLoader(self._conan_api.cache_folder)\n        profile = loader.from_cli_args(profiles, settings, options, conf, cwd, context)\n        if profile_plugin is not None:\n            try:\n                profile_plugin(profile)\n            except Exception as e:\n                msg = f\"Error while processing 'profile.py' plugin\"\n                msg = scoped_traceback(msg, e, scope=\"/extensions/plugins\")\n                raise ConanException(msg)\n        profile.process_settings(cache_settings)\n        profile.conf.validate()\n        # Apply the new_config to the profiles the global one, so recipes get it too\n        profile.conf.rebase_conf_definition(global_conf)\n        for k, v in sorted(profile.options._package_options.items()):\n            ConanOutput().warning(\"Unscoped option definition is ambiguous.\\n\"\n                                  f\"Use '&:{k}={v}' to refer to the current package.\\n\"\n                                  f\"Use '*:{k}={v}' or other pattern if the intent was to apply to \"\n                                  f\"dependencies\", warn_tag=\"legacy\")\n        if profile.conf.get(\"tools.graph:skip_test\", check_type=bool):\n            ConanOutput().warning(\"Usage of 'tools.graph:skip_test'\", warn_tag=\"experimental\")\n            if not profile.conf.get(\"tools.build:skip_test\", check_type=bool):\n                ConanOutput().warning(\"tools.graph:skip_test set, but tools.build:skip_test is not, \"\n                                      \"probably you need to define it too\")\n        return profile\n\n    def get_path(self, profile, cwd=None, exists=True):\n        \"\"\"\n        :return: the resolved path of the given profile name, that could be in the cache,\n            or local, depending on the \"cwd\"\n        \"\"\"\n        cwd = cwd or os.getcwd()\n        profiles_folder = self._home_paths.profiles_path\n        profile_path = ProfileLoader.get_profile_path(profiles_folder, profile, cwd, exists=exists)\n        return profile_path\n\n    def list(self):\n        \"\"\"\n        List all the profiles file sin the cache\n        :return: an alphabetically ordered list of profile files in the default cache location\n        \"\"\"\n        # List is to be extended (directories should not have a trailing slash)\n        paths_to_ignore = ['.DS_Store']\n\n        profiles = []\n        profiles_path = self._home_paths.profiles_path\n        if os.path.exists(profiles_path):\n            for current_directory, _, files in os.walk(profiles_path, followlinks=True):\n                files = filter(lambda file: os.path.relpath(\n                    os.path.join(current_directory, file), profiles_path) not in paths_to_ignore, files)\n\n                for filename in files:\n                    rel_path = os.path.relpath(os.path.join(current_directory, filename),\n                                               profiles_path)\n                    profiles.append(rel_path)\n\n        profiles.sort()\n        return profiles\n\n    @staticmethod\n    def detect():\n        \"\"\"\n        :return: an automatically detected Profile, with a \"best guess\" of the system settings\n        \"\"\"\n        profile = Profile()\n        from conan.internal.api.profile.detect import detect_defaults_settings\n        settings = detect_defaults_settings()\n        for name, value in settings:\n            profile.settings[name] = value\n        # TODO: This profile is very incomplete, it doesn't have the processed_settings\n        #  good enough at the moment for designing the API interface, but to improve\n        return profile\n\n    def _load_profile_plugin(self):\n        profile_plugin = self._home_paths.profile_plugin_path\n        if not os.path.exists(profile_plugin):\n            raise ConanException(\"The 'profile.py' plugin file doesn't exist. If you want \"\n                                 \"to disable it, edit its contents instead of removing it\")\n\n        mod, _ = load_python_file(profile_plugin)\n        if hasattr(mod, \"profile_plugin\"):\n            return mod.profile_plugin\n"
  },
  {
    "path": "conan/api/subapi/remotes.py",
    "content": "import fnmatch\nimport json\nimport os\nfrom collections import OrderedDict\nfrom urllib.parse import urlparse\n\nfrom conan.api.model import Remote, LOCAL_RECIPES_INDEX\nfrom conan.api.output import ConanOutput\nfrom conan.internal.cache.home_paths import HomePaths\nfrom conan.internal.rest.remote_credentials import RemoteCredentials\nfrom conan.internal.rest.rest_client_local_recipe_index import add_local_recipes_index_remote, \\\n    remove_local_recipes_index_remote\nfrom conan.internal.api.remotes.localdb import LocalDB\nfrom conan.errors import ConanException\nfrom conan.internal.util.files import save, load\n\nCONAN_CENTER_REMOTE_NAME = \"conancenter\"\n\n\nclass RemotesAPI:\n    \"\"\" The ``RemotesAPI`` manages the definition of remotes, contained in the \"remotes.json\" file\n    in the Conan home, supporting addition, removal, update, rename, enable, disable of remotes.\n    These operations do not contact the servers or check their existence at all. If they are not\n    available, they will fail later when used.\n\n    The ``user_xxx`` methods perform authentication related tasks, and some of them will contact\n    the servers to perform such authentication\n    \"\"\"\n\n    def __init__(self, conan_api, api_helpers):\n        # This method is private, the subapi is not instantiated by users\n        self._conan_api = conan_api\n        self._api_helpers = api_helpers\n        self._home_folder = conan_api.home_folder\n        self._remotes_file = HomePaths(self._home_folder).remotes_path\n\n    def list(self, pattern=None, only_enabled=True):\n        \"\"\"\n        Obtain a list of :ref:`Remote <conan.api.model.Remote>` objects matching the pattern.\n\n        :param pattern: ``None``, single ``str`` or list of ``str``. If it is ``None``,\n          all remotes will be returned (equivalent to ``pattern=\"*\"``).\n        :param only_enabled: boolean, by default return only enabled remotes\n        :return: A list of :ref:`Remote <conan.api.model.Remote>` objects\n\n        \"\"\"\n        remotes = _load(self._remotes_file)\n        if only_enabled:\n            remotes = [r for r in remotes if not r.disabled]\n        if pattern:\n            remotes = _filter(remotes, pattern, only_enabled)\n        return remotes\n\n    def disable(self, pattern):\n        \"\"\"\n        Disable all remotes matching ``pattern``\n\n        :param pattern: single ``str`` or list of ``str``. If the pattern is an exact name without\n          wildcards like \"*\" and no remote is found matching that exact name, it will raise an error.\n        :return: the list of disabled :ref:`Remote <conan.api.model.Remote>` objects  (even if they\n          were already disabled)\n        \"\"\"\n        remotes = _load(self._remotes_file)\n        disabled = _filter(remotes, pattern, only_enabled=False)\n        result = []\n        if disabled:\n            for r in disabled:\n                r.disabled = True\n                result.append(r)\n            _save(self._remotes_file, remotes)\n        return result\n\n    def enable(self, pattern):\n        \"\"\"\n        Enable all remotes matching ``pattern``.\n\n        :param pattern: single ``str`` or list of ``str``. If the pattern is an exact name without\n          wildcards like \"*\" and no remote is found matching that exact name, it will raise an error.\n        :return: the list of enabled :ref:`Remote <conan.api.model.Remote>` objects (even if they\n          were already enabled)\n        \"\"\"\n        remotes = _load(self._remotes_file)\n        enabled = _filter(remotes, pattern, only_enabled=False)\n        result = []\n        if enabled:\n            for r in enabled:\n                r.disabled = False\n                result.append(r)\n            _save(self._remotes_file, remotes)\n        return result\n\n    def get(self, remote_name):\n        \"\"\"\n        Obtain a :ref:`Remote <conan.api.model.Remote>` object\n\n        :param remote_name: the exact name of the remote to be returned\n        :return: the :ref:`Remote <conan.api.model.Remote>` object, or raise an Exception if the\n          remote does not exist.\n        \"\"\"\n        remotes = _load(self._remotes_file)\n        try:\n            return {r.name: r for r in remotes}[remote_name]\n        except KeyError:\n            raise ConanException(f\"Remote '{remote_name}' doesn't exist\")\n\n    def add(self, remote: Remote, force=False, index=None):\n        \"\"\"\n        Add a new :ref:`Remote <conan.api.model.Remote>` object to the existing ones\n\n\n        :param remote: a :ref:`Remote <conan.api.model.Remote>` object to be added\n        :param force: do not fail if the remote already exist (but default it fails)\n        :param index: if not defined, the new remote will be last one. Pass an integer to insert\n          the remote in that position instead of the last one\n        \"\"\"\n        add_local_recipes_index_remote(self._home_folder, remote)\n        remotes = _load(self._remotes_file)\n        if remote.remote_type != LOCAL_RECIPES_INDEX:\n            _validate_url(remote.url)\n        current = {r.name: r for r in remotes}.get(remote.name)\n        if current:  # same name remote existing!\n            if not force:\n                raise ConanException(f\"Remote '{remote.name}' already exists in remotes \"\n                                     \"(use --force to continue)\")\n            ConanOutput().warning(f\"Remote '{remote.name}' already exists in remotes\")\n            if current.url != remote.url:\n                ConanOutput().warning(\"Updating existing remote with new url\")\n\n        _check_urls(remotes, remote.url, force, current)\n        if index is None:  # append or replace in place\n            d = {r.name: r for r in remotes}\n            d[remote.name] = remote\n            remotes = list(d.values())\n        else:\n            remotes = [r for r in remotes if r.name != remote.name]\n            remotes.insert(index, remote)\n        _save(self._remotes_file, remotes)\n\n    def remove(self, pattern):\n        \"\"\"\n        Remove the remotes matching the ``pattern``\n\n        :param pattern: single ``str`` or list of ``str``. If the pattern is an exact name without\n          wildcards like \"*\" and no remote is found matching that exact name, it will raise an error.\n        :return: The list of removed :ref:`Remote <conan.api.model.Remote>` objects\n        \"\"\"\n        remotes = _load(self._remotes_file)\n        removed = _filter(remotes, pattern, only_enabled=False)\n        remotes = [r for r in remotes if r not in removed]\n        _save(self._remotes_file, remotes)\n        localdb = LocalDB(self._home_folder)\n        for remote in removed:\n            remove_local_recipes_index_remote(self._home_folder, remote)\n            localdb.clean(remote_url=remote.url)\n        return removed\n\n    def update(self, remote_name: str, url=None, secure=None, disabled=None, index=None,\n               allowed_packages=None, recipes_only=None):\n        \"\"\"\n        Update an existing remote\n\n        :param remote_name: The name of the remote to update, must exist\n        :param url: optional url to update, if not defined it will not be updated\n        :param secure:  optional ssl secure connection to update\n        :param disabled: optional disabled state\n        :param index:  optional integer to change the order of the remote\n        :param allowed_packages: optional list of packages allowed from this remote\n        :param recipes_only: optional boolean to only allow recipe downloads from this remote,\n            never package binaries\n        \"\"\"\n        remotes = _load(self._remotes_file)\n        try:\n            remote = {r.name: r for r in remotes}[remote_name]\n        except KeyError:\n            raise ConanException(f\"Remote '{remote_name}' doesn't exist\")\n        if url is not None:\n            if remote.remote_type != LOCAL_RECIPES_INDEX:\n                _validate_url(url)\n            _check_urls(remotes, url, force=False, current=remote)\n            remote.url = url\n        if secure is not None:\n            remote.verify_ssl = secure\n        if disabled is not None:\n            remote.disabled = disabled\n        if allowed_packages is not None:\n            remote.allowed_packages = allowed_packages\n        if recipes_only is not None:\n            remote.recipes_only = recipes_only\n\n        if index is not None:\n            remotes = [r for r in remotes if r.name != remote.name]\n            remotes.insert(index, remote)\n        _save(self._remotes_file, remotes)\n\n    def rename(self, remote_name: str, new_name: str):\n        \"\"\"\n        Change the name of an existing remote\n\n        :param remote_name: The previous existing name\n        :param new_name: The new name\n        \"\"\"\n        remotes = _load(self._remotes_file)\n        d = {r.name: r for r in remotes}\n        if new_name in d:\n            raise ConanException(f\"Remote '{new_name}' already exists\")\n        try:\n            d[remote_name].name = new_name\n        except KeyError:\n            raise ConanException(f\"Remote '{remote_name}' doesn't exist\")\n        _save(self._remotes_file, remotes)\n\n    def user_info(self, remote: Remote):\n        # TODO: Review\n        localdb = LocalDB(self._home_folder)\n        user_info = {}\n        user, token, _ = localdb.get_login(remote.url)\n        user_info[\"name\"] = remote.name\n        user_info[\"user_name\"] = user\n        user_info[\"authenticated\"] = True if token else False\n        return user_info\n\n    def user_login(self, remote: Remote, username: str, password: str):\n        \"\"\"\n        Perform user authentication against the given remote with the provided username and password\n\n        :param remote: a :ref:`Remote <conan.api.model.Remote>` object\n        :param username: the user login as ``str``\n        :param password: password ``str``\n        \"\"\"\n        self._api_helpers.remote_manager.authenticate(remote, username, password)\n\n    def login(self, remotes, username=None, password=None):\n        creds = RemoteCredentials(self._conan_api.cache_folder, self._api_helpers.global_conf)\n\n        ret = OrderedDict()\n        for r in remotes:\n            previous_info = self.user_info(r)\n\n            if username is not None and password is not None:\n                user, password = username, password\n            else:\n                user, password, _ = creds.auth(r, username)\n                if username is not None and username != user:\n                    raise ConanException(f\"User '{username}' doesn't match user '{user}' in \"\n                                         f\"credentials.json or environment variables\")\n\n            self.user_login(r, user, password)\n            info = self.user_info(r)\n            ret[r.name] = {\"previous_info\": previous_info, \"info\": info}\n        return ret\n\n    def user_logout(self, remote: Remote):\n        \"\"\"\n        Logout from the given :ref:`Remote <conan.api.model.Remote>`\n\n        :param remote: The :ref:`Remote <conan.api.model.Remote>` object to logout\n        \"\"\"\n        localdb = LocalDB(self._home_folder)\n        # The localdb only stores url + username + token, not remote name, so use URL as key\n        localdb.clean(remote_url=remote.url)\n\n    def user_set(self, remote: Remote, username):\n        # TODO: Review\n        localdb = LocalDB(self._home_folder)\n        if username == \"\":\n            username = None\n        localdb.store(username, token=None, refresh_token=None, remote_url=remote.url)\n\n    def user_auth(self, remote: Remote, with_user=False, force=False):\n        # TODO: Review\n        localdb = LocalDB(self._home_folder)\n        if with_user:\n            user, token, _ = localdb.get_login(remote.url)\n            if not user:\n                var_name = f\"CONAN_LOGIN_USERNAME_{remote.name.replace('-', '_').upper()}\"\n                user = os.getenv(var_name, None) or os.getenv(\"CONAN_LOGIN_USERNAME\", None)\n            if not user:\n                return\n        self._api_helpers.remote_manager.check_credentials(remote, force)\n        user, token, _ = localdb.get_login(remote.url)\n        return user\n\n\ndef _load(remotes_file):\n    if not os.path.exists(remotes_file):\n        remote = Remote(CONAN_CENTER_REMOTE_NAME, \"https://center2.conan.io\", True, False)\n        _save(remotes_file, [remote])\n        return [remote]\n\n    try:\n        data = json.loads(load(remotes_file))\n    except Exception as e:\n        raise ConanException(f\"Error loading JSON remotes file '{remotes_file}': {e}\")\n    result = []\n    for r in data.get(\"remotes\", []):\n        remote = Remote(r[\"name\"], r[\"url\"], r[\"verify_ssl\"], r.get(\"disabled\", False),\n                        r.get(\"allowed_packages\"), r.get(\"remote_type\"),\n                        r.get(\"recipes_only\", False))\n        result.append(remote)\n    return result\n\n\ndef _save(remotes_file, remotes):\n    remote_list = []\n    for r in remotes:\n        remote = {\"name\": r.name, \"url\": r.url, \"verify_ssl\": r.verify_ssl}\n        if r.disabled:\n            remote[\"disabled\"] = True\n        if r.allowed_packages:\n            remote[\"allowed_packages\"] = r.allowed_packages\n        if r.remote_type:\n            remote[\"remote_type\"] = r.remote_type\n        if r.recipes_only:\n            remote[\"recipes_only\"] = r.recipes_only\n        remote_list.append(remote)\n    # This atomic replace avoids a corrupted remotes.json file if this is killed during the process\n    save(remotes_file + \".tmp\", json.dumps({\"remotes\": remote_list}, indent=True))\n    os.replace(remotes_file + \".tmp\", remotes_file)\n\n\ndef _filter(remotes, pattern, only_enabled=True):\n    filtered_remotes = []\n    patterns = [pattern] if isinstance(pattern, str) else pattern\n    for p in patterns:\n        is_match = False\n        for remote in remotes:\n            if fnmatch.fnmatch(remote.name, p):\n                is_match = True\n                if remote not in filtered_remotes:\n                    filtered_remotes.append(remote)\n        if not is_match:\n            if \"*\" in p or \"?\" in p:\n                if only_enabled:\n                    raise ConanException(\n                        f\"Remotes for pattern '{p}' can't be found or are disabled\")\n            else:\n                raise ConanException(f\"Remote '{p}' can't be found or is disabled\")\n    return filtered_remotes\n\n\ndef _validate_url(url):\n    \"\"\" Check if URL contains protocol and address\n    :param url: URL to be validated\n    \"\"\"\n    out = ConanOutput()\n    if url:\n        if url.startswith(\"https://conan.io/center\"):\n            raise ConanException(\"Wrong ConanCenter remote URL. You are adding the web \"\n                                 \"https://conan.io/center the correct remote API is \"\n                                 \"https://center2.conan.io\")\n        address = urlparse(url)\n        if not all([address.scheme, address.netloc]):\n            out.warning(f\"The URL '{url}' is invalid. It must contain scheme and hostname.\")\n    else:\n        out.warning(\"The URL is empty. It must contain scheme and hostname.\")\n\n\ndef _check_urls(remotes, url, force, current):\n    # The remote name doesn't exist\n    for r in remotes:\n        if r is not current and r.url == url:\n            msg = f\"Remote url already existing in remote '{r.name}'. \" \\\n                  f\"Having different remotes with same URL is not recommended.\"\n            if not force:\n                raise ConanException(msg + \" Use '--force' to override.\")\n            else:\n                ConanOutput().warning(msg + \" Adding duplicated remote url because '--force'.\")\n"
  },
  {
    "path": "conan/api/subapi/remove.py",
    "content": "from typing import Optional\n\nfrom conan.api.model import Remote\nfrom conan.api.model import PkgReference\nfrom conan.api.model import RecipeReference\n\n\nclass RemoveAPI:\n\n    def __init__(self, conan_api, api_helpers):\n        self._conan_api = conan_api\n        self._api_helpers = api_helpers\n\n    def recipe(self, ref: RecipeReference, remote: Optional[Remote] = None):\n        assert ref.revision, \"Recipe revision cannot be None to remove a recipe\"\n        \"\"\"Removes the recipe (or recipe revision if present) and all the packages (with all prev)\"\"\"\n\n        if remote:\n            self._api_helpers.remote_manager.remove_recipe(ref, remote)\n        else:\n            self.all_recipe_packages(ref)\n            recipe_layout = self._api_helpers.cache.recipe_layout(ref)\n            self._api_helpers.cache.remove_recipe_layout(recipe_layout)\n\n    def all_recipe_packages(self, ref: RecipeReference, remote: Optional[Remote] = None):\n        assert ref.revision, \"Recipe revision cannot be None to remove a recipe\"\n        \"\"\"Removes all the packages from the provided reference\"\"\"\n\n        if remote:\n            self._api_helpers.remote_manager.remove_all_packages(ref, remote)\n        else:\n            # Remove all the prefs with all the prevs\n            self._remove_all_local_packages(ref)\n\n    def _remove_all_local_packages(self, ref):\n        # Get all the prefs and all the prevs\n        pkg_ids = self._api_helpers.cache.get_package_references(ref, only_latest_prev=False)\n        for pref in pkg_ids:\n            package_layout = self._api_helpers.cache.pkg_layout(pref)\n            self._api_helpers.cache.remove_package_layout(package_layout)\n\n    def package(self, pref: PkgReference, remote: Optional[Remote]):\n        assert pref.ref.revision, \"Recipe revision cannot be None to remove a package\"\n        assert pref.revision, \"Package revision cannot be None to remove a package\"\n\n        if remote:\n            # FIXME: Create a \"packages\" method to optimize remote remove?\n            self._api_helpers.remote_manager.remove_packages([pref], remote)\n        else:\n            package_layout = self._api_helpers.cache.pkg_layout(pref)\n            self._api_helpers.cache.remove_package_layout(package_layout)\n"
  },
  {
    "path": "conan/api/subapi/report.py",
    "content": "import base64\nimport os\nfrom io import StringIO\n\nfrom conan.api.output import ConanOutput\nfrom conan.errors import ConanException\nfrom conan.api.model import RecipeReference\nfrom conan.internal.conan_app import ConanApp\nfrom conan.internal.errors import conanfile_exception_formatter\nfrom conan.internal.graph.graph import CONTEXT_HOST\nfrom conan.internal.graph.profile_node_definer import initialize_conanfile_profile\nfrom conan.internal.source import config_source\nfrom conan.internal.util.runners import conan_run\n\n\nclass ReportAPI:\n    \"\"\" Used to compute the differences (the \"diff\") between two versions or revisions, for\n    both the recipe and source code.\n    \"\"\"\n    def __init__(self, conan_api, helpers):\n        self._conan_api = conan_api\n        self._helpers = helpers\n\n    def diff(self, old_reference, new_reference, remotes, old_path=None, new_path=None, cwd=None):\n        \"\"\"\n        Compare two recipes and return the differences.\n\n        :param old_reference: The reference of the old recipe.\n        :param new_reference: The reference of the new recipe.\n        :param remotes: List of remotes to search for the recipes.\n        :param old_path: Optional path to the old recipe's conanfile.py.\n        :param new_path: Optional path to the new recipe's conanfile.py.\n        :param cwd: Current working directory, used to resolve paths.\n        :return: A dictionary with the differences between the two recipes.\n        \"\"\"\n\n        def _source(path_to_conanfile, reference):\n            if path_to_conanfile is None:\n                export_ref, cache_path = _get_ref_from_cache_or_remote(self._conan_api, reference,\n                                                                       remotes)\n            else:\n                export_ref, cache_path = _export_recipe_from_path(self._conan_api, path_to_conanfile,\n                                                                  reference, remotes, cwd)\n            exported_path = self._conan_api.local.get_conanfile_path(cache_path, cwd, py=True)\n            _configure_source(self._conan_api, self._helpers.hook_manager, exported_path, export_ref,\n                              remotes)\n            return export_ref, cache_path\n\n        old_export_ref, old_cache_path = _source(old_path, old_reference)\n        new_export_ref, new_cache_path = _source(new_path, new_reference)\n\n        old_diff_path = os.path.abspath(os.path.join(old_cache_path, os.path.pardir)).replace(\"\\\\\",\n                                                                                              \"/\")\n        new_diff_path = os.path.abspath(os.path.join(new_cache_path, os.path.pardir)).replace(\"\\\\\",\n                                                                                              \"/\")\n\n        src_prefix = base64.b64encode(str(new_export_ref.repr_notime()).encode()).decode() + \"/\"\n        dst_prefix = base64.b64encode(str(old_export_ref.repr_notime()).encode()).decode() + \"/\"\n\n        command = (f'git diff --no-index --src-prefix \"{src_prefix}\" --dst-prefix \"{dst_prefix}\" '\n                   f'\"{old_diff_path}\" \"{new_diff_path}\"')\n\n        ConanOutput().info(\n            f\"Generating diff from {old_export_ref.repr_notime()} to {new_export_ref.repr_notime()} \"\n            f\"(this might take a while)\")\n        ConanOutput().info(command)\n\n        stdout, stderr = StringIO(), StringIO()\n        conan_run(command, stdout=stdout, stderr=stderr)\n        diff = stdout.getvalue()\n\n        if old_path:\n            self._conan_api.remove.recipe(old_export_ref)\n        if new_path:\n            self._conan_api.remove.recipe(new_export_ref)\n\n        return {\n            \"diff\": diff,\n            \"old_export_ref\": old_export_ref,\n            \"new_export_ref\": new_export_ref,\n            \"old_cache_path\": old_diff_path,\n            \"new_cache_path\": new_diff_path,\n            \"src_prefix\": src_prefix,\n            \"dst_prefix\": dst_prefix,\n        }\n\n\ndef _configure_source(conan_api, hook_manager, conanfile_path, ref, remotes):\n    app = ConanApp(conan_api)\n    conanfile = app.loader.load_consumer(conanfile_path, name=ref.name, version=str(ref.version),\n                                         user=ref.user, channel=ref.channel, graph_lock=None,\n                                         remotes=remotes)\n    # This profile is empty, but with the conf from global.conf\n    profile = conan_api.profiles.get_profile([])\n    initialize_conanfile_profile(conanfile, profile, profile, CONTEXT_HOST, False)\n    # This is important, otherwise the ``conan source`` doesn't define layout and fails\n    if hasattr(conanfile, \"layout\"):\n        with conanfile_exception_formatter(conanfile, \"layout\"):\n            conanfile.layout()\n\n    cache = conan_api._api_helpers.cache # noqa\n    recipe_layout = cache.recipe_layout(ref)\n    export_source_folder = recipe_layout.export_sources()\n    source_folder = recipe_layout.source()\n\n    conanfile.folders.set_base_source(source_folder)\n    conanfile.folders.set_base_export_sources(export_source_folder)\n    conanfile.folders.set_base_recipe_metadata(recipe_layout.metadata())\n    config_source(export_source_folder, conanfile, hook_manager)\n\n\ndef _get_ref_from_cache_or_remote(conan_api, reference, enabled_remotes):\n    ref = RecipeReference.loads(reference)\n    full_ref, matching_remote = None, False\n    # The first remote is None, which means local cache for the list subapi methods\n    for remote in [None] + enabled_remotes:\n        if ref.revision:\n            no_rrev_ref = RecipeReference.loads(reference)\n            no_rrev_ref.revision = None\n            try:\n                remote_revisions = conan_api.list.recipe_revisions(no_rrev_ref, remote)\n                if ref in remote_revisions:\n                    full_ref = ref\n                    matching_remote = remote\n                    break\n            except (Exception,):\n                continue\n        else:\n            try:\n                latest_recipe_revision = conan_api.list.latest_recipe_revision(ref, remote)\n            except (Exception,):\n                continue\n            if full_ref is None or (latest_recipe_revision.timestamp > full_ref.timestamp):\n                full_ref = latest_recipe_revision\n                matching_remote = remote\n    if full_ref is None or matching_remote is False:\n        raise ConanException(f\"No matching reference for {reference} in remotes.\\n\"\n                             \"If you want to check against a local recipe, add an \"\n                             \"additional --{old,new}-path arg.\\n\")\n    if matching_remote is not None:\n        conan_api.download.recipe(full_ref, matching_remote)\n    cache_path = conan_api.cache.export_path(full_ref)\n    return full_ref, cache_path\n\n\ndef _export_recipe_from_path(conan_api, path_to_conanfile, reference, enabled_remotes, cwd=None):\n    path = conan_api.local.get_conanfile_path(path_to_conanfile, cwd, py=True)\n    ref = RecipeReference.loads(reference)\n    export_ref, conanfile = conan_api.export.export(path=path,\n                                                    name=ref.name, version=str(ref.version),\n                                                    user=ref.user, channel=ref.channel,\n                                                    lockfile=None,\n                                                    remotes=enabled_remotes)\n    cache_path = conan_api.cache.export_path(export_ref)\n    return export_ref, cache_path\n"
  },
  {
    "path": "conan/api/subapi/upload.py",
    "content": "import os\nimport time\nfrom multiprocessing.pool import ThreadPool\nfrom typing import List\n\nfrom conan.api.model import PackagesList, Remote\nfrom conan.api.output import ConanOutput\nfrom conan.internal.api.upload import add_urls\nfrom conan.internal.conan_app import ConanApp\nfrom conan.internal.api.uploader import PackagePreparator, UploadExecutor, UploadUpstreamChecker\nfrom conan.internal.rest.pkg_sign import PkgSignaturesPlugin\nfrom conan.internal.rest.file_uploader import FileUploader\nfrom conan.internal.errors import AuthenticationException, ForbiddenException\nfrom conan.errors import ConanException\n\n\nclass UploadAPI:\n    \"\"\" This API is used to upload recipes and packages to a remote server.\"\"\"\n\n    def __init__(self, conan_api, api_helpers):\n        self._conan_api = conan_api\n        self._api_helpers = api_helpers\n\n    def check_upstream(self, package_list: PackagesList, remote: Remote,\n                       enabled_remotes: List[Remote], force=False):\n        \"\"\" Checks ``remote`` for the existence of the recipes and packages in ``package_list``.\n        Items that are not present in the remote will add an ``upload`` key to the entry\n        with the value ``True``.\n\n        If the recipe has an upload policy of ``skip``, it will be discarded from the upload list.\n\n        :parameter package_list: A ``PackagesList`` object with the recipes and packages to check.\n        :parameter remote: Remote to check.\n        :parameter enabled_remotes: List of enabled remotes. This is used to possibly load\n            python_requires from the listed recipes if necessary.\n        :parameter force: If ``True``, it will skip the check and mark that all items need to be\n            uploaded. A ``force_upload`` key will be added to the entries that will be uploaded.\n        \"\"\"\n        app = ConanApp(self._conan_api)\n        for ref, _ in package_list.items():\n            layout = self._api_helpers.cache.recipe_layout(ref)\n            conanfile_path = layout.conanfile()\n            conanfile = app.loader.load_basic(conanfile_path, remotes=enabled_remotes)\n            if conanfile.upload_policy == \"skip\":\n                ConanOutput().info(f\"{ref}: Skipping upload of binaries, \"\n                                   \"because upload_policy='skip'\")\n                package_list.recipe_dict(ref)[\"packages\"] = {}\n\n        UploadUpstreamChecker(self._api_helpers.remote_manager).check(package_list, remote, force)\n\n    def prepare(self, package_list: PackagesList, enabled_remotes: List[Remote],\n                metadata: List[str] = None):\n        \"\"\"Compress the recipes and packages and fill the upload_data objects\n        with the complete information. It doesn't perform the upload nor checks upstream to see\n        if the recipe is still there\n\n        :param package_list: A PackagesList object with the recipes and packages to upload.\n        :param enabled_remotes: A list of remotes that are enabled in the client.\n            Recipe sources will attempt to be fetched from these remotes.\n        :param metadata: A list of patterns of metadata that should be uploaded.\n            Default ``None`` means all metadata will be uploaded together with the package artifacts.\n            If metadata contains an empty string (``\"\"``),\n            it means that no metadata files should be uploaded.\"\"\"\n        if metadata and metadata != [''] and '' in metadata:\n            raise ConanException(\"Empty string and patterns can not be mixed for metadata.\")\n        app = ConanApp(self._conan_api)\n        preparator = PackagePreparator(app, self._api_helpers.cache,\n                                       self._api_helpers.remote_manager,\n                                       self._api_helpers.global_conf)\n        preparator.prepare(package_list, enabled_remotes, metadata)\n        signer = PkgSignaturesPlugin(self._api_helpers.cache, self._conan_api.home_folder)\n        if signer.is_sign_configured:\n            ConanOutput().warning(\"[Package sign] Implicitly signing packages in the upload \"\n                                  \"command has been removed. Use 'conan cache sign' command before \"\n                                  \"uploading instead.\", warn_tag=\"deprecated\")\n\n    def _upload(self, package_list, remote):\n        self._api_helpers.remote_manager.check_credentials(remote)\n        executor = UploadExecutor(self._api_helpers.remote_manager)\n        executor.upload(package_list, remote)\n\n    def upload_full(self, package_list: PackagesList, remote: Remote, enabled_remotes: List[Remote],\n                    check_integrity=False, force=False, metadata: List[str] = None, dry_run=False):\n        \"\"\" Does the whole process of uploading, including the possibility of parallelizing\n        per recipe based on the ``core.upload:parallel`` conf.\n\n        The steps that this method performs are:\n            - calls ``conan_api.cache.check_integrity`` to ensure the packages are not corrupted\n            - checks the upload policy of the recipes\n                - (if it is ``\"skip\"``, it will not upload the binaries, but will still upload\n                  the metadata)\n            - checks which revisions already exist in the server so that it can skip the upload\n            - prepares the artifacts to upload (compresses the conan_package.tgz)\n            - executes the actual upload\n            - uploads associated sources backups if any\n\n        :param package_list: A PackagesList object with the recipes and packages to upload.\n        :param remote: The remote to upload the packages to.\n        :param enabled_remotes: A list of remotes that are enabled in the client.\n            Recipe sources will attempt to be fetched from these remotes,\n            and to possibly load python_requires from the listed recipes if necessary.\n        :param check_integrity: If ``True``, it will check the integrity of the cache packages\n            before uploading them. This is useful to ensure that the packages are not corrupted.\n        :param force: If ``True``, it will force the upload of the recipes and packages,\n            even if they already exist in the remote. Note that this might update the timestamps\n        :param metadata: A list of patterns of metadata that should be uploaded.\n            Default ``None`` means all metadata will be uploaded together with the package artifacts.\n            If metadata contains an empty string (``\"\"``),\n            it means that no metadata files should be uploaded.\n        :param dry_run: If ``True``, it will not perform the actual upload,\n            but will still prepare the artifacts and check the upstream.\n        \"\"\"\n\n        def _upload_pkglist(pkglist, subtitle=lambda _: None):\n            if check_integrity:\n                subtitle(\"Checking integrity of cache packages\")\n                self._conan_api.cache.check_integrity(pkglist)\n            # Check if the recipes/packages are in the remote\n            subtitle(\"Checking server for existing packages\")\n            self.check_upstream(pkglist, remote, enabled_remotes, force)\n            subtitle(\"Preparing artifacts for upload\")\n            self.prepare(pkglist, enabled_remotes, metadata)\n\n            if not dry_run:\n                subtitle(\"Uploading artifacts\")\n                self._upload(pkglist, remote)\n                backup_files = self._conan_api.cache.get_backup_sources(pkglist)\n                self.upload_backup_sources(backup_files)\n\n        t = time.time()\n        ConanOutput().title(f\"Uploading to remote {remote.name}\")\n        parallel = self._conan_api.config.get(\"core.upload:parallel\", default=1, check_type=int)\n        thread_pool = ThreadPool(parallel) if parallel > 1 else None\n        if not thread_pool or len(package_list._data) <= 1:  # FIXME: Iteration when multiple rrevs\n            _upload_pkglist(package_list, subtitle=ConanOutput().subtitle)\n        else:\n            ConanOutput().subtitle(f\"Uploading with {parallel} parallel threads\")\n            thread_pool.map(_upload_pkglist, package_list.split())\n        if thread_pool:\n            thread_pool.close()\n            thread_pool.join()\n        elapsed = time.time() - t\n        ConanOutput().success(f\"Upload completed in {int(elapsed)}s\\n\")\n        add_urls(package_list, remote)\n\n    def upload_backup_sources(self, files: List) -> None:\n        \"\"\"\n        Upload to the server the backup sources files, that have been typically gathered by\n        CacheAPI.get_backup_sources()\n\n        :param files: The list of files that must be uploaded\n        \"\"\"\n        config = self._api_helpers.global_conf\n        url = config.get(\"core.sources:upload_url\", check_type=str)\n        if url is None:\n            return\n        url = url if url.endswith(\"/\") else url + \"/\"\n\n        output = ConanOutput()\n        output.subtitle(\"Uploading backup sources\")\n        if not files:\n            output.info(\"No backup sources files to upload\")\n            return\n\n        requester = self._api_helpers.requester\n        uploader = FileUploader(requester, verify=True, config=config, source_credentials=True)\n        # TODO: For Artifactory, we can list all files once and check from there instead\n        #  of 1 request per file, but this is more general\n        for file in files:\n            basename = os.path.basename(file)\n            full_url = url + basename\n            is_summary = file.endswith(\".json\")\n            file_kind = \"summary\" if is_summary else \"file\"\n            try:\n                if is_summary or not uploader.exists(full_url, auth=None):\n                    output.info(f\"Uploading {file_kind} '{basename}' to backup sources server\")\n                    uploader.upload(full_url, file, dedup=False, auth=None)\n                else:\n                    output.info(f\"File '{basename}' already in backup sources server, \"\n                                \"skipping upload\")\n            except (AuthenticationException, ForbiddenException) as e:\n                if is_summary:\n                    output.warning(f\"Could not update summary '{basename}' in backup sources server. \"\n                                   \"Skipping updating file but continuing with upload. \"\n                                   f\"Missing permissions?: {e}\")\n                else:\n                    raise ConanException(f\"Authentication to source backup server '{url}' failed, \"\n                                         f\"please check your 'source_credentials.json': {e}\")\n\n        output.success(\"Upload backup sources complete\\n\")\n"
  },
  {
    "path": "conan/api/subapi/workspace.py",
    "content": "import inspect\nimport os\nimport shutil\nimport textwrap\nfrom pathlib import Path\n\nfrom conan import ConanFile\nfrom conan.api.model import RecipeReference\nfrom conan.api.output import ConanOutput\nfrom conan.cli import make_abs_path\nfrom conan.cli.printers.graph import print_graph_basic, print_graph_packages\nfrom conan.errors import ConanException\nfrom conan.internal.conan_app import ConanApp\nfrom conan.internal.errors import conanfile_exception_formatter\nfrom conan.internal.graph.install_graph import ProfileArgs\nfrom conan.internal.methods import auto_language, auto_shared_fpic_config_options, \\\n    auto_shared_fpic_configure\nfrom conan.internal.model.options import Options\nfrom conan.internal.model.workspace import Workspace, WORKSPACE_YML, WORKSPACE_PY, WORKSPACE_FOLDER\nfrom conan.tools.scm import Git\nfrom conan.internal.graph.graph import (RECIPE_EDITABLE, DepsGraph, CONTEXT_HOST, RECIPE_VIRTUAL,\n                                        Node, RECIPE_CONSUMER)\nfrom conan.internal.graph.graph import TransitiveRequirement\nfrom conan.internal.graph.profile_node_definer import consumer_definer, initialize_conanfile_profile\nfrom conan.internal.loader import load_python_file\nfrom conan.internal.source import retrieve_exports_sources\nfrom conan.internal.util.files import merge_directories, save\n\n\ndef _find_ws_folder():\n    path = Path(os.getcwd())\n    while path.is_dir() and len(path.parts) > 1:  # finish at '/' or 'conanws/'\n        if path.name == WORKSPACE_FOLDER:\n            if (path / WORKSPACE_YML).is_file() or (path / WORKSPACE_PY).is_file():\n                return str(path)\n        if (path / WORKSPACE_YML).is_file() or (path / WORKSPACE_PY).is_file():\n            return str(path)\n        else:\n            path = path.parent\n\n\ndef _load_workspace(ws_folder, conan_api):\n    \"\"\" loads a conanfile basic object without evaluating anything, returns the module too\n    \"\"\"\n    wspy = os.path.join(ws_folder, WORKSPACE_PY)\n    if not os.path.isfile(wspy):\n        ConanOutput().info(f\"{WORKSPACE_PY} doesn't exist in {ws_folder}, using default behavior\")\n        assert os.path.exists(os.path.join(ws_folder, WORKSPACE_YML))\n        ws = Workspace(ws_folder, conan_api)\n    else:\n        try:\n            module, module_id = load_python_file(wspy)\n            ws = _parse_module(module, module_id)\n            ws = ws(ws_folder, conan_api)\n        except ConanException as e:\n            raise ConanException(f\"Error loading {WORKSPACE_PY} at '{wspy}': {e}\")\n    return ws\n\n\ndef _parse_module(conanfile_module, module_id):\n    result = None\n    for name, attr in conanfile_module.__dict__.items():\n        if (name.startswith(\"_\") or not inspect.isclass(attr) or\n                attr.__dict__.get(\"__module__\") != module_id):\n            continue\n\n        if issubclass(attr, Workspace) and attr != Workspace:\n            if result is None:\n                result = attr\n            else:\n                raise ConanException(\"More than 1 Workspace in the file\")\n\n    if result is None:\n        raise ConanException(\"No subclass of Workspace\")\n\n    return result\n\n\nclass WorkspaceAPI:\n    TEST_ENABLED = False\n\n    def __init__(self, conan_api):\n        self._enabled = True\n        self._conan_api = conan_api\n        self._folder = _find_ws_folder()\n        if self._folder:\n            ConanOutput().warning(f\"Workspace found: {self._folder}\")\n            if (WorkspaceAPI.TEST_ENABLED or os.getenv(\"CONAN_WORKSPACE_ENABLE\")) != \"will_break_next\":\n                ConanOutput().warning(\"Workspace ignored as CONAN_WORKSPACE_ENABLE is not set\")\n                self._folder = None\n            else:\n                ConanOutput().warning(f\"Workspace is a dev-only feature, exclusively for testing\")\n                self._ws = _load_workspace(self._folder, conan_api)  # Error if not loading\n\n    def enable(self, value):\n        self._enabled = value\n\n    def name(self):\n        self._check_ws()\n        return self._ws.name()\n\n    def folder(self):\n        \"\"\"\n        @return: the current workspace folder where the conanws.yml or conanws.py is located\n        \"\"\"\n        self._check_ws()\n        return self._folder\n\n    def packages(self):\n        \"\"\"\n        @return: Returns {RecipeReference: {\"path\": full abs-path, \"output_folder\": abs-path}}\n        \"\"\"\n        if not self._folder or not self._enabled:\n            return\n        packages = {}\n        for editable_info in self._ws.packages():\n            rel_path = editable_info[\"path\"]\n            path = os.path.normpath(os.path.join(self._folder, rel_path, \"conanfile.py\"))\n            if not os.path.isfile(path):\n                raise ConanException(f\"Workspace package not found: {path}\")\n            ref = editable_info.get(\"ref\")\n            try:\n                if ref is None:\n                    conanfile = self._ws.load_conanfile(rel_path)\n                    reference = RecipeReference(name=conanfile.name, version=conanfile.version,\n                                                user=conanfile.user, channel=conanfile.channel)\n                else:\n                    reference = RecipeReference.loads(ref)\n                reference.validate_ref(reference)\n            except Exception as e:\n                raise ConanException(f\"Workspace package reference could not be deduced by\"\n                                     f\" {rel_path}/conanfile.py or it is not\"\n                                     f\" correctly defined in the conanws.yml file: {e}\")\n            if reference in packages:\n                raise ConanException(f\"Workspace package '{str(reference)}' already exists.\")\n            packages[reference] = {\"path\": path}\n            if editable_info.get(\"output_folder\"):\n                packages[reference][\"output_folder\"] = (\n                    os.path.normpath(os.path.join(self._folder, editable_info[\"output_folder\"]))\n                )\n        return packages\n\n    def open(self, ref, remotes, cwd=None):\n        cwd = cwd or os.getcwd()\n        app = ConanApp(self._conan_api)\n        ref = RecipeReference.loads(ref) if isinstance(ref, str) else ref\n        recipe = app.proxy.get_recipe(ref, remotes, update=False, check_update=False)\n\n        layout, recipe_status, remote = recipe\n        if recipe_status == RECIPE_EDITABLE:\n            raise ConanException(f\"Can't open a dependency that is already an editable: {ref}\")\n        ref = layout.reference\n        conanfile_path = layout.conanfile()\n        conanfile, module = app.loader.load_basic_module(conanfile_path, remotes=remotes)\n\n        scm = conanfile.conan_data.get(\"scm\") if conanfile.conan_data else None\n        dst_path = os.path.join(cwd, ref.name)\n        if scm is None:\n            conanfile.output.warning(\"conandata doesn't contain 'scm' information\\n\"\n                                     \"doing a local copy!!!\")\n            shutil.copytree(layout.export(), dst_path)\n            remote_manager = self._conan_api._api_helpers.remote_manager # noqa\n            retrieve_exports_sources(remote_manager, layout, conanfile, ref, remotes)\n            export_sources = layout.export_sources()\n            if os.path.exists(export_sources):\n                conanfile.output.warning(\"There are export-sources, copying them, but the location\"\n                                         \" might be incorrect, use 'scm' approach\")\n                merge_directories(export_sources, dst_path)\n        else:\n            git = Git(conanfile, folder=cwd)\n            git.clone(url=scm[\"url\"], target=ref.name)\n            git.folder = ref.name  # change to the cloned folder\n            git.checkout(commit=scm[\"commit\"])\n        return dst_path\n\n    def _check_ws(self):\n        if not self._folder:\n            raise ConanException(f\"Workspace not defined, please create a \"\n                                 f\"'{WORKSPACE_PY}' or '{WORKSPACE_YML}' file\")\n\n    def add(self, path, name=None, version=None, user=None, channel=None, cwd=None,\n            output_folder=None, remotes=None):\n        \"\"\"\n        Add a new editable package to the current workspace (the current workspace must exist)\n        @param path: The path to the folder containing the conanfile.py that defines the package\n        @param name: (optional) The name of the package to be added if not defined in recipe\n        @param version:\n        @param user:\n        @param channel:\n        @param cwd:\n        @param output_folder:\n        @param remotes:\n        @return: The reference of the added package\n        \"\"\"\n        self._check_ws()\n        full_path = self._conan_api.local.get_conanfile_path(path, cwd, py=True)\n        app = ConanApp(self._conan_api)\n        conanfile = app.loader.load_named(full_path, name, version, user, channel, remotes=remotes)\n        if conanfile.name is None or conanfile.version is None:\n            raise ConanException(\"Editable package recipe should declare its name and version\")\n        ref = RecipeReference(conanfile.name, conanfile.version, conanfile.user, conanfile.channel)\n        ref.validate_ref()\n        output_folder = make_abs_path(output_folder) if output_folder else None\n        # Check the conanfile is there, and name/version matches\n        self._ws.add(ref, full_path, output_folder)\n        return ref\n\n    def complete(self, profile_host, profile_build, lockfile, remotes, update):\n        packages = self.packages()\n        if not packages:\n            ConanOutput().info(\"There are no packages in this workspace, nothing to complete\")\n            return\n\n        for ref, info in packages.items():\n            ConanOutput().title(f\"Computing the dependency graph for package: {ref}\")\n            gapi = self._conan_api.graph\n            deps_graph = gapi.load_graph_requires([ref], None, profile_host, profile_build,\n                                                  lockfile, remotes, update)\n            deps_graph.report_graph_error()\n            print_graph_basic(deps_graph)\n\n            nodes_to_complete = []\n            for node in deps_graph.nodes[1:]:  # Exclude the current virtual root\n                if node.recipe != RECIPE_EDITABLE:\n                    # sanity check, a pacakge in the cache cannot have dependencies to the workspace\n                    if any(d.node.recipe == RECIPE_EDITABLE for d in node.transitive_deps.values()):\n                        nodes_to_complete.append(node)\n\n            if not nodes_to_complete:\n                ConanOutput().info(\"There are no intermediate packages to add to the workspace\")\n                return\n\n            for node in nodes_to_complete:\n                full_path = os.path.join(self._folder, node.name, \"conanfile.py\")\n                dep_ref = node.ref\n                ConanOutput().info(f\"Adding to workspace {dep_ref}\")\n                try:\n                    self._ws.add(dep_ref, full_path, output_folder=None)\n                except ConanException:\n                    if os.path.isfile(full_path):\n                        raise\n                    ConanOutput().info(f\"Conanfile in {node.name} not found, trying \"\n                                       \"to open it first\")\n                    self.open(dep_ref, remotes, cwd=self._folder)\n                    self._ws.add(dep_ref, full_path, output_folder=None)\n\n    @staticmethod\n    def init(path):\n        abs_path = make_abs_path(path)\n        os.makedirs(abs_path, exist_ok=True)\n        ws_yml_file = Path(abs_path, WORKSPACE_YML)\n        ws_py_file = Path(abs_path, WORKSPACE_PY)\n        if not ws_yml_file.exists():\n            ConanOutput().success(f\"Created empty {WORKSPACE_YML} in {path}\")\n            save(ws_yml_file, \"\")\n        if not ws_py_file.exists():\n            ConanOutput().success(f\"Created minimal {WORKSPACE_PY} in {path}\")\n            ws_name = os.path.basename(abs_path)\n            save(ws_py_file, textwrap.dedent(f'''\\\n            from conan import Workspace\n\n            class MyWorkspace(Workspace):\n               \"\"\"\n               Minimal Workspace class definition.\n               More info: https://docs.conan.io/2/incubating.html#workspaces\n               \"\"\"\n               def name(self):\n                  return \"{ws_name}\"\n            '''))\n\n    def remove(self, path):\n        self._check_ws()\n        return self._ws.remove(path)\n\n    def clean(self):\n        self._check_ws()\n        return self._ws.clean()\n\n    def info(self):\n        self._check_ws()\n        return {\"name\": self._ws.name(),\n                \"folder\": self._folder,\n                \"packages\": self._ws.packages()}\n\n    @staticmethod\n    def _init_options(conanfile, options):\n        if hasattr(conanfile, \"config_options\"):\n            with conanfile_exception_formatter(conanfile, \"config_options\"):\n                conanfile.config_options()\n        elif \"auto_shared_fpic\" in conanfile.implements:\n            auto_shared_fpic_config_options(conanfile)\n\n        auto_language(conanfile)  # default implementation removes `compiler.cstd`\n\n        # Assign only the current package options values, but none of the dependencies\n        conanfile.options.apply_downstream(Options(), options, None, True)\n\n        if hasattr(conanfile, \"configure\"):\n            with conanfile_exception_formatter(conanfile, \"configure\"):\n                conanfile.configure()\n        elif \"auto_shared_fpic\" in conanfile.implements:\n            auto_shared_fpic_configure(conanfile)\n\n    def super_build_graph(self, deps_graph, profile_host, profile_build):\n        order = []\n        packages = self.packages()\n\n        def find_folder(ref):\n            return next(os.path.dirname(os.path.relpath(p[\"path\"], self._folder)) for p_ref, p in\n                        packages.items() if p_ref == ref)\n\n        for level in deps_graph.by_levels():\n            items = [item for item in level if item.recipe == \"Editable\"]\n            level_order = []\n            for node in items:\n                conanfile = node.conanfile\n                if hasattr(conanfile, \"layout\"):\n                    with conanfile_exception_formatter(conanfile, \"layout\"):\n                        conanfile.layout()\n                base_folder = find_folder(node.ref)\n                src_folder = os.path.normpath(os.path.join(base_folder, conanfile.folders.source))\n                level_order.append({\"ref\": node.ref, \"folder\": src_folder.replace(\"\\\\\", \"/\")})\n            order.append(level_order)\n\n        self._ws.build_order(order)\n\n        ConanOutput().title(\"Collapsing workspace packages\")\n\n        root_class = self._ws.root_conanfile()\n        if root_class is not None:\n            conanfile = root_class(f\"{WORKSPACE_PY} base project Conanfile\")\n            # To inject things like cmd_wrapper to the consumer conanfile, so self.run() works\n            helpers = ConanApp(self._conan_api).loader._conanfile_helpers  # noqa\n            conanfile._conan_helpers = helpers\n            conanfile._conan_is_consumer = True\n            initialize_conanfile_profile(conanfile, profile_build, profile_host, CONTEXT_HOST,\n                                         is_build_require=False)\n            # consumer_definer(conanfile, profile_host, profile_build)\n            self._init_options(conanfile, profile_host.options)\n            for field in (\"requires\", \"build_requires\", \"test_requires\", \"requirements\", \"build\",\n                          \"source\", \"package\"):\n                if getattr(conanfile, field, None):\n                    raise ConanException(f\"Conanfile in conanws.py shouldn't have '{field}'\")\n            root = Node(None, conanfile, context=CONTEXT_HOST, recipe=RECIPE_CONSUMER,\n                        path=self._folder)  # path lets use the conanws.py folder\n            root.should_build = True  # It is a consumer, this is something we are building\n        else:\n            ConanOutput().info(f\"Workspace {WORKSPACE_PY} not found in the workspace folder, \"\n                               \"using default behavior\")\n            conanfile = ConanFile(display_name=\"cli\")\n            consumer_definer(conanfile, profile_host, profile_build)\n            root = Node(ref=None, conanfile=conanfile, context=CONTEXT_HOST, recipe=RECIPE_VIRTUAL)\n\n        result = DepsGraph()  # TODO: We might need to copy more information from the original graph\n        result.add_node(root)\n        conanfile.workspace_packages = {}\n\n        self._check_graph(deps_graph)\n        for node in deps_graph.nodes[1:]:  # Exclude the current root\n            if node.recipe != RECIPE_EDITABLE:\n                result.add_node(node)\n                continue\n            # At the moment we are exposing the full conanfile, docs will warn against usage of\n            # non pure functions\n            conanfile.workspace_packages[node.ref] = node.conanfile\n            for r, t in node.transitive_deps.items():\n                if t.node.recipe == RECIPE_EDITABLE:\n                    continue\n                existing = root.transitive_deps.pop(r, None)\n                if existing is None:\n                    root.transitive_deps[r] = t\n                else:\n                    require = existing.require\n                    require.aggregate(r)\n                    root.transitive_deps[require] = TransitiveRequirement(require, t.node)\n\n        # The graph edges must be defined too\n        for r, t in root.transitive_deps.items():\n            result.add_edge(root, t.node, r)\n\n        return result\n\n    @staticmethod\n    def _check_graph(graph):\n        for node in graph.nodes[1:]:  # Exclude the current root\n            if node.recipe != RECIPE_EDITABLE:\n                # sanity check, a pacakge in the cache cannot have dependencies to the workspace\n                deps_edit = [d.node for d in node.transitive_deps.values()\n                             if d.node.recipe == RECIPE_EDITABLE]\n                if deps_edit:\n                    raise ConanException(f\"Workspace definition error. Package {node} in the \"\n                                         f\"Conan cache has dependencies to packages \"\n                                         f\"in the workspace: {deps_edit}\\n\"\n                                         \"Try the 'conan workspace complete' to open/add \"\n                                         \"intermediate packages\")\n\n    def export(self, lockfile=None, remotes=None):\n        self._check_ws()\n        exported = []\n        for ref, info in self.packages().items():\n            exported_ref = self._conan_api.export.export(info[\"path\"], ref.name, str(ref.version),\n                                                         ref.user, ref.channel,\n                                                         lockfile=lockfile, remotes=remotes)\n            ref, _ = exported_ref\n            exported.append(ref)\n        return exported\n\n    def select_packages(self, packages):\n        self._check_ws()\n        editable = self.packages()\n        packages = packages or []\n        selected_editables = {}\n        for ref, info in editable.items():\n            if packages and not any(ref.matches(p, False) for p in packages):\n                continue\n            selected_editables[ref] = info\n        if not selected_editables:\n            raise ConanException(\"There are no selected packages defined in the workspace\")\n\n        return selected_editables\n\n    def build_order(self, packages, profile_host, profile_build, build_mode, lockfile, remotes,\n                    profile_args, update=False):\n        ConanOutput().title(f\"Computing dependency graph for each package\")\n        conan_api = self._conan_api\n        from conan.internal.graph.install_graph import InstallGraph\n        install_order = InstallGraph(None)\n\n        for ref, info in packages.items():\n            ConanOutput().title(f\"Computing the dependency graph for package: {ref}\")\n\n            deps_graph = conan_api.graph.load_graph_requires([ref], None,\n                                                             profile_host, profile_build, lockfile,\n                                                             remotes, update)\n            deps_graph.report_graph_error()\n            print_graph_basic(deps_graph)\n\n            self._check_graph(deps_graph)\n\n            conan_api.graph.analyze_binaries(deps_graph, build_mode, remotes=remotes, update=update,\n                                             lockfile=lockfile)\n            print_graph_packages(deps_graph)\n\n            ConanOutput().success(f\"\\nAggregating build-order for package: {ref}\")\n            install_graph = InstallGraph(deps_graph, order_by=\"recipe\",\n                                         profile_args=ProfileArgs.from_args(profile_args))\n            install_graph.raise_errors()\n            install_order.merge(install_graph)\n\n        return install_order\n"
  },
  {
    "path": "conan/cli/__init__.py",
    "content": "import os\n\n\ndef make_abs_path(path, cwd=None):\n    \"\"\"convert 'path' to absolute if necessary (could be already absolute)\n    if not defined (empty, or None), will return 'default' one or 'cwd'\n    \"\"\"\n    if path is None:\n        return None\n    if os.path.isabs(path):\n        return path\n    cwd = cwd or os.getcwd()\n    abs_path = os.path.normpath(os.path.join(cwd, path))\n    return abs_path\n"
  },
  {
    "path": "conan/cli/args.py",
    "content": "import argparse\n\nfrom conan.cli.command import OnceArgument\nfrom conan.errors import ConanException\n\n_help_build_policies = '''Optional, specify which packages to build from source. Combining multiple\n    '--build' options on one command line is allowed.\n    Possible values:\n\n    --build=never      Disallow build for all packages, use binary packages or fail if a binary\n                       package is not found, it cannot be combined with other '--build' options.\n    --build=missing    Build packages from source whose binary package is not found.\n    --build=cascade    Build packages from source that have at least one dependency being built from\n                       source.\n    --build=[pattern]  Build packages from source whose package reference matches the pattern. The\n                       pattern uses 'fnmatch' style wildcards, so '--build=\"*\"' will build everything\n                       from source.\n    --build=~[pattern] Excluded packages, which will not be built from the source, whose package\n                       reference matches the pattern. The pattern uses 'fnmatch' style wildcards.\n    --build=missing:[pattern] Build from source if a compatible binary does not exist, only for\n                              packages matching pattern.\n    --build=compatible:[pattern] (Experimental) Build from source if a compatible binary does not\n                                 exist, and the requested package is invalid, the closest package\n                                 binary following the defined compatibility policies (method and\n                                 compatibility.py)\n'''\n\n\ndef add_lockfile_args(parser):\n    group = parser.add_argument_group(\"lockfile arguments\")\n    group.add_argument(\"-l\", \"--lockfile\", action=OnceArgument,\n                       help=\"Path to a lockfile. Use --lockfile=\\\"\\\" to avoid automatic use of \"\n                            \"existing 'conan.lock' file\")\n    group.add_argument(\"--lockfile-partial\", action=\"store_true\",\n                       help=\"Do not raise an error if some dependency is not found in lockfile\")\n    group.add_argument(\"--lockfile-out\", action=OnceArgument,\n                       help=\"Filename of the updated lockfile\")\n    group.add_argument(\"--lockfile-packages\", action=\"store_true\",\n                       help=argparse.SUPPRESS)\n    group.add_argument(\"--lockfile-clean\", action=\"store_true\",\n                       help=\"Remove unused entries from the lockfile\")\n    group.add_argument(\"--lockfile-overrides\",\n                       help=\"Overwrite lockfile overrides\")\n\n\ndef add_common_install_arguments(parser):\n    parser.add_argument(\"-b\", \"--build\", action=\"append\", help=_help_build_policies)\n\n    group = parser.add_argument_group(\"remote arguments\")\n    exclusive_group = group.add_mutually_exclusive_group()\n    exclusive_group.add_argument(\"-r\", \"--remote\", action=\"append\", default=None,\n                                 help='Look in the specified remote or remotes server')\n    exclusive_group.add_argument(\"-nr\", \"--no-remote\", action=\"store_true\",\n                                 help='Do not use remote, resolve exclusively in the cache')\n\n    update_help = (\"Will install newer versions and/or revisions in the local cache \"\n                   \"for the given reference name, or all references in the graph if no argument is supplied. \"\n                   \"When using version ranges, it will install the latest version that \"\n                   \"satisfies the range. It will update to the \"\n                   \"latest revision for the resolved version range.\")\n\n    group.add_argument(\"-u\", \"--update\", action=\"append\", nargs=\"?\", help=update_help, const=\"*\")\n    add_profiles_args(parser)\n\n\ndef add_profiles_args(parser):\n    contexts = [\"build\", \"host\"]\n\n    group = parser.add_argument_group(\"profile arguments\")\n\n    # This comes from the _AppendAction code but modified to add to the contexts\n    class ContextAllAction(argparse.Action):\n\n        def __call__(self, action_parser, namespace, values, option_string=None):\n            for context in contexts:\n                items = getattr(namespace, self.dest + \"_\" + context, None)\n                items = items[:] if items else []\n                items.append(values)\n                setattr(namespace, self.dest + \"_\" + context, items)\n\n    def create_config(short, long, example=None):\n        group.add_argument(f\"-{short}\", f\"--{long}\",\n                           default=None,\n                           action=\"append\",\n                           dest=f\"{long}_host\",\n                           metavar=long.upper(),\n                           help=f'Apply the specified {long}. '\n                                f'By default, or if specifying -{short}:h (--{long}:host), it applies to the host context. '\n                                f'Use -{short}:b (--{long}:build) to specify the build context, '\n                                f'or -{short}:a (--{long}:all) to specify both contexts at once'\n                                + ('' if not example else f\". Example: {example}\"))\n        for context in contexts:\n            group.add_argument(f\"-{short}:{context[0]}\", f\"--{long}:{context}\",\n                               default=None,\n                               action=\"append\",\n                               dest=f\"{long}_{context}\",\n                               help=\"\")\n\n        group.add_argument(f\"-{short}:a\", f\"--{long}:all\",\n                           default=None,\n                           action=ContextAllAction,\n                           dest=long,\n                           metavar=f\"{long.upper()}_ALL\",\n                           help=\"\")\n\n    create_config(\"pr\", \"profile\")\n    create_config(\"o\", \"options\", '-o=\"pkg/*:with_qt=True\"')\n    create_config(\"s\", \"settings\", '-s=\"compiler=gcc\"')\n    create_config(\"c\", \"conf\", '-c=\"tools.cmake.cmaketoolchain:generator=Xcode\"')\n\n\ndef add_reference_args(parser):\n    group = parser.add_argument_group(\"reference arguments\")\n    group.add_argument(\"--name\", action=OnceArgument,\n                       help='Provide a package name if not specified in conanfile')\n    group.add_argument(\"--version\", action=OnceArgument,\n                       help='Provide a package version if not specified in conanfile')\n    group.add_argument(\"--user\", action=OnceArgument,\n                       help='Provide a user if not specified in conanfile')\n    group.add_argument(\"--channel\", action=OnceArgument,\n                       help='Provide a channel if not specified in conanfile')\n\n\ndef common_graph_args(subparser):\n    subparser.add_argument(\"path\", nargs=\"?\",\n                           help=\"Path to a folder containing a recipe (conanfile.py \"\n                                \"or conanfile.txt) or to a recipe file. e.g., \"\n                                \"./my_project/conanfile.txt. Defaults to the current \"\n                                \"directory when no --requires or --tool-requires is \"\n                                \"given\",\n                           default=None)\n    add_common_install_arguments(subparser)\n    subparser.add_argument(\"--requires\", action=\"append\",\n                           help='Directly provide requires instead of a conanfile')\n    subparser.add_argument(\"--tool-requires\", action='append',\n                           help='Directly provide tool-requires instead of a conanfile')\n    add_reference_args(subparser)\n    add_lockfile_args(subparser)\n\n\ndef validate_common_graph_args(args):\n    if args.requires and (args.name or args.version or args.user or args.channel):\n        raise ConanException(\"Can't use --name, --version, --user or --channel arguments with \"\n                             \"--requires\")\n    if args.path and (args.requires or args.tool_requires):\n        raise ConanException(\"--requires and --tool-requires arguments are incompatible with \"\n                             f\"[path] '{args.path}' argument\")\n\n    if not args.requires and not args.tool_requires and args.path is None:\n        args.path = \".\"\n\n    # graph build-order command does not define a build-require argument\n    if not args.path and getattr(args, \"build_require\", False):\n        raise ConanException(\"--build-require should only be used with <path> argument\")\n"
  },
  {
    "path": "conan/cli/cli.py",
    "content": "import importlib\nimport os\nimport pkgutil\nimport re\nimport signal\nimport sys\nimport textwrap\nimport traceback\nfrom collections import defaultdict\nfrom difflib import get_close_matches\nfrom inspect import getmembers\n\nfrom conan.api.conan_api import ConanAPI\nfrom conan.api.output import ConanOutput, Color, cli_out_write, LEVEL_TRACE\nfrom conan.cli.command import ConanSubCommand\nfrom conan.cli.exit_codes import SUCCESS, ERROR_MIGRATION, ERROR_GENERAL, USER_CTRL_C, \\\n    ERROR_SIGTERM, USER_CTRL_BREAK, ERROR_INVALID_CONFIGURATION, ERROR_UNEXPECTED\nfrom conan import __version__\nfrom conan.errors import ConanException, ConanInvalidConfiguration, ConanMigrationError\n\n_CONAN_INTERNAL_CUSTOM_COMMANDS_PATH = \"_CONAN_INTERNAL_CUSTOM_COMMANDS_PATH\"\n\n\nclass Cli:\n    \"\"\"A single command of the conan application, with all the first level commands. Manages the\n    parsing of parameters and delegates functionality to the conan python api. It can also show the\n    help of the tool.\n    \"\"\"\n    _builtin_commands = None  # Caching the builtin commands, no need to load them over and over\n\n    def __init__(self, conan_api):\n        assert isinstance(conan_api, ConanAPI), \\\n            \"Expected 'Conan' type, got '{}'\".format(type(conan_api))\n        self._conan_api = conan_api\n        self._conan_api.command.cli = self\n        self._groups = defaultdict(list)\n        self._commands = {}\n\n    def add_commands(self):\n        if Cli._builtin_commands is None:\n            conan_cmd_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), \"commands\")\n            for module in pkgutil.iter_modules([conan_cmd_path]):\n                module_name = module[1]\n                self._add_command(\"conan.cli.commands.{}\".format(module_name), module_name)\n            Cli._builtin_commands = self._commands.copy()\n        else:\n            self._commands = Cli._builtin_commands.copy()\n            self._groups = defaultdict(list)\n            for k, v in self._commands.items():  # Fill groups data too\n                self._groups[v.group].append(k)\n\n        conan_custom_commands_path = os.path.join(self._conan_api.cache_folder, \"extensions\",\n                                                  \"commands\")\n        # Important! This variable should be only used for testing/debugging purpose\n        developer_custom_commands_path = os.getenv(_CONAN_INTERNAL_CUSTOM_COMMANDS_PATH)\n        # Notice that in case of having same custom commands file names, the developer one has\n        # preference over the Conan default location because of the sys.path.append(xxxx)\n        custom_commands_folders = [developer_custom_commands_path, conan_custom_commands_path] \\\n            if developer_custom_commands_path else [conan_custom_commands_path]\n\n        for custom_commands_path in custom_commands_folders:\n            if not os.path.isdir(custom_commands_path):\n                return\n\n            sys.path.append(custom_commands_path)\n            for module in pkgutil.iter_modules([custom_commands_path]):\n                module_name = module[1]\n                if module_name.startswith(\"cmd_\"):\n                    try:\n                        self._add_command(module_name, module_name.replace(\"cmd_\", \"\"))\n                    except Exception as e:\n                        ConanOutput().error(f\"Error loading custom command '{module_name}.py': {e}\",\n                                            error_type=\"exception\")\n            # layers\n            for folder in os.listdir(custom_commands_path):\n                layer_folder = os.path.join(custom_commands_path, folder)\n                sys.path.append(layer_folder)\n                if not os.path.isdir(layer_folder):\n                    continue\n                for module in pkgutil.iter_modules([layer_folder]):\n                    module_name = module[1]\n                    if module_name.startswith(\"cmd_\"):\n                        module_path = f\"{folder}.{module_name}\"\n                        try:\n                            self._add_command(module_path, module_name.replace(\"cmd_\", \"\"),\n                                              package=folder)\n                        except Exception as e:\n                            ConanOutput().error(f\"Error loading custom command {module_path}: {e}\",\n                                                error_type=\"exception\")\n\n    def _add_command(self, import_path, method_name, package=None):\n        try:\n            imported_module = importlib.import_module(import_path)\n            command_wrapper = getattr(imported_module, method_name)\n            if command_wrapper.doc:\n                name = f\"{package}:{command_wrapper.name}\" if package else command_wrapper.name\n                self._commands[name] = command_wrapper\n                command_wrapper._prog = name  # set the program name with possible package, if any\n                # Avoiding duplicated command help messages\n                if name not in self._groups[command_wrapper.group]:\n                    self._groups[command_wrapper.group].append(name)\n            for name, value in getmembers(imported_module):\n                if isinstance(value, ConanSubCommand):\n                    if name.startswith(\"{}_\".format(method_name)):\n                        command_wrapper.add_subcommand(value)\n                    else:\n                        raise ConanException(\"The name for the subcommand method should \"\n                                             \"begin with the main command name + '_'. \"\n                                             \"i.e. {}_<subcommand_name>\".format(method_name))\n        except AttributeError:\n            raise ConanException(\"There is no {} method defined in {}\".format(method_name,\n                                                                              import_path))\n\n    def _print_similar(self, command):\n        \"\"\" Looks for similar commands and prints them if found.\n        \"\"\"\n        output = ConanOutput()\n        matches = get_close_matches(\n            word=command, possibilities=self._commands.keys(), n=5, cutoff=0.75)\n\n        if len(matches) == 0:\n            return\n\n        if len(matches) > 1:\n            output.info(\"The most similar commands are\")\n        else:\n            output.info(\"The most similar command is\")\n\n        for match in matches:\n            output.info(\"    %s\" % match)\n\n        output.writeln(\"\")\n\n    def _output_help_cli(self):\n        \"\"\"\n        Prints a summary of all commands.\n        \"\"\"\n        max_len = max((len(c) for c in self._commands)) + 1\n        line_format = '{{: <{}}}'.format(max_len)\n\n        for group_name, comm_names in sorted(self._groups.items()):\n            cli_out_write(\"\\n\" + group_name + \" commands\", Color.BRIGHT_MAGENTA)\n            for name in comm_names:\n                # future-proof way to ensure tabular formatting\n                cli_out_write(line_format.format(name), Color.GREEN, endline=\"\")\n\n                # Help will be all the lines up to the first empty one\n                docstring_lines = self._commands[name].doc.split('\\n')\n                start = False\n                data = []\n                for line in docstring_lines:\n                    line = line.strip()\n                    if not line:\n                        if start:\n                            break\n                        start = True\n                        continue\n                    data.append(line)\n\n                txt = textwrap.fill(' '.join(data), 80, subsequent_indent=\" \" * (max_len + 2))\n                cli_out_write(txt)\n\n        cli_out_write(\"\")\n        cli_out_write('Type \"conan <command> -h\" for help', Color.BRIGHT_MAGENTA)\n\n    def run(self, *args):\n        \"\"\" Entry point for executing commands, dispatcher to class\n        methods\n        \"\"\"\n        output = ConanOutput()\n        self.add_commands()\n        try:\n            command_argument = args[0][0]\n        except IndexError:  # No parameters\n            self._output_help_cli()\n            return\n        try:\n            command = self._commands[command_argument]\n        except KeyError as exc:\n            if command_argument in [\"-v\", \"--version\"]:\n                cli_out_write(\"Conan version %s\" % __version__)\n                return\n\n            if command_argument in [\"-h\", \"--help\"]:\n                self._output_help_cli()\n                return\n\n            output.info(\"'%s' is not a Conan command. See 'conan --help'.\" % command_argument)\n            output.info(\"\")\n            self._print_similar(command_argument)\n            raise ConanException(\"Unknown command %s\" % str(exc))\n\n        try:\n            command.run(self._conan_api, args[0][1:])\n            _warn_frozen_center(self._conan_api)\n        except Exception as e:\n            # must be a local-import to get updated value\n            if ConanOutput.level_allowed(LEVEL_TRACE):\n                print(traceback.format_exc(), file=sys.stderr)\n            self._conan2_migrate_recipe_msg(e)\n            raise\n\n    @staticmethod\n    def _conan2_migrate_recipe_msg(exception):\n        message = str(exception)\n\n        result = re.search(r\"Package '(.*)' not resolved: .*: Cannot load recipe\", message)\n        if result:\n            pkg = result.group(1)\n            error = \"*********************************************************\\n\" \\\n                    f\"Recipe '{pkg}' seems broken.\\n\" \\\n                    f\"It is possible that this recipe is not Conan 2.0 ready\\n\"\\\n                    \"If the recipe comes from ConanCenter, report it at https://github.com/conan-io/conan-center-index/issues\\n\" \\\n                    \"If it is your recipe, check if it is updated to 2.0\\n\" \\\n                    \"*********************************************************\\n\"\n            ConanOutput().writeln(error, fg=Color.BRIGHT_MAGENTA)\n\n    @staticmethod\n    def exception_exit_error(exception):\n        output = ConanOutput()\n        assert exception is not None\n        if isinstance(exception, ConanInvalidConfiguration):\n            output.error(exception, error_type=\"exception\")\n            return ERROR_INVALID_CONFIGURATION\n        if isinstance(exception, ConanException):\n            output.error(exception, error_type=\"exception\")\n            return ERROR_GENERAL\n        if isinstance(exception, SystemExit):\n            if exception.code != 0:\n                output.error(\"Exiting with code: %d\" % exception.code, error_type=\"exception\")\n            return exception.code\n\n        assert isinstance(exception, Exception)\n        output.error(traceback.format_exc(), error_type=\"exception\")\n        output.error(str(exception), error_type=\"exception\")\n        return ERROR_UNEXPECTED\n\n\ndef _warn_frozen_center(conan_api):\n    remotes = conan_api.remotes.list()\n    for r in remotes:\n        if r.url == \"https://center.conan.io\" and not r.disabled:\n            ConanOutput().warning(\n                \"The remote 'https://center.conan.io' is now frozen and has been replaced by 'https://center2.conan.io'. \\n\"\n                \"Starting from Conan 2.9.2, the default remote is 'center2.conan.io'. \\n\"\n                \"It is recommended to update to the new remote using the following command:\\n\"\n                f\"'conan remote update {r.name} --url=\\\"https://center2.conan.io\\\"'\",\n                warn_tag=\"deprecated\"\n            )\n            break\n\n\ndef main(args):\n    \"\"\" main entry point of the conan application, using a Command to\n    parse parameters\n\n    Exit codes for conan command:\n\n        0: Success (done)\n        1: General ConanException error (done)\n        2: Migration error\n        3: Ctrl+C\n        4: Ctrl+Break\n        5: SIGTERM\n        6: Invalid configuration (done)\n    \"\"\"\n\n    try:\n        conan_api = ConanAPI()\n    except ConanMigrationError:  # Error migrating\n        sys.exit(ERROR_MIGRATION)\n    except ConanException as e:\n        sys.stderr.write(\"Error in Conan initialization: {}\".format(e))\n        sys.exit(ERROR_GENERAL)\n\n    def ctrl_c_handler(_, __):\n        print('You pressed Ctrl+C!')\n        sys.exit(USER_CTRL_C)\n\n    def sigterm_handler(_, __):\n        print('Received SIGTERM!')\n        sys.exit(ERROR_SIGTERM)\n\n    def ctrl_break_handler(_, __):\n        print('You pressed Ctrl+Break!')\n        sys.exit(USER_CTRL_BREAK)\n\n    signal.signal(signal.SIGINT, ctrl_c_handler)\n    signal.signal(signal.SIGTERM, sigterm_handler)\n\n    if sys.platform == 'win32':\n        signal.signal(signal.SIGBREAK, ctrl_break_handler)\n\n    cli = Cli(conan_api)\n    error = SUCCESS\n    try:\n        cli.run(args)\n        _warn_python_version()\n    except BaseException as e:\n        error = cli.exception_exit_error(e)\n    sys.exit(error)\n\n\ndef _warn_python_version():\n    version = sys.version_info\n    if version.minor == 7:\n        ConanOutput().writeln(\"\")\n        ConanOutput().warning(\"*\"*80, warn_tag=\"deprecated\")\n        ConanOutput().warning(\"Python 3.7 is end-of-life since June 2023. \"\n                              \"Conan future versions will drop support for it, \"\n                              \"please upgrade Python\", warn_tag=\"deprecated\")\n        ConanOutput().warning(\"*\" * 80, warn_tag=\"deprecated\")\n"
  },
  {
    "path": "conan/cli/command.py",
    "content": "import argparse\nimport os\nimport textwrap\nfrom contextlib import redirect_stdout\n\nfrom conan.api.output import ConanOutput\nfrom conan.errors import ConanException\n\n\nclass OnceArgument(argparse.Action):\n    \"\"\"Allows declaring a parameter that can have only one value, by default argparse takes the\n    latest declared and it's very confusing.\n    \"\"\"\n\n    def __call__(self, parser, namespace, values, option_string=None):\n        if getattr(namespace, self.dest) is not None and self.default is None:\n            msg = '{o} can only be specified once'.format(o=option_string)\n            raise argparse.ArgumentError(None, msg)\n        setattr(namespace, self.dest, values)\n\n\nclass SmartFormatter(argparse.HelpFormatter):\n\n    def _fill_text(self, text, width, indent):\n        text = textwrap.dedent(text)\n        return ''.join(indent + line for line in text.splitlines(True))\n\n\nclass BaseConanCommand:\n    def __init__(self, method, formatters=None):\n        self._formatters = {\"text\": lambda x: None}\n        self._method = method\n        self._name = None\n        if formatters:\n            for kind, action in formatters.items():\n                if callable(action):\n                    self._formatters[kind] = action\n                else:\n                    raise ConanException(\"Invalid formatter for {}. The formatter must be\"\n                                         \" a valid function\".format(kind))\n        if method.__doc__:\n            self._doc = method.__doc__\n        else:\n            raise ConanException(\"No documentation string defined for command: '{}'. Conan \"\n                                 \"commands should provide a documentation string explaining \"\n                                 \"its use briefly.\".format(self._name))\n\n    @staticmethod\n    def _init_core_options(parser):\n        # Define possible levels, including \"\" for verbose\n        possible_levels = list(ConanOutput.valid_log_levels().keys())\n        possible_levels.pop(possible_levels.index(None))\n        parser.add_argument(\"-v\", default=\"status\", nargs='?',\n                            help=\"Level of detail of the output. Valid options from less verbose \"\n                                 \"to more verbose: -vquiet, -verror, -vwarning, -vnotice, -vstatus, \"\n                                 \"-v or -vverbose, -vv or -vdebug, -vvv or -vtrace\",\n                            choices=possible_levels,\n                            )\n        parser.add_argument(\"-cc\", \"--core-conf\", action=\"append\",\n                            help=\"Define core configuration, overwriting global.conf \"\n                                 \"values. E.g.: -cc core:non_interactive=True\")\n\n    @property\n    def _help_formatters(self):\n        \"\"\"\n        Formatters that are shown as available in help, 'text' formatter\n        should not appear\n        \"\"\"\n        return [formatter for formatter in self._formatters if formatter != \"text\"]\n\n    def _init_formatters(self, parser):\n        formatters = self._help_formatters\n        if formatters:\n            help_message = \"Select the output format: {}\".format(\", \".join(formatters))\n            parser.add_argument('-f', '--format', action=OnceArgument, help=help_message)\n\n        parser.add_argument(\"--out-file\", action=OnceArgument,\n                            help=\"Write the output of the command to the specified file instead of \"\n                                 \"stdout.\")\n\n    @property\n    def name(self):\n        return self._name\n\n    @property\n    def method(self):\n        return self._method\n\n    @property\n    def doc(self):\n        return self._doc\n\n    def _format(self, parser, info, *args):\n        parser_args, _ = parser.parse_known_args(*args)\n\n        formatarg = getattr(parser_args, \"format\", None) or \"text\"\n        out_file = getattr(parser_args, \"out_file\", None)\n\n        try:\n            formatter = self._formatters[formatarg]\n        except KeyError:\n            raise ConanException(\"{} is not a known format. Supported formatters are: {}\".format(\n                formatarg, \", \".join(self._help_formatters)))\n\n        if out_file:\n            if os.path.dirname(out_file):\n                os.makedirs(os.path.dirname(out_file), exist_ok=True)\n            with open(out_file, 'w') as f:\n                with redirect_stdout(f):\n                    formatter(info)\n            ConanOutput().info(f\"Formatted output saved to '{out_file}'\")\n        else:\n            formatter(info)\n\n    @staticmethod\n    def _dispatch_errors(info):\n        if info and isinstance(info, dict):\n            if info.get(\"conan_error\"):\n                e = info[\"conan_error\"]\n                # Storing and launching an exception is better than the string, as it keeps\n                # the correct backtrace for debugging.\n                if isinstance(e, Exception):\n                    raise e\n                raise ConanException(e)\n            if info.get(\"conan_warning\"):\n                ConanOutput().warning(info[\"conan_warning\"])\n\n\nclass ConanArgumentParser(argparse.ArgumentParser):\n\n    def __init__(self, conan_api, *args, **kwargs):\n        self._conan_api = conan_api\n        super().__init__(*args, **kwargs)\n\n    def parse_args(self, args=None, namespace=None):\n        args = super().parse_args(args)\n        ConanOutput.define_log_level(args.v)\n        if getattr(args, \"lockfile_packages\", None):\n            ConanOutput().error(\"The --lockfile-packages arg is private and shouldn't be used\")\n\n        if args.core_conf:\n            self._conan_api._api_helpers.set_core_confs(args.core_conf)  # noqa\n\n        global_conf = self._conan_api._api_helpers.global_conf  # noqa\n        # TODO: This might be even better moved to the ConanAPI so users without doing custom\n        #  commands can benefit from it\n        ConanOutput.set_warnings_as_errors(global_conf.get(\"core:warnings_as_errors\",\n                                                           default=[], check_type=list))\n        ConanOutput.define_silence_warnings(global_conf.get(\"core:skip_warnings\",\n                                                            default=[], check_type=list))\n        return args\n\n\nclass ConanCommand(BaseConanCommand):\n    def __init__(self, method, group=None, formatters=None):\n        super().__init__(method, formatters=formatters)\n        self._subcommands = {}\n        self._group = group or \"Other\"\n        self._name = method.__name__.replace(\"_\", \"-\")\n        self._prog = self._name\n\n    def add_subcommand(self, subcommand):\n        subcommand.set_name(self.name)\n        self._subcommands[subcommand.name] = subcommand\n\n    def run_cli(self, conan_api, *args):\n        parser = ConanArgumentParser(conan_api, description=self._doc,\n                                     prog=\"conan {}\".format(self._prog),\n                                     formatter_class=SmartFormatter)\n        self._init_formatters(parser)\n        self._init_core_options(parser)\n        parser.suggest_on_error = True\n        info = self._method(conan_api, parser, *args)\n        if not self._subcommands:\n            return info\n\n        subcommand_parser = parser.add_subparsers(dest='subcommand', help='sub-command help')\n        subcommand_parser.required = True\n\n        subcmd = args[0][0]\n        try:\n            sub = self._subcommands[subcmd]\n        except (KeyError, IndexError):  # display help\n            raise ConanException(f\"Sub command {subcmd} does not exist\")\n        else:\n            sub.set_parser(subcommand_parser, conan_api)\n            return sub.run_cli(conan_api, parser, *args)\n\n    def run(self, conan_api, *args):\n        parser = ConanArgumentParser(conan_api, description=self._doc,\n                                     prog=\"conan {}\".format(self._prog),\n                                     formatter_class=SmartFormatter)\n        self._init_formatters(parser)\n        self._init_core_options(parser)\n        parser.suggest_on_error = True\n\n        info = self._method(conan_api, parser, *args)\n\n        if not self._subcommands:\n            self._format(parser, info, *args)\n        else:\n            subcommand_parser = parser.add_subparsers(dest='subcommand', help='sub-command help')\n            subcommand_parser.required = True\n\n            try:\n                sub = self._subcommands[args[0][0]]\n            except (KeyError, IndexError):  # display help\n                for sub in self._subcommands.values():\n                    sub.set_parser(subcommand_parser, conan_api)\n                parser.parse_args(*args)\n            else:\n                sub.set_parser(subcommand_parser, conan_api)\n                sub.run(conan_api, parser, *args)\n        self._dispatch_errors(info)\n\n    @property\n    def group(self):\n        return self._group\n\n\nclass ConanSubCommand(BaseConanCommand):\n    def __init__(self, method, formatters=None):\n        super().__init__(method, formatters=formatters)\n        self._parser = None\n        self._subcommand_name = method.__name__.replace('_', '-')\n\n    def run_cli(self, conan_api, parent_parser, *args):\n        return self._method(conan_api, parent_parser, self._parser, *args)\n\n    def run(self, conan_api, parent_parser, *args):\n        info = self._method(conan_api, parent_parser, self._parser, *args)\n        # It is necessary to do it after calling the \"method\" otherwise parser not complete\n        self._format(parent_parser, info, *args)\n        self._dispatch_errors(info)\n\n    def set_name(self, parent_name):\n        self._name = self._subcommand_name.replace(f'{parent_name}-', '', 1)\n\n    def set_parser(self, subcommand_parser, conan_api):\n        self._parser = subcommand_parser.add_parser(self._name, conan_api=conan_api, help=self._doc)\n        self._parser.description = self._doc\n        self._init_formatters(self._parser)\n        self._init_core_options(self._parser)\n        self._parser.suggest_on_error = True\n\n\ndef conan_command(group=None, formatters=None):\n    return lambda f: ConanCommand(f, group, formatters=formatters)\n\n\ndef conan_subcommand(formatters=None):\n    return lambda f: ConanSubCommand(f, formatters=formatters)\n"
  },
  {
    "path": "conan/cli/commands/__init__.py",
    "content": ""
  },
  {
    "path": "conan/cli/commands/audit.py",
    "content": "import json\nimport os\n\nfrom conan.api.conan_api import ConanAPI\nfrom conan.api.input import UserInput\nfrom conan.api.model import MultiPackagesList, RecipeReference\nfrom conan.api.output import cli_out_write, ConanOutput\nfrom conan.api.subapi.audit import CONAN_CENTER_AUDIT_PROVIDER_NAME\nfrom conan.cli import make_abs_path\nfrom conan.cli.args import common_graph_args, validate_common_graph_args\nfrom conan.cli.command import conan_command, conan_subcommand\nfrom conan.cli.formatters.audit.vulnerabilities import text_vuln_formatter, json_vuln_formatter, \\\n    html_vuln_formatter\nfrom conan.cli.printers import print_profiles\nfrom conan.cli.printers.graph import print_graph_basic\nfrom conan.errors import ConanException\nfrom conan.internal.util.files import load\n\n\ndef _add_provider_arg(subparser):\n    subparser.add_argument(\"-p\", \"--provider\", help=\"Provider to use for scanning\")\n\n\ndef _parse_error_threshold(result: dict, error_level: float) -> None:\n    \"\"\"Mark the result as error if any of the vulnerabilities has a severity greater than or equal to\n       The error_level reflects the severity level configured by the user. As it uses float and CVSS\n       score is limited to 10.0, users can use any higher number to skip it.\n\n       :param result: Conan audit scan result. It's expected to find cvss there\n       :param error_level: Threshold to raise an error in case of matching the severity level\n       :return: None\n    \"\"\"\n    if \"conan_error\" not in result:\n        for ref in result[\"data\"]:\n            if \"vulnerabilities\" not in result[\"data\"][ref]:\n                continue\n            for edge in result[\"data\"][ref][\"vulnerabilities\"][\"edges\"]:\n                preferred_base_score = float(edge[\"node\"][\"cvss\"].get(\"preferredBaseScore\", 0.0))\n                if preferred_base_score >= error_level:\n                    result.update(\n                        {\"conan_error\":\n                             f\"The package {ref} has a CVSS score {preferred_base_score} and \"\n                             f\"exceeded the threshold severity level {error_level}.\"})\n                    break\n\n\n@conan_subcommand(formatters={\"text\": text_vuln_formatter,\n                              \"json\": json_vuln_formatter,\n                              \"html\": html_vuln_formatter})\ndef audit_scan(conan_api: ConanAPI, parser, subparser, *args) -> dict:\n    \"\"\"\n    Scan a given recipe for vulnerabilities in its dependencies.\n    \"\"\"\n    common_graph_args(subparser)\n    # Needed for the validation of args, but this should usually be left as False here\n    # TODO: Do we then want to hide it in the --help?\n    subparser.add_argument(\"--build-require\", action='store_true', default=False,\n                           help='Whether the provided reference is a build-require')\n    subparser.add_argument(\"-sl\", \"--severity-level\", action=\"store\", default=9.0, type=float,\n                           help=\"Set threshold for severity level to raise an error. \"\n                                \"By default raises an error for any critical CVSS (9.0 or higher). \"\n                                \" Use 100.0 to disable it.\")\n    subparser.add_argument(\"--context\", help=\"Context to scan, by default both contexts are scanned \"\n                                             \"if not specified\",\n                           choices=[\"host\", \"build\"], default=None)\n\n    _add_provider_arg(subparser)\n    args = parser.parse_args(*args)\n\n    # This comes from install command\n\n    validate_common_graph_args(args)\n    # basic paths\n    cwd = os.getcwd()\n    path = conan_api.local.get_conanfile_path(args.path, cwd, py=None) if args.path else None\n\n    # Basic collaborators: remotes, lockfile, profiles\n    remotes = conan_api.remotes.list(args.remote) if not args.no_remote else []\n    overrides = eval(args.lockfile_overrides) if args.lockfile_overrides else None\n    lockfile = conan_api.lockfile.get_lockfile(lockfile=args.lockfile, conanfile_path=path, cwd=cwd,\n                                               partial=args.lockfile_partial, overrides=overrides)\n    profile_host, profile_build = conan_api.profiles.get_profiles_from_args(args)\n    print_profiles(profile_host, profile_build)\n\n    # Graph computation (without installation of binaries)\n    gapi = conan_api.graph\n    if path:\n        deps_graph = gapi.load_graph_consumer(path, args.name, args.version, args.user, args.channel,\n                                              profile_host, profile_build, lockfile, remotes,\n                                              # TO DISCUSS: defaulting to False the is_build_require\n                                              args.update, is_build_require=args.build_require)\n    else:\n        deps_graph = gapi.load_graph_requires(args.requires, args.tool_requires, profile_host,\n                                              profile_build, lockfile, remotes, args.update)\n    print_graph_basic(deps_graph)\n    deps_graph.report_graph_error()\n\n    if deps_graph.error:\n        return {\"conan_error\": deps_graph.error}\n\n    provider = conan_api.audit.get_provider(args.provider or CONAN_CENTER_AUDIT_PROVIDER_NAME)\n\n    scan_result = conan_api.audit.scan(deps_graph, provider, args.context)\n    _parse_error_threshold(scan_result, args.severity_level)\n    return scan_result\n\n\n@conan_subcommand(formatters={\"text\": text_vuln_formatter,\n                              \"json\": json_vuln_formatter,\n                              \"html\": html_vuln_formatter})\ndef audit_list(conan_api: ConanAPI, parser, subparser, *args):\n    \"\"\"\n    List the vulnerabilities of the given reference.\n    \"\"\"\n    input_group = subparser.add_mutually_exclusive_group(required=True)\n    input_group.add_argument(\"reference\", help=\"Reference to list vulnerabilities for\", nargs=\"?\")\n    input_group.add_argument(\"-l\", \"--list\", help=\"Package list file to list vulnerabilities for\")\n    input_group.add_argument(\"-s\", \"--sbom\", help=\"SBOM file to list vulnerabilities for\")\n    input_group.add_argument(\"-lock\", \"--lockfile\", help=\"Path to the lockfile to check for vulnerabilities\")\n    subparser.add_argument(\"-r\", \"--remote\", help=\"Remote to use for listing\")\n    _add_provider_arg(subparser)\n    args = parser.parse_args(*args)\n\n    provider = conan_api.audit.get_provider(args.provider or CONAN_CENTER_AUDIT_PROVIDER_NAME)\n\n    if args.list:\n        listfile = make_abs_path(args.list)\n        multi_package_list = MultiPackagesList.load(listfile)\n        cache_name = \"Local Cache\" if not args.remote else args.remote\n        package_list = multi_package_list[cache_name]\n        refs_to_list = package_list.serialize()\n        references = list(refs_to_list.keys())\n        if not references:  # the package list might contain only refs, no revs\n            ConanOutput().warning(\"Nothing to list, package list does not contain recipe revisions\")\n    elif args.sbom:\n        sbom_file = make_abs_path(args.sbom)\n        sbom = json.loads(load(sbom_file))\n        if sbom.get(\"bomFormat\") != \"CycloneDX\":\n            raise ConanException(f\"Unsupported SBOM format, only CycloneDX is supported.\")\n        purls = [component[\"purl\"] for component in sbom[\"components\"]]\n        references = [purl.split(\"pkg:conan/\")[1].replace(\"@\", \"/\") for purl in purls]\n    elif args.lockfile:\n        lock_file = make_abs_path(args.lockfile)\n        lockfile = conan_api.lockfile.get_lockfile(lock_file).serialize()\n        references = [str(RecipeReference.loads(ref[0] if isinstance(ref, tuple) else ref))\n                      for ref in lockfile[\"requires\"]]\n    else:\n        references = [args.reference]\n    return conan_api.audit.list(references, provider)\n\n\ndef _text_provider_formatter(providers_action):\n    providers = providers_action[0]\n    action = providers_action[1]\n\n    if action == \"remove\":\n        cli_out_write(\"Provider removed successfully.\")\n    elif action == \"add\":\n        cli_out_write(\"Provider added successfully.\")\n    elif action == \"auth\":\n        cli_out_write(\"Provider authentication added.\")\n    elif action == \"list\":\n        if not providers:\n            cli_out_write(\"No providers found.\")\n        else:\n            for provider in providers:\n                if provider:\n                    cli_out_write(f\"{provider.name} (type: {provider.type}) - {provider.url}\")\n\n\ndef _json_provider_formatter(providers_action):\n    ret = []\n    for provider in providers_action[0]:\n        if provider:\n            ret.append({\"name\": provider.name, \"url\": provider.url, \"type\": provider.type})\n    cli_out_write(json.dumps(ret, indent=4))\n\n\n@conan_subcommand(formatters={\"text\": _text_provider_formatter, \"json\": _json_provider_formatter})\ndef audit_provider(conan_api, parser, subparser, *args):\n    \"\"\"\n    Manage security providers for the 'conan audit' command.\n    \"\"\"\n\n    subparser.add_argument(\"action\", choices=[\"add\", \"list\", \"auth\", \"remove\"],\n                           help=\"Action to perform from 'add', 'list' , 'remove' or 'auth'\")\n    subparser.add_argument(\"name\", help=\"Provider name\", nargs=\"?\")\n\n    subparser.add_argument(\"--url\", help=\"Provider URL\")\n    subparser.add_argument(\"--type\", help=\"Provider type\", choices=[\"conan-center-proxy\", \"private\"])\n    subparser.add_argument(\"--token\", help=\"Provider token\")\n    args = parser.parse_args(*args)\n\n    if args.action == \"add\":\n        if not args.name or not args.url or not args.type:\n            raise ConanException(\"Name, URL and type are required to add a provider\")\n        if \" \" in args.name:\n            raise ConanException(\"Name cannot contain spaces\")\n        conan_api.audit.add_provider(args.name, args.url, args.type)\n\n        if not args.token:\n            user_input = UserInput(conan_api.config.get(\"core:non_interactive\"))\n            ConanOutput().write(f\"Please enter a token for {args.name} the provider: \")\n            token = user_input.get_password()\n        else:\n            token = args.token\n\n        provider = conan_api.audit.get_provider(args.name)\n        if token:\n            conan_api.audit.auth_provider(provider, token)\n\n        return [provider], args.action\n    elif args.action == \"remove\":\n        if not args.name:\n            raise ConanException(\"Name required to remove a provider\")\n        conan_api.audit.remove_provider(args.name)\n        return [], args.action\n    elif args.action == \"list\":\n        providers = conan_api.audit.list_providers()\n        return providers, args.action\n    elif args.action == \"auth\":\n        if not args.name:\n            raise ConanException(\"Name is required to authenticate on a provider\")\n        if not args.token:\n            user_input = UserInput(conan_api.config.get(\"core:non_interactive\"))\n            ConanOutput().write(f\"Please enter a token for {args.name} the provider: \")\n            token = user_input.get_password()\n        else:\n            token = args.token\n\n        provider = conan_api.audit.get_provider(args.name)\n        conan_api.audit.auth_provider(provider, token)\n        return [provider], args.action\n\n\n@conan_command(group=\"Security\")\ndef audit(conan_api, parser, *args):  # noqa\n    \"\"\"\n    Find vulnerabilities in your dependencies.\n    \"\"\"\n"
  },
  {
    "path": "conan/cli/commands/build.py",
    "content": "import os\n\nfrom conan.api.output import ConanOutput\nfrom conan.cli.command import conan_command\nfrom conan.cli.formatters.graph import format_graph_json\nfrom conan.cli import make_abs_path\nfrom conan.cli.args import add_lockfile_args, add_common_install_arguments, add_reference_args\nfrom conan.cli.printers import print_profiles\nfrom conan.cli.printers.graph import print_graph_packages, print_graph_basic\n\n\n@conan_command(group='Creator', formatters={\"json\": format_graph_json})\ndef build(conan_api, parser, *args):\n    \"\"\"\n    Install dependencies and call the build() method.\n    \"\"\"\n    parser.add_argument(\"path\",\n                        help='Path to a python-based recipe file or a folder '\n                             'containing a conanfile.py recipe. conanfile.txt '\n                             'cannot be used with conan build. '\n                             'Defaults to current directory',\n                        default=\".\", nargs='?')\n    add_reference_args(parser)\n    parser.add_argument(\"-g\", \"--generator\", action=\"append\", help='Generators to use')\n    parser.add_argument(\"-of\", \"--output-folder\",\n                        help='The root output folder for generated and build files')\n    parser.add_argument(\"-d\", \"--deployer\", action=\"append\",\n                        help=\"Deploy using the provided deployer to the output folder. \"\n                             \"Built-in deployers: 'full_deploy', 'direct_deploy', 'runtime_deploy'\")\n    parser.add_argument(\"--deployer-folder\",\n                        help=\"Deployer output folder, base build folder by default if not set\")\n    parser.add_argument(\"--build-require\", action='store_true', default=False,\n                        help='Whether the provided path is a build-require')\n    parser.add_argument(\"--envs-generation\", default=None, choices=[\"false\"],\n                        help=\"Generation strategy for virtual environment files for the root\")\n    add_common_install_arguments(parser)\n    add_lockfile_args(parser)\n    args = parser.parse_args(*args)\n\n    cwd = os.getcwd()\n    path = conan_api.local.get_conanfile_path(args.path, cwd, py=True)\n    source_folder = os.path.dirname(path)\n    output_folder = make_abs_path(args.output_folder, cwd) if args.output_folder else None\n    deployer_folder = make_abs_path(args.deployer_folder, cwd) if args.deployer_folder else None\n\n    # Basic collaborators: remotes, lockfile, profiles\n    remotes = conan_api.remotes.list(args.remote) if not args.no_remote else []\n    overrides = eval(args.lockfile_overrides) if args.lockfile_overrides else None\n    lockfile = conan_api.lockfile.get_lockfile(lockfile=args.lockfile, conanfile_path=path, cwd=cwd,\n                                               partial=args.lockfile_partial, overrides=overrides)\n    profile_host, profile_build = conan_api.profiles.get_profiles_from_args(args)\n    print_profiles(profile_host, profile_build)\n\n    deps_graph = conan_api.graph.load_graph_consumer(path, args.name, args.version,\n                                                     args.user, args.channel,\n                                                     profile_host, profile_build, lockfile, remotes,\n                                                     args.update,\n                                                     is_build_require=args.build_require)\n    print_graph_basic(deps_graph)\n    deps_graph.report_graph_error()\n    conan_api.graph.analyze_binaries(deps_graph, args.build, remotes=remotes, update=args.update,\n                                     lockfile=lockfile)\n    print_graph_packages(deps_graph)\n\n    out = ConanOutput()\n    conan_api.install.install_binaries(deps_graph=deps_graph, remotes=remotes)\n\n    out.title(\"Finalizing install (deploy, generators)\")\n    conan_api.install.install_consumer(deps_graph, args.generator, source_folder, output_folder,\n                                       deploy=args.deployer, deploy_folder=deployer_folder,\n                                       envs_generation=args.envs_generation)\n\n    out.title(\"Calling build()\")\n    conanfile = deps_graph.root.conanfile\n    conan_api.local.build(conanfile)\n\n    lockfile = conan_api.lockfile.update_lockfile(lockfile, deps_graph, args.lockfile_packages,\n                                                  clean=args.lockfile_clean)\n    conan_api.lockfile.save_lockfile(lockfile, args.lockfile_out, source_folder)\n    return {\"graph\": deps_graph}\n"
  },
  {
    "path": "conan/cli/commands/cache.py",
    "content": "import json\n\nfrom conan.api.conan_api import ConanAPI\nfrom conan.api.model import ListPattern, MultiPackagesList\nfrom conan.api.output import cli_out_write, ConanOutput\nfrom conan.cli import make_abs_path\nfrom conan.cli.command import conan_command, conan_subcommand, OnceArgument\nfrom conan.cli.commands.list import print_list_text, print_list_json, print_serial\nfrom conan.errors import ConanException\nfrom conan.api.model import PkgReference\nfrom conan.api.model import RecipeReference\n\n\ndef _get_package_sign_error(pkg_list):\n    conan_exception = ConanException(\"There were some errors in the package signing process. \"\n                                     \"Please check the output.\")\n    for rref, packages in pkg_list.items():\n        recipe_bundle = pkg_list.recipe_dict(rref)\n        if recipe_bundle.get(\"pkgsign_error\"):\n            return conan_exception\n        for pref in packages:\n            pkg_bundle = pkg_list.package_dict(pref)\n            if pkg_bundle:\n                if pkg_bundle.get(\"pkgsign_error\"):\n                    return conan_exception\n    return None\n\n\ndef print_package_sign_text(data):\n    results_dict = data.get(\"results\", {})\n\n    signs = []\n    for ref_data in results_dict.values():\n        for revision_data in ref_data.get(\"revisions\", {}).values():\n            sign = revision_data.get(\"pkgsign_error\")\n            signs.append(sign)\n\n            for pkg in revision_data.get(\"packages\", {}).values():\n                for prev in pkg.get(\"revisions\", {}).values():\n                    sign = prev.get(\"pkgsign_error\")\n                    signs.append(sign)\n\n    remove_keys = {\"info\", \"timestamp\", \"files\"}\n\n    def clean_inline(obj):\n        if not isinstance(obj, dict):\n            return obj\n\n        cleaned = {k: clean_inline(v) for k, v in obj.items() if k not in remove_keys}\n\n        if \"packages\" in cleaned and not cleaned[\"packages\"]:\n            del cleaned[\"packages\"]\n\n        return cleaned\n\n    items = {ref: clean_inline(item) for ref, item in results_dict.items() if item}\n\n    # Output\n    cli_out_write(f\"[Package sign] Results:\\n\")\n    print_serial(items)\n\n    # Summary\n    fail = sum((s is not None) for s in signs)\n    ok = len(signs) - fail\n    cli_out_write(f\"\\n[Package sign] Summary: OK={ok}, FAILED={fail}\")\n\n\ndef json_export(data):\n    cli_out_write(json.dumps({\"cache_path\": data}))\n\n\n@conan_command(group=\"Consumer\")\ndef cache(conan_api: ConanAPI, parser, *args):\n    \"\"\"\n    Perform file operations in the local cache (of recipes and/or packages).\n    \"\"\"\n    pass\n\n\n@conan_subcommand(formatters={\"text\": cli_out_write, \"json\": json_export})\ndef cache_path(conan_api: ConanAPI, parser, subparser, *args):\n    \"\"\"\n    Show the path to the Conan cache for a given reference.\n    \"\"\"\n    subparser.add_argument(\"reference\", help=\"Recipe reference or Package reference\")\n    subparser.add_argument(\"--folder\", choices=['export_source', 'source', 'build', 'metadata'],\n                           help=\"Path to show. The 'build' requires a package reference. \"\n                                \"If the argument is not passed, it shows 'exports' path for recipe references \"\n                                \"and 'package' folder for package references.\")\n\n    args = parser.parse_args(*args)\n    try:\n        pref = PkgReference.loads(args.reference)\n    except ConanException:\n        pref = None\n\n    if not pref:  # Not a package reference\n        ref = RecipeReference.loads(args.reference)\n        if args.folder is None:\n            path = conan_api.cache.export_path(ref)\n        elif args.folder == \"export_source\":\n            path = conan_api.cache.export_source_path(ref)\n        elif args.folder == \"source\":\n            path = conan_api.cache.source_path(ref)\n        elif args.folder == \"metadata\":\n            path = conan_api.cache.recipe_metadata_path(ref)\n        else:\n            raise ConanException(f\"'--folder {args.folder}' requires a valid package reference\")\n    else:\n        if args.folder is None:\n            path = conan_api.cache.package_path(pref)\n        elif args.folder == \"build\":\n            path = conan_api.cache.build_path(pref)\n        elif args.folder == \"metadata\":\n            path = conan_api.cache.package_metadata_path(pref)\n        else:\n            raise ConanException(f\"'--folder {args.folder}' requires a recipe reference\")\n    return path\n\n\n@conan_subcommand(formatters={\"text\": cli_out_write})\ndef cache_ref(conan_api: ConanAPI, parser, subparser, *args):\n    \"\"\"\n    Show the reference for a given Conan cache folder\n    \"\"\"\n    subparser.add_argument(\"path\", help=\"Path to a Conan cache folder\")\n    args = parser.parse_args(*args)\n    ref = conan_api.cache.path_to_ref(args.path)\n    if ref is None:\n        raise ConanException(\"Reference for this path not found in cache\")\n    return ref.repr_notime()\n\n\n@conan_subcommand()\ndef cache_clean(conan_api: ConanAPI, parser, subparser, *args):\n    \"\"\"\n    Remove non-critical folders from the cache, like source, build and/or download\n    (.tgz store) ones.\n    \"\"\"\n    subparser.add_argument(\"pattern\", nargs=\"?\", help=\"Selection pattern for references to clean\")\n    subparser.add_argument(\"-l\", \"--list\", action=OnceArgument,\n                            help=\"Package list of packages to clean\")\n    subparser.add_argument(\"-s\", \"--source\", action='store_true', default=False,\n                           help=\"Clean source folders\")\n    subparser.add_argument(\"-b\", \"--build\", action='store_true', default=False,\n                           help=\"Clean build folders\")\n    subparser.add_argument(\"-d\", \"--download\", action='store_true', default=False,\n                           help=\"Clean download and metadata folders\")\n    subparser.add_argument(\"-t\", \"--temp\", action='store_true', default=False,\n                           help=\"Clean temporary folders\")\n    subparser.add_argument(\"-bs\", \"--backup-sources\", action='store_true', default=False,\n                           help=\"Clean backup sources\")\n    subparser.add_argument('-p', '--package-query', action=OnceArgument,\n                           help=\"Remove only the packages matching a specific query, e.g., \"\n                                \"os=Windows AND (arch=x86 OR compiler=gcc)\")\n    args = parser.parse_args(*args)\n\n    # If pattern is None, it will be replaced by \"*\"\n    if args.pattern and args.list:\n        raise ConanException(\"Cannot specify both pattern and list\")\n\n    if args.list:\n        listfile = make_abs_path(args.list)\n        multi_package_list = MultiPackagesList.load(listfile)\n        package_list = multi_package_list[\"Local Cache\"]\n    else:\n        ref_pattern = ListPattern(args.pattern or \"*\", rrev=\"*\", package_id=\"*\", prev=\"*\")\n        package_list = conan_api.list.select(ref_pattern, package_query=args.package_query)\n    if args.build or args.source or args.download or args.temp or args.backup_sources:\n        conan_api.cache.clean(package_list, source=args.source, build=args.build,\n                              download=args.download, temp=args.temp,\n                              backup_sources=args.backup_sources)\n    else:\n        conan_api.cache.clean(package_list)\n\n\ndef print_list_check_integrity_json(data):\n    results = data[\"results\"]\n    myjson = json.dumps(results, indent=4)\n    cli_out_write(myjson)\n\n\n@conan_subcommand(formatters={\"text\": lambda _: (),\n                              \"json\": print_list_check_integrity_json})\ndef cache_check_integrity(conan_api: ConanAPI, parser, subparser, *args):\n    \"\"\"\n    Check the integrity of the local cache for the given references\n    \"\"\"\n    subparser.add_argument(\"pattern\", nargs=\"?\",\n                           help=\"Selection pattern for references to check integrity for\")\n    subparser.add_argument(\"-l\", \"--list\", action=OnceArgument,\n                           help=\"Package list of packages to check integrity for\")\n    subparser.add_argument('-p', '--package-query', action=OnceArgument,\n                           help=\"Only the packages matching a specific query, e.g., \"\n                                \"os=Windows AND (arch=x86 OR compiler=gcc)\")\n    args = parser.parse_args(*args)\n\n    if args.pattern is None and args.list is None:\n        raise ConanException(\"Missing pattern or package list file\")\n    if args.pattern and args.list:\n        raise ConanException(\"Cannot specify both pattern and list\")\n\n    if args.list:\n        listfile = make_abs_path(args.list)\n        multi_package_list = MultiPackagesList.load(listfile)\n        package_list = multi_package_list[\"Local Cache\"]\n    else:\n        ref_pattern = ListPattern(args.pattern, rrev=\"*\", package_id=\"*\", prev=\"*\")\n        package_list = conan_api.list.select(ref_pattern, package_query=args.package_query)\n\n    corrupted_artifacts = conan_api.cache.check_integrity(package_list, return_pkg_list=True)\n    return {\"results\": {\"Local Cache\": corrupted_artifacts.serialize()},\n            \"conan_error\": \"There are corrupted artifacts, check the error logs\" if corrupted_artifacts else \"\"}\n\n@conan_subcommand(formatters={\"text\": print_package_sign_text,\n                              \"json\": print_list_json})\ndef cache_sign(conan_api: ConanAPI, parser, subparser, *args):\n    \"\"\"\n    Sign packages with the Package Signing Plugin\n    \"\"\"\n    subparser.add_argument(\"pattern\", nargs=\"?\",\n                           help=\"Selection pattern for references to be signed\")\n    subparser.add_argument(\"-l\", \"--list\", action=OnceArgument,\n                           help=\"Package list of packages to be signed\")\n    subparser.add_argument('-p', '--package-query', action=OnceArgument,\n                           help=\"Only the packages matching a specific query, e.g., \"\n                                \"os=Windows AND (arch=x86 OR compiler=gcc)\")\n    args = parser.parse_args(*args)\n\n    if args.pattern is None and args.list is None:\n        raise ConanException(\"Missing pattern or package list file\")\n    if args.pattern and args.list:\n        raise ConanException(\"Cannot specify both pattern and list\")\n\n    if args.list:\n        listfile = make_abs_path(args.list)\n        multi_package_list = MultiPackagesList.load(listfile)\n        package_list = multi_package_list[\"Local Cache\"]\n    else:\n        ref_pattern = ListPattern(args.pattern, package_id=\"*\")\n        package_list = conan_api.list.select(ref_pattern, package_query=args.package_query)\n\n    if not dict(package_list.items()):\n        raise ConanException(\"No packages to process in the package list provided\")\n\n    conan_api.cache.sign(package_list)\n    return {\n        \"conan_error\": _get_package_sign_error(package_list),\n        \"results\": package_list.serialize()\n    }\n\n\n@conan_subcommand(formatters={\"text\": print_package_sign_text,\n                              \"json\": print_list_json})\ndef cache_verify(conan_api: ConanAPI, parser, subparser, *args):\n    \"\"\"\n    Check the signature of packages with the Package Signing Plugin\n    \"\"\"\n    subparser.add_argument(\"pattern\", nargs=\"?\",\n                           help=\"Selection pattern for references to verify their signature\")\n    subparser.add_argument(\"-l\", \"--list\", action=OnceArgument,\n                           help=\"Package list of packages to verify their signature\")\n    subparser.add_argument('-p', '--package-query', action=OnceArgument,\n                           help=\"Only the packages matching a specific query, e.g., \"\n                                \"os=Windows AND (arch=x86 OR compiler=gcc)\")\n    args = parser.parse_args(*args)\n\n    if args.pattern is None and args.list is None:\n        raise ConanException(\"Missing pattern or package list file\")\n    if args.pattern and args.list:\n        raise ConanException(\"Cannot specify both pattern and list\")\n\n    if args.list:\n        listfile = make_abs_path(args.list)\n        multi_package_list = MultiPackagesList.load(listfile)\n        package_list = multi_package_list[\"Local Cache\"]\n    else:\n        ref_pattern = ListPattern(args.pattern, package_id=\"*\")\n        package_list = conan_api.list.select(ref_pattern, package_query=args.package_query)\n\n    if not dict(package_list.items()):\n        raise ConanException(\"No packages to process in the package list provided\")\n\n    conan_api.cache.verify(package_list)\n    return {\n        \"conan_error\": _get_package_sign_error(package_list),\n        \"results\": package_list.serialize()\n    }\n\n\n@conan_subcommand(formatters={\"text\": print_list_text,\n                              \"json\": print_list_json})\ndef cache_save(conan_api: ConanAPI, parser, subparser, *args):\n    \"\"\"\n    Get the artifacts from a package list and archive them\n    \"\"\"\n    subparser.add_argument('pattern', nargs=\"?\",\n                           help=\"A pattern in the form 'pkg/version#revision:package_id#revision', \"\n                                \"e.g: zlib/1.2.13:* means all binaries for zlib/1.2.13. \"\n                                \"If revision is not specified, it is assumed latest one.\")\n    subparser.add_argument(\"-l\", \"--list\", help=\"Package list of packages to save\")\n    subparser.add_argument('--file', help=\"Save to this file. Allowed extensions .tgz, .txz, .tzst\"\n                                          \" (.txz and .tzst experimental and .tzst requires \"\n                                          \"Python>=3.14)\")\n    subparser.add_argument(\"--no-source\", action=\"store_true\", help=\"Exclude the sources\")\n    args = parser.parse_args(*args)\n\n    if args.pattern is None and args.list is None:\n        raise ConanException(\"Missing pattern or package list file\")\n    if args.pattern and args.list:\n        raise ConanException(\"Cannot define both the pattern and the package list file\")\n\n    if args.list:\n        listfile = make_abs_path(args.list)\n        multi_package_list = MultiPackagesList.load(listfile)\n        package_list = multi_package_list[\"Local Cache\"]\n    else:\n        ref_pattern = ListPattern(args.pattern)\n        package_list = conan_api.list.select(ref_pattern)\n    tgz_path = make_abs_path(args.file or \"conan_cache_save.tgz\")\n    conan_api.cache.save(package_list, tgz_path, args.no_source)\n    return {\"results\": {\"Local Cache\": package_list.serialize()}}\n\n\n@conan_subcommand(formatters={\"text\": print_list_text,\n                              \"json\": print_list_json})\ndef cache_restore(conan_api: ConanAPI, parser, subparser, *args):\n    \"\"\"\n    Put  the artifacts from an archive into the cache\n    \"\"\"\n    subparser.add_argument(\"file\", help=\"Path to archive to restore\")\n    args = parser.parse_args(*args)\n    path = make_abs_path(args.file)\n    package_list = conan_api.cache.restore(path)\n    return {\"results\": {\"Local Cache\": package_list.serialize()}}\n\n\n@conan_subcommand()\ndef cache_backup_upload(conan_api: ConanAPI, parser, subparser, *args):\n    \"\"\"\n    Upload all the source backups present in the cache\n    \"\"\"\n    parser.parse_args(*args)\n    files = conan_api.cache.get_backup_sources()\n    conan_api.upload.upload_backup_sources(files)\n"
  },
  {
    "path": "conan/cli/commands/config.py",
    "content": "import os\n\nfrom conan.api.model import Remote\nfrom conan.api.output import cli_out_write\nfrom conan.cli import make_abs_path\nfrom conan.cli.command import conan_command, conan_subcommand, OnceArgument\nfrom conan.cli.formatters import default_json_formatter\nfrom conan.errors import ConanException\n\n\n@conan_command(group='Consumer')\ndef config(conan_api, parser, *args):  # noqa\n    \"\"\"\n    Manage the Conan configuration in the Conan home.\n    \"\"\"\n\n\n@conan_subcommand()\ndef config_install(conan_api, parser, subparser, *args):\n    \"\"\"\n    Install the configuration (remotes, profiles, conf), from git, http or a folder, into the\n    Conan home folder.\n    \"\"\"\n    subparser.add_argument(\"item\",\n                           help=\"git repository, local file or folder or zip file (local or \"\n                                \"http) where the configuration is stored\")\n\n    ssl_subgroup = subparser.add_mutually_exclusive_group()\n    ssl_subgroup.add_argument(\"--verify-ssl\", nargs=\"?\", default=\"True\",\n                              help='Verify SSL connection when downloading file')\n    ssl_subgroup.add_argument(\"--insecure\", action=\"store_false\", default=None,\n                              help=\"Allow insecure server connections when using SSL. \"\n                                   \"Equivalent to --verify-ssl=False\",\n                              dest=\"verify_ssl\")\n    subparser.add_argument(\"-t\", \"--type\", choices=[\"git\", \"dir\", \"file\", \"url\"],\n                           help='Type of remote config')\n    subparser.add_argument(\"-a\", \"--args\",\n                           help='String with extra arguments for \"git clone\"')\n    subparser.add_argument(\"-sf\", \"--source-folder\",\n                           help='Install files only from a source subfolder from the '\n                                'specified origin')\n    subparser.add_argument(\"-tf\", \"--target-folder\",\n                           help='Install to that path in the conan cache')\n\n    args = parser.parse_args(*args)\n\n    def get_bool_from_text(value):  # TODO: deprecate this\n        value = value.lower()\n        if value in [\"1\", \"yes\", \"y\", \"true\"]:\n            return True\n        if value in [\"0\", \"no\", \"n\", \"false\"]:\n            return False\n        raise ConanException(\"Unrecognized boolean value '%s'\" % value)\n    verify_ssl = args.verify_ssl if isinstance(args.verify_ssl, bool) \\\n        else get_bool_from_text(args.verify_ssl)\n    conan_api.config.install(args.item, verify_ssl, args.type, args.args,\n                             source_folder=args.source_folder,\n                             target_folder=args.target_folder)\n\n\n@conan_subcommand()\ndef config_install_pkg(conan_api, parser, subparser, *args):\n    \"\"\"\n    (Experimental) Install the configuration (remotes, profiles, conf), from a Conan package\n    or from a conanconfig.yml file\n    \"\"\"\n    subparser.add_argument(\"reference\", nargs=\"?\",\n                           help=\"Package reference 'pkg/version' to install configuration from \"\n                                \"or path to 'conanconfig.yml' file\")\n    subparser.add_argument(\"-l\", \"--lockfile\", action=OnceArgument,\n                           help=\"Path to a lockfile. Use --lockfile=\\\"\\\" to avoid automatic use of \"\n                                \"existing 'conan.lock' file\")\n    subparser.add_argument(\"--lockfile-partial\", action=\"store_true\",\n                           help=\"Do not raise an error if some dependency is not found in lockfile\")\n    subparser.add_argument(\"--lockfile-out\", action=OnceArgument,\n                           help=\"Filename of the updated lockfile\")\n    subparser.add_argument(\"-f\", \"--force\", action='store_true',\n                           help=\"Force the re-installation of configuration\")\n    subparser.add_argument(\"--url\", action=OnceArgument,\n                           help=\"(Experimental) Provide Conan repository URL \"\n                                \"(for first install without remotes)\")\n    subparser.add_argument(\"-pr\", \"--profile\", help=\"Profile to install config\")\n    subparser.add_argument(\"-s\", \"--settings\", action=\"append\", help=\"Settings to install config\")\n    subparser.add_argument(\"-o\", \"--options\", action=\"append\", help=\"Options to install config\")\n    args = parser.parse_args(*args)\n\n    path = make_abs_path(args.reference or \".\")\n    if os.path.isdir(path):\n        path = os.path.join(path, \"conanconfig.yml\")\n    path = path if os.path.exists(path) else None\n    if path is None and args.reference is None:\n        raise ConanException(\"Must provide a package reference or a path to a conanconfig.yml file\")\n\n    lockfile = conan_api.lockfile.get_lockfile(lockfile=args.lockfile,\n                                               partial=args.lockfile_partial)\n\n    try:\n        default_profile = args.profile or conan_api.profiles.get_default_build()\n    except ConanException:  # it can fail if the default profile doesn't exist yet\n        default_profile = None\n    profiles = [default_profile] if default_profile else []\n    profile = conan_api.profiles.get_profile(profiles, args.settings, args.options)\n    remotes = [Remote(\"config_install_url\", url=args.url)] if args.url else None\n\n    if path:\n        conanconfig = path\n        refs = conan_api.config.install_conanconfig(conanconfig, lockfile=lockfile, force=args.force,\n                                                    remotes=remotes, profile=profile)\n    else:\n        refs = conan_api.config.install_package(args.reference, lockfile=lockfile, force=args.force,\n                                                remotes=remotes, profile=profile)\n    lockfile = conan_api.lockfile.add_lockfile(lockfile, config_requires=refs)\n    conan_api.lockfile.save_lockfile(lockfile, args.lockfile_out)\n\n\ndef _list_text_formatter(confs):\n    for k, v in confs.items():\n        cli_out_write(f\"{k}: {v}\")\n\n\n@conan_subcommand(formatters={\"text\": cli_out_write})\ndef config_home(conan_api, parser, subparser, *args):  # noqa\n    \"\"\"\n    Show the Conan home folder.\n    \"\"\"\n    parser.parse_args(*args)\n    return conan_api.config.home()\n\n\n@conan_subcommand(formatters={\"text\": _list_text_formatter, \"json\": default_json_formatter})\ndef config_list(conan_api, parser, subparser, *args):\n    \"\"\"\n    Show all the Conan available configurations: core and tools.\n    \"\"\"\n    subparser.add_argument('pattern', nargs=\"?\",\n                           help=\"Filter configuration items that matches this pattern\")\n    args = parser.parse_args(*args)\n    confs = conan_api.config.conf_list()\n    if args.pattern:\n        p = args.pattern.lower()\n        confs = {k: v for k, v in confs.items() if p in k.lower() or p in v.lower()}\n    return confs\n\n\n@conan_subcommand(formatters={\"text\": _list_text_formatter, \"json\": default_json_formatter})\ndef config_show(conan_api, parser, subparser, *args):\n    \"\"\"\n    Get the value of the specified conf\n    \"\"\"\n    subparser.add_argument('pattern', help='Conf item(s) pattern for which to query their value')\n    args = parser.parse_args(*args)\n\n    return conan_api.config.show(args.pattern)\n\n\n@conan_subcommand()\ndef config_clean(conan_api, parser, subparser, *args):  # noqa\n    \"\"\"\n    (Experimental) Clean the configuration files in the Conan home folder, while keeping\n    installed packages\n    \"\"\"\n    parser.parse_args(*args)\n    conan_api.config.clean()\n"
  },
  {
    "path": "conan/cli/commands/create.py",
    "content": "import os\nimport shutil\n\nfrom conan.api.output import ConanOutput\nfrom conan.cli.args import add_lockfile_args, add_common_install_arguments\nfrom conan.cli.command import conan_command, OnceArgument\nfrom conan.cli.commands.export import common_args_export\nfrom conan.cli.formatters.graph import format_graph_json\nfrom conan.cli.printers import print_profiles\nfrom conan.cli.printers.graph import print_graph_packages, print_graph_basic\nfrom conan.errors import ConanException\n\n\n@conan_command(group=\"Creator\", formatters={\"json\": format_graph_json})\ndef create(conan_api, parser, *args):\n    \"\"\"\n    Create a package.\n    \"\"\"\n    common_args_export(parser)\n    add_lockfile_args(parser)\n    add_common_install_arguments(parser)\n    parser.add_argument(\"--build-require\", action='store_true', default=False,\n                        help='Whether the package being created is a build-require (to be used'\n                             ' as tool_requires() by other packages)')\n    parser.add_argument(\"-tf\", \"--test-folder\", action=OnceArgument,\n                        help='Alternative test folder name. By default it is \"test_package\". '\n                             'Use \"\" to skip the test stage')\n    parser.add_argument(\"-tm\", \"--test-missing\", action='store_true', default=False,\n                        help='Run the test_package checks only if the package is built from source'\n                             ' but not if it already existed (using --build=missing)')\n    parser.add_argument(\"-bt\", \"--build-test\", action=\"append\",\n                        help=\"Same as '--build' but only for the test_package requires. By default\"\n                             \" if not specified it will take the '--build' value if specified\")\n    raw_args = args[0]\n    args = parser.parse_args(*args)\n\n    if args.test_missing and args.test_folder == \"\":\n        raise ConanException('--test-folder=\"\" is incompatible with --test-missing')\n\n    cwd = os.getcwd()\n    path = conan_api.local.get_conanfile_path(args.path, cwd, py=True)\n    overrides = eval(args.lockfile_overrides) if args.lockfile_overrides else None\n    lockfile = conan_api.lockfile.get_lockfile(lockfile=args.lockfile,\n                                               conanfile_path=path,\n                                               cwd=cwd,\n                                               partial=args.lockfile_partial,\n                                               overrides=overrides)\n    remotes = conan_api.remotes.list(args.remote) if not args.no_remote else []\n    profile_host, profile_build = conan_api.profiles.get_profiles_from_args(args)\n\n    ref, conanfile = conan_api.export.export(path=path,\n                                             name=args.name, version=args.version,\n                                             user=args.user, channel=args.channel,\n                                             lockfile=lockfile,\n                                             remotes=remotes)\n\n    # FIXME: Dirty: package type still raw, not processed yet\n    is_build = args.build_require or conanfile.package_type == \"build-scripts\"\n    # The package_type is not fully processed at export\n    is_python_require = conanfile.package_type == \"python-require\"\n    lockfile = conan_api.lockfile.update_lockfile_export(lockfile, conanfile, ref, is_build)\n\n    print_profiles(profile_host, profile_build)\n    runner = conan_api.command.get_runner(profile_host)\n    if runner is not None:\n        return runner(conan_api, 'create', profile_host, profile_build, args, raw_args).run()\n\n    if args.build is not None and args.build_test is None:\n        args.build_test = args.build\n\n    install_error = None\n    if is_python_require:\n        deps_graph = conan_api.graph.load_graph_requires([], [],\n                                                         profile_host=profile_host,\n                                                         profile_build=profile_build,\n                                                         lockfile=lockfile,\n                                                         remotes=remotes, update=args.update,\n                                                         python_requires=[ref])\n    else:\n        requires = [ref] if not is_build else None\n        tool_requires = [ref] if is_build else None\n        if conanfile.vendor:  # Automatically allow repackaging for conan create\n            pr = profile_build if is_build else profile_host\n            pr.conf.update(\"&:tools.graph:vendor\", \"build\")\n        deps_graph = conan_api.graph.load_graph_requires(requires, tool_requires,\n                                                         profile_host=profile_host,\n                                                         profile_build=profile_build,\n                                                         lockfile=lockfile,\n                                                         remotes=remotes, update=args.update)\n        print_graph_basic(deps_graph)\n        deps_graph.report_graph_error()\n\n        # Not specified, force build the tested library\n        build_modes = [ref.repr_notime()] if args.build is None else args.build\n        if args.build is None and conanfile.build_policy == \"never\":\n            raise ConanException(\n                \"This package cannot be created, 'build_policy=never', it can only be 'export-pkg'\")\n        conan_api.graph.analyze_binaries(deps_graph, build_modes, remotes=remotes,\n                                         update=args.update, lockfile=lockfile)\n        print_graph_packages(deps_graph)\n\n        install_error = conan_api.install.install_binaries(deps_graph=deps_graph, remotes=remotes,\n                                                           return_install_error=True)\n\n        # We update the lockfile, so it will be updated for later ``test_package``\n        lockfile = conan_api.lockfile.update_lockfile(lockfile, deps_graph, args.lockfile_packages,\n                                                      clean=args.lockfile_clean)\n\n    test_package_folder = getattr(conanfile, \"test_package_folder\", None) \\\n        if args.test_folder is None else args.test_folder\n    test_conanfile_path = _get_test_conanfile_path(test_package_folder, path)\n    # If the user provide --test-missing and the binary was not built from source, skip test_package\n    if args.test_missing and deps_graph.root.edges\\\n            and deps_graph.root.edges[0].dst.binary != \"Build\":\n        test_conanfile_path = None  # disable it\n\n    if test_conanfile_path and not install_error:\n        # TODO: We need arguments for:\n        #  - decide update policy \"--test_package_update\"\n        # If it is a string, it will be injected always, if it is a RecipeReference, then it will\n        # be replaced only if ``python_requires = \"tested_reference_str\"``\n        tested_python_requires = ref.repr_notime() if is_python_require else ref\n        from conan.cli.commands.test import run_test\n        # The test_package do not make the \"conan create\" command return a different graph or\n        # produce a different lockfile. The result is always the same, irrespective of test_package\n        run_test(conan_api, test_conanfile_path, ref, profile_host, profile_build, remotes, lockfile,\n                 update=None, build_modes=args.build, build_modes_test=args.build_test,\n                 tested_python_requires=tested_python_requires, tested_graph=deps_graph)\n\n    conan_api.lockfile.save_lockfile(lockfile, args.lockfile_out, cwd)\n    return {\"graph\": deps_graph,\n            \"conan_api\": conan_api,\n            \"conan_error\": install_error}\n\n\ndef _check_tested_reference_matches(deps_graph, tested_ref, out):\n    \"\"\" Check the test_profile_override_conflict test. If we are testing a build require\n    but we specify the build require with a different version in the profile, it has priority,\n    it is correct but weird and likely a mistake\"\"\"\n    # https://github.com/conan-io/conan/issues/10453\n    direct_refs = [n.conanfile.ref for n in deps_graph.root.neighbors()]\n    # There is a reference with same name but different\n    missmatch = [ref for ref in direct_refs if ref.name == tested_ref.name and ref != tested_ref]\n    if missmatch:\n        out.warning(\"The package created was '{}' but the reference being \"\n                    \"tested is '{}'\".format(missmatch[0], tested_ref))\n\n\ndef test_package(conan_api, deps_graph, test_conanfile_path):\n    out = ConanOutput()\n    out.title(\"Testing the package\")\n    # TODO: Better modeling when we are testing a python_requires\n    conanfile = deps_graph.root.conanfile\n    if len(deps_graph.nodes) == 1 and not hasattr(conanfile, \"python_requires\"):\n        raise ConanException(\"The conanfile at '{}' doesn't declare any requirement, \"\n                             \"use `self.tested_reference_str` to require the \"\n                             \"package being created.\".format(test_conanfile_path))\n    conanfile_folder = os.path.dirname(test_conanfile_path)\n    # To make sure the folders are correct\n    conanfile.folders.set_base_folders(conanfile_folder, output_folder=None)\n    if conanfile.build_folder and conanfile.build_folder != conanfile.source_folder:\n        # should be the same as build folder, but we can remove it\n        out.info(\"Removing previously existing 'test_package' build folder: \"\n                 f\"{conanfile.build_folder}\")\n        shutil.rmtree(conanfile.build_folder, ignore_errors=True)\n        os.makedirs(conanfile.build_folder, exist_ok=True)\n    conanfile.output.info(f\"Test package build: {conanfile.folders.build}\")\n    conanfile.output.info(f\"Test package build folder: {conanfile.build_folder}\")\n    conan_api.install.install_consumer(deps_graph=deps_graph,\n                                       source_folder=conanfile_folder)\n\n    out.title(\"Testing the package: Building\")\n    conan_api.local.build(conanfile)\n\n    out.title(\"Testing the package: Executing test\")\n    conanfile.output.highlight(\"Running test()\")\n    conan_api.local.test(conanfile)\n\n\ndef _get_test_conanfile_path(tf, conanfile_path):\n    \"\"\"Searches in the declared test_folder or in the standard \"test_package\"\n    \"\"\"\n    if tf == \"\":  # Now if parameter --test-folder=\"\" we have to skip tests\n        return None\n    base_folder = os.path.dirname(conanfile_path)\n    test_conanfile_path = os.path.join(base_folder, tf or \"test_package\", \"conanfile.py\")\n    if os.path.exists(test_conanfile_path):\n        return test_conanfile_path\n    elif tf:\n        raise ConanException(f\"test folder '{tf}' not available, or it doesn't have a conanfile.py\")\n"
  },
  {
    "path": "conan/cli/commands/download.py",
    "content": "from conan.api.conan_api import ConanAPI\nfrom conan.api.model import ListPattern, MultiPackagesList\nfrom conan.api.output import ConanOutput\nfrom conan.cli import make_abs_path\nfrom conan.cli.command import conan_command, OnceArgument\nfrom conan.cli.commands.list import print_list_text, print_list_json\nfrom conan.errors import ConanException\n\n\n@conan_command(group=\"Creator\", formatters={\"text\": print_list_text,\n                                            \"json\": print_list_json})\ndef download(conan_api: ConanAPI, parser, *args):\n    \"\"\"\n    Download (without installing) a single conan package from a remote server.\n\n    It downloads just the package, but not its transitive dependencies, and it will not call\n    any generate, generators or deployers.\n    It can download multiple packages if patterns are used, and also works with\n    queries over the package binaries.\n    \"\"\"\n\n    parser.add_argument('pattern', nargs=\"?\",\n                        help=\"A pattern in the form 'pkg/version#revision:package_id#revision', \"\n                             \"e.g: \\\"zlib/1.2.13:*\\\" means all binaries for zlib/1.2.13. \"\n                             \"If revision is not specified, it is assumed latest one.\")\n    parser.add_argument(\"--only-recipe\", action='store_true', default=False,\n                        help='Download only the recipe/s, not the binary packages.')\n    parser.add_argument('-p', '--package-query', default=None, action=OnceArgument,\n                        help=\"Only download packages matching a specific query. e.g: os=Windows AND \"\n                             \"(arch=x86 OR compiler=gcc)\")\n    parser.add_argument(\"-r\", \"--remote\", action=OnceArgument, required=True,\n                        help='Download from this specific remote')\n    parser.add_argument(\"-m\", \"--metadata\", action='append',\n                        help='Download the metadata matching the pattern, even if the package is '\n                             'already in the cache and not downloaded')\n    parser.add_argument(\"-l\", \"--list\", help=\"Package list file\")\n\n    args = parser.parse_args(*args)\n    if args.pattern is None and args.list is None:\n        raise ConanException(\"Missing pattern or package list file\")\n    if args.pattern and args.list:\n        raise ConanException(\"Cannot define both the pattern and the package list file\")\n\n    remote = conan_api.remotes.get(args.remote)\n\n    if args.list:\n        listfile = make_abs_path(args.list)\n        multi_package_list = MultiPackagesList.load(listfile)\n        try:\n            package_list = multi_package_list[remote.name]\n        except KeyError:\n            raise ConanException(f\"The current package list does not contain remote '{remote.name}'\")\n        if args.only_recipe:\n            package_list.only_recipes()\n    else:\n        ref_pattern = ListPattern(args.pattern, package_id=\"*\", only_recipe=args.only_recipe)\n        package_list = conan_api.list.select(ref_pattern, args.package_query, remote)\n\n    if package_list:\n        conan_api.download.download_full(package_list, remote, args.metadata)\n    else:\n        ConanOutput().warning(f\"No packages were downloaded because the package list is empty.\")\n\n    return {\"results\": {\"Local Cache\": package_list.serialize()}}\n"
  },
  {
    "path": "conan/cli/commands/editable.py",
    "content": "import json\nimport os\n\nfrom conan.api.output import ConanOutput, cli_out_write\nfrom conan.cli.args import add_reference_args\nfrom conan.cli.command import conan_command, conan_subcommand\n\n\n@conan_command(group=\"Creator\")\ndef editable(conan_api, parser, *args):\n    \"\"\"\n    Allow working with a package that resides in user folder.\n    \"\"\"\n\n\n@conan_subcommand()\ndef editable_add(conan_api, parser, subparser, *args):\n    \"\"\"\n    Define the given <path> location as the package <reference>, so when this\n    package is required, it is used from this <path> location instead of the cache.\n    \"\"\"\n    subparser.add_argument('path', help='Path to the package folder in the user workspace',\n                           default=\".\", nargs='?')\n    add_reference_args(subparser)\n    subparser.add_argument(\"-of\", \"--output-folder\",\n                           help='The root output folder for generated and build files')\n    group = subparser.add_mutually_exclusive_group()\n    group.add_argument(\"-r\", \"--remote\", action=\"append\", default=None,\n                       help='Look in the specified remote or remotes server')\n    group.add_argument(\"-nr\", \"--no-remote\", action=\"store_true\",\n                       help='Do not use remote, resolve exclusively in the cache')\n    args = parser.parse_args(*args)\n\n    remotes = conan_api.remotes.list(args.remote) if not args.no_remote else []\n    cwd = os.getcwd()\n    ref = conan_api.local.editable_add(args.path, args.name, args.version, args.user, args.channel,\n                                       cwd, args.output_folder, remotes=remotes)\n    ConanOutput().success(\"Reference '{}' in editable mode\".format(ref))\n\n\n@conan_subcommand()\ndef editable_remove(conan_api, parser, subparser, *args):\n    \"\"\"\n    Remove the \"editable\" mode for this reference.\n    \"\"\"\n    subparser.add_argument(\"path\", nargs=\"?\",\n                           help=\"Path to a folder containing a recipe conanfile.py \"\n                                \"or to a recipe file. e.g., \"\n                                \"./my_project/conanfile.py.\",\n                           default=None)\n    subparser.add_argument(\"-r\", \"--refs\", action=\"append\",\n                           help='Directly provide reference patterns')\n    args = parser.parse_args(*args)\n    if not args.refs and args.path is None:\n        args.path = \".\"\n    # TODO: Fix this API to use get_conanfile_path\n    editables = conan_api.local.editable_remove(args.path, args.refs)\n    out = ConanOutput()\n    if editables:\n        for ref, info in editables.items():\n            out.success(f\"Removed editable '{ref}': {info['path']}\")\n    else:\n        out.warning(\"No editables were removed\")\n\n\ndef print_editables_json(data):\n    results = {str(k): v for k, v in data.items()}\n    myjson = json.dumps(results, indent=4)\n    cli_out_write(myjson)\n\n\ndef print_editables_text(data):\n    for k, v in data.items():\n        cli_out_write(\"%s\" % k)\n        cli_out_write(\"    Path: %s\" % v[\"path\"])\n        if v.get(\"output_folder\"):\n            cli_out_write(\"    Output: %s\" % v[\"output_folder\"])\n\n\n@conan_subcommand(formatters={\"text\": print_editables_text, \"json\": print_editables_json})\ndef editable_list(conan_api, parser, subparser, *args):\n    \"\"\"\n    List all the packages in editable mode.\n    \"\"\"\n    parser.parse_args(*args)\n    editables = conan_api.local.editable_list()\n    return editables\n"
  },
  {
    "path": "conan/cli/commands/export.py",
    "content": "import json\nimport os\n\nfrom conan.api.model import MultiPackagesList, PackagesList\nfrom conan.api.output import cli_out_write\nfrom conan.cli.command import conan_command, OnceArgument\nfrom conan.cli.args import add_reference_args\n\n\ndef common_args_export(parser):\n    parser.add_argument(\"path\", help=\"Path to a folder containing a recipe (conanfile.py). \"\n                                     \"Defaults to current directory\",\n                        default=\".\", nargs=\"?\")\n    add_reference_args(parser)\n\n\ndef json_export(data):\n    cli_out_write(json.dumps({\"reference\": data[\"reference\"].repr_notime()}))\n\n\ndef pkglist_export(data):\n    cli_out_write(json.dumps(data[\"pkglist\"], indent=4))\n\n\n@conan_command(group=\"Creator\", formatters={\"json\": json_export, \"pkglist\": pkglist_export})\ndef export(conan_api, parser, *args):\n    \"\"\"\n    Export a recipe to the Conan package cache.\n    \"\"\"\n    common_args_export(parser)\n    group = parser.add_mutually_exclusive_group()\n    group.add_argument(\"-r\", \"--remote\", action=\"append\", default=None,\n                       help='Look in the specified remote or remotes server')\n    group.add_argument(\"-nr\", \"--no-remote\", action=\"store_true\",\n                       help='Do not use remote, resolve exclusively in the cache')\n    parser.add_argument(\"-l\", \"--lockfile\", action=OnceArgument,\n                        help=\"Path to a lockfile.\")\n    parser.add_argument(\"--lockfile-out\", action=OnceArgument,\n                        help=\"Filename of the updated lockfile\")\n    parser.add_argument(\"--lockfile-partial\", action=\"store_true\",\n                        help=\"Do not raise an error if some dependency is not found in lockfile\")\n    parser.add_argument(\"--build-require\", action='store_true', default=False,\n                        help='Whether the provided reference is a build-require')\n    args = parser.parse_args(*args)\n\n    cwd = os.getcwd()\n    path = conan_api.local.get_conanfile_path(args.path, cwd, py=True)\n    remotes = conan_api.remotes.list(args.remote) if not args.no_remote else []\n    lockfile = conan_api.lockfile.get_lockfile(lockfile=args.lockfile,\n                                               conanfile_path=path,\n                                               cwd=cwd,\n                                               partial=args.lockfile_partial)\n    ref, conanfile = conan_api.export.export(path=path,\n                                             name=args.name, version=args.version,\n                                             user=args.user, channel=args.channel,\n                                             lockfile=lockfile,\n                                             remotes=remotes)\n    lockfile = conan_api.lockfile.update_lockfile_export(lockfile, conanfile, ref,\n                                                         args.build_require)\n    conan_api.lockfile.save_lockfile(lockfile, args.lockfile_out, cwd)\n\n    exported_list = PackagesList()\n    exported_list.add_ref(ref)\n\n    pkglist = MultiPackagesList()\n    pkglist.add(\"Local Cache\", exported_list)\n\n    return {\n        \"pkglist\": pkglist.serialize(),\n        \"reference\": ref\n    }\n"
  },
  {
    "path": "conan/cli/commands/export_pkg.py",
    "content": "import os\n\nfrom conan.api.output import ConanOutput\nfrom conan.cli import make_abs_path\nfrom conan.cli.args import add_lockfile_args, add_profiles_args, add_reference_args\nfrom conan.cli.command import conan_command, OnceArgument\nfrom conan.cli.commands.create import _get_test_conanfile_path\nfrom conan.cli.formatters.graph import format_graph_json\nfrom conan.errors import ConanException\n\n\n@conan_command(group=\"Creator\", formatters={\"json\": format_graph_json})\ndef export_pkg(conan_api, parser, *args):\n    \"\"\"\n    Create a package directly from pre-compiled binaries.\n    \"\"\"\n    parser.add_argument(\"path\", help=\"Path to a folder containing a recipe (conanfile.py). \"\n                                     \"Defaults to current directory\",\n                        default=\".\", nargs=\"?\")\n    parser.add_argument(\"-of\", \"--output-folder\",\n                        help='The root output folder for generated and build files')\n    parser.add_argument(\"--build-require\", action='store_true', default=False,\n                        help='Whether the provided reference is a build-require')\n    parser.add_argument(\"-tf\", \"--test-folder\", action=OnceArgument,\n                        help='Alternative test folder name. By default it is \"test_package\". '\n                             'Use \"\" to skip the test stage')\n    parser.add_argument(\"-sb\", \"--skip-binaries\", action=\"store_true\",\n                        help=\"Skip installing dependencies binaries\")\n    group = parser.add_mutually_exclusive_group()\n    group.add_argument(\"-r\", \"--remote\", action=\"append\", default=None,\n                       help='Look in the specified remote or remotes server')\n    group.add_argument(\"-nr\", \"--no-remote\", action=\"store_true\",\n                       help='Do not use remote, resolve exclusively in the cache')\n\n    add_reference_args(parser)\n    add_lockfile_args(parser)\n    add_profiles_args(parser)\n    args = parser.parse_args(*args)\n\n    cwd = os.getcwd()\n    path = conan_api.local.get_conanfile_path(args.path, cwd, py=True)\n    overrides = eval(args.lockfile_overrides) if args.lockfile_overrides else None\n    lockfile = conan_api.lockfile.get_lockfile(lockfile=args.lockfile, conanfile_path=path,\n                                               cwd=cwd, partial=args.lockfile_partial,\n                                               overrides=overrides)\n    profile_host, profile_build = conan_api.profiles.get_profiles_from_args(args)\n    remotes = conan_api.remotes.list(args.remote) if not args.no_remote else []\n    output_folder = make_abs_path(args.output_folder, cwd) if args.output_folder else None\n\n    # UX error check, for python-requires use \"conan export\" or \"conan create\"\n    conanfile = conan_api.local.inspect(path, remotes, lockfile, name=args.name,\n                                        version=args.version, user=args.user, channel=args.channel)\n    # The package_type is not fully processed at export\n    if conanfile.package_type == \"python-require\":\n        raise ConanException(\"export-pkg can only be used for binaries, not for 'python-require'\")\n\n    # First, ensure recipe is exported\n    ref, conanfile = conan_api.export.export(path=path, name=args.name, version=args.version,\n                                             user=args.user, channel=args.channel, lockfile=lockfile,\n                                             remotes=remotes)\n    lockfile = conan_api.lockfile.update_lockfile_export(lockfile, conanfile, ref,\n                                                         args.build_require)\n\n    # Compute the dependency graph to prepare the exporting of the package biary\n    graph = conan_api.export.export_pkg_graph(path=path, ref=ref, profile_host=profile_host,\n                                              profile_build=profile_build, lockfile=lockfile,\n                                              remotes=remotes, is_build_require=args.build_require,\n                                              skip_binaries=args.skip_binaries,\n                                              output_folder=output_folder)\n\n    # Now export the final binary\n    ConanOutput().title(\"Exporting recipe and package to the cache\")\n    conan_api.export.export_pkg(graph, output_folder)\n    lockfile = conan_api.lockfile.update_lockfile(lockfile, graph, args.lockfile_packages,\n                                                  clean=args.lockfile_clean)\n\n    test_package_folder = getattr(conanfile, \"test_package_folder\", None) \\\n        if args.test_folder is None else args.test_folder\n    test_conanfile_path = _get_test_conanfile_path(test_package_folder, path)\n    if test_conanfile_path:\n        from conan.cli.commands.test import run_test\n        # same as ``conan create`` the lockfile, and deps graph is the one of the exported-pkg\n        # not the one from test_package\n        run_test(conan_api, test_conanfile_path, ref, profile_host, profile_build,\n                 remotes=remotes, lockfile=lockfile, update=None, build_modes=None)\n\n    conan_api.lockfile.save_lockfile(lockfile, args.lockfile_out, cwd)\n    return {\"graph\": graph,\n            \"conan_api\": conan_api}\n"
  },
  {
    "path": "conan/cli/commands/graph.py",
    "content": "import json\nimport os\n\nfrom conan.api.output import ConanOutput, cli_out_write, Color\nfrom conan.cli import make_abs_path\nfrom conan.cli.args import common_graph_args, validate_common_graph_args\nfrom conan.cli.command import conan_command, conan_subcommand\nfrom conan.cli.commands.list import prepare_pkglist_compact, print_serial\nfrom conan.cli.formatters.graph import format_graph_html, format_graph_json, format_graph_dot\nfrom conan.cli.formatters.graph.build_order_html import format_build_order_html\nfrom conan.cli.formatters.graph.graph_info_text import format_graph_info\nfrom conan.cli.printers import print_profiles\nfrom conan.cli.printers.graph import print_graph_packages, print_graph_basic\nfrom conan.errors import ConanException\n\n\ndef explain_formatter_text(data):\n    if \"closest_binaries\" in data:\n        # To be able to reuse the print_list_compact method,\n        # we need to wrap this in a MultiPackagesList\n        pkglist = data[\"closest_binaries\"]\n        prepare_pkglist_compact(pkglist)\n        # Now we make sure that if there are no binaries we will print something that makes sense\n        for ref, ref_info in pkglist.items():\n            for rrev, rrev_info in ref_info.items():\n                if not rrev_info:\n                    rrev_info[\"ERROR\"] = \"No package binaries exist\"\n        print_serial(pkglist)\n\n\ndef explain_formatter_json(data):\n    myjson = json.dumps(data, indent=4)\n    cli_out_write(myjson)\n\n\n@conan_command(group=\"Consumer\")\ndef graph(conan_api, parser, *args):  # noqa\n    \"\"\"\n    Compute a dependency graph, without installing or building the binaries.\n    \"\"\"\n\n\ndef cli_build_order(result):\n    # TODO: Very simple cli output, probably needs to be improved\n    build_order = result[\"build_order\"]\n    build_order = build_order[\"order\"] if isinstance(build_order, dict) else build_order\n    for level in build_order:\n        for item in level:\n            # If this is a configuration order, it has no packages entry, each item is a package\n            if 'packages' in item:\n                for package_level in item['packages']:\n                    for package in package_level:\n                        cli_out_write(f\"{item['ref']}:{package['package_id']} - {package['binary']}\")\n            else:\n                cli_out_write(f\"{item['ref']}:{item['package_id']} - {item['binary']}\")\n\n\ndef json_build_order(result):\n    cli_out_write(json.dumps(result[\"build_order\"], indent=4))\n\n\n@conan_subcommand(formatters={\"text\": cli_build_order, \"json\": json_build_order,\n                              \"html\": format_build_order_html})\ndef graph_build_order(conan_api, parser, subparser, *args):\n    \"\"\"\n    Compute the build order of a dependency graph.\n    \"\"\"\n    common_graph_args(subparser)\n    subparser.add_argument(\"--order-by\", choices=['recipe', 'configuration'],\n                           help='Select how to order the output, \"recipe\" by default if not set.')\n    subparser.add_argument(\"--reduce\", action='store_true', default=False,\n                           help='Reduce the build order, output only those to build. Use this '\n                                'only if the result will not be merged later with other build-order')\n    args = parser.parse_args(*args)\n    validate_common_graph_args(args)\n    if args.order_by is None:\n        ConanOutput().warning(\"Please specify --order-by argument\", warn_tag=\"deprecated\")\n\n    cwd = os.getcwd()\n    path = conan_api.local.get_conanfile_path(args.path, cwd, py=None) if args.path else None\n\n    # Basic collaborators, remotes, lockfile, profiles\n    remotes = conan_api.remotes.list(args.remote) if not args.no_remote else []\n    overrides = eval(args.lockfile_overrides) if args.lockfile_overrides else None\n    lockfile = conan_api.lockfile.get_lockfile(lockfile=args.lockfile,\n                                               conanfile_path=path,\n                                               cwd=cwd,\n                                               partial=args.lockfile_partial,\n                                               overrides=overrides)\n    profile_host, profile_build = conan_api.profiles.get_profiles_from_args(args)\n\n    if path:\n        deps_graph = conan_api.graph.load_graph_consumer(path, args.name, args.version,\n                                                         args.user, args.channel,\n                                                         profile_host, profile_build, lockfile,\n                                                         remotes, args.build, args.update)\n    else:\n        deps_graph = conan_api.graph.load_graph_requires(args.requires, args.tool_requires,\n                                                         profile_host, profile_build, lockfile,\n                                                         remotes, args.build, args.update)\n    print_graph_basic(deps_graph)\n    deps_graph.report_graph_error()\n    conan_api.graph.analyze_binaries(deps_graph, args.build, remotes=remotes, update=args.update,\n                                     lockfile=lockfile)\n    print_graph_packages(deps_graph)\n\n    out = ConanOutput()\n    out.title(\"Computing the build order\")\n    install_graph = conan_api.graph.build_order(deps_graph, args.order_by, args.reduce,\n                                                profile_args=args)\n    install_order_serialized = install_graph.install_build_order()\n    if args.order_by is None:  # legacy\n        install_order_serialized = install_order_serialized[\"order\"]\n\n    lockfile = conan_api.lockfile.update_lockfile(lockfile, deps_graph, args.lockfile_packages,\n                                                  clean=args.lockfile_clean)\n    conan_api.lockfile.save_lockfile(lockfile, args.lockfile_out, cwd)\n\n    return {\"build_order\": install_order_serialized,\n            \"conan_error\": install_graph.get_errors()}\n\n\n@conan_subcommand(formatters={\"text\": cli_build_order, \"json\": json_build_order,\n                              \"html\": format_build_order_html})\ndef graph_build_order_merge(conan_api, parser, subparser, *args):  # noqa\n    \"\"\"\n    Merge more than 1 build-order file.\n    \"\"\"\n    subparser.add_argument(\"--file\", nargs=\"?\", action=\"append\", help=\"Files to be merged\")\n    subparser.add_argument(\"--reduce\", action='store_true', default=False,\n                           help='Reduce the build order, output only those to build. Use this '\n                                'only if the result will not be merged later with other build-order')\n    args = parser.parse_args(*args)\n    if not args.file or len(args.file) < 2:\n        raise ConanException(\"At least 2 files are needed to be merged\")\n\n    files = [make_abs_path(f) for f in args.file]\n    result = conan_api.graph.build_order_merge(files, args.reduce)\n\n    install_order_serialized = result.install_build_order()\n    if getattr(result, \"legacy\"):\n        install_order_serialized = install_order_serialized[\"order\"]\n    return {\"build_order\": install_order_serialized,\n            \"conan_error\": result.get_errors()}\n\n\n@conan_subcommand(formatters={\"text\": format_graph_info,\n                              \"html\": format_graph_html,\n                              \"json\": format_graph_json,\n                              \"dot\": format_graph_dot})\ndef graph_info(conan_api, parser, subparser, *args):\n    \"\"\"\n    Compute the dependency graph and show information about it.\n    \"\"\"\n    common_graph_args(subparser)\n    subparser.add_argument(\"--check-updates\", default=False, action=\"store_true\",\n                           help=\"Check if there are recipe updates\")\n    subparser.add_argument(\"--filter\", action=\"append\",\n                           help=\"Show only the specified fields\")\n    subparser.add_argument(\"--package-filter\", action=\"append\",\n                           help='Print information only for packages that match the patterns')\n    subparser.add_argument(\"-d\", \"--deployer\", action=\"append\",\n                           help=\"Deploy using the provided deployer to the output folder. \"\n                                \"Built-in deployers: 'full_deploy', 'direct_deploy'. Deployers \"\n                                \"will only deploy recipes, as 'conan graph info' do not retrieve \"\n                                \"binaries\")\n    subparser.add_argument(\"-df\", \"--deployer-folder\",\n                           help=\"Deployer output folder, base build folder by default if not set\")\n    subparser.add_argument(\"--build-require\", action='store_true', default=False,\n                           help='Whether the provided reference is a build-require')\n    args = parser.parse_args(*args)\n    # parameter validation\n    validate_common_graph_args(args)\n    if args.format in (\"html\", \"dot\") and args.filter:\n        raise ConanException(f\"Formatted output '{args.format}' cannot filter fields\")\n\n    cwd = os.getcwd()\n    path = conan_api.local.get_conanfile_path(args.path, cwd, py=None) if args.path else None\n\n    # Basic collaborators, remotes, lockfile, profiles\n    remotes = conan_api.remotes.list(args.remote) if not args.no_remote else []\n    overrides = eval(args.lockfile_overrides) if args.lockfile_overrides else None\n    lockfile = conan_api.lockfile.get_lockfile(lockfile=args.lockfile,\n                                               conanfile_path=path,\n                                               cwd=cwd,\n                                               partial=args.lockfile_partial,\n                                               overrides=overrides)\n    profile_host, profile_build = conan_api.profiles.get_profiles_from_args(args)\n    print_profiles(profile_host, profile_build)\n\n    if path:\n        deps_graph = conan_api.graph.load_graph_consumer(path, args.name, args.version,\n                                                         args.user, args.channel,\n                                                         profile_host, profile_build, lockfile,\n                                                         remotes, args.update,\n                                                         check_updates=args.check_updates,\n                                                         is_build_require=args.build_require)\n    else:\n        deps_graph = conan_api.graph.load_graph_requires(args.requires, args.tool_requires,\n                                                         profile_host, profile_build, lockfile,\n                                                         remotes, args.update,\n                                                         check_updates=args.check_updates)\n    print_graph_basic(deps_graph)\n    if not deps_graph.error:\n        conan_api.graph.analyze_binaries(deps_graph, args.build, remotes=remotes, update=args.update,\n                                         lockfile=lockfile)\n        print_graph_packages(deps_graph)\n\n        conan_api.install.install_system_requires(deps_graph, only_info=True)\n        conan_api.install.install_sources(deps_graph, remotes=remotes)\n\n        lockfile = conan_api.lockfile.update_lockfile(lockfile, deps_graph, args.lockfile_packages,\n                                                      clean=args.lockfile_clean)\n        conan_api.lockfile.save_lockfile(lockfile, args.lockfile_out, cwd)\n        if args.deployer:\n            base_folder = args.deployer_folder or os.getcwd()\n            conan_api.install.deploy(deps_graph, args.deployer, None, base_folder)\n\n    warn_msg = None\n    missing = set(str(n.ref.name) for n in deps_graph.nodes if n.binary == \"Missing\")\n    invalid = set(str(n.ref.name) for n in deps_graph.nodes if n.binary == \"Invalid\")\n    if missing or invalid:\n        warn_msg = \"There are some error(s) in the graph:\"\n        if missing:\n            warn_msg += f\"\\n    - Missing packages: {', '.join(missing)}\"\n        if invalid:\n            warn_msg += f\"\\n    - Invalid packages: {', '.join(invalid)}\"\n\n    return {\"graph\": deps_graph,\n            \"field_filter\": args.filter,\n            \"package_filter\": args.package_filter,\n            \"conan_api\": conan_api,\n            \"conan_error\": str(deps_graph.error) if deps_graph.error else None,\n            \"conan_warning\": warn_msg}\n\n\n@conan_subcommand(formatters={\"text\": explain_formatter_text,\n                              \"json\": explain_formatter_json})\ndef graph_explain(conan_api, parser,  subparser, *args):\n    \"\"\"\n    Explain what is wrong with the dependency graph, like report missing binaries closest\n    alternatives, trying to explain why the existing binaries do not match\n    \"\"\"\n    common_graph_args(subparser)\n    subparser.add_argument(\"--check-updates\", default=False, action=\"store_true\",\n                           help=\"Check if there are recipe updates\")\n    subparser.add_argument(\"--build-require\", action='store_true', default=False,\n                           help='Whether the provided reference is a build-require')\n    subparser.add_argument('--missing', nargs=\"?\",\n                           help=\"A pattern in the form 'pkg/version#revision:package_id#revision', \"\n                                \"e.g: \\\"zlib/1.2.13:*\\\" means all binaries for zlib/1.2.13. \"\n                                \"If revision is not specified, it is assumed latest one.\")\n\n    args = parser.parse_args(*args)\n    # parameter validation\n    validate_common_graph_args(args)\n\n    cwd = os.getcwd()\n    path = conan_api.local.get_conanfile_path(args.path, cwd, py=None) if args.path else None\n\n    # Basic collaborators, remotes, lockfile, profiles\n    remotes = conan_api.remotes.list(args.remote) if not args.no_remote else []\n    overrides = eval(args.lockfile_overrides) if args.lockfile_overrides else None\n    lockfile = conan_api.lockfile.get_lockfile(lockfile=args.lockfile,\n                                               conanfile_path=path,\n                                               cwd=cwd,\n                                               partial=args.lockfile_partial,\n                                               overrides=overrides)\n    profile_host, profile_build = conan_api.profiles.get_profiles_from_args(args)\n\n    if path:\n        deps_graph = conan_api.graph.load_graph_consumer(path, args.name, args.version,\n                                                         args.user, args.channel,\n                                                         profile_host, profile_build, lockfile,\n                                                         remotes, args.update,\n                                                         check_updates=args.check_updates,\n                                                         is_build_require=args.build_require)\n    else:\n        deps_graph = conan_api.graph.load_graph_requires(args.requires, args.tool_requires,\n                                                         profile_host, profile_build, lockfile,\n                                                         remotes, args.update,\n                                                         check_updates=args.check_updates)\n    print_graph_basic(deps_graph)\n    deps_graph.report_graph_error()\n    conan_api.graph.analyze_binaries(deps_graph, args.build, remotes=remotes, update=args.update,\n                                     lockfile=lockfile)\n    print_graph_packages(deps_graph)\n\n    ConanOutput().title(\"Retrieving and computing closest binaries\")\n    # compute ref and conaninfo of the first missing binary\n    ref, conaninfo = conan_api.graph.find_first_missing_binary(deps_graph, args.missing)\n    pkglist = conan_api.list.explain_missing_binaries(ref, conaninfo, remotes)\n\n    ConanOutput().title(\"Closest binaries\")\n    return {\"closest_binaries\": pkglist.serialize()}\n\n\ndef outdated_text_formatter(result):\n    cli_out_write(\"======== Outdated dependencies ========\", fg=Color.BRIGHT_MAGENTA)\n\n    if len(result) == 0:\n        cli_out_write(\"No outdated dependencies in graph\", fg=Color.BRIGHT_YELLOW)\n\n    for key, value in result.items():\n        current_versions_set = list({str(v) for v in value[\"cache_refs\"]})\n        cli_out_write(key, fg=Color.BRIGHT_YELLOW)\n        cli_out_write(\n            f'    Current versions:  {\", \".join(current_versions_set) if value[\"cache_refs\"] else \"No version found in cache\"}', fg=Color.BRIGHT_CYAN)\n        cli_out_write(\n            f'    Latest in remote(s):  {value[\"latest_remote\"][\"ref\"]} - {value[\"latest_remote\"][\"remote\"]}',\n            fg=Color.BRIGHT_CYAN)\n        if value[\"version_ranges\"]:\n            cli_out_write(f'    Version ranges: ' + str(value[\"version_ranges\"])[1:-1], fg=Color.BRIGHT_CYAN)\n\n\ndef outdated_json_formatter(result):\n    output = {key: {\"current_versions\": list({str(v) for v in value[\"cache_refs\"]}),\n                    \"version_ranges\": [str(r) for r in value[\"version_ranges\"]],\n                    \"latest_remote\": [] if value[\"latest_remote\"] is None\n                                        else {\"ref\": str(value[\"latest_remote\"][\"ref\"]),\n                                              \"remote\": str(value[\"latest_remote\"][\"remote\"])}}\n              for key, value in result.items()}\n    cli_out_write(json.dumps(output))\n\n\n@conan_subcommand(formatters={\"text\": outdated_text_formatter, \"json\": outdated_json_formatter})\ndef graph_outdated(conan_api, parser, subparser, *args):\n    \"\"\"\n    List the dependencies in the graph and it's newer versions in the remote\n    \"\"\"\n    common_graph_args(subparser)\n    subparser.add_argument(\"--check-updates\", default=False, action=\"store_true\",\n                           help=\"Check if there are recipe updates\")\n    subparser.add_argument(\"--build-require\", action='store_true', default=False,\n                           help='Whether the provided reference is a build-require')\n    args = parser.parse_args(*args)\n    # parameter validation\n    validate_common_graph_args(args)\n    cwd = os.getcwd()\n    path = conan_api.local.get_conanfile_path(args.path, cwd, py=None) if args.path else None\n\n    # Basic collaborators, remotes, lockfile, profiles\n    remotes = conan_api.remotes.list(args.remote) if not args.no_remote else []\n    overrides = eval(args.lockfile_overrides) if args.lockfile_overrides else None\n    lockfile = conan_api.lockfile.get_lockfile(lockfile=args.lockfile,\n                                               conanfile_path=path,\n                                               cwd=cwd,\n                                               partial=args.lockfile_partial,\n                                               overrides=overrides)\n    profile_host, profile_build = conan_api.profiles.get_profiles_from_args(args)\n\n    if path:\n        deps_graph = conan_api.graph.load_graph_consumer(path, args.name, args.version,\n                                                         args.user, args.channel,\n                                                         profile_host, profile_build, lockfile,\n                                                         remotes, args.update,\n                                                         check_updates=args.check_updates,\n                                                         is_build_require=args.build_require)\n    else:\n        deps_graph = conan_api.graph.load_graph_requires(args.requires, args.tool_requires,\n                                                         profile_host, profile_build, lockfile,\n                                                         remotes, args.update,\n                                                         check_updates=args.check_updates)\n    print_graph_basic(deps_graph)\n\n    # Data structure to store info per library\n    # DO NOT USE this API call yet, it is not stable\n    outdated = conan_api.list.outdated(deps_graph, remotes)\n    return outdated\n"
  },
  {
    "path": "conan/cli/commands/inspect.py",
    "content": "import os\n\nfrom conan.api.output import cli_out_write\nfrom conan.cli.command import conan_command, OnceArgument\nfrom conan.cli.formatters import default_json_formatter\n\n\ndef inspect_text_formatter(data):\n    for name, value in sorted(data.items()):\n        if value is None:\n            continue\n        if isinstance(value, dict):\n            cli_out_write(f\"{name}:\")\n            for k, v in value.items():\n                cli_out_write(f\"    {k}: {v}\")\n        else:\n            cli_out_write(\"{}: {}\".format(name, str(value)))\n\n\n@conan_command(group=\"Consumer\", formatters={\"text\": inspect_text_formatter,\n                                             \"json\": default_json_formatter})\ndef inspect(conan_api, parser, *args):\n    \"\"\"\n    Inspect a conanfile.py to return its public fields.\n    \"\"\"\n    parser.add_argument(\"path\", help=\"Path to a folder containing a recipe (conanfile.py). \"\n                                     \"Defaults to current directory\",\n                        default=\".\", nargs=\"?\")\n    group = parser.add_mutually_exclusive_group()\n    group.add_argument(\"-r\", \"--remote\", default=None, action=\"append\",\n                       help=\"Remote names. Accepts wildcards ('*' means all the remotes available)\")\n    group.add_argument(\"-nr\", \"--no-remote\", action=\"store_true\",\n                       help='Do not use remote, resolve exclusively in the cache')\n    parser.add_argument(\"-l\", \"--lockfile\", action=OnceArgument,\n                        help=\"Path to a lockfile. Use --lockfile=\\\"\\\" to avoid automatic use of \"\n                             \"existing 'conan.lock' file\")\n    parser.add_argument(\"--lockfile-partial\", action=\"store_true\",\n                        help=\"Do not raise an error if some dependency is not found in lockfile\")\n\n    args = parser.parse_args(*args)\n    path = conan_api.local.get_conanfile_path(args.path, os.getcwd(), py=True)\n    lockfile = conan_api.lockfile.get_lockfile(lockfile=args.lockfile,\n                                               conanfile_path=path,\n                                               cwd=os.getcwd(),\n                                               partial=args.lockfile_partial)\n    remotes = conan_api.remotes.list(args.remote) if not args.no_remote else []\n    conanfile = conan_api.local.inspect(path, remotes=remotes, lockfile=lockfile)\n    result = conanfile.serialize()\n    # Some of the serialization info is not initialized so it's pointless to show it to the user\n    for item in (\"cpp_info\", \"system_requires\", \"recipe_folder\", \"conf_info\"):\n        if item in result:\n            del result[item]\n\n    return result\n"
  },
  {
    "path": "conan/cli/commands/install.py",
    "content": "import os\n\nfrom conan.api.output import ConanOutput\nfrom conan.cli import make_abs_path\nfrom conan.cli.args import common_graph_args, validate_common_graph_args\nfrom conan.cli.command import conan_command\nfrom conan.cli.formatters.graph import format_graph_json\nfrom conan.cli.printers import print_profiles\nfrom conan.cli.printers.graph import print_graph_packages, print_graph_basic\n\n\n@conan_command(group=\"Consumer\", formatters={\"json\": format_graph_json})\ndef install(conan_api, parser, *args):\n    \"\"\"\n    Install the requirements specified in a recipe (conanfile.py or conanfile.txt).\n\n    It can also be used to install packages without a conanfile, using the\n    --requires and --tool-requires arguments.\n\n    If any requirement is not found in the local cache, it will iterate the remotes\n    looking for it. When the full dependency graph is computed, and all dependencies\n    recipes have been found, it will look for binary packages matching the current settings.\n    If no binary package is found for some or several dependencies, it will error,\n    unless the '--build' argument is used to build it from source.\n\n    After installation of packages, the generators and deployers will be called.\n    \"\"\"\n    common_graph_args(parser)\n    parser.add_argument(\"-g\", \"--generator\", action=\"append\", help='Generators to use')\n    parser.add_argument(\"-of\", \"--output-folder\",\n                        help='The root output folder for generated and build files')\n    parser.add_argument(\"-d\", \"--deployer\", action=\"append\",\n                        help=\"Deploy using the provided deployer to the output folder. \"\n                             \"Built-in deployers: 'full_deploy', 'direct_deploy', 'runtime_deploy'\")\n    parser.add_argument(\"--deployer-folder\",\n                        help=\"Deployer output folder, base build folder by default if not set\")\n    parser.add_argument(\"--deployer-package\", action=\"append\",\n                        help=\"Execute the deploy() method of the packages matching \"\n                             \"the provided patterns\")\n    parser.add_argument(\"--build-require\", action='store_true', default=False,\n                        help='Whether the provided path is a build-require')\n    parser.add_argument(\"--envs-generation\", default=None, choices=[\"false\"],\n                        help=\"Generation strategy for virtual environment files for the root\")\n    args = parser.parse_args(*args)\n    validate_common_graph_args(args)\n    cwd = os.getcwd()\n\n    deps_graph, lockfile, install_error = _run_install_command(conan_api, args, cwd)\n\n    # Update lockfile if necessary\n    lockfile = conan_api.lockfile.update_lockfile(lockfile, deps_graph, args.lockfile_packages,\n                                                  clean=args.lockfile_clean)\n    conan_api.lockfile.save_lockfile(lockfile, args.lockfile_out, cwd)\n    return {\"graph\": deps_graph,\n            \"conan_api\": conan_api,\n            \"conan_error\": install_error}\n\n\ndef _run_install_command(conan_api, args, cwd, return_install_error=True):\n    \"\"\"\n    This method should not be imported as-is, it is internal to the installation process and\n    its signature might change without warning.\n\n    Users are however free to copy its code and adapt it to their needs, as an example of\n    using the Conan API to perform an installation\n    \"\"\"\n    # basic paths\n\n    path = conan_api.local.get_conanfile_path(args.path, cwd, py=None) if args.path else None\n    source_folder = os.path.dirname(path) if args.path else cwd\n    output_folder = make_abs_path(args.output_folder, cwd) if args.output_folder else None\n\n    # Basic collaborators: remotes, lockfile, profiles\n    remotes = conan_api.remotes.list(args.remote) if not args.no_remote else []\n    overrides = eval(args.lockfile_overrides) if args.lockfile_overrides else None\n    lockfile = conan_api.lockfile.get_lockfile(lockfile=args.lockfile, conanfile_path=path, cwd=cwd,\n                                               partial=args.lockfile_partial, overrides=overrides)\n    profile_host, profile_build = conan_api.profiles.get_profiles_from_args(args)\n    print_profiles(profile_host, profile_build)\n\n    # Graph computation (without installation of binaries)\n    gapi = conan_api.graph\n    if path:\n        deps_graph = gapi.load_graph_consumer(path, args.name, args.version, args.user, args.channel,\n                                              profile_host, profile_build, lockfile, remotes,\n                                              args.update, is_build_require=args.build_require)\n    else:\n        deps_graph = gapi.load_graph_requires(args.requires, args.tool_requires, profile_host,\n                                              profile_build, lockfile, remotes, args.update)\n    print_graph_basic(deps_graph)\n    deps_graph.report_graph_error()\n    gapi.analyze_binaries(deps_graph, args.build, remotes, update=args.update, lockfile=lockfile)\n    print_graph_packages(deps_graph)\n\n    # Installation of binaries and consumer generators\n    install_error = conan_api.install.install_binaries(deps_graph=deps_graph, remotes=remotes,\n                                                       return_install_error=return_install_error)\n    if not install_error:\n        ConanOutput().title(\"Finalizing install (deploy, generators)\")\n        conan_api.install.install_consumer(deps_graph, args.generator, source_folder, output_folder,\n                                           deploy=getattr(args, \"deployer\", None),\n                                           deploy_package=getattr(args, \"deployer_package\", None),\n                                           deploy_folder=getattr(args, \"deployer_folder\", None),\n                                           envs_generation=getattr(args, \"envs_generation\", None))\n        ConanOutput().success(\"Install finished successfully\")\n\n    return deps_graph, lockfile, install_error\n"
  },
  {
    "path": "conan/cli/commands/list.py",
    "content": "import json\nimport datetime\n\nfrom conan.api.conan_api import ConanAPI\nfrom conan.api.model import ListPattern, MultiPackagesList\nfrom conan.api.output import Color, cli_out_write\nfrom conan.cli import make_abs_path\nfrom conan.cli.command import conan_command, OnceArgument\nfrom conan.cli.formatters.list import list_packages_html\nfrom conan.errors import ConanException\n\n# Keep them so we don't break other commands that import them, but TODO: Remove later\nremote_color = Color.BRIGHT_BLUE\nrecipe_name_color = Color.GREEN\nrecipe_color = Color.BRIGHT_WHITE\nreference_color = Color.WHITE\nerror_color = Color.BRIGHT_RED\nfield_color = Color.BRIGHT_YELLOW\nvalue_color = Color.CYAN\n\n\ndef _format_timestamp_human(timestamp):\n    # used by ref.repr_humantime() to print human readable time\n    return datetime.datetime.fromtimestamp(int(timestamp),\n                                           datetime.timezone.utc).strftime('%Y-%m-%d %H:%M:%S UTC')\n\n\ndef print_serial(item, indent=None, color_index=None):\n    indent = \"\" if indent is None else (indent + \"  \")\n    color_index = 0 if color_index is None else (color_index + 1)\n    color_array = [Color.BRIGHT_BLUE, Color.BRIGHT_GREEN, Color.BRIGHT_WHITE,\n                   Color.BRIGHT_YELLOW, Color.BRIGHT_CYAN, Color.BRIGHT_MAGENTA, Color.WHITE]\n    color = color_array[color_index % len(color_array)]\n    if isinstance(item, dict):\n        for k, v in item.items():\n            if isinstance(v, (str, int)):\n                if \"error\" in k.lower():\n                    color = Color.BRIGHT_RED\n                    k = \"ERROR\"\n                elif k.lower() == \"warning\":\n                    color = Color.BRIGHT_YELLOW\n                    k = \"WARN\"\n                color = Color.BRIGHT_RED if k == \"expected\" else color\n                color = Color.BRIGHT_GREEN if k == \"existing\" else color\n                cli_out_write(f\"{indent}{k}: {v}\", fg=color)\n            else:\n                cli_out_write(f\"{indent}{k}\", fg=color)\n                print_serial(v, indent, color_index)\n    elif isinstance(item, type([])):\n        for elem in item:\n            cli_out_write(f\"{indent}{elem}\", fg=color)\n    elif isinstance(item, int):  # Can print 0\n        cli_out_write(f\"{indent}{item}\", fg=color)\n    elif item:\n        cli_out_write(f\"{indent}{item}\", fg=color)\n\n\ndef print_list_text(results):\n    \"\"\" Do a little format modification to serialized\n    package list, so it looks prettier on text output\n    \"\"\"\n    info = results[\"results\"]\n\n    # Extract command single package name\n    new_info = {}\n    for remote, remote_info in info.items():\n        new_remote_info = {}\n        for ref, content in remote_info.items():\n            if ref == \"error\":\n                new_remote_info[ref] = content\n            else:\n                name, _ = ref.split(\"/\", 1)\n                new_remote_info.setdefault(name, {})[ref] = content\n        new_info[remote] = new_remote_info\n    info = new_info\n\n    # TODO: The errors are not being displayed\n    info = {remote: {\"warning\": \"There are no matching recipe references\"} if not values else values\n            for remote, values in info.items()}\n\n    def format_timestamps(item):\n        if isinstance(item, dict):\n            result = {}\n            for k, v in item.items():\n                if isinstance(v, dict) and v.get(\"timestamp\"):\n                    timestamp = v.pop(\"timestamp\")\n                    k = f\"{k} ({_format_timestamp_human(timestamp)})\"\n                result[k] = format_timestamps(v)\n            return result\n        return item\n    info = {remote: format_timestamps(values) for remote, values in info.items()}\n    print_serial(info)\n\n\ndef print_list_compact(results):\n    info = results[\"results\"]\n\n    \"\"\" transform the dictionary into a more compact one, keeping the internals\n    but forming full recipe and package references including revisions at the top levels\n    \"\"\"\n    for remote, remote_info in info.items():\n        if not remote_info or \"error\" in remote_info:\n            info[remote] = {\"warning\": \"There are no matching recipe references\"}\n            continue\n        prepare_pkglist_compact(remote_info)\n\n    print_serial(info)\n\n\ndef prepare_pkglist_compact(pkglist):\n    for ref, ref_info in pkglist.items():\n        new_ref_info = {}\n        for rrev, rrev_info in ref_info.get(\"revisions\", {}).items():\n            new_rrev = f\"{ref}#{rrev}\"\n            timestamp = rrev_info.pop(\"timestamp\", None)\n            if timestamp:\n                new_rrev += f\"%{timestamp} ({_format_timestamp_human(timestamp)})\"\n\n            packages = rrev_info.pop(\"packages\", None)\n            if packages:\n                for pid, pid_info in packages.items():\n                    new_pid = f\"{ref}#{rrev}:{pid}\"\n                    rrev_info[new_pid] = pid_info\n            new_ref_info[new_rrev] = rrev_info\n        pkglist[ref] = new_ref_info\n\n    def compute_common_options(pkgs):\n        \"\"\" compute the common subset of existing options with same values of a set of packages\n        \"\"\"\n        result = {}\n        all_package_options = [p.get(\"info\", {}).get(\"options\") for p in pkgs.values()]\n        all_package_options = [p for p in all_package_options if p]  # filter pkgs without options\n        for package_options in all_package_options:  # Accumulate all options for all binaries\n            result.update(package_options)\n        for package_options in all_package_options:  # Filter those not common to all\n            result = {k: v for k, v in result.items()\n                      if k in package_options and v == package_options[k]}\n        for package_options in all_package_options:\n            for k, v in package_options.items():\n                if v != result.get(k):\n                    result.pop(k, None)\n        return result\n\n    def compact_format_info(local_info, common_options=None):\n        \"\"\" return a dictionary with settings and options in short form for compact format\n        \"\"\"\n        result = {}\n        settings = local_info.pop(\"settings\", None)\n        if settings:  # A bit of pretty order, first OS-ARCH\n            values = [settings.pop(s, None)\n                      for s in (\"os\", \"arch\", \"build_type\", \"compiler\")]\n            values = [v for v in values if v is not None]\n            values.extend(settings.values())\n            result[\"settings\"] = \", \".join(values)\n        options = local_info.pop(\"options\", None)\n        if options:\n            if common_options is not None:\n                options = {k: v for k, v in options.items() if k not in common_options}\n            options = \", \".join(f\"{k}={v}\" for k, v in options.items())\n            options_tag = \"options(diff)\" if common_options is not None else \"options\"\n            result[options_tag] = options\n        for k, v in local_info.items():\n            if isinstance(v, dict):\n                v = \", \".join(f\"{kv}={vv}\" for kv, vv in v.items())\n            elif isinstance(v, type([])):\n                v = \", \".join(v)\n            if v:\n                result[k] = v\n        return result\n\n    def compact_diff(diffinfo):\n        \"\"\" return a compact and red/green diff for binary differences\n        \"\"\"\n        result = {}\n        for k, v in diffinfo.items():\n            if not v:\n                continue\n            if isinstance(v, dict):\n                result[k] = {\"expected\": \", \".join(value for value in v[\"expected\"]),\n                             \"existing\": \", \".join(value for value in v[\"existing\"])}\n            else:\n                result[k] = v\n        return result\n\n    for ref, revisions in pkglist.items():\n        if not isinstance(revisions, dict):\n            continue\n        for rrev, prefs in revisions.items():\n            pkg_common_options = compute_common_options(prefs)\n            pkg_common_options = pkg_common_options if len(pkg_common_options) > 4 else None\n            for pref, pref_contents in prefs.items():\n                pref_info = pref_contents.pop(\"info\", None)\n                if pref_info is not None:\n                    pref_contents.update(compact_format_info(pref_info, pkg_common_options))\n                diff_info = pref_contents.pop(\"diff\", None)\n                if diff_info is not None:\n                    pref_contents[\"diff\"] = compact_diff(diff_info)\n\n\ndef print_list_json(data):\n    results = data[\"results\"]\n    myjson = json.dumps(results, indent=4)\n    cli_out_write(myjson)\n\n\n@conan_command(group=\"Consumer\", formatters={\"text\": print_list_text,\n                                             \"json\": print_list_json,\n                                             \"html\": list_packages_html,\n                                             \"compact\": print_list_compact})\ndef list(conan_api: ConanAPI, parser, *args):\n    \"\"\"\n    List existing recipes, revisions, or packages in the cache (by default) or the remotes.\n    \"\"\"\n    parser.add_argument('pattern', nargs=\"?\",\n                        help=\"A pattern in the form 'pkg/version#revision:package_id#revision', \"\n                             \"e.g: \\\"zlib/1.2.13:*\\\" means all binaries for zlib/1.2.13. \"\n                             \"If revision is not specified, it is assumed latest one.\")\n    parser.add_argument('-p', '--package-query', default=None, action=OnceArgument,\n                        help=\"List only the packages matching a specific query, e.g, os=Windows AND \"\n                             \"(arch=x86 OR compiler=gcc)\")\n    parser.add_argument('-fp', '--filter-profile', action=\"append\",\n                        help=\"Profiles to filter the binaries\")\n    parser.add_argument('-fs', '--filter-settings', action=\"append\",\n                        help=\"Settings to filter the binaries\")\n    parser.add_argument('-fo', '--filter-options', action=\"append\",\n                        help=\"Options to filter the binaries\")\n    parser.add_argument(\"-r\", \"--remote\", default=None, action=\"append\",\n                        help=\"Remote names. Accepts wildcards ('*' means all the remotes available)\")\n    parser.add_argument(\"-c\", \"--cache\", action='store_true', help=\"Search in the local cache\")\n    parser.add_argument(\"-g\", \"--graph\", help=\"Graph json file\")\n    parser.add_argument(\"-gb\", \"--graph-binaries\", help=\"Which binaries are listed\", action=\"append\")\n    parser.add_argument(\"-gr\", \"--graph-recipes\", help=\"Which recipes are listed\", action=\"append\")\n    parser.add_argument(\"-gc\", \"--graph-context\", help=\"Filter the results by the given context\",\n                        default=None, action=OnceArgument,\n                        choices=[\"build\", \"host\", \"build-only\", \"host-only\"])\n    parser.add_argument('--lru', default=None, action=OnceArgument,\n                        help=\"List recipes and binaries that have not been recently used. Use a\"\n                             \" time limit like --lru=5d (days) or --lru=4w (weeks),\"\n                             \" h (hours), m(minutes)\")\n\n    args = parser.parse_args(*args)\n\n    if args.pattern is None and args.graph is None:\n        args.pattern = \"*\"  # All packages\n    if args.graph:  # a few arguments are not compatible with this\n        if args.pattern:\n            raise ConanException(\"Cannot define both the pattern and the graph json file\")\n        if args.lru:\n            raise ConanException(\"Cannot define lru when loading a graph json file\")\n        if args.filter_profile or args.filter_settings or args.filter_options:\n            raise ConanException(\"Filtering binaries cannot be done when loading a graph json file\")\n    if (args.graph_recipes or args.graph_binaries) and not args.graph:\n        raise ConanException(\"--graph-recipes and --graph-binaries require a --graph input\")\n    if args.remote and args.lru:\n        raise ConanException(\"'--lru' cannot be used in remotes, only in cache\")\n\n    if args.graph:\n        graphfile = make_abs_path(args.graph)\n        pkglist = MultiPackagesList.load_graph(graphfile, args.graph_recipes, args.graph_binaries,\n                                               context=args.graph_context)\n    else:\n        ref_pattern = ListPattern(args.pattern, rrev=None, prev=None)\n        if not ref_pattern.package_id and (args.package_query or args.filter_profile or\n                                           args.filter_settings or args.filter_options):\n            raise ConanException(\"--package-query and --filter-xxx can only be done for binaries, \"\n                                 \"a 'pkgname/version:*' pattern is necessary\")\n        if args.lru:\n            if not ref_pattern.rrev and not ref_pattern.package_id:  # If package_id => #latest\n                raise ConanException(\"'--lru' must be used with recipe revision pattern, \"\n                                     \"use 'pkg/version#*' argument\")\n            if ref_pattern.package_id and not ref_pattern.prev:\n                raise ConanException(\"'--lru' must be used with package revision pattern, \"\n                                     \"use 'pkg/version:*#*' argument\")\n        # If neither remote nor cache are defined, show results only from cache\n        pkglist = MultiPackagesList()\n        profile = conan_api.profiles.get_profile(args.filter_profile or [],\n                                                 args.filter_settings,\n                                                 args.filter_options) \\\n            if args.filter_profile or args.filter_settings or args.filter_options else None\n        if args.cache or not args.remote:\n            try:\n                cache_list = conan_api.list.select(ref_pattern, args.package_query, remote=None,\n                                                   lru=args.lru, profile=profile)\n            except Exception as e:\n                pkglist.add_error(\"Local Cache\", str(e))\n            else:\n                pkglist.add(\"Local Cache\", cache_list)\n        if args.remote:\n            remotes = conan_api.remotes.list(args.remote)\n            for remote in remotes:\n                try:\n                    remote_list = conan_api.list.select(ref_pattern, args.package_query, remote,\n                                                        profile=profile)\n                except Exception as e:\n                    pkglist.add_error(remote.name, str(e))\n                else:\n                    pkglist.add(remote.name, remote_list)\n\n    return {\n        \"results\": pkglist.serialize(),\n        \"conan_api\": conan_api,\n        \"cli_args\": \" \".join([f\"{arg}={getattr(args, arg)}\" for arg in vars(args) if getattr(args, arg)])\n    }\n"
  },
  {
    "path": "conan/cli/commands/lock.py",
    "content": "import os\n\nfrom conan.api.output import ConanOutput\nfrom conan.cli.command import conan_command, OnceArgument, conan_subcommand\n\nfrom conan.cli import make_abs_path\nfrom conan.cli.args import common_graph_args, validate_common_graph_args\nfrom conan.cli.printers.graph import print_graph_packages, print_graph_basic\nfrom conan.errors import ConanException\nfrom conan.api.model import RecipeReference\n\n\n@conan_command(group=\"Consumer\")\ndef lock(conan_api, parser, *args):  # noqa\n    \"\"\"\n    Create or manage lockfiles.\n    \"\"\"\n\n\n@conan_subcommand()\ndef lock_create(conan_api, parser, subparser, *args):\n    \"\"\"\n    Create a lockfile from a conanfile or a reference.\n    \"\"\"\n    common_graph_args(subparser)\n    subparser.add_argument(\"--build-require\", action='store_true', default=False,\n                           help='Whether the provided reference is a build-require')\n    args = parser.parse_args(*args)\n    # parameter validation\n    validate_common_graph_args(args)\n\n    cwd = os.getcwd()\n    path = conan_api.local.get_conanfile_path(args.path, cwd, py=None) if args.path else None\n    remotes = conan_api.remotes.list(args.remote) if not args.no_remote else []\n    overrides = eval(args.lockfile_overrides) if args.lockfile_overrides else None\n    lockfile = conan_api.lockfile.get_lockfile(lockfile=args.lockfile, conanfile_path=path,\n                                               cwd=cwd, partial=True, overrides=overrides)\n    profile_host, profile_build = conan_api.profiles.get_profiles_from_args(args)\n\n    if path:\n        graph = conan_api.graph.load_graph_consumer(path, args.name, args.version,\n                                                    args.user, args.channel,\n                                                    profile_host, profile_build, lockfile,\n                                                    remotes, args.update,\n                                                    is_build_require=args.build_require)\n    else:\n        graph = conan_api.graph.load_graph_requires(args.requires, args.tool_requires,\n                                                    profile_host, profile_build, lockfile,\n                                                    remotes, args.update)\n\n    print_graph_basic(graph)\n    graph.report_graph_error()\n    conan_api.graph.analyze_binaries(graph, args.build, remotes=remotes, update=args.update,\n                                     lockfile=lockfile)\n    print_graph_packages(graph)\n\n    lockfile = conan_api.lockfile.update_lockfile(lockfile, graph, args.lockfile_packages,\n                                                  clean=args.lockfile_clean)\n    conanfile_path = os.path.dirname(graph.root.path) \\\n        if graph.root.path and args.lockfile_out is None else cwd\n    conan_api.lockfile.save_lockfile(lockfile, args.lockfile_out or \"conan.lock\", conanfile_path)\n\n\n@conan_subcommand()\ndef lock_merge(conan_api, parser, subparser, *args): # noqa\n    \"\"\"\n    Merge 2 or more lockfiles.\n    \"\"\"\n    subparser.add_argument('--lockfile', action=\"append\", help='Path to lockfile to be merged')\n    subparser.add_argument(\"--lockfile-out\", action=OnceArgument, default=\"conan.lock\",\n                           help=\"Filename of the created lockfile\")\n\n    args = parser.parse_args(*args)\n    result = conan_api.lockfile.merge_lockfiles(args.lockfile)\n    lockfile_out = make_abs_path(args.lockfile_out)\n    result.save(lockfile_out)\n    ConanOutput().info(\"Generated lockfile: %s\" % lockfile_out)\n\n\n@conan_subcommand()\ndef lock_add(conan_api, parser, subparser, *args):\n    \"\"\"\n    Add requires, build-requires or python-requires to an existing or new lockfile.\n    The resulting lockfile will be ordered, newer versions/revisions first.\n    References can be supplied with and without revisions like \"--requires=pkg/version\",\n    but they must be recipe references, including at least the version,\n    and they cannot contain a version range.\n    \"\"\"\n    subparser.add_argument('--requires', action=\"append\", help='Add references to lockfile.')\n    subparser.add_argument('--build-requires', action=\"append\",\n                           help='Add build-requires to lockfile')\n    subparser.add_argument('--python-requires', action=\"append\",\n                           help='Add python-requires to lockfile')\n    subparser.add_argument('--config-requires', action=\"append\",\n                           help='Add config-requires to lockfile')\n    subparser.add_argument(\"--lockfile-out\", action=OnceArgument, default=\"conan.lock\",\n                           help=\"Filename of the created lockfile\")\n    subparser.add_argument(\"--lockfile\", action=OnceArgument, help=\"Filename of the input lockfile\")\n    args = parser.parse_args(*args)\n\n    lockfile = conan_api.lockfile.get_lockfile(lockfile=args.lockfile, partial=True)\n\n    allow_uppercase = conan_api.config.get(\"core:allow_uppercase_pkg_names\", check_type=bool)\n\n    def _parse_requires(reqs):\n        if reqs:\n            result = [RecipeReference.loads(r) for r in reqs]\n            [r.validate_ref(allow_uppercase) for r in result]\n            return result\n\n    requires = _parse_requires(args.requires)\n    build_requires = _parse_requires(args.build_requires)\n    python_requires = _parse_requires(args.python_requires)\n    config_requires = _parse_requires(args.config_requires)\n\n    lockfile = conan_api.lockfile.add_lockfile(lockfile,\n                                               requires=requires,\n                                               python_requires=python_requires,\n                                               build_requires=build_requires,\n                                               config_requires=config_requires)\n    conan_api.lockfile.save_lockfile(lockfile, args.lockfile_out)\n\n\n@conan_subcommand()\ndef lock_remove(conan_api, parser, subparser, *args):\n    \"\"\"\n    Remove requires, build-requires or python-requires from an existing lockfile.\n    References can be supplied with and without revisions like \"--requires=pkg/version\",\n    \"\"\"\n    subparser.add_argument('--requires', action=\"append\", help='Remove references to lockfile.')\n    subparser.add_argument('--build-requires', action=\"append\",\n                           help='Remove build-requires from lockfile')\n    subparser.add_argument('--python-requires', action=\"append\",\n                           help='Remove python-requires from lockfile')\n    subparser.add_argument('--config-requires', action=\"append\",\n                           help='Remove config-requires from lockfile')\n    subparser.add_argument(\"--lockfile-out\", action=OnceArgument, default=\"conan.lock\",\n                           help=\"Filename of the created lockfile\")\n    subparser.add_argument(\"--lockfile\", action=OnceArgument, help=\"Filename of the input lockfile\")\n    args = parser.parse_args(*args)\n\n    lockfile = conan_api.lockfile.get_lockfile(lockfile=args.lockfile, partial=True)\n    lockfile = conan_api.lockfile.remove_lockfile(lockfile,\n                                                  requires=args.requires,\n                                                  python_requires=args.python_requires,\n                                                  build_requires=args.build_requires,\n                                                  config_requires=args.config_requires)\n    conan_api.lockfile.save_lockfile(lockfile, args.lockfile_out)\n\n\n@conan_subcommand()\ndef lock_update(conan_api, parser, subparser, *args):\n    \"\"\"\n    Update requires, build-requires or python-requires from an existing lockfile.\n    References that matches the arguments package names will be replaced by the arguments.\n    References can be supplied with and without revisions like \"--requires=pkg/version\",\n    \"\"\"\n    subparser.add_argument('--requires', action=\"append\", help='Update references to lockfile.')\n    subparser.add_argument('--build-requires', action=\"append\",\n                           help='Update build-requires from lockfile')\n    subparser.add_argument('--python-requires', action=\"append\",\n                           help='Update python-requires from lockfile')\n    subparser.add_argument('--config-requires', action=\"append\",\n                           help='Update config-requires from lockfile')\n    subparser.add_argument(\"--lockfile-out\", action=OnceArgument, default=\"conan.lock\",\n                           help=\"Filename of the created lockfile\")\n    subparser.add_argument(\"--lockfile\", action=OnceArgument, help=\"Filename of the input lockfile\")\n    args = parser.parse_args(*args)\n\n    lockfile = conan_api.lockfile.get_lockfile(lockfile=args.lockfile, partial=True)\n    lockfile.update(requires=args.requires, build_requires=args.build_requires,\n                    python_requires=args.python_requires, config_requires=args.config_requires)\n    conan_api.lockfile.save_lockfile(lockfile, args.lockfile_out)\n\n\n@conan_subcommand()\ndef lock_upgrade(conan_api, parser, subparser, *args):\n    \"\"\"\n    (Experimental) Upgrade requires, build-requires or python-requires from an existing lockfile\n    given a conanfile or a reference.\n    \"\"\"\n    common_graph_args(subparser)\n    subparser.add_argument('--update-requires', action=\"append\",\n                           help='Update requires from lockfile')\n    subparser.add_argument('--update-build-requires', action=\"append\",\n                           help='Update build-requires from lockfile')\n    subparser.add_argument('--update-python-requires', action=\"append\",\n                           help='Update python-requires from lockfile')\n    subparser.add_argument('--build-require', action='store_true', default=False,\n                           help='Whether the provided reference is a build-require')\n    args = parser.parse_args(*args)\n    # parameter validation\n    validate_common_graph_args(args)\n\n    if not any([args.update_requires, args.update_build_requires, args.update_python_requires]):\n        raise ConanException(\"At least one of --update-requires, --update-build-requires, \"\n                             \"--update-python-requires should be specified\")\n\n    cwd = os.getcwd()\n    path = conan_api.local.get_conanfile_path(args.path, cwd, py=None) if args.path else None\n    remotes = conan_api.remotes.list(args.remote) if not args.no_remote else []\n    overrides = eval(args.lockfile_overrides) if args.lockfile_overrides else None\n    lockfile = conan_api.lockfile.get_lockfile(lockfile=args.lockfile, conanfile_path=path,\n                                               cwd=cwd, partial=True, overrides=overrides)\n    if lockfile is None:\n        raise ConanException(\"No lockfile specified and default conan.lock not found\")\n    profile_host, profile_build = conan_api.profiles.get_profiles_from_args(args)\n\n    # Remove the lockfile entries that will be updated\n    lockfile = conan_api.lockfile.remove_lockfile(lockfile,\n                                                  requires=args.update_requires,\n                                                  python_requires=args.update_python_requires,\n                                                  build_requires=args.update_build_requires)\n    # Resolve new graph\n    if path:\n        graph = conan_api.graph.load_graph_consumer(path, args.name, args.version,\n                                                    args.user, args.channel,\n                                                    profile_host, profile_build, lockfile,\n                                                    remotes, args.update,\n                                                    is_build_require=args.build_require)\n    else:\n        graph = conan_api.graph.load_graph_requires(args.requires, args.tool_requires,\n                                                    profile_host, profile_build, lockfile,\n                                                    remotes, args.update)\n    print_graph_basic(graph)\n    graph.report_graph_error()\n    conan_api.graph.analyze_binaries(graph, args.build, remotes=remotes, update=args.update,\n                                     lockfile=lockfile)\n    print_graph_packages(graph)\n\n    lockfile = conan_api.lockfile.update_lockfile(lockfile, graph, clean=args.lockfile_clean)\n    conan_api.lockfile.save_lockfile(lockfile, args.lockfile_out or \"conan.lock\")\n\n\n@conan_subcommand()\ndef lock_upgrade_config(conan_api, parser, subparser, *args):\n    \"\"\"\n    (Experimental) Upgrade config requires in a lockfile\n    \"\"\"\n    common_graph_args(subparser)\n    subparser.add_argument('--update-config-requires', action=\"append\",\n                           help='Update config-requires from lockfile')\n    args = parser.parse_args(*args)\n    validate_common_graph_args(args)\n\n    if not args.update_config_requires:\n        raise ConanException(\"At least one --update-config-requires should be specified\")\n\n    cwd = os.getcwd()\n    path = conan_api.local.get_conanfile_path(args.path, cwd, py=None) if args.path else None\n    remotes = conan_api.remotes.list(args.remote) if not args.no_remote else []\n    lockfile = conan_api.lockfile.get_lockfile(lockfile=args.lockfile, conanfile_path=path,\n                                               cwd=cwd, partial=True)\n    if lockfile is None:\n        raise ConanException(\"No lockfile specified and default conan.lock not found\")\n    profile_host, profile_build = conan_api.profiles.get_profiles_from_args(args)\n\n    # Remove the lockfile entries that will be updated\n    lockfile = conan_api.lockfile.remove_lockfile(lockfile,\n                                                  config_requires=args.update_config_requires)\n\n    if args.path:\n        path = make_abs_path(args.path)\n        reqs, remotes = conan_api.config.load_conanconfig(path, remotes)\n    else:\n        reqs = [RecipeReference.loads(r) for r in args.requires]\n\n    pkgs = conan_api.config.fetch_packages(reqs, lockfile, remotes, profile_host)\n    refs = [p.ref for p in pkgs]\n    lockfile = conan_api.lockfile.add_lockfile(lockfile, config_requires=refs)\n    conan_api.lockfile.save_lockfile(lockfile, args.lockfile_out or \"conan.lock\")\n"
  },
  {
    "path": "conan/cli/commands/new.py",
    "content": "import os\n\nfrom conan.cli.command import conan_command\n\n\n@conan_command(group=\"Creator\")\ndef new(conan_api, parser, *args):\n    \"\"\"\n    Create a new example recipe and source files from a template.\n    \"\"\"\n    parser.add_argument(\"template\", nargs=\"?\", default=\"\", help=\"Template name, \"\n                        \"either a predefined built-in or a user-provided one. \"\n                        \"Available built-in templates: basic, cmake_lib, cmake_exe, header_lib, \"\n                        \"meson_lib, meson_exe, msbuild_lib, msbuild_exe, bazel_lib, bazel_exe, \"\n                        \"autotools_lib, autotools_exe, premake_lib, premake_exe, local_recipes_index, workspace. \"\n                        \"E.g. 'conan new cmake_lib -d name=hello -d version=0.1'. \"\n                        \"You can define your own templates too by inputting an absolute path \"\n                        \"as your template, or a path relative to your conan home folder.\"\n                        )\n    parser.add_argument(\"-d\", \"--define\", action=\"append\",\n                        help=\"Define a template argument as key=value, e.g., -d name=mypkg\")\n    parser.add_argument(\"-f\", \"--force\", action='store_true',\n                        help=\"Overwrite file if it already exists\")\n    parser.add_argument(\"-o\", \"--output\", help=\"Output folder for the generated files\",\n                        default=os.getcwd())\n\n    args = parser.parse_args(*args)\n    conan_api.new.save_template(args.template, args.define, args.output, args.force)\n"
  },
  {
    "path": "conan/cli/commands/pkglist.py",
    "content": "from conan.api.conan_api import ConanAPI\nfrom conan.api.model import MultiPackagesList\nfrom conan.cli import make_abs_path\nfrom conan.cli.command import conan_command, conan_subcommand\nfrom conan.cli.commands.list import print_list_text, print_list_json\nfrom conan.cli.formatters.list import list_packages_html\n\n\n@conan_command(group=\"Consumer\")\ndef pkglist(conan_api: ConanAPI, parser, *args):  # noqa\n    \"\"\"\n    Several operations over package lists\n    \"\"\"\n\n\n@conan_subcommand(formatters={\"text\": print_list_text,\n                              \"json\": print_list_json,\n                              \"html\": list_packages_html})\ndef pkglist_find_remote(conan_api, parser, subparser, *args):\n    \"\"\"\n    (Experimental) Find the remotes of a list of packages in the cache\n    \"\"\"\n    subparser.add_argument('list', help=\"Input package list\")\n    subparser.add_argument(\"-r\", \"--remote\", default=None, action=\"append\",\n                           help=\"Remote names. Accepts wildcards \"\n                                \"('*' means all the remotes available)\")\n    args = parser.parse_args(*args)\n\n    listfile = make_abs_path(args.list)\n    multi_pkglist = MultiPackagesList.load(listfile)\n    package_list = multi_pkglist[\"Local Cache\"]\n    selected_remotes = conan_api.remotes.list(args.remote)\n    result = conan_api.list.find_remotes(package_list, selected_remotes)\n    return {\n        \"results\": result.serialize(),\n        \"conan_api\": conan_api,\n        \"cli_args\": \" \".join([f\"{arg}={getattr(args, arg)}\"\n                              for arg in vars(args) if getattr(args, arg)])\n    }\n\n\n@conan_subcommand(formatters={\"text\": print_list_text,\n                              \"json\": print_list_json,\n                              \"html\": list_packages_html})\ndef pkglist_merge(conan_api, parser, subparser, *args):\n    \"\"\"\n    (Experimental) Merge several package lists into a single one\n    \"\"\"\n    subparser.add_argument(\"-l\", \"--list\", help=\"Package list file\", action=\"append\")\n    args = parser.parse_args(*args)\n\n    result = MultiPackagesList()\n    for pkg_list in args.list:\n        listfile = make_abs_path(pkg_list)\n        multi_pkglist = MultiPackagesList.load(listfile)\n        result.merge(multi_pkglist)\n\n    return {\n        \"results\": result.serialize(),\n        \"conan_api\": conan_api,\n        \"cli_args\": \" \".join([f\"{arg}={getattr(args, arg)}\"\n                              for arg in vars(args) if getattr(args, arg)])\n    }\n"
  },
  {
    "path": "conan/cli/commands/profile.py",
    "content": "import json\nimport os\n\nfrom conan.api.output import ConanOutput, cli_out_write\nfrom conan.cli.command import conan_command, conan_subcommand\nfrom conan.cli.formatters import default_json_formatter\nfrom conan.cli.args import add_profiles_args\nfrom conan.errors import ConanException\n\n\ndef _print_profiles(profiles):\n    if \"host\" in profiles:\n        ConanOutput().info(\"Host profile:\")\n        cli_out_write(profiles[\"host\"].dumps())\n    if \"build\" in profiles:\n        ConanOutput().info(\"Build profile:\")\n        cli_out_write(profiles[\"build\"].dumps())\n\n\ndef profiles_list_cli_output(profiles):\n    ConanOutput().info(\"Profiles found in the cache:\")\n    for p in profiles:\n        cli_out_write(p)\n\n\ndef _json_profiles(profiles):\n    result = {}\n    if \"host\" in profiles:\n        result[\"host\"] = profiles[\"host\"].serialize()\n    if \"build\" in profiles:\n        result[\"build\"] = profiles[\"build\"].serialize()\n    cli_out_write(json.dumps(result))\n\n\n@conan_subcommand(formatters={\"text\": _print_profiles, \"json\": _json_profiles})\ndef profile_show(conan_api, parser, subparser, *args):\n    \"\"\"\n    Show aggregated profiles from the passed arguments.\n    \"\"\"\n    add_profiles_args(subparser)\n    subparser.add_argument(\"-cx\", \"--context\", choices=[\"host\", \"build\"])\n    args = parser.parse_args(*args)\n    profiles = conan_api.profiles.get_profiles_from_args(args)\n    result = {}\n    if not args.context or args.context == \"host\":\n        result[\"host\"] = profiles[0]\n    if not args.context or args.context == \"build\":\n        result[\"build\"] = profiles[1]\n    return result\n\n\n@conan_subcommand(formatters={\"text\": cli_out_write})\ndef profile_path(conan_api, parser, subparser, *args):\n    \"\"\"\n    Show profile path location.\n    \"\"\"\n    subparser.add_argument(\"name\", help=\"Profile name\")\n    args = parser.parse_args(*args)\n    return conan_api.profiles.get_path(args.name)\n\n\n@conan_subcommand()\ndef profile_detect(conan_api, parser, subparser, *args):\n    \"\"\"\n    Generate a profile using auto-detected values.\n    \"\"\"\n    subparser.add_argument(\"--name\", help=\"Profile name, 'default' if not specified\")\n    subparser.add_argument(\"-f\", \"--force\", action='store_true', help=\"Overwrite if exists\")\n    subparser.add_argument(\"-e\", \"--exist-ok\", action='store_true',\n                           help=\"If the profile already exist, do not detect a new one\")\n    args = parser.parse_args(*args)\n\n    profile_name = args.name or \"default\"\n    profile_pathname = conan_api.profiles.get_path(profile_name, os.getcwd(), exists=False)\n    if os.path.exists(profile_pathname):\n        if args.exist_ok:\n            ConanOutput().info(f\"Profile '{profile_name}' already exists, skipping detection\")\n            return\n        if not args.force:\n            raise ConanException(f\"Profile '{profile_pathname}' already exists\")\n\n    detected_profile = conan_api.profiles.detect()\n    ConanOutput().success(\"\\nDetected profile:\")\n    cli_out_write(detected_profile.dumps())\n\n    contents = detected_profile.dumps()\n    ConanOutput().warning(\"This profile is a guess of your environment, please check it.\")\n    if detected_profile.settings.get(\"os\") == \"Macos\":\n        ConanOutput().warning(\"Defaulted to cppstd='gnu17' for apple-clang.\")\n    ConanOutput().warning(\"The output of this command is not guaranteed to be stable and can \"\n                          \"change in future Conan versions.\")\n    ConanOutput().warning(\"Use your own profile files for stability.\")\n    ConanOutput().success(f\"Saving detected profile to {profile_pathname}\")\n    dir_path = os.path.dirname(profile_pathname)\n    if dir_path:\n        os.makedirs(dir_path, exist_ok=True)\n    with open(profile_pathname, \"w\", encoding=\"utf-8\", newline=\"\") as f:\n        f.write(contents)\n\n\n@conan_subcommand(formatters={\"text\": profiles_list_cli_output, \"json\": default_json_formatter})\ndef profile_list(conan_api, parser, subparser, *args):  # noqa\n    \"\"\"\n    List all profiles in the cache.\n    \"\"\"\n    parser.parse_args(*args)\n    result = conan_api.profiles.list()\n    return result\n\n\n@conan_command(group=\"Consumer\")\ndef profile(conan_api, parser, *args):  # noqa\n    \"\"\"\n    Manage profiles.\n    \"\"\"\n"
  },
  {
    "path": "conan/cli/commands/remote.py",
    "content": "import json\nimport os\nfrom collections import OrderedDict\n\nfrom conan.api.conan_api import ConanAPI\nfrom conan.api.model import Remote, LOCAL_RECIPES_INDEX\nfrom conan.api.output import cli_out_write, Color\nfrom conan.cli import make_abs_path\nfrom conan.cli.command import conan_command, conan_subcommand, OnceArgument\nfrom conan.cli.commands.list import remote_color, error_color, recipe_color, \\\n    reference_color\nfrom conan.errors import ConanException\n\n\ndef _print_remotes_json(remotes):\n    info = [{\"name\": r.name,\n             \"url\": r.url,\n             \"verify_ssl\": r.verify_ssl,\n             \"enabled\": not r.disabled,\n             \"allowed_packages\": r.allowed_packages,\n             \"recipes_only\": r.recipes_only}\n            for r in remotes]\n    cli_out_write(json.dumps(info, indent=4))\n\n\ndef _print_remote_list(remotes):\n    for r in remotes:\n        output_str = str(r)\n        cli_out_write(output_str)\n\n\ndef _print_remote_user_list(results):\n    for remote_name, result in results.items():\n        cli_out_write(f\"{remote_name}:\", fg=remote_color)\n        if result[\"user_name\"] is None:\n            cli_out_write(\"  No user\", fg=error_color)\n        else:\n            cli_out_write(\"  Username: \", fg=recipe_color, endline=\"\")\n            cli_out_write(result[\"user_name\"], fg=reference_color)\n            cli_out_write(\"  authenticated: \", fg=recipe_color, endline=\"\")\n            cli_out_write(result[\"authenticated\"], fg=reference_color)\n\n\ndef _print_remote_user_set(results):\n    for remote_name, result in results.items():\n        from_user = \"'{}'\".format(result[\"previous_info\"][\"user_name\"])\n        from_user += \" (anonymous)\" \\\n            if not result[\"previous_info\"][\"authenticated\"] else \" (authenticated)\"\n        to_user = \"'{}'\".format(result[\"info\"][\"user_name\"])\n        to_user += \" (anonymous)\" \\\n            if not result[\"info\"][\"authenticated\"] else \" (authenticated)\"\n        message = \"Changed user of remote '{}' from {} to {}\".format(remote_name, from_user, to_user)\n        cli_out_write(message)\n\n\ndef _print_remotes_users_json(results):\n    cli_out_write(json.dumps(list(results.values())))\n\n\n@conan_subcommand(formatters={\"text\": _print_remote_list, \"json\": _print_remotes_json})\ndef remote_list(conan_api: ConanAPI, parser, subparser, *args):  # noqa\n    \"\"\"\n    List current remotes.\n    \"\"\"\n    parser.parse_args(*args)\n    return conan_api.remotes.list(only_enabled=False)\n\n\n@conan_subcommand()\ndef remote_add(conan_api, parser, subparser, *args):\n    \"\"\"\n    Add a remote.\n    \"\"\"\n    subparser.add_argument(\"name\", help=\"Name of the remote to add\")\n    subparser.add_argument(\"url\", help=\"Url of the remote\")\n    subparser.add_argument(\"--insecure\", dest=\"secure\", action='store_false',\n                           help=\"Allow insecure server connections when using SSL\")\n    subparser.add_argument(\"--index\", action=OnceArgument, type=int,\n                           help=\"Insert the remote at a specific position in the remote list\")\n    subparser.add_argument(\"-f\", \"--force\", action='store_true',\n                           help=\"Force the definition of the remote even if duplicated\")\n    subparser.add_argument(\"-ap\", \"--allowed-packages\", action=\"append\", default=None,\n                           help=\"Add recipe reference pattern to list of allowed packages for \"\n                                \"this remote\")\n    subparser.add_argument(\"-t\", \"--type\", choices=[LOCAL_RECIPES_INDEX],\n                           help=\"Define the remote type\")\n    subparser.add_argument(\"--recipes-only\", action=\"store_true\", default=False,\n                           help=\"Disallow binary downloads from this remote, only recipes \"\n                                \"will be downloaded\")\n\n    subparser.set_defaults(secure=True)\n    args = parser.parse_args(*args)\n\n    url_folder = make_abs_path(args.url)\n    remote_type = args.type or (LOCAL_RECIPES_INDEX if os.path.isdir(url_folder) else None)\n    url = url_folder if remote_type == LOCAL_RECIPES_INDEX else args.url\n    r = Remote(args.name, url, args.secure, disabled=False, remote_type=remote_type,\n               allowed_packages=args.allowed_packages,\n               recipes_only=args.recipes_only)\n    conan_api.remotes.add(r, force=args.force, index=args.index)\n\n\n@conan_subcommand(formatters={\"text\": _print_remote_list})\ndef remote_remove(conan_api, parser, subparser, *args):\n    \"\"\"\n    Remove remotes.\n    \"\"\"\n    subparser.add_argument(\"remote\", help=\"Name of the remote to remove. \"\n                                          \"Accepts 'fnmatch' style wildcards.\")  # to discuss\n    args = parser.parse_args(*args)\n    remotes = conan_api.remotes.remove(args.remote)\n    cli_out_write(\"Removed remotes:\")\n    return remotes\n\n\n@conan_subcommand()\ndef remote_update(conan_api, parser, subparser, *args):\n    \"\"\"\n    Update a remote.\n    \"\"\"\n    subparser.add_argument(\"remote\", help=\"Name of the remote to update\")\n    subparser.add_argument(\"--url\", action=OnceArgument, help=\"New url for the remote\")\n    subparser.add_argument(\"--secure\", dest=\"secure\", action='store_true',\n                           help=\"Don't allow insecure server connections when using SSL\")\n    subparser.add_argument(\"--insecure\", dest=\"secure\", action='store_false',\n                           help=\"Allow insecure server connections when using SSL\")\n    subparser.add_argument(\"--index\", action=OnceArgument, type=int,\n                           help=\"Insert the remote at a specific position in the remote list\")\n    subparser.add_argument(\"-ap\", \"--allowed-packages\", action=\"append\", default=None,\n                           help=\"Add recipe reference pattern to the list of allowed packages \"\n                                \"for this remote\")\n    subparser.add_argument(\"--recipes-only\", default=None, const=\"True\", nargs=\"?\",\n                           choices=[\"True\", \"False\"],\n                           help=\"Disallow binary downloads from this remote, only recipes will \"\n                                \"be downloaded\")\n\n    subparser.set_defaults(secure=None)\n    args = parser.parse_args(*args)\n    if (args.url is None and args.secure is None and args.index is None and\n            args.allowed_packages is None and args.recipes_only is None):\n        subparser.error(\"Please add at least one argument to update\")\n    args.recipes_only = None if args.recipes_only is None else args.recipes_only == \"True\"\n    conan_api.remotes.update(args.remote, args.url, args.secure, index=args.index,\n                             allowed_packages=args.allowed_packages,\n                             recipes_only=args.recipes_only)\n\n\n@conan_subcommand()\ndef remote_rename(conan_api, parser, subparser, *args):\n    \"\"\"\n    Rename a remote.\n    \"\"\"\n    subparser.add_argument(\"remote\", help=\"Current name of the remote\")\n    subparser.add_argument(\"new_name\", help=\"New name for the remote\")\n    args = parser.parse_args(*args)\n    conan_api.remotes.rename(args.remote, args.new_name)\n\n\n@conan_subcommand(formatters={\"text\": _print_remote_list, \"json\": _print_remotes_json})\ndef remote_enable(conan_api, parser, subparser, *args):\n    \"\"\"\n    Enable all the remotes matching a pattern.\n    \"\"\"\n    subparser.add_argument(\"remote\", help=\"Pattern of the remote/s to enable. \"\n                                          \"The pattern uses 'fnmatch' style wildcards.\")\n    args = parser.parse_args(*args)\n    return conan_api.remotes.enable(args.remote)\n\n\n@conan_subcommand(formatters={\"text\": _print_remote_list, \"json\": _print_remotes_json})\ndef remote_disable(conan_api, parser, subparser, *args):\n    \"\"\"\n    Disable all the remotes matching a pattern.\n    \"\"\"\n    subparser.add_argument(\"remote\", help=\"Pattern of the remote/s to disable. \"\n                                          \"The pattern uses 'fnmatch' style wildcards.\")\n    args = parser.parse_args(*args)\n    return conan_api.remotes.disable(args.remote)\n\n\n# ### User related commands\n\n@conan_subcommand(formatters={\"text\": _print_remote_user_list, \"json\": _print_remotes_users_json})\ndef remote_list_users(conan_api, parser, subparser, *args):  # noqa\n    \"\"\"\n    List the users logged into all the remotes.\n    \"\"\"\n    parser.parse_args(*args)\n    remotes = conan_api.remotes.list()\n    ret = OrderedDict()\n    if not remotes:\n        raise ConanException(\"No remotes defined\")\n    for r in remotes:\n        ret[r.name] = conan_api.remotes.user_info(r)\n\n    return ret\n\n\n@conan_subcommand(formatters={\"text\": _print_remote_user_set, \"json\": _print_remotes_users_json})\ndef remote_login(conan_api, parser, subparser, *args):\n    \"\"\"\n    Login into the specified remotes matching a pattern.\n    \"\"\"\n    subparser.add_argument(\"remote\", help=\"Pattern or name of the remote to login into. \"\n                                          \"The pattern uses 'fnmatch' style wildcards.\")\n    subparser.add_argument(\"username\", nargs=\"?\", help='Username')\n    subparser.add_argument(\"-p\", \"--password\", nargs='?', type=str, action=OnceArgument,\n                           help='User password. Use double quotes if password with spacing, '\n                                'and escape quotes if existing. If empty, the password is '\n                                'requested interactively (not exposed)')\n\n    args = parser.parse_args(*args)\n    remotes = conan_api.remotes.list(pattern=args.remote, only_enabled=False)\n    if not remotes:\n        raise ConanException(\"There are no remotes matching the '{}' pattern\".format(args.remote))\n    return conan_api.remotes.login(remotes, args.username, args.password)\n\n\n@conan_subcommand(formatters={\"text\": _print_remote_user_set, \"json\": _print_remotes_users_json})\ndef remote_set_user(conan_api, parser, subparser, *args):\n    \"\"\"\n    Associate a username with a remote matching a pattern without performing the authentication.\n    \"\"\"\n    subparser.add_argument(\"remote\", help=\"Pattern or name of the remote. \"\n                                          \"The pattern uses 'fnmatch' style wildcards.\")\n    subparser.add_argument(\"username\", help='Username')\n\n    args = parser.parse_args(*args)\n    remotes = conan_api.remotes.list(pattern=args.remote)\n    if not remotes:\n        raise ConanException(\"There are no remotes matching the '{}' pattern\".format(args.remote))\n\n    ret = OrderedDict()\n    for r in remotes:\n        previous_info = conan_api.remotes.user_info(r)\n        if previous_info[\"user_name\"] != args.username:\n            conan_api.remotes.user_logout(r)\n            conan_api.remotes.user_set(r, args.username)\n        ret[r.name] = {\"previous_info\": previous_info, \"info\": conan_api.remotes.user_info(r)}\n    return ret\n\n\n@conan_subcommand(formatters={\"text\": _print_remote_user_set, \"json\": _print_remotes_users_json})\ndef remote_logout(conan_api, parser, subparser, *args):\n    \"\"\"\n    Clear the existing credentials for the specified remotes matching a pattern.\n    \"\"\"\n    subparser.add_argument(\"remote\", help=\"Pattern or name of the remote to logout. \"\n                                          \"The pattern uses 'fnmatch' style wildcards.\")\n    args = parser.parse_args(*args)\n    remotes = conan_api.remotes.list(pattern=args.remote)\n    if not remotes:\n        raise ConanException(\"There are no remotes matching the '{}' pattern\".format(args.remote))\n\n    ret = OrderedDict()\n    for r in remotes:\n        previous_info = conan_api.remotes.user_info(r)\n        conan_api.remotes.user_logout(r)\n        info = conan_api.remotes.user_info(r)\n        ret[r.name] = {\"previous_info\": previous_info, \"info\": info}\n    return ret\n\n\ndef _print_auth(remotes):\n    for remote_name, msg in remotes.items():\n        if msg is None:\n            cli_out_write(f\"{remote_name}: No user defined\")\n        else:\n            cli_out_write(f\"{remote_name}:\")\n            for k, v in msg.items():\n                cli_out_write(f\"    {k}: {v}\", fg=Color.BRIGHT_RED if k == \"error\" else Color.WHITE)\n\n\ndef _print_auth_json(results):\n    cli_out_write(json.dumps(results))\n\n\n@conan_subcommand(formatters={\"text\": _print_auth, \"json\": _print_auth_json})\ndef remote_auth(conan_api, parser, subparser, *args):\n    \"\"\"\n    Authenticate in the defined remotes. Use CONAN_LOGIN_USERNAME* and CONAN_PASSWORD* variables\n    if available.\n    Ask for username and password interactively in case (re-)authentication is required and there are\n    no CONAN_LOGIN* and CONAN_PASSWORD* variables available which could be used.\n    Usually you'd use this method over conan remote login for scripting which needs to run in CI\n    and locally.\n    \"\"\"\n    subparser.add_argument(\"remote\", help=\"Pattern or name of the remote/s to authenticate against.\"\n                                          \" The pattern uses 'fnmatch' style wildcards.\")\n    subparser.add_argument(\"--with-user\", action=\"store_true\",\n                           help=\"Only try to auth in those remotes that already \"\n                                \"have a username or a CONAN_LOGIN_USERNAME* env-var defined\")\n    subparser.add_argument(\"--force\", action=\"store_true\",\n                           help=\"Force authentication for anonymous-enabled repositories. \"\n                                \"Can be used for force authentication in case your Artifactory \"\n                                \"instance has anonymous access enabled and Conan would not ask \"\n                                \"for username and password even for non-anonymous repositories \"\n                                \"if not yet authenticated.\")\n    args = parser.parse_args(*args)\n    remotes = conan_api.remotes.list(pattern=args.remote)\n    if not remotes:\n        raise ConanException(\"There are no remotes matching the '{}' pattern\".format(args.remote))\n\n    results = {}\n    for r in remotes:\n        try:\n            results[r.name] = {\"user\": conan_api.remotes.user_auth(r, args.with_user, args.force)}\n        except Exception as e:\n            results[r.name] = {\"error\": str(e)}\n    return results\n\n\n@conan_command(group=\"Consumer\")\ndef remote(conan_api, parser, *args):  # noqa\n    \"\"\"\n    Manage the remote list and the users authenticated on them.\n    \"\"\"\n"
  },
  {
    "path": "conan/cli/commands/remove.py",
    "content": "from conan.api.conan_api import ConanAPI\nfrom conan.api.model import ListPattern, MultiPackagesList, PackagesList\nfrom conan.api.output import cli_out_write, ConanOutput\nfrom conan.api.input import UserInput\nfrom conan.cli import make_abs_path\nfrom conan.cli.command import conan_command, OnceArgument\nfrom conan.cli.commands.list import print_list_json, print_serial\nfrom conan.errors import ConanException\n\n\ndef summary_remove_list(results):\n    \"\"\" Do a little format modification to serialized\n    package list so it looks prettier on text output\n    \"\"\"\n    cli_out_write(\"Remove summary:\")\n    info = results[\"results\"]\n    result = {}\n    for remote, remote_info in info.items():\n        new_info = result.setdefault(remote, {})\n        for ref, content in remote_info.items():\n            for rev, rev_content in content.get(\"revisions\", {}).items():\n                pkgids = rev_content.get('packages')\n                if pkgids is None:\n                    new_info.setdefault(f\"{ref}#{rev}\", \"Removed recipe and all binaries\")\n                else:\n                    new_info.setdefault(f\"{ref}#{rev}\", f\"Removed binaries: {list(pkgids)}\")\n    print_serial(result)\n\n\n@conan_command(group=\"Consumer\", formatters={\"text\": summary_remove_list,\n                                             \"json\": print_list_json})\ndef remove(conan_api: ConanAPI, parser, *args):\n    \"\"\"\n    Remove recipes or packages from local cache or a remote.\n\n    - If no remote is specified (-r), the removal will be done in the local conan cache.\n    - If a recipe reference is specified, it will remove the recipe and all the packages, unless -p\n      is specified, in that case, only the packages matching the specified query (and not the recipe)\n      will be removed.\n    - If a package reference is specified, it will remove only the package.\n    \"\"\"\n    parser.add_argument('pattern', nargs=\"?\",\n                        help=\"A pattern in the form 'pkg/version#revision:package_id#revision', \"\n                             \"e.g: \\\"zlib/1.2.13:*\\\" means all binaries for zlib/1.2.13. \"\n                             \"If revision is not specified, it is assumed latest one.\")\n    parser.add_argument('-c', '--confirm', default=False, action='store_true',\n                        help='Remove without requesting a confirmation')\n    parser.add_argument('-p', '--package-query', action=OnceArgument,\n                        help=\"Remove all packages (empty) or provide a query: \"\n                             \"os=Windows AND (arch=x86 OR compiler=gcc)\")\n    parser.add_argument('-r', '--remote', action=OnceArgument,\n                        help='Will remove from the specified remote')\n    parser.add_argument(\"-l\", \"--list\", help=\"Package list file\")\n    parser.add_argument('--lru', default=None, action=OnceArgument,\n                        help=\"Remove recipes and binaries that have not been recently used. Use a\"\n                             \" time limit like --lru=5d (days) or --lru=4w (weeks),\"\n                             \" h (hours), m(minutes)\")\n    parser.add_argument(\"--dry-run\", default=False, action=\"store_true\",\n                        help=\"Do not remove any items, only print those which would be removed\")\n    args = parser.parse_args(*args)\n\n    if args.pattern is None and args.list is None:\n        raise ConanException(\"Missing pattern or package list file\")\n    if args.pattern and args.list:\n        raise ConanException(\"Cannot define both the pattern and the package list file\")\n    if args.package_query and args.list:\n        raise ConanException(\"Cannot define package-query and the package list file\")\n    if args.remote and args.lru:\n        raise ConanException(\"'--lru' cannot be used in remotes, only in cache\")\n    if args.list and args.lru:\n        raise ConanException(\"'--lru' cannot be used with input package list\")\n\n    ui = UserInput(conan_api.config.get(\"core:non_interactive\"))\n    remote = conan_api.remotes.get(args.remote) if args.remote else None\n    cache_name = \"Local Cache\" if not remote else remote.name\n\n    def confirmation(message):\n        return args.confirm or ui.request_boolean(message)\n\n    if args.list:\n        listfile = make_abs_path(args.list)\n        multi_package_list = MultiPackagesList.load(listfile)\n        package_list = multi_package_list[cache_name]\n        refs_to_remove = list(package_list.items())\n        if not refs_to_remove:  # the package list might contain only refs, no revs\n            ConanOutput().warning(\"Nothing to remove, package list do not contain recipe revisions\")\n    else:\n        ref_pattern = ListPattern(args.pattern, rrev=\"*\", prev=\"*\")\n        if ref_pattern.package_id is None and args.package_query is not None:\n            raise ConanException('--package-query supplied but the pattern does not match packages')\n        package_list = conan_api.list.select(ref_pattern, args.package_query, remote, lru=args.lru)\n        multi_package_list = MultiPackagesList()\n        multi_package_list.add(cache_name, package_list)\n\n    result = PackagesList()\n    for ref, packages in package_list.items():\n        ref_dict = package_list.recipe_dict(ref).copy()\n        packages_dict = ref_dict.pop(\"packages\", None)\n        if packages_dict is None:\n            if confirmation(f\"Remove the recipe and all the packages of '{ref.repr_notime()}'?\"):\n                if not args.dry_run:\n                    conan_api.remove.recipe(ref, remote=remote)\n                result.add_ref(ref)\n                result.recipe_dict(ref).update(ref_dict)  # it doesn't contain \"packages\"\n        else:\n            if not packages:  # weird, there is inner package-ids but without prevs\n                ConanOutput().info(f\"No binaries to remove for '{ref.repr_notime()}'\")\n                continue\n            for pref, pkg_id_info in packages.items():\n                if confirmation(f\"Remove the package '{pref.repr_notime()}'?\"):\n                    if not args.dry_run:\n                        conan_api.remove.package(pref, remote=remote)\n                    result.add_ref(ref)\n                    result.recipe_dict(ref).update(ref_dict)  # it doesn't contain \"packages\"\n                    result.add_pref(pref, pkg_id_info)\n                    pkg_dict = package_list.package_dict(pref)\n                    result.package_dict(pref).update(pkg_dict)\n    multi_package_list.add(cache_name, result)\n\n    return {\n        \"results\": multi_package_list.serialize(),\n        \"conan_api\": conan_api\n    }\n"
  },
  {
    "path": "conan/cli/commands/report.py",
    "content": "import os\n\nfrom conan.cli.formatters.report import format_diff_html, format_diff_txt, format_diff_json\nfrom conan.api.conan_api import ConanAPI\nfrom conan.cli.command import conan_command, conan_subcommand\n\n\n@conan_command(group=\"Security\")\ndef report(conan_api: ConanAPI, parser, *args):\n    \"\"\"\n    Gets information about the recipe and its sources.\n    \"\"\"\n\n\n@conan_subcommand(formatters={\"text\": format_diff_txt,\n                              \"json\": format_diff_json,\n                              \"html\": format_diff_html})\ndef report_diff(conan_api, parser, subparser, *args):\n    \"\"\"\n    Get the difference between two recipes with their sources.\n    It can be used to compare two different versions of the same recipe, or two different recipe revisions.\n\n    Each old/new recipe can be specified by a path to a conanfile.py and a companion reference,\n    or by a reference only.\n\n    If only a reference is specified, it will be searched in the local cache,\n    or downloaded from the specified remotes. If no revision is specified, the latest revision will be used.\n    \"\"\"\n\n    ref_help = (\"{type} reference, e.g. 'mylib/1.0'. \"\n                \"If used on its own, it can contain a revision, which will be resolved to the latest one if not provided, \"\n                \"but it will be ignored if a path is specified. \"\n                \"If used with a path, it will be used to create the reference for the recipe to be compared.\")\n\n    subparser.add_argument(\"-op\", \"--old-path\", help=\"Path to the old recipe if comparing a local recipe is desired\")\n    subparser.add_argument(\"-or\", \"--old-reference\", help=ref_help.format(type=\"Old\"), required=True)\n\n    subparser.add_argument(\"-np\", \"--new-path\", help=\"Path to the new recipe if comparing a local recipe is desired\")\n    subparser.add_argument(\"-nr\", \"--new-reference\", help=ref_help.format(type=\"New\"), required=True)\n\n    subparser.add_argument(\"-r\", \"--remote\", action=\"append\", default=None,\n                           help='Look in the specified remote or remotes server')\n\n    args = parser.parse_args(*args)\n\n    cwd = os.getcwd()\n    enabled_remotes = conan_api.remotes.list(args.remote or \"*\")\n\n    result = conan_api.report.diff(args.old_reference, args.new_reference, enabled_remotes,\n                                   old_path=args.old_path, new_path=args.new_path, cwd=cwd)\n    return {\n        \"conan_api\": conan_api,\n        \"diff\": result[\"diff\"],\n        \"old_export_ref\": result[\"old_export_ref\"],\n        \"new_export_ref\": result[\"new_export_ref\"],\n        \"old_cache_path\": result[\"old_cache_path\"],\n        \"new_cache_path\": result[\"new_cache_path\"],\n        \"src_prefix\": result[\"src_prefix\"],\n        \"dst_prefix\": result[\"dst_prefix\"],\n    }\n"
  },
  {
    "path": "conan/cli/commands/require.py",
    "content": "import os\nimport re\n\nfrom conan.api.conan_api import ConanAPI\nfrom conan.api.model import ListPattern, RecipeReference\nfrom conan.api.output import ConanOutput\nfrom conan.cli.command import conan_command, conan_subcommand\nfrom conan.errors import ConanException\nfrom conan.internal.util.files import save, load\n\n\n@conan_subcommand()\ndef require_remove(conan_api, parser, subparser, *args):\n    \"\"\"\n    Removes a requirement from your local conanfile.\n    \"\"\"\n    subparser.add_argument(\"--folder\",\n                           help=\"Path to a folder containing a recipe (conanfile.py). \"\n                                \"Defaults to the current directory\",)\n    subparser.add_argument(\"requires\", nargs=\"*\", help=\"Requirement name.\")\n    subparser.add_argument(\"-tor\", \"--tool\", action=\"append\", default=[],\n                           help=\"Tool requirement name.\")\n    subparser.add_argument(\"-ter\", \"--test\", action=\"append\", default=[],\n                           help=\"Test requirement name.\")\n    args = parser.parse_args(*args)\n    path = conan_api.local.get_conanfile_path(args.folder or '.', os.getcwd(), py=True)\n    # Check if that requirement exists in the conanfile. If yes, abort.\n    conanfile = load(path)\n    ConanOutput().debug(f\"Loaded conanfile from {path}.\")\n    requires = [(r, \"requires\") for r in args.requires]\n    tool_requires = [(r, \"tool_requires\") for r in args.tool]\n    test_requires = [(r, \"test_requires\") for r in args.test]\n    success_msgs = []\n    for (name, req_attr) in requires + tool_requires + test_requires:\n        if not re.search(rf\"self\\.{req_attr}\\([\\\"']{name}\", conanfile):\n            ConanOutput().warning(f\"The {req_attr} {name} is not declared in your conanfile.\")\n            continue\n        # Replace the whole line\n        conanfile = re.sub(rf\"^\\s*self\\.{req_attr}\\([\\\"']{name}.*\\n?\", '',\n                           conanfile, flags=re.MULTILINE)\n        success_msgs.append(f\"Removed {name} dependency as {req_attr}.\")\n    save(path, conanfile)\n    ConanOutput().success('\\n'.join(success_msgs))\n\n\n@conan_subcommand()\ndef require_add(conan_api, parser, subparser, *args):\n    \"\"\"\n    Add a new requirement to your local conanfile as a version range.\n    By default, it will look for the requirement versions remotely.\n    \"\"\"\n    subparser.add_argument(\"--folder\",\n                           help=\"Path to a folder containing a recipe (conanfile.py). \"\n                                \"Defaults to the current directory\",)\n    subparser.add_argument(\"requires\", nargs=\"*\", help=\"Requirement name.\")\n    subparser.add_argument(\"-tor\", \"--tool\", action=\"append\", default=[],\n                           help=\"Tool requirement name.\")\n    subparser.add_argument(\"-ter\", \"--test\", action=\"append\", default=[],\n                           help=\"Test requirement name.\")\n    group = subparser.add_mutually_exclusive_group()\n    group.add_argument(\"-r\", \"--remote\", default=None, action=\"append\",\n                       help=\"Remote names. Accepts wildcards ('*' means all the remotes available)\")\n    group.add_argument(\"-nr\", \"--no-remote\", action=\"store_true\",\n                       help='Do not use remote, resolve exclusively in the cache')\n    args = parser.parse_args(*args)\n    requires = [(r, \"requires\", \"requirements\") for r in args.requires]\n    tool_requires = [(r, \"tool_requires\", \"build_requirements\") for r in args.tool]\n    test_requires = [(r, \"test_requires\", \"build_requirements\") for r in args.test]\n    if not any(requires + tool_requires + test_requires):\n        raise ConanException(\"You need to add any requires, tool_requires or test_requires.\")\n    path = conan_api.local.get_conanfile_path(args.folder or \".\", os.getcwd(), py=True)\n    remotes = conan_api.remotes.list(args.remote) if not args.no_remote else [None]\n    conanfile = load(path)\n    ConanOutput().debug(f\"Loaded conanfile from {path}.\")\n    cached_results = {}\n    success_msgs = []\n    for (name, req_attr, req_func) in requires + tool_requires + test_requires:\n        # Check if that requirement exists in the conanfile. If yes, do nothing.\n        if re.search(rf\"self\\.{req_attr}\\([\\\"']{name}\", conanfile):\n            ConanOutput().warning(f\"The {req_attr} {name} is already in use.\")\n            continue\n        if name in cached_results:\n            # Avoid double-search in remotes/cache, e.g., protobuf\n            reference = RecipeReference.loads(f\"{name}/{cached_results[name]}\")\n        elif \"/\" in name:  # it already brings a version\n            reference = RecipeReference.loads(name)\n            cached_results[name] = reference.version  # caching the result\n        else:  # Search the latest version in remotes/cache\n            ref_pattern = ListPattern(f\"{name}/*\")\n            # If neither remote nor cache are defined, show results only from cache\n            results = {}\n            for remote in remotes:\n                try:\n                    pkglist = conan_api.list.select(ref_pattern, remote=remote)\n                except Exception as e:\n                    remote_name = \"Cache\" if remote is None else remote.name\n                    ConanOutput().warning(f\"[{remote_name}] {str(e)}\")\n                else:\n                    results = pkglist.serialize()\n                    if results:\n                        break\n            if not results:\n                ConanOutput().error(f\"Recipe {name} not found.\")\n                continue\n            # Put the upper limit for that requirement (next major version)\n            reference = RecipeReference.loads(results.popitem()[0])\n            cached_results[name] = reference.version  # caching the result\n        try:\n            version_range = f\"{reference.name}/[>={reference.version} <{str(reference.version.bump(0))}]\"\n        except ConanException:  # likely cannot bump the version, using it without ranges\n            version_range = str(reference)\n        full_version_range = f'self.{req_attr}(\"{version_range}\")'\n        if full_version_range:\n            tab_space = \" \" * 4\n            if f\"def {req_func}(\" in conanfile:\n                conanfile = conanfile.replace(f\"def {req_func}(self):\\n\",\n                                              f\"def {req_func}(self):\\n{tab_space * 2}{full_version_range}\\n\")\n            else:\n                requirements_func = f\"\\n{tab_space}def {req_func}(self):\\n{tab_space * 2}{full_version_range}\\n\"\n                conanfile += requirements_func\n        success_msgs.append(f\"Added '{version_range}' as a new {req_attr}.\")\n    save(path, conanfile)\n    ConanOutput().success('\\n'.join(success_msgs))\n\n\n@conan_command(group=\"Consumer\")\ndef require(conan_api: ConanAPI, parser, *args):\n    \"\"\"\n    Adds/removes requirements to/from your local conanfile.\n    \"\"\"\n"
  },
  {
    "path": "conan/cli/commands/run.py",
    "content": "import os\nimport tempfile\n\nfrom conan.api.output import ConanOutput, LEVEL_STATUS, Color, LEVEL_ERROR, LEVEL_QUIET\nfrom conan.cli.args import common_graph_args, validate_common_graph_args\nfrom conan.cli.command import conan_command\nfrom conan.cli.commands.install import _run_install_command\nfrom conan.errors import ConanException\n\n\n@conan_command(group=\"Consumer\")\ndef run(conan_api, parser, *args):\n    \"\"\"\n    (Experimental) Run a command given a set of requirements from a recipe or from command line.\n    \"\"\"\n    common_graph_args(parser)\n    parser.add_argument(\"command\", help=\"Command to run\")\n    parser.add_argument(\"--context\", help=\"Context to use, by default both contexts are activated \"\n                                          \"if not specified\",\n                        choices=[\"host\", \"build\"], default=None)\n    parser.add_argument(\"--build-require\", action='store_true', default=False,\n                        help='Whether the provided path is a build-require')\n    args = parser.parse_args(*args)\n    validate_common_graph_args(args)\n    cwd = os.getcwd()\n\n    ConanOutput().info(\"Installing and building dependencies, this might take a while...\",\n                       fg=Color.BRIGHT_MAGENTA)\n    previous_log_level = ConanOutput.get_output_level()\n    if previous_log_level == LEVEL_STATUS:\n        ConanOutput.set_output_level(LEVEL_QUIET)\n\n    with tempfile.TemporaryDirectory(\"conanrun\") as tmpdir:\n        # Default values for install\n        setattr(args, \"output_folder\", tmpdir)\n        setattr(args, \"generator\", [])\n        try:\n            deps_graph, lockfile, _ = _run_install_command(conan_api, args, cwd,\n                                                           return_install_error=False)\n        except ConanException as e:\n            ConanOutput.set_output_level(previous_log_level)\n            ConanOutput().error(\"Error installing the dependencies. To debug this, you can either:\\n\"\n                                \" - Re-run the command with increased verbosity (-v, -vv)\\n\"\n                                \" - Run 'conan install' first to ensure dependencies are installed, \"\n                                \"or to see errors during installation\\n\")\n            raise e\n\n        context_env_map = {\n            \"build\": \"conanbuild\",\n            \"host\": \"conanrun\",\n        }\n        envfiles = list(context_env_map.values()) if args.context is None \\\n            else [context_env_map.get(args.context)]\n        ConanOutput.set_output_level(LEVEL_ERROR)\n        deps_graph.root.conanfile.run(args.command, cwd=cwd, env=envfiles)\n"
  },
  {
    "path": "conan/cli/commands/search.py",
    "content": "from collections import OrderedDict\n\nfrom conan.api.conan_api import ConanAPI\nfrom conan.api.model import ListPattern\nfrom conan.cli.command import conan_command\nfrom conan.cli.commands.list import print_list_text, print_list_json\nfrom conan.errors import ConanException\n\n\n@conan_command(group=\"Consumer\", formatters={\"text\": print_list_text,\n                                             \"json\": print_list_json})\ndef search(conan_api: ConanAPI, parser, *args):\n    \"\"\"\n    Search for package recipes in all the remotes (by default), or a remote.\n    \"\"\"\n    parser.add_argument('reference', help=\"Recipe reference to search for. \"\n                                          \"It can contain * as wildcard at any reference field.\")\n    parser.add_argument(\"-r\", \"--remote\", action=\"append\",\n                        help=\"Remote names. Accepts wildcards. If not specified it searches \"\n                             \"in all the remotes\")\n    args = parser.parse_args(*args)\n    ref_pattern = ListPattern(args.reference, rrev=None)\n    if ref_pattern.package_id is not None or ref_pattern.rrev is not None:\n        raise ConanException(\"Specifying a recipe revision or package ID is not allowed\")\n\n    remotes = conan_api.remotes.list(args.remote)\n    if not remotes:\n        raise ConanException(\"There are no remotes to search from\")\n\n    results = OrderedDict()\n    for remote in remotes:\n        try:\n            pkglist = conan_api.list.select(ref_pattern, package_query=None, remote=remote)\n        except Exception as e:\n            results[remote.name] = {\"error\": str(e)}\n        else:\n            results[remote.name] = pkglist.serialize()\n    return {\n        \"results\": results\n    }\n"
  },
  {
    "path": "conan/cli/commands/source.py",
    "content": "import os\n\nfrom conan.cli.command import conan_command\nfrom conan.cli.args import add_reference_args\n\n\n@conan_command(group=\"Creator\")\ndef source(conan_api, parser, *args):\n    \"\"\"\n    Call the source() method.\n    \"\"\"\n    parser.add_argument(\"path\", help=\"Path to a folder containing a conanfile.py. \"\n                                     \"Defaults to current directory\",\n                        default=\".\", nargs=\"?\")\n    add_reference_args(parser)\n    args = parser.parse_args(*args)\n\n    cwd = os.getcwd()\n    path = conan_api.local.get_conanfile_path(args.path, cwd, py=True)\n    enabled_remotes = conan_api.remotes.list()  # for python_requires not local\n    # TODO: Missing lockfile for python_requires\n    conan_api.local.source(path, name=args.name, version=args.version, user=args.user,\n                           channel=args.channel, remotes=enabled_remotes)\n"
  },
  {
    "path": "conan/cli/commands/test.py",
    "content": "import os\n\nfrom conan.api.output import ConanOutput\nfrom conan.cli.command import conan_command, OnceArgument\nfrom conan.cli.commands.create import test_package, _check_tested_reference_matches\nfrom conan.cli.args import add_lockfile_args, add_common_install_arguments\nfrom conan.cli.formatters.graph import format_graph_json\nfrom conan.cli.printers import print_profiles\nfrom conan.cli.printers.graph import print_graph_basic, print_graph_packages\nfrom conan.api.model import RecipeReference\n\n\n@conan_command(group=\"Creator\", formatters={\"json\": format_graph_json})\ndef test(conan_api, parser, *args):\n    \"\"\"\n    Test a package from a test_package folder.\n    \"\"\"\n    parser.add_argument(\"path\", action=OnceArgument,\n                        help=\"Path to a test_package folder containing a conanfile.py. \"\n                             \"Defaults to a 'test_package' folder in the current directory\",\n                        default=\"test_package\", nargs='?')\n    parser.add_argument(\"reference\", action=OnceArgument,\n                        help='Provide a package reference to test')\n    add_common_install_arguments(parser)\n    add_lockfile_args(parser)\n    args = parser.parse_args(*args)\n\n    cwd = os.getcwd()\n    ref = RecipeReference.loads(args.reference)\n    path = conan_api.local.get_conanfile_path(args.path, cwd, py=True)\n    overrides = eval(args.lockfile_overrides) if args.lockfile_overrides else None\n    lockfile = conan_api.lockfile.get_lockfile(lockfile=args.lockfile,\n                                               conanfile_path=path,\n                                               cwd=cwd,\n                                               partial=args.lockfile_partial,\n                                               overrides=overrides)\n    remotes = conan_api.remotes.list(args.remote) if not args.no_remote else []\n    profile_host, profile_build = conan_api.profiles.get_profiles_from_args(args)\n\n    print_profiles(profile_host, profile_build)\n\n    deps_graph = run_test(conan_api, path, ref, profile_host, profile_build, remotes, lockfile,\n                          args.update, build_modes=args.build, tested_python_requires=ref)\n    lockfile = conan_api.lockfile.update_lockfile(lockfile, deps_graph, args.lockfile_packages,\n                                                  clean=args.lockfile_clean)\n    conan_api.lockfile.save_lockfile(lockfile, args.lockfile_out, cwd)\n\n    return {\"graph\": deps_graph,\n            \"conan_api\": conan_api}\n\n\ndef run_test(conan_api, path, ref, profile_host, profile_build, remotes, lockfile, update,\n             build_modes, tested_python_requires=None, build_modes_test=None, tested_graph=None):\n    root_node = conan_api.graph.load_root_test_conanfile(path, ref,\n                                                         profile_host, profile_build,\n                                                         remotes=remotes,\n                                                         update=update,\n                                                         lockfile=lockfile,\n                                                         tested_python_requires=tested_python_requires)\n    out = ConanOutput()\n    out.title(\"Launching test_package\")\n    deps_graph = conan_api.graph.load_graph(root_node, profile_host=profile_host,\n                                            profile_build=profile_build,\n                                            lockfile=lockfile,\n                                            remotes=remotes,\n                                            update=update,\n                                            check_update=update)\n    print_graph_basic(deps_graph)\n    deps_graph.report_graph_error()\n\n    conan_api.graph.analyze_binaries(deps_graph, build_modes, remotes=remotes, update=update,\n                                     lockfile=lockfile, build_modes_test=build_modes_test,\n                                     tested_graph=tested_graph)\n    print_graph_packages(deps_graph)\n\n    conan_api.install.install_binaries(deps_graph=deps_graph, remotes=remotes)\n    _check_tested_reference_matches(deps_graph, ref, out)\n    test_package(conan_api, deps_graph, path)\n    return deps_graph\n"
  },
  {
    "path": "conan/cli/commands/upload.py",
    "content": "from conan.api.conan_api import ConanAPI\nfrom conan.api.model import ListPattern, MultiPackagesList, PackagesList\nfrom conan.api.output import ConanOutput\nfrom conan.cli import make_abs_path\nfrom conan.cli.command import conan_command, OnceArgument\nfrom conan.cli.commands.list import print_list_json, print_serial\nfrom conan.api.input import UserInput\nfrom conan.errors import ConanException\n\n\ndef summary_upload_list(results):\n    \"\"\" Do a little format modification to serialized\n    package list, so it looks prettier on text output\n    \"\"\"\n    ConanOutput().subtitle(\"Upload summary\")\n    info = results[\"results\"]\n\n    def format_upload(item):\n        if isinstance(item, dict):\n            result = {}\n            for k, v in item.items():\n                if isinstance(v, dict):\n                    v.pop(\"info\", None)\n                    v.pop(\"timestamp\", None)\n                    v.pop(\"files\", None)\n                    v.pop(\"upload-urls\", None)\n                    upload_value = v.pop(\"upload\", None)\n                    if upload_value is not None:\n                        msg = \"Uploaded\" if upload_value else \"Skipped, already in server\"\n                        force_upload = v.pop(\"force_upload\", None)\n                        if force_upload:\n                            msg += \" - forced\"\n                        k = f\"{k} ({msg})\"\n                result[k] = format_upload(v)\n            return result\n        return item\n    info = {remote: format_upload(values) for remote, values in info.items()}\n    print_serial(info)\n\n\n@conan_command(group=\"Creator\", formatters={\"text\": summary_upload_list,\n                                            \"json\": print_list_json})\ndef upload(conan_api: ConanAPI, parser, *args):\n    \"\"\"\n    Upload packages to a remote.\n\n    By default, all the matching references are uploaded (all revisions).\n    By default, if a recipe reference is specified, it will upload all the revisions for all the\n    binary packages, unless --only-recipe is specified. You can use the \"latest\" placeholder at the\n    \"reference\" argument to specify the latest revision of the recipe or the package.\n    \"\"\"\n    parser.add_argument('pattern', nargs=\"?\",\n                        help=\"A pattern in the form 'pkg/version#revision:package_id#revision', \"\n                             \"e.g: \\\"zlib/1.2.13:*\\\" means all binaries for zlib/1.2.13. \"\n                             \"If revision is not specified, it is assumed latest one.\")\n    parser.add_argument('-p', '--package-query', default=None, action=OnceArgument,\n                        help=\"Only upload packages matching a specific query. e.g: os=Windows AND \"\n                             \"(arch=x86 OR compiler=gcc)\")\n    # using required, we may want to pass this as a positional argument?\n    parser.add_argument(\"-r\", \"--remote\", action=OnceArgument, required=True,\n                        help='Upload to this specific remote')\n    parser.add_argument(\"--only-recipe\", action='store_true', default=False,\n                        help='Upload only the recipe/s, not the binary packages.')\n    parser.add_argument(\"--force\", action='store_true', default=False,\n                        help='Force the upload of the artifacts even if the revision already exists'\n                             ' in the server')\n    parser.add_argument(\"--check\", action='store_true', default=False,\n                        help='Perform an integrity check, using the manifests, before upload')\n    parser.add_argument('-c', '--confirm', default=False, action='store_true',\n                        help='Upload all matching recipes without confirmation')\n    parser.add_argument('--dry-run', default=False, action='store_true',\n                        help='Do not execute the real upload (experimental)')\n    parser.add_argument(\"-l\", \"--list\", help=\"Package list file\")\n    parser.add_argument(\"-m\", \"--metadata\", action='append',\n                        help='Upload the metadata, even if the package is already in the server and '\n                             'not uploaded')\n\n    args = parser.parse_args(*args)\n\n    remote = conan_api.remotes.get(args.remote)\n    enabled_remotes = conan_api.remotes.list()\n\n    if args.pattern is None and args.list is None:\n        raise ConanException(\"Missing pattern or package list file\")\n    if args.pattern and args.list:\n        raise ConanException(\"Cannot define both the pattern and the package list file\")\n    if args.package_query and args.list:\n        raise ConanException(\"Cannot define package-query and the package list file\")\n\n    if args.list:\n        listfile = make_abs_path(args.list)\n        multi_package_list = MultiPackagesList.load(listfile)\n        package_list = multi_package_list[\"Local Cache\"]\n        if args.only_recipe:\n            package_list.only_recipes()\n    else:\n        ref_pattern = ListPattern(args.pattern, package_id=\"*\", only_recipe=args.only_recipe)\n        package_list = conan_api.list.select(ref_pattern, package_query=args.package_query)\n\n    if package_list:\n        # If only if search with \"*\" we ask for confirmation\n        if not args.list and not args.confirm and \"*\" in args.pattern:\n            package_list = _ask_confirm_upload(conan_api, package_list)\n\n        conan_api.upload.upload_full(package_list, remote, enabled_remotes, args.check,\n                                     args.force, args.metadata, args.dry_run)\n    elif args.list:\n        # Don't error on no recipes for automated workflows using list,\n        # but warn to tell the user that no packages were uploaded\n        ConanOutput().warning(f\"No packages were uploaded because the package list is empty.\")\n    else:\n        raise ConanException(\"No recipes found matching pattern '{}'\".format(args.pattern))\n\n    pkglist = MultiPackagesList()\n    pkglist.add(remote.name, package_list)\n    return {\n        \"results\": pkglist.serialize(),\n        \"conan_api\": conan_api\n    }\n\n\ndef _ask_confirm_upload(conan_api, package_list):\n    ui = UserInput(conan_api.config.get(\"core:non_interactive\"))\n    result = PackagesList()\n    for ref, packages in package_list.items():\n        msg = f\"Are you sure you want to upload recipe '{ref.repr_notime()}'?\"\n        if ui.request_boolean(msg):\n            result.add_ref(ref)\n            ref_dict = package_list.recipe_dict(ref).copy()\n            ref_dict.pop(\"packages\", None)\n            result.recipe_dict(ref).update(ref_dict)\n            for pref, pkg_id_info in packages.items():\n                msg = f\"Are you sure you want to upload package '{pref.repr_notime()}'?\"\n                if ui.request_boolean(msg):\n                    result.add_pref(pref, pkg_id_info)\n                    result.package_dict(pref).update(package_list.package_dict(pref))\n    return result\n"
  },
  {
    "path": "conan/cli/commands/version.py",
    "content": "from conan.cli.commands.list import print_serial\nfrom conan.cli.command import conan_command\nfrom conan.cli.formatters import default_json_formatter\nfrom conan import conan_version\nimport platform\nimport sys\n\n\n@conan_command(group=\"Consumer\", formatters={\"text\": print_serial, \"json\": default_json_formatter})\ndef version(conan_api, parser, *args):\n    \"\"\"\n    Give information about the Conan client version.\n    \"\"\"\n    parser.parse_args(*args)\n\n    return {\n            'version': str(conan_version),\n            'conan_path': sys.argv[0],\n            'python': {\n                'version': platform.python_version().replace('\\n', ''),\n                'sys_version': sys.version.replace('\\n', ''),\n                'sys_executable': sys.executable,\n                'is_frozen': getattr(sys, 'frozen', False),\n                'architecture': platform.machine(),\n                },\n            'system': {\n                'version': platform.version(),\n                'platform': platform.platform(),\n                'system': platform.system(),\n                'release': platform.release(),\n                'cpu': platform.processor(),\n                }\n            }\n\n"
  },
  {
    "path": "conan/cli/commands/workspace.py",
    "content": "import json\nimport os\n\nfrom conan.api.conan_api import ConanAPI\nfrom conan.api.model import RecipeReference\nfrom conan.api.output import ConanOutput, cli_out_write\nfrom conan.api.subapi.workspace import WorkspaceAPI\nfrom conan.cli import make_abs_path\nfrom conan.cli.args import add_reference_args, add_common_install_arguments, add_lockfile_args\nfrom conan.cli.command import conan_command, conan_subcommand, OnceArgument\nfrom conan.cli.commands.list import print_serial\nfrom conan.cli.formatters.graph import format_graph_json\nfrom conan.cli.printers import print_profiles\nfrom conan.cli.printers.graph import print_graph_packages, print_graph_basic\nfrom conan.errors import ConanException\nfrom conan.internal.graph.install_graph import ProfileArgs\n\n\n@conan_subcommand(formatters={\"text\": cli_out_write})\ndef workspace_root(conan_api: ConanAPI, parser, subparser, *args):  # noqa\n    \"\"\"\n    Return the folder containing the conanws.py/conanws.yml workspace file\n    \"\"\"\n    parser.parse_args(*args)\n    ws = conan_api.workspace\n    return ws.folder()\n\n\n@conan_subcommand()\ndef workspace_open(conan_api: ConanAPI, parser, subparser, *args):\n    \"\"\"\n    Open specific references\n    \"\"\"\n    subparser.add_argument(\"reference\",\n                           help=\"Open this package source repository\")\n    group = subparser.add_mutually_exclusive_group()\n    group.add_argument(\"-r\", \"--remote\", action=\"append\", default=None,\n                       help='Look in the specified remote or remotes server')\n    group.add_argument(\"-nr\", \"--no-remote\", action=\"store_true\",\n                       help='Do not use remote, resolve exclusively in the cache')\n    args = parser.parse_args(*args)\n    remotes = conan_api.remotes.list(args.remote) if not args.no_remote else []\n    cwd = os.getcwd()\n    conan_api.workspace.open(args.reference, remotes=remotes, cwd=cwd)\n\n\n@conan_subcommand()\ndef workspace_add(conan_api: ConanAPI, parser, subparser, *args):\n    \"\"\"\n    Add packages to current workspace\n    \"\"\"\n    subparser.add_argument('path',  nargs=\"?\",\n                           help='Path to the package folder in the user workspace')\n    add_reference_args(subparser)\n    subparser.add_argument(\"--ref\", help=\"Open and add this reference\")\n    subparser.add_argument(\"-of\", \"--output-folder\",\n                           help='The root output folder for generated and build files')\n    group = subparser.add_mutually_exclusive_group()\n    group.add_argument(\"-r\", \"--remote\", action=\"append\", default=None,\n                       help='Look in the specified remote or remotes server')\n    group.add_argument(\"-nr\", \"--no-remote\", action=\"store_true\",\n                       help='Do not use remote, resolve exclusively in the cache')\n    args = parser.parse_args(*args)\n    if args.path and args.ref:\n        raise ConanException(\"Do not use both 'path' and '--ref' argument\")\n    remotes = conan_api.remotes.list(args.remote) if not args.no_remote else []\n    cwd = os.getcwd()\n    path = args.path\n    if args.ref:\n        # TODO: Use path here to open in this path\n        path = conan_api.workspace.open(args.ref, remotes, cwd=cwd)\n    ref = conan_api.workspace.add(path,\n                                  args.name, args.version, args.user, args.channel,\n                                  cwd, args.output_folder, remotes=remotes)\n    ConanOutput().success(\"Reference '{}' added to workspace\".format(ref))\n\n\n@conan_subcommand()\ndef workspace_complete(conan_api: ConanAPI, parser, subparser, *args):\n    \"\"\"\n    Complete the workspace, opening or adding intermediate packages to it that have\n    requirements to other packages in the workspace.\n    \"\"\"\n    add_common_install_arguments(subparser)\n    group = subparser.add_argument_group(\"lockfile arguments\")\n    group.add_argument(\"-l\", \"--lockfile\", action=OnceArgument,\n                       help=\"Path to a lockfile. Use --lockfile=\\\"\\\" to avoid automatic use of \"\n                            \"existing 'conan.lock' file\")\n    group.add_argument(\"--lockfile-partial\", action=\"store_true\",\n                       help=\"Do not raise an error if some dependency is not found in lockfile\")\n    args = parser.parse_args(*args)\n    remotes = conan_api.remotes.list(args.remote) if not args.no_remote else []\n    # The lockfile by default if not defined will be read from the root workspace folder\n    ws_folder = conan_api.workspace.folder()\n    lockfile = conan_api.lockfile.get_lockfile(lockfile=args.lockfile, conanfile_path=ws_folder,\n                                               cwd=None, partial=args.lockfile_partial)\n    profile_host, profile_build = conan_api.profiles.get_profiles_from_args(args)\n    print_profiles(profile_host, profile_build)\n\n    ConanOutput().box(\"Workspace completing intermediate packages\")\n    conan_api.workspace.complete(profile_host, profile_build, lockfile, remotes, update=args.update)\n\n\n@conan_subcommand()\ndef workspace_remove(conan_api: ConanAPI, parser, subparser, *args):\n    \"\"\"\n    Remove packages from the current workspace\n    \"\"\"\n    subparser.add_argument('path',\n                           help='Path to the package folder in the user workspace')\n    args = parser.parse_args(*args)\n    removed = conan_api.workspace.remove(make_abs_path(args.path))\n    ConanOutput().info(f\"Removed from workspace: {removed}\")\n\n\ndef _print_json(data):\n    results = data[\"info\"]\n    myjson = json.dumps(results, indent=4)\n    cli_out_write(myjson)\n\n\ndef _print_workspace_info(data):\n    ret = []\n    for package_info in data[\"info\"][\"packages\"]:\n        ret.append(f\"- path: {package_info['path']}\")\n        ref = package_info.get('ref')\n        if ref:\n            ret.append(f\"  ref: {ref}\")\n    data[\"info\"][\"packages\"] = ret or \"(empty)\"\n    print_serial(data[\"info\"])\n\n\n@conan_subcommand(formatters={\"text\": _print_workspace_info, \"json\": _print_json})\ndef workspace_info(conan_api: ConanAPI, parser, subparser, *args):  # noqa\n    \"\"\"\n    Display info for current workspace\n    \"\"\"\n    parser.parse_args(*args)\n    return {\"info\": conan_api.workspace.info()}\n\n\n@conan_subcommand()\ndef workspace_build(conan_api: ConanAPI, parser, subparser, *args):\n    \"\"\"\n    Call \"conan build\" for packages in the workspace, in the right order\n    \"\"\"\n    _install_build(conan_api, parser, subparser, True, *args)\n\n\n@conan_subcommand()\ndef workspace_install(conan_api: ConanAPI, parser, subparser, *args):\n    \"\"\"\n    Call \"conan install\" for packages in the workspace, in the right order\n    \"\"\"\n    _install_build(conan_api, parser, subparser, False, *args)\n\n\ndef _install_build(conan_api: ConanAPI, parser, subparser, build, *args):\n    subparser.add_argument(\"--pkg\", action=\"append\", help='Define specific packages')\n    add_common_install_arguments(subparser)\n    group = subparser.add_argument_group(\"lockfile arguments\")\n    group.add_argument(\"-l\", \"--lockfile\", action=OnceArgument,\n                       help=\"Path to a lockfile. Use --lockfile=\\\"\\\" to avoid automatic use of \"\n                            \"existing 'conan.lock' file\")\n    group.add_argument(\"--lockfile-partial\", action=\"store_true\",\n                       help=\"Do not raise an error if some dependency is not found in lockfile\")\n    args = parser.parse_args(*args)\n    # Basic collaborators: remotes, lockfile, profiles\n    remotes = conan_api.remotes.list(args.remote) if not args.no_remote else []\n    # The lockfile by default if not defined will be read from the root workspace folder\n    ws_folder = conan_api.workspace.folder()\n    lockfile = conan_api.lockfile.get_lockfile(lockfile=args.lockfile, conanfile_path=ws_folder,\n                                               cwd=None, partial=args.lockfile_partial)\n    profile_host, profile_build = conan_api.profiles.get_profiles_from_args(args)\n    print_profiles(profile_host, profile_build)\n\n    buildmode = args.build\n    if build and (not buildmode or \"editable\" not in buildmode):\n        ConanOutput().info(\"Adding '--build=editable' as build mode\")\n        buildmode = buildmode or []\n        buildmode.append(\"editable\")\n\n    all_editables = conan_api.workspace.packages()\n    packages = conan_api.workspace.select_packages(args.pkg)\n    ConanOutput().box(\"Workspace computing the build order\")\n    install_order = conan_api.workspace.build_order(packages, profile_host, profile_build, buildmode,\n                                                    lockfile, remotes, args, update=args.update)\n\n    msg = \"build\" if build else \"install\"\n    ConanOutput().box(f\"Workspace {msg}ing each package\")\n    order = install_order.install_build_order()\n\n    profile_args = ProfileArgs.from_args(args)\n    lockfile_args = [f\"--lockfile={a}\" for a in args.lockfile or []]\n    if args.lockfile_partial:\n        lockfile_args.append(\"--lockfile-partial\")\n    lockfile_args = \" \".join(lockfile_args)\n    for level in order[\"order\"]:\n        for elem in level:\n            ref = RecipeReference.loads(elem[\"ref\"])\n            for package_level in elem[\"packages\"]:\n                for package in package_level:\n                    ws_pkg = all_editables.get(ref)\n                    is_editable = package[\"binary\"] in (\"Editable\", \"EditableBuild\")\n                    if ws_pkg is None:\n                        if is_editable or package[\"binary\"] == \"Build\":  # Build extern to Workspace\n                            cmd = f'install {package[\"build_args\"]} {profile_args} {lockfile_args}'\n                            ConanOutput().box(f\"Workspace building external {ref}\")\n                            ConanOutput().info(f\"Command: {cmd}\\n\")\n                            conan_api.command.run(cmd)\n                    else:\n                        path = ws_pkg[\"path\"]\n                        output_folder = ws_pkg.get(\"output_folder\")\n                        build_arg = \"--build-require\" if package[\"context\"] == \"build\" else \"\"\n                        ref_args = \" \".join(f\"--{k}={getattr(ref, k)}\"\n                                            for k in (\"name\", \"version\", \"user\", \"channel\")\n                                            if getattr(ref, k, None))\n                        of_arg = f'-of=\"{output_folder}\"' if output_folder else \"\"\n                        # TODO: Missing --lockfile-overrides arg here\n                        command = \"build\" if build else \"install\"\n                        cmd = (f'{command} \"{path}\" {profile_args} {build_arg} {ref_args} {of_arg} '\n                               f'{lockfile_args}')\n                        ConanOutput().box(f\"Workspace {command}: {ref}\")\n                        ConanOutput().info(f\"Command: {cmd}\\n\")\n                        conan_api.command.run(cmd)\n\n\n@conan_subcommand(formatters={\"json\": format_graph_json})\ndef workspace_super_install(conan_api: ConanAPI, parser, subparser, *args):\n    \"\"\"\n    Install the workspace as a monolith, installing only external dependencies to the workspace,\n    generating a single result (generators, etc) for the whole workspace.\n    \"\"\"\n    subparser.add_argument(\"--pkg\", action=\"append\", help='Define specific packages')\n    subparser.add_argument(\"-g\", \"--generator\", action=\"append\", help='Generators to use')\n    subparser.add_argument(\"-of\", \"--output-folder\",\n                           help='The root output folder for generated and build files')\n    subparser.add_argument(\"-d\", \"--deployer\", action=\"append\",\n                           help=\"Deploy using the provided deployer to the output folder. \"\n                                \"Built-in deployers: 'full_deploy', 'direct_deploy', \"\n                                \"'runtime_deploy'\")\n    subparser.add_argument(\"--deployer-folder\",\n                           help=\"Deployer output folder, base build folder by default if not set\")\n    subparser.add_argument(\"--deployer-package\", action=\"append\",\n                           help=\"Execute the deploy() method of the packages matching \"\n                                \"the provided patterns\")\n    subparser.add_argument(\"--envs-generation\", default=None, choices=[\"false\"],\n                           help=\"Generation strategy for virtual environment files for the root\")\n    add_common_install_arguments(subparser)\n    add_lockfile_args(subparser)\n    args = parser.parse_args(*args)\n    # Basic collaborators: remotes, lockfile, profiles\n    remotes = conan_api.remotes.list(args.remote) if not args.no_remote else []\n    overrides = eval(args.lockfile_overrides) if args.lockfile_overrides else None\n    # The lockfile by default if not defined will be read from the root workspace folder\n    ws_folder = conan_api.workspace.folder()\n    lockfile = conan_api.lockfile.get_lockfile(lockfile=args.lockfile, conanfile_path=ws_folder,\n                                               cwd=None,\n                                               partial=args.lockfile_partial, overrides=overrides)\n    profile_host, profile_build = conan_api.profiles.get_profiles_from_args(args)\n    print_profiles(profile_host, profile_build)\n\n    # Build a dependency graph with all editables as requirements\n    requires = conan_api.workspace.select_packages(args.pkg)\n    deps_graph = conan_api.graph.load_graph_requires(requires, [],\n                                                     profile_host, profile_build, lockfile,\n                                                     remotes, update=args.update)\n    deps_graph.report_graph_error()\n    print_graph_basic(deps_graph)\n\n    # Collapsing the graph\n    ws_graph = conan_api.workspace.super_build_graph(deps_graph, profile_host, profile_build)\n    ConanOutput().subtitle(\"Collapsed graph\")\n    print_graph_basic(ws_graph)\n    conan_api.graph.analyze_binaries(ws_graph, args.build, remotes=remotes, update=args.update,\n                                     lockfile=lockfile)\n    print_graph_packages(ws_graph)\n    conan_api.install.install_binaries(deps_graph=ws_graph, remotes=remotes)\n    ConanOutput().title(\"Finalizing install (deploy, generators)\")\n    output_folder = make_abs_path(args.output_folder) if args.output_folder else None\n    conan_api.install.install_consumer(ws_graph, args.generator, ws_folder, output_folder,\n                                       deploy=args.deployer, deploy_package=args.deployer_package,\n                                       deploy_folder=args.deployer_folder,\n                                       envs_generation=args.envs_generation)\n\n    # Update and save lockfile if requested\n    lockfile = conan_api.lockfile.update_lockfile(lockfile, deps_graph, args.lockfile_packages,\n                                                  clean=args.lockfile_clean)\n    conan_api.lockfile.save_lockfile(lockfile, args.lockfile_out)\n\n    ConanOutput().success(\"Install finished successfully\")\n\n    return {\"graph\": ws_graph,\n            \"conan_api\": conan_api}\n\n\n@conan_subcommand()\ndef workspace_clean(conan_api: ConanAPI, parser, subparser, *args):  # noqa\n    \"\"\"\n    Clean the temporary build folders when possible\n    \"\"\"\n    parser.parse_args(*args)\n    conan_api.workspace.clean()\n\n\n@conan_subcommand()\ndef workspace_init(conan_api: ConanAPI, parser, subparser, *args):\n    \"\"\"\n    Clean the temporary build folders when possible\n    \"\"\"\n    subparser.add_argument(\"path\", nargs=\"?\", default=os.getcwd(),\n                           help=\"Path to a folder where the workspace will be initialized. \"\n                                \"Defaults to the current directory\")\n    args = parser.parse_args(*args)\n    conan_api.workspace.init(args.path)\n\n\n@conan_subcommand()\ndef workspace_create(conan_api: ConanAPI, parser, subparser, *args):\n    \"\"\"\n    Call \"conan create\" for packages in the workspace, in the correct order.\n    Packages will be created in the Conan cache, not locally\n    \"\"\"\n    subparser.add_argument(\"--pkg\", action=\"append\", help='Define specific packages')\n    add_common_install_arguments(subparser)\n    group = subparser.add_argument_group(\"lockfile arguments\")\n    group.add_argument(\"-l\", \"--lockfile\", action=OnceArgument,\n                       help=\"Path to a lockfile. Use --lockfile=\\\"\\\" to avoid automatic use of \"\n                            \"existing 'conan.lock' file\")\n    group.add_argument(\"--lockfile-partial\", action=\"store_true\",\n                       help=\"Do not raise an error if some dependency is not found in lockfile\")\n\n    args = parser.parse_args(*args)\n    # Basic collaborators: remotes, lockfile, profiles\n    remotes = conan_api.remotes.list(args.remote) if not args.no_remote else []\n    # The lockfile by default if not defined will be read from the root workspace folder\n    ws_folder = conan_api.workspace.folder()\n    lockfile = conan_api.lockfile.get_lockfile(lockfile=args.lockfile, conanfile_path=ws_folder,\n                                               cwd=None, partial=args.lockfile_partial)\n    profile_host, profile_build = conan_api.profiles.get_profiles_from_args(args)\n    print_profiles(profile_host, profile_build)\n\n    build_mode = args.build if args.build else []\n    ConanOutput().box(\"Exporting workspace recipes to Conan cache\")\n    exported_refs = conan_api.workspace.export()\n    build_mode.extend(f\"missing:{r}\" for r in exported_refs)\n\n    all_packages = conan_api.workspace.packages()\n    packages = conan_api.workspace.select_packages(args.pkg)\n\n    # If we don't disable the workspace, then, the packages are not created in the Conan cache,\n    # but locally in the user folders, are they are intercepted as editables\n    conan_api.workspace.enable(False)\n\n    install_order = conan_api.workspace.build_order(packages, profile_host, profile_build,\n                                                    build_mode, lockfile, remotes, args,\n                                                    update=args.update)\n\n    ConanOutput().box(\"Workspace creating each package\")\n    order = install_order.install_build_order()\n\n    profile_args = ProfileArgs.from_args(args)\n    for level in order[\"order\"]:\n        for elem in level:\n            ref = RecipeReference.loads(elem[\"ref\"])\n            for package_level in elem[\"packages\"]:\n                for package in package_level:\n                    if package[\"binary\"] not in (\"Build\", \"EditableBuild\"):\n                        ConanOutput().info(f\"Skip build for {ref} binary: {package['binary']}\")\n                        continue\n\n                    if ref not in all_packages:\n                        # Build external to Workspace\n                        cmd = f'install {package[\"build_args\"]} {profile_args}'\n                        ConanOutput().box(f\"Workspace building external {ref}\")\n                        ConanOutput().info(f\"Build command: {cmd}\\n\")\n                        conan_api.command.run(cmd)\n                    else:  # Package in workspace\n                        path = packages[ref][\"path\"]\n                        # TODO: Missing --lockfile-overrides arg here\n                        build = \"--build-require\" if package[\"context\"] == \"build\" else \"\"\n                        ref_args = \" \".join(f\"--{k}={getattr(ref, k)}\"\n                                            for k in (\"name\", \"version\", \"user\", \"channel\")\n                                            if getattr(ref, k, None))\n                        cmd = f'create \"{path}\" {profile_args} {build} {ref_args}'\n                        ConanOutput().box(f\"Workspace create {ref}\")\n                        ConanOutput().info(f\"Conan create command: {cmd}\\n\")\n                        conan_api.command.run(cmd)\n\n\n@conan_subcommand()\ndef workspace_source(conan_api: ConanAPI, parser, subparser, *args):\n    \"\"\"\n    Call the source() method of packages in the workspace\n    \"\"\"\n    subparser.add_argument(\"--pkg\", action=\"append\", help='Define specific packages')\n    args = parser.parse_args(*args)\n\n    remotes = conan_api.remotes.list()  # In case \"python_requires\" are needed\n    packages = conan_api.workspace.select_packages(args.pkg)\n\n    ConanOutput().box(\"Workspace getting sources\")\n    for pkg, info in packages.items():\n        conan_api.local.source(info[\"path\"], name=pkg.name, version=str(pkg.version),\n                               user=pkg.user, channel=pkg.channel, remotes=remotes)\n\n\n@conan_command(group=\"Consumer\")\ndef workspace(conan_api, parser, *args):  # noqa\n    \"\"\"\n    Manage Conan workspaces (group of packages in editable mode)\n    \"\"\"\n    if (WorkspaceAPI.TEST_ENABLED or os.getenv(\"CONAN_WORKSPACE_ENABLE\")) != \"will_break_next\":\n        raise ConanException(\"Workspace command disabled without CONAN_WORKSPACE_ENABLE env var,\"\n                             \"please read the docs about this 'incubating' feature\")\n"
  },
  {
    "path": "conan/cli/exit_codes.py",
    "content": "# Exit codes for conan command:\nSUCCESS = 0                             # 0: Success (done)\nERROR_GENERAL = 1                       # 1: General ConanException error (done)\nERROR_MIGRATION = 2                     # 2: Migration error\nUSER_CTRL_C = 3                         # 3: Ctrl+C\nUSER_CTRL_BREAK = 4                     # 4: Ctrl+Break\nERROR_SIGTERM = 5                       # 5: SIGTERM\nERROR_INVALID_CONFIGURATION = 6         # 6: Invalid configuration (done)\nERROR_UNEXPECTED = 7\n"
  },
  {
    "path": "conan/cli/formatters/__init__.py",
    "content": "import json\n\nfrom conan.api.output import cli_out_write\n\n\ndef default_json_formatter(data):\n    myjson = json.dumps(data, indent=4)\n    cli_out_write(myjson)\n"
  },
  {
    "path": "conan/cli/formatters/audit/__init__.py",
    "content": ""
  },
  {
    "path": "conan/cli/formatters/audit/vulnerabilities.py",
    "content": "import json\n\nfrom jinja2 import select_autoescape, Template\n\nfrom conan.api.output import cli_out_write, Color\n\n\nseverity_order = {\n    \"Critical\": 4,\n    \"High\": 3,\n    \"Medium\": 2,\n    \"Low\": 1\n}\n\n\ndef text_vuln_formatter(result):\n\n    severity_colors = {\n        \"Critical\": Color.BRIGHT_RED,\n        \"High\": Color.RED,\n        \"Medium\": Color.BRIGHT_YELLOW,\n        \"Low\": Color.BRIGHT_CYAN\n    }\n\n    def wrap_and_indent(txt, limit=80, indent=2):\n        txt = txt.replace(\"\\n\", \" \").strip()\n        if len(txt) <= limit:\n            return \" \" * indent + txt\n        lines = []\n        while len(txt) > limit:\n            split_index = txt.rfind(\" \", 0, limit)\n            if split_index == -1:\n                split_index = limit\n            lines.append(\" \" * indent + txt[:split_index].strip())\n            txt = txt[split_index:].strip()\n        lines.append(\" \" * indent + txt)\n        return \"\\n\".join(lines)\n\n    total_vulns = 0\n    summary_lines = []\n\n    for ref, pkg_info in result[\"data\"].items():\n        edges = pkg_info.get(\"vulnerabilities\", {}).get(\"edges\", [])\n        count = len(edges)\n\n        border_line = \"*\" * (len(ref) + 4)\n        cli_out_write(\"\\n\" + border_line, fg=Color.BRIGHT_WHITE)\n        cli_out_write(f\"* {ref} *\", fg=Color.BRIGHT_WHITE)\n        cli_out_write(border_line, fg=Color.BRIGHT_WHITE)\n\n        if \"error\" in pkg_info:\n            details = pkg_info[\"error\"].get(\"details\", \"\")\n            cli_out_write(f\"\\n{details}\\n\", fg=Color.BRIGHT_YELLOW)\n            continue\n\n        if not count:\n            cli_out_write(\"\\nNo vulnerabilities found.\\n\", fg=Color.BRIGHT_GREEN)\n            continue\n\n        total_vulns += count\n        summary_lines.append(\n            f\"{ref} {count} {'vulnerability' if count == 1 else 'vulnerabilities'} found\")\n        cli_out_write(f\"\\n{count} {'vulnerability' if count == 1 else 'vulnerabilities'} found:\\n\",\n                      fg=Color.BRIGHT_YELLOW)\n\n        sorted_vulns = sorted(edges,\n                              key=lambda v: -severity_order.get(v[\"node\"].get(\"severity\", \"Medium\"),\n                                                                2))\n\n        for vuln in sorted_vulns:\n            node = vuln[\"node\"]\n            name = node[\"name\"]\n            sev = node.get(\"severity\", \"Medium\")\n            sev_color = severity_colors.get(sev, Color.BRIGHT_YELLOW)\n            score = node.get(\"cvss\", {}).get(\"preferredBaseScore\")\n            score_txt = f\", CVSS: {score}\" if score else \"\"\n            desc = node.get(\"description\", \"\")\n            desc = (desc[:240] + \"...\") if len(desc) > 240 else desc\n            desc_wrapped = wrap_and_indent(desc)\n            isWithdrawn = node.get(\"withdrawn\", False)\n            publishedAt = node.get(\"publishedAt\")\n\n            cli_out_write(f\"- {name}\", fg=Color.BRIGHT_WHITE, endline=\"\")\n            if isWithdrawn:\n                cli_out_write(\" [WITHDRAWN]\", fg=Color.BRIGHT_CYAN, endline=\"\")\n            cli_out_write(f\" (Severity: {sev}{score_txt})\", fg=sev_color)\n            advisories = node.get(\"advisories\", {})\n            jfrog_advisories = [adv for adv in advisories\n                                if adv.get(\"name\", \"\").startswith(\"JFSA-\")]\n            for adv in jfrog_advisories:\n                if adv.get(\"shortDescription\"):\n                    cli_out_write(f\"  Summary provided by JFrog Research ({adv['name']})\",\n                                  fg=Color.BRIGHT_GREEN)\n                    cli_out_write(wrap_and_indent(f\"Short description: {adv['shortDescription']}\",\n                                                  indent=4))\n                    if adv.get(\"severity\"):\n                        cli_out_write(f\"    Severity: \", endline=\"\")\n                        cli_out_write(adv['severity'], fg=severity_colors.get(adv['severity']))\n                        reasons = adv.get(\"impactReasons\", [])\n                        if reasons:\n                            cli_out_write(f\"    Impact reasons:\")\n                            for reason in reasons:\n                                cli_out_write(wrap_and_indent(f\"* {reason['name']}\", indent=8),\n                                              fg=Color.GREEN if reason['isPositive'] else Color.RED)\n                    if result[\"provider_url\"]:\n                        expected_url = (result[\"provider_url\"].rstrip(\"/\")\n                                        + f\"/ui/catalog/vulnerabilities/details/{adv['name']}\")\n                        cli_out_write(f\"    Url: {expected_url}\")\n                    cli_out_write(\"\")\n\n            cli_out_write(\"\\n\" + desc_wrapped)\n\n            if publishedAt:\n                cli_out_write(f\"  Published at: \", endline=\"\", fg=Color.BRIGHT_BLUE)\n                cli_out_write(publishedAt)\n\n            references = node.get(\"references\")\n            if references:\n                cli_out_write(f\"  url: \", endline=\"\", fg=Color.BRIGHT_BLUE)\n                cli_out_write(references[0])\n\n            vulnerablePackages = node.get(\"vulnerablePackages\")\n            if vulnerablePackages:\n                fixVersions = [fix['version']\n                               for fix_edge in vulnerablePackages.get(\"edges\", [])\n                               for fix in fix_edge['node'].get(\"fixVersions\", [])]\n                if fixVersions:\n                    cli_out_write(f\"  fixed in version(s): \", endline=\"\", fg=Color.BRIGHT_BLUE)\n                    cli_out_write(', '.join(fixVersions))\n            cli_out_write(\"\")\n\n    color_for_total = Color.BRIGHT_RED if total_vulns else Color.BRIGHT_GREEN\n\n    cli_out_write(f\"Total vulnerabilities found: {total_vulns}\\n\", fg=color_for_total)\n\n    if total_vulns > 0:\n        cli_out_write(\"\\nSummary:\\n\", fg=Color.BRIGHT_WHITE)\n        for line in summary_lines:\n            cli_out_write(f\"- {line}\", fg=Color.BRIGHT_WHITE)\n\n        cli_out_write(\"\\nIf you are using packages from Conan Center, some vulnerabilities may have already been mitigated \"\n                      \"through patches applied in the recipe.\\nTo verify if a patch has been applied, check the recipe in Conan Center.\\n\",\n                      fg=Color.BRIGHT_YELLOW)\n\n    if total_vulns > 0 or \"error\" not in result:\n        cli_out_write(\"\\nVulnerability information provided by JFrog Catalog. Check \"\n                      \"https://audit.conan.io/jfrogcuration for more information.\\n\",\n                      fg=Color.BRIGHT_GREEN)\n        cli_out_write(\"You can send questions and report issues about \"\n                      \"the returned vulnerabilities to conan-research@jfrog.com.\\n\",\n                      fg=Color.BRIGHT_GREEN)\n\n\ndef json_vuln_formatter(result):\n    cli_out_write(json.dumps(result, indent=4))\n\n\ndef _render_vulns(vulns, template):\n    from conan import __version__\n    template = Template(template, autoescape=select_autoescape(['html', 'xml']))\n    return template.render(vulns=vulns, version=__version__)\n\n\nvuln_html = \"\"\"\n<!DOCTYPE html>\n<html lang=\"en\" class=\"dark\">\n<head>\n  <meta charset=\"UTF-8\">\n  <title>Conan Audit Vulnerabilities Report</title>\n  <link rel=\"stylesheet\" href=\"https://cdn.datatables.net/2.3.4/css/dataTables.dataTables.min.css\">\n  <style>\n    body { margin: 0; padding: 0; font-family: Arial, sans-serif; background: #333; color: #ffffff; }\n    .container { width: 95%; margin: 40px auto; padding: 20px; background: #222; box-shadow: 0 2px 5px rgba(0,0,0,0.1); border-radius: 8px; }\n    h1 { text-align: center; margin-bottom: 20px; }\n    table { width: 100%; border-collapse: collapse; margin-bottom: 20px; table-layout: fixed; padding-top: 10px;}\n    col[data-dt-column=\"0\"] { width: 10%; }\n    col[data-dt-column=\"1\"] { width: 10%; }\n    col[data-dt-column=\"2\"] { width: auto; }\n    thead { background: #333; color: #fff; }\n    thead th { padding: 12px; text-align: left; }\n    tbody tr { border-bottom: 1px solid #ddd; }\n    tbody tr:hover { background: #f0f0f0; }\n    td { padding: 10px; vertical-align: top; white-space: normal; word-wrap: break-word; overflow-wrap: break-word; word-break: break-word;}\n    .severity-badge { padding: 2px 4px; border-radius: 4px; color: #fff; font-weight: bold; display: inline-block; }\n    .severity-Critical { background: #d9534f; animation: pulse 2s infinite; }\n    @keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(217,83,79,0.7); } 70% { box-shadow: 0 0 0 12px rgba(217,83,79,0); } 100% { box-shadow: 0 0 0 0 rgba(217,83,79,0); } }\n    .severity-High { background: #f0ad4e; }\n    .severity-Medium { background: #f7ecb5; color: #333; }\n    .severity-Low { background: #5cb85c; }\n    .footer { text-align: center; color: #666; margin-bottom: 10px; }\n    a { color: #007bff; text-decoration: none; }\n    a:hover { text-decoration: underline; }\n    .jfrog-research-summary { padding: 10px; border-radius: 6px; margin-bottom: 10px; border: 1px solid #555; }\n    .jfrog-research-details { margin-top: 10px; }\n  </style>\n  <script\n    src=\"https://code.jquery.com/jquery-3.7.1.min.js\"\n    integrity=\"sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=\"\n    crossorigin=\"anonymous\"></script>\n  <script src=\"https://cdn.datatables.net/2.3.4/js/dataTables.min.js\"></script>\n  <script>\n    $(document).ready(function(){\n      $('#vuln_table').DataTable({\n        \"columnDefs\": [\n          { \"orderable\": true, \"targets\": [0, 1] },\n          { \"orderable\": false, \"targets\": [2] }\n        ],\n        \"order\": [[1, \"desc\"]],\n        \"autoWidth\": false,\n      });\n    });\n  </script>\n</head>\n<body>\n  <div class=\"container\">\n    <h1>Conan Audit Vulnerabilities Report</h1>\n    <table id=\"vuln_table\" class=\"stripe\">\n      <colgroup>\n        <col class=\"pkg-col\">\n        <col class=\"info-col\">\n        <col class=\"desc-col\">\n      </colgroup>\n      <thead>\n        <tr>\n          <th>Package</th>\n          <th>Info</th>\n          <th>Description</th>\n        </tr>\n      </thead>\n      <tbody>\n      {% for vuln in vulns %}\n        {% set parts = vuln.severity.split(' - ') %}\n        {% set severity_id = parts[0] %}\n        {% set severity_label = parts[1] if parts|length > 1 else parts[0] %}\n        <tr>\n          <td>\n            {{ vuln.package }}\n          </td>\n          <td>\n            <span style=\"display: none\">{{ vuln.score }}</span>\n            {% if vuln.withdrawn %}\n                <span style=\"color: #00ced1; font-weight: bold;\">[WITHDRAWN]</span><br>\n            {% endif %}\n            {{ vuln.vuln_id }}\n            <br>\n            {% if vuln.severity not in ['N/A', ''] %}\n              <span class=\"severity-badge severity-{{ severity_label }}\">{{ severity_label }}</span>\n            {% else %}\n              {{ vuln.severity }}\n            {% endif %}\n            {{ vuln.score }}\n          </td>\n          <td>\n            {% for research in vuln.advisories %}\n                {% if research.shortDescription %}\n                <div class=\"jfrog-research-summary\">\n                    <strong>Summary provided by JFrog Research <span style=\"color: green\">({{ research.name }})</span></strong>\n                    <div class=\"jfrog-research-details\">\n                        <b>Short description:</b> {{ research.shortDescription }}<br>\n                        {% if research.severity %}\n                            <b>Impact severity:</b> <span class=\"severity-badge severity-{{ research.severity }}\">{{ research.severity }}</span><br>\n                            {% if research.impactReasons %}\n                                <b>Impact reasons:</b>\n                                <ul>\n                                {% for reason in research.impactReasons %}\n                                    <li style=\"color: {{ 'inherit' if reason.isPositive else 'red' }};\">{{ reason.name }}</li>\n                                {% endfor %}\n                                </ul>\n                            {% endif %}\n                        {% endif %}\n                        {% if vuln.provider_url %}\n                            {% set expected_url = vuln.provider_url.rstrip('/') + '/ui/catalog/vulnerabilities/details/' + research.name %}\n                            <b>More info available in:</b> <a href=\"{{ expected_url }}\" target=\"_blank\">{{ expected_url }}</a><br>\n                        {% endif %}\n                    </div>\n                </div>\n                {% endif %}\n            {% endfor %}\n            <strong>Description:</strong>\n            <br>\n            {{ vuln.description }}\n            {% if vuln.publishedAt %}\n                <br>\n                <br>\n                <strong>Published at:</strong> {{ vuln.publishedAt }}\n            {% endif %}\n            {% if vuln.fixVersions %}\n                <div class=\"fix-versions-section\">\n                    <br>\n                    <strong>Fixed in version(s):</strong>\n                    <br>\n                    {% for version in vuln.fixVersions %}\n                        <span class=\"severity-badge severity-Medium\">{{ version }}</span>\n                    {% endfor %}\n                </div>\n            {% endif %}\n            {% if vuln.references %}\n              <br><strong>References:</strong>\n              <ul>\n                {% for ref in vuln.references %}\n                  <li><a href=\"{{ ref }}\" target=\"_blank\">{{ ref }}</a></li>\n                {% endfor %}\n              </ul>\n            {% endif %}\n            {% if vuln.aliases %}\n              <br><strong>Aliases:</strong> {{ ', '.join(vuln.aliases) }}\n            {% endif %}\n          </td>\n        </tr>\n      {% endfor %}\n      </tbody>\n    </table>\n    <div class=\"footer\">\n      <p>Vulnerability information provided by JFrog Advanced Security. Please check <a href=\"https://jfrog.com/advanced-security/\" target=\"_blank\">https://jfrog.com/advanced-security/</a> for more information.</p>\n      <p>You can send questions and report issues about the returned vulnerabilities to <a href=\"mailto:conan-research@jfrog.com\">conan-research@jfrog.com</a>.</p>\n      <p>Conan version: {{ version }}</p>\n    </div>\n  </div>\n</body>\n</html>\n\"\"\"\n\n\ndef html_vuln_formatter(result):\n    vulns = []\n    for ref, pkg_info in result[\"data\"].items():\n        edges = pkg_info.get(\"vulnerabilities\", {}).get(\"edges\", [])\n        if not edges:\n            description = \"No vulnerabilities found.\" if \"error\" not in pkg_info \\\n                else pkg_info[\"error\"].get(\"details\", \"\")\n            vulns.append({\n                \"package\": ref,\n                \"vuln_id\": \"-\",\n                \"aliases\": [],\n                \"severity\": \"N/A\",\n                \"score\": \"-\",\n                \"description\": description,\n                \"references\": [],\n                \"withdrawn\": False,\n                \"advisories\": [],\n                \"provider_url\": result.get(\"provider_url\"),\n                \"fixVersions\": [],\n                \"publishedAt\": None\n            })\n        else:\n            sorted_vulns = sorted(edges, key=lambda v: -severity_order.get(v[\"node\"].get(\"severity\", \"Medium\"), 2))\n            for vuln in sorted_vulns:\n                node = vuln[\"node\"]\n                name = node.get(\"name\")\n                sev = node.get(\"severity\", \"Medium\")\n                sev = f\"{severity_order.get(sev, 2)} - {sev}\"\n                score = node.get(\"cvss\", {}).get(\"preferredBaseScore\")\n                score_txt = f\"CVSS: {score}\" if score else \"-\"\n                aliases = node.get(\"aliases\", [])\n                references = node.get(\"references\", [])\n                desc = node.get(\"description\", \"\")\n                withdrawn = node.get(\"withdrawn\", False)\n                advisories = node.get(\"advisories\", [])\n                jfrogAdvisories = [adv for adv in advisories\n                                   if adv.get(\"name\", \"\").startswith(\"JFSA-\")]\n                fixVersions = [fix['version']\n                               for fix_edge in node.get(\"vulnerablePackages\", {}).get(\"edges\", [])\n                               for fix in fix_edge['node'].get(\"fixVersions\", [])]\n                vulns.append({\n                    \"package\": ref,\n                    \"vuln_id\": name,\n                    \"aliases\": aliases,\n                    \"severity\": sev,\n                    \"score\": score_txt,\n                    \"description\": desc,\n                    \"references\": references,\n                    \"withdrawn\": withdrawn,\n                    \"advisories\": jfrogAdvisories,\n                    \"provider_url\": result.get(\"provider_url\"),\n                    \"fixVersions\": fixVersions,\n                    \"publishedAt\": node.get(\"publishedAt\")\n                })\n\n    cli_out_write(_render_vulns(vulns, vuln_html))\n"
  },
  {
    "path": "conan/cli/formatters/graph/__init__.py",
    "content": "from .graph import format_graph_html\nfrom .graph import format_graph_dot\nfrom .graph import format_graph_json\n"
  },
  {
    "path": "conan/cli/formatters/graph/build_order_html.py",
    "content": "from jinja2 import select_autoescape, Template\nfrom conan.api.output import cli_out_write\n\nbuild_order_html = r\"\"\"\n<html lang=\"en\">\n    <head>\n        <script src=\"https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.30.0/cytoscape.min.js\"\n        integrity=\"sha512-zHc90yHSbkgx0bvVpDK/nVgxANlE+yKN/jKy91tZ4P/vId8AL7HyjSpZqHmEujWDWNwxYXcfaLdYWjAULl35MQ==\"\n        crossorigin=\"anonymous\"\n        referrerpolicy=\"no-referrer\"></script>\n    </head>\n\n    <body>\n        <style>\n            body {\n                font: 14px helvetica neue, helvetica, arial, sans-serif;\n                display: flex;\n                margin: 0;\n                padding: 0;\n                height: 100vh;\n            }\n\n            .sidebar {\n                background: #f9f9f9;\n                border-right: 1px solid #ccc;\n                padding: 20px;\n                box-sizing: border-box;\n                overflow-y: auto;\n                font-size: 14px;\n                width: 440px;\n            }\n\n            .content {\n                flex-grow: 1;\n                display: flex;\n                flex-direction: column;\n                overflow: hidden;\n            }\n\n            #cy {\n                flex-grow: 1;\n            }\n\n            #node-info {\n                margin-top: 20px;\n                background: #f9f9f9;\n                padding: 12px;\n                font-family: monospace;\n                white-space: pre-wrap;\n                font-size: 12px;\n                word-wrap: break-word;\n            }\n\n            .legend {\n                margin-top: 20px;\n                font-size: 14px;\n            }\n\n            .legend-item {\n                display: flex;\n                align-items: center;\n                margin-bottom: 5px;\n            }\n\n            .legend-color {\n                width: 20px;\n                height: 20px;\n                margin-right: 10px;\n            }\n        </style>\n\n        <div class=\"sidebar\">\n            <div class=\"legend\">\n                <div class=\"legend-item\">\n                    <div class=\"legend-color\" style=\"background-color: #ffff37;\"></div>\n                    <span>All packages need to be built</span>\n                </div>\n                <div class=\"legend-item\">\n                    <div class=\"legend-color\" style=\"background-color: #ff9b28;\"></div>\n                    <span>Some packages need to be built</span>\n                </div>\n                <div class=\"legend-item\">\n                    <div class=\"legend-color\" style=\"background-color: #70c7e6;\"></div>\n                    <span>Cache</span>\n                </div>\n                <div class=\"legend-item\">\n                    <div class=\"legend-color\" style=\"background-color: #79eb8a;\"></div>\n                    <span>Download</span>\n                </div>\n                <div class=\"legend-item\">\n                    <div class=\"legend-color\" style=\"border: 1px solid black; width: 20px; height: 20px;\"></div>\n                    <span>Requirements in the <i>host</i> context</span>\n                </div>\n                <div class=\"legend-item\">\n                    <div class=\"legend-color\" style=\"border: 1px solid black; border-radius: 50%; width: 20px; height: 20px;\"></div>\n                    <span>Requirements in the <i>build</i> context</span>\n                </div>\n            </div>\n            <div id=\"node-info\">\n                <p>Click on a node to see details.</p>\n            </div>\n        </div>\n        <div class=\"content\">\n            <div id=\"cy\"></div>\n        </div>\n\n        <script type=\"text/javascript\">\n            document.addEventListener(\"DOMContentLoaded\", function() {\n                var buildOrderData = {{ build_order | tojson }};\n\n                var elements = [];\n                var edges = [];\n\n                var yOffset = 50;\n                var posX = 0;\n                var posY = 0;\n                var columns = 4;\n\n                buildOrderData.forEach((step, stepIndex) => {\n                    var stepId = 'step' + stepIndex;\n                    elements.push({\n                        data: { id: stepId, label: 'Step ' + (stepIndex + 1) },\n                        position: { x: posX, y: posY }\n                    });\n\n                    step.forEach((lib, libIndex) => {\n                        var libId = stepId + '_lib' + libIndex;\n                        var libLabel = lib.ref.split('#')[0];\n\n                        // Determine the type of the library\n                        var libData = Array.isArray(lib.packages) ? lib.packages[0][0] : lib;\n                        var libType = libData.binary || libData.build || libData.cache;\n\n                        var isAllBuild = true;\n                        var isSomeBuild = false;\n                        var shape = 'rectangle';\n                        var borderColor = '#00695C';\n\n                        if (Array.isArray(lib.packages)) {\n                            lib.packages.forEach(pkgArray => {\n                                pkgArray.forEach(pkg => {\n                                    if (pkg.binary === \"Build\") {\n                                        isSomeBuild = true;\n                                    } else {\n                                        isAllBuild = false;\n                                    }\n                                    if (pkg.context === \"build\") {\n                                        shape = 'ellipse';\n                                        borderColor = '#0000FF';  // Different border color for build context\n                                    }\n                                });\n                            });\n                        }\n\n                        var nodeColor;\n                        if (isAllBuild) {\n                            nodeColor = \"#ffff37\"; // Light orange for all build\n                        } else if (isSomeBuild) {\n                            nodeColor = \"#ff9b28\"; // Yellow for some build\n                        } else if (libType === \"Cache\") {\n                            nodeColor = \"#70c7e6\"; // Light green\n                        } else if (libType === \"Download\") {\n                            nodeColor = \"#79eb8a\"; // Light blue\n                        } else {\n                            nodeColor = \"#FFFFFF\"; // Default color\n                        }\n\n                        if (libIndex % columns === 0) {\n                            posX = 0;\n                            posY += yOffset; // move to the next row\n                        }\n\n                        elements.push({\n                            data: { id: libId, parent: stepId, label: libLabel, info: lib, color: nodeColor, shape: shape, borderColor: borderColor },\n                            position: { x: posX + libLabel.length / 2.0 * 12, y: posY }\n                        });\n                        posX += libLabel.length * 12;\n                    });\n\n                    if (stepIndex > 0) {\n                        var prevStepId = 'step' + (stepIndex - 1);\n                        edges.push({ data: { id: prevStepId + '_to_' + stepId, source: prevStepId, target: stepId } });\n                    }\n\n                    posY += yOffset * 2;\n                    posX = 0;\n                });\n\n                var cy = cytoscape({\n                    container: document.getElementById('cy'),\n                    boxSelectionEnabled: false,\n                    style: [\n                        {\n                            selector: 'node[color][shape][borderColor]',\n                            style: {\n                                'shape': 'data(shape)',\n                                'content': 'data(label)',\n                                'text-valign': 'center',\n                                'text-halign': 'center',\n                                'background-color': 'data(color)',\n                                'border-color': 'data(borderColor)',\n                                'border-width': 1,\n                                'width': function(ele) { return ele.data('label').length * 10.5; },\n                                'padding': '5px',\n                                'font-family': 'monospace',\n                                'font-size': '16px'\n                            }\n                        },\n                        {\n                            selector: ':parent',\n                            style: {\n                                'text-valign': 'top',\n                                'text-halign': 'center',\n                                'shape': 'round-rectangle',\n                                'background-opacity': 0.1,\n                                'border-color': '#004D40',\n                                'border-width': 2,\n                                'padding': 10,\n                                'font-family': 'monospace',\n                                'font-size': '16px'\n                            }\n                        },\n                        {\n                            selector: 'edge',\n                            style: {\n                                'curve-style': 'bezier',\n                                'target-arrow-shape': 'triangle',\n                                'line-color': '#004D40',\n                                'target-arrow-color': '#004D40',\n                                'width': 2\n                            }\n                        }\n                    ],\n                    elements: {\n                        nodes: elements,\n                        edges: edges\n                    },\n                    layout: {\n                        name: 'preset',\n                        padding: 5,\n                        fit: true\n                    }\n                });\n\n                // Add click event listener to nodes\n                cy.on('tap', 'node', function(evt){\n                    var node = evt.target;\n                    var info = node.data('info');\n                    var infoHtml = '';\n                    for (var key in info) {\n                        if (info.hasOwnProperty(key)) {\n                            infoHtml += '<p><strong>' + key + ':</strong> ' + JSON.stringify(info[key], null, 2) + '</p>';\n                        }\n                    }\n                    document.getElementById('node-info').innerHTML = infoHtml;\n                });\n            });\n        </script>\n    </body>\n</html>\n\"\"\"\n\n\ndef _render_build_order(build_order, template):\n    from conan import __version__\n    context = {'build_order': build_order, 'version': __version__}\n    return template.render(context)\n\n\ndef format_build_order_html(result):\n    build_order = result[\"build_order\"]\n    build_order = build_order[\"order\"] if isinstance(build_order, dict) else build_order\n    template = Template(build_order_html, autoescape=select_autoescape(['html', 'xml']))\n    cli_out_write(_render_build_order(build_order, template))\n"
  },
  {
    "path": "conan/cli/formatters/graph/graph.py",
    "content": "import json\nimport os\n\nfrom jinja2 import Template, select_autoescape\n\nfrom conan.api.output import cli_out_write\nfrom conan.cli.formatters.graph.graph_info_text import filter_graph\nfrom conan.cli.formatters.graph.info_graph_dot import graph_info_dot\nfrom conan.cli.formatters.graph.info_graph_html import graph_info_html\n\n\ndef _render_graph(graph, template, template_folder):\n    deps_graph = graph.serialize()\n    from conan import __version__\n    template = Template(template, autoescape=select_autoescape(['html', 'xml']))\n    return template.render(deps_graph=deps_graph,\n                           base_template_path=template_folder, version=__version__)\n\n\ndef format_graph_html(result):\n    graph = result[\"graph\"]\n    conan_api = result[\"conan_api\"]\n\n    template_folder = os.path.join(conan_api.cache_folder, \"templates\")\n    user_template = os.path.join(template_folder, \"graph.html\")\n    template = graph_info_html\n    if os.path.isfile(user_template):\n        with open(user_template, 'r', encoding=\"utf-8\", newline=\"\") as handle:\n            template = handle.read()\n    cli_out_write(_render_graph(graph, template, template_folder))\n\n\ndef format_graph_dot(result):\n    graph = result[\"graph\"]\n    conan_api = result[\"conan_api\"]\n\n    template_folder = os.path.join(conan_api.cache_folder, \"templates\")\n    user_template = os.path.join(template_folder, \"graph.dot\")\n    template = graph_info_dot\n    if os.path.isfile(user_template):\n        with open(user_template, 'r', encoding=\"utf-8\", newline=\"\") as handle:\n            template = handle.read()\n    cli_out_write(_render_graph(graph, template, template_folder))\n\n\ndef format_graph_json(result):\n    graph = result[\"graph\"]\n    field_filter = result.get(\"field_filter\")\n    package_filter = result.get(\"package_filter\")\n    serial = graph.serialize()\n    serial = filter_graph(serial, package_filter=package_filter, field_filter=field_filter)\n    json_result = json.dumps({\"graph\": serial}, indent=4)\n    cli_out_write(json_result)\n"
  },
  {
    "path": "conan/cli/formatters/graph/graph_info_text.py",
    "content": "import fnmatch\nfrom collections import OrderedDict\n\nfrom conan.api.model import RecipeReference\nfrom conan.api.output import ConanOutput, cli_out_write\n\n\ndef filter_graph(graph, package_filter=None, field_filter=None):\n    if package_filter is not None:\n        def _matching(node, pattern):\n            if fnmatch.fnmatch(node[\"ref\"] or \"\", pattern):\n                return True\n            if pattern == \"&\":  # Handle the consumer pattern\n                if node[\"recipe\"] == \"Consumer\":\n                    return True\n                # How to deal with --requires=xxx --package-filter=& \"consumers\"\n                root = graph[\"nodes\"][\"0\"]\n                if root[\"recipe\"] == \"Cli\" and node is not root:\n                    # We look if the current node is a direct dependency of the root node\n                    node_ref = RecipeReference.loads(node[\"ref\"])\n                    for dep in root[\"dependencies\"].values():\n                        if dep[\"direct\"] and node_ref == RecipeReference.loads(dep[\"ref\"]):\n                            return True\n\n        graph[\"nodes\"] = {id_: n for id_, n in graph[\"nodes\"].items()\n                          if any(_matching(n, p) for p in package_filter)}\n    if field_filter is not None:\n        if \"ref\" not in field_filter:\n            field_filter.append(\"ref\")\n        result = {}\n        for id_, n in graph[\"nodes\"].items():\n            new_node = OrderedDict((k, v) for k, v in n.items() if k in field_filter)\n            result[id_] = new_node\n        graph[\"nodes\"] = result\n    return graph\n\n\ndef format_graph_info(result):\n    \"\"\" More complete graph output, including information for every node in the graph\n    Used for 'graph info' command\n    \"\"\"\n    graph = result[\"graph\"]\n    field_filter = result[\"field_filter\"]\n    package_filter = result[\"package_filter\"]\n\n    ConanOutput().subtitle(\"Basic graph information\")\n    serial = graph.serialize()\n    serial = filter_graph(serial, package_filter, field_filter)\n    for n in serial[\"nodes\"].values():\n        cli_out_write(f\"{n['ref']}:\")  # FIXME: This can be empty for consumers and it is ugly \":\"\n        _serial_pretty_printer(n, indent=\"  \")\n\n\ndef _serial_pretty_printer(data, indent=\"\"):\n    for k, v in data.items():\n        if isinstance(v, dict):\n            cli_out_write(f\"{indent}{k}:\")\n            # TODO: increment color too\n            _serial_pretty_printer(v, indent=indent+\"  \")\n        else:\n            cli_out_write(f\"{indent}{k}: {v}\")\n"
  },
  {
    "path": "conan/cli/formatters/graph/info_graph_dot.py",
    "content": "\ngraph_info_dot = \"\"\"\\\ndigraph {\n    {%- for node_id, node in deps_graph[\"nodes\"].items() %}\n        {%- for dep_id, dep in node[\"dependencies\"].items() %}\n        {%- if dep[\"direct\"] %}\n        \"{{ node[\"label\"] }}\" -> \"{{ deps_graph[\"nodes\"][dep_id][\"label\"] }}\"\n        {%- endif %}\n        {%- endfor %}\n    {%- endfor %}\n}\n\n\"\"\"\n"
  },
  {
    "path": "conan/cli/formatters/graph/info_graph_html.py",
    "content": "graph_info_html = r\"\"\"\n<html lang=\"en\">\n    <head>\n        <script src=\"https://cdnjs.cloudflare.com/ajax/libs/vis-network/9.1.9/standalone/umd/vis-network.min.js\" integrity=\"sha512-iTgTmIgxyA2YehKNVbzLJx4j9SnuC5ihtRrtxVkXH/9nF3vXBN5YeNQp+6wufBWKD3u+roHVNOvWBMufQnBbug==\" crossorigin=\"anonymous\" referrerpolicy=\"no-referrer\"></script>\n    </head>\n\n    <body>\n        <style>\n            @media print {\n                .noPrint {\n                    display: none;\n                }\n            }\n            .button {\n                background-color: #5555cc;\n                border: none;\n                color: white;\n                padding: 5px 10px;\n                text-align: center;\n                text-decoration: none;\n                display: inline-block;\n                font-size: 18px;\n            }\n        </style>\n\n        <div style=\"display: grid; grid-template-columns: 75% 25%; grid-template-rows: 30px auto; height: 100vh;\">\n            <div id=\"mylegend\" style=\"background-color: lightgrey; grid-column-end: span 2;height: 100%\"></div>\n            <div id=\"mynetwork\"></div>\n            <div style=\"background-color: lightgrey;min-height:100%;height:0;overflow-y: auto;\">\n                <div>\n                    <input type=\"checkbox\" onchange=\"switchBuild()\" id=\"show_build_requires\" checked />\n                    <label for=\"show_build_requires\">Show build-requires</label>\n                </div>\n                <div>\n                    <input type=\"checkbox\" onchange=\"switchTest()\" id=\"show_test_requires\" checked />\n                    <label for=\"show_test_requires\">Show test-requires</label>\n                </div>\n                <div>\n                    <input type=\"checkbox\" onchange=\"switchTransitive()\" id=\"show_transitive_requires\"/>\n                    <label for=\"show_transitive_requires\">Show transitive-requires</label>\n                </div>\n                <div>\n                    <input type=\"checkbox\" onchange=\"collapsePackages()\" id=\"collapse_packages\"/>\n                    <label for=\"collapse_packages\">Group packages</label>\n                </div>\n                 <div>\n                    <input type=\"checkbox\" onchange=\"showPackageType()\" id=\"show_package_type\"/>\n                    <label for=\"show_package_type\">Show package type</label>\n                </div>\n                 <div>\n                    <input type=\"search\" placeholder=\"Search packages...\" oninput=\"searchPackages(this)\" onkeydown=\"onSearchKeyDown(event)\">\n                </div>\n                 <div>\n                    <input type=\"search\" placeholder=\"Exclude packages...\" title=\"Add a comma to exclude an additional package\" oninput=\"excludePackages(this)\">\n                </div>\n                <div>\n                    <input type=\"checkbox\" onchange=\"showhideclass('controls')\" id=\"show_controls\"/>\n                    <label for=\"show_controls\">Show graph controls</label>\n                </div>\n                <div id=\"controls\" class=\"controls\" style=\"padding:5; display:none\"></div>\n                <div id=\"details\"  style=\"padding:10;\" class=\"noPrint\">Package info: Click on one package to show information</div>\n                <div id=\"error\" style=\"padding:10;\" class=\"noPrint\"></div>\n            </div>\n        </div>\n\n        <script type=\"text/javascript\">\n            const graph_data = {{ deps_graph | tojson }};\n            let hide_build = false;\n            let hide_test = false;\n            let show_transitive = false;\n            let search_pkgs = null;\n            let focus_search = false;\n            let excluded_pkgs = null;\n            let collapse_packages = false;\n            let show_package_type = false;\n            let color_map = {Cache: \"SkyBlue\",\n                             Download: \"LightGreen\",\n                             Build: \"Yellow\",\n                             Missing: \"Orange\",\n                             Update: \"SeaGreen\",\n                             Skip: \"White\",\n                             Editable: \"LightCyan\",\n                             EditableBuild: \"Cyan\",\n                             Invalid: \"Red\",\n                             Platform: \"Violet\"};\n            let global_edges = {};\n            function define_data(){\n                let nodes = [];\n                let edges = [];\n                let collapsed_packages = {\"build\": {}, \"host\": {}};\n                let targets = {};\n                global_edges = {};\n                let edge_counter = 0;\n                let conflict=null;\n                let provide_conflict=null;\n                let missing_error=null;\n                let loop_error=null;\n                if (graph_data[\"error\"] && graph_data[\"error\"][\"type\"] == \"conflict\")\n                    conflict = graph_data[\"error\"];\n                else if (graph_data[\"error\"] && graph_data[\"error\"][\"type\"] == \"provide_conflict\")\n                    provide_conflict = graph_data[\"error\"];\n                else if (graph_data[\"error\"] && graph_data[\"error\"][\"type\"] == \"missing\")\n                    missing_error = graph_data[\"error\"];\n                else if (graph_data[\"error\"] && graph_data[\"error\"][\"type\"] == \"loop\")\n                    loop_error = [graph_data[\"error\"]['node']['label'], graph_data[\"error\"]['require']['name']];\n                for (const [node_id, node] of Object.entries(graph_data[\"nodes\"])) {\n                    if (node.context == \"build\" && hide_build) continue;\n                    if (node.test && hide_test) continue;\n                    let shape = node.context == \"build\" || node.test ? \"ellipse\" : \"box\";\n                    let label = null;\n                    if (node[\"name\"])\n                        label =  node[\"name\"] + \"/\" + node[\"version\"];\n                    else if (node[\"ref\"])\n                        label = node[\"ref\"];\n                    else\n                        label = node.recipe == \"Consumer\"? \"conanfile\": \"CLI\";\n                    if (collapse_packages) {\n                        let existing = collapsed_packages[node.context][label];\n                        targets[node_id] = existing;\n                        if (existing) continue;\n                        collapsed_packages[node.context][label] = node_id;\n                    }\n                    if (excluded_pkgs) {\n                        let patterns = excluded_pkgs.split(',')\n                            .map(pattern => pattern.trim())\n                            .filter(pattern => pattern.length > 0)\n                            .map(pattern => pattern.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&'));\n                        if (patterns.some(pattern => label.match(pattern))) {\n                            continue;\n                        }\n                    }\n                    if (show_package_type) {\n                         label = \"<b>\" + label + \"\\n\" + \"<i>\" + node.package_type + \"</i>\";\n                    }\n                    borderWidth = 1;\n                    borderColor = \"SkyBlue\";\n                    font = {multi: 'html'};\n                    shapeProperties = {};\n                    let color = color_map[node.binary]\n                    if (conflict && conflict.branch1.dst_id == node_id){\n                        font.color = \"white\";\n                        color = \"Black\";\n                        shape = \"circle\";\n                    }\n                    if (provide_conflict && provide_conflict.node.id == node_id){\n                        font.color = \"white\";\n                        color = \"Black\";\n                        shape = \"circle\";\n                    }\n                    if (search_pkgs) {\n                        let patterns = search_pkgs.split(',')\n                            .map(pattern => pattern.trim())\n                            .filter(pattern => pattern.length > 0)\n                            .map(pattern => pattern.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&'));\n                        if (patterns.some(pattern => label.match(pattern))) {\n                            borderWidth = 3;\n                            borderColor = \"Magenta\";\n                            if (focus_search) {\n                                focus_search = node_id;\n                            }\n                        }\n                    }\n                    if (node.test) {\n                        font.background = \"lightgrey\";\n                        shapeProperties = {borderDashes: true};\n                    }\n                    if (node.recipe == \"Platform\") {\n                        font.background = \"Violet\";\n                    }\n                    if (node.vendor) {\n                        borderColor = \"Red\";\n                        shapeProperties = {borderDashes: [3,5]};\n                        borderWidth = 2;\n                    }\n                    nodes.push({\n                        id: node_id,\n                        font: font,\n                        label: label,\n                        shape: shape,\n                        shapeProperties: shapeProperties,\n                        borderWidth: borderWidth,\n                        color: {border: borderColor, background: color,\n                                highlight: {background: color, border: \"Blue\"}},\n                    });\n                }\n                for (const [node_id, node] of Object.entries(graph_data[\"nodes\"])) {\n                    for (const [dep_id, dep] of Object.entries(node[\"dependencies\"])) {\n                        if (dep.direct){\n                            let target_id = targets[dep_id] || dep_id;\n                            edges.push({id: edge_counter, from: node_id, to: target_id,\n                                        color: {color: \"SkyBlue\", highlight: \"Blue\"}});\n                            global_edges[edge_counter++] = dep;\n                        }\n                        if (show_transitive && dep.direct === false){\n                            let target_id = targets[dep_id] || dep_id;\n                            edges.push({id: edge_counter, from: node_id, to: target_id,\n                                        color: {color: \"LightGray\", highlight: \"Gray\"},\n                                        dashes: true});\n                            global_edges[edge_counter++] = dep;\n                        }\n                        if (loop_error && loop_error[1] == node[\"name\"] && loop_error[0] == dep[\"ref\"]) {\n                            let target_id = targets[dep_id] || dep_id;\n                            edges.push({id: edge_counter, from: node_id, to: target_id,\n                                        color: {color: \"Red\", highlight: \"Red\"},\n                                        smooth: { enabled: true, type: 'curvedCW', roundness: 0.4 },\n                                        arrows: \"from\",\n                                        label: \"loop\",\n                                        title: \"loop\"});\n                            global_edges[edge_counter++] = dep;\n                        }\n                    }\n                }\n                if (conflict) {\n                    let conflict_id = null;\n                    if (conflict.branch1.dst_id) { // already created conflict node\n                        conflict_id = conflict.branch1.dst_id;\n                    }\n                    else {\n                        conflict_id = \"conflict_id\";\n                        nodes.push({\n                            id: conflict_id,\n                            font: {color: \"white\"},\n                            label: conflict.name,\n                            shape: \"circle\",\n                            color: {background: \"black\",\n                                    highlight: {background: \"black\", border: \"Blue\"}},\n                        });\n                        edges.push({id: edge_counter, from: conflict.branch1.src_id, to: conflict_id,\n                                    color: {color: \"Red\", highlight: \"Red\"},\n                                    label: conflict.branch1.require.ref});\n                        global_edges[edge_counter++] = conflict.branch1.require;\n                    }\n                    edges.push({id: edge_counter, from: conflict.branch2.src_id, to: conflict_id,\n                                color: {color: \"Red\", highlight: \"Red\"},\n                                label: conflict.branch2.require.ref});\n                    global_edges[edge_counter++] = conflict.branch2.require;\n                }\n                if (provide_conflict) {\n                    // The nodes are already there, we'll just add an edge to the conflict node\n                    edges.push({id: edge_counter,\n                                from: provide_conflict.conflicting_node.id,\n                                to: provide_conflict.node.id,\n                                color: {color: \"Red\", highlight: \"Red\"},\n                                label: provide_conflict.provided,\n                                title: \"Both nodes provide the same requirement: \" + provide_conflict.provided.join(\", \"),\n                                dashes: true});\n                    global_edges[edge_counter++] = {\"provided\": provide_conflict.provided};\n                }\n                if(missing_error) {\n                    nodes.push({\n                        id: \"missing_node\",\n                        font: {multi: 'html', color: \"white\"},\n                        label: missing_error[\"require\"][\"ref\"],\n                        shape: \"Circle\",\n                        color: {background: \"Black\"},\n                    });\n                    edges.push({id: edge_counter,\n                                from: missing_error[\"node\"][\"id\"],\n                                to: \"missing_node\",\n                                color: {color: \"Red\", highlight: \"Red\"},\n                                label: \"missing\",\n                                title: \"missing\",\n                                dashes: true});\n                    global_edges[edge_counter++] = {\"missing\": missing_error[\"error\"]};\n                }\n                return {nodes: new vis.DataSet(nodes), edges: new vis.DataSet(edges)};\n            };\n            function define_legend() {\n                let x = 0;\n                let y = 0;\n                let step = 250;\n                let legend_nodes = [];\n                legend_nodes.push({id: 0, x: x, y: y, shape: \"box\", font: {size: 35},\n                    label: \"require\",\n                });\n                legend_nodes.push({id: 1, x: x + step, y: y, font: {size: 35}, shape: \"ellipse\",\n                    label: \"tool-require\",\n                });\n                legend_nodes.push({id: 2, x: x + 2* step, y: y, font: {size: 35, background: \"lightgrey\"},\n                    shape: \"ellipse\", shapeProperties: {borderDashes: true},\n                    label: \"test-require\",\n                })\n                let counter = 3;\n                legend_nodes.push({x: x + counter*step, y: y, shape: \"ellipse\",\n                    label: \"platform\",\n                    font: {size: 35, background: \"Violet\"},\n                });\n                counter++;\n                for (const [status, color] of Object.entries(color_map)) {\n                    legend_nodes.push({x: x + counter*step, y: y, shape: \"box\", font: {size: 35},\n                        label: status,\n                        color: {border: \"SkyBlue\", background: color}\n                    });\n                    counter++;\n                }\n                legend_nodes.push({x: x + counter*step, y: y, shape: \"box\",\n                    label: \"conflict\",\n                    font: {size: 35, color: \"white\"},\n                    color: {border: \"SkyBlue\", background: \"Black\"}\n                });\n                counter++;\n\n                legend_nodes.push({x: x + counter*step, y: y, shape: \"box\",\n                    label: \"vendor\", font: {size: 35},\n                    color: {border: \"Red\"},\n                    shapeProperties: {borderDashes: [3,5]},\n                    borderWidth: 2\n                });\n                return {nodes: new vis.DataSet(legend_nodes)};\n            }\n            let error = document.getElementById(\"error\");\n            if (graph_data[\"error\"]){\n                 let div = document.createElement('div');\n                 div.innerHTML = \"<pre>Error in the graph: \" + JSON.stringify(graph_data[\"error\"], undefined, 2) + \"</pre>\";\n                 error.appendChild(div);\n            }\n            let container = document.getElementById('mynetwork');\n            let controls = document.getElementById('controls');\n            let legend_container = document.getElementById('mylegend');\n\n            let options = {\n                autoResize: true,\n                locale: 'en',\n                edges: {\n                    arrows: { to: {enabled: true} },\n                    smooth: { enabled: false}\n                },\n                nodes: {font: {'face': 'monospace', 'align': 'left'}},\n                layout: {\n                    \"hierarchical\": {\n                        enabled: true,\n                        sortMethod: \"directed\",\n                        direction: \"DU\",\n                        nodeSpacing: 170,\n                        blockShifting: true,\n                        edgeMinimization: true,\n                        shakeTowards: \"roots\",\n                    }\n                },\n                physics: { enabled: false},\n                configure: {\n                    enabled: true,\n                    filter: 'layout physics',\n                    showButton: false,\n                    container: controls\n                }\n            };\n\n            let data = define_data();\n            let network = new vis.Network(container, data, options);\n            let legend_data = define_legend();\n            let options_legend = {interaction: {selectable: false, dragView: false, dragNodes: false,\n                                                zoomView: false}, physics: {enabled: false}};\n            let legend = new vis.Network(legend_container, legend_data, options_legend);\n\n            network.on('click', function (properties) {\n                let ids = properties.nodes;\n                let ids_edges = properties.edges;\n                let control = document.getElementById(\"details\");\n                while (control.firstChild) {\n                    control.removeChild(control.firstChild);\n                }\n                if(ids[0] !== undefined || ids_edges[0] !== undefined) {\n                    selected = graph_data[\"nodes\"][ids[0]] || global_edges[ids_edges[0]];\n                    let div = document.createElement('div');\n                    let f = Object.fromEntries(Object.entries(selected).filter(([_, v]) => v != null));\n                    div.innerText = JSON.stringify(f, undefined, 2);\n                    let div2 = document.createElement('div');\n                    div2.innerHTML = \"<pre>\" + div.innerHTML + \"</pre>\";\n                    control.appendChild(div2);\n                }\n                else {\n                    control.innerHTML = \"<b>Info</b>: Click on a package or edge for more info\";\n                }\n            });\n            function draw() {\n                let scale = network.getScale();\n                let viewPos = network.getViewPosition();\n                data = define_data();\n                network.setData(data);\n                network.redraw();\n                network.moveTo({position: viewPos, scale: scale});\n                // If we have found a package to focus, we need to move the view\n                if (typeof focus_search === \"string\") {\n                    network.focus(focus_search, {animation: true, locked: false});\n                }\n            }\n            function switchBuild() {\n                hide_build = !hide_build;\n                draw();\n            }\n            function switchTest() {\n                hide_test = !hide_test;\n                draw();\n            }\n            function switchTransitive() {\n                show_transitive = !show_transitive;\n                draw();\n            }\n            function collapsePackages() {\n                collapse_packages = !collapse_packages;\n                draw();\n            }\n            const debounce = (func, delay) => {\n                let timeout;\n                return function(...args) {\n                    clearTimeout(timeout);\n                    timeout = setTimeout(() => func.apply(this, args), delay);\n                };\n            };\n            const debouncedDraw = debounce(draw, 300);\n            function searchPackages(e) {\n                search_pkgs = e.value;\n                debouncedDraw();\n            }\n            function onSearchKeyDown(event) {\n                if (event.key === \"Enter\") {\n                    focus_search = true;\n                    draw();\n                    focus_search = false;\n                }\n            }\n            function excludePackages(e) {\n                excluded_pkgs = e.value;\n                debouncedDraw();\n            }\n            function showPackageType(e) {\n                show_package_type = !show_package_type;\n                draw();\n            }\n            function showhideclass(id) {\n                let elements = document.getElementsByClassName(id)\n                for (let i = 0; i < elements.length; i++) {\n                    elements[i].style.display = (elements[i].style.display != 'none') ? 'none' : 'block';\n                }\n            }\n            window.addEventListener(\"load\", () => {\n               draw();\n            });\n        </script>\n    </body>\n</html>\n\"\"\"\n"
  },
  {
    "path": "conan/cli/formatters/list/__init__.py",
    "content": "from .list import list_packages_html\n"
  },
  {
    "path": "conan/cli/formatters/list/list.py",
    "content": "import json\nimport os\n\nfrom jinja2 import Template, select_autoescape\n\nfrom conan.api.output import cli_out_write\nfrom conan.cli.formatters.list.search_table_html import list_packages_html_template\nfrom conan import __version__\n\n\ndef list_packages_html(result):\n    results = result[\"results\"]\n    cli_args = result[\"cli_args\"]\n    conan_api = result[\"conan_api\"]\n    template_folder = os.path.join(conan_api.cache_folder, \"templates\")\n    user_template = os.path.join(template_folder, \"list_packages.html\")\n    template = list_packages_html_template\n    if os.path.isfile(user_template):\n        with open(user_template, 'r', encoding=\"utf-8\", newline=\"\") as handle:\n            template = handle.read()\n    template = Template(template, autoescape=select_autoescape(['html', 'xml']))\n    content = template.render(results=json.dumps(results), base_template_path=template_folder,\n                              version=__version__, cli_args=cli_args)\n    cli_out_write(content)\n"
  },
  {
    "path": "conan/cli/formatters/list/search_table_html.py",
    "content": "list_packages_html_template = r\"\"\"\n<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n    <title>conan list results</title>\n    <link href=\"https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css\" rel=\"stylesheet\"\n        integrity=\"sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65\" crossorigin=\"anonymous\">\n    <style>\n        body {\n            font-family: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n            font-size: 0.75rem;\n        }\n\n        .accordion-button {\n            padding: 0.25rem 0.25rem;\n        }\n\n        .list-group {\n            max-height: 100vh;\n            overflow: auto;\n        }\n\n        .list-group-item {\n            padding: 0.2rem 0.35rem;\n            border: 0px;\n        }\n    </style>\n    <script>\n        var list_results = {{ results| safe }};\n\n        function replaceChars(origin, ref) {\n            return origin + \"_\" + ref.replaceAll(\".\", \"_\").replaceAll(\"/\", \"_\").replaceAll(\"#\", \"_\").replaceAll(\"@\", \"_\").replaceAll(\":\", \"_\").replaceAll(\" \", \"_\")\n        }\n\n        function getPackagesCount(revInfo) {\n            if (\"packages\" in revInfo) {\n                return Object.keys(revInfo[\"packages\"]).length;\n            }\n            return 0;\n        }\n\n        function formatDate(timeStamp) {\n            var options = {\n                year: \"numeric\",\n                month: \"2-digit\",\n                day: \"2-digit\",\n                hour: \"2-digit\",\n                minute: \"2-digit\",\n                second: \"2-digit\",\n                hour12: false\n            };\n            return new Date(timeStamp * 1000).toLocaleDateString('en', options);\n        }\n\n        function getInfoFieldsBadges(info) {\n            let style = '';\n            let badges = '';\n            for (property of [\"settings\", \"options\"]) {\n                if (property in info) {\n                    for (const [key, value] of Object.entries(info[property])) {\n                        style = (key == 'os') ? 'text-bg-info' : 'text-bg-secondary';\n                        badges += `<span class=\"badge ${style}\">${key}: ${value}</span>&nbsp;`\n                    }\n                }\n            }\n            return badges;\n        }\n\n        function isSubset(setA, setB) {\n            for (let elem of setA) {\n                if (!setB.has(elem)) {\n                    return false;\n                }\n            }\n            return true;\n        }\n\n        function isFiltered(info, filters) {\n            if (filters.length == 0) {\n                return false;\n            }\n            packageProperties = [];\n            for (property of [\"settings\", \"options\"]) {\n                if (property in info) {\n                    for (const [key, value] of Object.entries(info[property])) {\n                        packageProperties.push(`${key}=${value}`);\n                    }\n                }\n            }\n            packageSet = new Set(packageProperties);\n            filtersSet = new Set(filters);\n            if (isSubset(filtersSet, packageSet)) {\n                return false;\n            }\n            return true;\n        }\n\n        function getUniqueSettingsOptions(revInfo) {\n            let options = new Set();\n            let settings = new Set();\n            for (const [package, packageInfo] of Object.entries(revInfo[\"packages\"])) {\n                let info = packageInfo[\"info\"];\n                if (\"options\" in info) {\n                    for (const [key, value] of Object.entries(info[\"options\"])) {\n                        options.add(`${key}=${value}`)\n                    }\n                }\n                if (\"settings\" in info) {\n                    for (const [key, value] of Object.entries(info[\"settings\"])) {\n                        settings.add(`${key}=${value}`)\n                    }\n                }\n            }\n            return [options, settings]\n        }\n\n        function getFilters(revID, revInfo) {\n            let options_settings = getUniqueSettingsOptions(revInfo);\n            let options = Array.from(options_settings[0]);\n            let settings = Array.from(options_settings[1]);\n            let filter = `<h6>Filter packages:</h6>`\n            for (setting of settings) {\n                filter += `\n                        <div class=\"form-check form-check-inline\">\n                            <input class=\"form-check-input\" type=\"checkbox\" id=\"${revID}#${setting}\" value=\"${setting}\">\n                            <label class=\"form-check-label\" for=\"${revID}#${setting}\">${setting}</label>\n                        </div>\n                      `\n            }\n            for (option of options) {\n                filter += `\n                        <div class=\"form-check form-check-inline\">\n                            <input class=\"form-check-input\" type=\"checkbox\" id=\"${revID}#${option}\" value=\"${option}\">\n                            <label class=\"form-check-label\" for=\"${revID}#${option}\">${option}</label>\n                        </div>\n                      `\n            }\n            return filter;\n        }\n\n        let activeRevision = {};\n        let tabsInfo = {};\n\n        function filterPackages() {\n            const activeTab = document.querySelector('.tab-pane.active');\n            const packageList = activeTab.querySelector('#packageList');\n            activeRevision.revision = tabsInfo[activeTab.getAttribute('id')].revision;\n            activeRevision.revInfo = tabsInfo[activeTab.getAttribute('id')].revInfo;\n            packageList.innerHTML = getPackagesList(activeRevision.revision, activeRevision.revInfo);\n        }\n\n        function getPackagesList(revision, revInfo) {\n            const checkboxes = document.querySelectorAll('input[type=\"checkbox\"]');\n            filters = [];\n            checkboxes.forEach(function (checkbox) {\n                if (checkbox.checked) {\n                    filters.push(checkbox.value)\n                }\n            })\n\n            activeRevInfo = revInfo;\n            let packageList = ``;\n            for (const [package, packageInfo] of Object.entries(revInfo[\"packages\"])) {\n\n                if (!isFiltered(packageInfo[\"info\"], filters)) {\n                    packageList += `<div class=\"bg-light\">`;\n                    packageList += `<h6 class=\"mb-1\">${package}</h6>`;\n                    packageList += `${getInfoFieldsBadges(packageInfo[\"info\"])}`;\n\n                    packageList += `<br><br>`;\n                    if (\"revisions\" in packageInfo) {\n                        packageList += `<br><br><b>Package revisions:</>`;\n                        packageList += `<ul>`;\n                        for (const [packageRev, packageRevInfo] of Object.entries(packageInfo[\"revisions\"])) {\n                            packageList += `<li>${packageRev}&nbsp(${formatDate(packageRevInfo[\"timestamp\"])})</li>`;\n                        }\n                        packageList += `</ul>`;\n                    }\n                    packageList += `</div>`;\n                    packageList += `<br>`;\n                }\n            }\n            return packageList;\n        }\n\n        function getTabContent(tabID, revID, revInfo) {\n\n            let tabContent = `<div class=\"tab-pane\" id=\"${tabID}\" role=\"tabpanel\">`;\n\n            if (\"packages\" in revInfo && Object.entries(revInfo[\"packages\"]).length > 0) {\n\n                tabContent += `<h3>Packages for revision ${revID}</h3>`;\n\n                tabContent += getFilters(revID, revInfo);\n\n                tabContent += `<div id=\"packageList\">`;\n                tabContent += getPackagesList(revID, revInfo);\n                tabContent += `</div>`;\n\n            }\n            tabContent += `<h3>JSON</h3>`;\n            tabContent += `<pre class=\"p-3 mb-2 bg-light text-dark\">${JSON.stringify(revInfo, null, 2)}</pre>`;\n            tabContent += `</div>`\n            return tabContent;\n        }\n\n        let menu = `<div class=\"list-group list-group-flush\" id=\"leftTabs\" role=\"tablist\">`;\n        let tabs = `<div class=\"tab-content\">`;\n\n        for (const [origin, references] of Object.entries(list_results)) {\n            if (Object.keys(references).length > 0) {\n                menu += `<li class=\"list-group-item\"><b>${origin}</b>`;\n                if (\"error\" in references) {\n                    menu += `<pre>${references[\"error\"]}</pre>`;\n                }\n                else {\n                    for (const [reference, revisions] of Object.entries(references)) {\n                        let originStr = origin.replaceAll(\" \", \"_\");\n                        const refLink = replaceChars(originStr, reference);\n\n                        menu += `<div class=\"accordion accordion-flush\" id=\"accordion_${originStr}\">`;\n                        menu += `<div class=\"accordion-item\">`;\n                        menu += `<h2 class=\"accordion-header\" id=\"heading_${refLink}\">`;\n                        menu += `<button class=\"accordion-button collapsed\" type=\"button\" id=\"left_${refLink}\" data-bs-toggle=\"collapse\" data-bs-target=\"#rev_list_${refLink}\" aria-expanded=\"false\" aria-controls=\"${refLink}\">${reference}</button>`;\n                        menu += `</h2>`;\n                        menu += `<div id=\"rev_list_${refLink}\" class=\"accordion-collapse collapse\" aria-labelledby=\"heading_${refLink}\" data-bs-parent=\"#accordion_${originStr}\">`\n\n                        if (\"revisions\" in revisions) {\n                            for (const [revision, revInfo] of Object.entries(revisions[\"revisions\"])) {\n                                let packageCount = getPackagesCount(revInfo);\n                                packageBadge = (packageCount == 0) ? '' : `&nbsp<span class=\"badge rounded-pill text-bg-success\">${packageCount}</span>`;\n                                let tabID = `${originStr}_${revision}`;\n                                menu += `<a class=\"list-group-item list-group-item-action\" id=\"left_${revision}\" data-bs-toggle=\"list\" href=\"#${tabID}\" role=\"tab\" aria-controls=\"list-home\">${revision.substring(0, 6)}&nbsp(${formatDate(revInfo[\"timestamp\"])})${packageBadge}</a>`;\n\n                                tabsInfo[tabID] = { \"revision\": revision, \"revInfo\": revInfo }\n                                tabs += getTabContent(tabID, revision, revInfo);\n                            }\n                        }\n                        menu += `</div>`\n                        menu += '</div>';\n                        menu += '</div>';\n                    }\n\n                }\n\n                menu += \"</li>\";\n            }\n        }\n        menu += \"</div>\";\n        tabs += \"</div>\";\n\n        document.addEventListener(\"DOMContentLoaded\", function () {\n            let leftMenu = document.getElementById(\"leftmenu\");\n            let rightMenu = document.getElementById(\"rightmenu\");\n            leftMenu.innerHTML = menu;\n            rightMenu.innerHTML = tabs;\n\n            var triggerTabList = [].slice.call(document.querySelectorAll('#leftTabs a'))\n            triggerTabList.forEach(function (triggerEl) {\n                var tabTrigger = new bootstrap.Tab(triggerEl)\n                triggerEl.addEventListener('click', function (event) {\n                    // remove active from all, so only .list-group-item is selected\n                    var listItems = document.querySelectorAll('.list-group-item');\n                    for (var i = 0; i < listItems.length; i++) {\n                        listItems[i].classList.remove('active');\n                    }\n                    event.preventDefault()\n                    tabTrigger.show()\n                })\n            })\n\n            const checkboxes = document.querySelectorAll('input[type=\"checkbox\"]');\n            checkboxes.forEach(function (checkbox) {\n                checkbox.addEventListener('change', function () {\n                    filterPackages();\n                });\n            });\n\n        });\n    </script>\n</head>\n\n<body>\n    <nav class=\"navbar navbar-expand-lg bg-light\">\n        <div class=\"container-fluid\">\n            <a class=\"navbar-brand\">conan list: {{ cli_args }}</a>\n        </div>\n    </nav>\n\n    <div class=\"container-fluid\">\n        <div class=\"row\">\n            <div class=\"col-2\" id=\"leftmenu\"></div>\n            <div class=\"col-10\" id=\"rightmenu\"></div>\n        </div>\n    </div>\n    <script src=\"https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js\"\n        integrity=\"sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4\"\n        crossorigin=\"anonymous\"></script>\n</body>\n\n<footer>\n    <div class=\"text-center p-2\" style=\"background-color: rgba(0, 0, 0, 0.05);\">\n        Conan <b>{{ version }}</b>\n        <script>\n            document.write(new Date().getFullYear());\n        </script>\n        JFrog LTD. <a href=\"https://conan.io\">https://conan.io</a>\n    </div>\n</footer>\n\n</html>\n\"\"\"\n"
  },
  {
    "path": "conan/cli/formatters/report/__init__.py",
    "content": "from .diff import format_diff_html, format_diff_txt, format_diff_json\n"
  },
  {
    "path": "conan/cli/formatters/report/diff.py",
    "content": "import json\nimport os\nimport base64\n\nfrom jinja2 import Template\n\nfrom conan.api.output import cli_out_write\nfrom conan.cli.formatters.report.diff_html import diff_html\n\n\ndef _generate_json(result):\n    diff_text = result[\"diff\"]\n    src_prefix = result[\"src_prefix\"]\n    dst_prefix = result[\"dst_prefix\"]\n    ret = {}\n    current_filename = None\n    for line in diff_text.splitlines():\n        if line.startswith(\"diff --git \"):\n            src_filename, dst_filename = _get_filenames(line, src_prefix, dst_prefix)\n            current_filename = src_filename\n            ret[current_filename] = [line]\n        else:\n            ret[current_filename].append(line)\n    return ret\n\n\ndef _get_filenames(line, src_prefix, dst_prefix):\n    \"\"\"\n    Extracts the source and destination filenames from a diff line.\n    \"\"\"\n    src_index = line.find(src_prefix)\n    dst_index = line.find(dst_prefix)\n\n    if src_index == -1 or dst_index == -1:\n        return None, None\n\n    src_filename = line[src_index + len(src_prefix) - 1:dst_index - 1].strip()\n    dst_filename = line[dst_index + len(dst_prefix) - 1:].strip()\n\n    return src_filename, dst_filename\n\n\ndef _render_diff(content, template, template_folder, **kwargs):\n    from conan import __version__\n    template = Template(template, autoescape=True)\n\n    def _safe_filename(filename):\n        # Calculate base64 of the filename\n        return base64.b64encode(filename.encode(), altchars=b'-_').decode()\n\n    def _remove_prefixes(line):\n        return line.replace(kwargs[\"src_prefix\"][:-1], \"\").replace(kwargs[\"dst_prefix\"][:-1], \"\")\n\n    def _replace_cache_paths(line):\n        return line.replace(kwargs[\"old_cache_path\"], \"(old)\").replace(kwargs[\"new_cache_path\"], \"(new)\")\n\n    def _replace_paths(line):\n        return _remove_prefixes(_replace_cache_paths(line))\n\n    def _extract_header(diff_lines):\n        # Header ends at the first occurrence of +++ line,\n        # and it can be at most 10 lines long\n        for i, line in enumerate(diff_lines[:10]):\n            if line.startswith(\"+++ \"):\n                return diff_lines[:i + 1]\n        return diff_lines[:10]\n\n    def _parse_header_is_deleted(header_contents):\n        return (\"+++ /dev/null\" in header_contents\n                or any(\"deleted file mode\" in line for line in header_contents))\n\n    def _parse_header_rename_to(header_contents):\n        if not any(\"similarity index\" in line for line in header_contents):\n            return None\n        for line in header_contents:\n            if line.startswith(\"rename to \"):\n                return line[len(\"rename to \"):]\n        return None\n\n    per_folder = {\"folders\": {}, \"files\": {}}\n    for file in content:\n        header = _extract_header(content[file])\n        renamed_to = _parse_header_rename_to(header)\n        replaced_path = _replace_paths(renamed_to or file)\n        replaced_file = replaced_path.replace(\"(old)\", \"\").replace(\"(new)\", \"\").replace(\"\\\\\", \"/\")\n        bits = replaced_file.split(\"/\")[1:]\n        cur = per_folder\n        for folder in bits[:-1]:\n            cur = cur[\"folders\"].setdefault(folder, {\"folders\": {}, \"files\": {}})\n        filename = bits[-1]\n        cur[\"files\"][filename] = {\"filename\": file,  # This is file so renamed use old name\n                                  \"is_new\": \"(new)\" in replaced_path,\n                                  \"is_deleted\": _parse_header_is_deleted(header),\n                                  \"renamed_to\": renamed_to,\n                                  \"relative_path\": replaced_path}\n\n    def flatten_empty_folders(current_node):\n        for folder_data in current_node[\"folders\"].values():\n            flatten_empty_folders(folder_data)\n\n        promoted_folders = {}\n\n        # The list here is important to avoid modifying the dict while iterating\n        for folder_name, folder_data in list(current_node[\"folders\"].items()):\n            if not folder_data[\"files\"]:\n                for sub_folder_name, sub_folder_data in folder_data['folders'].items():\n                    new_key = os.path.join(folder_name, sub_folder_name)\n                    promoted_folders[new_key] = sub_folder_data\n\n                del current_node[\"folders\"][folder_name]\n\n        current_node[\"folders\"].update(promoted_folders)\n\n    flatten_empty_folders(per_folder)\n\n    # Now sort each folder and file recursively\n    def sort_folders_and_files(node):\n        node[\"folders\"] = dict(sorted(node[\"folders\"].items()))\n        node[\"files\"] = dict(sorted(node[\"files\"].items(), key=lambda x: x[0].lower()))\n        for folder_data in node[\"folders\"].values():\n            sort_folders_and_files(folder_data)\n    sort_folders_and_files(per_folder)\n\n    return template.render(content=content,\n                           per_folder=per_folder,\n                           base_template_path=template_folder, version=__version__,\n                           safe_filename=_safe_filename,\n                           replace_paths=_replace_paths,\n                           replace_cache_paths=_replace_cache_paths,\n                           remove_prefixes=_remove_prefixes,\n                           **kwargs)\n\n\ndef format_diff_html(result):\n    conan_api = result[\"conan_api\"]\n\n    template_folder = os.path.join(conan_api.cache_folder, \"templates\")\n    user_template = os.path.join(template_folder, \"diff.html\")\n    template = diff_html\n    if os.path.isfile(user_template):\n        with open(user_template, 'r', encoding=\"utf-8\", newline=\"\") as handle:\n            template = handle.read()\n\n    content = _generate_json(result)\n\n    cli_out_write(_render_diff(content, template, template_folder,\n                               old_reference=result[\"old_export_ref\"],\n                               new_reference=result[\"new_export_ref\"],\n                               old_cache_path=result[\"old_cache_path\"],\n                               new_cache_path=result[\"new_cache_path\"],\n                               src_prefix=result[\"src_prefix\"],\n                               dst_prefix=result[\"dst_prefix\"]))\n\n\ndef format_diff_txt(result):\n    diff_text = result[\"diff\"]\n    cli_out_write(diff_text)\n\n\ndef format_diff_json(result):\n    cli_out_write(json.dumps(_generate_json(result), indent=2))\n"
  },
  {
    "path": "conan/cli/formatters/report/diff_html.py",
    "content": "diff_html = r\"\"\"\n{% macro render_sidebar_folder(folder, folder_info) %}\n    {%- for name, sub_folder_info in folder_info[\"folders\"].items() %}\n        {% set folder_name = folder + \"/\" + name %}\n        <li>\n            <details open class=\"folder\">\n                <summary>{{ name }}</summary>\n                <ul>\n                    {{ render_sidebar_folder(folder_name, sub_folder_info) }}\n                </ul>\n            </details>\n        </li>\n    {%- endfor %}\n    {%- for name, file_info in folder_info[\"files\"].items() %}\n        {% set file_type = \"renamed\" if file_info[\"renamed_to\"] else (\n                           \"deleted\" if file_info[\"is_deleted\"] else (\n                           \"new\" if file_info[\"is_new\"] else \"old\")) %}\n        <li class=\"file file-{{ file_type }}\"\n            data-path=\"{{ file_info[\"relative_path\"] }}\"\n            data-type=\"{{ file_type }}\">\n            <a href=\"#diff_{{- safe_filename(file_info[\"filename\"]) -}}\"\n                onclick=\"setDataIsLinked(event)\" draggable=\"false\"\n                class=\"side-link\"\n                title=\"{{ replace_cache_paths(file_info[\"relative_path\"]) | replace(\"(old)/\", \"\") | replace(\"(new)/\", \"\") }}\">\n                {% if file_info[\"renamed_to\"] %}\n                    {{ file_info[\"renamed_to\"].split(\"/\")[1:][-1] }}\n                {% else %}\n                    {{ name }}\n                {% endif %}\n            </a>\n        </li>\n    {%- endfor %}\n{% endmacro %}\n\n{% macro render_diff_folder(folder_info) %}\n    {%- for name, sub_folder_info in folder_info[\"folders\"].items() %}\n        {{ render_diff_folder(sub_folder_info) }}\n    {%- endfor %}\n    {%- for name, file_info in folder_info[\"files\"].items() %}\n        {% set filename = file_info[\"filename\"] %}\n\n        <div id=\"diff_{{ safe_filename(filename) }}\" data-path=\"{{ filename }}\" class=\"diff-container\">\n            <div class=\"diff-content\">\n                <details open class=\"diff-details\">\n                    <summary class=\"diff-summary\">\n                        <b id=\"diff_{{ safe_filename(filename) }}_filename\" class=\"filename\" data-replaced-paths=\"\">\n                            <span>{{ replace_cache_paths(filename) | replace(\"(old)/\", \"\") | replace(\"(new)/\", \"\") }}</span>\n                            {% if file_info[\"renamed_to\"] %}\n                                &nbsp;&#x2192&nbsp;\n                                <span>{{ replace_cache_paths(file_info[\"renamed_to\"]) | replace(\"(old)/\", \"\") | replace(\"(new)/\", \"\") }}</span>\n                            {% endif %}\n                        </b>\n                        <div class=\"changes-count-container\"></div>\n                    </summary>\n                    <div class=\"diff-lines\">\n                    </div>\n                </details>\n            </div>\n        </div>\n    {%- endfor %}\n{% endmacro %}\n<html lang=\"en\">\n    <head>\n        <meta charset=\"utf-8\">\n        <title>Diff report for {{ old_reference }} - {{ new_reference }}</title>\n        <style>\n            /* --- Colors --- */\n            :root {\n                --body-bgColor: #f8f8f8;\n                --sidebar-bgColor: #f4f4f466;\n                --sidebar-borderColor: #ccc;\n                --sidebar-contents-bgColor: #f4f4f4;\n                --content-bgColor: #f8f8f8;\n                --search-area-borderColor: #ccc;\n                --search-field-borderColor: #ccc;\n                --file-list-borderColor: #ddd;\n                --folder-summary-hover-bgColor: #e0e0e033;\n                --folder-ul-hover-borderColor: #00000066;\n                --sidebar-li-a-hover-bgColor: #e0e0e0;\n                --sidebar-button-hover-bgColor: var(--sidebar-li-a-hover-bgColor);\n                --sidebar-link-color: black;\n                --sidebar-link-hover-color: var(--sidebar-link-color);\n                --sidebar-link-visited-color: var(--sidebar-link-color);\n                --sidebar-file-new-color: green;\n                --sidebar-file-old-color: gray;\n                --sidebar-file-deleted-color: red;\n                --diff-content-borderColor: black;\n                --diff-content-bgColor: white;\n                --diff-container-linked-borderColor: #0078d7;\n                --diff-summary-borderColor: #ccc;\n                --diff-summary-bgColor: #f8f8f8;\n                --diff-summary-hover-bgColor: #f0f0f0;\n                --new-lines-count-color: green;\n                --old-lines-count-color: black;\n                --context-line-color: #888;\n                --context-chunk-header-bgColor: #cef8ff;\n                --context-chunk-header-color: var(--context-line-color);\n                --added-line-bgColor: #cbfcd9;\n                --added-line-color: black;\n                --deleted-line-bgColor: #ffebe9;\n                --deleted-line-color: black;\n                --line-number-added-bgColor: #76ffbb;\n                --line-number-deleted-bgColor: #fdb9c1;\n            }\n\n            /* --- Global Styles --- */\n\n            body {\n                font-family: monospace;\n                margin: 0px;\n                background-color: var(--body-bgColor);\n            }\n\n            /* --- Main Layout --- */\n\n            .container {\n                display: flex;\n                height: 100%;\n                overflow: scroll;\n            }\n\n            .sidebar {\n                width: 17%;\n                min-width: 10%;\n                max-width: 33%;\n                padding: 10px;\n                overflow: scroll;\n                background: var(--sidebar-bgColor);\n                border-right: 1px solid var(--sidebar-borderColor);\n                resize: horizontal;\n                position: sticky;\n                top: 0;\n            }\n\n            .content {\n                padding: 20px;\n                background: var(--content-bgColor);\n                width: 100%;\n            }\n\n            /* --- Sidebar & File Tree --- */\n\n            #sidebar-contents {\n                background: var(--sidebar-contents-bgColor);\n                border-radius: 7px;\n                overflow-y: hidden;\n                padding-top: 5px;\n            }\n\n            .sidebar-reveal {\n                display: none;\n                position: sticky;\n                top: 10px;\n            }\n\n            .search-area {\n                border-bottom: 1px solid var(--search-area-borderColor);\n            }\n\n            .search-header {\n                display: flex;\n                justify-content: space-between;\n            }\n\n            .search-field {\n                border: 1px solid var(--search-field-borderColor);\n                border-radius: 5px;\n                padding: 5px;\n                margin: 5px;\n                width: 80%;\n            }\n\n            .file-tree-controls {\n                border-bottom: 1px solid var(--search-area-borderColor);\n                padding: 5px;\n                display: flex;\n                justify-content: space-between;\n                align-items: center;\n            }\n\n            .file-tree-controls .folder-collapse button {\n                display: inline-block;\n                line-height: 0.7;\n            }\n\n            .file-tree-controls button,\n            .sidebar-reveal button,\n            .search-header button {\n                cursor: pointer;\n                border: 0px solid var(--search-field-borderColor);\n                border-radius: 5px;\n                background: none;\n                padding: 5px;\n                min-width: 3ch;\n            }\n\n            .file-tree-controls button:hover,\n            .sidebar-reveal button:hover,\n            .search-header button:hover {\n                background-color: var(--sidebar-li-a-hover-bgColor);\n            }\n\n            .file-tree-more {\n                display: none;\n                padding: 5px;\n                border-bottom: 1px solid var(--search-area-borderColor);\n            }\n\n            .file-tree-more-option {\n                display: block;\n            }\n\n            .file-list {\n                padding-left: 10px;\n                width: 100%;\n                overflow-x: clip;\n            }\n\n            .file-list ul li {\n                width: 100%;\n            }\n\n            .file-list li ul {\n                border-left: 1px solid var(--file-list-borderColor);\n                margin-left: 3px;\n            }\n\n            li ul {\n                padding-left: 1ch;\n            }\n\n            details.folder {\n                text-wrap: nowrap;\n            }\n\n            .folder > summary {\n                cursor: pointer;\n                list-style: none;\n            }\n\n            .folder > summary:hover {\n                background-color: var(--folder-summary-hover-bgColor);\n            }\n\n            .folder:not(:open) > summary:before {\n                content: \"\\1F4C1\";\n                display: inline-block;\n                margin-right: 3px;\n            }\n\n            .folder:open > summary:before {\n                content: \"\\1F4C2\";\n                display: inline-block;\n                margin-right: 3px;\n            }\n\n            details.folder ul:hover {\n                border-left: 1px solid var(--folder-ul-hover-borderColor);\n            }\n\n            .sidebar li {\n                line-height: 1.8;\n                list-style: none;\n                list-style-position: inside;\n                user-select: none;\n            }\n\n            .sidebar li a {\n                text-decoration: none;\n                padding: 5px;\n                color: var(--sidebar-link-color);\n            }\n\n            .sidebar li a:hover {\n                text-decoration: none;\n                border-radius: 5px;\n                background-color: var(--sidebar-li-a-hover-bgColor);\n                padding: 5px;\n                color: var(--sidebar-link-hover-color);\n            }\n\n            .sidebar li a:visited {\n                color: var(--sidebar-link-visited-color);\n            }\n\n            .side-link {\n                text-wrap: nowrap;\n            }\n\n            /* File Status Indicators */\n            .sidebar li.file-new,\n            .sidebar li.file-old,\n            .sidebar li.file-deleted,\n            .sidebar li.file-renamed {\n                list-style: none;\n                padding-left: 0;\n            }\n\n            .sidebar li.file-new:before {\n                content: \"+\";\n                color: var(--sidebar-file-new-color);\n                font-weight: bold;\n            }\n\n            .sidebar li.file-old:before {\n                content: \"\\00B1\";\n                color: var(--sidebar-file-old-color);\n            }\n\n            .sidebar li.file-deleted:before {\n                content: \"-\";\n                color: var(--sidebar-file-deleted-color);\n                font-weight: bold;\n            }\n\n            .sidebar li.file-renamed:before {\n                content: \"\\2192\";\n                color: var(--sidebar-file-old-color);\n                font-weight: bold;\n            }\n\n            /* --- Diff View Components --- */\n\n            .diff-container {\n                scroll-margin-top: 10px;\n            }\n\n            .diff-content {\n                padding-bottom: 7px;\n                border: 1px solid var(--diff-content-borderColor);\n                border-radius: 7px;\n                margin-bottom: 10px;\n                background-color: var(--diff-content-bgColor);\n            }\n\n            .diff-container[data-is-linked=\"true\"] .diff-content {\n                border: 2px solid var(--diff-container-linked-borderColor);\n            }\n\n            details.diff-details summary.diff-summary {\n                cursor: pointer;\n                display: flex;\n                justify-content: space-between;\n                align-items: center;\n                border-bottom: 1px solid var(--diff-summary-borderColor);\n                padding: 5px 0px;\n                position: sticky;\n                top: 0;\n                background-color: var(--diff-summary-bgColor);\n                border-radius: 7px 7px 0px 0px;\n            }\n\n            details.diff-details summary.diff-summary:hover {\n                background-color: var(--diff-summary-hover-bgColor);\n            }\n\n            details:open .diff-summary .filename:before {\n                content: \"\\25BC\";\n                display: inline-block;\n            }\n\n            details:not(:open) .diff-summary .filename:before {\n                content: \"\\25B6\";\n                display: inline-block;\n            }\n\n            .diff-header {\n                padding: 0px 5px 5px 5px;\n            }\n\n            .filename {\n                font-size: 1.2em;\n                padding-left: 10px;\n            }\n\n            .changes-count-container {\n                font-size: 0.9em;\n                padding-right: 10px;\n            }\n\n            .new-lines-count {\n                color: var(--new-lines-count-color);\n                font-weight: bold;\n            }\n\n            .old-lines-count {\n                color: var(--old-lines-count-color);\n                font-weight: bold;\n            }\n\n            /* --- Diff Line Styles --- */\n\n            .content span {\n                white-space: pre-wrap;\n            }\n\n            .context-chunk-header {\n                list-style: none;\n                background-color: var(--context-chunk-header-bgColor);\n                color: var(--context-chunk-header-color);\n                line-height: 2;\n                cursor: pointer;\n            }\n\n            details:open .context-chunk-header .line-number:before {\n                content: \"\\25BC\";\n                display: inline-block;\n            }\n\n            details:not(:open) .context-chunk-header .line-number:before {\n                content: \"\\25B6\";\n                display: inline-block;\n            }\n\n            .diff-lines {\n                line-break: anywhere;\n            }\n\n            .line-number {\n                width: 4ch;\n                min-width: 4ch;\n                display: inline-block;\n                text-align: center;\n                user-select: none;\n            }\n\n            .context-line {\n                color: var(--context-line-color);\n            }\n\n            .add {\n                background-color: var(--added-line-bgColor);\n                color: var(--added-line-color);\n            }\n\n            .del {\n                background-color: var(--deleted-line-bgColor);\n                color: var(--deleted-line-color);\n            }\n\n            .add,\n            .del,\n            .context-line {\n                height: 100%;\n            }\n\n            .diff-line {\n                display: flex;\n                box-sizing: border-box;\n                line-height: 1.5em;\n            }\n\n            .line-number.add {\n                background-color: var(--line-number-added-bgColor);\n            }\n\n            .line-number.del {\n                background-color: var(--line-number-deleted-bgColor);\n            }\n\n            .line-number.add,\n            .line-number.del {\n                height: auto;\n            }\n\n            .diff-symbol {\n                display: inline-block;\n                width: 1ch;\n                user-select: none;\n            }\n\n            /* --- Utility & Page States --- */\n\n            #empty_result {\n                justify-content: center;\n                align-items: center;\n                color: black;\n                font-weight: bold;\n                font-size: 4em;\n                text-align: center;\n            }\n        </style>\n        <script>\n\n            const data = {{ content | tojson | safe }};\n\n            const oldPattern = \"{{ src_prefix[:-1] }}{{ old_cache_path }}\";\n            const newPattern = \"{{ dst_prefix[:-1] }}{{ new_cache_path }}\";\n\n            function extractLineNumbers(hunkHeader) {\n                const regex = /@@ -(\\d+),\\d+ \\+(\\d+),\\d+ @@/;\n                const match = hunkHeader.match(regex);\n                if (!match) {\n                    return [0, 0];\n                }\n                return [parseInt(match[1]), parseInt(match[2])];\n            }\n\n\n            function makeDiffLines(lines) {\n                const element = document.createElement(\"div\");\n                let seen_header = false;\n                let new_line_index = 0;\n                let old_line_index = 0;\n                let new_line_count = 0;\n                let old_line_count = 0;\n                const headerDiv = document.createElement(\"div\");\n                let currentDetails = null;\n                for (let i = 0; i < lines.length; i++) {\n                    const line = lines[i];\n                    let spanLine = document.createElement(\"span\");\n                    const lineDiv = document.createElement(\"div\");\n                    lineDiv.className = \"diff-line\";\n                    let shouldAddLine = true;\n                    if (line.startsWith(\"+++\")) {\n                        seen_header = true;\n                        spanLine.className = \"add\";\n                        spanLine.textContent = line.replace(newPattern, \"(new)\");\n                        headerDiv.appendChild(spanLine);\n                        continue;\n                    } else if (line.startsWith(\"---\")) {\n                        spanLine.className = \"del\";\n                        spanLine.textContent = line.replace(oldPattern, \"(old)\");\n                        headerDiv.appendChild(spanLine);\n                        continue;\n                    } else if (line.startsWith(\"@@\")) {\n                        currentDetails = document.createElement(\"details\");\n                        currentDetails.open = true;\n\n                        const summary = document.createElement(\"summary\");\n                        summary.className = \"context-chunk-header\";\n                        const summaryArrow = document.createElement(\"span\");\n                        summaryArrow.className = \"line-number\";\n                        const summaryText = document.createElement(\"span\");\n                        summaryText.textContent = line;\n\n                        summary.appendChild(summaryArrow);\n                        summary.appendChild(summaryText);\n\n                        currentDetails.appendChild(summary);\n                        element.appendChild(currentDetails);\n                        shouldAddLine = false;\n\n                        const lineNumbers = extractLineNumbers(line);\n                        old_line_index = lineNumbers[0];\n                        new_line_index = lineNumbers[1];\n                    } else if (line.startsWith(\"+\")) {\n                        const spanSymbol = document.createElement(\"span\");\n                        spanSymbol.textContent = \"+\";\n                        spanSymbol.className = \"diff-symbol\";\n                        spanLine.className = \"add\";\n                        spanLine.textContent = line.substring(1);\n                        spanLine.prepend(spanSymbol);\n\n                        const lineNumberSpan = document.createElement(\"span\");\n                        lineNumberSpan.className = \"line-number add\";\n                        lineNumberSpan.textContent = new_line_index;\n                        lineDiv.appendChild(lineNumberSpan);\n\n                        new_line_index += 1;\n                        new_line_count += 1;\n                    } else if (line.startsWith(\"-\")) {\n                        const spanSymbol = document.createElement(\"span\");\n                        spanSymbol.textContent = \"-\";\n                        spanSymbol.className = \"diff-symbol\";\n                        spanLine.className = \"del\";\n                        spanLine.textContent = line.substring(1);\n                        spanLine.prepend(spanSymbol);\n\n                        const lineNumberSpan = document.createElement(\"span\");\n                        lineNumberSpan.className = \"line-number del\";\n                        lineNumberSpan.textContent = old_line_index;\n                        lineDiv.appendChild(lineNumberSpan);\n\n                        old_line_index += 1;\n                        old_line_count += 1;\n                    } else {\n                        spanLine.className = \"context-line\";\n                        if (!seen_header) {\n                            spanLine.textContent = line.replace(oldPattern, \"(old)\").replace(newPattern, \"(new)\");\n                            headerDiv.appendChild(spanLine);\n                            headerDiv.appendChild(document.createElement(\"br\"));\n                            continue;\n                        } else {\n                            const spanSymbol = document.createElement(\"span\");\n                            spanSymbol.className = \"diff-symbol\";\n                            spanLine.textContent = line;\n                            spanLine.prepend(spanSymbol);\n                        }\n\n                        const lineNumberSpan = document.createElement(\"span\");\n                        lineNumberSpan.className = \"line-number context-line\";\n                        lineNumberSpan.textContent = new_line_index;\n                        lineDiv.appendChild(lineNumberSpan);\n\n                        new_line_index += 1;\n                        old_line_index += 1;\n                    }\n                    if (shouldAddLine) {\n                        lineDiv.appendChild(spanLine);\n\n                        currentDetails.appendChild(lineDiv);\n                        //currentDetails.appendChild(document.createElement(\"br\"));\n                    }\n                }\n                if (!seen_header) {\n                    element.appendChild(headerDiv);\n                }\n                return [element, new_line_count, old_line_count];\n            }\n\n            function createChangesCountElement(new_count, old_count) {\n                const changes = document.createElement(\"span\");\n                changes.className = \"changes-count\";\n                changes.innerHTML = `<span class=\"new-lines-count\">+${new_count}</span> <span class=\"old-lines-count\">-${old_count}</span>`;\n                return changes;\n            }\n\n\n            function intersectionCallback(entries) {\n              entries.forEach((entry) => {\n                if (entry.isIntersecting) {\n                    let elem = entry.target;\n                    const path = elem.dataset.path;\n                    const [lines, new_count, old_count] = makeDiffLines(data[path]);\n                    const diffLines = elem.querySelector(\".diff-lines\")\n\n                    // If we're scrolling up, new lines are added to the top, so we need to\n                    // preserve the scroll position relative to the bottom of the new content\n                    const prevRect = elem.getBoundingClientRect();\n\n\n                    diffLines.appendChild(lines);\n\n                    if (new_count !== 0 || old_count !== 0) {\n                        elem.querySelector(\".changes-count-container\").appendChild(createChangesCountElement(new_count, old_count));\n                    }\n\n                    if (elem.getAttribute(\"data-is-linked\") === \"true\") {\n                        // We need to scroll to the element again now that its height has changed\n                        elem.scrollIntoView({block: \"start\", inline: \"nearest\", behavior: \"instant\"});\n                    } else {\n                        if (prevRect.top < 0) {\n                            const prevBottom = prevRect.bottom;\n                            const newBottom = elem.getBoundingClientRect().bottom;\n                            const container = document.querySelector('.container');\n                            container.scroll(0, container.scrollTop + (newBottom - prevBottom));\n                        }\n                    }\n\n                    observer.unobserve(elem);\n                }\n              });\n            }\n\n            const options = {\n                root: document.querySelector('.content'),\n                rootMargin: \"0px\",\n                scrollMargin: \"0px\",\n                threshold: 0.05,\n            };\n\n            const observer = new IntersectionObserver(intersectionCallback, options);\n\n            document.addEventListener(\"DOMContentLoaded\", (e) => {\n                setDataIsLinked(null);\n                document.querySelectorAll('.diff-container').forEach((section) => {\n                    observer.observe(section);\n                });\n            });\n\n            function debounce(func, delay) {\n                let timeout;\n                return function(...args) {\n                    const context = this;\n                    clearTimeout(timeout);\n                    timeout = setTimeout(() => {\n                        func.apply(context, args);\n                    }, delay);\n                };\n            }\n            let includeSearchQuery = \"\";\n            let excludeSearchQuery = \"\";\n\n            async function onSearchInput(event) {\n                const sidebar = document.querySelectorAll(\".sidebar li\");\n                const fileList = document.querySelector(\".file-list\");\n                const content = document.querySelectorAll(\".content .diff-container .diff-content\");\n                const searchingIcon = document.getElementById(\"searching_icon\");\n\n                searchingIcon.style.display = \"inline-block\";\n\n                let emptySearch = true;\n                let includedFiles = 0;\n\n                const typeVisibility = {\n                    \"renamed\": document.getElementById(\"show-moved-files\").checked,\n                    \"deleted\": document.getElementById(\"show-deleted-files\").checked,\n                    \"new\": document.getElementById(\"show-new-files\").checked,\n                    \"old\": document.getElementById(\"show-old-files\").checked,\n                };\n\n                sidebar.forEach(async function(item) {\n                    if (item.dataset.path === undefined) {\n                        // A folder, those are handled later\n                        return;\n                    }\n                    const text = item.dataset.path.toLowerCase();\n                    const shouldInclude = includeSearchQuery === \"\" || text.includes(includeSearchQuery);\n                    let shouldExclude = excludeSearchQuery !== \"\" && text.includes(excludeSearchQuery);\n                    const associatedId = item.querySelector(\"a\").getAttribute(\"href\").substring(1)\n                    const contentItem = document.getElementById(associatedId);\n\n                    const fileType = item.dataset.type;\n                    const isTypeVisible = typeVisibility[fileType] !== false;\n\n                    shouldExclude = shouldExclude || !isTypeVisible;\n\n                    if (shouldInclude) {\n                        if (shouldExclude) {\n                            item.style.display = \"none\";\n                            contentItem.style.display = \"none\";\n                        } else {\n                            includedFiles += 1;\n                            item.style.display = \"list-item\";\n                            contentItem.style.display = \"block\";\n                            emptySearch = false;\n                        }\n                    } else {\n                        item.style.display = \"none\";\n                        contentItem.style.display = \"none\";\n                    }\n\n                });\n\n                searchingIcon.style.display = \"none\";\n                const emptySearchTag = document.getElementById(\"empty_search\");\n                const emptyResultTag = document.getElementById(\"empty_result\");\n                if (emptySearch) {\n                    emptySearchTag.style.display = \"block\";\n                    emptyResultTag.style.display = \"block\";\n                    fileList.style.display = \"none\";\n                } else {\n                    emptySearchTag.style.display = \"none\";\n                    emptyResultTag.style.display = \"none\";\n                    fileList.style.display = \"block\";\n                }\n\n                const fileCountTag = document.getElementById(\"file-count\");\n                fileCountTag.textContent = includedFiles;\n\n                const allDetails = document.querySelectorAll(\".sidebar details.folder\");\n                allDetails.forEach(function(details) {\n                    details.style.display = \"none\";\n                    details.querySelectorAll(\"li.file\").forEach(function(li) {\n                        if (li.style.display !== \"none\") {\n                            details.style.display = \"block\";\n                            return;\n                        }\n                    });\n                });\n\n            }\n\n            const debouncedOnSearchInput = debounce(onSearchInput, 300);\n\n            async function onExcludeSearchInput(event) {\n                excludeSearchQuery = event.currentTarget.value.toLowerCase();\n                debouncedOnSearchInput(event);\n            }\n\n            async function onIncludeSearchInput(event) {\n                includeSearchQuery = event.currentTarget.value.toLowerCase();\n                debouncedOnSearchInput(event);\n            }\n\n            function setDataIsLinked(event) {\n                const hash = event ? event.currentTarget.getAttribute(\"href\").substring(1) : window.location.hash.substring(1);\n                document.querySelectorAll('.diff-container').forEach((section) => {\n                    if (section.id === hash) {\n                        section.setAttribute(\"data-is-linked\", \"true\");\n                        if (!event) {\n                            // Scroll to the linked element on page load\n                            section.scrollIntoView({block: \"start\", inline: \"nearest\", behavior: \"instant\"});\n                        }\n                    } else {\n                        section.setAttribute(\"data-is-linked\", \"false\");\n                    }\n                });\n            }\n\n            function toggleFolders(open) {\n                if (open) {\n                    const toOpen = document.querySelectorAll('details.folder:open > ul > li > details.folder:not(:open)');\n                    if (toOpen.length === 0) {\n                        // We might need to open the root folders\n                        document.querySelectorAll('.file-list > li > details.folder:not(:open)').forEach(d => d.open = true);\n                    } else {\n                        toOpen.forEach(d => d.open = true);\n                    }\n                } else {\n                    document.querySelectorAll('details.folder:open').forEach(d => d.open = false);\n                }\n            }\n\n            function toggleSidebar(show) {\n                const sidebar = document.querySelector('.sidebar');\n                const sidebarReveal = document.querySelector('.sidebar-reveal');\n                const content = document.querySelector('.content');\n                if (show) {\n                    sidebar.style.display = 'block';\n                    sidebarReveal.style.display = 'none';\n                    content.style.padding = '20px';\n                } else {\n                    sidebar.style.display = 'none';\n                    sidebarReveal.style.display = 'block';\n                    content.style.padding = '20px 20px 20px 5px';\n                }\n            }\n\n            function toggleMoreFileTree() {\n                const moreOptions = document.querySelector('.file-tree-more');\n                console.log(moreOptions.style.display);\n                const show = moreOptions.style.display !== 'block';\n                if (show) {\n                    moreOptions.style.display = 'block';\n                } else {\n                    moreOptions.style.display = 'none';\n                }\n            }\n        </script>\n    </head>\n    <body>\n        <div class='container'>\n            <div class='sidebar'>\n                <div id=\"sidebar-contents\">\n                    <div class=\"search-area\">\n                        <div class=\"search-header\">\n                            <div>\n                                <input type=\"search\" class=\"search-field\" id=\"search-include\" placeholder=\"Include search...\" oninput=\"onIncludeSearchInput(event)\" />\n                                <input type=\"search\" class=\"search-field\" id=\"search-exclude\" placeholder=\"Exclude search...\" oninput=\"onExcludeSearchInput(event)\" />\n                                <span id=\"searching_icon\" style=\"display:none\">...</span>\n                            </div>\n\n                            <button onclick=\"toggleSidebar(false)\" title=\"Hide\">\n                                &#x2190;\n                            </button>\n                        </div>\n                        <p>Showing <b id=\"file-count\">{{ content|length }}</b> out of <b>{{ content|length }}</b> files</p>\n                    </div>\n                    <div class=\"file-tree\">\n                        <div class=\"file-tree-controls\">\n                            <div class=\"folder-collapse\">\n                                <button onclick=\"toggleFolders(true)\" title=\"Expand current level\">\n                                    &#x02C4;\n                                    <br/>\n                                    &#x02C5;\n                                </button>\n                                <button onclick=\"toggleFolders(false)\" title=\"Collapse all\">\n                                    &#x02C5;\n                                    <br/>\n                                    &#x02C4\n                                </button>\n                            </div>\n                            <button onclick=\"toggleMoreFileTree()\" title=\"Show more options\"\n                                class=\"file-tree-reveal-more\">\n                                    &#x22EE;\n                            </button>\n                        </div>\n                        <div class=\"file-tree-more\">\n                            <h4>Show...</h4>\n                            <div class=\"file-tree-more-option\">\n                                <input type=\"checkbox\" id=\"show-old-files\" checked\n                                    onclick=\"debouncedOnSearchInput(event)\"/>\n                                <label for=\"show-old-files\">Old files</label>\n                            </div>\n\n                            <div class=\"file-tree-more-option\">\n                                <input type=\"checkbox\" id=\"show-new-files\" checked\n                                    onclick=\"debouncedOnSearchInput(event)\"/>\n                                <label for=\"show-new-files\">New files</label>\n                            </div>\n\n                            <div class=\"file-tree-more-option\">\n                                <input type=\"checkbox\" id=\"show-deleted-files\" checked\n                                    onclick=\"debouncedOnSearchInput(event)\"/>\n                                <label for=\"show-deleted-files\">Deleted files</label>\n                            </div>\n\n                            <div class=\"file-tree-more-option\">\n                                <input type=\"checkbox\" id=\"show-moved-files\" checked\n                                    onclick=\"debouncedOnSearchInput(event)\"/>\n                                <label for=\"show-moved-files\">Moved files</label>\n                            </div>\n                        </div>\n                        <ul class=\"file-list\">\n                            {{ render_sidebar_folder(\"\", per_folder) }}\n                        </ul>\n                    </div>\n                </div>\n                <span id=\"empty_search\" style=\"display:none\">No results found</span>\n            </div>\n            <div class='sidebar-reveal'>\n                <button onclick=\"toggleSidebar(true)\" title=\"Show\">\n                    &#x2192;\n                </button>\n            </div>\n            <div class='content'>\n                <div class=\"diff-header\">\n                    <h2>Diff Report Between <b class=\"del\">{{ old_reference.repr_notime() }}</b> And <b class=\"add\">{{ new_reference.repr_notime() }}</b></h2>\n                </div>\n                <span id=\"empty_result\" style=\"display:none\">No matches</span>\n                {{ render_diff_folder(per_folder) }}\n            </div>\n        </div>\n    </body>\n</html>\n\"\"\"\n"
  },
  {
    "path": "conan/cli/printers/__init__.py",
    "content": "from conan.api.output import ConanOutput, Color\n\n\ndef print_profiles(profile_host, profile_build):\n    out = ConanOutput()\n    out.title(\"Input profiles\")\n    out.info(\"Profile host:\", fg=Color.BRIGHT_CYAN)\n    out.info(profile_host.dumps())\n    out.info(\"Profile build:\", fg=Color.BRIGHT_CYAN)\n    out.info(profile_build.dumps())\n"
  },
  {
    "path": "conan/cli/printers/graph.py",
    "content": "from conan.api.output import ConanOutput, Color, LEVEL_VERBOSE, LEVEL_DEBUG\n\n\ndef print_graph_basic(graph):\n    # I am excluding the \"download\"-\"cache\" or remote information, that is not\n    # the definition of the graph, but some history how it was computed\n    # maybe we want to summarize that info after the \"GraphBuilder\" ends?\n    # TODO: Should all of this be printed from a json representation of the graph? (the same json\n    #   that would be in the json_formatter for the graph?)\n    output = ConanOutput()\n    requires = {}\n    build_requires = {}\n    test_requires = {}\n    python_requires = {}\n    deprecated = {}\n    for node in graph.nodes:\n        if hasattr(node.conanfile, \"python_requires\"):\n            for _, r in node.conanfile.python_requires.items():\n                python_requires[r.ref] = r.recipe, r.remote\n        if node.recipe in (\"Consumer\", \"Cli\"):\n            continue\n        if node.context == \"build\":\n            build_requires[node.ref] = node.recipe, node.remote\n        else:\n            if node.test:\n                test_requires[node.ref] = node.recipe, node.remote\n            else:\n                requires[node.ref] = node.recipe, node.remote\n        if node.conanfile.deprecated:\n            deprecated[node.ref] = node.conanfile.deprecated\n\n    output.info(\"Graph root\", Color.BRIGHT_YELLOW)\n    path = \": {}\".format(graph.root.path) if graph.root.path else \"\"\n    output.info(\"    {}{}\".format(graph.root, path), Color.BRIGHT_CYAN)\n\n    def _format_requires(title, reqs_to_print):\n        if not reqs_to_print:\n            return\n        output.info(title, Color.BRIGHT_YELLOW)\n        for ref_, (recipe, remote) in sorted(reqs_to_print.items()):\n            if remote is not None:\n                recipe = \"{} ({})\".format(recipe, remote.name)\n            output.info(\"    {} - {}\".format(ref_.repr_notime(), recipe), Color.BRIGHT_CYAN)\n\n    _format_requires(\"Requirements\", requires)\n    _format_requires(\"Test requirements\", test_requires)\n    _format_requires(\"Build requirements\", build_requires)\n    _format_requires(\"Python requires\", python_requires)\n\n    def _format_resolved(title, reqs_to_print):\n        if not reqs_to_print:\n            return\n        output.info(title, Color.BRIGHT_YELLOW)\n        for k_, v_ in sorted(reqs_to_print.items()):\n            output.info(\"    {}: {}\".format(k_, v_), Color.BRIGHT_CYAN)\n\n    if graph.replaced_requires:\n        output.info(\"Replaced requires\", Color.BRIGHT_YELLOW)\n        for k, v in graph.replaced_requires.items():\n            output.info(\"    {}: {}\".format(k, v), Color.BRIGHT_CYAN)\n\n    _format_resolved(\"Resolved alias\", graph.aliased)\n    if graph.aliased:\n        output.warning(\"'alias' is a Conan 1.X legacy, unsupported and undocumented feature, \"\n                       \"completely discouraged. \"\n                       \"It might be removed in future Conan versions\", warn_tag=\"deprecated\")\n        output.warning(\"Consider using version-ranges instead.\")\n    _format_resolved(\"Resolved version ranges\", graph.resolved_ranges)\n    for req in graph.resolved_ranges:\n        if str(req.version) == \"[]\":\n            output.warning(\"Empty version range usage is discouraged. Use [*] instead\",\n                           warn_tag=\"deprecated\")\n            break\n\n    overrides = graph.overrides()\n    if overrides:\n        output.info(\"Overrides\", Color.BRIGHT_YELLOW)\n        for req, override_info in overrides.serialize().items():\n            output.info(\"    {}: {}\".format(req, override_info), Color.BRIGHT_CYAN)\n\n    if deprecated:\n        output.info(\"Deprecated\", Color.BRIGHT_YELLOW)\n        for d, reason in deprecated.items():\n            reason = f\": {reason}\" if reason else \"\"\n            output.info(\"    {}{}\".format(d, reason), Color.BRIGHT_CYAN)\n\n    if graph.options_conflicts:\n        output.info(\"Options conflicts\", Color.BRIGHT_YELLOW)\n        for ref, ref_conflicts in graph.options_conflicts.items():\n            for option, conflict_info in ref_conflicts.items():\n                prev_value = conflict_info['value']\n                output.info(f\"    {ref}:{option}={prev_value} (current value)\", Color.BRIGHT_CYAN)\n                for src_ref, conflict_value in conflict_info[\"conflicts\"]:\n                    output.info(f\"        {src_ref}->{option}={conflict_value}\", Color.BRIGHT_CYAN)\n        output.info(\"    It is recommended to define options values in profiles, not in recipes\",\n                    Color.BRIGHT_CYAN)\n        output.warning(\"There are options conflicts in the dependency graph\", warn_tag=\"risk\")\n\n    if deprecated:\n        output.warning(\"There are deprecated packages in the graph\", warn_tag=\"risk\")\n\n    if graph.visibility_conflicts:\n        msg = [\"Packages required both with visible=True and visible=False\"]\n        for ref, consumers in graph.visibility_conflicts.items():\n            msg.append(f\"    {ref}: Required by {', '.join(str(c) for c in consumers)}\")\n        output.warning(\"\\n\".join(msg), warn_tag=\"risk\")\n\n\ndef print_graph_packages(graph):\n    # I am excluding the \"download\"-\"cache\" or remote information, that is not\n    # the definition of the graph, but some history how it was computed\n    # maybe we want to summarize that info after the \"GraphBuilder\" ends?\n    output = ConanOutput()\n    requires = {}\n    build_requires = {}\n    test_requires = {}\n    skipped_requires = []\n    tab = \"    \"\n    for node in graph.nodes:\n        if node.recipe in (\"Consumer\", \"Cli\"):\n            continue\n        node_info = node.conanfile.info\n        if node.context == \"build\":\n            existing = build_requires.setdefault(node.pref,\n                                                 [node.binary, node.binary_remote, node_info])\n        else:\n            if node.test:\n                existing = test_requires.setdefault(node.pref,\n                                                    [node.binary, node.binary_remote, node_info])\n            else:\n                existing = requires.setdefault(node.pref,\n                                               [node.binary, node.binary_remote, node_info])\n        # TO avoid showing as \"skip\" something that is used in other node of the graph\n        if existing[0] == \"Skip\":\n            existing[0] = node.binary\n\n    def _format_requires(title, reqs_to_print):\n        if not reqs_to_print:\n            return\n        output.info(title, Color.BRIGHT_YELLOW)\n        for pref, (status, remote, info) in sorted(reqs_to_print.items(), key=repr):\n            name = pref.repr_notime() if status != \"Platform\" else str(pref.ref)\n            msg = f\"{tab}{name} - \"\n            if status == \"Skip\":\n                skipped_requires.append(str(pref.ref))\n                output.verbose(f\"{msg}{status}\", Color.BRIGHT_CYAN)\n            elif status == \"Missing\" or status == \"Invalid\":\n                output.write(msg, Color.BRIGHT_CYAN)\n                output.writeln(status, Color.BRIGHT_RED)\n            elif status == \"Build\":\n                output.write(msg, Color.BRIGHT_CYAN)\n                output.writeln(status, Color.BRIGHT_YELLOW)\n            else:\n                # Support python36\n                msg += status\n                if remote:\n                    msg += f\" ({remote.name})\"\n                output.info(msg, Color.BRIGHT_CYAN)\n            if output.level_allowed(LEVEL_DEBUG):\n                compact_dumps = info.summarize_compact()\n                for line in compact_dumps:\n                    output.debug(f\"{tab}{tab}{line}\", Color.BRIGHT_GREEN)\n\n    _format_requires(\"Requirements\", requires)\n    _format_requires(\"Test requirements\", test_requires)\n    _format_requires(\"Build requirements\", build_requires)\n\n    if skipped_requires and not output.level_allowed(LEVEL_VERBOSE):\n        output.info(\"Skipped binaries\", Color.BRIGHT_YELLOW)\n        output.info(f\"{tab}{', '.join(skipped_requires)}\", Color.BRIGHT_CYAN)\n"
  },
  {
    "path": "conan/cps/__init__.py",
    "content": "from conan.cps.cps import CPS\n"
  },
  {
    "path": "conan/cps/cps.py",
    "content": "import json\nimport os\nfrom enum import Enum\n\nfrom conan.internal.model.cpp_info import CppInfo\nfrom conan.internal.util.files import save, load\n\n\nclass CPSComponentType(Enum):\n    DYLIB = \"dylib\"\n    ARCHIVE = \"archive\"\n    INTERFACE = \"interface\"\n    EXE = \"executable\"\n    JAR = \"jar\"\n    UNKNOWN = \"unknown\"\n\n    def __str__(self):\n        return self.value\n\n    def __eq__(self, other):\n        # This is useful for comparing with string type at user code, like ``type == \"xxx\"``\n        return super().__eq__(CPSComponentType(other))\n\n    @staticmethod\n    def from_conan(pkg_type):\n        _package_type_map = {\n            \"shared-library\": \"dylib\",\n            \"static-library\": \"archive\",\n            \"header-library\": \"interface\",\n            \"application\": \"executable\"\n        }\n        return CPSComponentType(_package_type_map.get(str(pkg_type), \"unknown\"))\n\n\nclass CPSComponent:\n    def __init__(self, component_type=None):\n        self.includes = []\n        self.type = component_type or \"unknown\"\n        self.definitions = {}\n        self.requires = []\n        self.link_requires = []\n        self.location = None\n        self.link_location = None\n        self.link_languages = []\n        self.link_libraries = []  # system libraries\n\n    def serialize(self):\n        component = {\"type\": str(self.type)}\n        if self.requires:\n            component[\"requires\"] = self.requires\n        if self.link_requires:\n            component[\"link_requires\"] = self.link_requires\n        if self.includes:\n            component[\"includes\"] = [x.replace(\"\\\\\", \"/\") for x in self.includes]\n        if self.definitions:\n            component[\"definitions\"] = self.definitions\n        if self.location:  # TODO: @prefix@\n            component[\"location\"] = self.location\n        if self.link_location:\n            component[\"link_location\"] = self.link_location\n        if self.link_libraries:\n            component[\"link_libraries\"] = self.link_libraries\n        if self.link_languages:\n            component[\"link_languages\"] = self.link_languages\n        return component\n\n    @staticmethod\n    def deserialize(data):\n        comp = CPSComponent()\n        comp.type = CPSComponentType(data.get(\"type\"))\n        comp.requires = data.get(\"requires\", [])\n        comp.link_requires = data.get(\"link_requires\", [])\n        comp.includes = data.get(\"includes\", [])\n        comp.definitions = data.get(\"definitions\", {})\n        comp.location = data.get(\"location\")\n        comp.link_location = data.get(\"link_location\")\n        comp.link_libraries = data.get(\"link_libraries\", [])\n        comp.link_languages = data.get(\"link_languages\", [])\n        return comp\n\n    @staticmethod\n    def from_cpp_info(cpp_info, conanfile, libname=None):\n        cps_langs_mapping = {\"C\": \"c\", \"C++\": \"cpp\"}\n        comp_langs = cpp_info.languages or conanfile.languages or []\n        def definitions_from_conan(defines):\n            result = {}\n            for define in defines:\n                if \"=\" in define:\n                    k, v = define.split(\"=\", 1)\n                    result[k] = v\n                else:\n                    result[define] = None\n            return result\n\n        cps_comp = CPSComponent()\n        if not libname:\n            cps_comp.definitions = {\n                cps_langs_mapping.get(lang, \"*\"): definitions_from_conan(cpp_info.defines)\n                for lang in (comp_langs or [\"*\"])\n            } if cpp_info.defines else {}\n            cps_comp.includes = [x.replace(\"\\\\\", \"/\") for x in cpp_info.includedirs]\n\n        if not cpp_info.libs:\n            cps_comp.type = CPSComponentType.INTERFACE\n            return cps_comp\n\n        if len(cpp_info.libs) > 1 and not libname:  # Multi-lib pkg without components defined\n            cps_comp.type = CPSComponentType.INTERFACE\n            return cps_comp\n\n        cpp_info.deduce_locations(conanfile)\n        cps_comp.type = CPSComponentType.from_conan(cpp_info.type)\n        cps_comp.location = cpp_info.location\n        cps_comp.link_location = cpp_info.link_location\n        cps_comp.link_libraries = cpp_info.system_libs\n        cps_comp.link_languages = [cps_langs_mapping[lang] for lang in comp_langs]\n        required = cpp_info.requires\n        cps_comp.requires = [f\":{c}\" if \"::\" not in c else c.replace(\"::\", \":\") for c in required]\n\n        cps_comp.definitions = {\n            cps_langs_mapping.get(lang, \"*\"): definitions_from_conan(cpp_info.defines)\n            for lang in (comp_langs or [\"*\"])\n        } if cpp_info.defines else {}\n        return cps_comp\n\n    def update(self, conf, conf_def):\n        # TODO: conf not used at the moent\n        self.link_languages = self.link_languages or conf_def.get(\"link_languages\")\n        self.location = self.location or conf_def.get(\"location\")\n        self.link_location = self.link_location or conf_def.get(\"link_location\")\n        self.link_libraries = self.link_libraries or conf_def.get(\"link_libraries\")\n\n\nclass CPS:\n    \"\"\" represents the CPS file for 1 package\n    \"\"\"\n    def __init__(self, name=None, version=None):\n        self.name = name\n        self.version = version\n        self.default_components = []\n        self.components = {}\n        self.configurations = []\n        self.requires = []\n        # Supplemental\n        self.description = None\n        self.license = None\n        self.website = None\n        self.prefix = None\n\n    def serialize(self):\n        cps = {\"cps_version\": \"0.13.0\",\n               \"name\": self.name,\n               \"version\": self.version}\n\n        if self.prefix is not None:\n            cps[\"prefix\"] = self.prefix\n\n        # Supplemental\n        for data in \"license\", \"description\", \"website\":\n            if getattr(self, data, None):\n                cps[data] = getattr(self, data)\n\n        if self.requires:\n            cps[\"requires\"] = self.requires\n\n        if self.configurations:\n            cps[\"configurations\"] = self.configurations\n\n        cps[\"default_components\"] = self.default_components\n        cps[\"components\"] = {}\n        for name, comp in self.components.items():\n            cps[\"components\"][name] = comp.serialize()\n\n        return cps\n\n    @staticmethod\n    def deserialize(data):\n        cps = CPS()\n        cps.name = data.get(\"name\")\n        cps.prefix = data.get(\"prefix\")\n        cps.version = data.get(\"version\")\n        cps.license = data.get(\"license\")\n        cps.description = data.get(\"description\")\n        cps.website = data.get(\"website\")\n        cps.requires = data.get(\"requires\")\n        cps.configurations = data.get(\"configurations\")\n        cps.default_components = data.get(\"default_components\")\n        cps.components = {k: CPSComponent.deserialize(v)\n                          for k, v in data.get(\"components\", {}).items()}\n        return cps\n\n    @staticmethod\n    def from_conan(dep):\n        cps = CPS(dep.ref.name, str(dep.ref.version))\n        cps.prefix = dep.package_folder.replace(\"\\\\\", \"/\")\n        # supplemental\n        cps.license = dep.license\n        cps.description = dep.description\n        cps.website = dep.homepage\n\n        cps.requires = {d.ref.name: None for d in dep.dependencies.host.values()}\n        if dep.settings.get_safe(\"build_type\"):\n            cps.configurations = [str(dep.settings.build_type).lower()]\n\n        if not dep.cpp_info.has_components:\n            if dep.cpp_info.libs and len(dep.cpp_info.libs) > 1:\n                comp = CPSComponent.from_cpp_info(dep.cpp_info, dep)  # base\n                base_name = f\"_{cps.name}\"\n                cps.components[base_name] = comp\n                for lib in dep.cpp_info.libs:\n                    comp = CPSComponent.from_cpp_info(dep.cpp_info, dep, lib)\n                    comp.requires.insert(0, f\":{base_name}\")  # dep to the common one\n                    cps.components[lib] = comp\n                cps.default_components = dep.cpp_info.libs\n                # FIXME: What if one lib is named equal to the package?\n            else:\n                # single component, called same as library\n                component = CPSComponent.from_cpp_info(dep.cpp_info, dep)\n                if not component.requires and dep.dependencies:\n                    for transitive_dep in dep.dependencies.host.items():\n                        dep_name = transitive_dep[0].ref.name\n                        component.requires.append(f\"{dep_name}:{dep_name}\")\n\n                # the component will be just the package name\n                cps.default_components = [f\"{dep.ref.name}\"]\n                cps.components[f\"{dep.ref.name}\"] = component\n        else:\n            sorted_comps = dep.cpp_info.get_sorted_components()\n            for comp_name, comp in sorted_comps.items():\n                component = CPSComponent.from_cpp_info(comp, dep)\n                cps.components[comp_name] = component\n            # Now by default all are default_components\n            cps.default_components = [comp_name for comp_name in sorted_comps]\n\n        return cps\n\n    def to_conan(self):\n        def strip_prefix(dirs):\n            return [d.replace(\"@prefix@/\", \"\") for d in dirs]\n\n        def lib_location(loc, info):\n            loc = loc.replace(\"@prefix@/\", \"\")\n            info.libdirs = [os.path.dirname(loc)]\n            filename = os.path.basename(loc)\n            basefile, ext = os.path.splitext(filename)\n            if basefile.startswith(\"lib\") and ext != \".lib\":\n                basefile = basefile[3:]\n            info.libs = [basefile]\n\n        def definitions(defs):\n            # TODO: C/CPP specific as per CPS spec\n            # \"*\" has less priority than specific language\n            aggregated = {}\n            aggregated.update(defs.get(\"*\", {}))\n            aggregated.update(defs.get(\"c\", {}))\n            aggregated.update(defs.get(\"cpp\", {}))\n            result = list(f\"{k}={v}\" if v is not None else k for k, v in aggregated.items())\n            return result\n\n        cpp_info = CppInfo()\n        cpp_info.default_components = self.default_components\n        for comp_name, comp in self.components.items():\n            cpp_comp = cpp_info if len(self.components) == 1 else cpp_info.components[comp_name]\n            cpp_comp.includedirs = strip_prefix(comp.includes)\n            cpp_comp.defines = definitions(comp.definitions)\n            cpp_info.set_property(\"cmake_file_name\", self.name)\n            cpp_info.set_property(\"cmake_target_name\", f\"{self.name}::{comp_name}\")\n            if comp.link_location:\n                link_location = comp.link_location\n                lib_location(link_location, cpp_comp)\n                location = comp.location\n                location = location.replace(\"@prefix@/\", \"\")\n                cpp_comp.bindirs = [os.path.dirname(location)]\n            elif comp.location:\n                location = comp.location\n                lib_location(location, cpp_comp)\n            requires = comp.link_requires + comp.requires\n            for r in requires:\n                cpp_comp.requires.append(r[1:] if r.startswith(\":\") else r.replace(\":\", \"::\"))\n            cpp_comp.system_libs = comp.link_libraries\n\n        return cpp_info\n\n    def save(self, folder):\n        filename = os.path.join(folder, f\"{self.name}.cps\")\n        save(filename, json.dumps(self.serialize(), indent=2))\n        return filename\n\n    @staticmethod\n    def load(file):\n        contents = load(file)\n        base = CPS.deserialize(json.loads(contents))\n\n        path, name = os.path.split(file)\n        basename, ext = os.path.splitext(name)\n        # Find, load and merge configuration specific files\n        for conf in \"release\", \"debug\":\n            full_conf = os.path.join(path, f\"{basename}@{conf}{ext}\")\n            if os.path.exists(full_conf):\n                conf_content = json.loads(load(full_conf))\n                for comp, comp_def in conf_content.get(\"components\", {}).items():\n                    existing = base.components.get(comp)\n                    if existing:\n                        existing.update(conf, comp_def)\n                    else:\n                        base.components[comp] = comp_def\n        return base\n"
  },
  {
    "path": "conan/errors.py",
    "content": "class ConanException(Exception):\n    \"\"\" Generic conan exception \"\"\"\n    def __init__(self, msg=None, remote=None):\n        self.remote = remote\n        super().__init__(msg)\n\n    def __str__(self):\n        msg = super().__str__()\n        if self.remote:\n            return f\"{msg}. [Remote: {self.remote.name}]\"\n        return msg\n\n\nclass ConanInvalidConfiguration(ConanException):\n    \"\"\"\n    This binary, for the requested configuration and package-id cannot be built\n    \"\"\"\n    pass\n\n\nclass ConanMigrationError(ConanException):\n    pass\n"
  },
  {
    "path": "conan/internal/__init__.py",
    "content": "from conan.errors import ConanException\n\n\nREVISIONS = \"revisions\"  # capability\n\n\ndef check_duplicated_generator(generator, conanfile):\n    if generator.__class__.__name__ in conanfile.generators:\n        raise ConanException(f\"{generator.__class__.__name__} is declared in the generators \"\n                             \"attribute, but was instantiated in the generate() method too. \"\n                             \"It should only be present in one of them.\")\n"
  },
  {
    "path": "conan/internal/api/__init__.py",
    "content": ""
  },
  {
    "path": "conan/internal/api/audit/__init__.py",
    "content": ""
  },
  {
    "path": "conan/internal/api/audit/providers.py",
    "content": "import textwrap\nfrom urllib.parse import urljoin\nfrom conan.api.output import Color, ConanOutput\nfrom conan.errors import ConanException\n\n\ndef _build_headers(token):\n    return {\"Content-Type\": \"application/json\",\n            \"Accept\": \"application/json\",\n            \"Authorization\": f\"Bearer {token}\"}\n\n\nclass ConanCenterProvider:\n    def __init__(self, conan_api, name, provider_data):\n        self.name = name\n        self.url = provider_data[\"url\"]\n        self.type = provider_data[\"type\"]\n        self._token = provider_data.get(\"token\")\n        self._session = conan_api._api_helpers.requester  # noqa\n        self._query_url = urljoin(self.url, \"api/v1/query\")\n\n    def get_cves(self, refs):\n        if not self._token:\n            from conan.api.subapi.audit import CONAN_CENTER_AUDIT_PROVIDER_NAME\n            if self.name == CONAN_CENTER_AUDIT_PROVIDER_NAME:\n                output = ConanOutput()\n                output.write(\"\\n\")\n                output.write(\"Authentication required for the CVE provider: \", fg=Color.BRIGHT_RED,\n                             newline=False)\n                output.write(f\"'{self.name}'\\n\", fg=Color.BRIGHT_WHITE)\n                output.write(\"\\nTo resolve, please:\\n\")\n                output.write(\"  1. Visit: \", fg=Color.BRIGHT_WHITE, newline=False)\n                output.write(\"https://audit.conan.io/register\\n\", fg=Color.BRIGHT_BLUE)\n                output.write(\"  2. Register to obtain the access token and activate it.\\n\",\n                             fg=Color.BRIGHT_WHITE)\n                output.write(\"  3. Use the command below to authenticate:\\n\", fg=Color.BRIGHT_WHITE)\n                output.write(f\"\\n     conan audit provider auth {self.name} --token=<your_token>\",\n                             fg=Color.BRIGHT_GREEN, newline=True)\n                output.write(\"\\nOnce authenticated, re-run the command.\\n\\n\")\n\n            raise ConanException(\"Missing authentication token. Please authenticate and retry.\")\n\n        result = {\"data\": {}, \"error\": None, \"provider_url\": None}\n\n        for ref in refs:\n            ConanOutput().info(f\"Requesting vulnerability info for: {ref}\")\n            response = self._session.post(self._query_url, headers=_build_headers(self._token),\n                                          json={\"reference\": str(ref)})\n            if response.status_code == 200:\n                result[\"data\"][str(ref)] = response.json().get(\"data\", {}).get(\"query\", {})\n            elif response.status_code == 400:\n                ConanOutput().warning(f\"Package '{ref}' not found.\\n\"\n                                      f\"Only libraries available in Conan Center can be queried for vulnerabilities.\\n\"\n                                      f\"Please ensure the package exists in the official repository: https://conan.io/center\\n\"\n                                      f\"If the package exists in the repository, please report it to conan-research@jfrog.com.\\n\")\n                result[\"data\"][str(ref)] = {\"error\": {\"details\": f\"Package '{ref}' not scanned: Not found.\"}}\n                continue\n            elif response.status_code == 403:\n                # TODO: How to report auth error to the user\n                ConanOutput().error(f\"Authentication error ({response.status_code}).\\n\"\n                                    f\"Your token may be invalid or not yet validated. If you recently registered, please check your email to validate your token.\\n\"\n                                    f\" - Set a valid token using: 'conan audit provider auth {self.name} --token=<your_token>'\\n\"\n                                    f\" - If you don’t have a token, register at: https://audit.conan.io/register\")\n\n                result[\"conan_error\"] = f\"Authentication error ({response.status_code}).\"\n                break\n            elif response.status_code == 429:\n                reset_seconds = int(response.headers.get(\"retry-after\", 0))\n                reset_in_hours = reset_seconds // 3600\n                reset_in_minutes = (reset_seconds % 3600) // 60\n\n                output = ConanOutput()\n                output.write(\"\\n\")\n\n                if reset_in_hours > 0:\n                    output.write(\n                        f\"You have exceeded the number of allowed requests. \"\n                        f\"The limit will reset in {reset_in_hours} \"\n                        f\"hour{'s' if reset_in_hours > 1 else ''} and {reset_in_minutes} \"\n                        f\"minute{'s' if reset_in_minutes > 1 else ''}.\\n\",\n                        fg=Color.BRIGHT_WHITE,\n                    )\n                else:\n                    output.write(\n                        f\"You have exceeded the number of allowed requests. \"\n                        f\"The limit will reset in {reset_in_minutes} \"\n                        f\"minute{'s'if reset_in_minutes > 1 else ''}.\\n\",\n                        fg=Color.BRIGHT_WHITE,\n                    )\n                output.write(\"Visit our website to learn more about JFrog's DevSecOps solution: \",\n                             fg=Color.BRIGHT_WHITE, newline=False)\n                output.write(\"https://audit.conan.io/limit\", newline=True,\n                             fg=Color.BRIGHT_BLUE)\n                output.write(\"\\n\")\n\n                result[\"conan_error\"] = \"Rate limit exceeded.\"\n                break\n            elif response.status_code == 500:\n                # TODO: How to report internal server error to the user\n                result[\"conan_error\"] = f\"Internal server error ({response.status_code})\"\n                break\n            else:\n                result[\"conan_error\"] = f\"Error in {ref} ({response.status_code})\"\n                break\n        return result\n\n\nclass PrivateProvider:\n    def __init__(self, conan_api, name, provider_data):\n        self.name = name\n        self.url = provider_data[\"url\"]\n        self.type = provider_data[\"type\"]\n        self._token = provider_data.get(\"token\")\n        self._session = conan_api._api_helpers.requester  # noqa\n        self._query_url = urljoin(self.url, \"catalog/api/v0/public/graphql\")\n\n    def get_cves(self, refs):\n        if not self._token:\n            raise ConanException(f\"Missing authentication token for '{self.name}' provider.\\n\"\n                                 f\"Please authenticate using 'conan audit provider auth' and retry.\")\n\n        result = {\"data\": {}, \"error\": None, \"provider_url\": self.url}\n\n        for ref in refs:\n            try:\n                response = self._get(ref)\n                if \"error\" in response:\n                    result[\"data\"][str(ref)] = {\"error\": {\"details\": response[\"error\"]}}\n                else:\n                    result[\"data\"][str(ref)] = response.get(\"data\", {}).get(\"query\", {})\n            except Exception as e:\n                result[\"conan_error\"] = str(e)\n                break\n\n        return result\n\n    @staticmethod\n    def _build_query(ref):\n        name, version = ref.name, ref.version\n        full_query = f\"\"\"query packageVersionDetails {{\n            query: packageVersion(name: \"{name}\", type: \"conan\", version: \"{version}\") {{\n                vulnerabilities(first: 100) {{\n                    totalCount\n                    edges {{\n                        node {{\n                            name\n                            description\n                            severity\n                            cvss {{\n                                preferredBaseScore\n                            }}\n                            aliases\n                            withdrawn\n                            publishedAt\n                            advisories {{\n                                name\n                                ...on JfrogAdvisory {{\n                                          name\n                                          shortDescription\n                                          severity\n                                          impactReasons {{\n                                                name\n                                                isPositive\n                                          }}\n                                }}\n                            }}\n                            references\n                            vulnerablePackages(first: 100) {{\n                                totalCount\n                                edges {{\n                                     node {{\n                                        fixVersions {{\n                                            version\n                                        }}\n                                    }}\n                                }}\n                            }}\n                        }}\n                    }}\n                }}\n            }}\n        }}\"\"\"\n        return full_query\n\n    @staticmethod\n    def _parse_error(errors, ref):\n        \"\"\"This function removes the errors array that comes from the catalog and returns a\n        more user-friendly message if we know how to parse it, or a generic one if we don't\n        find such one\"\"\"\n\n        def _replace_message(message):\n            if \"not found\" in message:\n                return f\"Package '{ref}' not scanned: Not found.\"\n            return None\n\n        error_msgs = filter(bool, [_replace_message(error[\"message\"]) for error in errors])\n        return next(error_msgs, \"Unknown error\")\n\n    def _get(self, ref):\n        full_query = self._build_query(ref)\n        try:\n            response = self._session.post(\n                self._query_url,\n                headers=_build_headers(self._token),\n                json={\n                    \"query\": textwrap.dedent(full_query)\n                }\n            )\n\n            if response.status_code == 404:\n                ConanOutput().write(\"\\n\")\n                ConanOutput().warning(\n                    f\"An error occurred while connecting to the '{self.name}' provider.\\n\"\n                    \"This is likely because your JFrog Platform instance does not have JFrog Curation.\\n\"\n                    \"For more information, visit: https://audit.conan.io/missing-curation\\n\"\n                )\n\n            # Raises if some HTTP error was found\n            response.raise_for_status()\n        except Exception as e:\n            raise e\n\n        response_json = response.json()\n        # filter the extensions key with graphql data\n        response_json.pop('extensions', None)\n\n        if \"errors\" in response_json:\n            return {\"error\": self._parse_error(response_json[\"errors\"], ref)}\n        return response_json\n"
  },
  {
    "path": "conan/internal/api/config/__init__.py",
    "content": ""
  },
  {
    "path": "conan/internal/api/config/config_installer.py",
    "content": "import os\nimport shutil\nimport fnmatch\nimport zipfile\n\nfrom urllib.parse import urlparse, urlsplit\nfrom contextlib import contextmanager\n\nfrom conan.api.output import ConanOutput\nfrom conan.internal.paths import find_file_walk_up\nfrom conan.internal.rest.file_downloader import FileDownloader\nfrom conan.errors import ConanException\nfrom conan.internal.util.files import mkdir, rmdir, remove, chdir\nfrom conan.internal.util.runners import detect_runner\nfrom conan.tools.files.files import untargz\n\n\nclass _ConanIgnoreMatcher:\n    def __init__(self, conanignore_path, ignore=None):\n        self._ignored_entries = {\".conanignore\"}\n        self._included_entries = set()\n        if ignore:\n            self._ignored_entries.update(ignore)\n        if conanignore_path is None or not os.path.exists(conanignore_path):\n            return\n        with open(conanignore_path, 'r') as conanignore:\n            for line in conanignore:\n                line_content = line.split(\"#\", maxsplit=1)[0].strip()\n                if line_content:\n                    if line_content.startswith(\"!\"):\n                        self._included_entries.add(line_content[1:])\n                    else:\n                        self._ignored_entries.add(line_content)\n\n    def matches(self, path):\n        \"\"\"Returns whether the path should be ignored\n\n        It's ignored if:\n         - The path does not match any of the included entries\n         - And the path matches any of the ignored entries\n\n        In any other, the path is not ignored\"\"\"\n        for include_entry in self._included_entries:\n            if fnmatch.fnmatch(path, include_entry):\n                return False\n        for ignore_entry in self._ignored_entries:\n            if fnmatch.fnmatch(path, ignore_entry):\n                return True\n        return False\n\n\ndef _hide_password(resource):\n    \"\"\"\n    Hide password from url/file path\n\n    :param resource: string with url or file path\n    :return: resource with hidden password if present\n    \"\"\"\n    password = urlparse(resource).password\n    return resource.replace(password, \"<hidden>\") if password else resource\n\n\n@contextmanager\ndef tmp_config_install_folder(cache_folder):\n    tmp_folder = os.path.join(cache_folder, \"tmp_config_install\")\n    # necessary for Mac OSX, where the temp folders in /var/ are symlinks to /private/var/\n    tmp_folder = os.path.abspath(tmp_folder)\n    rmdir(tmp_folder)\n    mkdir(tmp_folder)\n    try:\n        yield tmp_folder\n    finally:\n        rmdir(tmp_folder)\n\n\ndef _process_git_repo(config, cache_folder):\n    output = ConanOutput()\n    output.info(\"Trying to clone repo: %s\" % config.uri)\n    with tmp_config_install_folder(cache_folder) as tmp_folder:\n        with chdir(tmp_folder):\n            args = config.args or \"\"\n            ret, out = detect_runner('git clone \"{}\" . {}'.format(config.uri, args))\n            if ret != 0:\n                raise ConanException(\"Can't clone repo: {}\".format(out))\n            output.info(\"Repo cloned!\")\n        _process_folder(config, tmp_folder, cache_folder)\n\n\ndef _process_zip_file(config, zippath, cache_folder, tmp_folder, first_remove=False):\n    # First, unzip. This is repeated with the tools.unzip, but better do not mess\n    # Same list as below\n    tgz_exts = (\".tar.gz\", \".tgz\", \".tbz2\", \".tar.bz2\", \".tar\", \".tar.xz\", \".txz\")\n    if any(zippath.endswith(e) for e in tgz_exts):\n        untargz(zippath, tmp_folder)\n    else:\n        full_path = os.path.normpath(os.path.join(os.getcwd(), tmp_folder))\n        with zipfile.ZipFile(zippath, \"r\") as z:\n            zip_info = z.infolist()\n            extracted_size = 0\n            for file_ in zip_info:\n                extracted_size += file_.file_size\n                z.extract(file_, full_path)\n\n    if first_remove:\n        os.unlink(zippath)\n    _process_folder(config, tmp_folder, cache_folder)\n\n\ndef _filecopy(src, filename, dst):\n    # https://github.com/conan-io/conan/issues/6556\n    # This is just a local convenience for \"conan config install\", using copyfile to avoid\n    # copying with permissions that later cause bugs\n    src = os.path.join(src, filename)\n    dst = os.path.join(dst, filename)\n    # Clear the destination file\n    if os.path.exists(dst):\n        if os.path.isdir(dst):  # dst was a directory and now src is a file\n            rmdir(dst)\n        else:\n            remove(dst)\n    shutil.copyfile(src, dst)\n\n\ndef _process_file(directory, filename, config, cache_folder, folder):\n    output = ConanOutput()\n    if filename == \"settings.yml\":\n        output.info(\"Installing settings.yml\")\n        _filecopy(directory, filename, cache_folder)\n    elif filename == \"remotes.json\":\n        output.info(\"Defining remotes from remotes.json\")\n        _filecopy(directory, filename, cache_folder)\n    else:\n        relpath = os.path.relpath(directory, folder)\n        if config.target_folder:\n            target_folder = os.path.join(cache_folder, config.target_folder, relpath)\n        else:\n            target_folder = os.path.join(cache_folder, relpath)\n\n        if os.path.isfile(target_folder):  # Existed as a file and now should be a folder\n            remove(target_folder)\n\n        mkdir(target_folder)\n        output.info(\"Copying file %s to %s\" % (filename, target_folder))\n        _filecopy(directory, filename, target_folder)\n\n\ndef _process_folder(config, folder, cache_folder, ignore=None):\n    if not os.path.isdir(folder):\n        raise ConanException(\"No such directory: '%s'\" % str(folder))\n    original_folder = folder\n    if config.source_folder:\n        folder = os.path.join(folder, config.source_folder)\n    conanignore_path = find_file_walk_up(folder, \".conanignore\", end=original_folder)\n    conanignore = _ConanIgnoreMatcher(conanignore_path, ignore)\n    for root, dirs, files in os.walk(folder):\n        # .git is always ignored by default, even if not present in .conanignore\n        dirs[:] = [d for d in dirs if d != \".git\"]\n        for f in files:\n            rel_path = os.path.relpath(os.path.join(root, f), folder)\n            if not conanignore.matches(rel_path):\n                _process_file(root, f, config, cache_folder, folder)\n\n\ndef _process_download(config, cache_folder, requester):\n    output = ConanOutput()\n    with tmp_config_install_folder(cache_folder) as tmp_folder:\n        output.info(\"Trying to download  %s\" % _hide_password(config.uri))\n        path = urlsplit(config.uri).path\n        filename = os.path.basename(path)\n        zippath = os.path.join(tmp_folder, filename)\n        try:\n            downloader = FileDownloader(requester=requester, source_credentials=True)\n            downloader.download(url=config.uri, file_path=zippath, verify_ssl=config.verify_ssl,\n                                retry=1)\n            _process_zip_file(config, zippath, cache_folder, tmp_folder, first_remove=True)\n        except Exception as e:\n            raise ConanException(\"Error while installing config from %s\\n%s\" % (config.uri, str(e)))\n\n\nclass _ConfigOrigin:\n    def __init__(self, uri, config_type, verify_ssl, args, source_folder, target_folder):\n        if config_type:\n            self.type = config_type\n        else:\n            if uri.endswith(\".git\"):\n                self.type = \"git\"\n            elif os.path.isdir(uri):\n                self.type = \"dir\"\n            elif os.path.isfile(uri):\n                self.type = \"file\"\n            elif uri.startswith(\"http\"):\n                self.type = \"url\"\n            else:\n                raise ConanException(\"Unable to deduce type config install: %s\" % uri)\n        self.source_folder = source_folder\n        self.target_folder = target_folder\n        self.args = args\n        self.verify_ssl = verify_ssl\n        if os.path.exists(uri):\n            uri = os.path.abspath(uri)\n        self.uri = uri\n\n\ndef _is_compressed_file(filename):\n    open(filename, \"r\")  # Check if the file exist and can be opened\n    import zipfile\n    if zipfile.is_zipfile(filename):\n        return True\n    tgz_exts = (\".tar.gz\", \".tgz\", \".tbz2\", \".tar.bz2\", \".tar\", \".tar.xz\", \".txz\")\n    return any(filename.endswith(e) for e in tgz_exts)\n\n\ndef configuration_install(cache_folder, requester, uri, verify_ssl, config_type=None,\n                          args=None, source_folder=None, target_folder=None, ignore=None):\n    config = _ConfigOrigin(uri, config_type, verify_ssl, args, source_folder, target_folder)\n    try:\n        if config.type == \"git\":\n            _process_git_repo(config, cache_folder)\n        elif config.type == \"dir\":\n            _process_folder(config, config.uri, cache_folder, ignore)\n        elif config.type == \"file\":\n            if _is_compressed_file(config.uri):\n                with tmp_config_install_folder(cache_folder) as tmp_folder:\n                    _process_zip_file(config, config.uri, cache_folder, tmp_folder)\n            else:\n                dirname, filename = os.path.split(config.uri)\n                _process_file(dirname, filename, config, cache_folder, dirname)\n        elif config.type == \"url\":\n            _process_download(config, cache_folder, requester=requester)\n        else:\n            raise ConanException(\"Unable to process config install: %s\" % config.uri)\n    except Exception as e:\n        raise ConanException(\"Failed conan config install: %s\" % str(e))\n"
  },
  {
    "path": "conan/internal/api/detect/__init__.py",
    "content": ""
  },
  {
    "path": "conan/internal/api/detect/detect_api.py",
    "content": "import os\nimport platform\nimport re\nimport tempfile\nimport textwrap\n\nfrom conan.api.output import ConanOutput\nfrom conan.errors import ConanException\nfrom conan.internal.model.version import Version\nfrom conan.internal.util.files import load, save\nfrom conan.internal.util.runners import check_output_runner, detect_runner\n\n\ndef detect_os():\n    the_os = platform.system()\n    if the_os == \"Darwin\":\n        the_os = \"Macos\"\n    return the_os\n\n\ndef detect_arch():\n    machine = platform.machine()\n    arch = None\n    system = platform.system()\n\n    # special detectors\n    if system == \"SunOS\":\n        arch = _get_solaris_architecture()\n    elif system == \"AIX\":\n        arch = _get_aix_architecture()\n    if arch:\n        return arch\n\n    if \"ppc64le\" in machine:\n        return \"ppc64le\"\n    elif \"ppc64\" in machine:\n        return \"ppc64\"\n    elif \"ppc\" in machine:\n        return \"ppc32\"\n    elif \"mips64\" in machine:\n        return \"mips64\"\n    elif \"mips\" in machine:\n        return \"mips\"\n    elif \"sparc64\" in machine:\n        return \"sparcv9\"\n    elif \"sparc\" in machine:\n        return \"sparc\"\n    elif \"aarch64\" in machine:\n        return \"armv8\"\n    elif \"arm64\" in machine:\n        return \"armv8\"\n    elif \"ARM64\" in machine:\n        return \"armv8\"\n    elif 'riscv64' in machine:\n        return \"riscv64\"\n    elif \"riscv32\" in machine:\n        return 'riscv32'\n    elif \"64\" in machine:\n        return \"x86_64\"\n    elif \"86\" in machine:\n        return \"x86\"\n    elif \"armv8\" in machine:\n        return \"armv8\"\n    elif \"armv7\" in machine:\n        return \"armv7\"\n    elif \"arm\" in machine:\n        return \"armv6\"\n    elif \"s390x\" in machine:\n        return \"s390x\"\n    elif \"s390\" in machine:\n        return \"s390\"\n    elif \"sun4v\" in machine:\n        return \"sparc\"\n    elif \"e2k\" in machine:\n        return _get_e2k_architecture()\n\n    return None\n\n\ndef _get_solaris_architecture():\n    # under intel solaris, platform.machine()=='i86pc' so we need to handle\n    # it early to suport 64-bit\n    processor = platform.processor()\n    kernel_bitness, elf = platform.architecture()\n    if \"sparc\" in processor:\n        return \"sparcv9\" if kernel_bitness == \"64bit\" else \"sparc\"\n    elif \"i386\" in processor:\n        return \"x86_64\" if kernel_bitness == \"64bit\" else \"x86\"\n\n\ndef _get_aix_conf(options=None):\n    options = \" %s\" % options if options else \"\"\n    try:\n        ret = check_output_runner(\"getconf%s\" % options).strip()\n        return ret\n    except Exception as e:\n        ConanOutput(scope=\"detect_api\").warning(f\"Couldn't get aix getconf {e}\")\n        return None\n\n\ndef _get_aix_architecture():\n    processor = platform.processor()\n    if \"powerpc\" in processor:\n        kernel_bitness = _get_aix_conf(\"KERNEL_BITMODE\")\n        if kernel_bitness:\n            return \"ppc64\" if kernel_bitness == \"64\" else \"ppc32\"\n    elif \"rs6000\" in processor:\n        return \"ppc32\"\n\n\ndef _get_e2k_architecture():\n    return {\n        \"E1C+\": \"e2k-v4\",  # Elbrus 1C+ and Elbrus 1CK\n        \"E2C+\": \"e2k-v2\",  # Elbrus 2CM\n        \"E2C+DSP\": \"e2k-v2\",  # Elbrus 2C+\n        \"E2C3\": \"e2k-v6\",  # Elbrus 2C3\n        \"E2S\": \"e2k-v3\",  # Elbrus 2S (aka Elbrus 4C)\n        \"E8C\": \"e2k-v4\",  # Elbrus 8C and Elbrus 8C1\n        \"E8C2\": \"e2k-v5\",  # Elbrus 8C2 (aka Elbrus 8CB)\n        \"E12C\": \"e2k-v6\",  # Elbrus 12C\n        \"E16C\": \"e2k-v6\",  # Elbrus 16C\n        \"E32C\": \"e2k-v7\",  # Elbrus 32C\n    }.get(platform.processor())\n\n\ndef _parse_gnu_libc(ldd_output):\n    first_line = ldd_output.partition(\"\\n\")[0]\n    if any(glibc_indicator in first_line for glibc_indicator in [\"GNU libc\", \"GLIBC\"]):\n        return first_line.split()[-1].strip()\n    return None\n\n\ndef _detect_gnu_libc(ldd=\"/usr/bin/ldd\"):\n    if platform.system() != \"Linux\":\n        ConanOutput(scope=\"detect_api\").warning(\"detect_gnu_libc() only works on Linux\")\n        return None\n    try:\n        ldd_output = check_output_runner(f\"{ldd} --version\")\n        version = _parse_gnu_libc(ldd_output)\n        if version is None:\n            first_line = ldd_output.partition(\"\\n\")[0]\n            ConanOutput(scope=\"detect_api\").warning(\n                f\"detect_gnu_libc() did not detect glibc in the first line of output from '{ldd} --version': '{first_line}'\"\n            )\n            return None\n        return version\n    except Exception as e:\n        ConanOutput(scope=\"detect_api\").debug(\n            f\"Couldn't determine the glibc version from the output of the '{ldd} --version' command {e}\"\n        )\n    return None\n\n\ndef _parse_musl_libc(ldd_output):\n    lines = ldd_output.splitlines()\n    if \"musl libc\" not in lines[0]:\n        return None\n    return lines[1].split()[-1].strip()\n\n\ndef _detect_musl_libc(ldd=\"/usr/bin/ldd\"):\n    if platform.system() != \"Linux\":\n        ConanOutput(scope=\"detect_api\").warning(\n            \"detect_musl_libc() only works on Linux\"\n        )\n        return None\n\n    d = tempfile.mkdtemp()\n    tmp_file = os.path.join(d, \"err\")\n    try:\n        with open(tmp_file, 'w') as stderr:\n            check_output_runner(f\"{ldd}\", stderr=stderr, ignore_error=True)\n        ldd_output = load(tmp_file)\n        version = _parse_musl_libc(ldd_output)\n        if version is None:\n            first_line = ldd_output.partition(\"\\n\")[0]\n            ConanOutput(scope=\"detect_api\").warning(\n                f\"detect_musl_libc() did not detect musl libc in the first line of output from '{ldd}': '{first_line}'\"\n            )\n            return None\n        return version\n    except Exception as e:\n        ConanOutput(scope=\"detect_api\").debug(\n            f\"Couldn't determine the musl libc version from the output of the '{ldd}' command {e}\"\n        )\n    finally:\n        try:\n            os.unlink(tmp_file)\n        except OSError:\n            pass\n    return None\n\n\ndef detect_libc(ldd=\"/usr/bin/ldd\"):\n    if platform.system() != \"Linux\":\n        ConanOutput(scope=\"detect_api\").warning(\n            f\"detect_libc() is only supported on Linux currently\"\n        )\n        return None, None\n    version = _detect_gnu_libc(ldd)\n    if version is not None:\n        return \"gnu\", version\n    version = _detect_musl_libc(ldd)\n    if version is not None:\n        return \"musl\", version\n    ConanOutput(scope=\"detect_api\").warning(\n        f\"Couldn't detect the libc provider and version\"\n    )\n    return None, None\n\n\ndef detect_libcxx(compiler, version, compiler_exe=None):\n    assert isinstance(version, Version)\n\n    def _detect_gcc_libcxx(version_, executable):\n        output = ConanOutput(scope=\"detect_api\")\n        # Assumes a working g++ executable\n        if executable == \"g++\":  # we can rule out old gcc versions\n            new_abi_available = version_ >= \"5.1\"\n            if not new_abi_available:\n                return \"libstdc++\"\n\n        main = textwrap.dedent(\"\"\"\n            #include <string>\n\n            using namespace std;\n            static_assert(sizeof(std::string) != sizeof(void*), \"using libstdc++\");\n            int main(){}\n            \"\"\")\n        t = tempfile.mkdtemp()\n        filename = os.path.join(t, \"main.cpp\")\n        save(filename, main)\n        old_path = os.getcwd()\n        os.chdir(t)\n        try:\n            error, out_str = detect_runner(f'\"{executable}\" main.cpp -std=c++11')\n            if error:\n                if \"using libstdc++\" in out_str:\n                    output.info(\"gcc C++ standard library: libstdc++\")\n                    return \"libstdc++\"\n                # Other error, but can't know, lets keep libstdc++11\n                output.warning(\"compiler.libcxx check error: %s\" % out_str)\n                output.warning(\"Couldn't deduce compiler.libcxx for gcc>=5.1, assuming libstdc++11\")\n            else:\n                output.info(\"gcc C++ standard library: libstdc++11\")\n            return \"libstdc++11\"\n        finally:\n            os.chdir(old_path)\n\n        # This is not really a detection in most cases\n        # Get compiler C++ stdlib\n\n    if compiler == \"apple-clang\":\n        return \"libc++\"\n    elif compiler == \"gcc\":\n        libcxx = _detect_gcc_libcxx(version, compiler_exe or \"g++\")\n        return libcxx\n    elif compiler == \"cc\":\n        if platform.system() == \"SunOS\":\n            return \"libstdcxx4\"\n    elif compiler == \"clang\":\n        if platform.system() == \"FreeBSD\":\n            return \"libc++\"\n        elif platform.system() == \"Darwin\":\n            return \"libc++\"\n        elif platform.system() == \"Windows\":\n            return  # by default windows will assume LLVM/Clang with VS backend\n        else:  # Linux\n            libcxx = _detect_gcc_libcxx(version, compiler_exe or \"clang++\")\n            return libcxx\n    elif compiler == \"sun-cc\":\n        return \"libCstd\"\n    elif compiler == \"mcst-lcc\":\n        return \"libstdc++\"\n    elif compiler == \"intel-cc\":\n        return \"libstdc++11\"\n\n\ndef default_msvc_runtime(compiler):\n    if platform.system() != \"Windows\":\n        return None, None\n    if compiler == \"clang\":\n        # It could be LLVM/Clang with VS runtime or Msys2 with libcxx\n        ConanOutput(scope=\"detect_api\").warning(\"Assuming LLVM/Clang in Windows with VS 17 2022\")\n        ConanOutput(scope=\"detect_api\").warning(\"If Msys2/Clang need to remove compiler.runtime* \"\n                                                \"and define compiler.libcxx\")\n        return \"dynamic\", \"v143\"\n    elif compiler == \"msvc\":\n        # Add default mandatory fields for MSVC compiler\n        return \"dynamic\", None\n    return None, None\n\n\ndef detect_msvc_update(version):\n    from conan.internal.api.detect.detect_vs import vs_detect_update\n    return vs_detect_update(version)\n\n\ndef default_cppstd(compiler, compiler_version):\n    \"\"\" returns the default cppstd for the compiler-version. This is not detected, just the default\n    \"\"\"\n\n    def _clang_cppstd_default(version):\n        if version >= \"16\":\n            return \"gnu17\"\n        # Official docs are wrong, in 6.0 the default is gnu14 to follow gcc's choice\n        return \"gnu98\" if version < \"6\" else \"gnu14\"\n\n    def _gcc_cppstd_default(version):\n        if version >= \"11\":\n            return \"gnu17\"\n        return \"gnu98\" if version < \"6\" else \"gnu14\"\n\n    def _visual_cppstd_default(version):\n        if version >= \"190\":  # VS 2015 update 3 only\n            return \"14\"\n        return None\n\n    def _mcst_lcc_cppstd_default(version):\n        return \"gnu14\" if version >= \"1.24\" else \"gnu98\"\n\n    def _intel_cppstd_default(version):\n        tokens = version.main\n        major = tokens[0]\n        # https://www.intel.com/content/www/us/en/developer/articles/troubleshooting/icx-changes-default-cpp-std-to-cpp17-with-2023.html\n        return \"17\" if major >= \"2023\" else \"14\"\n\n    def _apple_clang_cppstd_default(version):\n        return \"gnu98\" if version < \"17\" else \"gnu14\"\n\n    default = {\"gcc\": _gcc_cppstd_default(compiler_version),\n               \"clang\": _clang_cppstd_default(compiler_version),\n               \"apple-clang\": _apple_clang_cppstd_default(compiler_version),\n               \"intel-cc\": _intel_cppstd_default(compiler_version),\n               \"msvc\": _visual_cppstd_default(compiler_version),\n               \"mcst-lcc\": _mcst_lcc_cppstd_default(compiler_version)}.get(str(compiler), None)\n    return default\n\n\ndef detect_cppstd(compiler, compiler_version):\n    cppstd = default_cppstd(compiler, compiler_version)\n    if compiler == \"apple-clang\" and compiler_version >= \"11\":\n        # Conan does not detect the default cppstd for apple-clang,\n        # because it's still 98/14 for the compiler (even though xcode uses newer in projects)\n        # and having it be so old would be annoying for users\n        cppstd = \"gnu17\"\n    return cppstd\n\n\ndef default_cstd(compiler, compiler_version):\n    \"\"\"returns the default cstd for the compiler-version. This is not detected, just the default\"\"\"\n\n    def _clang_cstd_default(version):\n        if version >= \"11\":\n            return \"gnu17\"  # https://releases.llvm.org/11.0.0/tools/clang/docs/ReleaseNotes.html#c-language-changes-in-clang\n        elif version >= \"4\":  # 3.5 actually\n            return \"gnu11\"\n        else:\n            return \"gnu99\"  # It was gnu89 actually\n\n    def _gcc_cstd_default(version):\n        if version >= \"15\":  # https://www.gnu.org/software/gcc/gcc-15/changes.html#c\n            return \"gnu23\"\n        elif version >= \"8\":\n            return \"gnu17\"  # https://www.gnu.org/software/gcc/gcc-8/changes.html#c\n        elif version >= \"5\":\n            return \"gnu11\"  # https://www.gnu.org/software/gcc/gcc-5/changes.html#c\n        else:\n            return \"gnu99\"  # It was gnu89 actually\n\n    def _visual_cstd_default(version):\n        return None\n\n    def _apple_clang_cstd_default(version):\n        # Based on which LLVM/Clang versions these are based on\n        if version >= \"12\":\n            return \"gnu17\"\n        if version >= \"10\":\n            return \"gnu11\"\n        return \"gnu99\"\n\n    def _intel_cstd_default(version):\n        return None\n\n    def _mcst_lcc_cstd_default(version):\n        return None\n\n    default = {\n        \"gcc\": _gcc_cstd_default(compiler_version),\n        \"clang\": _clang_cstd_default(compiler_version),\n        \"apple-clang\": _apple_clang_cstd_default(compiler_version),\n        \"intel-cc\": _intel_cstd_default(compiler_version),\n        \"msvc\": _visual_cstd_default(compiler_version),\n        \"mcst-lcc\": _mcst_lcc_cstd_default(compiler_version),\n    }.get(str(compiler), None)\n    return default\n\n\ndef detect_default_compiler():\n    \"\"\"\n        find the default compiler on the build machine\n        search order and priority:\n        1. CC and CXX environment variables are always top priority\n        2. Visual Studio detection (Windows only) via vswhere or registry or environment variables\n        3. Apple Clang (Mac only)\n        4. cc executable\n        5. gcc executable\n        6. clang executable\n        \"\"\"\n    output = ConanOutput(scope=\"detect_api\")\n    cc = os.environ.get(\"CC\", \"\")\n    cxx = os.environ.get(\"CXX\", \"\")\n    if cc or cxx:  # Env defined, use them\n        output.info(\"CC and CXX: %s, %s \" % (cc or \"None\", cxx or \"None\"))\n        command = cc or cxx\n        if \"/usr/bin/cc\" == command or \"/usr/bin/c++\" == command:  # Symlinks of linux \"alternatives\"\n            return _cc_compiler(command)\n        if \"clang\" in command.lower():\n            return detect_clang_compiler(command)\n        if \"gnu-cc\" in command or \"gcc\" in command or \"g++\" in command or \"c++\" in command:\n            gcc, gcc_version, compiler_exe = detect_gcc_compiler(command)\n            if platform.system() == \"Darwin\" and gcc is None:\n                output.error(\"%s detected as a frontend using apple-clang. \"\n                             \"Compiler not supported\" % command)\n            return gcc, gcc_version, compiler_exe\n        if \"icpx\" in command or \"icx\" in command:\n            intel, intel_version, compiler_exe = detect_intel_compiler(command)\n            return intel, intel_version, compiler_exe\n        if platform.system() == \"SunOS\" and command.lower() == \"cc\":\n            return detect_suncc_compiler(command)\n        if (platform.system() == \"Windows\" and command.rstrip('\"').endswith((\"cl\", \"cl.exe\"))\n                and \"clang\" not in command):\n            return detect_cl_compiler(command)\n\n        # I am not able to find its version\n        output.error(\"Not able to automatically detect '%s' version\" % command)\n        return None, None, None\n\n    if platform.system() == \"Windows\":\n        compiler, version, compiler_exe = detect_msvc_compiler()\n        if compiler:\n            return compiler, version, compiler_exe\n\n    if platform.system() == \"SunOS\":\n        sun_cc, sun_cc_version, compiler_exe = detect_suncc_compiler()\n        if sun_cc:\n            return sun_cc, sun_cc_version, compiler_exe\n\n    if platform.system() in [\"Darwin\", \"FreeBSD\"]:\n        clang, clang_version, compiler_exe = detect_clang_compiler()  # prioritize clang\n        if clang:\n            return clang, clang_version, compiler_exe\n        return None, None, None\n    else:  # linux like system\n        compiler, compiler_version, compiler_exe = _cc_compiler()\n        if compiler:\n            return compiler, compiler_version, compiler_exe\n        gcc, gcc_version, compiler_exe = detect_gcc_compiler()\n        if gcc:\n            return gcc, gcc_version, compiler_exe\n        return detect_clang_compiler()\n\n\ndef default_msvc_ide_version(version):\n    version = {\"195\": \"18\", \"194\": \"17\", \"193\": \"17\", \"192\": \"16\", \"191\": \"15\"}.get(str(version))\n    if version:\n        return Version(version)\n\n\ndef _detect_vs_ide_version():\n    from conan.internal.api.detect.detect_vs import vs_installation_path\n    msvc_versions = \"18\", \"17\", \"16\", \"15\"\n    for version in msvc_versions:\n        vs_path = os.getenv('vs%s0comntools' % version)\n        path = vs_path or vs_installation_path(version)\n        if path:\n            ConanOutput(scope=\"detect_api\").info(\"Found msvc %s\" % version)\n            return Version(version)\n    return None\n\n\ndef _cc_compiler(compiler_exe=\"cc\"):\n    # Try to detect the \"cc\" linux system \"alternative\". It could point to gcc or clang\n    try:\n        ret, out = detect_runner(f'\"{compiler_exe}\" --version')\n        if ret != 0:\n            return None, None, None\n        compiler = \"clang\" if \"clang\" in out else \"gcc\"\n        # clang and gcc have version after a space, first try to find that to skip extra numbers\n        # that might appear in the first line of the output before the version\n        # There might also be a leading parenthesis that contains build information,\n        # so we try to skip it\n        installed_version = re.search(r\"(?:\\(.*\\))? ([0-9]+(\\.[0-9]+)*)\", out)\n        # Fallback to the first number we find optionally followed by other version fields\n        installed_version = installed_version or re.search(r\"([0-9]+(\\.[0-9]+)*)\", out)\n        if installed_version and installed_version.group(1):\n            installed_version = installed_version.group(1)\n            ConanOutput(scope=\"detect_api\").info(\"Found cc=%s-%s\" % (compiler, installed_version))\n            return compiler, Version(installed_version), compiler_exe\n    except (Exception,):  # to disable broad-except\n        return None, None, None\n\n\ndef detect_gcc_compiler(compiler_exe=\"gcc\"):\n    try:\n        if platform.system() == \"Darwin\":\n            # In Mac OS X check if gcc is a fronted using apple-clang\n            _, out = detect_runner(f'\"{compiler_exe}\" --version')\n            out = out.lower()\n            if \"clang\" in out:\n                return None, None, None\n\n        ret, out = detect_runner(f'\"{compiler_exe}\" -dumpversion')\n        if ret != 0:\n            return None, None, None\n        compiler = \"gcc\"\n        installed_version = re.search(r\"([0-9]+(\\.[0-9]+)?)\", out).group()\n        if installed_version:\n            ConanOutput(scope=\"detect_api\").info(\"Found %s %s\" % (compiler, installed_version))\n            return compiler, Version(installed_version), compiler_exe\n    except (Exception,):  # to disable broad-except\n        return None, None, None\n\n\ndef detect_compiler():\n    ConanOutput(scope=\"detect_api\").warning(\"detect_compiler() is deprecated, \"\n                                            \"use detect_default_compiler()\", warn_tag=\"deprecated\")\n    compiler, version, _ = detect_default_compiler()\n    return compiler, version\n\n\ndef detect_intel_compiler(compiler_exe=\"icx\"):\n    try:\n        ret, out = detect_runner(f'\"{compiler_exe}\" --version')\n        if ret != 0:\n            return None, None, None\n        compiler = \"intel-cc\"\n        installed_version = re.search(r\"(202[0-9]+(\\.[0-9])?)\", out).group()\n        if installed_version:\n            ConanOutput(scope=\"detect_api\").info(\"Found %s %s\" % (compiler, installed_version))\n            return compiler, Version(installed_version), compiler_exe\n    except (Exception,):  # to disable broad-except\n        return None, None, None\n\n\ndef detect_suncc_compiler(compiler_exe=\"cc\"):\n    try:\n        _, out = detect_runner(f'\"{compiler_exe}\" -V')\n        compiler = \"sun-cc\"\n        installed_version = re.search(r\"Sun C.*([0-9]+\\.[0-9]+)\", out)\n        if installed_version:\n            installed_version = installed_version.group(1)\n        else:\n            installed_version = re.search(r\"([0-9]+\\.[0-9]+)\", out).group()\n        if installed_version:\n            ConanOutput(scope=\"detect_api\").info(\"Found %s %s\" % (compiler, installed_version))\n            return compiler, Version(installed_version), compiler_exe\n    except (Exception,):  # to disable broad-except\n        return None, None, None\n\n\ndef detect_clang_compiler(compiler_exe=\"clang\"):\n    try:\n        ret, out = detect_runner(f'\"{compiler_exe}\" --version')\n        if ret != 0:\n            return None, None, None\n        if \"Apple\" in out:\n            compiler = \"apple-clang\"\n        elif \"clang version\" in out:\n            compiler = \"clang\"\n        else:\n            return None, None, None\n        installed_version = re.search(r\"([0-9]+\\.[0-9])\", out).group()\n        if installed_version:\n            ConanOutput(scope=\"detect_api\").info(\"Found %s %s\" % (compiler, installed_version))\n            return compiler, Version(installed_version), compiler_exe\n    except (Exception,):  # to disable broad-except\n        return None, None, None\n\n\ndef detect_msvc_compiler():\n    ide_version = _detect_vs_ide_version()\n    # Map to compiler\n    version = {\"18\": \"195\", \"17\": \"193\", \"16\": \"192\", \"15\": \"191\"}.get(str(ide_version))\n    if ide_version == \"17\":\n        update = detect_msvc_update(version)  # FIXME weird passing here the 193 compiler version\n        if update and int(update) >= 10:\n            version = \"194\"\n    if version:\n        return 'msvc', Version(version), None\n    return None, None, None\n\n\ndef detect_cl_compiler(compiler_exe=\"cl\"):\n    \"\"\" only if CC/CXX env-vars are defined pointing to cl.exe, and the VS environment must\n    be active to have them in the path\n    \"\"\"\n    try:\n        compiler_exe = compiler_exe.strip('\"')\n        ret, out = detect_runner(f'\"{compiler_exe}\" /?')\n        if ret != 0:\n            return None, None, None\n        first_line = out.splitlines()[0]\n        if \"Microsoft\" not in first_line:\n            return None, None, None\n        compiler = \"msvc\"\n        version_regex = re.search(r\"(?P<major>[0-9]+)\\.(?P<minor>[0-9]+)\\.([0-9]+)\\.?([0-9]+)?\",\n                                  first_line)\n        if not version_regex:\n            return None, None, None\n        # 19.36.32535 -> 193\n        version = f\"{version_regex.group('major')}{version_regex.group('minor')[0]}\"\n        return compiler, Version(version), compiler_exe\n    except (Exception,):  # to disable broad-except\n        return None, None, None\n\n\ndef detect_emcc_compiler(compiler_exe=\"emcc\"):\n    ret, out = detect_runner(f'\"{compiler_exe}\" --version')\n    if ret != 0:\n        return None, None, None\n    if \"Emscripten\" not in out:\n        return None, None, None\n    compiler = \"emcc\"\n    version_match = re.search(r\"[0-9]+\\.[0-9]+\\.[0-9]+\", out)\n    if not version_match:\n        return None, None, None\n    version = version_match.group()\n    ConanOutput(scope=\"detect_api\").info(\"Found %s %s\" % (compiler, version))\n    return compiler, Version(version), compiler_exe\n\n\ndef default_compiler_version(compiler, version):\n    \"\"\" returns the default version that Conan uses in profiles, typically dropping some\n    of the minor or patch digits, that do not affect binary compatibility\n    \"\"\"\n    output = ConanOutput(scope=\"detect_api\")\n    if not version:\n        raise ConanException(\n            f\"No version provided to 'detect_api.default_compiler_version()' for {compiler} compiler\")\n    tokens = version.main\n    major = tokens[0]\n    minor = tokens[1] if len(tokens) > 1 else 0\n    if compiler == \"clang\" and major >= 8:\n        output.info(\"clang>=8, using the major as version\")\n        return major\n    elif compiler == \"gcc\":\n        if major >= 5:\n            output.info(\"gcc>=5, using the major as version\")\n            return major\n        else:\n            output.info(\"gcc<5, using the major.minor as version\")\n            return Version(f\"{major}.{minor}\")\n    elif compiler == \"apple-clang\" and major >= 13:\n        output.info(\"apple-clang>=13, using the major as version\")\n        return major\n    elif compiler == \"intel\" and (major < 19 or (major == 19 and minor == 0)):\n        return major\n    elif compiler == \"msvc\":\n        return major\n    elif compiler == \"intel-cc\":\n        return major\n    return version\n\n\ndef detect_sdk_version(sdk):\n    if platform.system() != \"Darwin\":\n        return\n    cmd = f'xcrun -sdk {sdk} --show-sdk-version'\n    _, result = detect_runner(cmd)\n    result = result.strip()\n    return result\n"
  },
  {
    "path": "conan/internal/api/detect/detect_vs.py",
    "content": "import json\nimport os\nfrom shutil import which\n\nfrom conan.tools.build import cmd_args_to_string\nfrom conan.errors import ConanException\n\n\ndef vs_installation_path(version):\n    return _vs_installation_path(version)[0]\n\n\ndef vs_detect_update(version):\n    version = {\"195\": \"18\", \"194\": \"17\", \"193\": \"17\", \"192\": \"16\", \"191\": \"15\"}.get(str(version))\n    full_version = _vs_installation_path(version)[1]\n    components = full_version.split(\".\")\n    if len(components) > 1:\n        return components[1]\n\n\ndef _vs_installation_path(version):\n    # TODO: Preference hardcoded, [conf] must be defined\n    preference = [\"Enterprise\", \"Professional\", \"Community\", \"BuildTools\"]\n\n    # Try with vswhere()\n    try:\n        legacy_products = vswhere(legacy=True)\n        products = vswhere(products=[\"*\"])\n        products.extend(p for p in legacy_products if p not in products)\n    except ConanException:\n        products = None\n\n    if products:  # First matching\n        for product_type in preference:\n            for product in products:\n                if product[\"installationVersion\"].startswith(f\"{version}.\"):\n                    if product_type in product.get(\"productId\", \"\"):\n                        return product[\"installationPath\"], product[\"installationVersion\"]\n\n        # Append products without \"productId\" (Legacy installations)\n        for product in products:\n            if (product[\"installationVersion\"].startswith(f\"{version}.\")\n                    and \"productId\" not in product):\n                return product[\"installationPath\"], product[\"installationVersion\"]\n\n    # If vswhere does not find anything or not available, try with vs_comntools\n    vs_path = os.getenv(\"vs%s0comntools\" % version)\n    if vs_path:\n        sub_path_to_remove = os.path.join(\"\", \"Common7\", \"Tools\", \"\")\n        # Remove '\\\\Common7\\\\Tools\\\\' to get same output as vswhere\n        if vs_path.endswith(sub_path_to_remove):\n            vs_path = vs_path[:-(len(sub_path_to_remove)+1)]\n\n    return vs_path, None\n\n\ndef vswhere(all_=False, prerelease=True, products=None, requires=None, version=\"\", latest=False,\n            legacy=False, property_=\"\", nologo=True):\n\n    # 'version' option only works if Visual Studio 2017 is installed:\n    # https://github.com/Microsoft/vswhere/issues/91\n\n    products = list() if products is None else products\n    requires = list() if requires is None else requires\n\n    if legacy and (products or requires):\n        raise ConanException(\"The 'legacy' parameter cannot be specified with either the \"\n                             \"'products' or 'requires' parameter\")\n\n    installer_path = None\n    program_files = os.environ.get(\"ProgramFiles(x86)\") or os.environ.get(\"ProgramFiles\")\n    if program_files:\n        expected_path = os.path.join(program_files, \"Microsoft Visual Studio\", \"Installer\",\n                                     \"vswhere.exe\")\n        if os.path.isfile(expected_path):\n            installer_path = expected_path\n    vswhere_path = installer_path or which(\"vswhere\")\n\n    if not vswhere_path:\n        raise ConanException(\"Cannot locate vswhere in 'Program Files'/'Program Files (x86)' \"\n                             \"directory nor in PATH\")\n\n    arguments = list()\n    arguments.append(vswhere_path)\n\n    # Output json format\n    arguments.append(\"-utf8\")\n    arguments.append(\"-format\")\n    arguments.append(\"json\")\n\n    if all_:\n        arguments.append(\"-all\")\n\n    if prerelease:\n        arguments.append(\"-prerelease\")\n\n    if products:\n        arguments.append(\"-products\")\n        arguments.extend(products)\n\n    if requires:\n        arguments.append(\"-requires\")\n        arguments.extend(requires)\n\n    if len(version) != 0:\n        arguments.append(\"-version\")\n        arguments.append(version)\n\n    if latest:\n        arguments.append(\"-latest\")\n\n    if legacy:\n        arguments.append(\"-legacy\")\n\n    if len(property_) != 0:\n        arguments.append(\"-property\")\n        arguments.append(property_)\n\n    if nologo:\n        arguments.append(\"-nologo\")\n\n    try:\n        from conan.internal.util.runners import check_output_runner\n        cmd = cmd_args_to_string(arguments)\n        output = check_output_runner(cmd).strip()\n        # Ignore the \"description\" field, that even decoded contains non valid charsets for json\n        # (ignored ones)\n        output = \"\\n\".join([line for line in output.splitlines()\n                            if not line.strip().startswith('\"description\"')])\n\n    except (ValueError, UnicodeDecodeError) as e:\n        raise ConanException(\"vswhere error: %s\" % str(e))\n\n    return json.loads(output)\n"
  },
  {
    "path": "conan/internal/api/export.py",
    "content": "import os\nimport shutil\n\nfrom conan.tools.files import copy\nfrom conan.api.output import ConanOutput\nfrom conan.tools.scm import Git\nfrom conan.internal.errors import conanfile_exception_formatter\nfrom conan.errors import ConanException\nfrom conan.internal.model.manifest import FileTreeManifest\nfrom conan.api.model import RecipeReference\nfrom conan.internal.paths import DATA_YML\nfrom conan.internal.util.files import is_dirty, rmdir, set_dirty, mkdir, clean_dirty, chdir\n\n\ndef cmd_export(loader, cache, hook_manager, global_conf, conanfile_path,\n               name, version, user, channel,\n               graph_lock=None, remotes=None):\n    \"\"\" Export the recipe\n    param conanfile_path: the original source directory of the user containing a\n                       conanfile.py\n    \"\"\"\n    conanfile = loader.load_export(conanfile_path, name, version, user, channel, graph_lock,\n                                   remotes=remotes)\n\n    ref = RecipeReference(conanfile.name, conanfile.version,  conanfile.user, conanfile.channel)\n    ref.validate_ref(allow_uppercase=global_conf.get(\"core:allow_uppercase_pkg_names\",\n                                                     check_type=bool))\n\n    conanfile.conf = global_conf.get_conanfile_conf(ref, is_consumer=True)\n    conanfile.display_name = str(ref)\n    conanfile.output.scope = conanfile.display_name\n    scoped_output = conanfile.output\n    # Even though the package_id_non_embed_mode is minor_mode by default,\n    # and package_id_unknown_mode is semver_mode by default,\n    # recipes with buggy versions that do not define the attribute will have\n    # the same problem regardless\n    if not isinstance(ref.version.major.value, int) and ref.version.minor is not None:\n        modes = [getattr(conanfile, f\"package_id_{m}_mode\", None)\n                 for m in (\"embed\", \"non_embed\", \"unknown\")]\n        if (any(m in (\"semver\", \"major\", \"minor\", \"patch\") for m in modes) or\n                all(m is None for m in modes)):\n            msg = (f\"Version '{ref.version}' contains an alphanumeric major alongside a minor \"\n                   f\"version, without correct 'package_id_xxx_mode' attributes.\\n\"\n                   f\"This is highly discouraged due to unexpected package ID calculation \"\n                   f\"risks. Either a different version scheme should be used \"\n                   f\"(e.g., semantic versioning), or the 'package_id_xxx_mode' attributes \"\n                   f\"should be set (to something other than major, minor, patch or semver modes).\\n\"\n                   f\"Refer to the documentation for more details: \"\n                   f\"https://docs.conan.io/2/knowledge/guidelines.html#guidelines-bad-alphanumeric-majors\")\n            scoped_output.warning(msg, warn_tag=\"risk\")\n\n    recipe_layout = cache.create_export_recipe_layout(ref)\n\n    hook_manager.execute(\"pre_export\", conanfile=conanfile)\n\n    scoped_output.info(f\"Exporting package recipe: {conanfile_path}\")\n\n    export_folder = recipe_layout.export()\n    export_src_folder = recipe_layout.export_sources()\n    # TODO: cache2.0 move this creation to other place\n    mkdir(export_folder)\n    mkdir(export_src_folder)\n    recipe_metadata = recipe_layout.metadata()\n    mkdir(recipe_metadata)\n    conanfile.folders.set_base_recipe_metadata(recipe_metadata)\n    _export_recipe(conanfile, export_folder)\n    _export_source(conanfile, export_src_folder)\n    shutil.copy2(conanfile_path, recipe_layout.conanfile())\n\n    # Execute post-export hook before computing the digest\n    hook_manager.execute(\"post_export\", conanfile=conanfile)\n    conanfile.folders.set_base_export(None)\n    conanfile.folders.set_base_export_sources(None)\n\n    # Compute the new digest\n    manifest = FileTreeManifest.create(export_folder, export_src_folder)\n    manifest.save(export_folder)\n    manifest.report_summary(scoped_output)\n\n    # Compute the revision for the recipe\n    revision = _calc_revision(scoped_output=conanfile.output,\n                              path=os.path.dirname(conanfile_path),\n                              manifest=manifest,\n                              revision_mode=conanfile.revision_mode,\n                              conanfile=conanfile)\n\n    ref.revision = revision\n    recipe_layout.reference = ref\n    cache.assign_rrev(recipe_layout)\n    scoped_output.info('Exported to cache folder: %s' % recipe_layout.export())\n\n    # TODO: cache2.0: check this part\n    source_folder = recipe_layout.source()\n    if os.path.exists(source_folder):\n        try:\n            if is_dirty(source_folder):\n                scoped_output.info(\"Source folder is corrupted, forcing removal\")\n                rmdir(source_folder)\n                clean_dirty(source_folder)\n        except BaseException as e:\n            scoped_output.error(\"Unable to delete source folder. Will be marked as corrupted \"\n                                \"for deletion\", error_type=\"exception\")\n            scoped_output.warning(str(e))\n            set_dirty(source_folder)\n\n    scoped_output.success(f\"Exported: {ref.repr_humantime()}\")\n    return ref, conanfile\n\n\ndef _calc_revision(scoped_output, path, manifest, revision_mode, conanfile):\n    if revision_mode not in [\"scm\", \"scm_folder\", \"hash\"]:\n        raise ConanException(\"Revision mode should be one of 'hash' (default) or 'scm'\")\n\n    # Use the proper approach depending on 'revision_mode'\n    if revision_mode == \"hash\":\n        revision = manifest.summary_hash\n    else:\n        # Exception to the rule that tools should only be used in recipes, this Git helper is ok\n        excluded = getattr(conanfile, \"revision_mode_excluded\", None)\n        git = Git(conanfile, folder=path, excluded=excluded)\n        try:\n            revision = git.get_commit(repository=(revision_mode == \"scm\"))\n        except Exception as exc:\n            error_msg = \"Cannot detect revision using '{}' mode from repository at \" \\\n                        \"'{}'\".format(revision_mode, path)\n            raise ConanException(\"{}: {}\".format(error_msg, exc))\n\n        if git.is_dirty():\n            raise ConanException(\"Can't have a dirty repository using revision_mode='scm' and doing\"\n                                 \" 'conan export', please commit the changes and run again, or \"\n                                 \"use 'revision_mode_excluded' recipe attribute or \"\n                                 \"'core.scm:excluded' global configuration to define the list of \"\n                                 \"excluded file patterns\")\n\n        scoped_output.info(\"Using git commit as the recipe revision: %s\" % revision)\n\n    return revision\n\n\ndef _classify_patterns(patterns):\n    patterns = patterns or []\n    included, excluded = [], []\n    for p in patterns:\n        if p.startswith(\"!\"):\n            excluded.append(p[1:])\n        else:\n            included.append(p)\n\n    return included, excluded\n\n\ndef _export_source(conanfile, destination_source_folder):\n    if callable(conanfile.exports_sources):\n        raise ConanException(\"conanfile 'exports_sources' shouldn't be a method, \"\n                             \"use 'export_sources()' instead\")\n\n    if isinstance(conanfile.exports_sources, str):\n        conanfile.exports_sources = (conanfile.exports_sources,)\n\n    included_sources, excluded_sources = _classify_patterns(conanfile.exports_sources)\n    for pattern in included_sources:\n        copy(conanfile, pattern, src=conanfile.recipe_folder,\n             dst=destination_source_folder, excludes=excluded_sources)\n\n    conanfile.folders.set_base_export_sources(destination_source_folder)\n    _run_method(conanfile, \"export_sources\")\n\n\ndef _export_recipe(conanfile, destination_folder):\n    if callable(conanfile.exports):\n        raise ConanException(\"conanfile 'exports' shouldn't be a method, use 'export()' instead\")\n    if isinstance(conanfile.exports, str):\n        conanfile.exports = (conanfile.exports,)\n\n    package_output = ConanOutput(scope=\"%s: exports\" % conanfile.output.scope)\n\n    if os.path.exists(os.path.join(conanfile.recipe_folder, DATA_YML)):\n        package_output.info(\"File '{}' found. Exporting it...\".format(DATA_YML))\n        tmp = [DATA_YML]\n        if conanfile.exports:\n            tmp.extend(conanfile.exports)  # conanfile.exports could be a tuple (immutable)\n        conanfile.exports = tmp\n\n    included_exports, excluded_exports = _classify_patterns(conanfile.exports)\n\n    for pattern in included_exports:\n        copy(conanfile, pattern, conanfile.recipe_folder, destination_folder,\n             excludes=excluded_exports)\n\n    conanfile.folders.set_base_export(destination_folder)\n    _run_method(conanfile, \"export\")\n\n\ndef _run_method(conanfile, method):\n    export_method = getattr(conanfile, method, None)\n    if export_method:\n        if not callable(export_method):\n            raise ConanException(\"conanfile '%s' must be a method\" % method)\n\n        conanfile.output.highlight(\"Calling %s()\" % method)\n        default_options = conanfile.default_options\n        options = conanfile.options\n        try:\n            # TODO: Poor man attribute control access. Convert to nice decorator\n            conanfile.default_options = None\n            conanfile.options = None\n            with chdir(conanfile.recipe_folder):\n                with conanfile_exception_formatter(conanfile, method):\n                    export_method()\n        finally:\n            conanfile.default_options = default_options\n            conanfile.options = options\n"
  },
  {
    "path": "conan/internal/api/install/__init__.py",
    "content": ""
  },
  {
    "path": "conan/internal/api/install/generators.py",
    "content": "import importlib\nimport inspect\nimport os\nimport traceback\n\nfrom conan.errors import ConanException\nfrom conan.internal.cache.home_paths import HomePaths\nfrom conan.internal.errors import conanfile_exception_formatter\nfrom conan.internal.util.files import mkdir, chdir\n\n\n_generators = {\"CMakeToolchain\": \"conan.tools.cmake\",\n               \"CMakeDeps\": \"conan.tools.cmake\",\n               \"CMakeConfigDeps\": \"conan.tools.cmake\",\n               \"MesonToolchain\": \"conan.tools.meson\",\n               \"MSBuildDeps\": \"conan.tools.microsoft\",\n               \"MSBuildToolchain\": \"conan.tools.microsoft\",\n               \"NMakeToolchain\": \"conan.tools.microsoft\",\n               \"NMakeDeps\": \"conan.tools.microsoft\",\n               \"VCVars\": \"conan.tools.microsoft\",\n               \"VirtualRunEnv\": \"conan.tools.env.virtualrunenv\",\n               \"VirtualBuildEnv\": \"conan.tools.env.virtualbuildenv\",\n               \"AutotoolsDeps\": \"conan.tools.gnu\",\n               \"AutotoolsToolchain\": \"conan.tools.gnu\",\n               \"GnuToolchain\": \"conan.tools.gnu\",\n               \"PkgConfigDeps\": \"conan.tools.gnu\",\n               \"BazelDeps\": \"conan.tools.google\",\n               \"BazelToolchain\": \"conan.tools.google\",\n               \"IntelCC\": \"conan.tools.intel\",\n               \"XcodeDeps\": \"conan.tools.apple\",\n               \"XcodeToolchain\": \"conan.tools.apple\",\n               \"PremakeDeps\": \"conan.tools.premake\",\n               \"PremakeToolchain\": \"conan.tools.premake\",\n               \"MakeDeps\": \"conan.tools.gnu\",\n               \"SConsDeps\": \"conan.tools.scons\",\n               \"QbsDeps\": \"conan.tools.qbs\",\n               \"QbsProfile\": \"conan.tools.qbs\",\n               \"CPSDeps\": \"conan.tools.cps\",\n               \"ROSEnv\": \"conan.tools.ros\"\n               }\n\n\ndef _get_generator_class(generator_name):\n    try:\n        generator_class = _generators[generator_name]\n        # This is identical to import ... form ... in terms of cacheing\n    except KeyError as e:\n        raise ConanException(f\"Invalid generator '{generator_name}'. \"\n                             f\"Available types: {', '.join(_generators)}\") from e\n    try:\n        return getattr(importlib.import_module(generator_class), generator_name)\n    except ImportError as e:\n        raise ConanException(\"Internal Conan error: \"\n                             f\"Could not find module {generator_class}\") from e\n    except AttributeError as e:\n        raise ConanException(\"Internal Conan error: \"\n                             f\"Could not find name {generator_name} \"\n                             f\"inside module {generator_class}\") from e\n\n\ndef load_cache_generators(path):\n    from conan.internal.loader import load_python_file\n    result = {}  # Name of the generator: Class\n    if not os.path.isdir(path):\n        return result\n    for f in os.listdir(path):\n        if not f.endswith(\".py\") or f.startswith(\"_\"):\n            continue\n        full_path = os.path.join(path, f)\n        mod, _ = load_python_file(full_path)\n        for name, value in inspect.getmembers(mod):\n            if inspect.isclass(value) and not name.startswith(\"_\"):\n                result[name] = value\n    return result\n\n\ndef write_generators(conanfile, hook_manager, home_folder, envs_generation=None):\n    new_gen_folder = conanfile.generators_folder\n    _receive_conf(conanfile)\n    _receive_generators(conanfile)\n\n    # TODO: Optimize this, so the global generators are not loaded every call to write_generators\n    global_generators = load_cache_generators(HomePaths(home_folder).custom_generators_path)\n    hook_manager.execute(\"pre_generate\", conanfile=conanfile)\n\n    if conanfile.generators:\n        conanfile.output.highlight(f\"Writing generators to {new_gen_folder}\")\n    # generators check that they are not present in the generators field,\n    # to avoid duplicates between the generators attribute and the generate() method\n    # They would raise an exception here if we don't invalidate the field while we call them\n    old_generators = []\n    for gen in conanfile.generators:\n        if gen not in old_generators:\n            old_generators.append(gen)\n    conanfile.generators = []\n\n    for generator_name in old_generators:\n        if isinstance(generator_name, str):\n            global_generator = global_generators.get(generator_name)\n            generator_class = global_generator or _get_generator_class(generator_name)\n        else:\n            generator_class = generator_name\n            generator_name = generator_class.__name__\n        assert generator_class\n        try:\n            generator = generator_class(conanfile)\n            mkdir(new_gen_folder)\n            conanfile.output.info(f\"Generator '{generator_name}' calling 'generate()'\")\n            with chdir(new_gen_folder):\n                generator.generate()\n        except Exception as e:\n            # When a generator fails, it is very useful to have the whole stacktrace\n            if not isinstance(e, ConanException):\n                conanfile.output.error(traceback.format_exc(), error_type=\"exception\")\n            raise ConanException(f\"Error in generator '{generator_name}': {str(e)}\") from e\n\n    # restore the generators attribute, so it can raise\n    # if the user tries to instantiate a generator already present in generators\n    conanfile.generators = old_generators\n\n    if hasattr(conanfile, \"generate\"):\n        conanfile.output.highlight(\"Calling generate()\")\n        conanfile.output.info(f\"Generators folder: {new_gen_folder}\")\n        mkdir(new_gen_folder)\n        with chdir(new_gen_folder):\n            with conanfile_exception_formatter(conanfile, \"generate\"):\n                conanfile.generate()\n\n    if envs_generation is None:\n        if conanfile.virtualbuildenv:\n            mkdir(new_gen_folder)\n            with chdir(new_gen_folder):\n                from conan.tools.env.virtualbuildenv import VirtualBuildEnv\n                env = VirtualBuildEnv(conanfile)\n                # TODO: Check length of env.vars().keys() when adding NotEmpty\n                env.generate()\n        if conanfile.virtualrunenv:\n            mkdir(new_gen_folder)\n            with chdir(new_gen_folder):\n                from conan.tools.env import VirtualRunEnv\n                env = VirtualRunEnv(conanfile)\n                env.generate()\n\n    from conan.tools.env.environment import generate_aggregated_env\n    generate_aggregated_env(conanfile)\n    hook_manager.execute(\"post_generate\", conanfile=conanfile)\n\n\ndef _receive_conf(conanfile):\n    \"\"\"  collect conf_info from the immediate build_requires, aggregate it and injects/update\n    current conf\n    \"\"\"\n    # TODO: Open question 1: Only build_requires can define config?\n    # TODO: Only direct build_requires?\n    # TODO: Is really the best mechanism to define this info? Better than env-vars?\n    # Conf only for first level build_requires\n    for build_require in conanfile.dependencies.direct_build.values():\n        if build_require.conf_info:\n            conanfile.conf.compose_conf(build_require.conf_info)\n\n\ndef _receive_generators(conanfile):\n    \"\"\"  Collect generators_info from the immediate build_requires\"\"\"\n    for build_req in conanfile.dependencies.direct_build.values():\n        if build_req.generator_info:\n            if not isinstance(build_req.generator_info, list):\n                raise ConanException(f\"{build_req} 'generator_info' must be a list\")\n            names = [c.__name__ if not isinstance(c, str) else c for c in build_req.generator_info]\n            conanfile.output.warning(f\"Tool-require {build_req} adding generators: {names}\",\n                                     warn_tag=\"experimental\")\n            # Generators can be defined as a tuple in recipes, ensure we don't break if so\n            conanfile.generators = build_req.generator_info + list(conanfile.generators)\n\n\ndef relativize_path(path, conanfile, placeholder, normalize=True):\n    \"\"\"\n    relative path from the \"generators_folder\" to \"path\", asuming the root file, like\n    conan_toolchain.cmake will be directly in the \"generators_folder\"\n    \"\"\"\n    base_common_folder = conanfile.folders._base_generators # noqa\n    if not base_common_folder or not os.path.isabs(base_common_folder):\n        return path\n    try:\n        common_path = os.path.commonpath([path, conanfile.generators_folder, base_common_folder])\n        if common_path.replace(\"\\\\\", \"/\") == base_common_folder.replace(\"\\\\\", \"/\"):\n            rel_path = os.path.relpath(path, conanfile.generators_folder)\n            new_path = os.path.join(placeholder, rel_path)\n            return new_path.replace(\"\\\\\", \"/\") if normalize else new_path\n    except ValueError:  # In case the unit in Windows is different, path cannot be made relative\n        pass\n    return path\n"
  },
  {
    "path": "conan/internal/api/list/__init__.py",
    "content": ""
  },
  {
    "path": "conan/internal/api/list/query_parse.py",
    "content": "from collections import OrderedDict\n\n\ndef filter_package_configs(pkg_configurations, query):\n    postfix = _infix_to_postfix(query) if query else []\n    result = OrderedDict()\n    for pref, data in pkg_configurations.items():\n        if _evaluate_postfix_with_info(postfix, data):\n            result[pref] = data\n    return result\n\n\ndef _evaluate_postfix_with_info(postfix, binary_info):\n\n    # Evaluate conaninfo with the expression\n\n    def evaluate_info(expression):\n        \"\"\"Receives an expression like compiler.version=\"12\"\n        Uses conan_vars_info in the closure to evaluate it\"\"\"\n        name, value = expression.split(\"=\", 1)\n        value = value.replace(\"\\\"\", \"\")\n        return _evaluate(name, value, binary_info)\n\n    return _evaluate_postfix(postfix, evaluate_info)\n\n\ndef _evaluate(prop_name, prop_value, binary_info):\n    \"\"\"\n    Evaluates a single prop_name, prop_value like \"os\", \"Windows\" against\n    conan_vars_info.serialize_min()\n    \"\"\"\n\n    def compatible_prop(setting_value, _prop_value):\n        return (_prop_value == setting_value) or (_prop_value == \"None\" and setting_value is None)\n\n    # TODO: Necessary to generalize this query evaluation to include all possible fields\n    info_settings = binary_info.get(\"settings\", {})\n    info_options = binary_info.get(\"options\", {})\n\n    if not prop_name.startswith(\"options.\"):\n        return compatible_prop(info_settings.get(prop_name), prop_value)\n    else:\n        prop_name = prop_name[len(\"options.\"):]\n        return compatible_prop(info_options.get(prop_name), prop_value)\n\n\ndef _is_operator(el):\n    return el in [\"|\", \"&\"]\n\n\ndef _parse_expression(subexp):\n    \"\"\"Expressions like:\n     compiler.version=12\n     compiler=\"Visual Studio\"\n     arch=\"x86\"\n     Could be replaced with another one to parse different queries \"\"\"\n    ret = \"\"\n    quoted = False\n    for char in subexp:\n        if char in ['\"', \"'\"]:  # Fixme: Mix quotes\n            quoted = not quoted\n            ret += char\n            continue\n\n        if quoted:\n            ret += char\n        elif char == \" \" or _is_operator(char) or char in [\")\", \"(\"]:\n            break\n        else:\n            ret += char\n\n    if \"=\" not in ret:\n        raise Exception(\"Invalid expression: %s\" % ret)\n\n    return ret\n\n\ndef _evaluate_postfix(postfix, evaluator):\n    \"\"\"\n    Evaluates a postfix expression and returns a boolean\n    @param postfix:  Postfix expression as a list\n    @param evaluator: Function that will return a bool receiving expressions\n                      like \"compiler.version=12\"\n    @return: bool\n    \"\"\"\n    if not postfix:  # If no query return all?\n        return True\n\n    stack = []\n    for el in postfix:\n        if not _is_operator(el):\n            stack.append(el)\n        else:\n            o1 = stack.pop()\n            o2 = stack.pop()\n            if not isinstance(o1, bool):\n                o1 = evaluator(o1)\n            if not isinstance(o2, bool):\n                o2 = evaluator(o2)\n\n            if el == \"|\":\n                res = o1 or o2\n            elif el == \"&\":\n                res = o1 and o2\n            stack.append(res)\n    if len(stack) != 1:\n        raise Exception(\"Bad stack: %s\" % str(stack))\n    elif not isinstance(stack[0], bool):\n        return evaluator(stack[0])  # Single Expression without AND or OR\n    else:\n        return stack[0]\n\n\ndef _infix_to_postfix(exp):\n    \"\"\"\n    Translates an infix expression to postfix using an standard algorithm\n    with little hacks for parse complex expressions like \"compiler.version=4\"\n    instead of just numbers and without taking in account the operands priority\n    except the priority specified by the \"(\"\n\n    @param exp: String with an expression with & and | operators,\n        e.g.: \"os=Windows & (compiler=gcc | compiler.version=3)\"\n        e.g.: \"os=Windows AND (compiler=gcc or compiler.version=3)\"\n    @return List with the postfix expression\n    \"\"\"\n\n    # To ease the parser, operators only with one character\n    exp = exp.replace(\" AND \", \"&\").replace(\" OR \", \"|\").replace(\" and \", \"&\").replace(\" or \", \"|\")\n    output = []\n    stack = []\n\n    i = -1\n    while i < len(exp) - 1:\n        i += 1\n        char = exp[i]\n        if char == \" \":  # Ignore spaces between expressions and operators\n            continue\n        if char == \")\":  # Pop the stack until \"(\" and send them to output\n            popped = None\n            while popped != \"(\" and stack:\n                popped = stack.pop()\n                if popped != \"(\":\n                    output.append(popped)\n            if popped != \"(\":\n                raise Exception(\"Bad expression, not balanced parenthesis\")\n        elif _is_operator(char):\n            # Same operations has the same priority\n            # replace this lines if the operators need to have\n            # some priority\n            if stack and _is_operator(stack[:-1]):\n                popped = stack.pop()\n                output.append(popped)\n            stack.append(char)\n        elif char == \"(\":\n            stack.append(\"(\")\n        else:  # Parse an expression, in our case something like \"compiler=gcc\"\n            expr = _parse_expression(exp[i:])\n            i += len(expr) - 1\n            output.append(expr)\n\n    # Append remaining elements\n    if \"(\" in stack:\n        raise Exception(\"Bad expression, not balanced parenthesis\")\n    output.extend(stack)\n    return output\n"
  },
  {
    "path": "conan/internal/api/local/__init__.py",
    "content": ""
  },
  {
    "path": "conan/internal/api/local/editable.py",
    "content": "import copy\nimport fnmatch\nimport json\nimport os\nfrom os.path import join, normpath\n\nfrom conan.api.model import RecipeReference\nfrom conan.internal.util.files import load, save\n\n\nEDITABLE_PACKAGES_FILE = 'editable_packages.json'\n\n\nclass EditablePackages:\n    def __init__(self, cache_folder=None):\n        if cache_folder is None:\n            self._edited_refs = {}\n            return\n        self._edited_file = normpath(join(cache_folder, EDITABLE_PACKAGES_FILE))\n        if os.path.exists(self._edited_file):\n            edited = load(self._edited_file)\n            edited_js = json.loads(edited)\n            self._edited_refs = {RecipeReference.loads(r): d\n                                 for r, d in edited_js.items()}\n        else:\n            self._edited_refs = {}  # {ref: {\"path\": path, \"layout\": layout}}\n\n    def update_copy(self, ws_editables):\n        \"\"\"\n        Create a new instance with the union of the editable packages of self and other\n        \"\"\"\n        if ws_editables is None:\n            return self\n        result = EditablePackages()\n        result._edited_refs = self._edited_refs.copy()\n        result._edited_refs.update(ws_editables)\n        return result\n\n    @property\n    def edited_refs(self):\n        return self._edited_refs\n\n    def save(self):\n        d = {str(ref): d for ref, d in self._edited_refs.items()}\n        save(self._edited_file, json.dumps(d))\n\n    def get(self, ref):\n        _tmp = copy.copy(ref)\n        _tmp.revision = None\n        return self._edited_refs.get(_tmp)\n\n    def get_path(self, ref):\n        editable = self.get(ref)\n        if editable is not None:\n            return editable[\"path\"]\n\n    def add(self, ref, path, output_folder=None):\n        assert isinstance(ref, RecipeReference)\n        _tmp = copy.copy(ref)\n        _tmp.revision = None\n        self._edited_refs[ref] = {\"path\": path, \"output_folder\": output_folder}\n        self.save()\n\n    def remove(self, path, requires):\n        removed = {}\n        kept = {}\n        for ref, info in self._edited_refs.items():\n            to_remove = False\n            if path and info[\"path\"] == path:\n                to_remove = True\n            else:\n                for r in requires or []:\n                    if fnmatch.fnmatch(str(ref), r):\n                        to_remove = True\n            if to_remove:\n                removed[ref] = info\n            else:\n                kept[ref] = info\n        self._edited_refs = kept\n        self.save()\n        return removed\n"
  },
  {
    "path": "conan/internal/api/migrations.py",
    "content": "import os\nimport textwrap\n\nfrom conan.api.output import ConanOutput\nfrom conan.internal.default_settings import migrate_settings_file\nfrom conans.migrations import Migrator\nfrom conan.internal.util.files import load, save\n\nCONAN_GENERATED_COMMENT = \"This file was generated by Conan\"\n\n\ndef update_file(file_path, new_content):\n    \"\"\"\n    Update any file path given with the new content.\n    Notice that the file is only updated whether it contains the ``CONAN_GENERATED_COMMENT``.\n\n    :param file_path: ``str`` path to the file.\n    :param new_content: ``str`` content to be saved.\n    \"\"\"\n    out = ConanOutput()\n    file_name = os.path.basename(file_path)\n\n    if not os.path.exists(file_path):\n        save(file_path, new_content)\n    else:\n        content = load(file_path)\n\n        first_line = content.lstrip().split(\"\\n\", 1)[0]\n\n        if CONAN_GENERATED_COMMENT in first_line and content != new_content:\n            save(file_path, new_content)\n            out.success(f\"Migration: Successfully updated {file_name}\")\n\n\nclass ClientMigrator(Migrator):\n\n    def __init__(self, cache_folder, current_version):\n        self.cache_folder = cache_folder\n        super(ClientMigrator, self).__init__(cache_folder, current_version)\n\n    def _apply_migrations(self, old_version):\n        # Migrate the settings if they were the default for that version\n        # Time for migrations!\n        # Update settings.yml\n        migrate_settings_file(self.cache_folder)\n        # Update compatibility.py, app_compat.py, and cppstd_compat.py.\n        from conan.internal.graph.compatibility import migrate_compatibility_files\n        migrate_compatibility_files(self.cache_folder)\n        # Update profile plugin\n        from conan.internal.api.profile.profile_loader import migrate_profile_plugin\n        migrate_profile_plugin(self.cache_folder)\n\n        # let the back migration files be stored\n        # if there was not a previous install (old_version==None)\n        if old_version is None or old_version < \"2.4\":\n            _migrate_default_compatibility(self.cache_folder)\n\n\ndef _migrate_default_compatibility(cache_folder):\n    # just the back migration\n    undo = textwrap.dedent(\"\"\"\\\n        import os\n\n        def migrate(home_folder):\n            from conans.client.graph.compatibility import migrate_compatibility_files\n            migrate_compatibility_files(home_folder)\n        \"\"\")\n    path = os.path.join(cache_folder, \"migrations\", \"2.4_1-migrate.py\")\n    save(path, undo)\n"
  },
  {
    "path": "conan/internal/api/new/__init__.py",
    "content": ""
  },
  {
    "path": "conan/internal/api/new/alias_new.py",
    "content": "_conanfile = '''\\\nfrom conan import ConanFile\n\nclass AliasConanfile(ConanFile):\n    name = \"{{name}}\"\n    {% if version %}version = \"{{version}}\"{%endif%}\n    alias = \"{{name}}/{{target}}\"\n    revision_mode = \"{{revision_mode|default('hash')}}\"\n'''\n\n\nalias_file = {\"conanfile.py\": _conanfile}\n"
  },
  {
    "path": "conan/internal/api/new/autoools_exe.py",
    "content": "from conan.internal.api.new.autotools_lib import makefile_am\nfrom conan.internal.api.new.cmake_lib import source_cpp, test_main, source_h\n\nconanfile_exe = \"\"\"\\\nimport os\n\nfrom conan import ConanFile\nfrom conan.tools.gnu import AutotoolsToolchain, Autotools, AutotoolsDeps\nfrom conan.tools.layout import basic_layout\nfrom conan.tools.files import chdir\n\n\nclass {{package_name}}Conan(ConanFile):\n    name = \"{{name}}\"\n    version = \"{{version}}\"\n    package_type = \"application\"\n    win_bash = True\n\n    # Optional metadata\n    license = \"<Put the package license here>\"\n    author = \"<Put your name here> <And your email here>\"\n    url = \"<Package recipe repository url here, for issues about the package>\"\n    description = \"<Description of {package_name} here>\"\n    topics = (\"<Put some tag here>\", \"<here>\", \"<and here>\")\n\n    # Binary configuration\n    settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n    # Sources are located in the same place as this recipe, copy them to the recipe\n    exports_sources = \"configure.ac\", \"Makefile.am\", \"src/*\"\n\n    {% if requires is defined -%}\n    def requirements(self):\n        {% for require in requires -%}\n        self.requires(\"{{ require }}\")\n        {% endfor %}\n    {%- endif %}\n\n    def layout(self):\n        basic_layout(self)\n\n    def generate(self):\n        deps = AutotoolsDeps(self)\n        deps.generate()\n        at_toolchain = AutotoolsToolchain(self)\n        at_toolchain.generate()\n\n    def build(self):\n        autotools = Autotools(self)\n        autotools.autoreconf()\n        autotools.configure()\n        autotools.make()\n\n    def package(self):\n        autotools = Autotools(self)\n        autotools.install()\n\"\"\"\nmakefile_am_exe = \"\"\"\\\nbin_PROGRAMS = {{name}}\n{{name}}_SOURCES = main.cpp {{name}}.cpp\n\"\"\"\n\ntest_conanfile_exe_v2 = \"\"\"\\\nimport os\nfrom conan import ConanFile\nfrom conan.tools.build import can_run\nfrom conan.tools.layout import basic_layout\n\n\nclass {{package_name}}TestConan(ConanFile):\n    settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n    def requirements(self):\n        self.requires(self.tested_reference_str)\n\n    def layout(self):\n        basic_layout(self)\n\n    def test(self):\n        if can_run(self):\n            self.run(\"{{name}}\", env=\"conanrun\")\n\"\"\"\n\n\nconfigure_ac = \"\"\"\\\nAC_INIT([{{name}}], [{{version}}], [])\nAM_INIT_AUTOMAKE([-Wall -Werror foreign])\nAC_PROG_CXX\nAC_PROG_RANLIB\nAM_PROG_AR\nAC_CONFIG_FILES([Makefile src/Makefile])\nAC_OUTPUT\n\"\"\"\n\n\nautotools_exe_files = {\"conanfile.py\": conanfile_exe,\n                       \"src/{{name}}.cpp\": source_cpp,\n                       \"src/{{name}}.h\": source_h,\n                       \"src/main.cpp\": test_main,\n                       \"configure.ac\": configure_ac,\n                       \"Makefile.am\": makefile_am,\n                       \"src/Makefile.am\": makefile_am_exe,\n                       \"test_package/conanfile.py\": test_conanfile_exe_v2\n                       }\n"
  },
  {
    "path": "conan/internal/api/new/autotools_lib.py",
    "content": "from conan.internal.api.new.cmake_lib import source_cpp, source_h, test_main\n\n\nconanfile_sources_v2 = \"\"\"\nimport os\n\nfrom conan import ConanFile\nfrom conan.tools.gnu import AutotoolsToolchain, Autotools\nfrom conan.tools.layout import basic_layout\nfrom conan.tools.apple import fix_apple_shared_install_name\n\n\nclass {{package_name}}Conan(ConanFile):\n    name = \"{{name}}\"\n    version = \"{{version}}\"\n    package_type = \"library\"\n    win_bash = True\n\n    # Optional metadata\n    license = \"<Put the package license here>\"\n    author = \"<Put your name here> <And your email here>\"\n    url = \"<Package recipe repository url here, for issues about the package>\"\n    description = \"<Description of {package_name} here>\"\n    topics = (\"<Put some tag here>\", \"<here>\", \"<and here>\")\n\n    # Binary configuration\n    settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n    options = {\"shared\": [True, False], \"fPIC\": [True, False]}\n    default_options = {\"shared\": False, \"fPIC\": True}\n\n    exports_sources = \"configure.ac\", \"Makefile.am\", \"src/*\"\n\n    def config_options(self):\n        if self.settings.os == \"Windows\":\n            self.options.rm_safe(\"fPIC\")\n\n    def configure(self):\n        if self.options.shared:\n            self.options.rm_safe(\"fPIC\")\n\n    def layout(self):\n        basic_layout(self)\n\n    def generate(self):\n        at_toolchain = AutotoolsToolchain(self)\n        at_toolchain.generate()\n\n    def build(self):\n        autotools = Autotools(self)\n        autotools.autoreconf()\n        autotools.configure()\n        autotools.make()\n\n    def package(self):\n        autotools = Autotools(self)\n        autotools.install()\n        fix_apple_shared_install_name(self)\n\n    def package_info(self):\n        self.cpp_info.libs = [\"{{name}}\"]\n\"\"\"\n\nconfigure_ac = \"\"\"\nAC_INIT([{{name}}], [{{version}}], [])\nAM_INIT_AUTOMAKE([-Wall -Werror foreign])\nAC_PROG_CXX\nAM_PROG_AR\nLT_INIT\nAC_CONFIG_FILES([Makefile src/Makefile])\nAC_OUTPUT\n\"\"\"\n\nmakefile_am = \"\"\"\nSUBDIRS = src\n\"\"\"\n\nmakefile_am_lib = \"\"\"\nlib_LTLIBRARIES = lib{{name}}.la\nlib{{name}}_la_SOURCES = {{name}}.cpp {{name}}.h\nlib{{name}}_la_HEADERS = {{name}}.h\nlib{{name}}_ladir = $(includedir)\n\"\"\"\n\ntest_conanfile_v2 = \"\"\"\nimport os\n\nfrom conan import ConanFile\nfrom conan.tools.gnu import AutotoolsToolchain, Autotools, AutotoolsDeps\nfrom conan.tools.layout import basic_layout\nfrom conan.tools.build import can_run\n\n\nclass {{package_name}}TestConan(ConanFile):\n    settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n    generators = \"AutotoolsDeps\", \"AutotoolsToolchain\"\n    win_bash = True\n\n    def requirements(self):\n        self.requires(self.tested_reference_str)\n\n    def build(self):\n        autotools = Autotools(self)\n        autotools.autoreconf()\n        autotools.configure()\n        autotools.make()\n\n    def layout(self):\n        basic_layout(self)\n\n    def test(self):\n        if can_run(self):\n            cmd = os.path.join(self.cpp.build.bindir, \"main\")\n            self.run(cmd, env=\"conanrun\")\n\"\"\"\n\ntest_configure_ac = \"\"\"\nAC_INIT([main], [1.0], [])\nAM_INIT_AUTOMAKE([-Wall -Werror foreign])\nAC_PROG_CXX\nAC_PROG_RANLIB\nAM_PROG_AR\nAC_CONFIG_FILES([Makefile])\nAC_OUTPUT\n\"\"\"\n\ntest_makefile_am = \"\"\"\nbin_PROGRAMS = main\nmain_SOURCES = main.cpp\n\"\"\"\n\nautotools_lib_files = {\"conanfile.py\": conanfile_sources_v2,\n                       \"src/{{name}}.cpp\": source_cpp,\n                       \"src/{{name}}.h\": source_h,\n                       \"src/Makefile.am\": makefile_am_lib,\n                       \"configure.ac\": configure_ac,\n                       \"Makefile.am\": makefile_am,\n                       \"test_package/conanfile.py\": test_conanfile_v2,\n                       \"test_package/main.cpp\": test_main,\n                       \"test_package/configure.ac\": test_configure_ac,\n                       \"test_package/Makefile.am\": test_makefile_am\n                       }\n"
  },
  {
    "path": "conan/internal/api/new/basic.py",
    "content": "def inject_get_or_else(variable, default):\n    return variable + ' = \"{% if ' + variable + \" is defined %}{{ \" + variable + \" }}{% else %}\" + default + '{% endif %}\"'\n\n\n_conanfile_header = f'''\\\n    {inject_get_or_else(\"name\", \"pkg\")}\n    {inject_get_or_else(\"version\", \"1.0\")}\n    {inject_get_or_else(\"description\", \"A basic recipe\")}\n    {inject_get_or_else(\"license\", \"<Your project license goes here>\")}\n    {inject_get_or_else(\"homepage\", \"<Your project homepage goes here>\")}\n'''\n\n_conanfile = '''\\\nfrom conan import ConanFile\n\nclass BasicConanfile(ConanFile):\n''' + _conanfile_header + '''\\\n\n    # Check the documentation for the rest of the available attributes\n\n\n    # The requirements method allows you to define the dependencies of your recipe\n    def requirements(self):\n        # Each call to self.requires() will add the corresponding requirement\n        # to the current list of requirements\n        {% if requires is defined -%}\n        {% for require in requires -%}\n        self.requires(\"{{ require }}\")\n        {% endfor %}\n        {% else -%}\n        # Uncommenting this line will add the zlib/1.2.13 dependency to your project\n        # self.requires(\"zlib/1.2.13\")\n        pass\n        {%- endif %}\n\n    # The build_requirements() method is functionally equivalent to the requirements() one,\n    # being executed just after it. It's a good place to define tool requirements,\n    # dependencies necessary at build time, not at application runtime\n    def build_requirements(self):\n        # Each call to self.tool_requires() will add the corresponding build requirement\n        {% if tool_requires is defined -%}\n        {% for require in tool_requires -%}\n        self.tool_requires(\"{{ require }}\")\n        {% endfor %}\n        {% else -%}\n        # Uncommenting this line will add the cmake >=3.15 build dependency to your project\n        # self.requires(\"cmake/[>=3.15]\")\n        pass\n        {%- endif %}\n\n    # The purpose of generate() is to prepare the build, generating the necessary files, such as\n    # Files containing information to locate the dependencies, environment activation scripts,\n    # and specific build system files among others\n    def generate(self):\n        pass\n\n    # This method is used to build the source code of the recipe using the desired commands.\n    def build(self):\n        # You can use your command line tools to invoke your build system\n        # or any of the build helpers provided with Conan in conan.tools\n        # self.run(\"g++ ...\")\n        pass\n\n    # The actual creation of the package, once it's built, is done in the package() method.\n    # Using the copy() method from tools.files, artifacts are copied\n    # from the build folder to the package folder\n    def package(self):\n        # copy(self, \"*.h\", self.source_folder, join(self.package_folder, \"include\"), keep_path=False)\n        pass\n'''\n\n\n_conanfile_default = '''from conan import ConanFile\nfrom conan.tools.cmake import CMakeToolchain, CMake, cmake_layout, CMakeDeps\n\n\nclass {{package_name}}Recipe(ConanFile):\n    name = \"{{name}}\"\n    version = \"{{version}}\"\n    settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n    def layout(self):\n        cmake_layout(self)\n    {% if requires is defined %}\n    def requirements(self):\n        {% for require in requires -%}\n        self.requires(\"{{ require }}\")\n        {% endfor %}\n    {%- endif %}\n    {%- if tool_requires is defined %}\n    def build_requirements(self):\n        {% for require in tool_requires -%}\n        self.tool_requires(\"{{ require }}\")\n        {% endfor %}\n    {%- endif %}\n    def generate(self):\n        deps = CMakeDeps(self)\n        deps.generate()\n        tc = CMakeToolchain(self)\n        tc.generate()\n\n    def build(self):\n        cmake = CMake(self)\n        cmake.configure()\n        cmake.build()\n\n    # This recipe is aimed at a consumer scenario. If you want to create\n    # a package, then you should add the following attributes/methods:\n    #   * exports_sources attribute (https://docs.conan.io/2/reference/conanfile/attributes.html#exports-sources)\n    #   * package method (https://docs.conan.io/2/reference/conanfile/methods/package.html)\n    #   * package_info method (https://docs.conan.io/2/reference/conanfile/methods/package_info.html)\n\n'''\n\n\nbasic_file = {\"conanfile.py\": _conanfile}\nbasic_default_file = {\"conanfile.py\": _conanfile_default}\n"
  },
  {
    "path": "conan/internal/api/new/bazel_7_exe.py",
    "content": "from conan.internal.api.new.cmake_lib import source_cpp, source_h, test_main\n\n\nconanfile_exe = \"\"\"\nimport os\nfrom conan import ConanFile\nfrom conan.tools.google import Bazel, bazel_layout\nfrom conan.tools.files import copy\n\n\nclass {{package_name}}Recipe(ConanFile):\n    name = \"{{name}}\"\n    version = \"{{version}}\"\n    package_type = \"application\"\n\n    # Binary configuration\n    settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n    # Sources are located in the same place as this recipe, copy them to the recipe\n    exports_sources = \"main/*\", \"MODULE.bazel\", \".bazelrc\"\n\n    generators = \"BazelToolchain\"\n\n    def layout(self):\n        bazel_layout(self)\n\n    def build(self):\n        bazel = Bazel(self)\n        bazel.build(target=\"//main:{{name}}\")\n\n    def package(self):\n        dest_bin = os.path.join(self.package_folder, \"bin\")\n        build = os.path.join(self.build_folder, \"bazel-bin\", \"main\")\n        copy(self, \"{{name}}\", build, dest_bin, keep_path=False)\n        copy(self, \"{{name}}.exe\", build, dest_bin, keep_path=False)\n        \"\"\"\n\ntest_conanfile_exe_v2 = \"\"\"from conan import ConanFile\nfrom conan.tools.build import can_run\n\n\nclass {{package_name}}Test(ConanFile):\n    settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n    def requirements(self):\n        self.requires(self.tested_reference_str)\n\n    def test(self):\n        if can_run(self):\n            self.run(\"{{name}}\", env=\"conanrun\")\n\"\"\"\n\n_bazel_build_exe = \"\"\"\\\ncc_binary(\n    name = \"{{name}}\",\n    srcs = [\"main.cpp\", \"{{name}}.cpp\", \"{{name}}.h\"]\n)\n\"\"\"\n\n_bazel_workspace = \" \"  # Important not empty, so template doesn't discard it\n_bazel_rc = \"\"\"\\\n{% if output_root_dir is defined %}startup --output_user_root={{output_root_dir}}{% endif %}\n\"\"\"\n\nbazel_exe_files_7 = {\"conanfile.py\": conanfile_exe,\n                     \"main/{{name}}.cpp\": source_cpp,\n                     \"main/{{name}}.h\": source_h,\n                     \"main/main.cpp\": test_main,\n                     \"main/BUILD\": _bazel_build_exe,\n                     \"MODULE.bazel\": _bazel_workspace,\n                     \".bazelrc\": _bazel_rc,\n                     \"test_package/conanfile.py\": test_conanfile_exe_v2\n                     }\n"
  },
  {
    "path": "conan/internal/api/new/bazel_7_lib.py",
    "content": "from conan.internal.api.new.cmake_lib import source_cpp, source_h, test_main\n\nconanfile_sources_v2 = \"\"\"\nimport os\nfrom conan import ConanFile\nfrom conan.tools.google import Bazel, bazel_layout\nfrom conan.tools.files import copy\n\nclass {{package_name}}Recipe(ConanFile):\n    name = \"{{name}}\"\n    version = \"{{version}}\"\n    package_type = \"library\"\n\n    # Binary configuration\n    settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n    options = {\"shared\": [True, False], \"fPIC\": [True, False]}\n    default_options = {\"shared\": False, \"fPIC\": True}\n\n    # Sources are located in the same place as this recipe, copy them to the recipe\n    exports_sources = \"main/*\", \"MODULE.bazel\", \".bazelrc\"\n    generators = \"BazelToolchain\"\n\n    def config_options(self):\n        if self.settings.os == \"Windows\":\n            self.options.rm_safe(\"fPIC\")\n\n    def configure(self):\n        if self.options.shared:\n            self.options.rm_safe(\"fPIC\")\n\n    def layout(self):\n        bazel_layout(self)\n\n    def build(self):\n        bazel = Bazel(self)\n        # On Linux platforms, Bazel creates both shared and static libraries by default, and\n        # it is getting naming conflicts if we use the cc_shared_library rule\n        if self.options.shared and self.settings.os != \"Linux\":\n            # We need to add '--experimental_cc_shared_library' because the project uses\n            # cc_shared_library to create shared libraries\n            bazel.build(args=[\"--experimental_cc_shared_library\"], target=\"//main:{{name}}_shared\")\n        else:\n            bazel.build(target=\"//main:{{name}}\")\n\n    def package(self):\n        dest_lib = os.path.join(self.package_folder, \"lib\")\n        dest_bin = os.path.join(self.package_folder, \"bin\")\n        build = os.path.join(self.build_folder, \"bazel-bin\", \"main\")\n        copy(self, \"*.so\", build, dest_lib, keep_path=False)\n        copy(self, \"*.dll\", build, dest_bin, keep_path=False)\n        copy(self, \"*.dylib\", build, dest_lib, keep_path=False)\n        if self.settings.os == \"Linux\" and self.options.get_safe(\"fPIC\"):\n            copy(self, \"*.pic.a\", build, dest_lib, keep_path=False)\n        else:\n            copy(self, \"*.a\", build, dest_lib, keep_path=False)\n        copy(self, \"*.lib\", build, dest_lib, keep_path=False)\n        copy(self, \"{{name}}.h\", os.path.join(self.source_folder, \"main\"),\n             os.path.join(self.package_folder, \"include\"), keep_path=False)\n\n    def package_info(self):\n        if self.options.shared and self.settings.os != \"Linux\":\n            self.cpp_info.libs = [\"{{name}}_shared\"]\n        else:\n            self.cpp_info.libs = [\"{{name}}\"]\n\"\"\"\n\n\ntest_conanfile_v2 = \"\"\"import os\nfrom conan import ConanFile\nfrom conan.tools.google import Bazel, bazel_layout\nfrom conan.tools.build import can_run\n\n\nclass {{package_name}}TestConan(ConanFile):\n    settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n    generators = \"BazelToolchain\", \"BazelDeps\"\n\n    def requirements(self):\n        self.requires(self.tested_reference_str)\n\n    def build(self):\n        bazel = Bazel(self)\n        bazel.build(target=\"//main:example\")\n\n    def layout(self):\n        bazel_layout(self)\n\n    def test(self):\n        if can_run(self):\n            cmd = os.path.join(self.cpp.build.bindir, \"main\", \"example\")\n            self.run(cmd, env=\"conanrun\")\n\"\"\"\n\n\n_bazel_build_test = \"\"\"\\\ncc_binary(\n    name = \"example\",\n    srcs = [\"example.cpp\"],\n    deps = [\n        \"@{{name}}//:{{name}}\",\n    ],\n)\n\"\"\"\n\n_bazel_build = \"\"\"\\\ncc_library(\n    name = \"{{name}}\",\n    srcs = [\"{{name}}.cpp\"],\n    hdrs = [\"{{name}}.h\"],\n)\n\"\"\"\n\n_bazel_build_shared = \"\"\"\ncc_shared_library(\n    name = \"{{name}}_shared\",\n    shared_lib_name = \"lib{{name}}_shared.%s\",\n    deps = [\":{{name}}\"],\n)\n\"\"\"\n\n_bazel_workspace = \" \"  # Important not empty, so template doesn't discard it\n_bazel_rc = \"\"\"\\\n{% if output_root_dir is defined %}startup --output_user_root={{output_root_dir}}{% endif %}\n\"\"\"\n_test_bazel_module_bazel = \"\"\"\\\nload_conan_dependencies = use_extension(\"//conan:conan_deps_module_extension.bzl\", \"conan_extension\")\nuse_repo(load_conan_dependencies, \"{{name}}\")\n\"\"\"\n\n\ndef _get_bazel_build():\n    import platform\n    os_ = platform.system()\n    ret = _bazel_build\n    if os_ != \"Linux\":\n        ret += _bazel_build_shared % (\"dylib\" if os_ == \"Darwin\" else \"dll\")\n    return ret\n\n\nbazel_lib_files_7 = {\"conanfile.py\": conanfile_sources_v2,\n                     \"main/{{name}}.cpp\": source_cpp,\n                     \"main/{{name}}.h\": source_h,\n                     \"main/BUILD\": _get_bazel_build(),\n                     \"MODULE.bazel\": _bazel_workspace,\n                     \".bazelrc\": _bazel_rc,\n                     \"test_package/conanfile.py\": test_conanfile_v2,\n                     \"test_package/main/example.cpp\": test_main,\n                     \"test_package/main/BUILD\": _bazel_build_test,\n                     \"test_package/MODULE.bazel\": _test_bazel_module_bazel,\n                     \"test_package/.bazelrc\": _bazel_rc}\n"
  },
  {
    "path": "conan/internal/api/new/bazel_exe.py",
    "content": "from conan.internal.api.new.cmake_lib import source_cpp, source_h, test_main\n\n\nconanfile_exe = \"\"\"\nimport os\nfrom conan import ConanFile\nfrom conan.tools.google import Bazel, bazel_layout\nfrom conan.tools.files import copy\n\n\nclass {{package_name}}Recipe(ConanFile):\n    name = \"{{name}}\"\n    version = \"{{version}}\"\n    package_type = \"application\"\n\n    # Binary configuration\n    settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n    # Sources are located in the same place as this recipe, copy them to the recipe\n    exports_sources = \"main/*\", \"WORKSPACE\", \".bazelrc\"\n    generators = \"BazelToolchain\"\n\n    def layout(self):\n        bazel_layout(self)\n\n    def build(self):\n        from conan.api.output import ConanOutput\n        ConanOutput().warning(\"This is the template for Bazel 6.x version, \"\n                              \"but it will be overridden by the 'bazel_7_exe' template \"\n                              \"(Bazel >= 7.1 compatible).\", warn_tag=\"deprecated\")\n        bazel = Bazel(self)\n        bazel.build(target=\"//main:{{name}}\")\n\n    def package(self):\n        dest_bin = os.path.join(self.package_folder, \"bin\")\n        build = os.path.join(self.build_folder, \"bazel-bin\", \"main\")\n        copy(self, \"{{name}}\", build, dest_bin, keep_path=False)\n        copy(self, \"{{name}}.exe\", build, dest_bin, keep_path=False)\n        \"\"\"\n\ntest_conanfile_exe_v2 = \"\"\"from conan import ConanFile\nfrom conan.tools.build import can_run\n\n\nclass {{package_name}}Test(ConanFile):\n    settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n    def requirements(self):\n        self.requires(self.tested_reference_str)\n\n    def test(self):\n        if can_run(self):\n            self.run(\"{{name}}\", env=\"conanrun\")\n\"\"\"\n\n_bazel_build_exe = \"\"\"\\\ncc_binary(\n    name = \"{{name}}\",\n    srcs = [\"main.cpp\", \"{{name}}.cpp\", \"{{name}}.h\"]\n)\n\"\"\"\n\n_bazel_workspace = \" \"  # Important not empty, so template doesn't discard it\n_bazel_rc = \"\"\"\\\n{% if output_root_dir is defined %}startup --output_user_root={{output_root_dir}}{% endif %}\n\"\"\"\n\nbazel_exe_files = {\"conanfile.py\": conanfile_exe,\n                   \"main/{{name}}.cpp\": source_cpp,\n                   \"main/{{name}}.h\": source_h,\n                   \"main/main.cpp\": test_main,\n                   \"main/BUILD\": _bazel_build_exe,\n                   \"WORKSPACE\": _bazel_workspace,\n                   \".bazelrc\": _bazel_rc,\n                   \"test_package/conanfile.py\": test_conanfile_exe_v2\n                   }\n"
  },
  {
    "path": "conan/internal/api/new/bazel_lib.py",
    "content": "from conan.internal.api.new.cmake_lib import source_cpp, source_h, test_main\n\nconanfile_sources_v2 = \"\"\"\nimport os\nfrom conan import ConanFile\nfrom conan.tools.google import Bazel, bazel_layout\nfrom conan.tools.files import copy\n\nclass {{package_name}}Recipe(ConanFile):\n    name = \"{{name}}\"\n    version = \"{{version}}\"\n    package_type = \"library\"\n\n    # Binary configuration\n    settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n    options = {\"shared\": [True, False], \"fPIC\": [True, False]}\n    default_options = {\"shared\": False, \"fPIC\": True}\n\n    # Sources are located in the same place as this recipe, copy them to the recipe\n    exports_sources = \"main/*\", \"WORKSPACE\", \".bazelrc\"\n    generators = \"BazelToolchain\"\n\n    def config_options(self):\n        if self.settings.os == \"Windows\":\n            self.options.rm_safe(\"fPIC\")\n\n    def configure(self):\n        if self.options.shared:\n            self.options.rm_safe(\"fPIC\")\n\n    def layout(self):\n        bazel_layout(self)\n\n    def build(self):\n        from conan.api.output import ConanOutput\n        ConanOutput().warning(\"This is the template for Bazel 6.x version, \"\n                              \"but it will be overridden by the 'bazel_7_lib' template \"\n                              \"(Bazel >= 7.1 compatible).\", warn_tag=\"deprecated\")\n        bazel = Bazel(self)\n        # On Linux platforms, Bazel creates both shared and static libraries by default, and\n        # it is getting naming conflicts if we use the cc_shared_library rule\n        if self.options.shared and self.settings.os != \"Linux\":\n            # We need to add '--experimental_cc_shared_library' because the project uses\n            # cc_shared_library to create shared libraries\n            bazel.build(args=[\"--experimental_cc_shared_library\"], target=\"//main:{{name}}_shared\")\n        else:\n            bazel.build(target=\"//main:{{name}}\")\n\n    def package(self):\n        dest_lib = os.path.join(self.package_folder, \"lib\")\n        dest_bin = os.path.join(self.package_folder, \"bin\")\n        build = os.path.join(self.build_folder, \"bazel-bin\", \"main\")\n        copy(self, \"*.so\", build, dest_lib, keep_path=False)\n        copy(self, \"*.dll\", build, dest_bin, keep_path=False)\n        copy(self, \"*.dylib\", build, dest_lib, keep_path=False)\n        if self.settings.os == \"Linux\" and self.options.get_safe(\"fPIC\"):\n            copy(self, \"*.pic.a\", build, dest_lib, keep_path=False)\n        else:\n            copy(self, \"*.a\", build, dest_lib, keep_path=False)\n        copy(self, \"*.lib\", build, dest_lib, keep_path=False)\n        copy(self, \"{{name}}.h\", os.path.join(self.source_folder, \"main\"),\n             os.path.join(self.package_folder, \"include\"), keep_path=False)\n\n    def package_info(self):\n        if self.options.shared and self.settings.os != \"Linux\":\n            self.cpp_info.libs = [\"{{name}}_shared\"]\n        else:\n            self.cpp_info.libs = [\"{{name}}\"]\n\"\"\"\n\n\ntest_conanfile_v2 = \"\"\"import os\nfrom conan import ConanFile\nfrom conan.tools.google import Bazel, bazel_layout\nfrom conan.tools.build import can_run\n\n\nclass {{package_name}}TestConan(ConanFile):\n    settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n    generators = \"BazelToolchain\", \"BazelDeps\"\n\n    def requirements(self):\n        self.requires(self.tested_reference_str)\n\n    def build(self):\n        bazel = Bazel(self)\n        bazel.build()\n\n    def layout(self):\n        bazel_layout(self)\n\n    def test(self):\n        if can_run(self):\n            cmd = os.path.join(self.cpp.build.bindir, \"main\", \"example\")\n            self.run(cmd, env=\"conanrun\")\n\"\"\"\n\n\n_bazel_build_test = \"\"\"\\\ncc_binary(\n    name = \"example\",\n    srcs = [\"example.cpp\"],\n    deps = [\n        \"@{{name}}//:{{name}}\",\n    ],\n)\n\"\"\"\n\n_bazel_build = \"\"\"\\\ncc_library(\n    name = \"{{name}}\",\n    srcs = [\"{{name}}.cpp\"],\n    hdrs = [\"{{name}}.h\"],\n)\n\"\"\"\n\n_bazel_build_shared = \"\"\"\ncc_shared_library(\n    name = \"{{name}}_shared\",\n    shared_lib_name = \"lib{{name}}_shared.%s\",\n    deps = [\":{{name}}\"],\n)\n\"\"\"\n\n_bazel_workspace = \" \"  # Important not empty, so template doesn't discard it\n_bazel_rc = \"\"\"\\\n{% if output_root_dir is defined %}startup --output_user_root={{output_root_dir}}{% endif %}\n\"\"\"\n_test_bazel_workspace = \"\"\"\nload(\"@//conan:dependencies.bzl\", \"load_conan_dependencies\")\nload_conan_dependencies()\n\"\"\"\n\n\ndef _get_bazel_build():\n    import platform\n    os_ = platform.system()\n    ret = _bazel_build\n    if os_ != \"Linux\":\n        ret += _bazel_build_shared % (\"dylib\" if os_ == \"Darwin\" else \"dll\")\n    return ret\n\n\nbazel_lib_files = {\"conanfile.py\": conanfile_sources_v2,\n                   \"main/{{name}}.cpp\": source_cpp,\n                   \"main/{{name}}.h\": source_h,\n                   \"main/BUILD\": _get_bazel_build(),\n                   \"WORKSPACE\": _bazel_workspace,\n                   \".bazelrc\": _bazel_rc,\n                   \"test_package/conanfile.py\": test_conanfile_v2,\n                   \"test_package/main/example.cpp\": test_main,\n                   \"test_package/main/BUILD\": _bazel_build_test,\n                   \"test_package/WORKSPACE\": _test_bazel_workspace,\n                   \"test_package/.bazelrc\": _bazel_rc}\n"
  },
  {
    "path": "conan/internal/api/new/cmake_exe.py",
    "content": "from conan.internal.api.new.cmake_lib import source_cpp, source_h, test_main\n\nconanfile_exe = '''from conan import ConanFile\nfrom conan.tools.cmake import CMakeToolchain, CMake, cmake_layout, CMakeDeps\n\n\nclass {{package_name}}Recipe(ConanFile):\n    name = \"{{name}}\"\n    version = \"{{version}}\"\n    package_type = \"application\"\n\n    # Optional metadata\n    license = \"<Put the package license here>\"\n    author = \"<Put your name here> <And your email here>\"\n    url = \"<Package recipe repository url here, for issues about the package>\"\n    description = \"<Description of {{ name }} package here>\"\n    topics = (\"<Put some tag here>\", \"<here>\", \"<and here>\")\n\n    # Binary configuration\n    settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n    # Sources are located in the same place as this recipe, copy them to the recipe\n    exports_sources = \"CMakeLists.txt\", \"src/*\"\n\n    def layout(self):\n        cmake_layout(self)\n\n    def generate(self):\n        deps = CMakeDeps(self)\n        deps.generate()\n        tc = CMakeToolchain(self)\n        tc.generate()\n\n    def build(self):\n        cmake = CMake(self)\n        cmake.configure()\n        cmake.build()\n\n    def package(self):\n        cmake = CMake(self)\n        cmake.install()\n\n    {% if requires is defined -%}\n    def requirements(self):\n        {% for require in requires -%}\n        self.requires(\"{{ require }}\")\n        {% endfor %}\n    {%- endif %}\n\n    {% if tool_requires is defined -%}\n    def build_requirements(self):\n        {% for require in tool_requires -%}\n        self.tool_requires(\"{{ require }}\")\n        {% endfor %}\n    {%- endif %}\n'''\n\ncmake_exe_v2 = \"\"\"cmake_minimum_required(VERSION 3.15)\nproject({{name}} CXX)\n\n{% if requires is defined -%}\n{% for require in requires -%}\nfind_package({{as_name(require)}} CONFIG REQUIRED)\n{% endfor %}\n{%- endif %}\n\nadd_executable({{name}} src/{{name}}.cpp src/main.cpp)\n\n{% if requires is defined -%}\n{% for require in requires -%}\ntarget_link_libraries({{name}} PRIVATE {{as_name(require)}}::{{as_name(require)}})\n{% endfor %}\n{%- endif %}\n\ninstall(TARGETS {{name}} DESTINATION \".\"\n        RUNTIME DESTINATION bin\n        ARCHIVE DESTINATION lib\n        LIBRARY DESTINATION lib\n        )\n\"\"\"\n\ntest_conanfile_exe_v2 = \"\"\"import os\nfrom conan import ConanFile\nfrom conan.tools.build import can_run\n\n\nclass {{package_name}}TestConan(ConanFile):\n    settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n    def requirements(self):\n        self.requires(self.tested_reference_str)\n\n    def test(self):\n        if can_run(self):\n            self.run(\"{{name}}\", env=\"conanrun\")\n\"\"\"\n\ncmake_exe_files = {\"conanfile.py\": conanfile_exe,\n                   \"src/{{name}}.cpp\": source_cpp,\n                   \"src/{{name}}.h\": source_h,\n                   \"src/main.cpp\": test_main,\n                   \"CMakeLists.txt\": cmake_exe_v2,\n                   \"test_package/conanfile.py\": test_conanfile_exe_v2\n                   }\n"
  },
  {
    "path": "conan/internal/api/new/cmake_lib.py",
    "content": "conanfile_sources_v2 = '''from conan import ConanFile\nfrom conan.tools.cmake import CMakeToolchain, CMake, cmake_layout, CMakeDeps\n\n\nclass {{package_name}}Recipe(ConanFile):\n    name = \"{{name}}\"\n    version = \"{{version}}\"\n    package_type = \"library\"\n\n    # Optional metadata\n    license = \"<Put the package license here>\"\n    author = \"<Put your name here> <And your email here>\"\n    url = \"<Package recipe repository url here, for issues about the package>\"\n    description = \"<Description of {{ name }} package here>\"\n    topics = (\"<Put some tag here>\", \"<here>\", \"<and here>\")\n\n    # Binary configuration\n    settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n    options = {\"shared\": [True, False], \"fPIC\": [True, False]}\n    default_options = {\"shared\": False, \"fPIC\": True}\n\n    # Sources are located in the same place as this recipe, copy them to the recipe\n    exports_sources = \"CMakeLists.txt\", \"src/*\", \"include/*\"\n\n    def config_options(self):\n        if self.settings.os == \"Windows\":\n            self.options.rm_safe(\"fPIC\")\n\n    def configure(self):\n        if self.options.shared:\n            self.options.rm_safe(\"fPIC\")\n\n    def layout(self):\n        cmake_layout(self)\n    {% if requires is defined %}\n    def requirements(self):\n        {% for require in requires -%}\n        self.requires(\"{{ require }}\")\n        {% endfor %}\n    {%- endif %}\n    {%- if tool_requires is defined %}\n    def build_requirements(self):\n        {% for require in tool_requires -%}\n        self.tool_requires(\"{{ require }}\")\n        {% endfor %}\n    {%- endif %}\n    def generate(self):\n        deps = CMakeDeps(self)\n        deps.generate()\n        tc = CMakeToolchain(self)\n        tc.generate()\n\n    def build(self):\n        cmake = CMake(self)\n        cmake.configure()\n        cmake.build()\n\n    def package(self):\n        cmake = CMake(self)\n        cmake.install()\n\n    def package_info(self):\n        self.cpp_info.libs = [\"{{name}}\"]\n\n'''\n\ncmake_v2 = \"\"\"cmake_minimum_required(VERSION 3.15)\nproject({{name}} CXX)\n\n{% if requires is defined -%}\n{% for require in requires -%}\nfind_package({{as_name(require)}} CONFIG REQUIRED)\n{% endfor %}\n{%- endif %}\n\n\nadd_library({{name}} src/{{name}}.cpp)\ntarget_include_directories({{name}} PUBLIC include)\n\n{% if requires is defined -%}\n{% for require in requires -%}\ntarget_link_libraries({{name}} PRIVATE {{as_name(require)}}::{{as_name(require)}})\n{% endfor %}\n{%- endif %}\n\nset_target_properties({{name}} PROPERTIES PUBLIC_HEADER \"include/{{name}}.h\")\ninstall(TARGETS {{name}})\n\"\"\"\n\nsource_h = \"\"\"#pragma once\n\n#include <vector>\n#include <string>\n\n{% set define_name = package_name.upper() %}\n#ifdef _WIN32\n  #define {{define_name}}_EXPORT __declspec(dllexport)\n#else\n  #define {{define_name}}_EXPORT\n#endif\n\n{{define_name}}_EXPORT void {{package_name}}();\n{{define_name}}_EXPORT void {{package_name}}_print_vector(const std::vector<std::string> &strings);\n\"\"\"\n\nsource_cpp = r\"\"\"#include <iostream>\n#include \"{{name}}.h\"\n{% if requires is defined -%}\n{% for require in requires -%}\n#include \"{{ as_name(require) }}.h\"\n{% endfor %}\n{%- endif %}\n\n\nvoid {{package_name}}(){\n    {% if requires is defined -%}\n    {% for require in requires -%}\n    {{ as_name(require).replace(\".\", \"_\") }}();\n    {% endfor %}\n    {%- endif %}\n\n    #ifdef NDEBUG\n    std::cout << \"{{name}}/{{version}}: Hello World Release!\\n\";\n    #else\n    std::cout << \"{{name}}/{{version}}: Hello World Debug!\\n\";\n    #endif\n\n    // ARCHITECTURES\n    #ifdef _M_X64\n    std::cout << \"  {{name}}/{{version}}: _M_X64 defined\\n\";\n    #endif\n\n    #ifdef _M_IX86\n    std::cout << \"  {{name}}/{{version}}: _M_IX86 defined\\n\";\n    #endif\n\n    #ifdef _M_ARM64\n    std::cout << \"  {{name}}/{{version}}: _M_ARM64 defined\\n\";\n    #endif\n\n    #if __i386__\n    std::cout << \"  {{name}}/{{version}}: __i386__ defined\\n\";\n    #endif\n\n    #if __x86_64__\n    std::cout << \"  {{name}}/{{version}}: __x86_64__ defined\\n\";\n    #endif\n\n    #if __aarch64__\n    std::cout << \"  {{name}}/{{version}}: __aarch64__ defined\\n\";\n    #endif\n\n    // Libstdc++\n    #if defined _GLIBCXX_USE_CXX11_ABI\n    std::cout << \"  {{name}}/{{version}}: _GLIBCXX_USE_CXX11_ABI \"<< _GLIBCXX_USE_CXX11_ABI << \"\\n\";\n    #endif\n\n    // MSVC runtime\n    #if defined(_DEBUG)\n        #if defined(_MT) && defined(_DLL)\n        std::cout << \"  {{name}}/{{version}}: MSVC runtime: MultiThreadedDebugDLL\\n\";\n        #elif defined(_MT)\n        std::cout << \"  {{name}}/{{version}}: MSVC runtime: MultiThreadedDebug\\n\";\n        #endif\n    #else\n        #if defined(_MT) && defined(_DLL)\n        std::cout << \"  {{name}}/{{version}}: MSVC runtime: MultiThreadedDLL\\n\";\n        #elif defined(_MT)\n        std::cout << \"  {{name}}/{{version}}: MSVC runtime: MultiThreaded\\n\";\n        #endif\n    #endif\n\n    // COMPILER VERSIONS\n    #if _MSC_VER\n    std::cout << \"  {{name}}/{{version}}: _MSC_VER\" << _MSC_VER<< \"\\n\";\n    #endif\n\n    #if _MSVC_LANG\n    std::cout << \"  {{name}}/{{version}}: _MSVC_LANG\" << _MSVC_LANG<< \"\\n\";\n    #endif\n\n    #if __cplusplus\n    std::cout << \"  {{name}}/{{version}}: __cplusplus\" << __cplusplus<< \"\\n\";\n    #endif\n\n    #if __INTEL_COMPILER\n    std::cout << \"  {{name}}/{{version}}: __INTEL_COMPILER\" << __INTEL_COMPILER<< \"\\n\";\n    #endif\n\n    #if __GNUC__\n    std::cout << \"  {{name}}/{{version}}: __GNUC__\" << __GNUC__<< \"\\n\";\n    #endif\n\n    #if __GNUC_MINOR__\n    std::cout << \"  {{name}}/{{version}}: __GNUC_MINOR__\" << __GNUC_MINOR__<< \"\\n\";\n    #endif\n\n    #if __clang_major__\n    std::cout << \"  {{name}}/{{version}}: __clang_major__\" << __clang_major__<< \"\\n\";\n    #endif\n\n    #if __clang_minor__\n    std::cout << \"  {{name}}/{{version}}: __clang_minor__\" << __clang_minor__<< \"\\n\";\n    #endif\n\n    #if __apple_build_version__\n    std::cout << \"  {{name}}/{{version}}: __apple_build_version__\" << __apple_build_version__<< \"\\n\";\n    #endif\n\n    // SUBSYSTEMS\n\n    #if __MSYS__\n    std::cout << \"  {{name}}/{{version}}: __MSYS__\" << __MSYS__<< \"\\n\";\n    #endif\n\n    #if __MINGW32__\n    std::cout << \"  {{name}}/{{version}}: __MINGW32__\" << __MINGW32__<< \"\\n\";\n    #endif\n\n    #if __MINGW64__\n    std::cout << \"  {{name}}/{{version}}: __MINGW64__\" << __MINGW64__<< \"\\n\";\n    #endif\n\n    #if __CYGWIN__\n    std::cout << \"  {{name}}/{{version}}: __CYGWIN__\" << __CYGWIN__<< \"\\n\";\n    #endif\n}\n\nvoid {{package_name}}_print_vector(const std::vector<std::string> &strings) {\n    for(std::vector<std::string>::const_iterator it = strings.begin(); it != strings.end(); ++it) {\n        std::cout << \"{{package_name}}/{{version}} \" << *it << std::endl;\n    }\n}\n\"\"\"\n\n\ntest_conanfile_v2 = \"\"\"import os\n\nfrom conan import ConanFile\nfrom conan.tools.cmake import CMake, cmake_layout\nfrom conan.tools.build import can_run\n\n\nclass {{package_name}}TestConan(ConanFile):\n    settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n    generators = \"CMakeDeps\", \"CMakeToolchain\"\n\n    def requirements(self):\n        self.requires(self.tested_reference_str)\n\n    def build(self):\n        cmake = CMake(self)\n        cmake.configure()\n        cmake.build()\n\n    def layout(self):\n        cmake_layout(self)\n\n    def test(self):\n        if can_run(self):\n            cmd = os.path.join(self.cpp.build.bindir, \"example\")\n            self.run(cmd, env=\"conanrun\")\n\"\"\"\n\ntest_cmake_v2 = \"\"\"cmake_minimum_required(VERSION 3.15)\nproject(PackageTest CXX)\n\nfind_package({{name}} CONFIG REQUIRED)\n\nadd_executable(example src/example.cpp)\ntarget_link_libraries(example {{name}}::{{name}})\n\"\"\"\n\n\ntest_main = \"\"\"#include \"{{name}}.h\"\n#include <vector>\n#include <string>\n\nint main() {\n    {{package_name}}();\n\n    std::vector<std::string> vec;\n    vec.push_back(\"test_package\");\n\n    {{package_name}}_print_vector(vec);\n}\n\"\"\"\n\ncmake_lib_files = {\"conanfile.py\": conanfile_sources_v2,\n                   \"src/{{name}}.cpp\": source_cpp,\n                   \"include/{{name}}.h\": source_h,\n                   \"CMakeLists.txt\": cmake_v2,\n                   \"test_package/conanfile.py\": test_conanfile_v2,\n                   \"test_package/src/example.cpp\": test_main,\n                   \"test_package/CMakeLists.txt\": test_cmake_v2}\n"
  },
  {
    "path": "conan/internal/api/new/header_lib.py",
    "content": "conanfile_sources_v2 = '''from conan import ConanFile\nfrom conan.tools.layout import basic_layout\nfrom conan.tools.files import copy\n\nclass {{package_name}}Recipe(ConanFile):\n    name = \"{{name}}\"\n    version = \"{{version}}\"\n    package_type = \"header-library\"\n\n    # Optional metadata\n    license = \"<Put the package license here>\"\n    author = \"<Put your name here> <And your email here>\"\n    url = \"<Package recipe repository url here, for issues about the package>\"\n    description = \"<Description of {{ name }} package here>\"\n    topics = (\"<Put some tag here>\", \"<here>\", \"<and here>\")\n\n    # Sources are located in the same place as this recipe, copy them to the recipe\n    exports_sources = \"include/*\"\n\n    # Automatically manage the package ID clearing of settings and options\n    implements = [\"auto_header_only\"]\n\n    def layout(self):\n        basic_layout(self)\n    {% if requires is defined %}\n    def requirements(self):\n        {% for require in requires -%}\n        self.requires(\"{{ require }}\")\n        {% endfor %}\n    {%- endif %}\n\n    def package(self):\n        copy(self, \"include/*\", self.source_folder, self.package_folder)\n\n    def package_info(self):\n        self.cpp_info.bindirs = []\n        self.cpp_info.libdirs = []\n\n'''\n\nsource_h = \"\"\"#pragma once\n\n#include <iostream>\n#include <vector>\n#include <string>\n\n{% if requires is defined -%}\n{% for require in requires -%}\n#include \"{{ as_name(require) }}.h\"\n{% endfor %}\n{%- endif %}\n\nvoid {{package_name}}(){\n    {% if requires is defined -%}\n    {% for require in requires -%}\n    {{ as_name(require).replace(\".\", \"_\") }}();\n    {% endfor %}\n    {%- endif %}\n\n    std::cout << \"{{package_name}}/{{version}} header only called\" << std::endl;\n}\n\n\"\"\"\n\ntest_conanfile_v2 = \"\"\"import os\n\nfrom conan import ConanFile\nfrom conan.tools.cmake import CMake, cmake_layout\nfrom conan.tools.build import can_run\n\n\nclass {{package_name}}TestConan(ConanFile):\n    settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n    generators = \"CMakeDeps\", \"CMakeToolchain\"\n\n    def requirements(self):\n        self.requires(self.tested_reference_str)\n\n    def build(self):\n        cmake = CMake(self)\n        cmake.configure()\n        cmake.build()\n\n    def layout(self):\n        cmake_layout(self)\n\n    def test(self):\n        if can_run(self):\n            cmd = os.path.join(self.cpp.build.bindir, \"example\")\n            self.run(cmd, env=\"conanrun\")\n\"\"\"\n\ntest_cmake_v2 = \"\"\"cmake_minimum_required(VERSION 3.15)\nproject(PackageTest CXX)\n\nfind_package({{name}} CONFIG REQUIRED)\n\nadd_executable(example src/example.cpp)\ntarget_link_libraries(example {{name}}::{{name}})\n\"\"\"\n\n\ntest_main = \"\"\"#include \"{{name}}.h\"\n#include <vector>\n#include <string>\n\nint main() {\n    {{package_name}}();\n}\n\"\"\"\n\nheader_only_lib_files = {\"conanfile.py\": conanfile_sources_v2,\n                         \"include/{{name}}.h\": source_h,\n                         \"test_package/conanfile.py\": test_conanfile_v2,\n                         \"test_package/src/example.cpp\": test_main,\n                         \"test_package/CMakeLists.txt\": test_cmake_v2}\n"
  },
  {
    "path": "conan/internal/api/new/local_recipes_index.py",
    "content": "from conan.internal.api.new.cmake_lib import test_conanfile_v2, test_cmake_v2\n\nconfig_yml = \"\"\"\\\nversions:\n  \"{{version}}\":\n    folder: all\n\"\"\"\n\nconandata_yml = \"\"\"\\\nsources:\n  \"{{version}}\":\n    url:\n      {% if url is defined -%}\n      - \"{{url}}\"\n      {% else -%}\n      - \"http://put/here/the/url/to/release.1.2.3.zip\"\n      {% endif %}\n    {% if sha256 is defined -%}\n    sha256: \"{{sha256}}\"\n    {%- else -%}\n    sha256: \"Put here your tarball sha256\"\n    {% endif -%}\n\"\"\"\n\n\nconanfile = \"\"\"\\\nfrom conan import ConanFile\nfrom conan.tools.cmake import CMakeToolchain, CMake, cmake_layout, CMakeDeps\nfrom conan.tools.files import apply_conandata_patches, export_conandata_patches, get\n\n\nclass {{package_name}}Recipe(ConanFile):\n    name = \"{{name}}\"\n    package_type = \"library\"\n\n    # Optional metadata\n    license = \"<Put the package license here>\"\n    author = \"<Put your name here> <And your email here>\"\n    url = \"<Package recipe repository url here, for issues about the package>\"\n    description = \"<Description of {{ name }} package here>\"\n    topics = (\"<Put some tag here>\", \"<here>\", \"<and here>\")\n\n    # Binary configuration\n    settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n    options = {\"shared\": [True, False], \"fPIC\": [True, False]}\n    default_options = {\"shared\": False, \"fPIC\": True}\n\n    def config_options(self):\n        if self.settings.os == \"Windows\":\n            self.options.rm_safe(\"fPIC\")\n\n    def configure(self):\n        if self.options.shared:\n            self.options.rm_safe(\"fPIC\")\n\n    def export_sources(self):\n        export_conandata_patches(self)\n\n    def source(self):\n        get(self, **self.conan_data[\"sources\"][self.version], destination=self.source_folder,\n            strip_root=True)\n        apply_conandata_patches(self)\n\n    def layout(self):\n        cmake_layout(self, src_folder=\"src\")\n\n    def generate(self):\n        deps = CMakeDeps(self)\n        deps.generate()\n        tc = CMakeToolchain(self)\n        tc.generate()\n\n    def build(self):\n        cmake = CMake(self)\n        cmake.configure()\n        cmake.build()\n\n    def package(self):\n        cmake = CMake(self)\n        cmake.install()\n\n    def package_info(self):\n        self.cpp_info.libs = [\"{{name}}\"]\n\n    {% if requires is defined -%}\n    def requirements(self):\n        {% for require in requires -%}\n        self.requires(\"{{ require }}\")\n        {% endfor %}\n    {%- endif %}\n\n    {% if tool_requires is defined -%}\n    def build_requirements(self):\n        {% for require in tool_requires -%}\n        self.tool_requires(\"{{ require }}\")\n        {% endfor %}\n    {%- endif %}\n\"\"\"\n\n\ntest_main = \"\"\"#include \"{{name}}.h\"\n\nint main() {\n    {{package_name}}();\n}\n\"\"\"\n\nlocal_recipes_index_files = {\"recipes/{{name}}/config.yml\": config_yml,\n                             \"recipes/{{name}}/all/conandata.yml\": conandata_yml,\n                             \"recipes/{{name}}/all/conanfile.py\": conanfile,\n                             \"recipes/{{name}}/all/test_package/conanfile.py\": test_conanfile_v2,\n                             \"recipes/{{name}}/all/test_package/CMakeLists.txt\": test_cmake_v2,\n                             \"recipes/{{name}}/all/test_package/src/example.cpp\": test_main}\n"
  },
  {
    "path": "conan/internal/api/new/meson_exe.py",
    "content": "from conan.internal.api.new.cmake_lib import source_cpp, source_h, test_main\n\nconanfile_exe = \"\"\"from conan import ConanFile\nfrom conan.tools.meson import MesonToolchain, Meson\nfrom conan.tools.gnu import PkgConfigDeps\n\n\nclass {{package_name}}Conan(ConanFile):\n    name = \"{{name}}\"\n    version = \"{{version}}\"\n    package_type = \"application\"\n\n    # Binary configuration\n    settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n    # Sources are located in the same place as this recipe, copy them to the recipe\n    exports_sources = \"meson.build\", \"src/*\"\n\n    {% if requires is defined -%}\n    def requirements(self):\n        {% for require in requires -%}\n        self.requires(\"{{ require }}\")\n        {% endfor %}\n    {%- endif %}\n\n    def layout(self):\n        self.folders.build = \"build\"\n\n    def generate(self):\n        deps = PkgConfigDeps(self)\n        deps.generate()\n        tc = MesonToolchain(self)\n        tc.generate()\n\n    def build(self):\n        meson = Meson(self)\n        meson.configure()\n        meson.build()\n\n    def package(self):\n        meson = Meson(self)\n        meson.install()\n\"\"\"\n\ntest_conanfile_exe_v2 = \"\"\"import os\nfrom conan import ConanFile\nfrom conan.tools.build import can_run\n\n\nclass {{package_name}}TestConan(ConanFile):\n    settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n    def requirements(self):\n        self.requires(self.tested_reference_str)\n\n    def test(self):\n        if can_run(self):\n            self.run(\"{{name}}\", env=\"conanrun\")\n\"\"\"\n\n_meson_build_exe = \"\"\"\\\nproject('{{name}} ', 'cpp')\n{% if requires is defined -%}\ncxx = meson.get_compiler('cpp')\n{% for require in requires -%}\n{{as_name(require)}} = dependency('{{as_name(require)}}', required: true)\n{% endfor %}\n{%- endif %}\n{% if requires is defined -%}\nexecutable('{{name}}', 'src/{{name}}.cpp', 'src/main.cpp', install: true,\n           dependencies:  {{ names(requires) }} )\n{% else %}\nexecutable('{{name}}', 'src/{{name}}.cpp', 'src/main.cpp', install: true)\n{% endif %}\n\"\"\"\n\nmeson_exe_files = {\"conanfile.py\": conanfile_exe,\n                   \"src/{{name}}.cpp\": source_cpp,\n                   \"src/{{name}}.h\": source_h,\n                   \"src/main.cpp\": test_main,\n                   \"meson.build\": _meson_build_exe,\n                   \"test_package/conanfile.py\": test_conanfile_exe_v2\n                   }\n"
  },
  {
    "path": "conan/internal/api/new/meson_lib.py",
    "content": "from conan.internal.api.new.cmake_lib import source_cpp, source_h, test_main\n\nconanfile_sources_v2 = \"\"\"import os\nfrom conan import ConanFile\nfrom conan.tools.meson import MesonToolchain, Meson\nfrom conan.tools.layout import basic_layout\nfrom conan.tools.files import copy\n{% if requires is defined %}\nfrom conan.tools.gnu import PkgConfigDeps\n{% endif %}\n\n\nclass {{package_name}}Conan(ConanFile):\n    name = \"{{name}}\"\n    version = \"{{version}}\"\n    package_type = \"library\"\n\n    # Binary configuration\n    settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n    options = {\"shared\": [True, False], \"fPIC\": [True, False]}\n    default_options = {\"shared\": False, \"fPIC\": True}\n\n    # Sources are located in the same place as this recipe, copy them to the recipe\n    exports_sources = \"meson.build\", \"src/*\"\n\n    def config_options(self):\n        if self.settings.os == \"Windows\":\n            self.options.rm_safe(\"fPIC\")\n\n    def configure(self):\n        if self.options.shared:\n            self.options.rm_safe(\"fPIC\")\n\n    def layout(self):\n        basic_layout(self)\n\n    {% if requires is defined %}\n    def requirements(self):\n        {% for require in requires -%}\n        self.requires(\"{{ require }}\")\n        {% endfor %}\n    {%- endif %}\n\n    def generate(self):\n        {% if requires is defined %}\n        deps = PkgConfigDeps(self)\n        deps.generate()\n        {%- endif %}\n        tc = MesonToolchain(self)\n        tc.generate()\n\n    def build(self):\n        meson = Meson(self)\n        meson.configure()\n        meson.build()\n\n    def package(self):\n        meson = Meson(self)\n        meson.install()\n\n    def package_info(self):\n        self.cpp_info.libs = [\"{{name}}\"]\n\"\"\"\n\n\ntest_conanfile_v2 = \"\"\"import os\nfrom conan import ConanFile\nfrom conan.tools.build import can_run\nfrom conan.tools.meson import MesonToolchain, Meson\nfrom conan.tools.layout import basic_layout\n\n\nclass {{package_name}}TestConan(ConanFile):\n    settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n    generators = \"PkgConfigDeps\", \"MesonToolchain\"\n\n    def requirements(self):\n        self.requires(self.tested_reference_str)\n\n    def build(self):\n        meson = Meson(self)\n        meson.configure()\n        meson.build()\n\n    def layout(self):\n        basic_layout(self)\n\n    def test(self):\n        if can_run(self):\n            cmd = os.path.join(self.cpp.build.bindir, \"example\")\n            self.run(cmd, env=\"conanrun\")\n\"\"\"\n\n\n_meson_build_test = \"\"\"\\\nproject('Test{{name}}', 'cpp')\n{{name}} = dependency('{{name}}', version : '>=0.1')\nexecutable('example', 'src/example.cpp', dependencies: {{name}})\n\"\"\"\n\n\n_meson_build = \"\"\"\\\nproject('{{name}} ', 'cpp')\nlibrary('{{name}}', 'src/{{name}}.cpp', install: true)\ninstall_headers('src/{{name}}.h')\n\"\"\"\n\nmeson_lib_files = {\"conanfile.py\": conanfile_sources_v2,\n                   \"src/{{name}}.cpp\": source_cpp,\n                   \"src/{{name}}.h\": source_h,\n                   \"meson.build\": _meson_build,\n                   \"test_package/conanfile.py\": test_conanfile_v2,\n                   \"test_package/src/example.cpp\": test_main,\n                   \"test_package/meson.build\": _meson_build_test}\n"
  },
  {
    "path": "conan/internal/api/new/msbuild_exe.py",
    "content": "from conan.internal.api.new.msbuild_lib import vcxproj, sln_file\n\ntest_main = \"\"\"#include \"{{name}}.h\"\n\nint main() {\n    {{name}}();\n}\n\"\"\"\n\n\nconanfile_exe = \"\"\"import os\n\nfrom conan import ConanFile\nfrom conan.tools.microsoft import MSBuildToolchain, MSBuild, vs_layout\nfrom conan.tools.files import copy\n\n\nclass {{package_name}}Conan(ConanFile):\n    name = \"{{name}}\"\n    version = \"{{version}}\"\n    package_type = \"application\"\n\n    # Binary configuration\n    settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n    # Sources are located in the same place as this recipe, copy them to the recipe\n    exports_sources = \"{{name}}.sln\", \"{{name}}.vcxproj\", \"src/*\"\n\n    def layout(self):\n        vs_layout(self)\n\n    def generate(self):\n        tc = MSBuildToolchain(self)\n        tc.generate()\n\n    def build(self):\n        msbuild = MSBuild(self)\n        msbuild.build(\"{{name}}.sln\")\n\n    def package(self):\n        copy(self, \"*{{name}}.exe\", src=self.build_folder,\n             dst=os.path.join(self.package_folder, \"bin\"), keep_path=False)\n\"\"\"\n\n\ntest_conanfile_exe_v2 = \"\"\"import os\nfrom conan import ConanFile\nfrom conan.tools.build import can_run\nfrom conan.tools.layout import basic_layout\n\n\nclass {{package_name}}TestConan(ConanFile):\n    settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n    def requirements(self):\n        self.requires(self.tested_reference_str)\n\n    def layout(self):\n        basic_layout(self)\n\n    def test(self):\n        if can_run(self):\n            self.run(\"{{name}}\", env=\"conanrun\")\n\"\"\"\n\ntest_exe = r\"\"\"#include <iostream>\n\nint main() {\n    #ifdef NDEBUG\n    std::cout << \"{{name}}/{{version}}: Hello World Release!\\n\";\n    #else\n    std::cout << \"{{name}}/{{version}}: Hello World Debug!\\n\";\n    #endif\n}\n\"\"\"\n\n\nmsbuild_exe_files = {\"conanfile.py\": conanfile_exe,\n                     \"src/{{name}}.cpp\": test_exe,\n                     \"{{name}}.sln\": sln_file.replace(\"test_\", \"\"),\n                     \"{{name}}.vcxproj\": vcxproj.replace(\"TYPE_PLACEHOLDER\", \"Application\")\n                                                .replace(\"DEPENDENCIES\", \"\").replace(\"test_\", \"\"),\n                     \"test_package/conanfile.py\": test_conanfile_exe_v2\n                     }\n"
  },
  {
    "path": "conan/internal/api/new/msbuild_lib.py",
    "content": "from conan.internal.api.new.cmake_lib import source_cpp, source_h, test_main\n\nsln_file = r\"\"\"\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio 15\nVisualStudioVersion = 15.0.28307.757\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"test_{{name}}\", \"test_{{name}}.vcxproj\", \"{6F392A05-B151-490C-9505-B2A49720C4D9}\"\nEndProject\n\nGlobal\n    GlobalSection(SolutionConfigurationPlatforms) = preSolution\n        Debug|x64 = Debug|x64\n        Debug|x86 = Debug|x86\n        Release|x64 = Release|x64\n        Release|x86 = Release|x86\n    EndGlobalSection\n    GlobalSection(ProjectConfigurationPlatforms) = postSolution\n        {6F392A05-B151-490C-9505-B2A49720C4D9}.Debug|x64.ActiveCfg = Debug|x64\n        {6F392A05-B151-490C-9505-B2A49720C4D9}.Debug|x64.Build.0 = Debug|x64\n        {6F392A05-B151-490C-9505-B2A49720C4D9}.Debug|x86.ActiveCfg = Debug|Win32\n        {6F392A05-B151-490C-9505-B2A49720C4D9}.Debug|x86.Build.0 = Debug|Win32\n        {6F392A05-B151-490C-9505-B2A49720C4D9}.Release|x64.ActiveCfg = Release|x64\n        {6F392A05-B151-490C-9505-B2A49720C4D9}.Release|x64.Build.0 = Release|x64\n        {6F392A05-B151-490C-9505-B2A49720C4D9}.Release|x86.ActiveCfg = Release|Win32\n        {6F392A05-B151-490C-9505-B2A49720C4D9}.Release|x86.Build.0 = Release|Win32\n    EndGlobalSection\n    GlobalSection(SolutionProperties) = preSolution\n        HideSolutionNode = FALSE\n    EndGlobalSection\n    GlobalSection(ExtensibilityGlobals) = postSolution\n        SolutionGuid = {DE6E462F-E299-4F9C-951A-F9404EB51521}\n    EndGlobalSection\nEndGlobal\n\"\"\"\n\nvcxproj = r\"\"\"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Debug|x64\">\n      <Configuration>Debug</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|x64\">\n      <Configuration>Release</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <VCProjectVersion>15.0</VCProjectVersion>\n    <ProjectGuid>{6F392A05-B151-490C-9505-B2A49720C4D9}</ProjectGuid>\n    <Keyword>Win32Proj</Keyword>\n    <RootNamespace>test_{{name}}</RootNamespace>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <ImportGroup Label=\"PropertySheets\">\n      <Import Project=\"conan\\conantoolchain.props\" />\n      DEPENDENCIES\n  </ImportGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>TYPE_PLACEHOLDER</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>TYPE_PLACEHOLDER</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\" Label=\"Configuration\">\n    <ConfigurationType>TYPE_PLACEHOLDER</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" Label=\"Configuration\">\n    <ConfigurationType>TYPE_PLACEHOLDER</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Label=\"Shared\">\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\"\n    Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\"\n    Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\"\n    Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\"\n    Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\"\n    Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\"\n    Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\"\n    Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\"\n    Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <LinkIncremental>true</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <LinkIncremental>true</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <LinkIncremental>false</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <LinkIncremental>false</LinkIncremental>\n  </PropertyGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <ClCompile>\n      <PrecompiledHeader>NotUsing</PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>Disabled</Optimization>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)\n      </PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n      <AdditionalIncludeDirectories>include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <ClCompile>\n      <PrecompiledHeader>NotUsing</PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>Disabled</Optimization>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n      <AdditionalIncludeDirectories>include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <ClCompile>\n      <PrecompiledHeader>NotUsing</PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>MaxSpeed</Optimization>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)\n      </PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n      <AdditionalIncludeDirectories>include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <ClCompile>\n      <PrecompiledHeader>NotUsing</PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>MaxSpeed</Optimization>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n      <AdditionalIncludeDirectories>include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <ClCompile Include=\"src/test_{{name}}.cpp\" />\n  </ItemGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n</Project>\n\"\"\"\n\nconanfile_sources_v2 = \"\"\"import os\n\nfrom conan import ConanFile\nfrom conan.tools.microsoft import MSBuildToolchain, MSBuild, vs_layout\nfrom conan.tools.files import copy\n\n\nclass {{package_name}}Conan(ConanFile):\n    name = \"{{name}}\"\n    version = \"{{version}}\"\n\n    # Binary configuration\n    package_type = \"static-library\" # hardcoded in .vcxproj\n    settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n    # Sources are located in the same place as this recipe, copy them to the recipe\n    exports_sources = \"{{name}}.sln\", \"{{name}}.vcxproj\", \"src/*\", \"include/*\"\n\n    def layout(self):\n        vs_layout(self)\n\n    def generate(self):\n        tc = MSBuildToolchain(self)\n        tc.generate()\n\n    def build(self):\n        msbuild = MSBuild(self)\n        msbuild.build(\"{{name}}.sln\")\n\n    def package(self):\n        copy(self, \"*.h\", os.path.join(self.source_folder, \"include\"),\n             dst=os.path.join(self.package_folder, \"include\"))\n        copy(self, \"*.lib\", src=self.build_folder, dst=os.path.join(self.package_folder, \"lib\"),\n             keep_path=False)\n\n    def package_info(self):\n        self.cpp_info.libs = [\"{{name}}\"]\n\"\"\"\n\n\ntest_conanfile_v2 = \"\"\"import os\n\nfrom conan import ConanFile\nfrom conan.tools.microsoft import MSBuildDeps, MSBuildToolchain, MSBuild, vs_layout\nfrom conan.tools.build import can_run\n\n\nclass {{package_name}}TestConan(ConanFile):\n    settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n    generators = \"MSBuildDeps\"\n\n    def requirements(self):\n        self.requires(self.tested_reference_str)\n\n    def layout(self):\n        vs_layout(self)\n\n    def generate(self):\n        tc = MSBuildToolchain(self)\n        tc.generate()\n\n    def build(self):\n        msbuild = MSBuild(self)\n        msbuild.build(\"test_{{name}}.sln\")\n\n    def test(self):\n        if can_run(self):\n            cmd = os.path.join(self.cpp.build.bindir, \"test_{{name}}\")\n            self.run(cmd, env=\"conanrun\")\n\"\"\"\n\n\nmsbuild_lib_files = {\"conanfile.py\": conanfile_sources_v2,\n                     \"src/{{name}}.cpp\": source_cpp,\n                     \"include/{{name}}.h\": source_h,\n                     \"{{name}}.sln\": sln_file.replace(\"test_\", \"\"),\n                     \"{{name}}.vcxproj\": vcxproj.replace(\"TYPE_PLACEHOLDER\", \"StaticLibrary\")\n                                                .replace(\"DEPENDENCIES\", \"\").replace(\"test_\", \"\"),\n                     \"test_package/conanfile.py\": test_conanfile_v2,\n                     \"test_package/src/test_{{name}}.cpp\": test_main,\n                     \"test_package/test_{{name}}.sln\": sln_file,\n                     \"test_package/test_{{name}}.vcxproj\":\n                         vcxproj.replace(\"TYPE_PLACEHOLDER\", \"Application\")\n                         .replace(\"DEPENDENCIES\", r'<Import Project=\"conan\\conandeps.props\" />')\n                     }\n"
  },
  {
    "path": "conan/internal/api/new/premake_exe.py",
    "content": "from conan.internal.api.new.cmake_lib import source_cpp, source_h, test_main\n\nconanfile_exe = \"\"\"import os\nfrom conan import ConanFile\nfrom conan.tools.files import copy\nfrom conan.tools.layout import basic_layout\nfrom conan.tools.premake import PremakeDeps, PremakeToolchain, Premake\n\n\nclass {{package_name}}Recipe(ConanFile):\n    name = \"{{name}}\"\n    version = \"{{version}}\"\n    package_type = \"application\"\n\n    # Optional metadata\n    license = \"<Put the package license here>\"\n    author = \"<Put your name here> <And your email here>\"\n    url = \"<Package recipe repository url here, for issues about the package>\"\n    description = \"<Description of {{ name }} package here>\"\n    topics = (\"<Put some tag here>\", \"<here>\", \"<and here>\")\n\n    # Binary configuration\n    settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n    # Sources are located in the same place as this recipe, copy them to the recipe\n    exports_sources = \"premake5.lua\", \"src/*\"\n\n    def layout(self):\n        basic_layout(self)\n\n    def generate(self):\n        deps = PremakeDeps(self)\n        deps.generate()\n        tc = PremakeToolchain(self)\n        tc.generate()\n\n    def build(self):\n        premake = Premake(self)\n        premake.configure()\n        premake.build(workspace=\"{{name.capitalize()}}\")\n\n    def package(self):\n        dest_bin = os.path.join(self.package_folder, \"bin\")\n        build = os.path.join(self.build_folder, \"bin\")\n        copy(self, \"{{name}}\", build, dest_bin, keep_path=False)\n        copy(self, \"{{name}}.exe\", build, dest_bin, keep_path=False)\n\n\n    {% if requires is defined -%}\n    def requirements(self):\n        {% for require in requires -%}\n        self.requires(\"{{ require }}\")\n        {% endfor %}\n    {%- endif %}\n\n    {% if tool_requires is defined -%}\n    def build_requirements(self):\n        {% for require in tool_requires -%}\n        self.tool_requires(\"{{ require }}\")\n        {% endfor %}\n    {%- endif %}\n\"\"\"\n\npremake5 = \"\"\"workspace \"{{name.capitalize()}}\"\n   configurations { \"Debug\", \"Release\" }\n\nproject \"{{name}}\"\n    kind \"ConsoleApp\"\n    language \"C++\"\n    files { \"src/main.cpp\", \"src/{{name}}.cpp\", \"src/{{name}}.h\" }\n\n    filter \"configurations:Debug\"\n       defines { \"DEBUG\" }\n       symbols \"On\"\n\n    filter \"configurations:Release\"\n       defines { \"NDEBUG\" }\n       optimize \"On\"\n\"\"\"\n\ntest_conanfile_exe_v2 = \"\"\"\nfrom conan import ConanFile\nfrom conan.tools.build import can_run\n\n\nclass {{package_name}}TestConan(ConanFile):\n    settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n    def requirements(self):\n        self.requires(self.tested_reference_str)\n\n    def test(self):\n        if can_run(self):\n            self.run(\"{{name}}\", env=\"conanrun\")\n\"\"\"\n\npremake_exe_files = {\n    \"conanfile.py\": conanfile_exe,\n    \"src/{{name}}.cpp\": source_cpp,\n    \"src/{{name}}.h\": source_h,\n    \"src/main.cpp\": test_main,\n    \"premake5.lua\": premake5,\n    \"test_package/conanfile.py\": test_conanfile_exe_v2,\n}\n"
  },
  {
    "path": "conan/internal/api/new/premake_lib.py",
    "content": "from conan.internal.api.new.cmake_lib import source_cpp, source_h, test_main\n\nconanfile_sources = \"\"\"import os\nfrom conan import ConanFile\nfrom conan.tools.files import copy\nfrom conan.tools.layout import basic_layout\nfrom conan.tools.premake import PremakeDeps, PremakeToolchain, Premake\n\n\nclass {{package_name}}Recipe(ConanFile):\n    name = \"{{name}}\"\n    version = \"{{version}}\"\n    package_type = \"library\"\n\n    # Optional metadata\n    license = \"<Put the package license here>\"\n    author = \"<Put your name here> <And your email here>\"\n    url = \"<Package recipe repository url here, for issues about the package>\"\n    description = \"<Description of {{ name }} package here>\"\n    topics = (\"<Put some tag here>\", \"<here>\", \"<and here>\")\n\n    # Binary configuration\n    settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n    options = {\"shared\": [True, False], \"fPIC\": [True, False]}\n    default_options = {\"shared\": False, \"fPIC\": True}\n    implements = [\"auto_shared_fpic\"]\n\n    # Sources are located in the same place as this recipe, copy them to the recipe\n    exports_sources = \"premake5.lua\", \"src/*\", \"include/*\"\n\n    def layout(self):\n        basic_layout(self)\n    {% if requires is defined %}\n    def requirements(self):\n        {% for require in requires -%}\n        self.requires(\"{{ require }}\")\n        {% endfor %}\n    {%- endif %}\n    {%- if tool_requires is defined %}\n    def build_requirements(self):\n        {% for require in tool_requires -%}\n        self.tool_requires(\"{{ require }}\")\n        {% endfor %}\n    {%- endif %}\n    def generate(self):\n        deps = PremakeDeps(self)\n        deps.generate()\n        tc = PremakeToolchain(self)\n        tc.generate()\n\n    def build(self):\n        premake = Premake(self)\n        premake.configure()\n        premake.build(workspace=\"{{name.capitalize()}}\")\n\n    def package(self):\n        copy(self, \"*.h\", os.path.join(self.source_folder, \"include\"), os.path.join(self.package_folder, \"include\"))\n\n        for pattern in (\"*.lib\", \"*.a\", \"*.so*\", \"*.dylib\"):\n            copy(self, pattern, os.path.join(self.build_folder, \"bin\"), os.path.join(self.package_folder, \"lib\"))\n        copy(self, \"*.dll\", os.path.join(self.build_folder, \"bin\"), os.path.join(self.package_folder, \"bin\"))\n\n    def package_info(self):\n        self.cpp_info.libs = [\"{{name}}\"]\n\"\"\"\n\npremake5 = \"\"\"workspace \"{{name.capitalize()}}\"\n    configurations { \"Debug\", \"Release\" }\n    fatalwarnings {\"All\"}\n    floatingpoint \"Fast\"\n    includedirs { \".\", \"src\", \"include\" }\n\nproject \"{{name}}\"\n    cppdialect \"C++17\"\n\n    -- To let conan take control over `kind` of the libraries, DO NOT SET `kind` (StaticLib or\n    -- SharedLib) in `project` block.\n    -- kind \"<controlled by conan>\"\n\n    language \"C++\"\n    files { \"include/*.hpp\", \"include/*.h\", \"src/*.cpp\" }\n\n    filter \"configurations:Debug\"\n       defines { \"DEBUG\" }\n       symbols \"On\"\n\n    filter \"configurations:Release\"\n       defines { \"NDEBUG\" }\n       optimize \"On\"\n\n\"\"\"\n\ntest_conanfile = \"\"\"import os\n\nfrom conan import ConanFile\nfrom conan.tools.layout import basic_layout\nfrom conan.tools.premake import Premake\nfrom conan.tools.build import can_run\n\n\nclass {{package_name}}TestConan(ConanFile):\n    settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n    generators = \"PremakeDeps\", \"PremakeToolchain\"\n\n    def layout(self):\n        basic_layout(self)\n\n    def requirements(self):\n        self.requires(self.tested_reference_str)\n\n    def build(self):\n        premake = Premake(self)\n        premake.configure()\n        premake.build(workspace=\"Example\")\n\n    def test(self):\n        if can_run(self):\n            cmd = os.path.join(self.cpp.build.bindir, \"bin\", \"example\")\n            self.run(cmd, env=\"conanrun\")\n\"\"\"\n\ntest_premake5 = \"\"\"workspace \"Example\"\n   configurations { \"Debug\", \"Release\" }\n\nproject \"example\"\n   kind \"ConsoleApp\"\n   language \"C++\"\n   files { \"src/example.cpp\" }\n\n   filter \"configurations:Debug\"\n      defines { \"DEBUG\" }\n      symbols \"On\"\n\n   filter \"configurations:Release\"\n      defines { \"NDEBUG\" }\n      optimize \"On\"\n\"\"\"\n\n\npremake_lib_files = {\n    \"conanfile.py\": conanfile_sources,\n    \"src/{{name}}.cpp\": source_cpp,\n    \"include/{{name}}.h\": source_h,\n    \"premake5.lua\": premake5,\n    \"test_package/conanfile.py\": test_conanfile,\n    \"test_package/src/example.cpp\": test_main,\n    \"test_package/premake5.lua\": test_premake5,\n}\n"
  },
  {
    "path": "conan/internal/api/new/qbs_lib.py",
    "content": "from conan.internal.api.new.cmake_lib import source_cpp, source_h, test_main\n\n\nconanfile_sources = '''\nimport os\n\nfrom conan import ConanFile\nfrom conan.tools.qbs import Qbs\n\n\nclass {{package_name}}Recipe(ConanFile):\n    name = \"{{name}}\"\n    version = \"{{version}}\"\n\n    exports_sources = \"*.cpp\", \"*.h\", \"*.qbs\"\n    settings = \"os\", \"compiler\", \"arch\"\n    options = {\"shared\": [True, False]}\n    default_options = {\"shared\": False}\n\n    def build(self):\n        qbs = Qbs(self)\n        qbs_config = {\"products.{{name}}.isShared\": \"true\" if self.options.shared else \"false\"}\n        qbs.add_configuration(\"default\", qbs_config)\n        qbs.resolve()\n        qbs.build()\n\n    def package(self):\n        qbs = Qbs(self)\n        qbs.install()\n\n    def package_info(self):\n        self.cpp_info.libs = [\"{{name}}\"]\n'''\n\nqbs_lib_file = '''\n    Library {\n        property bool isShared: true\n        name: \"{{name}}\"\n        type: isShared ? \"dynamiclibrary\" : \"staticlibrary\"\n        files: [ \"{{name}}.cpp\" ]\n        Group {\n            name: \"headers\"\n            files: [ \"{{name}}.h\" ]\n            qbs.install: true\n            qbs.installDir: \"include\"\n        }\n        Depends { name: \"cpp\" }\n        Depends { name: \"bundle\" }\n        bundle.isBundle: false\n        install: true\n        qbs.installPrefix: \"\"\n    }\n'''\n\ntest_conanfile_v2 = \"\"\"import os\n\nfrom conan import ConanFile\nfrom conan.tools.build import can_run\nfrom conan.tools.qbs import Qbs\nfrom conan.tools.build import cmd_args_to_string\n\nclass {{package_name}}TestConan(ConanFile):\n    settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n    generators = \"PkgConfigDeps\"\n\n    def requirements(self):\n        self.requires(self.tested_reference_str)\n\n    def build(self):\n        qbs = Qbs(self)\n        qbs.resolve()\n        qbs.build()\n        qbs.install()\n\n    def test(self):\n        if can_run(self):\n            cmd = os.path.join(self.package_folder, \"bin\", \"example\")\n            self.run(cmd_args_to_string([cmd]), env=\"conanrun\")\n\"\"\"\n\nqbs_test_file = '''\n    Application {\n        name: \"example\"\n        consoleApplication: true\n        files: [ \"example.cpp\" ]\n        Depends { name: \"cpp\" }\n        install: true\n        qbs.installPrefix: \"\"\n        // external dependency via pkg-config\n        qbsModuleProviders: [\"qbspkgconfig\"]\n        moduleProviders.qbspkgconfig.libDirs: path\n        Depends { name: \"{{name}}\" }\n    }\n'''\n\nqbs_lib_files = {\"conanfile.py\": conanfile_sources,\n                 \"{{name}}.qbs\": qbs_lib_file,\n                 \"{{name}}.cpp\": source_cpp,\n                 \"{{name}}.h\": source_h,\n                 \"test_package/conanfile.py\": test_conanfile_v2,\n                 \"test_package/example.cpp\": test_main,\n                 \"test_package/example.qbs\": qbs_test_file}\n"
  },
  {
    "path": "conan/internal/api/new/workspace.py",
    "content": "from conan.api.subapi.new import NewAPI\nfrom conan.internal.api.new.cmake_exe import cmake_exe_files\nfrom conan.internal.api.new.cmake_lib import cmake_lib_files\n\n\nconanws_yml = \"\"\"\\\npackages:\n  - path: liba\n    ref: liba/0.1\n  - path: libb\n    ref: libb/0.1\n  - path: app1\n    ref: app1/0.1\n\"\"\"\n\ncmake = \"\"\"\\\ncmake_minimum_required(VERSION 3.25)\nproject(monorepo CXX)\n\ninclude(FetchContent)\n\nfunction(add_project PACKAGE_NAME SUBFOLDER)\n    message(STATUS \"Adding project: ${PACKAGE_NAME}. Folder: ${SUBFOLDER}\")\n    FetchContent_Declare(\n        ${PACKAGE_NAME}\n        SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/${SUBFOLDER}\n        SYSTEM\n        OVERRIDE_FIND_PACKAGE\n    )\n    FetchContent_MakeAvailable(${PACKAGE_NAME})\nendfunction()\n\ninclude(build/conanws_build_order.cmake)\n\nforeach(pair ${CONAN_WS_BUILD_ORDER})\n    string(FIND \"${pair}\" \":\" pos)\n    string(SUBSTRING \"${pair}\" 0 \"${pos}\" pkg)\n    math(EXPR pos \"${pos} + 1\")  # Skip the separator\n    string(SUBSTRING \"${pair}\" \"${pos}\" -1 folder)\n\n    add_project(${pkg} ${folder})\n    # This target should be defined in the liba/CMakeLists.txt, but we can fix it here\n    get_target_property(target_type ${pkg} TYPE)\n    if (NOT target_type STREQUAL \"EXECUTABLE\")\n        add_library(${pkg}::${pkg} ALIAS ${pkg})\n    endif()\nendforeach()\n\"\"\"\n\nconanfile = r'''\\\nimport json\nfrom conan import Workspace\nfrom conan import ConanFile\nfrom conan.tools.files import save\nfrom conan.tools.cmake import CMakeDeps, CMakeToolchain, cmake_layout\n\n\nclass MyWs(ConanFile):\n    \"\"\" This is a special conanfile, used only for workspace definition of layout\n    and generators. It shouldn't have requirements, tool_requirements. It shouldn't have\n    build() or package() methods\n    \"\"\"\n    settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n    def generate(self):\n        deps = CMakeDeps(self)\n        deps.generate()\n        tc = CMakeToolchain(self)\n        tc.generate()\n\n    def layout(self):\n        cmake_layout(self)\n\n\nclass Ws(Workspace):\n    def root_conanfile(self):\n        return MyWs\n\n    def build_order(self, order):\n        super().build_order(order)  # default behavior prints the build order\n        pkglist = \" \".join([f'{it[\"ref\"].name}:{it[\"folder\"]}' for level in order for it in level])\n        save(self, \"build/conanws_build_order.cmake\", f\"set(CONAN_WS_BUILD_ORDER {pkglist})\")\n'''\n\nworkspace_files = {\"conanws.yml\": conanws_yml,\n                   \"CMakeLists.txt\": cmake,\n                   \"conanws.py\": conanfile,\n                   \".gitignore\": \"build\"}\n# liba\nfiles = {f\"liba/{k}\": v for k, v in cmake_lib_files.items()}\nworkspace_files.update(files)\n# libb\nfiles = NewAPI.render(cmake_lib_files, {\"requires\": [\"liba/0.1\"], \"name\": \"libb\"})\nfiles = {f\"libb/{k}\": v for k, v in files.items()}\nworkspace_files.update(files)\n# app\nfiles = NewAPI.render(cmake_exe_files, definitions={\"name\": \"app1\", \"requires\": [\"libb/0.1\"]})\nfiles = {f\"app1/{k}\": v for k, v in files.items()}\nworkspace_files.update(files)\n"
  },
  {
    "path": "conan/internal/api/profile/__init__.py",
    "content": ""
  },
  {
    "path": "conan/internal/api/profile/detect.py",
    "content": "from conan.api.output import ConanOutput\nfrom conan.internal.api.detect.detect_api import detect_os, detect_arch, default_msvc_runtime, \\\n    detect_libcxx, detect_cppstd, detect_default_compiler, default_compiler_version\n\n\ndef detect_defaults_settings():\n    \"\"\" try to deduce current machine values without any constraints at all\n    :return: A list with default settings\n    \"\"\"\n    result = []\n    the_os = detect_os()\n    result.append((\"os\", the_os))\n\n    arch = detect_arch()\n    if arch:\n        result.append((\"arch\", arch))\n    compiler, version, compiler_exe = detect_default_compiler()\n    if not compiler:\n        result.append((\"build_type\", \"Release\"))\n        ConanOutput().warning(\"No compiler was detected (one may not be needed)\")\n        return result\n\n    result.append((\"compiler\", compiler))\n    result.append((\"compiler.version\", default_compiler_version(compiler, version)))\n\n    runtime, runtime_version = default_msvc_runtime(compiler)\n    if runtime:\n        result.append((\"compiler.runtime\", runtime))\n    if runtime_version:\n        result.append((\"compiler.runtime_version\", runtime_version))\n    libcxx = detect_libcxx(compiler, version, compiler_exe)\n    if libcxx:\n        result.append((\"compiler.libcxx\", libcxx))\n    cppstd = detect_cppstd(compiler, version)\n    if cppstd:\n        result.append((\"compiler.cppstd\", cppstd))\n    result.append((\"build_type\", \"Release\"))\n    return result\n"
  },
  {
    "path": "conan/internal/api/profile/profile_loader.py",
    "content": "import os\nimport platform\nimport subprocess\nfrom collections import OrderedDict, defaultdict\n\nfrom jinja2 import Environment, FileSystemLoader\n\nfrom conan import conan_version\nfrom conan.api.output import ConanOutput\nfrom conan.internal.api.detect import detect_api\nfrom conan.internal.cache.home_paths import HomePaths\nfrom conan.tools.env.environment import ProfileEnvironment\nfrom conan.errors import ConanException\nfrom conan.internal.model.conf import ConfDefinition, CORE_CONF_PATTERN\nfrom conan.internal.model.options import Options\nfrom conan.internal.model.profile import Profile\nfrom conan.api.model import RecipeReference\nfrom conan.internal.util.config_parser import TextINIParse\nfrom conan.internal.util.files import mkdir, load_user_encoded\n\n\ndef _unquote(text):\n    text = text.strip()\n    if len(text) > 1 and (text[0] == text[-1]) and text[0] in \"'\\\"\":\n        return text[1:-1]\n    return text\n\n\n_default_profile_plugin = \"\"\"\\\n# This file was generated by Conan. Remove this comment if you edit this file or Conan\n# will destroy your changes.\n\ndef profile_plugin(profile):\n    settings = profile.settings\n    if settings.get(\"compiler\") in (\"msvc\", \"clang\") and settings.get(\"compiler.runtime\"):\n        if settings.get(\"compiler.runtime_type\") is None:\n            runtime = \"Debug\" if settings.get(\"build_type\") == \"Debug\" else \"Release\"\n            try:\n                settings[\"compiler.runtime_type\"] = runtime\n            except ConanException:\n                pass\n    _check_correct_cppstd(settings)\n    _check_correct_cstd(settings)\n\n\ndef _check_correct_cppstd(settings):\n    cppstd = settings.get(\"compiler.cppstd\")\n    version = settings.get(\"compiler.version\")\n\n    if cppstd and version:\n        compiler = settings.get(\"compiler\")\n        from conan.tools.build.cppstd import supported_cppstd\n        supported = supported_cppstd(None, compiler, version)\n        # supported is None when we don't have information about the compiler\n        # but an empty list when no flags are supported for this version\n        if supported is not None and cppstd not in supported:\n            from conan.errors import ConanException\n            raise ConanException(f\"The provided compiler.cppstd={cppstd} is not supported by {compiler} {version}. \"\n                                 f\"Supported values are: {supported}\")\n\n\ndef _check_correct_cstd(settings):\n    cstd = settings.get(\"compiler.cstd\")\n    version = settings.get(\"compiler.version\")\n\n    if cstd and version:\n        compiler = settings.get(\"compiler\")\n        from conan.tools.build.cstd import supported_cstd\n        supported = supported_cstd(None, compiler, version)\n        # supported is None when we don't have information about the compiler\n        # but an empty list when no flags are supported for this version\n        if supported is not None and cstd not in supported:\n            from conan.errors import ConanException\n            raise ConanException(f\"The provided compiler.cstd={cstd} is not supported by {compiler} {version}. \"\n                                 f\"Supported values are: {supported}\")\n\"\"\"\n\n\nclass ProfileLoader:\n    def __init__(self, cache_folder):\n        self._home_paths = HomePaths(cache_folder)\n\n    def from_cli_args(self, profiles, settings, options, conf, cwd, context=None):\n        \"\"\" Return a Profile object, as the result of merging a potentially existing Profile\n        file and the args command-line arguments\n        \"\"\"\n        if conf and any(CORE_CONF_PATTERN.match(c) for c in conf):\n            raise ConanException(\"[conf] 'core.*' configurations are not allowed in profiles.\")\n\n        result = Profile()\n        for p in profiles:\n            tmp = self.load_profile(p, cwd, context)\n            result.compose_profile(tmp)\n\n        args_profile = _profile_parse_args(settings, options, conf)\n        result.compose_profile(args_profile)\n        return result\n\n    def load_profile(self, profile_name, cwd=None, context=None):\n        # TODO: This can be made private, only used in testing now\n        cwd = cwd or os.getcwd()\n        profile = self._load_profile(profile_name, cwd, context, root_profile_name=profile_name)\n        return profile\n\n    def _load_profile(self, profile_name, cwd, context, root_profile_name):\n        \"\"\" Will look for \"profile_name\" in disk if profile_name is absolute path,\n        in current folder if path is relative or in the default folder otherwise.\n        return: a Profile object\n        \"\"\"\n        profiles_folder = self._home_paths.profiles_path\n        profile_path = self.get_profile_path(profiles_folder, profile_name, cwd)\n        try:\n            text = load_user_encoded(profile_path)\n        except Exception as e:\n            raise ConanException(f\"Cannot load profile:\\n{e}\")\n\n        # All profiles will be now rendered with jinja2 as first pass\n        base_path = os.path.dirname(profile_path)\n        file_path = os.path.basename(profile_path)\n        renderc = {\"platform\": platform,\n                   \"os\": os,\n                   \"subprocess\": subprocess,\n                   \"profile_dir\": base_path,\n                   \"profile_name\": file_path,\n                   \"root_profile_name\": root_profile_name,\n                   \"conan_version\": conan_version,\n                   \"detect_api\": detect_api,\n                   \"context\": context}\n\n        # Always include the root Conan home \"profiles\" folder as secondary route for loading\n        # imports and includes from jinja2 templates.\n        loader_paths = [base_path, profiles_folder]\n\n        try:\n            rtemplate = Environment(loader=FileSystemLoader(loader_paths)).from_string(text)\n            text = rtemplate.render(renderc)\n        except Exception as e:\n            raise ConanException(f\"Error while rendering the profile template file '{profile_path}'. \"\n                                 f\"Check your Jinja2 syntax: {str(e)}\")\n\n        try:\n            return self._recurse_load_profile(text, profile_path, context, profile_name)\n        except ConanException as exc:\n            raise ConanException(\"Error reading '%s' profile: %s\" % (profile_name, exc))\n\n    def _recurse_load_profile(self, text, profile_path, context, root_profile_name):\n        \"\"\" Parse and return a Profile object from a text config like representation.\n            cwd is needed to be able to load the includes\n        \"\"\"\n        try:\n            inherited_profile = Profile()\n            cwd = os.path.dirname(os.path.abspath(profile_path)) if profile_path else None\n            profile_parser = _ProfileParser(text)\n            # Iterate the includes and call recursive to get the profile and variables\n            # from parent profiles\n            for include in profile_parser.includes:\n                # Recursion !!\n                profile = self._load_profile(include, cwd, context, root_profile_name)\n                inherited_profile.compose_profile(profile)\n\n            # Current profile before update with parents (but parent variables already applied)\n            inherited_profile = _ProfileValueParser.get_profile(profile_parser.profile_text,\n                                                                inherited_profile)\n            return inherited_profile\n        except ConanException:\n            raise\n        except Exception as exc:\n            raise ConanException(\"Error parsing the profile text file: %s\" % str(exc))\n\n    @staticmethod\n    def get_profile_path(profiles_path, profile_name, cwd, exists=True):\n        def valid_path(_profile_path, _profile_name=None):\n            if exists and not os.path.isfile(_profile_path):\n                raise ConanException(\"Profile not found: {}\".format(_profile_name or _profile_path))\n            return _profile_path\n\n        if os.path.isabs(profile_name):\n            return valid_path(profile_name)\n\n        if profile_name[:2] in (\"./\", \".\\\\\") or profile_name.startswith(\"..\"):  # local\n            profile_path = os.path.abspath(os.path.join(cwd, profile_name))\n            return valid_path(profile_path, profile_name)\n\n        default_folder = profiles_path\n        if not os.path.exists(default_folder):\n            mkdir(default_folder)\n        profile_path = os.path.join(default_folder, profile_name)\n        if exists:\n            if not os.path.isfile(profile_path):\n                profile_path = os.path.abspath(os.path.join(cwd, profile_name))\n            if not os.path.isfile(profile_path):\n                raise ConanException(\"Profile not found: %s\" % profile_name)\n        return profile_path\n\n\n# TODO: This class can be removed/simplified now to a function, it reduced to just __init__\nclass _ProfileParser:\n\n    def __init__(self, text):\n        \"\"\" divides the text in 3 items:\n        - self.includes: List of other profiles to include\n        - self.profile_text: the remaining, containing settings, options, env, etc\n        \"\"\"\n        self.includes = []\n        self.profile_text = \"\"\n\n        for counter, line in enumerate(text.splitlines()):\n            line = line.strip()\n            if not line or line.startswith(\"#\"):\n                continue\n            if line.startswith(\"[\"):\n                self.profile_text = \"\\n\".join(text.splitlines()[counter:])\n                break\n            elif line.startswith(\"include(\"):\n                include = line.split(\"include(\", 1)[1]\n                if not include.endswith(\")\"):\n                    raise ConanException(\"Invalid include statement\")\n                include = include[:-1]\n                self.includes.append(include)\n            else:\n                raise ConanException(\"Error while parsing line %i: '%s'\" % (counter, line))\n\n\nclass _ProfileValueParser:\n    \"\"\" parses a \"pure\" or \"effective\" profile, with no includes, no variables,\n    as the one in the lockfiles, or once these things have been processed by ProfileParser\n    \"\"\"\n    @staticmethod\n    def get_profile(profile_text, base_profile=None):\n        # Trying to strip comments might be problematic if things contain #\n        doc = TextINIParse(profile_text, allowed_fields=[\"tool_requires\",\n                                                         \"system_tools\",  # DEPRECATED: platform_tool_requires\n                                                         \"platform_requires\",\n                                                         \"platform_tool_requires\", \"settings\",\n                                                         \"options\", \"conf\", \"buildenv\", \"runenv\",\n                                                         \"replace_requires\", \"replace_tool_requires\",\n                                                         \"runner\"])\n        # Parse doc sections into Conan model, Settings, Options, etc\n        settings, package_settings = _ProfileValueParser._parse_settings(doc)\n        options = Options.loads(doc.options) if doc.options else None\n        tool_requires = _ProfileValueParser._parse_tool_requires(doc)\n\n        doc_platform_requires = doc.platform_requires or \"\"\n        doc_platform_tool_requires = doc.platform_tool_requires or doc.system_tools or \"\"\n        if doc.system_tools:\n            ConanOutput().warning(\"Profile [system_tools] is deprecated,\"\n                                  \" please use [platform_tool_requires]\")\n\n        def parse_replaces(replaces):\n            result = [RecipeReference.loads(r) for r in replaces.splitlines()]\n            errors = [r for r in result if str(r.version).startswith(\"[\")]\n            if errors:\n                raise ConanException(\"Profile [platform_requires]/[platform_tool_requires] must \"\n                                     f\"be exact versions, not version ranges: {errors}\")\n            return result\n        platform_tool_requires = parse_replaces(doc_platform_tool_requires)\n        platform_requires = parse_replaces(doc_platform_requires)\n\n        def load_replace(doc_replace_requires):\n            result = {}\n            for r in doc_replace_requires.splitlines():\n                r = r.strip()\n                if not r or r.startswith(\"#\"):\n                    continue\n                try:\n                    src, target = r.split(\":\")\n                    target = RecipeReference.loads(target.strip())\n                    src = RecipeReference.loads(src.strip())\n                except Exception as e:\n                    raise ConanException(f\"Error in [replace_xxx] '{r}'.\\nIt should be in the form\"\n                                         f\" 'pattern: replacement', without package-ids.\\n\"\n                                         f\"Original error: {str(e)}\")\n                result[src] = target\n            return result\n\n        replace_requires = load_replace(doc.replace_requires) if doc.replace_requires else {}\n        replace_tool = load_replace(doc.replace_tool_requires) if doc.replace_tool_requires else {}\n\n        if doc.conf:\n            conf = ConfDefinition()\n            conf.loads(doc.conf, profile=True)\n        else:\n            conf = None\n        buildenv = ProfileEnvironment.loads(doc.buildenv) if doc.buildenv else None\n        runenv = ProfileEnvironment.loads(doc.runenv) if doc.runenv else None\n\n        # Create or update the profile\n        base_profile = base_profile or Profile()\n        base_profile.replace_requires.update(replace_requires)\n        base_profile.replace_tool_requires.update(replace_tool)\n\n        current_platform_tool_requires = {r.name: r for r in base_profile.platform_tool_requires}\n        current_platform_tool_requires.update({r.name: r for r in platform_tool_requires})\n        base_profile.platform_tool_requires = list(current_platform_tool_requires.values())\n        current_platform_requires = {r.name: r for r in base_profile.platform_requires}\n        current_platform_requires.update({r.name: r for r in platform_requires})\n        base_profile.platform_requires = list(current_platform_requires.values())\n\n        base_profile.settings.update(settings)\n        for pkg_name, values_dict in package_settings.items():\n            existing = base_profile.package_settings[pkg_name]\n            existing.update(values_dict)\n            # Make sure they are ordered, so `compiler=xxx` goes before `compiler.cppstd` always\n            base_profile.package_settings[pkg_name] = OrderedDict(sorted(existing.items()))\n        for pattern, refs in tool_requires.items():\n            # If the same package, different version is added, the latest version prevail\n            current = base_profile.tool_requires.setdefault(pattern, [])\n            current_dict = {r.name: r for r in current}\n            current_dict.update({r.name: r for r in refs})\n            current[:] = list(current_dict.values())\n        if options is not None:\n            base_profile.options.update_options(options)\n        if conf is not None:\n            base_profile.conf.update_conf_definition(conf)\n        if buildenv is not None:\n            base_profile.buildenv.update_profile_env(buildenv)\n        if runenv is not None:\n            base_profile.runenv.update_profile_env(runenv)\n\n        runner = _ProfileValueParser._parse_key_value(doc.runner) if doc.runner else {}\n        base_profile.runner.update(runner)\n        return base_profile\n\n    @staticmethod\n    def _parse_key_value(raw_info):\n        result = OrderedDict()\n        for br_line in raw_info.splitlines():\n            tokens = br_line.split(\"=\", 1)\n            pattern, req_list = tokens\n            result[pattern.strip()] = req_list.strip()\n        return result\n\n    @staticmethod\n    def _parse_tool_requires(doc):\n        result = OrderedDict()\n        if doc.tool_requires:\n            # FIXME CHECKS OF DUPLICATED?\n            for br_line in doc.tool_requires.splitlines():\n                tokens = br_line.split(\":\", 1)\n                if len(tokens) == 1:\n                    pattern, req_list = \"*\", br_line\n                else:\n                    pattern, req_list = tokens\n                if \"[\" in pattern:\n                    ConanOutput().warning(\n                        f\"Tool requires pattern {pattern} contains a version range, which has no effect. \"\n                        f\"Only '&' for consumer and '*' as wildcard are supported in this context.\",\n                        warn_tag=\"risk\")\n                refs = [RecipeReference.loads(r.strip()) for r in req_list.split(\",\")]\n                result.setdefault(pattern, []).extend(refs)\n        return result\n\n    @staticmethod\n    def _parse_settings(doc):\n        def get_package_name_value(item):\n            \"\"\"Parse items like package:name=value or name=value\"\"\"\n            packagename = None\n            if \":\" in item:\n                tmp = item.split(\":\", 1)\n                packagename, item = tmp\n                if \"[\" in packagename:\n                    ConanOutput().warning(f\"Settings pattern {packagename} contains a version range, which has no effect. \"\n                                          f\"Only '&' for consumer and '*' as wildcard are supported in this context.\",\n                                          warn_tag=\"risk\")\n\n            result_name, result_value = item.split(\"=\", 1)\n            result_name = result_name.strip()\n            result_value = _unquote(result_value)\n            if result_value == \"~\":  # Can be used to undefine an already defined setting\n                result_value = None\n            return packagename, result_name, result_value\n\n        package_settings = OrderedDict()\n        settings = OrderedDict()\n        for setting in doc.settings.splitlines():\n            setting = setting.strip()\n            if not setting or setting.startswith(\"#\"):\n                continue\n            if \"=\" not in setting:\n                raise ConanException(\"Invalid setting line '%s'\" % setting)\n            package_name, name, value = get_package_name_value(setting)\n            if package_name:\n                package_settings.setdefault(package_name, OrderedDict())[name] = value\n            else:\n                settings[name] = value\n        return settings, package_settings\n\n\ndef _profile_parse_args(settings, options, conf):\n    \"\"\" return a Profile object result of parsing raw data\n    \"\"\"\n    def _get_tuples_list_from_extender_arg(items):\n        if not items:\n            return []\n        # Validate the pairs\n        for item in items:\n            chunks = item.split(\"=\", 1)\n            if len(chunks) != 2:\n                raise ConanException(\"Invalid input '%s', use 'name=value'\" % item)\n        return [(item[0], item[1]) for item in [item.split(\"=\", 1) for item in items]]\n\n    def _get_simple_and_package_tuples(items):\n        \"\"\"Parse items like \"thing:item=value or item2=value2 and returns a tuple list for\n        the simple items (name, value) and a dict for the package items\n        {package: [(item, value)...)], ...}\n        \"\"\"\n        simple_items = []\n        package_items = defaultdict(list)\n        tuples = _get_tuples_list_from_extender_arg(items)\n        for name, value in tuples:\n            if value == \"~\":  # Can be used to undefine an already defined setting\n                value = None\n            if \":\" in name:  # Scoped items\n                tmp = name.split(\":\", 1)\n                ref_name = tmp[0]\n                name = tmp[1]\n                if \"[\" in ref_name:\n                    ConanOutput().warning(\n                        f\"Pattern {ref_name} contains a version range, which has no effect. \"\n                        f\"Only '&' for consumer and '*' as wildcard are supported in this context.\",\n                        warn_tag=\"risk\")\n                package_items[ref_name].append((name, value))\n            else:\n                simple_items.append((name, value))\n        return simple_items, package_items\n\n    settings, package_settings = _get_simple_and_package_tuples(settings)\n\n    result = Profile()\n    result.options = Options.loads(\"\\n\".join(options or []))\n    result.settings = OrderedDict(settings)\n    if conf:\n        result.conf = ConfDefinition()\n        result.conf.loads(\"\\n\".join(conf))\n\n    for pkg, values in package_settings.items():\n        result.package_settings[pkg] = OrderedDict(values)\n\n    return result\n\n\ndef migrate_profile_plugin(cache_folder):\n    from conan.internal.api.migrations import update_file\n\n    profile_plugin_file = HomePaths(cache_folder).profile_plugin_path\n    update_file(profile_plugin_file, _default_profile_plugin)\n"
  },
  {
    "path": "conan/internal/api/remotes/__init__.py",
    "content": ""
  },
  {
    "path": "conan/internal/api/remotes/encrypt.py",
    "content": "\n# WARNING: These functions implements a Vigenere cypher, they are NO WAY OK FOR SECURITY!\nCHARS = [c for c in (chr(i) for i in range(32, 127))]\n\n\ndef _ascii_key(key):\n    key = \"\".join([it for it in key if it in CHARS])\n    assert len(key), \"Provide a key containing ASCII characters\"\n    return key\n\n\ndef encode(text, key):\n    assert isinstance(text, str), \"Expected string type, got '{}'\".format(type(text))\n    assert isinstance(key, str), \"Expected 'str' type, got '{}'\".format(type(key))\n    key = _ascii_key(key)\n    res = \"\"\n    for i, c in enumerate(text):\n        if c not in CHARS:\n            res += c\n        else:\n            text_index = CHARS.index(c)\n            key_index = CHARS.index(key[i % len(key)])\n            res += CHARS[(text_index + key_index) % len(CHARS)]\n    return res\n\n\ndef decode(text, key):\n    assert isinstance(text, str), \"Expected 'bytes', got '{}'\".format(type(text))\n    assert isinstance(key, str), \"Expected 'str' type, got '{}'\".format(type(key))\n    key = _ascii_key(key)\n    res = \"\"\n    for i, c in enumerate(text):\n        if c not in CHARS:\n            res += c\n        else:\n            text_index = CHARS.index(c)\n            key_index = CHARS.index(key[i % len(key)])\n            res += CHARS[(text_index - key_index) % len(CHARS)]\n    return res\n"
  },
  {
    "path": "conan/internal/api/remotes/localdb.py",
    "content": "import os\nimport sqlite3\nfrom contextlib import contextmanager\nfrom sqlite3 import OperationalError\n\nfrom conan.errors import ConanException\nfrom conan.internal.api.remotes import encrypt\n\nREMOTES_USER_TABLE = \"users_remotes\"\nLOCALDB = \".conan.db\"\n\n_localdb_encryption_key = os.environ.pop('CONAN_LOGIN_ENCRYPTION_KEY', None)\n\n\nclass LocalDB:\n\n    def __init__(self, dbfolder):\n        self.dbfile = os.path.join(dbfolder, LOCALDB)\n        self.encryption_key = _localdb_encryption_key\n\n        # Create the database file if it doesn't exist\n        if not os.path.exists(self.dbfile):\n            par = os.path.dirname(self.dbfile)\n            os.makedirs(par, exist_ok=True)\n            open(self.dbfile, 'w').close()\n\n            with self._connect() as connection:\n                try:\n                    cursor = connection.cursor()\n                    cursor.execute(\"create table if not exists %s \"\n                                   \"(remote_url TEXT UNIQUE, user TEXT, \"\n                                   \"token TEXT, refresh_token TEXT)\" % REMOTES_USER_TABLE)\n                except Exception as e:\n                    message = f\"Could not initialize local sqlite database {self.dbfile}\"\n                    raise ConanException(message, e)\n\n    def _encode(self, value):\n        if value and self.encryption_key:\n            return encrypt.encode(value, self.encryption_key)\n        return value\n\n    def _decode(self, value):\n        if value and self.encryption_key:\n            return encrypt.decode(value, self.encryption_key)\n        return value\n\n    def clean(self, remote_url=None):\n        with self._connect() as connection:\n            try:\n                cursor = connection.cursor()\n                query = \"DELETE FROM %s\" % REMOTES_USER_TABLE\n                if remote_url:\n                    query += \" WHERE remote_url='{}'\".format(remote_url)\n                cursor.execute(query)\n                try:\n                    # https://github.com/ghaering/pysqlite/issues/109\n                    connection.isolation_level = None\n                    cursor.execute('VACUUM')  # Make sure the DB is cleaned, drop doesn't do that\n                except OperationalError:\n                    pass\n            except Exception as e:\n                raise ConanException(\"Could not initialize local sqlite database\", e)\n\n    @contextmanager\n    def _connect(self):\n        connection = sqlite3.connect(self.dbfile, detect_types=sqlite3.PARSE_DECLTYPES)\n        connection.text_factory = str\n        try:\n            yield connection\n        finally:\n            connection.close()\n\n    def get_login(self, remote_url):\n        \"\"\" Returns login credentials. This method is also in charge of expiring them. \"\"\"\n        with self._connect() as connection:\n            try:\n                statement = connection.cursor()\n                statement.execute(\"select user, token, refresh_token from %s where remote_url='%s'\"\n                                  % (REMOTES_USER_TABLE, remote_url))\n                rs = statement.fetchone()\n                if not rs:\n                    return None, None, None\n                name = rs[0]\n                token = self._decode(rs[1])\n                refresh_token = self._decode(rs[2])\n                return name, token, refresh_token\n            except Exception:\n                raise ConanException(\"Couldn't read login\\n Try removing '%s' file\" % self.dbfile)\n\n    def get_username(self, remote_url):\n        return self.get_login(remote_url)[0]\n\n    def store(self, user, token, refresh_token, remote_url):\n        \"\"\" Login is a tuple of (user, token) \"\"\"\n        with self._connect() as connection:\n            try:\n                token = self._encode(token)\n                refresh_token = self._encode(refresh_token)\n                statement = connection.cursor()\n                statement.execute(\"INSERT OR REPLACE INTO %s (remote_url, user, token, \"\n                                  \"refresh_token) \"\n                                  \"VALUES (?, ?, ?, ?)\" % REMOTES_USER_TABLE,\n                                  (remote_url, user, token, refresh_token))\n                connection.commit()\n            except Exception as e:\n                raise ConanException(\"Could not store credentials %s\" % str(e))\n"
  },
  {
    "path": "conan/internal/api/upload.py",
    "content": "from conan.internal.rest.client_routes import ClientV2Router\nfrom conan.internal.util.files import sha1sum\n\n\ndef add_urls(package_list, remote):\n    router = ClientV2Router(remote.url.rstrip(\"/\"))\n    for ref, packages in package_list.items():\n        ref_info = package_list.recipe_dict(ref)\n        for f, fp in ref_info.get(\"files\", {}).items():\n            ref_info.setdefault(\"upload-urls\", {})[f] = {\n                'url': router.recipe_file(ref, f), 'checksum': sha1sum(fp)\n            }\n        for pref in packages:\n            pref_info = package_list.package_dict(pref)\n            for f, fp in pref_info.get(\"files\", {}).items():\n                pref_info.setdefault(\"upload-urls\", {})[f] = {\n                    'url': router.package_file(pref, f), 'checksum': sha1sum(fp)\n                }\n"
  },
  {
    "path": "conan/internal/api/uploader.py",
    "content": "import fnmatch\nimport gzip\nimport os\nimport shutil\nimport sys\nimport tarfile\nimport time\n\nfrom conan.internal.conan_app import ConanApp\nfrom conan.api.output import ConanOutput\nfrom conan.internal.source import retrieve_exports_sources\nfrom conan.internal.errors import NotFoundException\nfrom conan.errors import ConanException\nfrom conan.internal.paths import CONAN_MANIFEST, CONANFILE, CONANINFO, COMPRESSIONS, \\\n    EXPORT_SOURCES_FILE_NAME, EXPORT_FILE_NAME, PACKAGE_FILE_NAME\nfrom conan.internal.util.files import (clean_dirty, is_dirty, gather_files,\n                                       set_dirty_context_manager, mkdir, human_size)\n\nUPLOAD_POLICY_FORCE = \"force-upload\"\nUPLOAD_POLICY_SKIP = \"skip-upload\"\n\n\nclass UploadUpstreamChecker:\n    \"\"\" decides if something needs to be uploaded or force-uploaded checking if that exact\n    revision already exists in the remote server, or if the --force parameter is forcing the upload\n    This is completely irrespective of the actual package contents, it only uses the local\n    computed revision and the remote one\n    \"\"\"\n    def __init__(self, remote_manager):\n        self._remote_manager = remote_manager\n\n    def check(self, package_list, remote, force):\n        for ref, packages in package_list.items():\n            recipe_info = package_list.recipe_dict(ref)\n            self._check_upstream_recipe(ref, recipe_info, remote, force)\n            for pref in packages:\n                pkg_dict = package_list.package_dict(pref)\n                self._check_upstream_package(pref, pkg_dict, remote, force)\n\n    def _check_upstream_recipe(self, ref, ref_bundle, remote, force):\n        output = ConanOutput(scope=str(ref))\n        output.info(\"Checking which revisions exist in the remote server\")\n        try:\n            assert ref.revision\n            # TODO: It is a bit ugly, interface-wise to ask for revisions to check existence\n            server_ref = self._remote_manager.get_recipe_revision(ref, remote)\n            assert server_ref  # If successful (not raising NotFoundException), this will exist\n        except NotFoundException:\n            ref_bundle[\"force_upload\"] = False\n            ref_bundle[\"upload\"] = True\n        else:\n            if force:\n                output.info(f\"Recipe '{ref.repr_notime()}' already in server, forcing upload\")\n                ref_bundle[\"force_upload\"] = True\n                ref_bundle[\"upload\"] = True\n            else:\n                output.info(f\"Recipe '{ref.repr_notime()}' already in server, skipping upload\")\n                ref_bundle[\"upload\"] = False\n                ref_bundle[\"force_upload\"] = False\n\n    def _check_upstream_package(self, pref, prev_bundle, remote, force):\n        assert (pref.revision is not None), \"Cannot upload a package without PREV\"\n        assert (pref.ref.revision is not None), \"Cannot upload a package without RREV\"\n\n        try:\n            # TODO: It is a bit ugly, interface-wise to ask for revisions to check existence\n            server_revisions = self._remote_manager.get_package_revision(pref, remote)\n            assert server_revisions\n        except NotFoundException:\n            prev_bundle[\"force_upload\"] = False\n            prev_bundle[\"upload\"] = True\n        else:\n            output = ConanOutput(scope=str(pref.ref))\n            if force:\n                output.info(f\"Package '{pref.repr_notime()}' already in server, forcing upload\")\n                prev_bundle[\"force_upload\"] = True\n                prev_bundle[\"upload\"] = True\n            else:\n                output.info(f\"Package '{pref.repr_notime()}' already in server, skipping upload\")\n                prev_bundle[\"force_upload\"] = False\n                prev_bundle[\"upload\"] = False\n\n\ndef get_compress_level(compressformat, global_conf):\n    if compressformat == \"xz\":\n        msg = (\"The 'xz' compression is experimental. \"\n               \"Consumers using older Conan versions will not be able to install these packages. \"\n               \"Feedback is welcome, please report any issues as GitHub tickets.\")\n        ConanOutput().warning(msg, warn_tag=\"experimental\")\n    elif compressformat == \"zst\":\n        msg = (\"The 'zst' compression is experimental. \"\n               \"Consumers installing packages created with this format must use Python >= 3.14. \"\n               \"Consumers using older Conan or Python versions will not be able to install these \"\n               \"packages. Feedback is welcome, please report any issues as GitHub tickets.\")\n        ConanOutput().warning(msg, warn_tag=\"experimental\")\n\n    if compressformat == \"zst\" and sys.version_info.minor < 14:\n        raise ConanException(\"The 'core.upload:compression_format=zst' is only for Python>=3.14\")\n    compresslevel = global_conf.get(\"core:compresslevel\", check_type=int)\n    if compresslevel is None and compressformat == \"gz\":\n        compresslevel = global_conf.get(\"core.gzip:compresslevel\", check_type=int)\n        # do not deprecate yet core.gzip:compresslevel, wait a bit to stabilize core:compresslevel\n    return compresslevel\n\n\nclass PackagePreparator:\n    def __init__(self, app: ConanApp, cache, remote_manager, global_conf):\n        self._app = app\n        self._remote_manager = remote_manager\n        self._cache = cache\n        self._global_conf = global_conf\n        compressformat = self._global_conf.get(\"core.upload:compression_format\", default=\"gz\",\n                                               choices=COMPRESSIONS)\n        compresslevel = get_compress_level(compressformat, global_conf)\n        self._compressformat = compressformat\n        self._compresslevel = compresslevel\n\n    def prepare(self, pkg_list, enabled_remotes, metadata, force=False):\n        local_url = self._global_conf.get(\"core.scm:local_url\", choices=[\"allow\", \"block\"])\n        for ref, packages in pkg_list.items():\n            recipe_layout = self._cache.recipe_layout(ref)\n            conanfile_path = recipe_layout.conanfile()\n            conanfile = self._app.loader.load_basic(conanfile_path)\n            url = conanfile.conan_data.get(\"scm\", {}).get(\"url\") if conanfile.conan_data else None\n            if local_url != \"allow\" and url is not None:\n                if not any(url.startswith(v) for v in (\"ssh\", \"git\", \"http\", \"file\")):\n                    raise ConanException(f\"Package {ref} contains conandata scm url={url}\\n\"\n                                         \"This isn't a remote URL, the build won't be reproducible\\n\"\n                                         \"Failing because conf 'core.scm:local_url!=allow'\")\n\n            # Just in case it was defined from a previous run\n            bundle = pkg_list.recipe_dict(ref)\n            bundle.pop(\"files\", None)\n            bundle.pop(\"upload-urls\", None)\n            if bundle.get(\"upload\") or force:\n                self._prepare_recipe(recipe_layout, ref, bundle, conanfile, enabled_remotes)\n\n            # Package metadata files too\n            if metadata != [\"\"] and (metadata or bundle.get(\"upload\")):\n                metadata_folder = recipe_layout.metadata()\n                files = _metadata_files(metadata_folder, metadata)\n                if files:\n                    ConanOutput(scope=str(ref)).info(f\"Recipe metadata: {len(files)} files\")\n                    bundle.setdefault(\"files\", {}).update(files)\n                    bundle[\"upload\"] = True\n\n            for pref in packages:\n                prev_bundle = pkg_list.package_dict(pref)\n                prev_bundle.pop(\"files\", None)  # If defined from a previous upload\n                prev_bundle.pop(\"upload-urls\", None)\n                self._prepare_package(pref, prev_bundle, metadata, force=force)\n\n    def _prepare_recipe(self, recipe_layout, ref, ref_bundle, conanfile, remotes):\n        \"\"\" do a bunch of things that are necessary before actually executing the upload:\n        - retrieve exports_sources to complete the recipe if necessary\n        - compress the artifacts in conan_export.tgz and conan_export_sources.tgz\n        \"\"\"\n        try:\n            retrieve_exports_sources(self._remote_manager, recipe_layout, conanfile, ref,\n                                     remotes)\n            cache_files = self._compress_recipe_files(recipe_layout, ref)\n            ref_bundle[\"files\"] = cache_files\n        except Exception as e:\n            raise ConanException(f\"{ref} Error while compressing: {e}\")\n\n    def _compress_recipe_files(self, layout, ref):\n        download_export_folder = layout.download_export()\n\n        export_folder = layout.export()\n        files, symlinked_folders = gather_files(export_folder)\n        files.update(symlinked_folders)\n        if CONANFILE not in files or CONAN_MANIFEST not in files:\n            raise ConanException(\"Cannot upload corrupted recipe '%s'\" % str(ref))\n        export_src_folder = layout.export_sources()\n        src_files, src_symlinked_folders = gather_files(export_src_folder)\n        src_files.update(src_symlinked_folders)\n\n        # We do a copy of conanfile and conanmanifest to the download_export_folder\n        # so it is identical as when it is downloaded, and all files are from the same location\n        # to be uploaded\n        mkdir(download_export_folder)\n        shutil.copy2(os.path.join(export_folder, CONANFILE),\n                     os.path.join(download_export_folder, CONANFILE))\n        shutil.copy2(os.path.join(export_folder, CONAN_MANIFEST),\n                     os.path.join(download_export_folder, CONAN_MANIFEST))\n        result = {CONANFILE: os.path.join(download_export_folder, CONANFILE),\n                  CONAN_MANIFEST: os.path.join(download_export_folder, CONAN_MANIFEST)}\n        # Files NOT included in the tgz\n        files.pop(CONANFILE)\n        files.pop(CONAN_MANIFEST)\n\n        if files:\n            comp = self._compressed_file(EXPORT_FILE_NAME, files, download_export_folder, ref)\n            result[comp] = os.path.join(download_export_folder, comp)\n        if src_files:\n            comp = self._compressed_file(EXPORT_SOURCES_FILE_NAME, src_files,\n                                         download_export_folder, ref)\n            result[comp] = os.path.join(download_export_folder, comp)\n        return result\n\n    def _prepare_package(self, pref, prev_bundle, metadata, force=False):\n        pkg_layout = None\n        if prev_bundle.get(\"upload\") or force:\n            pkg_layout = self._cache.pkg_layout(pref)\n            if pkg_layout.package_is_dirty():\n                raise ConanException(f\"Package {pref} is corrupted, aborting upload.\\n\"\n                                     f\"Remove it with 'conan remove {pref}'\")\n            cache_files = self._compress_package_files(pkg_layout, pref)\n            prev_bundle[\"files\"] = cache_files\n\n        # Package metadata files too\n        if metadata != [\"\"] and (metadata or prev_bundle.get(\"upload\")):\n            pkg_layout = pkg_layout or self._cache.pkg_layout(pref)\n            metadata_folder = pkg_layout.metadata()\n            files = _metadata_files(metadata_folder, metadata)\n            if files:\n                ConanOutput(scope=str(pref)).info(f\"Package metadata: {len(files)} files\")\n                prev_bundle.setdefault(\"files\", {}).update(files)\n                prev_bundle[\"upload\"] = True\n\n    def _compressed_file(self, filename, files, download_folder, ref):\n        output = ConanOutput(scope=str(ref))\n\n        # Check if there is some existing compressed file already\n        matches = []\n        for extension in COMPRESSIONS:\n            file_name = filename + extension\n            package_file = os.path.join(download_folder, file_name)\n            if is_dirty(package_file):\n                output.warning(f\"Removing {file_name}, marked as dirty\")\n                os.remove(package_file)\n                clean_dirty(package_file)\n            if os.path.isfile(package_file):\n                matches.append(file_name)\n        if len(matches) > 1:\n            raise ConanException(f\"{ref}: Multiple package files found for {filename}: {matches}\")\n        if len(matches) == 1:\n            existing = matches[0]\n            if not existing.endswith(self._compressformat):\n                output.info(f\"Existing {existing} compressed file, \"\n                            f\"keeping it, not using '{self._compressformat}' format\")\n            return existing\n\n        file_name = filename + self._compressformat\n        package_file = os.path.join(download_folder, file_name)\n        compressed_path = compress_files(files, file_name, download_folder,\n                                         compresslevel=self._compresslevel, scope=str(ref))\n        assert compressed_path == package_file\n        assert os.path.exists(package_file)\n        return file_name\n\n    def _compress_package_files(self, layout, pref):\n        download_pkg_folder = layout.download_package()\n\n        # Get all the files in that directory\n        # existing package\n        package_folder = layout.package()\n        files, symlinked_folders = gather_files(package_folder)\n        files.update(symlinked_folders)\n\n        if CONANINFO not in files or CONAN_MANIFEST not in files:\n            raise ConanException(\"Cannot upload corrupted package '%s'\" % str(pref))\n\n        # Do a copy so the location of CONANINFO and MANIFEST is the \"download\" folder one\n        mkdir(download_pkg_folder)\n        shutil.copy2(os.path.join(package_folder, CONANINFO),\n                     os.path.join(download_pkg_folder, CONANINFO))\n        shutil.copy2(os.path.join(package_folder, CONAN_MANIFEST),\n                     os.path.join(download_pkg_folder, CONAN_MANIFEST))\n        # Files NOT included in the tgz\n        files.pop(CONANINFO)\n        files.pop(CONAN_MANIFEST)\n\n        compressed_file = self._compressed_file(PACKAGE_FILE_NAME, files, download_pkg_folder, pref)\n        return {compressed_file: os.path.join(download_pkg_folder, compressed_file),\n                CONANINFO: os.path.join(download_pkg_folder, CONANINFO),\n                CONAN_MANIFEST: os.path.join(download_pkg_folder, CONAN_MANIFEST)}\n\n\nclass UploadExecutor:\n    \"\"\" does the actual file transfer to the remote. The files to be uploaded have already\n    been computed and are passed in the ``upload_data`` parameter, so this executor is also\n    agnostic about which files are transferred\n    \"\"\"\n    def __init__(self, remote_manager):\n        self._remote_manager = remote_manager\n\n    def upload(self, upload_data, remote):\n        for ref, packages in upload_data.items():\n            bundle = upload_data.recipe_dict(ref)\n            if bundle.get(\"upload\"):\n                self.upload_recipe(ref, bundle, remote)\n            for pref in packages:\n                prev_bundle = upload_data.package_dict(pref)\n                if prev_bundle.get(\"upload\"):\n                    self.upload_package(pref, prev_bundle, remote)\n\n    def upload_recipe(self, ref, bundle, remote):\n        output = ConanOutput(scope=str(ref))\n        cache_files = bundle[\"files\"]\n\n        output.info(f\"Uploading recipe '{ref.repr_notime()}' ({_total_size(cache_files)})\")\n\n        t1 = time.time()\n        self._remote_manager.upload_recipe(ref, cache_files, remote)\n\n        duration = time.time() - t1\n        output.debug(f\"Upload {ref} in {duration} time\")\n        return ref\n\n    def upload_package(self, pref, prev_bundle, remote):\n        output = ConanOutput(scope=str(pref.ref))\n        cache_files = prev_bundle[\"files\"]\n        assert (pref.revision is not None), \"Cannot upload a package without PREV\"\n        assert (pref.ref.revision is not None), \"Cannot upload a package without RREV\"\n\n        output.info(f\"Uploading package '{pref.repr_notime()}' ({_total_size(cache_files)})\")\n\n        t1 = time.time()\n        self._remote_manager.upload_package(pref, cache_files, remote)\n        duration = time.time() - t1\n        output.debug(f\"Upload {pref} in {duration} time\")\n\n\ndef gzopen_without_timestamps(name, fileobj, compresslevel=None):\n    \"\"\" !! Method overrided by laso to pass mtime=0 (!=None) to avoid time.time() was\n        setted in Gzip file causing md5 to change. Not possible using the\n        previous tarfile open because arguments are not passed to GzipFile constructor\n    \"\"\"\n    compresslevel = compresslevel if compresslevel is not None else 9  # default Gzip = 9\n    fileobj = gzip.GzipFile(name, \"w\", compresslevel, fileobj, mtime=0)\n    # Format is forced because in Python3.8, it changed and it generates different tarfiles\n    # with different checksums, which break hashes of tgzs\n    # PAX_FORMAT is the default for Py38, lets make it explicit for older Python versions\n    t = tarfile.TarFile.taropen(name, \"w\", fileobj, format=tarfile.PAX_FORMAT)\n    t._extfileobj = False\n    return t\n\n\ndef compress_files(files, name, dest_dir, compresslevel=None, scope=None, recursive=False):\n    t1 = time.time()\n    tgz_path = os.path.join(dest_dir, name)\n\n    out = ConanOutput(scope=scope)\n    out.info(f\"Compressing {name}\")\n\n    if name.endswith(\"zst\"):\n        with tarfile.open(tgz_path, \"w:zst\", level=compresslevel) as tar:  # noqa Py314 only\n            for filename, abs_path in sorted(files.items()):\n                tar.add(abs_path, filename, recursive=recursive)\n        out.debug(f\"{name} compressed in {time.time() - t1} time\")\n        return tgz_path\n\n    if name.endswith(\"xz\"):\n        # The default to PAX_FORMAT in case of Python 3.7\n        with tarfile.open(tgz_path, \"w:xz\", preset=compresslevel, format=tarfile.PAX_FORMAT) as tar:\n            for filename, abs_path in sorted(files.items()):\n                tar.add(abs_path, filename, recursive=recursive)\n        out.debug(f\"{name} compressed in {time.time() - t1} time\")\n        return tgz_path\n\n    with set_dirty_context_manager(tgz_path), open(tgz_path, \"wb\") as tgz_handle:\n        tgz = gzopen_without_timestamps(name, fileobj=tgz_handle, compresslevel=compresslevel)\n        for filename, abs_path in sorted(files.items()):\n            # recursive is False by default in case it is a symlink to a folder\n            tgz.add(abs_path, filename, recursive=recursive)\n        tgz.close()\n\n    out.debug(f\"{name} compressed in {time.time() - t1} time\")\n    return tgz_path\n\n\ndef _total_size(cache_files):\n    total_size = 0\n    for file in cache_files.values():\n        stat = os.stat(file)\n        total_size += stat.st_size\n    return human_size(total_size)\n\n\ndef _metadata_files(folder, metadata):\n    result = {}\n    for root, _, files in os.walk(folder):\n        for f in files:\n            abs_path = os.path.join(root, f)\n            relpath = os.path.relpath(abs_path, folder)\n            if metadata:\n                if not any(fnmatch.fnmatch(relpath, m) for m in metadata):\n                    continue\n            path = os.path.join(\"metadata\", relpath).replace(\"\\\\\", \"/\")\n            result[path] = abs_path\n    return result\n"
  },
  {
    "path": "conan/internal/cache/__init__.py",
    "content": ""
  },
  {
    "path": "conan/internal/cache/cache.py",
    "content": "import hashlib\nimport os\nimport re\nimport shutil\nimport uuid\nfrom fnmatch import translate\nfrom typing import List\n\nfrom conan.internal.cache.conan_reference_layout import RecipeLayout, PackageLayout\n# TODO: Random folders are no longer accessible, how to get rid of them asap?\n# TODO: We need the workflow to remove existing references.\nfrom conan.internal.cache.db.cache_database import CacheDatabase\nfrom conan.internal.errors import ConanReferenceAlreadyExistsInDB\nfrom conan.errors import ConanException\nfrom conan.api.model import PkgReference\nfrom conan.api.model import RecipeReference\nfrom conan.internal.util.dates import revision_timestamp_now\nfrom conan.internal.util.files import rmdir, renamedir, mkdir\n\n\nclass PkgCache:\n    \"\"\" Class to represent the recipes and packages storage in disk\n    \"\"\"\n\n    def __init__(self, cache_folder, global_conf):\n        # paths\n        self._store_folder = global_conf.get(\"core.cache:storage_path\") or \\\n                             os.path.join(cache_folder, \"p\")\n\n        try:\n            mkdir(self._store_folder)\n            db_filename = os.path.join(self._store_folder, 'cache.sqlite3')\n            self._base_folder = os.path.abspath(self._store_folder)\n            self._db = CacheDatabase(filename=db_filename)\n        except Exception as e:\n            raise ConanException(f\"Couldn't initialize storage in {self._store_folder}: {e}\")\n\n    @property\n    def store(self):\n        return self._base_folder\n\n    @property\n    def temp_folder(self):\n        \"\"\" temporary folder where Conan puts exports and packages before the final revision\n        is computed\"\"\"\n        # TODO: Improve the path definitions, this is very hardcoded\n        return os.path.join(self._base_folder, \"t\")\n\n    @property\n    def builds_folder(self):\n        return os.path.join(self._base_folder, \"b\")\n\n    def _create_path(self, relative_path, remove_contents=True):\n        path = self._full_path(relative_path)\n        if os.path.exists(path) and remove_contents:\n            rmdir(path)\n        os.makedirs(path, exist_ok=True)\n\n    def _full_path(self, relative_path):\n        # This one is used only for rmdir and mkdir operations, not returned to user\n        # or stored in DB\n        path = os.path.realpath(os.path.join(self._base_folder, relative_path))\n        return path\n\n    @staticmethod\n    def _short_hash_path(h):\n        \"\"\":param h: Unicode text to reduce\"\"\"\n        h = h.encode(\"utf-8\")\n        md = hashlib.sha256()\n        md.update(h)\n        sha_bytes = md.hexdigest()\n        # len based on: https://github.com/conan-io/conan/pull/9595#issuecomment-918976451\n        # Reduce length in 3 characters 16 - 3 = 13\n        return sha_bytes[0:13]\n\n    @staticmethod\n    def _get_path(ref):\n        return ref.name[:5] + PkgCache._short_hash_path(ref.repr_notime())\n\n    @staticmethod\n    def _get_path_pref(pref):\n        return pref.ref.name[:5] + PkgCache._short_hash_path(pref.repr_notime())\n\n    def create_export_recipe_layout(self, ref: RecipeReference):\n        \"\"\"  This is a temporary layout while exporting a new recipe, because the revision is not\n        computed until later. The entry is not added to DB, just a temp folder is created\n\n        This temporary export folder will be moved to permanent when revision is computed by the\n        assign_rrev() method\n        \"\"\"\n        assert ref.revision is None, \"Recipe revision should be None\"\n        assert ref.timestamp is None\n        h = ref.name[:5] + PkgCache._short_hash_path(ref.repr_notime())\n        reference_path = os.path.join(\"t\", h)\n        self._create_path(reference_path)\n        return RecipeLayout(ref, os.path.join(self._base_folder, reference_path))\n\n    def create_build_pkg_layout(self, pref: PkgReference):\n        # Temporary layout to build a new package, when we don't know the package revision yet\n        assert pref.ref.revision, \"Recipe revision must be known to get or create the package layout\"\n        assert pref.package_id, \"Package id must be known to get or create the package layout\"\n        assert pref.revision is None, \"Package revision should be None\"\n        assert pref.timestamp is None\n\n        random_id = str(uuid.uuid4())\n        h = pref.ref.name[:5] + PkgCache._short_hash_path(pref.repr_notime() + random_id)\n        package_path = os.path.join(\"b\", h)\n        self._create_path(package_path)\n        return PackageLayout(pref, os.path.join(self._base_folder, package_path))\n\n    def recipe_layout(self, ref: RecipeReference):\n        \"\"\" the revision must exists, the folder must exist\n        The regular graph building will use this method if the revision is defined, like\n        when using lockfiles or explicit, or recipe_layout_latest() if not, to do one single DB\n        query\n        \"\"\"\n        assert ref.revision is not None\n        ref_data = self._db.get_recipe(ref)\n        ref_path = ref_data.get(\"path\")\n        ref = ref_data.get(\"ref\")  # new revision with timestamp\n        return RecipeLayout(ref, os.path.join(self._base_folder, ref_path))\n\n    def recipe_layout_latest(self, ref: RecipeReference):\n        \"\"\" the revision must be None, the folder must exist\n        This method was added so the ConanProxy used to resolve the dependency graph\n        avoid doing 2 DB calls when the revision is not defined\n        \"\"\"\n        assert ref.revision is None\n        ref_data = self._db.get_latest_recipe(ref)\n        ref_path = ref_data.get(\"path\")\n        ref = ref_data.get(\"ref\")  # new revision with timestamp\n        return RecipeLayout(ref, os.path.join(self._base_folder, ref_path))\n\n    def get_latest_recipe_revision(self, ref: RecipeReference) -> RecipeReference:\n        assert ref.revision is None\n        ref_data = self._db.get_latest_recipe(ref)\n        return ref_data.get(\"ref\")\n\n    def get_recipe_revisions(self, ref: RecipeReference):\n        # For listing multiple revisions only\n        assert ref.revision is None\n        return self._db.get_recipe_revisions_references(ref)\n\n    def pkg_layout(self, pref: PkgReference):\n        \"\"\" the revision must exists, the folder must exist\n        No longer used by GraphBinariesAnalyzer\n        \"\"\"\n        assert pref.ref.revision, \"Recipe revision must be known to get the package layout\"\n        assert pref.package_id, \"Package id must be known to get the package layout\"\n        assert pref.revision, \"Package revision must be known to get the package layout\"\n        pref_data = self._db.try_get_package(pref)\n        pref_path = pref_data.get(\"path\")\n        # we use abspath to convert cache forward slash in Windows to backslash\n        return PackageLayout(pref, os.path.abspath(os.path.join(self._base_folder, pref_path)))\n\n    def pkg_layout_latest(self, pref: PkgReference):\n        \"\"\"\n        GraphBinariesAnalyzer will call this method to avoid doing 2 DB calls, previously\n        it was using pkg_layout() after a get_latest_package_revision()\n        \"\"\"\n        assert pref.ref.revision, \"Recipe revision must be known to get the package layout\"\n        assert pref.package_id, \"Package id must be known to get the package layout\"\n        assert pref.revision is None\n\n        pref_data = self._db.get_latest_package_reference_data(pref)\n        if pref_data is None:\n            return None\n        pref_path = pref_data.get(\"path\")\n        pref = pref_data.get(\"pref\")  # new revision with timestamp\n        # we use abspath to convert cache forward slash in Windows to backslash\n        return PackageLayout(pref, os.path.abspath(os.path.join(self._base_folder, pref_path)))\n\n    def create_ref_layout(self, ref: RecipeReference):\n        \"\"\" called exclusively by:\n        - RemoteManager.get_recipe()\n        - cache restore\n        \"\"\"\n        assert ref.revision, \"Recipe revision must be known to create the package layout\"\n        reference_path = self._get_path(ref)\n        self._db.create_recipe(reference_path, ref)\n        self._create_path(reference_path, remove_contents=False)\n        return RecipeLayout(ref, os.path.join(self._base_folder, reference_path))\n\n    def create_pkg_layout(self, pref: PkgReference):\n        \"\"\" called by:\n         - RemoteManager.get_package()\n         - cache restore\n        \"\"\"\n        assert pref.ref.revision, \"Recipe revision must be known to create the package layout\"\n        assert pref.package_id, \"Package id must be known to create the package layout\"\n        assert pref.revision, \"Package revision should be known to create the package layout\"\n        package_path = self._get_path_pref(pref)\n        self._db.create_package(package_path, pref, None)\n        self._create_path(package_path, remove_contents=False)\n        return PackageLayout(pref, os.path.join(self._base_folder, package_path))\n\n    def update_recipe_timestamp(self, ref: RecipeReference):\n        \"\"\" when the recipe already exists in cache, but we get a new timestamp from a server\n        that would affect its order in our cache \"\"\"\n        assert ref.revision\n        assert ref.timestamp\n        self._db.update_recipe_timestamp(ref)\n\n    def search_recipes(self, pattern=None, ignorecase=True):\n        # Conan references in main storage\n        if pattern:\n            if isinstance(pattern, RecipeReference):\n                pattern = repr(pattern)\n            pattern = translate(pattern)\n            pattern = re.compile(pattern, re.IGNORECASE if ignorecase else 0)\n\n        return self._db.list_references(pattern)\n\n    def exists_prev(self, pref):\n        # Used just by download to skip downloads if prev already exists in cache\n        return self._db.exists_prev(pref)\n\n    def get_latest_package_revision(self, pref: PkgReference) -> PkgReference:\n        # This is no longer needed by the Graph resolution functionality, only by ListAPI\n        # its usage in graph resolution has been replaced by a single call to pkg_layout_latest()\n        return self._db.get_latest_package_reference(pref)\n\n    def get_package_references(self, ref: RecipeReference,\n                               only_latest_prev=True) -> List[PkgReference]:\n        \"\"\"Get the latest package references\"\"\"\n        return self._db.get_package_references(ref, only_latest_prev)\n\n    def get_package_revisions(self, pref: PkgReference) -> List[PkgReference]:\n        return self._db.get_package_revisions_references(pref)\n\n    def get_matching_build_id(self, ref, build_id):\n        return self._db.get_matching_build_id(ref, build_id)\n\n    def remove_recipe_layout(self, layout: RecipeLayout):\n        layout.remove()\n        # FIXME: This is clearing package binaries from DB, but not from disk/layout\n        self._db.remove_recipe(layout.reference)\n\n    def remove_package_layout(self, layout: PackageLayout):\n        layout.remove()\n        self._db.remove_package(layout.reference)\n\n    def remove_build_id(self, pref):\n        self._db.remove_build_id(pref)\n\n    def assign_prev(self, layout: PackageLayout):\n        pref = layout.reference\n\n        build_id = layout.build_id\n        pref.timestamp = revision_timestamp_now()\n        # Wait until it finish to really update the DB\n        relpath = os.path.relpath(layout.base_folder, self._base_folder)\n        relpath = relpath.replace(\"\\\\\", \"/\")  # Uniform for Windows and Linux\n        try:\n            self._db.create_package(relpath, pref, build_id)\n        except ConanReferenceAlreadyExistsInDB:\n            # TODO: Optimize this into 1 single UPSERT operation\n            # There was a previous package folder for this same package reference (and prev)\n            pkg_layout = self.pkg_layout(pref)\n            # We remove the old one and move the new one to the path of the previous one\n            # this can be necessary in case of new metadata or build-folder because of \"build_id()\"\n            pkg_layout.remove()\n            shutil.move(layout.base_folder, pkg_layout.base_folder)  # clean unused temporary build\n            layout._base_folder = pkg_layout.base_folder  # reuse existing one\n            # TODO: The relpath would be the same as the previous one, it shouldn't be ncessary to\n            #  update it, the update_package_timestamp() can be simplified and path dropped\n            relpath = os.path.relpath(layout.base_folder, self._base_folder)\n            self._db.update_package_timestamp(pref, path=relpath, build_id=build_id)\n\n    def assign_rrev(self, layout: RecipeLayout):\n        \"\"\" called at export, once the exported recipe revision has been computed, it\n        can register for the first time the new RecipeReference\"\"\"\n        ref = layout.reference\n        assert ref.revision is not None, \"Revision must exist after export\"\n        assert ref.timestamp is None, \"Timestamp no defined yet\"\n        ref.timestamp = revision_timestamp_now()\n\n        # TODO: here maybe we should block the recipe and all the packages too\n        # This is the destination path for the temporary created export and export_sources folders\n        # with the hash created based on the recipe revision\n        new_path_relative = self._get_path(ref)\n\n        new_path_absolute = self._full_path(new_path_relative)\n\n        if os.path.exists(new_path_absolute):\n            # If there source folder exists, export and export_sources\n            # folders are already copied so we can remove the tmp ones\n            rmdir(self._full_path(layout.base_folder))\n        else:\n            # Destination folder is empty, move all the tmp contents\n            renamedir(self._full_path(layout.base_folder), new_path_absolute)\n\n        layout._base_folder = os.path.join(self._base_folder, new_path_relative)\n\n        # Wait until it finish to really update the DB\n        try:\n            self._db.create_recipe(new_path_relative, ref)\n        except ConanReferenceAlreadyExistsInDB:\n            # This was exported before, making it latest again, update timestamp\n            ref = layout.reference\n            self._db.update_recipe_timestamp(ref)\n\n    def get_recipe_lru(self, ref):\n        path = self._full_path(self._get_path(ref))\n        return os.path.getmtime(path)  # seconds since EPOCH\n\n    def update_recipes_lru(self, refs):\n        for r in refs:\n            path = self._full_path(self._get_path(r))\n            os.utime(path, None)\n\n    def get_package_lru(self, pref):\n        layout = self.pkg_layout(pref)  # It can be a build folder too\n        return os.path.getmtime(layout.base_folder)  # seconds since EPOCH\n\n    def path_to_ref(self, path):\n        try:\n            path = os.path.relpath(path, self._base_folder)\n            path = path.replace(\"\\\\\", \"/\")  # Uniform for Windows and Linux\n        except ValueError:\n            raise ConanException(f\"Invalid path: {path}\")\n        return self._db.path_to_ref(path)\n"
  },
  {
    "path": "conan/internal/cache/conan_reference_layout.py",
    "content": "import os\nfrom contextlib import contextmanager\n\nfrom conan.internal.model.manifest import FileTreeManifest\nfrom conan.internal.paths import CONANFILE, DATA_YML\nfrom conan.internal.util.files import set_dirty, clean_dirty, is_dirty, rmdir\n\n\n# To be able to change them later to something shorter\nSRC_FOLDER = \"s\"\nBUILD_FOLDER = \"b\"\nPACKAGES_FOLDER = \"p\"\nFINALIZE_FOLDER = \"f\"\nEXPORT_FOLDER = \"e\"\nEXPORT_SRC_FOLDER = \"es\"\nDOWNLOAD_EXPORT_FOLDER = \"d\"\nMETADATA = \"metadata\"\n\n\nclass LayoutBase:\n    def __init__(self, ref, base_folder):\n        self.reference = ref\n        self._base_folder = base_folder\n\n    @property\n    def base_folder(self):\n        return self._base_folder\n\n    def remove(self):\n        rmdir(self._base_folder)\n\n\nclass BasicLayout(LayoutBase):\n    # For editables and platform_requires\n    def conanfile(self):\n        # the full conanfile path (including other other.py names) for editables\n        # None for platform_requires\n        return self._base_folder\n\n    def metadata(self):\n        if self._base_folder is None:\n            return\n        return os.path.join(os.path.dirname(self._base_folder), METADATA)\n\n\nclass RecipeLayout(LayoutBase):\n\n    @contextmanager\n    def conanfile_write_lock(self, output):\n        yield\n\n    def export(self):\n        return os.path.join(self._base_folder, EXPORT_FOLDER)\n\n    def export_sources(self):\n        return os.path.join(self._base_folder, EXPORT_SRC_FOLDER)\n\n    def metadata(self):\n        return os.path.join(self.download_export(), METADATA)\n\n    def download_export(self):\n        return os.path.join(self._base_folder, DOWNLOAD_EXPORT_FOLDER)\n\n    def source(self):\n        return os.path.join(self._base_folder, SRC_FOLDER)\n\n    def conanfile(self):\n        return os.path.join(self.export(), CONANFILE)\n\n    def conandata(self):\n        return os.path.join(self.export(), DATA_YML)\n\n    def recipe_manifests(self):\n        # Used for comparison and integrity check\n        export_folder = self.export()\n        readed_manifest = FileTreeManifest.load(export_folder)\n        exports_source_folder = self.export_sources()\n        expected_manifest = FileTreeManifest.create(export_folder, exports_source_folder)\n        return readed_manifest, expected_manifest\n\n    def sources_remove(self):\n        src_folder = self.source()\n        rmdir(src_folder)\n\n\nclass PackageLayout(LayoutBase):\n\n    def __init__(self, ref, base_folder):\n        super().__init__(ref, base_folder)\n        self.build_id = None\n\n    # TODO: cache2.0 locks implementation\n    @contextmanager\n    def package_lock(self):\n        yield\n\n    def build(self):\n        return os.path.join(self._base_folder, BUILD_FOLDER)\n\n    def package(self):\n        return os.path.join(self._base_folder, PACKAGES_FOLDER)\n\n    def finalize(self):\n        return os.path.join(self._base_folder, FINALIZE_FOLDER)\n\n    def download_package(self):\n        return os.path.join(self._base_folder, DOWNLOAD_EXPORT_FOLDER)\n\n    def metadata(self):\n        return os.path.join(self.download_package(), METADATA)\n\n    def package_manifests(self):\n        package_folder = self.package()\n        readed_manifest = FileTreeManifest.load(package_folder)\n        expected_manifest = FileTreeManifest.create(package_folder)\n        return readed_manifest, expected_manifest\n\n    @contextmanager\n    def set_dirty_context_manager(self):\n        set_dirty(self.package())\n        yield\n        clean_dirty(self.package())\n\n    # TODO: cache2.0 check this\n    def package_is_dirty(self):\n        return is_dirty(self.package())\n\n    def build_remove(self):\n        rmdir(self.build())\n\n    # TODO: cache2.0 locks\n    def package_remove(self):\n        # Here we could validate and check we own a write lock over this package\n        tgz_folder = self.download_package()\n        rmdir(tgz_folder)\n        rmdir(self.package())\n        if is_dirty(self.package()):\n            clean_dirty(self.package())\n"
  },
  {
    "path": "conan/internal/cache/db/__init__.py",
    "content": ""
  },
  {
    "path": "conan/internal/cache/db/cache_database.py",
    "content": "import os\nimport sqlite3\n\nfrom conan.api.output import ConanOutput\nfrom conan.internal.cache.db.packages_table import PackagesDBTable\nfrom conan.internal.cache.db.recipes_table import RecipesDBTable\nfrom conan.api.model import PkgReference\nfrom conan.api.model import RecipeReference\nfrom conan.internal.model.version import Version\n\n\nclass CacheDatabase:\n\n    def __init__(self, filename):\n        version = sqlite3.sqlite_version\n        if Version(version) < \"3.7.11\":\n            ConanOutput().error(f\"Your sqlite3 '{version} < 3.7.11' version is not supported\")\n        self._recipes = RecipesDBTable(filename)\n        self._packages = PackagesDBTable(filename)\n        if not os.path.isfile(filename):\n            self._recipes.create_table()\n            self._packages.create_table()\n\n    def exists_prev(self, ref):\n        return self._packages.get_package_revisions_reference_exists(ref)\n\n    def get_latest_package_reference(self, pref):\n        prevs = list(self._packages.get_package_revisions_references(pref, only_latest_prev=True))\n        return prevs[0][\"pref\"] if prevs else None\n\n    def get_latest_package_reference_data(self, pref):\n        # Used just for PkgCache.pkg_layout_latest()\n        # TODO: This can be refactored, unified with get_latest_package_reference()\n        prevs = list(self._packages.get_package_revisions_references(pref, only_latest_prev=True))\n        return prevs[0] if prevs else None\n\n    def update_recipe_timestamp(self, ref):\n        self._recipes.update_timestamp(ref)\n\n    def update_package_timestamp(self, pref: PkgReference, path: str, build_id: str):\n        self._packages.update_timestamp(pref, path=path, build_id=build_id)\n\n    def remove_recipe(self, ref: RecipeReference):\n        # Removing the recipe must remove all the package binaries too from DB\n        self._recipes.remove(ref)\n        self._packages.remove_recipe(ref)\n\n    def remove_package(self, ref: PkgReference):\n        # Removing the recipe must remove all the package binaries too from DB\n        self._packages.remove(ref)\n\n    def remove_build_id(self, pref):\n        self._packages.remove_build_id(pref)\n\n    def get_matching_build_id(self, ref, build_id):\n        result = self._packages.get_package_references_with_build_id_match(ref, build_id)\n        if result:\n            return result[\"pref\"]\n        return None\n\n    def get_recipe(self, ref: RecipeReference):\n        \"\"\" Returns the reference data as a dictionary (or fails) \"\"\"\n        return self._recipes.get_recipe(ref)\n\n    def get_latest_recipe(self, ref: RecipeReference):\n        \"\"\" Returns the reference data as a dictionary (or fails) \"\"\"\n        return self._recipes.get_latest_recipe(ref)\n\n    def get_recipe_revisions_references(self, ref: RecipeReference):\n        return self._recipes.get_recipe_revisions_references(ref)\n\n    def try_get_package(self, ref: PkgReference):\n        \"\"\" Returns the reference data as a dictionary (or fails) \"\"\"\n        ref_data = self._packages.get(ref)\n        return ref_data\n\n    def create_recipe(self, path, ref: RecipeReference):\n        self._recipes.create(path, ref)\n\n    def create_package(self, path, ref: PkgReference, build_id):\n        self._packages.create(path, ref, build_id=build_id)\n\n    def list_references(self, pattern=None):\n        \"\"\"Returns a list of all RecipeReference in the cache, optionally filtering by pattern.\n         The references have their revision and timestamp attributes unset\"\"\"\n        return [ref for ref in self._recipes.all_references()\n                if pattern is None or ref.partial_match(pattern)]\n\n    def get_package_revisions_references(self, pref: PkgReference):\n        return [d[\"pref\"]\n                for d in self._packages.get_package_revisions_references(pref,\n                                                                         only_latest_prev=False)]\n\n    def get_package_references(self, ref: RecipeReference, only_latest_prev=True):\n        return [d[\"pref\"]\n                for d in self._packages.get_package_references(ref, only_latest_prev)]\n\n    def path_to_ref(self, path):\n        ref = self._recipes.path_to_ref(path)\n        if ref is not None:\n            return ref\n        return self._packages.path_to_ref(path)\n"
  },
  {
    "path": "conan/internal/cache/db/packages_table.py",
    "content": "import sqlite3\n\nfrom conan.internal.cache.db.table import BaseDbTable\nfrom conan.internal.errors import ConanReferenceDoesNotExistInDB, ConanReferenceAlreadyExistsInDB\nfrom conan.api.model import PkgReference\nfrom conan.api.model import RecipeReference\nfrom conan.internal.util.dates import timestamp_now\n\n\nclass PackagesDBTable(BaseDbTable):\n    table_name = 'packages'\n    columns_description = [('reference', str),\n                           ('rrev', str),\n                           ('pkgid', str, True),\n                           ('prev', str, True),\n                           ('path', str, False, True),\n                           ('timestamp', float),\n                           ('build_id', str, True),\n                           ('lru', int)]\n    unique_together = ('reference', 'rrev', 'pkgid', 'prev')\n\n    @staticmethod\n    def _as_dict(row):\n        ref = RecipeReference.loads(row.reference)\n        ref.revision = row.rrev\n        pref = PkgReference(ref, row.pkgid, row.prev, row.timestamp)\n        return {\n            \"pref\": pref,\n            \"build_id\": row.build_id,\n            \"path\": row.path,\n            \"lru\": row.lru\n        }\n\n    def _where_clause(self, pref: PkgReference):\n        where_dict = {\n            self.columns.reference: str(pref.ref),\n            self.columns.rrev: pref.ref.revision,\n            self.columns.pkgid: pref.package_id,\n            self.columns.prev: pref.revision,\n        }\n        where_expr = ' AND '.join(\n            [f\"{k}='{v}' \" if v is not None else f'{k} IS NULL' for k, v in where_dict.items()])\n        return where_expr\n\n    def _set_clause(self, pref: PkgReference, path=None, build_id=None):\n        set_dict = {\n            self.columns.reference: str(pref.ref),\n            self.columns.rrev: pref.ref.revision,\n            self.columns.pkgid: pref.package_id,\n            self.columns.prev: pref.revision,\n            self.columns.path: path,\n            self.columns.timestamp: pref.timestamp,\n            self.columns.build_id: build_id,\n        }\n        set_expr = ', '.join([f\"{k} = '{v}'\" for k, v in set_dict.items() if v is not None])\n        return set_expr\n\n    def get(self, pref: PkgReference):\n        \"\"\" Returns the row matching the reference or fails \"\"\"\n        where_clause = self._where_clause(pref)\n        query = f'SELECT * FROM {self.table_name} ' \\\n                f'WHERE {where_clause};'\n\n        with self.db_connection() as conn:\n            r = conn.execute(query)\n            row = r.fetchone()\n\n        if not row:\n            raise ConanReferenceDoesNotExistInDB(f\"No entry for package '{repr(pref)}'\")\n        return self._as_dict(self.row_type(*row))\n\n    def create(self, path, pref: PkgReference, build_id):\n        assert pref.revision\n        assert pref.timestamp\n        # we set the timestamp to 0 until they get a complete reference, here they\n        # are saved with the temporary uuid one, we don't want to consider these\n        # not yet built packages for search and so on\n        placeholders = ', '.join(['?' for _ in range(len(self.columns))])\n        lru = timestamp_now()\n        with self.db_connection() as conn:\n            try:\n                conn.execute(f'INSERT INTO {self.table_name} '\n                             f'VALUES ({placeholders})',\n                             [str(pref.ref), pref.ref.revision, pref.package_id, pref.revision,\n                              path, pref.timestamp, build_id, lru])\n            except sqlite3.IntegrityError:\n                raise ConanReferenceAlreadyExistsInDB(f\"Reference '{repr(pref)}' already exists\")\n\n    def update_timestamp(self, pref: PkgReference, path: str, build_id: str):\n        assert pref.revision\n        assert pref.timestamp\n        where_clause = self._where_clause(pref)\n        set_clause = self._set_clause(pref, path=path, build_id=build_id)\n        query = f\"UPDATE {self.table_name} \" \\\n                f\"SET {set_clause} \" \\\n                f\"WHERE {where_clause};\"\n        with self.db_connection() as conn:\n            try:\n                conn.execute(query)\n            except sqlite3.IntegrityError:\n                raise ConanReferenceAlreadyExistsInDB(f\"Reference '{repr(pref)}' already exists\")\n\n    def remove_build_id(self, pref):\n        where_clause = self._where_clause(pref)\n        query = f\"UPDATE {self.table_name} \" \\\n                f\"SET {self.columns.build_id} = 'null' \" \\\n                f\"WHERE {where_clause};\"\n        with self.db_connection() as conn:\n            try:\n                conn.execute(query)\n            except sqlite3.IntegrityError:\n                raise ConanReferenceAlreadyExistsInDB(f\"Reference '{repr(pref)}' already exists\")\n\n    def remove_recipe(self, ref: RecipeReference):\n        # can't use the _where_clause, because that is an exact match on the package_id, etc\n        query = f\"DELETE FROM {self.table_name} \" \\\n                f\"WHERE {self.columns.reference} = '{str(ref)}' \" \\\n                f\"AND {self.columns.rrev} = '{ref.revision}' \"\n        with self.db_connection() as conn:\n            conn.execute(query)\n\n    def remove(self, pref: PkgReference):\n        where_clause = self._where_clause(pref)\n        query = f\"DELETE FROM {self.table_name} \" \\\n                f\"WHERE {where_clause};\"\n        with self.db_connection() as conn:\n            conn.execute(query)\n\n    def get_package_revisions_references(self, pref: PkgReference, only_latest_prev=False):\n        assert pref.ref.revision, \"To search package revisions you must provide a recipe revision.\"\n        assert pref.package_id, \"To search package revisions you must provide a package id.\"\n        check_prev = f\"AND {self.columns.prev} = '{pref.revision}' \" if pref.revision else \"\"\n        if only_latest_prev:\n            query = f'SELECT {self.columns.reference}, ' \\\n                    f'{self.columns.rrev}, ' \\\n                    f'{self.columns.pkgid}, ' \\\n                    f'{self.columns.prev}, ' \\\n                    f'{self.columns.path}, ' \\\n                    f'MAX({self.columns.timestamp}), ' \\\n                    f'{self.columns.build_id}, ' \\\n                    f'{self.columns.lru} ' \\\n                    f'FROM {self.table_name} ' \\\n                    f\"WHERE {self.columns.rrev} = '{pref.ref.revision}' \" \\\n                    f\"AND {self.columns.reference} = '{str(pref.ref)}' \" \\\n                    f\"AND {self.columns.pkgid} = '{pref.package_id}' \" \\\n                    f'{check_prev} ' \\\n                    f'AND {self.columns.prev} IS NOT NULL ' \\\n                    f'GROUP BY {self.columns.pkgid} '\n        else:\n            query = f'SELECT * FROM {self.table_name} ' \\\n                    f\"WHERE {self.columns.rrev} = '{pref.ref.revision}' \" \\\n                    f\"AND {self.columns.reference} = '{str(pref.ref)}' \" \\\n                    f\"AND {self.columns.pkgid} = '{pref.package_id}' \" \\\n                    f'{check_prev} ' \\\n                    f'AND {self.columns.prev} IS NOT NULL ' \\\n                    f'ORDER BY {self.columns.timestamp} DESC'\n        with self.db_connection() as conn:\n            r = conn.execute(query)\n            rows = r.fetchall()\n        return [self._as_dict(self.row_type(*row)) for row in rows]\n\n    def get_package_revisions_reference_exists(self, pref: PkgReference):\n        assert pref.ref.revision, \"To check package revision existence you must provide a recipe revision.\"\n        assert pref.package_id, \"To check package revisions existence you must provide a package id.\"\n        check_prev = f\"AND {self.columns.prev} = '{pref.revision}' \" if pref.revision else \"\"\n        query = f'SELECT 1 FROM {self.table_name} ' \\\n                f\"WHERE {self.columns.rrev} = '{pref.ref.revision}' \" \\\n                f\"AND {self.columns.reference} = '{str(pref.ref)}' \" \\\n                f\"AND {self.columns.pkgid} = '{pref.package_id}' \" \\\n                f'{check_prev} ' \\\n                f'AND {self.columns.prev} IS NOT NULL ' \\\n                'LIMIT 1 '\n        with self.db_connection() as conn:\n            r = conn.execute(query)\n            row = r.fetchone()\n        return bool(row)\n\n    def get_package_references(self, ref: RecipeReference, only_latest_prev=True):\n        # Return the latest revisions\n        assert ref.revision, \"To search for package id's you must provide a recipe revision.\"\n        # we select the latest prev for each package_id\n        if only_latest_prev:\n            query = f'SELECT {self.columns.reference}, ' \\\n                    f'{self.columns.rrev}, ' \\\n                    f'{self.columns.pkgid}, ' \\\n                    f'{self.columns.prev}, ' \\\n                    f'{self.columns.path}, ' \\\n                    f'MAX({self.columns.timestamp}), ' \\\n                    f'{self.columns.build_id}, ' \\\n                    f'{self.columns.lru} ' \\\n                    f'FROM {self.table_name} ' \\\n                    f\"WHERE {self.columns.rrev} = '{ref.revision}' \" \\\n                    f\"AND {self.columns.reference} = '{str(ref)}' \" \\\n                    f'GROUP BY {self.columns.pkgid} '\n        else:\n            query = f'SELECT * FROM {self.table_name} ' \\\n                    f\"WHERE {self.columns.rrev} = '{ref.revision}' \" \\\n                    f\"AND {self.columns.reference} = '{str(ref)}' \" \\\n                    f'AND {self.columns.prev} IS NOT NULL ' \\\n                    f'ORDER BY {self.columns.timestamp} DESC'\n        with self.db_connection() as conn:\n            r = conn.execute(query)\n            rows = r.fetchall()\n        return [self._as_dict(self.row_type(*row)) for row in rows]\n\n    def get_package_references_with_build_id_match(self, ref: RecipeReference, build_id):\n        # Return the latest revisions\n        assert ref.revision, \"To search for package id's by build_id you must provide a recipe revision.\"\n        # we select the latest prev for each package_id\n        # This is the same query as get_package_references, but with an additional filter\n        query = f'SELECT {self.columns.reference}, ' \\\n                f'{self.columns.rrev}, ' \\\n                f'{self.columns.pkgid}, ' \\\n                f'{self.columns.prev}, ' \\\n                f'{self.columns.path}, ' \\\n                f'MAX({self.columns.timestamp}), ' \\\n                f'{self.columns.build_id}, ' \\\n                f'{self.columns.lru} ' \\\n                f'FROM {self.table_name} ' \\\n                f\"WHERE {self.columns.rrev} = '{ref.revision}' \" \\\n                f\"AND {self.columns.reference} = '{str(ref)}' \" \\\n                f\"AND {self.columns.build_id} = '{build_id}' \" \\\n                f'GROUP BY {self.columns.pkgid} '\n\n        with self.db_connection() as conn:\n            r = conn.execute(query)\n            row = r.fetchone()\n        if row:\n            return self._as_dict(self.row_type(*row))\n        return None\n\n    def path_to_ref(self, path):\n        query = f'SELECT * FROM {self.table_name} ' \\\n                f\"WHERE {self.columns.path}='{path}'\"\n        with self.db_connection() as conn:\n            r = conn.execute(query)\n            row = r.fetchone()\n        if not row:\n            return None\n        ref = RecipeReference.loads(row[0])\n        ref.revision = row[1]\n        pref = PkgReference(ref, row[2], row[3], row[5])\n        return pref\n"
  },
  {
    "path": "conan/internal/cache/db/recipes_table.py",
    "content": "import sqlite3\n\nfrom conan.internal.cache.db.table import BaseDbTable\nfrom conan.internal.errors import ConanReferenceDoesNotExistInDB, ConanReferenceAlreadyExistsInDB\nfrom conan.api.model import RecipeReference\nfrom conan.internal.util.dates import timestamp_now\n\n\nclass RecipesDBTable(BaseDbTable):\n    table_name = 'recipes'\n    columns_description = [('reference', str),\n                           ('rrev', str),\n                           ('path', str, False, True),\n                           ('timestamp', float),\n                           ('lru', int)]\n    unique_together = ('reference', 'rrev')\n\n    @staticmethod\n    def _as_dict(row):\n        ref = RecipeReference.loads(row.reference)\n        ref.revision = row.rrev\n        ref.timestamp = row.timestamp\n        return {\n            \"ref\": ref,\n            \"path\": row.path,\n            \"lru\": row.lru,\n        }\n\n    def _where_clause(self, ref):\n        assert isinstance(ref, RecipeReference)\n        where_dict = {\n            self.columns.reference: str(ref),\n            self.columns.rrev: ref.revision,\n        }\n        where_expr = ' AND '.join(\n            [f\"{k}='{v}' \" if v is not None else f'{k} IS NULL' for k, v in where_dict.items()])\n        return where_expr\n\n    def create(self, path, ref: RecipeReference):\n        assert ref is not None\n        assert ref.revision is not None\n        assert ref.timestamp is not None\n        placeholders = ', '.join(['?' for _ in range(len(self.columns))])\n        lru = timestamp_now()\n        with self.db_connection() as conn:\n            try:\n                conn.execute(f'INSERT INTO {self.table_name} '\n                             f'VALUES ({placeholders})',\n                             [str(ref), ref.revision, path, ref.timestamp, lru])\n            except sqlite3.IntegrityError:\n                raise ConanReferenceAlreadyExistsInDB(f\"Reference '{repr(ref)}' already exists\")\n\n    def update_timestamp(self, ref: RecipeReference):\n        assert ref.revision is not None\n        assert ref.timestamp is not None\n        query = f\"UPDATE {self.table_name} \" \\\n                f\"SET {self.columns.timestamp} = '{ref.timestamp}' \" \\\n                f\"WHERE {self.columns.reference}='{str(ref)}' \" \\\n                f\"AND {self.columns.rrev} = '{ref.revision}' \"\n        with self.db_connection() as conn:\n            conn.execute(query)\n\n    def remove(self, ref: RecipeReference):\n        where_clause = self._where_clause(ref)\n        query = f\"DELETE FROM {self.table_name} \" \\\n                f\"WHERE {where_clause};\"\n        with self.db_connection() as conn:\n            conn.execute(query)\n\n    # returns all different conan references (name/version@user/channel)\n    def all_references(self):\n        query = f'SELECT DISTINCT {self.columns.reference} FROM {self.table_name}'\n\n        with self.db_connection() as conn:\n            r = conn.execute(query)\n            rows = r.fetchall()\n        return [RecipeReference.loads(row[0]) for row in rows]\n\n    def get_recipe(self, ref: RecipeReference):\n        query = f'SELECT * FROM {self.table_name} ' \\\n                f\"WHERE {self.columns.reference}='{str(ref)}' \" \\\n                f\"AND {self.columns.rrev} = '{ref.revision}' \"\n        with self.db_connection() as conn:\n            r = conn.execute(query)\n            row = r.fetchone()\n        if not row:\n            raise ConanReferenceDoesNotExistInDB(f\"Recipe '{ref.repr_notime()}' not found\")\n        ret = self._as_dict(self.row_type(*row))\n        return ret\n\n    def get_latest_recipe(self, ref: RecipeReference):\n        query = f'SELECT {self.columns.reference}, ' \\\n                f'{self.columns.rrev}, ' \\\n                f'{self.columns.path}, ' \\\n                f'MAX({self.columns.timestamp}), ' \\\n                f'{self.columns.lru} ' \\\n                f'FROM {self.table_name} ' \\\n                f\"WHERE {self.columns.reference} = '{str(ref)}' \" \\\n                f'GROUP BY {self.columns.reference} '  # OTHERWISE IT FAILS THE MAX()\n\n        with self.db_connection() as conn:\n            r = conn.execute(query)\n            row = r.fetchone()\n        if row is None:\n            raise ConanReferenceDoesNotExistInDB(f\"Recipe '{ref}' not found\")\n        ret = self._as_dict(self.row_type(*row))\n        return ret\n\n    def get_recipe_revisions_references(self, ref: RecipeReference):\n        assert ref.revision is None\n        query = f'SELECT * FROM {self.table_name} ' \\\n                f\"WHERE {self.columns.reference} = '{str(ref)}' \" \\\n                f'ORDER BY {self.columns.timestamp} DESC'\n\n        with self.db_connection() as conn:\n            r = conn.execute(query)\n            rows = r.fetchall()\n        ret = [self._as_dict(self.row_type(*row))[\"ref\"] for row in rows]\n        return ret\n\n    def path_to_ref(self, path):\n        query = f'SELECT * FROM {self.table_name} ' \\\n                f\"WHERE {self.columns.path}='{path}'\"\n        with self.db_connection() as conn:\n            r = conn.execute(query)\n            row = r.fetchone()\n        if not row:\n            return None\n        ref = RecipeReference.loads(row[0])\n        ref.revision = row[1]\n        ref.timestamp = row[3]\n        return ref\n"
  },
  {
    "path": "conan/internal/cache/db/table.py",
    "content": "import sqlite3\nimport threading\nimport traceback\nfrom collections import defaultdict, namedtuple\nfrom contextlib import contextmanager\nfrom typing import Tuple, List\n\nfrom conan.api.output import ConanOutput\nfrom conan.errors import ConanException\n\n\nclass BaseDbTable:\n    table_name: str = None\n    columns_description: List[Tuple[str, type]] = None\n    row_type: namedtuple = None\n    columns: namedtuple = None\n    unique_together: tuple = None\n    _lock: threading.Lock = None\n    _lock_storage = defaultdict(threading.Lock)\n\n    def __init__(self, filename):\n        self.filename = filename\n        column_names: List[str] = [it[0] for it in self.columns_description]\n        self.row_type = namedtuple('_', column_names)\n        self.columns = self.row_type(*column_names)\n        self._lock = self._lock_storage[self.filename]\n\n    @contextmanager\n    def db_connection(self):\n        if not self._lock.acquire(timeout=20):\n            m = traceback.format_exc() + \"\\n\"\n            ConanOutput().error(m)\n            raise ConanException(\"Conan failed to acquire database lock in 20s. Maybe the system is \"\n                                 \"under very heavy load. Please report it to Github tickets\")\n        # isolation_level=None, puts it in regular SQLITE autocommit mode, every\n        # connection.execute() will autocommit\n        connection = sqlite3.connect(self.filename, isolation_level=None, timeout=20)\n        try:\n            yield connection\n        finally:\n            connection.close()\n            self._lock.release()\n\n    def create_table(self):\n        def field(name, typename, nullable=False, unique=False):\n            field_str = name\n            if typename is str:\n                field_str += ' text'\n            elif typename is int:\n                field_str += ' integer'\n            else:\n                assert typename is float, f\"sqlite3 type not mapped for type '{typename}'\"\n                field_str += ' real'\n\n            if not nullable:\n                field_str += ' NOT NULL'\n\n            if unique:\n                field_str += ' UNIQUE'\n\n            return field_str\n\n        fields = ', '.join([field(*it) for it in self.columns_description])\n        guard = 'IF NOT EXISTS'\n        table_checks = f\", UNIQUE({', '.join(self.unique_together)})\" if self.unique_together else ''\n        with self.db_connection() as conn:\n            conn.execute(f\"CREATE TABLE {guard} {self.table_name} ({fields} {table_checks});\")\n"
  },
  {
    "path": "conan/internal/cache/home_paths.py",
    "content": "import os\n\nfrom conan.api.output import ConanOutput\n\n_EXTENSIONS_FOLDER = \"extensions\"\n_PLUGINS = \"plugins\"\n\n\nclass HomePaths:\n    \"\"\" pure computing of paths in the home, not caching anything\n    \"\"\"\n    def __init__(self, home_folder):\n        self._home = home_folder\n\n    @property\n    def local_recipes_index_path(self):\n        return os.path.join(self._home, \".local_recipes_index\")\n\n    @property\n    def global_conf_path(self):\n        return os.path.join(self._home, \"global.conf\")\n\n    @property\n    def deployers_path(self):\n        deploy = os.path.join(self._home, _EXTENSIONS_FOLDER, \"deploy\")\n        if os.path.exists(deploy):\n            ConanOutput().warning(\"Use 'deployers' cache folder for deployers instead of 'deploy'\",\n                                  warn_tag=\"deprecated\")\n            return deploy\n        return os.path.join(self._home, _EXTENSIONS_FOLDER, \"deployers\")\n\n    @property\n    def custom_generators_path(self):\n        return os.path.join(self._home, _EXTENSIONS_FOLDER, \"generators\")\n\n    @property\n    def hooks_path(self):\n        return os.path.join(self._home, _EXTENSIONS_FOLDER, \"hooks\")\n\n    @property\n    def wrapper_path(self):\n        return os.path.join(self._home, _EXTENSIONS_FOLDER, _PLUGINS, \"cmd_wrapper.py\")\n\n    @property\n    def profiles_path(self):\n        return os.path.join(self._home, \"profiles\")\n\n    @property\n    def profile_plugin_path(self):\n        return os.path.join(self._home, _EXTENSIONS_FOLDER, _PLUGINS, \"profile.py\")\n\n    @property\n    def auth_remote_plugin_path(self):\n        return os.path.join(self._home, _EXTENSIONS_FOLDER, _PLUGINS, \"auth_remote.py\")\n\n    @property\n    def auth_source_plugin_path(self):\n        return os.path.join(self._home, _EXTENSIONS_FOLDER, _PLUGINS, \"auth_source.py\")\n\n    @property\n    def sign_plugin_path(self):\n        return os.path.join(self._home, _EXTENSIONS_FOLDER, _PLUGINS, \"sign\", \"sign.py\")\n\n    @property\n    def remotes_path(self):\n        return os.path.join(self._home, \"remotes.json\")\n\n    @property\n    def providers_path(self):\n        return os.path.join(self._home, \"audit_providers.json\")\n\n    @property\n    def compatibility_plugin_path(self):\n        return os.path.join(self._home, _EXTENSIONS_FOLDER, _PLUGINS, \"compatibility\")\n\n    @property\n    def default_sources_backup_folder(self):\n        return os.path.join(self._home, \"sources\")\n\n    @property\n    def settings_path(self):\n        return os.path.join(self._home, \"settings.yml\")\n\n    @property\n    def settings_path_user(self):\n        return os.path.join(self._home, \"settings_user.yml\")\n\n    @property\n    def config_version_path(self):\n        return os.path.join(self._home, \"config_version.json\")\n"
  },
  {
    "path": "conan/internal/cache/integrity_check.py",
    "content": "import os\n\nfrom conan.api.model.list import PackagesList\nfrom conan.api.output import ConanOutput\nfrom conan.api.model import PkgReference\nfrom conan.api.model import RecipeReference\n\n\nclass IntegrityChecker:\n    \"\"\"\n    Check:\n        - Performs a corruption integrity check in the cache. This is done by loading the existing\n        conanmanifest.txt and comparing against a computed conanmanifest.txt. It\n        doesn't address someone tampering with the conanmanifest.txt, just accidental\n        modifying of a package contents, like if some file has been added after computing the\n        manifest.\n        This is to be done over the package contents, not the compressed conan_package.tgz\n        artifacts\n    \"\"\"\n    def __init__(self, cache):\n        self._cache = cache\n\n    def check(self, pkg_list) -> PackagesList:\n        corrupted_pkglist = PackagesList()\n        for ref, packages in pkg_list.items():\n            # Check if any of the packages are corrupted\n            if self._recipe_corrupted(ref):\n                # If the recipe is corrupted, all its packages are considered corrupted\n                corrupted_pkglist.add_ref(ref)\n            else:\n                # Do not check any binary if the recipe is corrupted\n                for pref in packages:\n                    if self._package_corrupted(pref):\n                        corrupted_pkglist.add_ref(ref)\n                        # Cannot add package reference without having the recipe reference already added\n                        corrupted_pkglist.add_pref(pref)\n        return corrupted_pkglist\n\n    def _recipe_corrupted(self, ref: RecipeReference):\n        layout = self._cache.recipe_layout(ref)\n        output = ConanOutput(scope=f\"{ref.repr_notime()}\")\n        try:\n            read_manifest, expected_manifest = layout.recipe_manifests()\n        except FileNotFoundError:\n            output.error(\"Manifest missing\", error_type=\"exception\")\n            return True\n        # Filter exports_sources from read manifest if there are no exports_sources locally\n        # This happens when recipe is downloaded without sources (not built from source)\n        export_sources_folder = layout.export_sources()\n        if not os.path.exists(export_sources_folder):\n            read_manifest.file_sums = {k: v for k, v in read_manifest.file_sums.items()\n                                       if not k.startswith(\"export_source\")}\n\n        if read_manifest != expected_manifest:\n            output_lines = [\"\", \"Manifest mismatch\", f\"    Folder: {layout.export()}\"]\n            diff = read_manifest.difference(expected_manifest)\n            for fname, (h1, h2) in diff.items():\n                output_lines.append(f\"        {fname} (manifest: {h1}, file: {h2})\")\n            output.error(\"\\n\".join(output_lines), error_type=\"exception\")\n            return True\n        output.info(\"Integrity check: ok\")\n\n    def _package_corrupted(self, ref: PkgReference):\n        layout = self._cache.pkg_layout(ref)\n        output = ConanOutput(scope=f\"{ref.repr_notime()}\")\n        try:\n            read_manifest, expected_manifest = layout.package_manifests()\n        except FileNotFoundError:\n            output.error(\"Manifest missing\", error_type=\"exception\")\n            return True\n\n        if read_manifest != expected_manifest:\n            output_lines = [\"\", \"Manifest mismatch\", f\"    Folder: {layout.package()}\"]\n            diff = read_manifest.difference(expected_manifest)\n            for fname, (h1, h2) in diff.items():\n                output_lines.append(f\"        {fname} (manifest: {h1}, file: {h2})\")\n            output.error(\"\\n\".join(output_lines), error_type=\"exception\")\n            return True\n        output.info(\"Integrity check: ok\")\n"
  },
  {
    "path": "conan/internal/conan_app.py",
    "content": "import os\n\nfrom conan.internal.api.local.editable import EditablePackages\nfrom conan.internal.cache.cache import PkgCache\nfrom conan.internal.cache.home_paths import HomePaths\nfrom conan.internal.model.conf import ConfDefinition\nfrom conan.internal.graph.proxy import ConanProxy\nfrom conan.internal.graph.python_requires import PyRequireLoader\nfrom conan.internal.graph.range_resolver import RangeResolver\nfrom conan.internal.loader import ConanFileLoader, load_python_file\nfrom conan.internal.rest.remote_manager import RemoteManager\n\n\nclass CmdWrapper:\n    def __init__(self, wrapper):\n        if os.path.isfile(wrapper):\n            mod, _ = load_python_file(wrapper)\n            self._wrapper = mod.cmd_wrapper\n        else:\n            self._wrapper = None\n\n    def wrap(self, cmd, conanfile, **kwargs):\n        if self._wrapper is None:\n            return cmd\n        return self._wrapper(cmd, conanfile=conanfile, **kwargs)\n\n\nclass ConanFileHelpers:\n    def __init__(self, requester, cmd_wrapper, global_conf, cache, home_folder, conan_api):\n        self.requester = requester\n        self.cmd_wrapper = cmd_wrapper\n        self.global_conf = global_conf\n        self.cache = cache\n        self.home_folder = home_folder\n        self.conan_api = conan_api  # Might be None for local-recipes-index\n\n\nclass ConanBasicApp:\n    def __init__(self, conan_api):\n        \"\"\" Needs:\n        - Global configuration\n        - Cache home folder\n        \"\"\"\n        # TODO: Remove this global_conf from here\n        global_conf = conan_api._api_helpers.global_conf  # noqa\n        # TODO: Temporary while refactoring, remove i nthe future\n        self._cache = conan_api._api_helpers.cache # noqa\n        self._remote_manager = conan_api._api_helpers.remote_manager  # noqa\n        self._global_conf = global_conf\n        self.cache_folder = conan_api.home_folder\n        global_editables = conan_api.local.editable_packages\n        ws_editables = conan_api.workspace.packages()\n        self.editable_packages = global_editables.update_copy(ws_editables)\n\n\nclass ConanApp(ConanBasicApp):\n    def __init__(self, conan_api):\n        \"\"\" Needs:\n        - LocalAPI to read editable packages\n        \"\"\"\n        super().__init__(conan_api)\n        legacy_update = self._global_conf.get(\"core:update_policy\", choices=[\"legacy\"])\n        self.proxy = ConanProxy(self._cache, self._remote_manager, self.editable_packages,\n                                legacy_update=legacy_update)\n        self.range_resolver = RangeResolver(self._cache, self._remote_manager, self._global_conf,\n                                            self.editable_packages)\n        cmd_wrap = CmdWrapper(HomePaths(self.cache_folder).wrapper_path)\n        requester = conan_api._api_helpers.requester  # noqa\n        conanfile_helpers = ConanFileHelpers(requester, cmd_wrap, self._global_conf, self._cache,\n                                             self.cache_folder, conan_api)\n        pyreq_loader = PyRequireLoader(self.proxy, self.range_resolver, self._global_conf)\n        self.loader = ConanFileLoader(pyreq_loader, conanfile_helpers)\n\n\nclass LocalRecipesIndexApp:\n    \"\"\"\n    Simplified one, without full API, for the LocalRecipesIndex. Only publicly used fields are:\n    - cache\n    - loader (for the export phase of local-recipes-index)\n    The others are internally use by other collaborators\n    \"\"\"\n    def __init__(self, cache_folder):\n        self.global_conf = ConfDefinition()\n        self.cache = PkgCache(cache_folder, self.global_conf)\n        self.remote_manager = RemoteManager(self.cache, auth_manager=None, home_folder=cache_folder)\n        editable_packages = EditablePackages()\n        self.proxy = ConanProxy(self.cache, self.remote_manager, editable_packages)\n        self.range_resolver = RangeResolver(self.cache, self.remote_manager, self.global_conf,\n                                            editable_packages)\n        pyreq_loader = PyRequireLoader(self.proxy, self.range_resolver, self.global_conf)\n        helpers = ConanFileHelpers(None, CmdWrapper(\"\"), self.global_conf, self.cache, cache_folder, None)\n        self.loader = ConanFileLoader(pyreq_loader, helpers)\n"
  },
  {
    "path": "conan/internal/default_settings.py",
    "content": "import os\n\ndefault_settings_yml = \"\"\"\\\n# This file was generated by Conan. Remove this comment if you edit this file or Conan\n# will destroy your changes.\nos:\n    Windows:\n        subsystem: [null, cygwin, msys, msys2, wsl]\n    WindowsStore:\n        version: [\"8.1\", \"10.0\"]\n    WindowsCE:\n        platform: [ANY]\n        version: [\"5.0\", \"6.0\", \"7.0\", \"8.0\"]\n    Linux:\n    iOS:\n        version: &ios_version\n                   [\"7.0\", \"7.1\", \"8.0\", \"8.1\", \"8.2\", \"8.3\", \"8.4\", \"9.0\", \"9.1\", \"9.2\", \"9.3\",\n                    \"10.0\", \"10.1\", \"10.2\", \"10.3\",\n                    \"11.0\", \"11.1\", \"11.2\", \"11.3\", \"11.4\",\n                    \"12.0\", \"12.1\", \"12.2\", \"12.3\", \"12.4\", \"12.5\",\n                    \"13.0\", \"13.1\", \"13.2\", \"13.3\", \"13.4\", \"13.5\", \"13.6\", \"13.7\",\n                    \"14.0\", \"14.1\", \"14.2\", \"14.3\", \"14.4\", \"14.5\", \"14.6\", \"14.7\", \"14.8\",\n                    \"15.0\", \"15.1\", \"15.2\", \"15.3\", \"15.4\", \"15.5\", \"15.6\", \"15.7\", \"15.8\",\n                    \"16.0\", \"16.1\", \"16.2\", \"16.3\", \"16.4\", \"16.5\", \"16.6\", \"16.7\",\n                    \"17.0\", \"17.1\", \"17.2\", \"17.3\", \"17.4\", \"17.5\", \"17.6\", \"17.7\", \"17.8\",\n                    \"18.0\", \"18.1\", \"18.2\", \"18.3\", \"18.4\", \"18.5\", \"18.6\", \"18.7\",\n                    \"26.0\", \"26.1\", \"26.2\", \"26.3\"]\n        sdk: [\"iphoneos\", \"iphonesimulator\"]\n        sdk_version: [null, \"11.3\", \"11.4\", \"12.0\", \"12.1\", \"12.2\", \"12.4\",\n                        \"13.0\", \"13.1\", \"13.2\", \"13.3\", \"13.4\", \"13.5\", \"13.6\", \"13.7\",\n                        \"14.0\", \"14.1\", \"14.2\", \"14.3\", \"14.4\", \"14.5\", \"15.0\", \"15.2\", \"15.4\",\n                        \"15.5\", \"16.0\", \"16.1\", \"16.2\", \"16.4\", \"17.0\", \"17.1\", \"17.2\", \"17.4\", \"17.5\",\n                        \"18.0\", \"18.1\", \"18.2\", \"18.4\", \"18.5\",\n                        \"26.0\", \"26.1\", \"26.2\"]\n    watchOS:\n        version: [\"4.0\", \"4.1\", \"4.2\", \"4.3\", \"5.0\", \"5.1\", \"5.2\", \"5.3\", \"6.0\", \"6.1\", \"6.2\", \"6.3\",\n                    \"7.0\", \"7.1\", \"7.2\", \"7.3\", \"7.4\", \"7.5\", \"7.6\",\n                    \"8.0\", \"8.1\", \"8.3\", \"8.4\", \"8.5\", \"8.6\", \"8.7\",\n                    \"9.0\",\"9.1\", \"9.2\", \"9.3\", \"9.4\", \"9.5\", \"9.6\",\n                    \"10.0\", \"10.1\", \"10.2\", \"10.3\", \"10.4\", \"10.5\", \"10.6\",\n                    \"11.0\", \"11.1\", \"11.2\", \"11.3\", \"11.4\", \"11.5\", \"11.6\",\n                    \"26.0\", \"26.1\", \"26.2\", \"26.3\"]\n        sdk: [\"watchos\", \"watchsimulator\"]\n        sdk_version: [null, \"4.3\", \"5.0\", \"5.1\", \"5.2\", \"5.3\", \"6.0\", \"6.1\", \"6.2\",\n                        \"7.0\", \"7.1\", \"7.2\", \"7.3\", \"7.4\", \"8.0\", \"8.0.1\", \"8.3\", \"8.5\", \"9.0\", \"9.1\",\n                        \"9.4\", \"10.0\", \"10.1\", \"10.2\", \"10.4\", \"10.5\",\n                        \"11.0\", \"11.1\", \"11.2\", \"11.4\", \"11.5\",\n                        \"26.0\", \"26.1\", \"26.2\"]\n    tvOS:\n        version: [\"11.0\", \"11.1\", \"11.2\", \"11.3\", \"11.4\",\n                    \"12.0\", \"12.1\", \"12.2\", \"12.3\", \"12.4\",\n                    \"13.0\", \"13.2\", \"13.3\", \"13.4\",\n                    \"14.0\", \"14.2\", \"14.3\", \"14.4\", \"14.5\", \"14.6\", \"14.7\",\n                    \"15.0\", \"15.1\", \"15.2\", \"15.3\", \"15.4\", \"15.5\", \"15.6\",\n                    \"16.0\", \"16.1\", \"16.2\", \"16.3\", \"16.4\", \"16.5\", \"16.6\",\n                    \"17.0\", \"17.1\", \"17.2\", \"17.3\", \"17.4\", \"17.5\", \"17.6\",\n                    \"18.0\", \"18.1\", \"18.2\", \"18.3\", \"18.4\", \"18.5\", \"18.6\",\n                    \"26.0\", \"26.1\", \"26.2\", \"26.3\"]\n        sdk: [\"appletvos\", \"appletvsimulator\"]\n        sdk_version: [null, \"11.3\", \"11.4\", \"12.0\", \"12.1\", \"12.2\", \"12.4\",\n                        \"13.0\", \"13.2\", \"13.3\", \"13.4\", \"14.0\", \"14.2\", \"14.3\", \"14.4\", \"14.5\", \"15.0\",\n                        \"15.2\", \"15.4\", \"15.5\", \"16.0\", \"16.1\", \"16.4\", \"17.0\", \"17.1\", \"17.2\", \"17.4\", \"17.5\",\n                        \"18.0\", \"18.1\", \"18.2\", \"18.4\", \"18.5\",\n                        \"26.0\", \"26.1\", \"26.2\"]\n    visionOS:\n        version: [\"1.0\", \"1.1\", \"1.2\", \"1.3\", \"2.0\", \"2.1\", \"2.2\", \"2.3\", \"2.4\", \"2.5\", \"2.6\",\n                  \"26.0\", \"26.1\", \"26.2\", \"26.3\"]\n        sdk: [\"xros\", \"xrsimulator\"]\n        sdk_version: [null, \"1.0\", \"1.1\", \"1.2\", \"1.3\", \"2.0\", \"2.1\", \"2.2\", \"2.4\", \"2.5\",\n                      \"26.0\", \"26.1\", \"26.2\"]\n    Macos:\n        version: [null, \"10.6\", \"10.7\", \"10.8\", \"10.9\", \"10.10\", \"10.11\", \"10.12\", \"10.13\", \"10.14\", \"10.15\",\n                    \"11.0\", \"11.1\", \"11.2\", \"11.3\", \"11.4\", \"11.5\", \"11.6\", \"11.7\",\n                    \"12.0\", \"12.1\", \"12.2\", \"12.3\", \"12.4\", \"12.5\", \"12.6\", \"12.7\",\n                    \"13.0\", \"13.1\", \"13.2\", \"13.3\", \"13.4\", \"13.5\", \"13.6\", \"13.7\",\n                    \"14.0\", \"14.1\", \"14.2\", \"14.3\", \"14.4\", \"14.5\", \"14.6\", \"14.7\",\n                    \"15.0\", \"15.1\", \"15.2\", \"15.3\", \"15.4\", \"15.5\", \"15.6\", \"15.7\",\n                    \"26.0\", \"26.1\", \"26.2\", \"26.3\"]\n        sdk_version: [null, \"10.13\", \"10.14\", \"10.15\", \"11.0\", \"11.1\", \"11.2\", \"11.3\", \"12.0\", \"12.1\",\n                        \"12.3\", \"12.4\", \"13.0\", \"13.1\", \"13.3\", \"14.0\", \"14.2\", \"14.4\", \"14.5\",\n                        \"15.0\", \"15.1\", \"15.2\", \"15.4\", \"15.5\",\n                        \"26.0\", \"26.1\", \"26.2\"]\n        subsystem:\n            null:\n            catalyst:\n                ios_version: *ios_version\n    Android:\n        api_level: [ANY]\n        ndk_version: [null, ANY]\n    FreeBSD:\n    SunOS:\n    AIX:\n    Arduino:\n        board: [ANY]\n    Emscripten:\n    Neutrino:\n        version: [\"6.4\", \"6.5\", \"6.6\", \"7.0\", \"7.1\"]\n    baremetal:\n    VxWorks:\n        version: [\"7\"]\narch: [x86, x86_64, ppc32be, ppc32, ppc64le, ppc64,\n       armv4, armv4i, armv5el, armv5hf, armv6, armv7, armv7hf, armv7s, armv7k, armv8, armv8_32, armv8.3, arm64ec,\n       sparc, sparcv9,\n       mips, mips64, avr, s390, s390x, asm.js, wasm, wasm64, sh4le,\n       e2k-v2, e2k-v3, e2k-v4, e2k-v5, e2k-v6, e2k-v7,\n       riscv64, riscv32,\n       xtensalx6, xtensalx106, xtensalx7,\n       tc131, tc16, tc161, tc162, tc18]\ncompiler:\n    sun-cc:\n        version: [\"5.10\", \"5.11\", \"5.12\", \"5.13\", \"5.14\", \"5.15\"]\n        threads: [null, posix]\n        libcxx: [libCstd, libstdcxx, libstlport, libstdc++]\n    gcc:\n        version: [\"4.1\", \"4.4\", \"4.5\", \"4.6\", \"4.7\", \"4.8\", \"4.9\",\n                    \"5\", \"5.1\", \"5.2\", \"5.3\", \"5.4\", \"5.5\",\n                    \"6\", \"6.1\", \"6.2\", \"6.3\", \"6.4\", \"6.5\",\n                    \"7\", \"7.1\", \"7.2\", \"7.3\", \"7.4\", \"7.5\",\n                    \"8\", \"8.1\", \"8.2\", \"8.3\", \"8.4\", \"8.5\",\n                    \"9\", \"9.1\", \"9.2\", \"9.3\", \"9.4\", \"9.5\",\n                    \"10\", \"10.1\", \"10.2\", \"10.3\", \"10.4\", \"10.5\",\n                    \"11\", \"11.1\", \"11.2\", \"11.3\", \"11.4\", \"11.5\",\n                    \"12\", \"12.1\", \"12.2\", \"12.3\", \"12.4\", \"12.5\",\n                    \"13\", \"13.1\", \"13.2\", \"13.3\", \"13.4\",\n                    \"14\", \"14.1\", \"14.2\", \"14.3\",\n                    \"15\", \"15.1\", \"15.2\"]\n        libcxx: [libstdc++, libstdc++11]\n        threads: [null, posix, win32, mcf]  # Windows MinGW\n        exception: [null, dwarf2, sjlj, seh]  # Windows MinGW\n        cppstd: [null, 98, gnu98, 11, gnu11, 14, gnu14, 17, gnu17, 20, gnu20, 23, gnu23, 26, gnu26]\n        cstd: [null, 99, gnu99, 11, gnu11, 17, gnu17, 23, gnu23]\n    msvc:\n        version: [170, 180, 190, 191, 192, 193, 194, 195]\n        update: [null, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n        runtime: [static, dynamic]\n        runtime_type: [Debug, Release]\n        cppstd: [null, 14, 17, 20, 23]\n        toolset: [null, v110_xp, v120_xp, v140_xp, v141_xp]\n        cstd: [null, 11, 17]\n    clang:\n        version: [\"3.3\", \"3.4\", \"3.5\", \"3.6\", \"3.7\", \"3.8\", \"3.9\", \"4.0\",\n                  \"5.0\", \"6.0\", \"7.0\", \"7.1\",\n                  \"8\", \"9\", \"10\", \"11\", \"12\", \"13\", \"14\", \"15\", \"16\", \"17\",\n                  \"18\", \"19\", \"20\", \"21\", \"22\"]\n        libcxx: [null, libstdc++, libstdc++11, libc++, c++_shared, c++_static]\n        cppstd: [null, 98, gnu98, 11, gnu11, 14, gnu14, 17, gnu17, 20, gnu20, 23, gnu23, 26, gnu26]\n        runtime: [null, static, dynamic]\n        runtime_type: [null, Debug, Release]\n        runtime_version: [null, v140, v141, v142, v143, v144, v145]\n        cstd: [null, 99, gnu99, 11, gnu11, 17, gnu17, 23, gnu23]\n    apple-clang:\n        version: [\"5.0\", \"5.1\", \"6.0\", \"6.1\", \"7.0\", \"7.3\", \"8.0\", \"8.1\", \"9.0\", \"9.1\",\n                  \"10.0\", \"11.0\", \"12.0\", \"13\", \"13.0\", \"13.1\", \"14\", \"14.0\", \"15\", \"15.0\",\n                  \"16\", \"16.0\", \"17\", \"17.0\"]\n        libcxx: [libstdc++, libc++]\n        cppstd: [null, 98, gnu98, 11, gnu11, 14, gnu14, 17, gnu17, 20, gnu20, 23, gnu23, 26, gnu26]\n        cstd: [null, 99, gnu99, 11, gnu11, 17, gnu17, 23, gnu23]\n    intel-cc:\n        version: [\"2021.1\", \"2021.2\", \"2021.3\", \"2021.4\", \"2022.1\", \"2022.2\",\n                  \"2022.3\", \"2023.0\", \"2023.1\", \"2023.2\", \"2024.0\", \"2024.1\",\n                  \"2025.0\", \"2025.1\"]\n        update: [null, ANY]\n        mode: [\"icx\", \"classic\", \"dpcpp\"]\n        libcxx: [null, libstdc++, libstdc++11, libc++]\n        cppstd: [null, 98, gnu98, \"03\", gnu03, 11, gnu11, 14, gnu14, 17, gnu17, 20, gnu20, 23, gnu23]\n        runtime: [null, static, dynamic]\n        runtime_type: [null, Debug, Release]\n    qcc:\n        version: [\"4.4\", \"5.4\", \"8.3\"]\n        libcxx: [cxx, gpp, cpp, cpp-ne, accp, acpp-ne, ecpp, ecpp-ne]\n        cppstd: [null, 98, gnu98, 11, gnu11, 14, gnu14, 17, gnu17]\n    mcst-lcc:\n        version: [\"1.19\", \"1.20\", \"1.21\", \"1.22\", \"1.23\", \"1.24\", \"1.25\"]\n        libcxx: [libstdc++, libstdc++11]\n        cppstd: [null, 98, gnu98, 11, gnu11, 14, gnu14, 17, gnu17, 20, gnu20, 23, gnu23]\n    emcc:\n        # From https://github.com/emscripten-core/emscripten/blob/main/ChangeLog.md\n        # There is no ABI compatibility guarantee between versions\n        version: [ANY]\n        libcxx: [null, libstdc++, libstdc++11, libc++]\n        threads: [null, posix, wasm_workers]\n        cppstd: [null, 98, gnu98, 11, gnu11, 14, gnu14, 17, gnu17, 20, gnu20, 23, gnu23, 26, gnu26]\n        cstd: [null, 99, gnu99, 11, gnu11, 17, gnu17, 23, gnu23]\n\nbuild_type: [null, Debug, Release, RelWithDebInfo, MinSizeRel]\n\"\"\"\n\n\ndef migrate_settings_file(cache_folder):\n    from conan.internal.api.migrations import update_file\n\n    settings_path = os.path.join(cache_folder, \"settings.yml\")\n    update_file(settings_path, default_settings_yml)\n"
  },
  {
    "path": "conan/internal/deploy.py",
    "content": "import filecmp\nimport os\nimport shutil\nimport fnmatch\n\nfrom conan.internal.cache.home_paths import HomePaths\nfrom conan.api.output import ConanOutput\nfrom conan.internal.loader import load_python_file\nfrom conan.internal.errors import conanfile_exception_formatter\nfrom conan.errors import ConanException\nfrom conan.internal.util.files import rmdir, mkdir, save\n\n\ndef _find_deployer(d, cache_deploy_folder):\n    \"\"\" Implements the logic of finding a deployer, with priority:\n    - 1) absolute paths\n    - 2) relative to cwd\n    - 3) in the cache/extensions/deploy folder\n    - 4) built-in\n    \"\"\"\n    def _load(path):\n        mod, _ = load_python_file(path)\n        try:\n            return mod.deploy\n        except AttributeError:\n            raise ConanException(f\"Deployer does not contain 'deploy()' function: {path}\")\n\n    if not d.endswith(\".py\"):\n        d += \".py\"  # Deployers must be python files\n    if os.path.isabs(d):\n        return _load(d)\n    cwd = os.getcwd()\n    local_path = os.path.normpath(os.path.join(cwd, d))\n    if os.path.isfile(local_path):\n        return _load(local_path)\n    cache_path = os.path.join(cache_deploy_folder, d)\n    if os.path.isfile(cache_path):\n        return _load(cache_path)\n    builtin_deploy = {\"full_deploy.py\": full_deploy,\n                      \"direct_deploy.py\": direct_deploy,\n                      \"runtime_deploy.py\": runtime_deploy,\n                      \"cyclone_1.6.py\": cyclonedx_1_6,\n                      \"cyclone_1.4.py\": cyclonedx_1_4}.get(d)\n    if builtin_deploy is not None:\n        return builtin_deploy\n    raise ConanException(f\"Cannot find deployer '{d}'\")\n\n\ndef do_deploys(home_folder, graph, deploy, deploy_package, deploy_folder):\n    try:\n        mkdir(deploy_folder)\n    except Exception as e:\n        raise ConanException(f\"Deployer folder cannot be created '{deploy_folder}':\\n{e}\")\n    # handle the recipe deploy()\n    if deploy_package:\n        # Similar processing as BuildMode class\n        excluded = [p[1:] for p in deploy_package if p[0] in [\"!\", \"~\"]]\n        included = [p for p in deploy_package if p[0] not in [\"!\", \"~\"]]\n        for node in graph.ordered_iterate():\n            conanfile = node.conanfile\n            if not conanfile.ref:  # virtual or conanfile.txt, can't have deployer\n                continue\n            consumer = conanfile._conan_is_consumer  # noqa\n            if any(conanfile.ref.matches(p, consumer) for p in excluded):\n                continue\n            if not any(conanfile.ref.matches(p, consumer) for p in included):\n                continue\n            if hasattr(conanfile, \"deploy\"):\n                conanfile.output.info(\"Executing deploy()\")\n                conanfile.deploy_folder = deploy_folder\n                with conanfile_exception_formatter(conanfile, \"deploy\"):\n                    conanfile.deploy()\n    # Handle the deploys\n    cache = HomePaths(home_folder)\n    for d in deploy or []:\n        deployer = _find_deployer(d, cache.deployers_path)\n        # IMPORTANT: Use always kwargs to not break if it changes in the future\n        deployer(graph=graph, output_folder=deploy_folder)\n\n\ndef full_deploy(graph, output_folder):\n    \"\"\"\n    Deploys to output_folder + host/dep/0.1/Release/x86_64 subfolder\n    \"\"\"\n    # TODO: This deployer needs to be put somewhere else\n    # TODO: Document that this will NOT work with editables\n    conanfile = graph.root.conanfile\n    conanfile.output.info(f\"Conan built-in full deployer to {output_folder}\")\n    for dep in conanfile.dependencies.values():\n        if dep.package_folder is None:\n            continue\n        folder_name = os.path.join(\"full_deploy\", dep.context, dep.ref.name, str(dep.ref.version))\n        build_type = dep.info.settings.get_safe(\"build_type\")\n        arch = dep.info.settings.get_safe(\"arch\")\n        if build_type:\n            folder_name = os.path.join(folder_name, build_type)\n        if arch:\n            folder_name = os.path.join(folder_name, arch)\n        _deploy_single(dep, conanfile, output_folder, folder_name)\n\n\ndef runtime_deploy(graph, output_folder):\n    \"\"\"\n    Deploy all the shared libraries and the executables of the dependencies in a flat directory.\n\n    It preserves symlinks in case the configuration tools.deployer:symlinks is True.\n    It preserves the directory structure when having subfolders\n    \"\"\"\n    conanfile = graph.root.conanfile\n    output = ConanOutput(scope=\"runtime_deploy\")\n    output.info(f\"Deploying dependencies runtime to folder: {output_folder}\")\n    output.warning(\"This deployer is experimental and subject to change. \"\n                   \"Please give feedback at https://github.com/conan-io/conan/issues\")\n    mkdir(output_folder)\n    symlinks = conanfile.conf.get(\"tools.deployer:symlinks\", check_type=bool, default=True)\n    for req, dep in conanfile.dependencies.host.items():\n        if not req.run:  # Avoid deploying unused binaries at runtime\n            continue\n        if dep.package_folder is None:\n            output.warning(f\"{dep.ref} does not have any package folder, skipping binary\")\n            continue\n        count = 0\n        cpp_info = dep.cpp_info.aggregated_components()\n        for bindir in cpp_info.bindirs:\n            if not os.path.isdir(bindir):\n                output.warning(f\"{dep.ref} {bindir} does not exist\")\n                continue\n            count += _flatten_directory(dep, bindir, output_folder, symlinks)\n\n        for libdir in cpp_info.libdirs:\n            if not os.path.isdir(libdir):\n                output.warning(f\"{dep.ref} {libdir} does not exist\")\n                continue\n            count += _flatten_directory(dep, libdir, output_folder, symlinks, [\".dylib*\", \".so*\"])\n\n        output.info(f\"Copied {count} files from {dep.ref}\")\n    conanfile.output.success(f\"Runtime deployed to folder: {output_folder}\")\n\n\ndef cyclonedx_1_4(graph, output_folder):\n    from conan.tools.sbom import cyclonedx_1_4\n    import json\n    sbom = cyclonedx_1_4(graph.root.conanfile)\n    save(os.path.join(output_folder, \"sbom-cyclonedx-1.4.json\"), json.dumps(sbom, indent=2))\n\n\ndef cyclonedx_1_6(graph, output_folder):\n    from conan.tools.sbom import cyclonedx_1_6\n    import json\n    sbom = cyclonedx_1_6(graph.root.conanfile)\n    save(os.path.join(output_folder, \"sbom-cyclonedx-1.6.json\"), json.dumps(sbom, indent=2))\n\n\ndef _flatten_directory(dep, src_dir, output_dir, symlinks, extension_filter=None):\n    \"\"\"\n    Copy all the files from the source directory in a flat output directory, respecting subfolders.\n    An optional string, named extension_filter, can be set to copy only the files with\n    the listed extensions.\n    \"\"\"\n    file_count = 0\n\n    output = ConanOutput(scope=\"runtime_deploy\")\n    for src_dirpath, _, src_filenames in os.walk(src_dir, followlinks=symlinks):\n        rel_path = os.path.relpath(src_dirpath, src_dir)\n        for src_filename in src_filenames:\n            if extension_filter and not any(fnmatch.fnmatch(src_filename, f'*{ext}') for ext in extension_filter):\n                continue\n\n            src_filepath = os.path.join(src_dirpath, src_filename)\n            dest_filepath = os.path.join(output_dir, rel_path, src_filename)\n\n            if not symlinks and os.path.islink(src_filepath):\n                continue\n\n            if not os.path.exists(os.path.dirname(dest_filepath)):\n                os.makedirs(os.path.dirname(dest_filepath))\n\n            if os.path.exists(dest_filepath):\n                if filecmp.cmp(src_filepath, dest_filepath):  # Be efficient, do not copy\n                    output.verbose(f\"{dest_filepath} exists with same contents, skipping copy\")\n                    continue\n                else:\n                    output.warning(f\"{dest_filepath} exists and will be overwritten\")\n\n            try:\n                file_count += 1\n                # INFO: When follow_symlinks is false, and src is a symbolic link, it tries to\n                # copy all metadata from the src symbolic link to the newly created dst link\n                shutil.copy2(src_filepath, dest_filepath, follow_symlinks=not symlinks)\n                output.verbose(f\"Copied {src_filepath} into {output_dir}\")\n            except Exception as e:\n                if \"WinError 1314\" in str(e):\n                    ConanOutput().error(\"runtime_deploy: Windows symlinks require admin privileges \"\n                                        \"or 'Developer mode = ON'\", error_type=\"exception\")\n                raise ConanException(f\"runtime_deploy: Copy of '{dep}' files failed: {e}.\\nYou can \"\n                                     f\"use 'tools.deployer:symlinks' conf to disable symlinks\")\n    return file_count\n\n\ndef _deploy_single(dep, conanfile, output_folder, folder_name):\n    new_folder = os.path.join(output_folder, folder_name)\n    rmdir(new_folder)\n    symlinks = conanfile.conf.get(\"tools.deployer:symlinks\", check_type=bool, default=True)\n    try:\n        shutil.copytree(dep.package_folder, new_folder, symlinks=symlinks)\n    except Exception as e:\n        if \"WinError 1314\" in str(e):\n            ConanOutput().error(\"full_deploy: Symlinks in Windows require admin privileges \"\n                                \"or 'Developer mode = ON'\", error_type=\"exception\")\n        raise ConanException(f\"full_deploy: The copy of '{dep}' files failed: {e}.\\nYou can \"\n                             f\"use 'tools.deployer:symlinks' conf to disable symlinks\")\n    dep.set_deploy_folder(new_folder)\n\n\ndef direct_deploy(graph, output_folder):\n    \"\"\"\n    Deploys to output_folder a single package,\n    \"\"\"\n    # TODO: This deployer needs to be put somewhere else\n    # TODO: Document that this will NOT work with editables\n    output_folder = os.path.join(output_folder, \"direct_deploy\")\n    conanfile = graph.root.conanfile\n    conanfile.output.info(f\"Conan built-in pkg deployer to {output_folder}\")\n    # If the argument is --requires, the current conanfile is a virtual one with 1 single\n    # dependency, the \"reference\" package. If the argument is a local path, then all direct\n    # dependencies\n    for dep in conanfile.dependencies.filter({\"direct\": True}).values():\n        _deploy_single(dep, conanfile, output_folder, dep.ref.name)\n"
  },
  {
    "path": "conan/internal/errors.py",
    "content": "import traceback\nfrom contextlib import contextmanager\n\nfrom conan.errors import ConanException, ConanInvalidConfiguration\n\n\n@contextmanager\ndef conanfile_remove_attr(conanfile, names, method):\n    \"\"\" remove some self.xxxx attribute from the class, so it raises an exception if used\n    within a given conanfile method\n    \"\"\"\n    original_class = type(conanfile)\n\n    def _prop(attr_name):\n        def _m(_):\n            raise ConanException(f\"'self.{attr_name}' access in '{method}()' method is forbidden\")\n        return property(_m)\n\n    try:\n        new_class = type(original_class.__name__, (original_class, ), {})\n        conanfile.__class__ = new_class\n        for name in names:\n            setattr(new_class, name, _prop(name))\n        yield\n    finally:\n        conanfile.__class__ = original_class\n\n\n@contextmanager\ndef conanfile_exception_formatter(conanfile, funcname):\n    \"\"\"\n    Decorator to throw an exception formatted with the line of the conanfile where the error ocurrs.\n    \"\"\"\n    try:\n        yield\n    except ConanInvalidConfiguration as exc:\n        # TODO: This is never called from `conanfile.validate()` but could be called from others\n        msg = \"{}: Invalid configuration: {}\".format(str(conanfile), exc)\n        raise ConanInvalidConfiguration(msg)\n    except Exception as exc:\n        m = scoped_traceback(f\"{conanfile}: Error in {funcname}() method\", exc, scope=\"conanfile.py\")\n        from conan.api.output import LEVEL_DEBUG, ConanOutput\n        if ConanOutput.level_allowed(LEVEL_DEBUG):\n            m = traceback.format_exc() + \"\\n\" + m\n        raise ConanException(m)\n\n\ndef scoped_traceback(header_msg, exception, scope):\n    \"\"\"\n    It will iterate the traceback lines, when it finds that the source code is inside the users\n    conanfile it \"start recording\" the messages, when the trace exits the conanfile we return\n    the traces.\n    \"\"\"\n    import sys\n    content_lines = []\n    try:\n        scope_reached = False\n        tb = sys.exc_info()[2]\n        index = 0\n\n        while True:  # If out of index will raise and will be captured later\n            # 40 levels of nested functions max, get the latest\n            filepath, line, name, contents = traceback.extract_tb(tb, 40)[index]\n            filepath = filepath.replace(\"\\\\\", \"/\")\n            if scope not in filepath:  # Avoid show trace from internal conan source code\n                if scope_reached:  # The error goes to internal code, exit print\n                    break\n            else:\n                if not scope_reached:  # First line\n                    msg = f\"{header_msg}, line {line}\\n\\t{contents}\"\n                else:\n                    msg = (f\"while calling '{name}', line {line}\\n\\t{contents}\"\n                           if line else \"\\n\\t%s\" % contents)\n                content_lines.append(msg)\n                scope_reached = True\n            index += 1\n    except IndexError:\n        pass\n    ret = \"\\n\".join(content_lines)\n    ret += \"\\n\\t%s: %s\" % (exception.__class__.__name__, str(exception))\n    return ret\n\n\nclass ConanReferenceDoesNotExistInDB(ConanException):\n    \"\"\" Reference does not exist in cache db \"\"\"\n    pass\n\n\nclass ConanReferenceAlreadyExistsInDB(ConanException):\n    \"\"\" Reference already exists in cache db \"\"\"\n    pass\n\n\nclass ConanConnectionError(ConanException):\n    pass\n\n\nclass InternalErrorException(ConanException):\n    \"\"\"\n         Generic 500 error\n    \"\"\"\n    pass\n\n\nclass RequestErrorException(ConanException):\n    \"\"\"\n         Generic 400 error\n    \"\"\"\n    pass\n\n\nclass AuthenticationException(ConanException):  # 401\n    \"\"\"\n        401 error\n    \"\"\"\n    pass\n\n\nclass ForbiddenException(ConanException):  # 403\n    \"\"\"\n        403 error\n    \"\"\"\n    pass\n\n\nclass NotFoundException(ConanException):  # 404\n    \"\"\"\n        404 error\n    \"\"\"\n    pass\n\n\nclass RecipeNotFoundException(NotFoundException):\n\n    def __init__(self, ref):\n        super().__init__(f\"Recipe not found: '{ref.repr_notime()}'\")\n\n\nclass PackageNotFoundException(NotFoundException):\n\n    def __init__(self, pref):\n        super().__init__(f\"Binary package not found: '{pref.repr_notime()}'\")\n\n\nEXCEPTION_CODE_MAPPING = {InternalErrorException: 500,\n                          RequestErrorException: 400,\n                          AuthenticationException: 401,\n                          ForbiddenException: 403,\n                          NotFoundException: 404,\n                          RecipeNotFoundException: 404,\n                          PackageNotFoundException: 404}\n"
  },
  {
    "path": "conan/internal/graph/__init__.py",
    "content": ""
  },
  {
    "path": "conan/internal/graph/build_mode.py",
    "content": "from conan.api.output import ConanOutput\nfrom conan.errors import ConanException\nfrom conan.internal.model.recipe_ref import ref_matches\n\n\nclass BuildMode:\n    \"\"\" build_mode => [\"*\"] if user wrote \"--build=*\"\n                   => [\"hello\", \"bye\"] if user wrote \"--build hello --build bye\"\n                   => [\"hello/0.1@foo/bar\"] if user wrote \"--build hello/0.1@foo/bar\"\n                   => [\"!foo\"] or [\"~foo\"] means exclude when building all from sources\n    \"\"\"\n    def __init__(self, params):\n        self._missing = False\n        self._never = False\n        self.cascade = False\n        self._editable = False\n        self._patterns = []\n        self._build_missing_patterns = []\n        self._build_missing_excluded = []\n        self._build_compatible_patterns = []\n        self._build_compatible_excluded = []\n        self._excluded_patterns = []\n        if params is None:\n            return\n\n        assert isinstance(params, list)\n        assert len(params) > 0  # Not empty list\n\n        for param in params:\n            if param == \"missing\":\n                self._missing = True\n            elif param == \"editable\":\n                self._editable = True\n            elif param == \"never\":\n                self._never = True\n            elif param == \"cascade\":\n                self.cascade = True\n                ConanOutput().warning(\"Using build-mode 'cascade' is generally inefficient and it \"\n                                      \"shouldn't be used. Use 'package_id' and 'package_id_modes' \"\n                                      \"for more efficient re-builds\")\n            else:\n                if param.startswith(\"missing:\"):\n                    clean_pattern = param[len(\"missing:\"):]\n                    if clean_pattern and clean_pattern[0] in [\"!\", \"~\"]:\n                        self._build_missing_excluded.append(clean_pattern[1:])\n                    else:\n                        self._build_missing_patterns.append(clean_pattern)\n                elif param == \"compatible\":\n                    self._build_compatible_patterns = [\"*\"]\n                elif param.startswith(\"compatible:\"):\n                    clean_pattern = param[len(\"compatible:\"):]\n                    if clean_pattern and clean_pattern[0] in [\"!\", \"~\"]:\n                        self._build_compatible_excluded.append(clean_pattern[1:])\n                    else:\n                        self._build_compatible_patterns.append(clean_pattern)\n                else:\n                    clean_pattern = param\n                    if clean_pattern and clean_pattern[0] in [\"!\", \"~\"]:\n                        self._excluded_patterns.append(clean_pattern[1:])\n                    else:\n                        self._patterns.append(clean_pattern)\n\n            if self._never and (self._missing or self._patterns or self.cascade):\n                raise ConanException(\"--build=never not compatible with other options\")\n\n    @property\n    def editable(self):\n        # we can make this conditional on the context in the future\n        return self._editable\n\n    def forced(self, conan_file, ref, with_deps_to_build=False):\n        # TODO: ref can be obtained from conan_file\n\n        for pattern in self._excluded_patterns:\n            if ref_matches(ref, pattern, is_consumer=conan_file._conan_is_consumer):  # noqa\n                conan_file.output.info(\"Excluded build from source\")\n                return False\n\n        if conan_file.build_policy == \"never\":  # this package has been export-pkg\n            return False\n\n        if self._never:\n            return False\n\n        if conan_file.build_policy == \"always\":\n            raise ConanException(\"{}: build_policy='always' has been removed. \"\n                                 \"Please use 'missing' only\".format(conan_file))\n\n        if self.cascade and with_deps_to_build:\n            return True\n\n        # Patterns to match, if package matches pattern, build is forced\n        for pattern in self._patterns:\n            if ref_matches(ref, pattern, is_consumer=conan_file._conan_is_consumer):  # noqa\n                return True\n        return False\n\n    def allowed(self, conan_file):\n        if self._never or conan_file.build_policy == \"never\":  # this package has been export-pkg\n            return False\n        if self._missing:\n            return True\n        if conan_file.build_policy == \"missing\":\n            conan_file.output.info(\"Building package from source as defined by \"\n                                   \"build_policy='missing'\")\n            return True\n        if self.should_build_missing(conan_file):\n            return True\n        if self.allowed_compatible(conan_file):\n            return True\n        return False\n\n    def allowed_compatible(self, conanfile):\n        if self._build_compatible_excluded:\n            for pattern in self._build_compatible_excluded:\n                if ref_matches(conanfile.ref, pattern, is_consumer=False):\n                    return False\n            return True  # If it has not been excluded by the negated patterns, it is included\n\n        for pattern in self._build_compatible_patterns:\n            if ref_matches(conanfile.ref, pattern, is_consumer=conanfile._conan_is_consumer):  # noqa\n                return True\n\n    def should_build_missing(self, conanfile):\n        if self._build_missing_excluded:\n            for pattern in self._build_missing_excluded:\n                if ref_matches(conanfile.ref, pattern, is_consumer=False):\n                    return False\n            return True  # If it has not been excluded by the negated patterns, it is included\n\n        for pattern in self._build_missing_patterns:\n            if ref_matches(conanfile.ref, pattern, is_consumer=conanfile._conan_is_consumer):  # noqa\n                return True\n"
  },
  {
    "path": "conan/internal/graph/compatibility.py",
    "content": "import os\nfrom collections import OrderedDict\n\nfrom conan.api.output import ConanOutput\nfrom conan.internal.cache.home_paths import HomePaths\nfrom conan.internal.graph.compute_pid import run_validate_package_id\nfrom conan.internal.loader import load_python_file\nfrom conan.internal.errors import conanfile_exception_formatter, scoped_traceback\nfrom conan.errors import ConanException\nfrom conan.internal.api.migrations import CONAN_GENERATED_COMMENT\n\n# TODO: Define other compatibility besides applications\nfrom conan.internal.util.files import load, save\n\n_default_compat = \"\"\"\\\n# This file was generated by Conan. Remove this comment if you edit this file or Conan\n# will destroy your changes.\n\nfrom conan.tools.build import supported_cppstd, supported_cstd\nfrom conan.errors import ConanException\n\n\ndef cppstd_compat(conanfile):\n    # It will try to find packages with all the cppstd versions\n    extension_properties = getattr(conanfile, \"extension_properties\", {})\n    compiler = conanfile.settings.get_safe(\"compiler\")\n    compiler_version = conanfile.settings.get_safe(\"compiler.version\")\n    cppstd = conanfile.settings.get_safe(\"compiler.cppstd\")\n    if not compiler or not compiler_version:\n        return []\n    factors = []  # List of list, each sublist is a potential combination\n    if cppstd is not None and extension_properties.get(\"compatibility_cppstd\") is not False:\n        cppstd_possible_values = supported_cppstd(conanfile)\n        if cppstd_possible_values is None:\n            conanfile.output.warning(f'No cppstd compatibility defined for compiler \"{compiler}\"')\n        else: # The current cppst must be included in case there is other factor\n            factors.append([{\"compiler.cppstd\": v} for v in cppstd_possible_values])\n\n    cstd = conanfile.settings.get_safe(\"compiler.cstd\")\n    if cstd is not None and extension_properties.get(\"compatibility_cstd\") is not False:\n        cstd_possible_values = supported_cstd(conanfile)\n        if cstd_possible_values is None:\n            conanfile.output.warning(f'No cstd compatibility defined for compiler \"{compiler}\"')\n        else:\n            factors.append([{\"compiler.cstd\": v} for v in cstd_possible_values if v != cstd])\n    return factors\n\n\ndef compatibility(conanfile):\n    # By default, different compiler.cppstd are compatible\n    # factors is a list of lists\n    factors = cppstd_compat(conanfile)\n\n    # MSVC 194->193 fallback compatibility\n    compiler = conanfile.settings.get_safe(\"compiler\")\n    compiler_version = conanfile.settings.get_safe(\"compiler.version\")\n    if compiler == \"msvc\":\n        msvc_fallback = {\"194\": \"193\"}.get(compiler_version)\n        if msvc_fallback:\n            factors.append([{\"compiler.version\": msvc_fallback}])\n\n    # Append more factors for your custom compatibility rules here\n\n    # Combine factors to compute all possible configurations\n    combinations = _factors_combinations(factors)\n    # Final compatibility settings combinations to check\n    return [{\"settings\": [(k, v) for k, v in comb.items()]} for comb in combinations]\n\n\ndef _factors_combinations(factors):\n    combinations = []\n    for factor in factors:\n        if not combinations:\n            combinations = factor\n            continue\n        new_combinations = []\n        for comb in combinations:\n            for f in factor:\n                new_comb = comb.copy()\n                new_comb.update(f)\n                new_combinations.append(new_comb)\n        combinations.extend(new_combinations)\n    return combinations\n\"\"\"\n\n\ndef migrate_compatibility_files(cache_folder):\n    compatible_folder = HomePaths(cache_folder).compatibility_plugin_path\n    compatibility_file = os.path.join(compatible_folder, \"compatibility.py\")\n    cppstd_compat_file = os.path.join(compatible_folder, \"cppstd_compat.py\")\n\n    def _is_migratable(file_path):\n        if not os.path.exists(file_path):\n            return True\n        content = load(file_path)\n        first_line = content.lstrip().split(\"\\n\", 1)[0]\n        return CONAN_GENERATED_COMMENT in first_line\n\n    if _is_migratable(compatibility_file) and _is_migratable(cppstd_compat_file):\n        compatibility_exists = os.path.exists(compatibility_file)\n        needs_update = not compatibility_exists or load(compatibility_file) != _default_compat\n        if needs_update:\n            save(compatibility_file, _default_compat)\n            if compatibility_exists:\n                ConanOutput().success(\"Migration: Successfully updated compatibility.py\")\n        if os.path.exists(cppstd_compat_file):\n            os.remove(cppstd_compat_file)\n\n\nclass BinaryCompatibility:\n\n    def __init__(self, compatibility_plugin_folder, hook_manager):\n        self._hook_manager = hook_manager\n        compatibility_file = os.path.join(compatibility_plugin_folder, \"compatibility.py\")\n        if not os.path.exists(compatibility_file):\n            raise ConanException(\"The 'compatibility.py' plugin file doesn't exist. If you want \"\n                                 \"to disable it, edit its contents instead of removing it\")\n        mod, _ = load_python_file(compatibility_file)\n        self._compatibility = mod.compatibility\n\n    def compatibles(self, conanfile):\n        compat_infos = []\n        if hasattr(conanfile, \"compatibility\"):\n            with conanfile_exception_formatter(conanfile, \"compatibility\"):\n                recipe_compatibles = conanfile.compatibility()\n                compat_infos.extend(self._compatible_infos(conanfile, recipe_compatibles))\n\n        try:\n            plugin_compatibles = self._compatibility(conanfile)\n        except Exception as e:\n            msg = f\"Error while processing 'compatibility.py' plugin for '{conanfile}'\"\n            msg = scoped_traceback(msg, e, scope=\"plugins/compatibility\")\n            raise ConanException(msg)\n        compat_infos.extend(self._compatible_infos(conanfile, plugin_compatibles))\n        if not compat_infos:\n            return {}\n\n        result = OrderedDict()\n        original_info = conanfile.info\n        original_settings = conanfile.settings\n        original_settings_target = conanfile.settings_target\n        original_options = conanfile.options\n        for c in compat_infos:\n            # we replace the conanfile, so ``validate()`` and ``package_id()`` can\n            # use the compatible ones\n            conanfile.info = c\n            conanfile.settings = c.settings\n            conanfile.settings_target = c.settings_target\n            conanfile.options = c.options\n            run_validate_package_id(conanfile, self._hook_manager)\n            pid = c.package_id()\n            if pid not in result and not c.invalid:\n                result[pid] = c\n        # Restore the original state\n        conanfile.info = original_info\n        conanfile.settings = original_settings\n        conanfile.settings_target = original_settings_target\n        conanfile.options = original_options\n        return result\n\n    @staticmethod\n    def _compatible_infos(conanfile, compatibles):\n        result = []\n        if compatibles:\n            for elem in compatibles:\n                compat_info = conanfile.original_info.clone()\n                compat_info.compatibility_delta = elem\n                settings = elem.get(\"settings\")\n                if settings:\n                    compat_info.settings.update_values(settings, raise_undefined=False)\n                options = elem.get(\"options\")\n                if options:\n                    compat_info.options.update(options_values=OrderedDict(options))\n                result.append(compat_info)\n                settings_target = elem.get(\"settings_target\")\n                if settings_target and compat_info.settings_target:\n                    compat_info.settings_target.update_values(settings_target, raise_undefined=False)\n        return result\n"
  },
  {
    "path": "conan/internal/graph/compute_pid.py",
    "content": "from collections import OrderedDict\n\nfrom conan.internal.errors import conanfile_remove_attr, conanfile_exception_formatter\nfrom conan.errors import ConanException, ConanInvalidConfiguration\nfrom conan.internal.methods import auto_header_only_package_id\nfrom conan.internal.model.info import (ConanInfo, RequirementsInfo, RequirementInfo,\n                                       PythonRequiresInfo)\nfrom conan.internal.model.pkg_type import PackageType\n\n\ndef compute_package_id(node, modes, config_version, hook_manager):\n    \"\"\"\n    Compute the binary package ID of this node\n    \"\"\"\n    conanfile = node.conanfile\n    unknown_mode, non_embed_mode, embed_mode, python_mode, build_mode = modes\n    python_requires = getattr(conanfile, \"python_requires\", None)\n    if python_requires:\n        python_requires = python_requires.info_requires()\n\n    data = OrderedDict()\n    build_data = OrderedDict()\n    for require, transitive in node.transitive_deps.items():\n        dep_node = transitive.node\n        require.deduce_package_id_mode(conanfile.package_type, dep_node,\n                                       non_embed_mode, embed_mode, build_mode, unknown_mode)\n        if require.package_id_mode is not None:\n            req_info = RequirementInfo(dep_node.pref.ref, dep_node.pref.package_id,\n                                       require.package_id_mode)\n            if require.build:\n                build_data[require] = req_info\n            else:\n                data[require] = req_info\n\n    if conanfile.vendor:  # Make the package_id fully independent of dependencies versions\n        data, build_data = OrderedDict(), OrderedDict()  # TODO, cleaner, now minimal diff\n\n    reqs_info = RequirementsInfo(data)\n    build_requires_info = RequirementsInfo(build_data)\n    python_requires = PythonRequiresInfo(python_requires, python_mode)\n    try:\n        copied_options = conanfile.options.copy_conaninfo_options()\n    except ConanException as e:\n        raise ConanException(f\"{conanfile}: {e}\")\n\n    conanfile.info = ConanInfo(settings=conanfile.settings.copy_conaninfo_settings(),\n                               options=copied_options,\n                               reqs_info=reqs_info,\n                               build_requires_info=build_requires_info,\n                               python_requires=python_requires,\n                               conf=conanfile.conf.copy_conaninfo_conf(),\n                               config_version=config_version.copy() if config_version else None)\n    conanfile.original_info = conanfile.info.clone()\n\n    # To account for effect of headers into consumers, like shared/static variability\n    # It affects to both embed and not embed, that would imply some \"repetition\" of the information\n    # in embed cases embedding the full package_id, but it is useful to have that info explicit too\n    if conanfile.package_type and conanfile.package_type in [PackageType.SHARED, PackageType.STATIC,\n                                                             PackageType.APP]:\n        for require, transitive in node.transitive_deps.items():\n            if require.headers:\n                header_opts = getattr(transitive.node.conanfile, \"package_id_abi_options\", ())\n                for pkg_id_option in header_opts:\n                    v = getattr(transitive.node.conanfile.options, pkg_id_option)\n                    setattr(conanfile.info.options[f\"{transitive.node.name}/*\"], pkg_id_option, v)\n\n    run_validate_package_id(conanfile, hook_manager)\n\n    if conanfile.info.settings_target:\n        # settings_target has beed added to conan package via package_id api\n        conanfile.original_info.settings_target = conanfile.info.settings_target\n\n    info = conanfile.info\n    node.package_id = info.package_id()\n\n\ndef run_validate_package_id(conanfile, hook_manager):\n    # IMPORTANT: This validation code must run before calling info.package_id(), to mark \"invalid\"\n    if hasattr(conanfile, \"validate_build\"):\n        with conanfile_exception_formatter(conanfile, \"validate_build\"):\n            with conanfile_remove_attr(conanfile, ['cpp_info'], \"validate_build\"):\n                try:\n                    conanfile.validate_build()\n                except ConanInvalidConfiguration as e:\n                    # This 'cant_build' will be ignored if we don't have to build the node.\n                    conanfile.info.cant_build = str(e)\n\n    if hasattr(conanfile, \"validate\") or hook_manager.validate_hook:\n        with conanfile_exception_formatter(conanfile, \"validate\"):\n            with conanfile_remove_attr(conanfile, ['cpp_info'], \"validate\"):\n                try:\n                    if hook_manager.validate_hook:\n                        hook_manager.execute(\"pre_validate\", conanfile=conanfile)\n                    if hasattr(conanfile, \"validate\"):\n                        conanfile.validate()\n                    if hook_manager.validate_hook:\n                        hook_manager.execute(\"post_validate\", conanfile=conanfile)\n                except ConanInvalidConfiguration as e:\n                    conanfile.info.invalid = str(e)\n\n    # Once we are done, call package_id() to narrow and change possible values\n    if hasattr(conanfile, \"package_id\"):\n        with conanfile_exception_formatter(conanfile, \"package_id\"):\n            with conanfile_remove_attr(conanfile, ['cpp_info', 'settings', 'options'], \"package_id\"):\n                conanfile.package_id()\n    elif \"auto_header_only\" in conanfile.implements:\n        auto_header_only_package_id(conanfile)\n    if hook_manager.post_package_id_hook:\n        with conanfile_exception_formatter(conanfile, \"package_id\"):\n            with conanfile_remove_attr(conanfile, ['cpp_info', 'settings', 'options'], \"package_id\"):\n                hook_manager.execute(\"post_package_id\", conanfile=conanfile)\n\n    conanfile.info.validate()\n"
  },
  {
    "path": "conan/internal/graph/graph.py",
    "content": "from collections import OrderedDict\n\nfrom conan.internal.graph.graph_error import GraphError, GraphConflictError\nfrom conan.api.output import ConanOutput\nfrom conan.api.model import PkgReference\nfrom conan.api.model import RecipeReference\n\nRECIPE_DOWNLOADED = \"Downloaded\"\nRECIPE_INCACHE = \"Cache\"  # The previously installed recipe in cache is being used\nRECIPE_UPDATED = \"Updated\"\nRECIPE_INCACHE_DATE_UPDATED = \"Cache (Updated date)\"\nRECIPE_NEWER = \"Newer\"  # The local recipe is  modified and newer timestamp than server\nRECIPE_NOT_IN_REMOTE = \"Not in remote\"\nRECIPE_UPDATEABLE = \"Update available\"  # The update of recipe is available (only in conan info)\n# These recipes do not have a full reference, not in the cache\nRECIPE_EDITABLE = \"Editable\"\nRECIPE_CONSUMER = \"Consumer\"  # A conanfile from the user\nRECIPE_VIRTUAL = \"Cli\"  # A virtual conanfile (dynamic in memory conanfile)\nRECIPE_PLATFORM = \"Platform\"\n\nBINARY_CACHE = \"Cache\"\nBINARY_DOWNLOAD = \"Download\"\nBINARY_UPDATE = \"Update\"\nBINARY_BUILD = \"Build\"\nBINARY_MISSING = \"Missing\"\nBINARY_SKIP = \"Skip\"\nBINARY_EDITABLE = \"Editable\"\nBINARY_EDITABLE_BUILD = \"EditableBuild\"\nBINARY_INVALID = \"Invalid\"\nBINARY_PLATFORM = \"Platform\"\n\nCONTEXT_HOST = \"host\"\nCONTEXT_BUILD = \"build\"\n\n\nclass TransitiveRequirement:\n    def __init__(self, require, node):\n        self.require = require\n        self.node = node\n\n    def __repr__(self):\n        return \"Require: {}, Node: {}\".format(repr(self.require), repr(self.node))\n\n\nclass Node:\n\n    def __init__(self, ref, conanfile, context, recipe=None, path=None, test=False):\n        self.ref = ref\n        self.path = path  # path to the consumer conanfile.xx for consumer, None otherwise\n        self._package_id = None\n        self.prev = None\n        self.pref_timestamp = None\n        if conanfile is not None:\n            conanfile._conan_node = self  # Reference to self, to access data\n        self.conanfile = conanfile\n\n        self.binary = None\n        self.recipe = recipe\n        self.remote = None\n        self.binary_remote = None\n        self.context = context\n        self.test = test\n\n        # real graph model\n        self.transitive_deps = OrderedDict()  # of _TransitiveRequirement\n        self.edges = []  # Ordered Edges\n        self.dependants = []  # Edges\n        self.error = None\n        self.should_build = False  # If the --build or policy wants to build this binary\n        self.build_allowed = False\n        self.is_conf = False\n        self.replaced_requires = {}  # To track the replaced requires for self.edges[old-ref]\n        self.skipped_build_requires = False\n\n    @property\n    def dependencies(self):\n        ConanOutput().warning(\"Node.dependencies is private and shouldn't be used. It is now \"\n                              \"node.edges. Please fix your code, Node.dependencies will be removed \"\n                              \"in future versions\", warn_tag=\"deprecated\")\n        return self.edges\n\n    def subgraph(self):\n        nodes = [self]\n        opened = [self]\n        while opened:\n            new_opened = []\n            for o in opened:\n                for n in o.neighbors():\n                    if n not in nodes:\n                        nodes.append(n)\n                    if n not in opened:\n                        new_opened.append(n)\n            opened = new_opened\n\n        graph = DepsGraph()\n        graph.nodes = nodes\n        return graph\n\n    def __lt__(self, other):\n        \"\"\"\n        :type other: Node\n        \"\"\"\n        # TODO: Remove this order, shouldn't be necessary\n        return (str(self.ref), self._package_id) < (str(other.ref), other._package_id)\n\n    def propagate_closing_loop(self, require, prev_node, visibility_conflicts):\n        self.propagate_downstream(require, prev_node, visibility_conflicts)\n        # List to avoid mutating the dict\n        for transitive in list(prev_node.transitive_deps.values()):\n            # TODO: possibly optimize in a bulk propagate\n            if transitive.require.override:\n                continue\n            prev_node.propagate_downstream(transitive.require, transitive.node, visibility_conflicts,\n                                           self)\n\n    def propagate_downstream(self, require, node, visibility_conflicts, src_node=None):\n        # print(\"  Propagating downstream \", self, \"<-\", require)\n        assert node is not None\n        # This sets the transitive_deps node if it was None (overrides)\n        # Take into account that while propagating we can find RUNTIME shared conflicts we\n        # didn't find at check_downstream_exist, because we didn't know the shared/static\n        existing = self.transitive_deps.get(require)\n\n        if existing is not None and existing.require is not require:\n            if existing.node is not None and existing.node.ref != node.ref:\n                # print(\"  +++++Runtime conflict!\", require, \"with\", node.ref)\n                raise GraphConflictError(self, require, existing.node, existing.require, node)\n            ill_formed = ((require.direct or existing.require.direct)\n                          and require.visible != existing.require.visible)\n            if ill_formed and not (require.test or existing.require.test):\n                visibility_conflicts.setdefault(require.ref, set()).add(self.ref)\n            require.aggregate(existing.require)\n            # An override can be overriden by a downstream force/override\n            if existing.require.override and existing.require.ref != require.ref:\n                # If it is an override, but other value, it has been overriden too\n                existing.require.overriden_ref = existing.require.ref\n                existing.require.override_ref = require.ref\n\n        assert not require.version_range  # No ranges slip into transitive_deps definitions\n        # TODO: Might need to move to an update() for performance\n        poped = self.transitive_deps.pop(require, None)\n        self.transitive_deps[require] = TransitiveRequirement(require, node)\n        if poped is not None:  # adjust .edges, to avoid orphans\n            for e in self.edges:\n                if e.dst is poped.node:  # check for identity, pointing to that node\n                    e.dst = node\n                    break\n\n        if self.conanfile.vendor:\n            return\n        # Check if need to propagate downstream\n        if not self.dependants:\n            return\n\n        if src_node is not None:  # This happens when closing a loop, and we need to know the edge\n            d = next(d for d in self.dependants if d.src is src_node)\n        else:\n            assert len(self.dependants) == 1\n            d = self.dependants[0]\n\n        down_require = d.require.transform_downstream(self.conanfile.package_type, require,\n                                                      node.conanfile.package_type)\n        if down_require is None:\n            return\n\n        down_require.defining_require = require.defining_require\n        # If the requirement propagates .files downstream, cannot be skipped\n        # But if the files are not needed in this graph branch, can be marked \"Skip\"\n        if down_require.files:\n            down_require.required_nodes = require.required_nodes.copy()\n        down_require.required_nodes.add(self)\n        d.src.propagate_downstream(down_require, node, visibility_conflicts)\n\n    def check_downstream_exists(self, require):\n        # First, a check against self, could be a loop-conflict\n        # This is equivalent as the Requirement hash and eq methods\n        # TODO: Make self.ref always exist, but with name=None if name not defined\n        if self.ref is not None and require.ref.name == self.ref.name:\n            if require.build and (self.context == CONTEXT_HOST or  # switch context\n                                  require.ref.version != self.ref.version):  # or different version\n                pass\n            elif require.visible is False:  # and require.ref.version != self.ref.version:\n                # Experimental, to support repackaging of openssl previous versions FIPS plugins\n                pass  # An invisible require doesn't conflict with itself\n            else:\n                return None, self, self  # First is the require, as it is a loop => None\n\n        # First do a check against the current node dependencies\n        prev = self.transitive_deps.get(require)\n        # print(\"    Transitive deps\", self.transitive_deps)\n        # (\"    THERE IS A PREV \", prev, \"in node \", self, \" for require \", require)\n        # Overrides: The existing require could be itself, that was just added\n        result = None\n        if prev and (prev.require is not require or prev.node is not None):\n            result = prev.require, prev.node, self\n            # Do not return yet, keep checking downstream, because downstream overrides or forces\n            # have priority\n\n        # Check if need to propagate downstream\n        # Then propagate downstream\n\n        if self.conanfile.vendor:\n            return result\n        # Seems the algrithm depth-first, would only have 1 dependant at most to propagate down\n        # at any given time\n        if not self.dependants:\n            return result\n        assert len(self.dependants) == 1\n        dependant = self.dependants[0]\n\n        # TODO: Implement an optimization where the requires is checked against a graph global\n        # print(\"    Lets check_downstream one more\")\n        down_require = dependant.require.transform_downstream(self.conanfile.package_type,\n                                                              require, None)\n\n        if down_require is None:\n            # print(\"    No need to check downstream more\")\n            return result\n\n        down_require.defining_require = require.defining_require\n        source_node = dependant.src\n        return source_node.check_downstream_exists(down_require) or result\n\n    def check_loops(self, new_node, count=0):\n        if self.ref == new_node.ref and self.context == new_node.context:\n            if count >= 1:\n                return self\n            count += 1\n        if not self.dependants:\n            return\n        assert len(self.dependants) == 1\n        dependant = self.dependants[0]\n        source_node = dependant.src\n        return source_node.check_loops(new_node, count)\n\n    @property\n    def package_id(self):\n        return self._package_id\n\n    @package_id.setter\n    def package_id(self, pkg_id):\n        assert self._package_id is None, \"Trying to override an existing package_id\"\n        self._package_id = pkg_id\n\n    @property\n    def name(self):\n        return self.ref.name if self.ref else None\n\n    @property\n    def pref(self):\n        assert self.ref is not None and self.package_id is not None, \"Node %s\" % self.recipe\n        return PkgReference(self.ref, self.package_id, self.prev, self.pref_timestamp)\n\n    def add_edge(self, edge):\n        if edge.src == self:\n            self.edges.append(edge)\n        else:\n            self.dependants.append(edge)\n\n    def neighbors(self):\n        return [edge.dst for edge in self.edges]\n\n    def inverse_neighbors(self):\n        return [edge.src for edge in self.dependants]\n\n    def __repr__(self):\n        return repr(self.conanfile)\n\n    def serialize(self):\n        result = OrderedDict()\n        result[\"ref\"] = self.ref.repr_notime() if self.ref is not None else \"conanfile\"\n        result[\"id\"] = getattr(self, \"id\")  # Must be assigned by graph.serialize()\n        result[\"recipe\"] = self.recipe\n        result[\"package_id\"] = self.package_id\n        result[\"prev\"] = self.prev\n        result[\"rrev\"] = self.ref.revision if self.ref is not None else None\n        result[\"rrev_timestamp\"] = self.ref.timestamp if self.ref is not None else None\n        result[\"prev_timestamp\"] = self.pref_timestamp\n        result[\"remote\"] = self.remote.name if self.remote else None\n        result[\"binary_remote\"] = self.binary_remote.name if self.binary_remote else None\n        from conan.internal.graph.installer import build_id\n        result[\"build_id\"] = build_id(self.conanfile)\n        result[\"binary\"] = self.binary\n        # TODO: This doesn't match the model, check it\n        result[\"invalid_build\"] = getattr(getattr(self.conanfile, \"info\", None), \"cant_build\", False)\n        result[\"info_invalid\"] = getattr(getattr(self.conanfile, \"info\", None), \"invalid\", None)\n        # Adding the conanfile information: settings, options, etc\n        result.update(self.conanfile.serialize())\n        result.pop(\"requires\", None)  # superseded by \"dependencies\" (graph.transitive_deps)\n        result[\"dependencies\"] = {d.node.id: d.require.serialize()\n                                  for d in self.transitive_deps.values() if d.node is not None}\n        result[\"context\"] = self.context\n        result[\"test\"] = self.test\n        return result\n\n    def overrides(self):\n\n        def transitive_subgraph():\n            result = set()\n            opened = {self}\n            while opened:\n                new_opened = set()\n                for o in opened:\n                    result.add(o)\n                    new_opened.update(set(o.neighbors()).difference(result))\n                opened = new_opened\n\n            return result\n\n        nodes = transitive_subgraph()\n        return Overrides.create(nodes)\n\n\nclass Edge:\n    def __init__(self, src, dst, require):\n        self.src = src\n        self.dst = dst\n        self.require = require\n\n\nclass Overrides:\n    def __init__(self):\n        self._overrides = {}  # {require_ref: {override_ref1, override_ref2}}\n\n    def __bool__(self):\n        return bool(self._overrides)\n\n    def __repr__(self):\n        return repr(self.serialize())\n\n    @staticmethod\n    def create(nodes):\n        overrides = {}\n        for n in nodes:\n            for r in n.conanfile.requires.values():\n                if r.override and not r.overriden_ref:  # overrides are not real graph edges\n                    continue\n                if r.overriden_ref:\n                    overrides.setdefault(r.overriden_ref, set()).add(r.override_ref)\n                else:\n                    overrides.setdefault(r.ref, set()).add(None)\n\n        # reduce, eliminate those overrides definitions that only override to None, that is, not\n        # really an override\n        result = Overrides()\n        for require, override_info in overrides.items():\n            if len(override_info) != 1 or None not in override_info:\n                result._overrides[require] = override_info\n        return result\n\n    def get(self, require):\n        return self._overrides.get(require)\n\n    def update(self, other):\n        \"\"\"\n        :type other: Overrides\n        \"\"\"\n        for require, override_info in other._overrides.items():\n            self._overrides.setdefault(require, set()).update(override_info)\n\n    def items(self):\n        return self._overrides.items()\n\n    def serialize(self):\n        return {k.repr_notime(): sorted([e.repr_notime() if e else None for e in v],\n                                        key=lambda e: \"\" if e is None else e)\n                for k, v in self._overrides.items()}\n\n    @staticmethod\n    def deserialize(data):\n        result = Overrides()\n        result._overrides = {RecipeReference.loads(k):\n                             set([RecipeReference.loads(e) if e else None for e in v])\n                             for k, v in data.items()}\n        return result\n\n\nclass DepsGraph:\n    def __init__(self):\n        self.nodes = []\n        self.aliased = {}\n        self.resolved_ranges = {}\n        self.replaced_requires = {}\n        self.options_conflicts = {}\n        self.visibility_conflicts = {}\n        self.error = False\n\n    def lockfile(self):\n        from conan.internal.model.lockfile import Lockfile\n        return Lockfile(self)\n\n    def overrides(self):\n        return Overrides.create(self.nodes)\n\n    def __repr__(self):\n        return \"\\n\".join((repr(n) for n in self.nodes))\n\n    @property\n    def root(self):\n        return self.nodes[0] if self.nodes else None\n\n    def add_node(self, node):\n        self.nodes.append(node)\n\n    @staticmethod\n    def add_edge(src, dst, require):\n        edge = Edge(src, dst, require)\n        src.add_edge(edge)\n        dst.add_edge(edge)\n\n    def ordered_iterate(self):\n        ordered = self.by_levels()\n        for level in ordered:\n            for node in level:\n                yield node\n\n    def by_levels(self):\n        \"\"\" order by node degree. The first level will be the one which nodes dont have\n        dependencies. Second level will be with nodes that only have dependencies to\n        first level nodes, and so on\n        return [[node1, node34], [node3], [node23, node8],...]\n        \"\"\"\n        result = []\n        # We make it a dict to preserve insertion order and be deterministic, s\n        # sets are not deterministic order. dict is fast for look up operations\n        opened = dict.fromkeys(self.nodes)\n        while opened:\n            current_level = []\n            for o in opened:\n                o_neighs = o.neighbors()\n                if not any(n in opened for n in o_neighs):\n                    current_level.append(o)\n\n            # TODO: SORTING seems only necessary for test order\n            current_level.sort()\n            result.append(current_level)\n            # now start new level, removing the current level items\n            for item in current_level:\n                opened.pop(item)\n\n        return result\n\n    def report_graph_error(self):\n        if self.error:\n            raise self.error\n\n    def serialize(self):\n        for i, n in enumerate(self.nodes):\n            n.id = str(i)\n        result = OrderedDict()\n        result[\"nodes\"] = {n.id: n.serialize() for n in self.nodes}\n        result[\"root\"] = {self.root.id: repr(self.root.ref)}  # TODO: ref of consumer/virtual\n        result[\"overrides\"] = self.overrides().serialize()\n        result[\"resolved_ranges\"] = {repr(r): s.repr_notime()\n                                     for r, s in self.resolved_ranges.items()}\n        result[\"replaced_requires\"] = {k: v for k, v in self.replaced_requires.items()}\n        result[\"error\"] = self.error.serialize() if isinstance(self.error, GraphError) else None\n        return result\n"
  },
  {
    "path": "conan/internal/graph/graph_binaries.py",
    "content": "import os\n\nfrom conan.api.output import ConanOutput, Color\nfrom conan.internal.cache.home_paths import HomePaths\nfrom conan.internal.graph.build_mode import BuildMode\nfrom conan.internal.graph.compatibility import BinaryCompatibility\nfrom conan.internal.graph.compute_pid import compute_package_id\nfrom conan.internal.graph.graph import (BINARY_BUILD, BINARY_CACHE, BINARY_DOWNLOAD, BINARY_MISSING,\n                                        BINARY_UPDATE, RECIPE_EDITABLE, BINARY_EDITABLE,\n                                        RECIPE_CONSUMER, RECIPE_VIRTUAL, BINARY_SKIP,\n                                        BINARY_INVALID, BINARY_EDITABLE_BUILD, RECIPE_PLATFORM,\n                                        BINARY_PLATFORM)\nfrom conan.internal.graph.proxy import should_update_reference\nfrom conan.internal.errors import (conanfile_exception_formatter, ConanConnectionError,\n                                   NotFoundException, PackageNotFoundException)\nfrom conan.errors import ConanException\nfrom conan.internal.model.conanconfig import loadconanconfig\nfrom conan.internal.model.info import RequirementInfo, RequirementsInfo\nfrom conan.internal.model.pkg_type import PackageType\n\n\nclass GraphBinariesAnalyzer:\n\n    def __init__(self, cache, remote_manager, home_folder, global_conf, hook_manager):\n        self._cache = cache\n        self._home_folder = home_folder\n        self._global_conf = global_conf\n        self._remote_manager = remote_manager\n        self._hook_manager = hook_manager\n        # These are the nodes with pref (not including PREV) that have been evaluated\n        self._evaluated = {}  # {pref: [nodes]}\n        compat_folder = HomePaths(home_folder).compatibility_plugin_path\n        self._compatibility = BinaryCompatibility(compat_folder, hook_manager)\n        unknown_mode = global_conf.get(\"core.package_id:default_unknown_mode\", default=\"semver_mode\")\n        non_embed = global_conf.get(\"core.package_id:default_non_embed_mode\", default=\"minor_mode\")\n        # recipe_revision_mode already takes into account the package_id\n        embed_mode = global_conf.get(\"core.package_id:default_embed_mode\", default=\"full_mode\")\n        python_mode = global_conf.get(\"core.package_id:default_python_mode\", default=\"minor_mode\")\n        build_mode = global_conf.get(\"core.package_id:default_build_mode\", default=None)\n        self._modes = unknown_mode, non_embed, embed_mode, python_mode, build_mode\n        self._warn_about_new_compatibility = False\n\n    @staticmethod\n    def _evaluate_build(node, build_mode):\n        ref, conanfile = node.ref, node.conanfile\n        with_deps_to_build = False\n        # check dependencies, if they are being built, \"cascade\" will try to build this one too\n        if build_mode.cascade:\n            with_deps_to_build = any(edge.dst.binary in (BINARY_BUILD, BINARY_EDITABLE_BUILD)\n                                     for edge in node.edges)\n        if build_mode.forced(conanfile, ref, with_deps_to_build):\n            node.should_build = True\n            conanfile.output.info('Forced build from source')\n            node.binary = BINARY_BUILD if not conanfile.info.cant_build else BINARY_INVALID\n            node.prev = None\n            return True\n\n    @staticmethod\n    def _evaluate_clean_pkg_folder_dirty(node, package_layout):\n        # Check if dirty, to remove it\n        with package_layout.package_lock():\n            assert node.recipe != RECIPE_EDITABLE, \"Editable package shouldn't reach this code\"\n            if package_layout.package_is_dirty():\n                node.conanfile.output.warning(\"Package binary is corrupted, \"\n                                              \"removing: %s\" % node.package_id)\n                package_layout.package_remove()\n                return True\n\n    # check through all the selected remotes:\n    # - if not --update: get the first package found\n    # - if --update: get the latest remote searching in all of them\n    def _get_package_from_remotes(self, node, remotes, update):\n        results = []\n        pref = node.pref\n        for r in remotes:\n            try:\n                info = node.conanfile.info\n                latest_pref = self._remote_manager.get_latest_package_revision(pref, r, info)\n                results.append({'pref': latest_pref, 'remote': r})\n                if len(results) > 0 and not should_update_reference(node.ref, update):\n                    break\n            except NotFoundException:\n                pass\n            except ConanConnectionError:\n                ConanOutput().error(f\"Failed checking for binary '{pref}' in remote '{r.name}': \"\n                                    \"remote not available\")\n                raise\n        if not remotes and should_update_reference(node.ref, update):\n            node.conanfile.output.warning(\"Can't update, there are no remotes defined\")\n\n        if len(results) > 0:\n            remotes_results = sorted(results, key=lambda k: k['pref'].timestamp, reverse=True)\n            result = remotes_results[0]\n            node.prev = result.get(\"pref\").revision\n            node.pref_timestamp = result.get(\"pref\").timestamp\n            node.binary_remote = result.get('remote')\n        else:\n            node.binary_remote = None\n            node.prev = None\n            raise PackageNotFoundException(pref)\n\n    def _evaluate_is_cached(self, node):\n        \"\"\" Each pref has to be evaluated just once, and the action for all of them should be\n        exactly the same\n        \"\"\"\n        pref = node.pref\n        previous_nodes = self._evaluated.get(pref)\n        if previous_nodes:\n            previous_nodes.append(node)\n            previous_node = previous_nodes[0]\n            node.binary = previous_node.binary\n            node.binary_remote = previous_node.binary_remote\n            node.prev = previous_node.prev\n            node.pref_timestamp = previous_node.pref_timestamp\n            node.should_build = previous_node.should_build\n            node.build_allowed = previous_node.build_allowed\n\n            # this line fixed the compatible_packages with private case.\n            # https://github.com/conan-io/conan/issues/9880\n            node._package_id = previous_node.package_id\n            return True\n        self._evaluated[pref] = [node]\n\n    def _compatible_get_packages(self, node):\n        # Evaluate the ``compatibility() methods to compute the compatible hypothesis variants\n        conanfile = node.conanfile\n        original_package_id = node.package_id\n\n        compatibles = self._compatibility.compatibles(conanfile)\n        existing = compatibles.pop(original_package_id, None)   # Skip main package_id\n        if existing:  # Skip the check if same package_id\n            conanfile.output.debug(f\"Compatible package ID {original_package_id} equal to \"\n                                   \"the default package ID: Skipping it.\")\n        return compatibles\n\n    @staticmethod\n    def _compatible_found(conanfile, pkg_id, compatible_pkg):\n        diff = conanfile.info.dump_diff(compatible_pkg)\n        conanfile.output.success(f\"Found compatible package '{pkg_id}': {diff}\")\n        # So they are available in package_info() method\n        conanfile.info = compatible_pkg  # Redefine current\n\n        # TODO: Improve this interface\n        # The package_id method might have modified the settings to erase information,\n        # ensure we allow those new values\n        conanfile.settings = conanfile.settings.copy_conaninfo_settings()\n        conanfile.settings.update_values(compatible_pkg.settings.values_list)\n        # Trick to allow mutating the options (they were freeze=True)\n        conanfile.options = conanfile.options.copy_conaninfo_options()\n        conanfile.options.update_options(compatible_pkg.options)\n\n    def _compatible_find_existing_binaries(self, node, compatibles, remotes, update):\n        # Do the actual search in the cache and remotes for the compatible package-ids\n        conanfile = node.conanfile\n        original_binary = node.binary\n        original_package_id = node.package_id\n        conanfile.output.info(f\"Main binary package '{original_package_id}' missing\")\n        conanfile.output.info(f\"Checking {len(compatibles)} compatible configurations\")\n        compatibility_mode = self._global_conf.get(\"core.graph:compatibility_mode\",\n                                                   choices=(\"optimized\",))\n        use_compatibility_optimization = compatibility_mode == \"optimized\"\n\n        if not should_update_reference(conanfile.ref, update):\n            # First look all in the cache\n            for package_id, compatible_package in compatibles.items():\n                node._package_id = package_id  # Modifying package id under the hood, FIXME\n                # Check that this same reference hasn't already been checked\n                if self._evaluate_is_cached(node):\n                    # If we have already processed this compatible pref,\n                    # mark it as usable based on previous evaluation\n                    if node.binary in (BINARY_CACHE, BINARY_DOWNLOAD):\n                        self._compatible_found(conanfile, package_id, compatible_package)\n                    return\n                cache_latest_prev = self._compatible_cache_latest_prev(node)  # not check remotes\n                if cache_latest_prev:\n                    # If we have binary info, it means that the package was already processed,\n                    # and we got a hit from the cache of compatibles\n                    self._binary_in_cache(node, cache_latest_prev)\n                    self._compatible_found(conanfile, package_id, compatible_package)\n                    return\n            # If not found in the cache, then look for the first one in servers\n            conanfile.output.info(f\"Compatible configurations not found in cache, checking servers\")\n            if use_compatibility_optimization:\n                compatible_packages = self._compatible_get_packages_from_remotes(node.ref, remotes)\n                candidates = {pkg_id: pkg for pkg_id, pkg in compatibles.items()\n                              if pkg_id in compatible_packages}\n                node.conanfile.output.info(f\"Found {len(candidates)} compatible configurations \"\n                                           f\"in remotes\")\n            else:\n                candidates = compatibles\n                compatible_packages = {}\n                self._warn_about_new_compatibility = True\n            for package_id, compatible_package in candidates.items():\n                conanfile.output.info(f\"'{package_id}': \"\n                                      f\"{conanfile.info.dump_diff(compatible_package)}\")\n                node._package_id = package_id  # Modifying package id under the hood, FIXME\n                # We already know which remotes have that package_id\n                available_remotes = compatible_packages.get(package_id, remotes)\n                self._evaluate_download(node, available_remotes, update=False)\n                if node.binary == BINARY_DOWNLOAD:\n                    self._compatible_found(conanfile, package_id, compatible_package)\n                    return\n        else:  # Need to check in servers too for the latest thing\n            if use_compatibility_optimization:\n                compatible_packages = self._compatible_get_packages_from_remotes(node.ref, remotes)\n            else:\n                compatible_packages = {}\n                self._warn_about_new_compatibility = True\n            for package_id, compatible_package in compatibles.items():\n                conanfile.output.info(f\"'{package_id}': \"\n                                      f\"{conanfile.info.dump_diff(compatible_package)}\")\n                node._package_id = package_id  # Modifying package id under the hood, FIXME\n\n                if self._evaluate_is_cached(node):\n                    # If we have already processed this compatible pref,\n                    # mark it as usable based on previous evaluation\n                    if node.binary in (BINARY_CACHE, BINARY_DOWNLOAD, BINARY_UPDATE):\n                        self._compatible_found(conanfile, package_id, compatible_package)\n                    return\n                cache_latest_prev = self._compatible_cache_latest_prev(node)  # Not check remotes\n                available_remotes = compatible_packages.get(package_id,\n                                                            [] if use_compatibility_optimization\n                                                            else remotes)\n                if cache_latest_prev:\n                    self._evaluate_cache_update(cache_latest_prev, node, available_remotes, update)\n                else:\n                    if available_remotes:\n                        self._evaluate_download(node, available_remotes, update)\n                    else:\n                        # If not in remotes, mark as missing, no need for further checks\n                        node.binary = BINARY_MISSING\n                if node.binary in (BINARY_CACHE, BINARY_UPDATE, BINARY_DOWNLOAD):\n                    self._compatible_found(conanfile, package_id, compatible_package)\n                    return\n\n        node.conanfile.output.info(\"No compatible configuration found\", fg=Color.BRIGHT_CYAN)\n        # If no compatible is found, restore original state\n        node.binary = original_binary\n        node._package_id = original_package_id\n\n    def _compatible_cache_latest_prev(self, node):\n        \"\"\" simplified checking of compatible_packages, that should be found existing, but\n        will never be built, for example. They cannot be editable either at this point.\n        \"\"\"\n        # Obtain the cache_latest valid one, cleaning things if dirty\n        while True:\n            package_layout = self._cache.pkg_layout_latest(node.pref)\n            cache_latest_prev = package_layout.reference if package_layout else None\n            if cache_latest_prev is None:\n                break\n            if not self._evaluate_clean_pkg_folder_dirty(node, package_layout):\n                break\n\n        return cache_latest_prev\n\n    @staticmethod\n    def _binary_in_cache(node, cache_latest_prev):\n        assert cache_latest_prev.revision\n        node.binary = BINARY_CACHE\n        node.binary_remote = None\n        node.prev = cache_latest_prev.revision\n        node.pref_timestamp = cache_latest_prev.timestamp\n\n    def _compatible_get_packages_from_remotes(self, ref, remotes):\n        \"\"\"\n        Get available package ids in remotes for the given node reference\n        \"\"\"\n        results = {}\n        for remote in remotes:\n            try:\n                remote_prefs = self._remote_manager.search_packages(remote, ref, list_only=True)\n                if remote_prefs:\n                    for remote_pref in remote_prefs:\n                        results.setdefault(remote_pref.package_id, []).append(remote)\n            except NotFoundException:\n                # Not finding the reference in the remote is not an error, just continue\n                pass\n            except ConanConnectionError:\n                ConanOutput().error(f\"Failed finding for package ids '{ref}' in \"\n                                    f\"remote '{remote.name}': remote not available\")\n                raise\n\n        return results\n\n    def _compatible_find_build_binary(self, node, compatibles):\n        output = node.conanfile.output\n        output.info(f\"Requested binary package '{node.package_id}' invalid, can't be built\")\n        output.info(f\"Checking {len(compatibles)} configurations, to build a compatible one, \"\n                    f\"as requested by '--build=compatible'\")\n        for pkg_id, compatible in compatibles.items():\n            if not compatible.cant_build:\n                node._package_id = pkg_id  # Modifying package id under the hood, FIXME\n                self._compatible_found(node.conanfile, pkg_id, compatible)\n                node.binary = BINARY_BUILD\n                return\n\n    def _evaluate_node(self, node, build_mode, remotes, update):\n        assert node.binary is None, \"Node.binary should be None\"\n        assert node.package_id is not None, \"Node.package_id shouldn't be None\"\n        assert node.prev is None, \"Node.prev should be None\"\n\n        # Check that this same reference hasn't already been checked\n        if self._evaluate_is_cached(node):\n            return\n\n        self._process_node(node, build_mode, remotes, update)\n        compatibles = None\n\n        if node.binary == BINARY_MISSING \\\n                and not build_mode.should_build_missing(node.conanfile) and not node.should_build:\n            compatibles = self._compatible_get_packages(node)\n            if compatibles:\n                self._compatible_find_existing_binaries(node, compatibles, remotes, update)\n\n        if node.binary == BINARY_MISSING and build_mode.allowed(node.conanfile):\n            node.should_build = True\n            node.build_allowed = True\n            node.binary = BINARY_BUILD if not node.conanfile.info.cant_build else BINARY_INVALID\n\n        if node.binary == BINARY_INVALID and build_mode.allowed_compatible(node.conanfile):\n            if compatibles is None:\n                compatibles = self._compatible_get_packages(node)\n            if compatibles:\n                # Before deciding to build a compatible binary, we check if it exists\n                self._compatible_find_existing_binaries(node, compatibles, remotes, update)\n                # And only if not found, we consider to build it\n                if node.binary == BINARY_INVALID:\n                    self._compatible_find_build_binary(node, compatibles)\n\n        if node.binary == BINARY_BUILD:\n            conanfile = node.conanfile\n            if conanfile.vendor and not conanfile.conf.get(\"tools.graph:vendor\", choices=(\"build\",)):\n                node.conanfile.info.invalid = f\"The package '{conanfile.ref}' is a vendoring one, \" \\\n                                              f\"needs to be built from source, but it \" \\\n                                              \"didn't enable 'tools.graph:vendor=build' to compute\" \\\n                                              \" its dependencies\"\n                node.binary = BINARY_INVALID\n            if any(n.node.binary in (BINARY_EDITABLE, BINARY_EDITABLE_BUILD)\n                   for n in node.transitive_deps.values()):\n                conanfile.output.warning(\"Package is being built in the cache using editable \"\n                                         \"dependencies, this is dangerous\", warn_tag=\"risk\")\n\n    def _process_node(self, node, build_mode, remotes, update):\n        if node.conanfile.info.invalid:\n            node.binary = BINARY_INVALID\n            return\n        if node.recipe == RECIPE_PLATFORM:\n            node.binary = BINARY_PLATFORM\n            return\n\n        if node.recipe == RECIPE_EDITABLE:\n            # TODO: Check what happens when editable is passed an Invalid configuration\n            if build_mode.editable or self._evaluate_build(node, build_mode) or \\\n                    build_mode.should_build_missing(node.conanfile):\n                node.binary = BINARY_EDITABLE_BUILD\n            else:\n                node.binary = BINARY_EDITABLE  # TODO: PREV?\n            return\n\n        # If the CLI says this package needs to be built, it doesn't make sense to mark\n        # it as invalid\n        if self._evaluate_build(node, build_mode):\n            return\n\n        # Obtain the cache_latest valid one, cleaning things if dirty\n        while True:\n            package_layout = self._cache.pkg_layout_latest(node.pref)\n            cache_latest_prev = package_layout.reference if package_layout else None\n            if cache_latest_prev is None:\n                break\n            if not self._evaluate_clean_pkg_folder_dirty(node, package_layout):\n                break\n\n        if node.conanfile.upload_policy == \"skip\":\n            # Download/update shouldn't be checked in the servers if this is \"skip-upload\"\n            # The binary can only be in cache or missing.\n            if cache_latest_prev:\n                self._binary_in_cache(node, cache_latest_prev)\n            else:\n                node.binary = BINARY_MISSING\n        elif cache_latest_prev is None:  # This binary does NOT exist in the cache\n            self._evaluate_download(node, remotes, update)\n        else:  # This binary already exists in the cache, maybe can be updated\n            self._evaluate_cache_update(cache_latest_prev, node, remotes, update)\n\n    def _process_locked_node(self, node, build_mode, locked_prev):\n        # Check that this same reference hasn't already been checked\n        if self._evaluate_is_cached(node):\n            return\n\n        # If the CLI says this package needs to be built, it doesn't make sense to mark\n        # it as invalid\n        if self._evaluate_build(node, build_mode):\n            # TODO: We migth want to rais if strict\n            return\n\n        if node.recipe == RECIPE_EDITABLE:\n            # TODO: Raise if strict\n            node.binary = BINARY_EDITABLE  # TODO: PREV?\n            return\n\n        # in cache:\n        node.prev = locked_prev\n        if self._cache.exists_prev(node.pref):\n            node.binary = BINARY_CACHE\n            node.binary_remote = None\n            # TODO: Dirty\n            return\n\n        # TODO: Check in remotes for download\n\n    def _evaluate_download(self, node, remotes, update):\n        try:\n            self._get_package_from_remotes(node, remotes, update)\n        except NotFoundException:\n            node.binary = BINARY_MISSING\n        else:\n            node.binary = BINARY_DOWNLOAD\n\n    def _evaluate_cache_update(self, cache_latest_prev, node, remotes, update):\n        assert cache_latest_prev.revision\n        if should_update_reference(node.ref, update):\n            output = node.conanfile.output\n            try:\n                self._get_package_from_remotes(node, remotes, update)\n            except NotFoundException:\n                output.warning(\"Can't update, no package in remote\")\n            else:\n                cache_time = cache_latest_prev.timestamp\n                # TODO: cache 2.0 should we update the date if the prev is the same?\n                if cache_time < node.pref_timestamp and cache_latest_prev != node.pref:\n                    node.binary = BINARY_UPDATE\n                    output.info(\"Current package revision is older than the remote one\")\n                    return\n                if cache_time > node.pref_timestamp:\n                    output.info(\"Current package revision is newer than the remote one\")\n\n        # The cache latest prev was there, if the server one didn't result as UPDATE\n        # Then resolve to the cache latest prev\n        self._binary_in_cache(node, cache_latest_prev)\n\n    def _config_version(self):\n        config_mode = self._global_conf.get(\"core.package_id:config_mode\", default=None)\n        if config_mode is None:\n            return\n        config_version_file = HomePaths(self._home_folder).config_version_path\n        try:\n            config_refs = loadconanconfig(config_version_file)\n            result = {r: RequirementInfo(r, None, config_mode) for r in config_refs}\n        except Exception as e:\n            raise ConanException(f\"core.package_id:config_mode defined, but error while loading \"\n                                 f\"'{os.path.basename(config_version_file)}'\"\n                                 f\" file in cache: {self._home_folder}: {e}\")\n        return RequirementsInfo(result)\n\n    def _evaluate_package_id(self, node, config_version):\n        compute_package_id(node, self._modes, config_version, self._hook_manager)\n\n        # TODO: layout() execution don't need to be evaluated at GraphBuilder time.\n        # it could even be delayed until installation time, but if we got enough info here for\n        # package_id, we can run it\n        conanfile = node.conanfile\n        if hasattr(conanfile, \"layout\"):\n            with conanfile_exception_formatter(conanfile, \"layout\"):\n                conanfile.layout()\n\n    def evaluate_graph(self, deps_graph, build_mode, lockfile, remotes, update, build_mode_test=None,\n                       tested_graph=None):\n        if tested_graph is None:\n            main_mode = BuildMode(build_mode)\n            test_mode = None  # Should not be used at all\n            mainprefs = None\n        else:\n            main_mode = BuildMode([\"never\"])\n            test_mode = BuildMode(build_mode_test)\n            mainprefs = [str(n.pref) for n in tested_graph.nodes\n                         if n.recipe not in (RECIPE_CONSUMER, RECIPE_VIRTUAL)]\n\n        def _evaluate_single(n):\n            mode = main_mode if mainprefs is None or str(n.pref) in mainprefs else test_mode\n            if lockfile:\n                locked_prev = lockfile.resolve_prev(n)  # this is not public, should never happen\n                if locked_prev:\n                    self._process_locked_node(n, mode, locked_prev)\n                    return\n            self._evaluate_node(n, mode, remotes, update)\n\n        levels = deps_graph.by_levels()\n        # When creating a \"conan config install-pkg\" package, it should be independent of conf\n        root_pkg_type = deps_graph.root.edges[0].dst.conanfile.package_type \\\n            if deps_graph.root.edges else None\n        config_version = self._config_version() if root_pkg_type is not PackageType.CONF else None\n        for level in levels[:-1]:  # all levels but the last one, which is the single consumer\n            for node in level:\n                self._evaluate_package_id(node, config_version)\n            # group by pref to paralelize, so evaluation is done only 1 per pref\n            nodes = {}\n            for node in level:\n                nodes.setdefault(node.pref, []).append(node)\n            # PARALLEL, this is the slow part that can query servers for packages, and compatibility\n            for pref, pref_nodes in nodes.items():\n                _evaluate_single(pref_nodes[0])\n            # END OF PARALLEL\n            # Evaluate the possible nodes with repeated \"prefs\" that haven't been evaluated\n            for pref, pref_nodes in nodes.items():\n                for n in pref_nodes[1:]:\n                    assert self._evaluate_is_cached(n)  # The pref is the same, must exist cached\n\n        if self._warn_about_new_compatibility:\n            (ConanOutput().info(\"\\nA new experimental approach for binary compatibility detection \"\n                                \"is available.\\n\"\n                                \"    Enable it by setting the \", newline=False)\n             .info('core.graph:compatibility_mode=optimized', newline=False, fg=Color.BRIGHT_YELLOW)\n             .info(\" conf\\n    and get improved performance when querying multiple \"\n                   \"compatible binaries in remotes.\\n\"))\n\n        # Last level is always necessarily a consumer or a virtual\n        assert len(levels[-1]) == 1\n        node = levels[-1][0]\n        assert node.recipe in (RECIPE_CONSUMER, RECIPE_VIRTUAL)\n        if node.path is not None:\n            if node.path.endswith(\".py\"):\n                # For .py we keep evaluating the package_id, validate(), etc\n                compute_package_id(node, self._modes, config_version, self._hook_manager)\n            # To support the ``[layout]`` in conanfile.txt\n            if hasattr(node.conanfile, \"layout\"):\n                with conanfile_exception_formatter(node.conanfile, \"layout\"):\n                    node.conanfile.layout()\n\n        self._skip_binaries(deps_graph)\n\n    @staticmethod\n    def _skip_binaries(graph):\n        required_nodes = set()\n        # Aggregate all necessary starting nodes\n        required_nodes.add(graph.root)\n        for node in graph.nodes:\n            if node.binary in (BINARY_BUILD, BINARY_EDITABLE_BUILD, BINARY_EDITABLE):\n                if node.skipped_build_requires:\n                    raise ConanException(f\"Package {node.ref} skipped its test/tool requires with \"\n                                         f\"tools.graph:skip_build, but was marked to be built \")\n                can_skip = node.conanfile.conf.get(\"tools.graph:skip_binaries\",\n                                                   check_type=bool, default=True)\n                # Only those that are forced to build, not only \"missing\"\n                if not node.build_allowed or not can_skip:\n                    required_nodes.add(node)\n\n        root_nodes = required_nodes.copy()\n        while root_nodes:\n            new_root_nodes = set()\n            for node in root_nodes:\n                # The nodes that are directly required by this one to build correctly\n                is_consumer = not (node.recipe != RECIPE_CONSUMER and\n                                   node.binary not in (BINARY_BUILD, BINARY_EDITABLE_BUILD,\n                                                       BINARY_EDITABLE))\n                deps_required = set()\n                for req, t in node.transitive_deps.items():\n                    if req.files or (req.direct and is_consumer):\n                        deps_required.add(t.node)\n                        deps_required.update(req.required_nodes)\n\n                # Third pass, mark requires as skippeable\n                for dep in node.transitive_deps.values():\n                    dep.require.skip = dep.node not in deps_required\n\n                # Finally accumulate all needed nodes for marking binaries as SKIP download\n                news_req = [r for r in deps_required\n                            if (r.binary in (BINARY_BUILD, BINARY_EDITABLE_BUILD, BINARY_EDITABLE)\n                                or any(req.no_skip for req in r.transitive_deps))\n                            if r not in required_nodes]  # Avoid already expanded before\n                new_root_nodes.update(news_req)  # For expanding the next iteration\n                required_nodes.update(deps_required)\n\n            root_nodes = new_root_nodes\n\n        for node in graph.nodes:\n            if node not in required_nodes and node.conanfile.conf.get(\"tools.graph:skip_binaries\",\n                                                                      check_type=bool, default=True):\n                node.binary = BINARY_SKIP\n"
  },
  {
    "path": "conan/internal/graph/graph_builder.py",
    "content": "import os\nfrom collections import deque\n\nfrom conan.internal.cache.conan_reference_layout import BasicLayout\nfrom conan.internal.methods import run_configure_method\nfrom conan.internal.model.recipe_ref import ref_matches\nfrom conan.internal.graph.graph import DepsGraph, Node, CONTEXT_HOST, \\\n    CONTEXT_BUILD, TransitiveRequirement, RECIPE_VIRTUAL, RECIPE_EDITABLE, RECIPE_CONSUMER\nfrom conan.internal.graph.graph import RECIPE_PLATFORM\nfrom conan.internal.graph.graph_error import (GraphLoopError, GraphConflictError, GraphMissingError,\n                                              GraphError)\nfrom conan.internal.graph.profile_node_definer import initialize_conanfile_profile\nfrom conan.internal.graph.provides import check_graph_provides\nfrom conan.errors import ConanException\nfrom conan.internal.model.conan_file import ConanFile\nfrom conan.internal.model.options import Options, _PackageOptions\nfrom conan.internal.model.pkg_type import PackageType\nfrom conan.api.model import RecipeReference\nfrom conan.internal.model.requires import Requirement\nfrom conan.internal.model.version_range import VersionRange\n\n\nclass DepsGraphBuilder:\n    ALLOW_ALIAS = False\n\n    def __init__(self, proxy, loader, resolver, cache, remotes, update, check_update, global_conf):\n        self._proxy = proxy\n        self._loader = loader\n        self._resolver = resolver\n        self._cache = cache\n        self._remotes = remotes  # TODO: pass as arg to load_graph()\n        self._update = update\n        self._check_update = check_update\n        self._resolve_prereleases = global_conf.get('core.version_ranges:resolve_prereleases')\n\n    def load_graph(self, root_node, profile_host, profile_build, graph_lock=None):\n        assert profile_host is not None\n        assert profile_build is not None\n        assert isinstance(profile_host.options, Options)\n        assert isinstance(profile_build.options, Options)\n        # print(\"Loading graph\")\n        dep_graph = DepsGraph()\n\n        is_test_package = getattr(root_node.conanfile, \"tested_reference_str\", None)\n        define_consumers = root_node.recipe == RECIPE_VIRTUAL or is_test_package\n        self._prepare_node(root_node, profile_host, profile_build, Options(), define_consumers)\n        rs = self._initialize_requires(root_node, dep_graph, graph_lock, profile_build, profile_host)\n        dep_graph.add_node(root_node)\n\n        open_requires = deque((r, root_node) for r in rs)\n        try:\n            while open_requires:\n                # Fetch the first waiting to be expanded (depth-first)\n                (require, node) = open_requires.popleft()\n                if require.override:\n                    continue\n                new_node = self._expand_require(require, node, dep_graph, profile_host,\n                                                profile_build, graph_lock)\n                if new_node and (not new_node.conanfile.vendor\n                                 or new_node.recipe == RECIPE_EDITABLE or\n                                 new_node.conanfile.conf.get(\"tools.graph:vendor\",\n                                                             choices=(\"build\",))):\n                    newr = self._initialize_requires(new_node, dep_graph, graph_lock, profile_build,\n                                                     profile_host)\n                    open_requires.extendleft((r, new_node) for r in reversed(newr))\n            self._remove_overrides(dep_graph)\n            self._remove_orphans(dep_graph)\n            check_graph_provides(dep_graph)\n        except GraphError as e:\n            dep_graph.error = e\n        dep_graph.resolved_ranges = self._resolver.resolved_ranges\n        refs = set(n.ref for n in dep_graph.nodes\n                   if n.recipe not in (RECIPE_VIRTUAL, RECIPE_EDITABLE, RECIPE_CONSUMER,\n                                       RECIPE_PLATFORM))\n        self._cache.update_recipes_lru(refs)\n        return dep_graph\n\n    def _expand_require(self, require, node, graph, profile_host, profile_build, graph_lock):\n        # Handle a requirement of a node. There are 2 possibilities\n        #    node -(require)-> new_node (creates a new node in the graph)\n        #    node -(require)-> previous (creates a diamond with a previously existing node)\n        # TODO: allow bootstrapping, use references instead of names\n        # print(\"  Expanding require \", node, \"->\", require)\n        self._deduce_host_version(require, node)\n        previous = node.check_downstream_exists(require)\n        prev_node = None\n        if previous is not None:\n            prev_require, prev_node, base_previous = previous\n            # print(\"  Existing previous requirements from \", base_previous, \"=>\", prev_require)\n\n            if prev_require is None:\n                raise GraphLoopError(node, require, prev_node)\n\n            prev_ref = prev_node.ref if prev_node else prev_require.ref\n            if prev_require.force or prev_require.override:  # override\n                if prev_require.defining_require is not require:\n                    require.overriden_ref = require.overriden_ref or require.ref.copy()  # Old one\n                    # require.override_ref can be !=None if lockfile-overrides defined\n                    require.override_ref = (require.override_ref or prev_require.override_ref\n                                            or prev_require.ref.copy())  # New one\n                    require.defining_require = prev_require.defining_require  # The overrider\n                require.ref = prev_ref  # New one, maybe resolved with revision\n            else:\n                self._conflicting_version(require, node, prev_require, prev_node,\n                                          prev_ref, base_previous, self._resolve_prereleases)\n\n        if prev_node is None:\n            # new node, must be added and expanded (node -> new_node)\n            new_node = self._create_new_node(node, require, graph, profile_host, profile_build,\n                                             graph_lock)\n            return new_node\n        else:\n            # print(\"Closing a loop from \", node, \"=>\", prev_node)\n            # Keep previous \"test\" status only if current is also test\n            prev_node.test = prev_node.test and (node.test or require.test)\n            self._save_options_conflicts(node, require, prev_node, graph)\n            require.process_package_type(node, prev_node)\n            graph.add_edge(node, prev_node, require)\n            node.propagate_closing_loop(require, prev_node, graph.visibility_conflicts)\n\n    def _save_options_conflicts(self, node, require, prev_node, graph):\n        \"\"\" Store the discrepancies of options when closing a diamond, to later report\n        them. This list is not exhaustive, only the diamond vertix, not other transitives\n        \"\"\"\n        down_options = self._compute_down_options(node, require, prev_node.ref)\n        down_options = down_options._deps_package_options  # noqa\n        if not down_options:\n            return\n        down_pkg_options = _PackageOptions()\n        for pattern, options in down_options.items():\n            if ref_matches(prev_node.ref, pattern, is_consumer=False):\n                down_pkg_options.update_options(options)\n        prev_options = {k: v for k, v in prev_node.conanfile.options.items()}\n        for k, v in down_pkg_options.items():\n            prev_value = prev_options.get(k)\n            if prev_value is not None and prev_value != v:\n                d = graph.options_conflicts.setdefault(str(prev_node.ref), {})\n                conflicts = d.setdefault(k, {\"value\": prev_value}).setdefault(\"conflicts\", [])\n                conflicts.append((node.ref, v))\n\n    @staticmethod\n    def _conflicting_version(require, node,\n                             prev_require, prev_node, prev_ref, base_previous, resolve_prereleases):\n        # As we are closing a diamond, there can be conflicts. This will raise if so\n        version_range = require.version_range\n        prev_version_range = prev_require.version_range if prev_node is None else None\n        if version_range:\n            if require.ref.user != prev_require.ref.user or \\\n                    require.ref.channel != prev_require.ref.channel:\n                raise GraphConflictError(node, require, prev_node, prev_require, base_previous)\n            if prev_version_range is not None:\n                # It it is not conflicting, but range can be incompatible, restrict range\n                restricted_version_range = version_range.intersection(prev_version_range)\n                if restricted_version_range is None:\n                    raise GraphConflictError(node, require, prev_node, prev_require, base_previous)\n                require.ref.version = restricted_version_range.version()\n            else:\n                if version_range.contains(prev_ref.version, resolve_prereleases):\n                    require.ref = prev_ref\n                else:\n                    raise GraphConflictError(node, require, prev_node, prev_require, base_previous)\n        elif prev_version_range is not None:\n            if require.ref.user != prev_require.ref.user or \\\n                    require.ref.channel != prev_require.ref.channel or \\\n                    not prev_version_range.contains(require.ref.version, resolve_prereleases):\n                raise GraphConflictError(node, require, prev_node, prev_require, base_previous)\n        else:\n            if prev_ref != require.ref:\n                raise GraphConflictError(node, require, prev_node, prev_require, base_previous)\n            # If there is no conflict, then the incomplete require without revision can be updated\n            # with the previous revision to avoid the later conflict\n            if prev_ref.revision is not None and require.ref.revision is None:\n                require.ref.revision = prev_ref.revision\n\n    @staticmethod\n    def _prepare_node(node, profile_host, profile_build, down_options, define_consumers=False):\n        # basic node configuration: calling configure() and requirements()\n        conanfile, ref = node.conanfile, node.ref\n\n        profile_options = profile_host.options if node.context == CONTEXT_HOST \\\n            else profile_build.options\n        assert isinstance(profile_options, Options), type(profile_options)\n        run_configure_method(conanfile, down_options, profile_options, ref)\n\n        if define_consumers:  # Mark this requirements as the \"consumers\" nodes\n            tested_ref = getattr(conanfile, \"tested_reference_str\", None)\n            tested_ref = RecipeReference.loads(tested_ref) if tested_ref else None\n            for r in conanfile.requires.values():\n                if tested_ref is None or r.ref == tested_ref:\n                    r.is_consumer = True\n\n        # Apply build_tools_requires from profile, overriding the declared ones\n        profile = profile_host if node.context == CONTEXT_HOST else profile_build\n        for pattern, tool_requires in profile.tool_requires.items():\n            if ref_matches(ref, pattern, is_consumer=conanfile._conan_is_consumer):  # noqa\n                for tool_require in tool_requires:  # Do the override\n                    # Check if it is a self-loop of build-requires in build context and avoid it\n                    if ref and tool_require.name == ref.name and tool_require.user == ref.user and \\\n                            tool_require.channel == ref.channel:\n                        if tool_require.version == ref.version:\n                            continue\n                        # Also avoid it if the version is in the range\n                        version_range = repr(tool_require.version)\n                        if version_range[0] == \"[\" and version_range[-1] == \"]\":\n                            if ref.version.in_range(version_range[1:-1]):\n                                continue\n                    node.conanfile.requires.tool_require(tool_require.repr_notime(),\n                                                         raise_if_duplicated=False)\n\n    def _initialize_requires(self, node, graph, graph_lock, profile_build, profile_host):\n        result = []\n        skip_build = node.conanfile.conf.get(\"tools.graph:skip_build\", check_type=bool)\n        skip_test = node.conanfile.conf.get(\"tools.graph:skip_test\", check_type=bool)\n        for require in node.conanfile.requires.values():\n            if not require.visible and not require.package_id_mode:\n                if skip_build and require.build:\n                    node.skipped_build_requires = True\n                    continue\n                if skip_test and require.test:\n                    continue\n            result.append(require)\n            alias = require.alias  # alias needs to be processed this early\n            if alias is not None:\n                if not DepsGraphBuilder.ALLOW_ALIAS and os.getenv(\"CONAN_ALLOW_ALIAS\") != \"will_break_next\":\n                    raise ConanException(f\"Alias requirements have been removed: '{node}' requiring: '{alias}'\")\n                resolved = False\n                if graph_lock is not None:\n                    resolved = graph_lock.replace_alias(require, alias)\n                # if partial, we might still need to resolve the alias\n                if not resolved:\n                    self._resolve_alias(node, require, alias, graph)\n            self._resolve_replace_requires(node, require, profile_build, profile_host, graph)\n            if graph_lock:\n                graph_lock.resolve_overrides(require, node.context)\n            node.transitive_deps[require] = TransitiveRequirement(require, node=None)\n        return result\n\n    def _resolve_alias(self, node, require, alias, graph):\n        # First try cached\n        cached = graph.aliased.get(alias)\n        if cached is not None:\n            while True:\n                new_cached = graph.aliased.get(cached)\n                if new_cached is None:\n                    break\n                else:\n                    cached = new_cached\n            require.ref = cached\n            return\n\n        while alias is not None:\n            # if not cached, then resolve\n            try:\n                result = self._proxy.get_recipe(alias, self._remotes, self._update,\n                                                self._check_update)\n                layout, recipe_status, remote = result\n            except ConanException as e:\n                raise GraphMissingError(node, require, str(e))\n\n            conanfile_path = layout.conanfile()\n            dep_conanfile = self._loader.load_basic(conanfile_path)\n            try:\n                pointed_ref = RecipeReference.loads(dep_conanfile.alias)\n            except Exception as e:\n                raise ConanException(f\"Alias definition error in {alias}: {str(e)}\")\n\n            # UPDATE THE REQUIREMENT!\n            require.ref = pointed_ref\n            graph.aliased[alias] = pointed_ref  # Caching the alias\n            new_req = Requirement(pointed_ref)  # FIXME: Ugly temp creation just for alias check\n            alias = new_req.alias\n            node.conanfile.output.warning(\"Requirement 'alias' is provided in Conan 2 mainly for \"\n                                          \"compatibility and upgrade from Conan 1, but it is an \"\n                                          \"undocumented and legacy feature. Please update to use \"\n                                          \"standard versioning mechanisms\", warn_tag=\"legacy\")\n\n    def _resolve_recipe(self, ref, graph_lock):\n        result = self._proxy.get_recipe(ref, self._remotes, self._update, self._check_update)\n        layout, recipe_status, remote = result\n        conanfile_path = layout.conanfile()\n        dep_conanfile = self._loader.load_conanfile(conanfile_path, ref=ref, graph_lock=graph_lock,\n                                                    remotes=self._remotes, update=self._update,\n                                                    check_update=self._check_update)\n        return layout, dep_conanfile, recipe_status, remote\n\n    @staticmethod\n    def _resolved_system(node, require, profile_build, profile_host, resolve_prereleases):\n        profile = profile_build if node.context == CONTEXT_BUILD else profile_host\n        if node.context == CONTEXT_BUILD:\n            # If we are in the build context, the platform_tool_requires ALSO applies to the\n            # regular requires. It is not possible in the build context to have tool-requires\n            # and regular requires to the same package from Conan and from Platform\n            system_reqs = profile.platform_tool_requires\n            if not require.build:\n                system_reqs = system_reqs + profile.platform_requires\n        else:\n            system_reqs = profile.platform_tool_requires if require.build \\\n                else profile.platform_requires\n        if system_reqs:\n            version_range = require.version_range\n            for d in system_reqs:\n                if require.ref.name == d.name:\n                    if version_range:\n                        if version_range.contains(d.version, resolve_prereleases):\n                            require.ref.version = d.version  # resolved range is replaced by exact\n                            require.ref.revision = d.revision or \"platform\"\n                            layout = BasicLayout(require.ref, None)\n                            return layout, ConanFile(str(d)), RECIPE_PLATFORM, None\n                    elif require.ref.version == d.version:\n                        if d.revision is None or require.ref.revision is None or \\\n                                d.revision == require.ref.revision:\n                            require.ref.revision = d.revision or \"platform\"\n                            layout = BasicLayout(require.ref, None)\n                            return layout, ConanFile(str(d)), RECIPE_PLATFORM, None\n\n    def _resolve_replace_requires(self, node, require, profile_build, profile_host, graph):\n        profile = profile_build if node.context == CONTEXT_BUILD else profile_host\n        replacements = profile.replace_tool_requires if require.build else profile.replace_requires\n        if not replacements:\n            return\n\n        for pattern, alternative_ref in replacements.items():\n            if pattern.name != require.ref.name:\n                continue  # no match in name\n            if pattern.version != \"*\":  # we need to check versions\n                rrange = require.version_range\n                # Is the version pattern a range itself?\n                pversion = repr(pattern.version)\n                if pversion[0] == \"[\" and pversion[-1] == \"]\":\n                    prange = VersionRange(pversion[1:-1])\n                    if rrange:\n                        valid = prange.intersection(rrange) is not None\n                    else:\n                        valid = prange.contains(require.ref.version, self._resolve_prereleases)\n                else:\n                    if rrange:\n                        valid = rrange.contains(pattern.version, self._resolve_prereleases)\n                    else:\n                        valid = require.ref.version == pattern.version\n                if not valid:\n                    continue\n            if pattern.user != \"*\" and pattern.user != require.ref.user:\n                continue\n            if pattern.channel != \"*\" and pattern.channel != require.ref.channel:\n                continue\n            require._required_ref = require.ref.copy()  # Save the original ref before replacing\n            original_require = repr(require.ref)\n            if alternative_ref.version != \"*\":\n                require.ref.version = alternative_ref.version\n            if alternative_ref.user != \"*\":\n                require.ref.user = alternative_ref.user\n            if alternative_ref.channel != \"*\":\n                require.ref.channel = alternative_ref.channel\n            if alternative_ref.revision != \"*\":\n                require.ref.revision = alternative_ref.revision\n            if require.ref.name != alternative_ref.name:  # This requires re-doing dict!\n                node.conanfile.requires.reindex(require, alternative_ref.name)\n            require.ref.name = alternative_ref.name\n            graph.replaced_requires[original_require] = repr(require.ref)\n            node.replaced_requires[original_require] = require\n            break  # First match executes the alternative and finishes checking others\n\n    @staticmethod\n    def _deduce_host_version(require, node):\n        require_version = str(require.ref.version)\n        if require_version.startswith(\"<host_version\") and require_version.endswith(\">\"):\n            if not require.build or require.visible:\n                raise ConanException(f\"{node.ref} require '{require.ref}': 'host_version' can only \"\n                                     \"be used for non-visible tool_requires\")\n            tracking_ref = require_version.split(':', 1)\n            ref = require.ref\n            if len(tracking_ref) > 1:\n                ref = RecipeReference.loads(str(require.ref))\n                ref.name = tracking_ref[1][:-1]  # Remove the trailing >\n            req = Requirement(ref, headers=True, libs=True, visible=True)\n            transitive = node.transitive_deps.get(req)\n            if transitive is None:\n                raise ConanException(f\"{node.ref} require '{ref}': didn't find a matching \"\n                                     \"host dependency\")\n            require.ref.version = transitive.require.ref.version\n\n    def _create_new_node(self, node, require, graph, profile_host, profile_build, graph_lock):\n        resolved = self._resolved_system(node, require, profile_build, profile_host,\n                                         self._resolve_prereleases)\n        if graph_lock is not None:\n            # Here is when the ranges and revisions are resolved\n            graph_lock.resolve_locked(node, require, self._resolve_prereleases)\n\n        if resolved is None:\n            try:\n                # TODO: If it is locked not resolve range\n                # TODO: This range-resolve might resolve in a given remote or cache\n                # Make sure next _resolve_recipe use it\n                self._resolver.resolve(require, str(node.ref), self._remotes, self._update)\n                resolved = self._resolve_recipe(require.ref, graph_lock)\n            except ConanException as e:\n                raise GraphMissingError(node, require, str(e))\n\n        layout, dep_conanfile, recipe_status, remote = resolved\n\n        new_ref = layout.reference\n        dep_conanfile.folders.set_base_recipe_metadata(layout.metadata())  # None for platform_xxx\n        if getattr(require, \"is_consumer\", None):\n            dep_conanfile._conan_is_consumer = True\n        initialize_conanfile_profile(dep_conanfile, profile_build, profile_host, node.context,\n                                     require.build, new_ref, parent=node.conanfile)\n\n        context = CONTEXT_BUILD if require.build else node.context\n        new_node = Node(new_ref, dep_conanfile, context=context, test=require.test or node.test)\n        new_node.recipe = recipe_status\n        new_node.remote = remote\n\n        down_options = self._compute_down_options(node, require, new_ref)\n\n        if recipe_status != RECIPE_PLATFORM:\n            self._prepare_node(new_node, profile_host, profile_build, down_options)\n        if dep_conanfile.package_type is PackageType.CONF and node.recipe != RECIPE_VIRTUAL:\n            raise ConanException(f\"Configuration package {dep_conanfile} cannot be used as \"\n                                 f\"requirement, but {node.ref} is requiring it\")\n\n        require.process_package_type(node, new_node)\n        graph.add_node(new_node)\n        graph.add_edge(node, new_node, require)\n        node.propagate_downstream(require, new_node, graph.visibility_conflicts)\n\n        # This is necessary to prevent infinite loops even when visibility is False\n        ancestor = node.check_loops(new_node)\n        if ancestor is not None:\n            raise GraphLoopError(new_node, require, ancestor)\n\n        return new_node\n\n    @staticmethod\n    def _compute_down_options(node, require, new_ref):\n        # The consumer \"up_options\" are the options that come from downstream to this node\n        visible = require.visible and not node.conanfile.vendor\n        if require.options is not None:\n            # If the consumer has specified \"requires(options=xxx)\", we need to use it\n            # It will have less priority than downstream consumers\n            down_options = Options(options_values=require.options)\n            down_options.scope(new_ref)\n            # At the moment, the behavior is the most restrictive one: default_options and\n            # options[\"dep\"].opt=value only propagate to visible and host dependencies\n            # we will evaluate if necessary a potential \"build_options\", but recall that it is\n            # now possible to do \"self.build_requires(..., options={k:v})\" to specify it\n            if visible:\n                # Only visible requirements in the host context propagate options from downstream\n                down_options.update_options(node.conanfile.up_options)\n        else:\n            if visible:\n                down_options = node.conanfile.up_options\n            elif not require.build:  # for requires in \"host\", like test_requires, pass myoptions\n                down_options = node.conanfile.private_up_options\n            else:\n                down_options = Options(options_values=node.conanfile.default_build_options)\n        return down_options\n\n    @staticmethod\n    def _remove_overrides(dep_graph):\n        for node in dep_graph.nodes:\n            to_remove = [r for r in node.transitive_deps if r.override]\n            for r in to_remove:\n                node.transitive_deps.pop(r)\n\n    @staticmethod\n    def _remove_orphans(dep_graph):\n        # when requires to the same thing with different visible=xxx converge, there can be orphans\n        opened = {dep_graph.root}\n        all_referenced = set()\n        while opened:\n            all_referenced.update(opened)\n            next_open = set(edge.dst for node in opened for edge in node.edges\n                            if edge.dst not in all_referenced)\n            opened = next_open\n        # Keep order in previous list\n        dep_graph.nodes = [n for n in dep_graph.nodes if n in all_referenced]\n"
  },
  {
    "path": "conan/internal/graph/graph_error.py",
    "content": "from conan.errors import ConanException\n\n\nclass GraphError(ConanException):\n    def serialize(self):\n        return\n\n\nclass GraphConflictError(GraphError):\n\n    def __init__(self, node, require, prev_node, prev_require, base_previous):\n        self.node = node\n        self.require = require\n        self.prev_node = prev_node\n        self.prev_require = prev_require\n        self.base_previous = base_previous\n\n    def serialize(self):\n        dst_id = self.prev_node.id if self.prev_node else None\n        return {\"type\": \"conflict\",\n                \"name\": self.require.ref.name,\n                \"branch1\": {\"src_id\": self.base_previous.id, \"src_ref\": str(self.base_previous.ref),\n                            \"dst_id\": dst_id, \"require\": self.prev_require.serialize()},\n                \"branch2\": {\"src_id\": self.node.id, \"src_ref\": str(self.node.ref),\n                            \"require\": self.require.serialize()}}\n\n    def __str__(self):\n        conflicting_node = self.node.ref or self.base_previous.ref\n        conflicting_node_msg = \"\"\n        if conflicting_node is not None:\n            conflicting_node_msg = f\"\\nConflict originates from {conflicting_node}\\n\"\n        return f\"Version conflict: \" \\\n               f\"Conflict between {self.require.ref} and {self.prev_require.ref} in the graph.\" \\\n               f\"{conflicting_node_msg}\" \\\n               f\"\\nRun 'conan graph info ... --format=html > graph.html' \" \\\n               f\"and open 'graph.html' to inspect the conflict graphically.\"\n\n\nclass GraphLoopError(GraphError):\n\n    def __init__(self, node, require, ancestor):\n        self.node = node\n        self.require = require\n        self.ancestor = ancestor\n\n    def serialize(self):\n        return {\"type\": \"loop\",\n                \"require\": {**self.require.serialize(), \"name\": str(self.require.ref).split(\"/\")[0]},\n                \"node\": self.node.serialize(),\n                \"ancestor\": self.ancestor.serialize()\n                }\n\n    def __str__(self):\n        return \"There is a cycle/loop in the graph:\\n\" \\\n               f\"    Initial ancestor: {self.ancestor}\\n\" \\\n               f\"    Require: {self.require.ref}\\n\" \\\n               f\"    Dependency: {self.node}\"\n\n\nclass GraphMissingError(GraphError):\n\n    def __init__(self, node, require, missing_error):\n        self.node = node\n        self.require = require\n        self.missing_error = missing_error\n\n    def serialize(self):\n        return {\"type\": \"missing\",\n                \"node\": {\"id\": self.node.id, \"ref\": str(self.node.ref)},\n                \"require\": self.require.serialize(),\n                \"error\": self.missing_error}\n\n    def __str__(self):\n        return (f\"Package '{self.require.ref}' not resolved: {self.missing_error}. \"\n                f\"Required by '{self.node.ref or 'cli'}'\")\n\n\nclass GraphProvidesError(GraphError):\n\n    def __init__(self, node, conflicting_node):\n        self.node = node\n        self.conflicting_node = conflicting_node\n        node.error = conflicting_node.error\n\n    def serialize(self):\n        return {\"type\": \"provide_conflict\",\n                \"node\": {\"id\": self.node.id, \"ref\": str(self.node.ref)},\n                \"conflicting_node\": {\"id\": self.conflicting_node.id,\n                                     \"ref\": str(self.conflicting_node.ref)},\n                \"provided\": self.node.conanfile.provides or self.conflicting_node.conanfile.provides}\n\n    def __str__(self):\n        provides = self.node.conanfile.provides or self.conflicting_node.conanfile.provides\n        return f\"Provide Conflict: Both '{self.node.ref}' and '{self.conflicting_node.ref}' \" \\\n               f\"provide '{provides}'.\"\n"
  },
  {
    "path": "conan/internal/graph/install_graph.py",
    "content": "import json\nimport os\nimport textwrap\n\nfrom conan.api.output import ConanOutput\nfrom conan.internal.graph.graph import RECIPE_CONSUMER, RECIPE_VIRTUAL, BINARY_SKIP, \\\n    BINARY_MISSING, BINARY_INVALID, Overrides, BINARY_BUILD, BINARY_EDITABLE_BUILD, BINARY_PLATFORM\nfrom conan.errors import ConanException, ConanInvalidConfiguration\nfrom conan.api.model import PkgReference\nfrom conan.api.model import RecipeReference\nfrom conan.internal.util.files import load\n\n\nclass _InstallPackageReference:\n    \"\"\" Represents a single, unique PackageReference to be downloaded, built, etc.\n    Same PREF should only be built or downloaded once, but it is possible to have multiple\n    nodes in the DepsGraph that share the same PREF.\n    PREF could have PREV if to be downloaded (must be the same for all), but won't if to be built\n    \"\"\"\n    def __init__(self):\n        self.package_id = None\n        self.prev = None\n        self.nodes = []  # GraphNode\n        self.binary = None  # The action BINARY_DOWNLOAD, etc must be the same for all nodes\n        self.context = None  # Same PREF could be in both contexts, but only 1 context is enough to\n        # be able to reproduce, typically host preferrably\n        self.options = []  # to be able to fire a build, the options will be necessary\n        self.filenames = []  # The build_order.json filenames e.g. \"windows_build_order\"\n        # If some package, like ICU, requires itself, built for the \"build\" context architecture\n        # to cross compile, there will be a dependency from the current \"self\" (host context)\n        # to that \"build\" package_id.\n        self.depends = []  # List of package_ids of dependencies to other binaries of the same ref\n        self.overrides = Overrides()\n        self.ref = None\n        self.info = None\n\n    @property\n    def pref(self):\n        return PkgReference(self.ref, self.package_id, self.prev)\n\n    @property\n    def conanfile(self):\n        return self.nodes[0].conanfile\n\n    @staticmethod\n    def create(node):\n        result = _InstallPackageReference()\n        result.ref = node.ref\n        result.package_id = node.pref.package_id\n        result.prev = node.pref.revision\n        result.binary = node.binary\n        result.context = node.context\n        # self_options are the minimum to reproduce state\n        result.options = node.conanfile.self_options.dumps().splitlines()\n        result.nodes.append(node)\n        result.overrides = node.overrides()\n        result.info = node.conanfile.info.serialize()  # ConanInfo doesn't have deserialize\n        return result\n\n    def add(self, node):\n        assert self.package_id == node.package_id\n        assert self.binary == node.binary, f\"Binary for {node}: {self.binary}!={node.binary}\"\n        assert self.prev == node.prev\n        # The context might vary, but if same package_id, all fine\n        # assert self.context == node.context\n        self.nodes.append(node)\n\n    def _build_args(self):\n        if self.binary not in (BINARY_BUILD, BINARY_EDITABLE_BUILD):\n            return None\n        cmd = f\"--requires={self.ref}\" if self.context == \"host\" else f\"--tool-requires={self.ref}\"\n        compatible = \"compatible:\" if self.info and self.info.get(\"compatibility_delta\") else \"\"\n        cmd += f\" --build={compatible}{self.ref}\"\n        if self.options:\n            scope = \"\" if self.context == \"host\" else \":b\"\n            cmd += \" \" + \" \".join(f'-o{scope}=\"{o}\"' for o in self.options)\n        if self.overrides:\n            cmd += f' --lockfile-overrides=\"{self.overrides}\"'\n        return cmd\n\n    def serialize(self):\n        return {\"package_id\": self.package_id,\n                \"prev\": self.prev,\n                \"context\": self.context,\n                \"binary\": self.binary,\n                \"options\": self.options,\n                \"filenames\": self.filenames,\n                \"depends\": self.depends,\n                \"overrides\": self.overrides.serialize(),\n                \"build_args\": self._build_args(),\n                \"info\": self.info}\n\n    @staticmethod\n    def deserialize(data, filename, ref):\n        result = _InstallPackageReference()\n        result.ref = ref\n        result.package_id = data[\"package_id\"]\n        result.prev = data[\"prev\"]\n        result.binary = data[\"binary\"]\n        result.context = data[\"context\"]\n        result.options = data[\"options\"]\n        result.filenames = data[\"filenames\"] or [filename]\n        result.depends = data[\"depends\"]\n        result.overrides = Overrides.deserialize(data[\"overrides\"])\n        result.info = data.get(\"info\")\n        return result\n\n\nclass _InstallRecipeReference:\n    \"\"\" represents a single, unique Recipe reference (including revision, must have it) containing\n    all the _InstallPackageReference that belongs to this RecipeReference. This approach is\n    oriented towards a user-intuitive grouping specially in CI, in which all binary variants for the\n    same recipe revision (repo+commit) are to be built grouped together\"\"\"\n    def __init__(self):\n        self.ref = None\n        self._node = None\n        self.packages = {}  # {package_id: _InstallPackageReference}\n        self.depends = []  # Other REFs, defines the graph topology and operation ordering\n\n    def __str__(self):\n        return f\"{self.ref} ({self._node.binary}) -> {[str(d) for d in self.depends]}\"\n\n    @property\n    def need_build(self):\n        for package in self.packages.values():\n            if package.binary in (BINARY_BUILD, BINARY_EDITABLE_BUILD):\n                return True\n        return False\n\n    def reduce(self):\n        result = _InstallRecipeReference()\n        result.ref = self.ref\n        result._node = self._node\n        result.depends = self.depends\n        result.packages = {pid: pkg for pid, pkg in self.packages.items()\n                           if pkg.binary in (BINARY_BUILD, BINARY_EDITABLE_BUILD)}\n        return result\n\n    @property\n    def node(self):\n        return self._node\n\n    @staticmethod\n    def create(node):\n        result = _InstallRecipeReference()\n        result._node = node\n        result.ref = node.ref\n        result.add(node)\n        return result\n\n    def merge(self, other):\n        assert self.ref == other.ref\n        for d in other.depends:\n            if d not in self.depends:\n                self.depends.append(d)\n        for other_pkgid, other_pkg in other.packages.items():\n            existing = self.packages.get(other_pkgid)\n            if existing is None:\n                self.packages[other_pkgid] = other_pkg\n            else:\n                assert existing.binary == other_pkg.binary\n                for f in other_pkg.filenames:\n                    if f not in existing.filenames:\n                        existing.filenames.append(f)\n\n    def add(self, node):\n        install_pkg_ref = self.packages.get(node.package_id)\n        if install_pkg_ref is not None:\n            install_pkg_ref.add(node)\n        else:\n            install_pkg_ref = _InstallPackageReference.create(node)\n            self.packages[node.package_id] = install_pkg_ref\n\n        for dep in node.edges:\n            if dep.dst.binary != BINARY_SKIP:\n                if dep.dst.ref == node.ref:  # If the node is itself, then it is internal dep\n                    install_pkg_ref.depends.append(dep.dst.pref.package_id)\n                elif dep.dst.ref not in self.depends:\n                    self.depends.append(dep.dst.ref)\n\n    def _install_order(self):\n        # TODO: Repeated, refactor\n        # a topological order by levels, returns a list of list, in order of processing\n        levels = []\n        opened = self.packages\n        while opened:\n            current_level = []\n            closed = []\n            for o in opened.values():\n                requires = o.depends\n                if not any(n in opened for n in requires):\n                    current_level.append(o)\n                    closed.append(o)\n\n            if current_level:\n                levels.append(current_level)\n            # now initialize new level\n            opened = {k: v for k, v in opened.items() if v not in closed}\n\n        return levels\n\n    def serialize(self):\n        return {\"ref\": self.ref.repr_notime(),\n                \"depends\": [ref.repr_notime() for ref in self.depends],\n                \"packages\": [[v.serialize() for v in level] for level in self._install_order()]\n                }\n\n    @staticmethod\n    def deserialize(data, filename):\n        result = _InstallRecipeReference()\n        result.ref = RecipeReference.loads(data[\"ref\"])\n        for d in data[\"depends\"]:\n            result.depends.append(RecipeReference.loads(d))\n        for level in data[\"packages\"]:\n            for p in level:\n                install_node = _InstallPackageReference.deserialize(p, filename, result.ref)\n                result.packages[install_node.package_id] = install_node\n        return result\n\n\nclass _InstallConfiguration:\n    \"\"\" Represents a single, unique PackageReference to be downloaded, built, etc.\n    Same PREF should only be built or downloaded once, but it is possible to have multiple\n    nodes in the DepsGraph that share the same PREF.\n    PREF could have PREV if to be downloaded (must be the same for all), but won't if to be built\n    \"\"\"\n    def __init__(self):\n        self.ref = None\n        self.package_id = None\n        self.prev = None\n        self.nodes = []  # GraphNode\n        self.binary = None  # The action BINARY_DOWNLOAD, etc must be the same for all nodes\n        self.context = None  # Same PREF could be in both contexts, but only 1 context is enough to\n        # be able to reproduce, typically host preferrably\n        self.options = []  # to be able to fire a build, the options will be necessary\n        self.filenames = []  # The build_order.json filenames e.g. \"windows_build_order\"\n        self.depends = []  # List of full prefs\n        self.overrides = Overrides()\n        self.info = None\n\n    def __str__(self):\n        return f\"{self.ref}:{self.package_id} ({self.binary}) -> {[str(d) for d in self.depends]}\"\n\n    @property\n    def need_build(self):\n        return self.binary in (BINARY_BUILD, BINARY_EDITABLE_BUILD)\n\n    def reduce(self):\n        return self\n\n    @property\n    def pref(self):\n        return PkgReference(self.ref, self.package_id, self.prev)\n\n    @property\n    def conanfile(self):\n        return self.nodes[0].conanfile\n\n    @staticmethod\n    def create(node):\n        result = _InstallConfiguration()\n        result.ref = node.ref\n        result.package_id = node.pref.package_id\n        result.prev = node.pref.revision\n        result.binary = node.binary\n        result.context = node.context\n        # self_options are the minimum to reproduce state\n        result.options = node.conanfile.self_options.dumps().splitlines()\n        result.overrides = node.overrides()\n        result.info = node.conanfile.info.serialize()\n\n        result.nodes.append(node)\n        for dep in node.edges:\n            if dep.dst.binary != BINARY_SKIP:\n                if dep.dst.pref not in result.depends:\n                    result.depends.append(dep.dst.pref)\n        return result\n\n    def add(self, node):\n        assert self.package_id == node.package_id, f\"{self.pref}!={node.pref}\"\n        assert self.binary == node.binary, f\"Binary for {node}: {self.binary}!={node.binary}\"\n        assert self.prev == node.prev\n        # The context might vary, but if same package_id, all fine\n        # assert self.context == node.context\n        self.nodes.append(node)\n\n        for edge in node.edges:\n            if edge.dst.binary != BINARY_SKIP:\n                if edge.dst.pref not in self.depends:\n                    self.depends.append(edge.dst.pref)\n\n    def _build_args(self):\n        if self.binary not in (BINARY_BUILD, BINARY_EDITABLE_BUILD):\n            return None\n        cmd = f\"--requires={self.ref}\" if self.context == \"host\" else f\"--tool-requires={self.ref}\"\n        compatible = \"compatible:\" if self.info and self.info.get(\"compatibility_delta\") else \"\"\n        cmd += f\" --build={compatible}{self.ref}\"\n        if self.options:\n            scope = \"\" if self.context == \"host\" else \":b\"\n            cmd += \" \" + \" \".join(f'-o{scope}=\"{o}\"' for o in self.options)\n        if self.overrides:\n            cmd += f' --lockfile-overrides=\"{self.overrides}\"'\n        return cmd\n\n    def serialize(self):\n        return {\"ref\": self.ref.repr_notime(),\n                \"pref\": self.pref.repr_notime(),\n                \"package_id\": self.pref.package_id,\n                \"prev\": self.pref.revision,\n                \"context\": self.context,\n                \"binary\": self.binary,\n                \"options\": self.options,\n                \"filenames\": self.filenames,\n                \"depends\": [d.repr_notime() for d in self.depends],\n                \"overrides\": self.overrides.serialize(),\n                \"build_args\": self._build_args(),\n                \"info\": self.info\n                }\n\n    @staticmethod\n    def deserialize(data, filename):\n        result = _InstallConfiguration()\n        result.ref = RecipeReference.loads(data[\"ref\"])\n        result.package_id = data[\"package_id\"]\n        result.prev = data[\"prev\"]\n        result.binary = data[\"binary\"]\n        result.context = data[\"context\"]\n        result.options = data[\"options\"]\n        result.filenames = data[\"filenames\"] or [filename]\n        result.depends = [PkgReference.loads(p) for p in data[\"depends\"]]\n        result.overrides = Overrides.deserialize(data[\"overrides\"])\n        result.info = data.get(\"info\")\n        return result\n\n    def merge(self, other):\n        assert self.binary == other.binary, f\"Binary for {self.ref}: {self.binary}!={other.binary}\"\n\n        assert self.ref == other.ref\n        for d in other.depends:\n            if d not in self.depends:\n                self.depends.append(d)\n\n        for d in other.filenames:\n            if d not in self.filenames:\n                self.filenames.append(d)\n\n\nclass ProfileArgs:\n    def __init__(self, args):\n        self._args = args\n\n    @staticmethod\n    def from_args(args):\n        pr_args = []\n        for context in \"host\", \"build\":\n            for f in \"profile\", \"settings\", \"options\", \"conf\":\n                s = \"pr\" if f == \"profile\" else f[0]\n                pr_args += [f'-{s}:{context[0]}=\"{v}\"' for v in\n                            getattr(args, f\"{f}_{context}\") or []]\n        return ProfileArgs(\" \".join(pr_args))\n\n    def __str__(self):\n        return self._args\n\n    @staticmethod\n    def deserialize(data):\n        return ProfileArgs(data.get(\"args\"))\n\n    def serialize(self):\n        return {\"args\": self._args}\n\n\nclass InstallGraph:\n    \"\"\" A graph containing the package references in order to be built/downloaded\n    \"\"\"\n\n    def __init__(self, deps_graph, order_by=None, profile_args=None):\n        self._nodes = {}  # ref with rev: _InstallGraphNode\n        order_by = order_by or \"recipe\"\n        self._order = order_by\n        self._node_cls = _InstallRecipeReference if order_by == \"recipe\" else _InstallConfiguration\n        self._is_test_package = False\n        self.reduced = False\n        self._profiles = {\"self\": profile_args} if profile_args is not None else {}\n        self._filename = None\n        if deps_graph is not None:\n            self._initialize_deps_graph(deps_graph)\n            self._is_test_package = deps_graph.root.conanfile.tested_reference_str is not None\n\n    @staticmethod\n    def load(filename):\n        data = json.loads(load(filename))\n        filename = os.path.basename(filename)\n        filename = os.path.splitext(filename)[0]\n        install_graph = InstallGraph.deserialize(data, filename)\n        return install_graph\n\n    def merge(self, other):\n        \"\"\"\n        :type other: InstallGraph\n        \"\"\"\n        if self.reduced or other.reduced:\n            raise ConanException(\"Reduced build-order files cannot be merged\")\n        if self._order != other._order:\n            raise ConanException(f\"Cannot merge build-orders of {self._order}!={other._order}\")\n        for ref, install_node in other._nodes.items():\n            existing = self._nodes.get(ref)\n            if existing is None:\n                self._nodes[ref] = install_node\n            else:\n                existing.merge(install_node)\n        # Make sure that self is also updated\n        current = self._profiles.pop(\"self\", None)\n        if current is not None:\n            self._profiles[self._filename] = current\n        new = other._profiles.get(\"self\")\n        if new is not None:\n            self._profiles[other._filename] = new\n\n    @staticmethod\n    def deserialize(data, filename):\n        legacy = isinstance(data, list)\n        order, data, reduced, profiles = (\"recipe\", data, False, {}) if legacy else \\\n            (data[\"order_by\"], data[\"order\"], data[\"reduced\"], data.get(\"profiles\", {}))\n        result = InstallGraph(None, order_by=order)\n        result.reduced = reduced\n        result.legacy = legacy\n        result._filename = filename\n        result._profiles = {k: ProfileArgs.deserialize(v) for k, v in profiles.items()}\n        for level in data:\n            for item in level:\n                elem = result._node_cls.deserialize(item, filename)\n                key = elem.ref if order == \"recipe\" else elem.pref\n                result._nodes[key] = elem\n        return result\n\n    def _initialize_deps_graph(self, deps_graph):\n        for node in deps_graph.ordered_iterate():\n            if node.recipe in (RECIPE_CONSUMER, RECIPE_VIRTUAL) \\\n                    or node.binary in (BINARY_SKIP, BINARY_PLATFORM):\n                continue\n\n            key = node.ref if self._order == \"recipe\" else node.pref\n            existing = self._nodes.get(key)\n            if existing is None:\n                self._nodes[key] = self._node_cls.create(node)\n            else:\n                existing.add(node)\n\n    def reduce(self):\n        result = {}\n        for k, node in self._nodes.items():\n            if node.need_build:\n                result[k] = node.reduce()\n            else:  # Eliminate this element from the graph\n                dependencies = node.depends\n                # Find all consumers\n                for n in self._nodes.values():\n                    if k in n.depends:\n                        n.depends = [d for d in n.depends if d != k]  # Discard the removed node\n                        # Add new edges, without repetition\n                        n.depends.extend(d for d in dependencies if d not in n.depends)\n        self._nodes = result\n        self.reduced = True\n\n    def install_order(self, flat=False):\n        # a topological order by levels, returns a list of list, in order of processing\n        levels = []\n        opened = self._nodes\n        while opened:\n            current_level = []\n            closed = []\n            for o in opened.values():\n                requires = o.depends\n                if not any(n in opened for n in requires):\n                    current_level.append(o)\n                    closed.append(o)\n\n            if current_level:\n                levels.append(current_level)\n            else:\n                self._raise_loop_detected(opened)\n\n            # now initialize new level\n            opened = {k: v for k, v in opened.items() if v not in closed}\n        if flat:\n            return [r for level in levels for r in level]\n        return levels\n\n    @staticmethod\n    def _raise_loop_detected(nodes):\n        \"\"\"\n        We can exclude the nodes that have already been processed they do not content loops\n        \"\"\"\n        msg = [f\"{n}\" for n in nodes.values()]\n        msg = \"\\n\".join(msg)\n        instructions = \"This graph is ill-formed, and cannot be installed\\n\" \\\n                       \"Most common cause is having dependencies both in build and host contexts\\n\"\\\n                       \"forming a cycle, due to tool_requires having transitive requires.\\n\"\\\n                       \"Check your profile [tool_requires] and recipe tool and regular requires\\n\"\\\n                       \"You might inspect the dependency graph with:\\n\"\\\n                       \"  $ conan graph info . --format=html > graph.html\"\n        raise ConanException(\"There is a loop in the graph (some packages already ommitted):\\n\"\n                             f\"{msg}\\n\\n{instructions}\")\n\n    def install_build_order(self):\n        # TODO: Rename to serialize()?\n        \"\"\" used for graph build-order and graph build-order-merge commands\n        This is basically a serialization of the build-order\n        \"\"\"\n        install_order = self.install_order()\n        result = {\"order_by\": self._order,\n                  \"reduced\": self.reduced,\n                  \"order\": [[n.serialize() for n in level] for level in install_order],\n                  \"profiles\": {k: v.serialize() for k, v in self._profiles.items()}\n                  }\n        return result\n\n    def _get_missing_invalid_packages(self):\n        missing, invalid = [], []\n\n        def analyze_package(pkg):\n            if pkg.binary == BINARY_MISSING:\n                missing.append(pkg)\n            elif pkg.binary == BINARY_INVALID:\n                invalid.append(pkg)\n        for _, install_node in self._nodes.items():\n            if self._order == \"recipe\":\n                for package in install_node.packages.values():\n                    analyze_package(package)\n            elif self._order == \"configuration\":\n                analyze_package(install_node)\n\n        return missing, invalid\n\n    def raise_errors(self):\n        missing, invalid = self._get_missing_invalid_packages()\n        if invalid:\n            self._raise_invalid(invalid)\n        if missing:\n            self._raise_missing(missing)\n\n    def get_errors(self):\n        missing, invalid = self._get_missing_invalid_packages()\n        errors = []\n        tab = \"    \"\n        if invalid or missing:\n            errors.append(\"There are some error(s) in the graph:\")\n        if invalid:\n            for package in invalid:\n                errors.append(f\"{tab}- {package.pref}: Invalid configuration\")\n        if missing:\n            missing_prefs = set(n.pref for n in missing)  # avoid duplicated\n            for pref in list(sorted([str(pref) for pref in missing_prefs])):\n                errors.append(f\"{tab}- {pref}: Missing binary\")\n        if errors:\n            return \"\\n\".join(errors)\n        return None\n\n    @staticmethod\n    def _raise_invalid(invalid):\n        msg = [\"There are invalid packages:\"]\n        for package in invalid:\n            node = package.nodes[0]\n            if node.conanfile.info.cant_build and node.should_build:\n                binary, reason = \"Cannot build for this configuration\", node.conanfile.info.cant_build\n            else:\n                binary, reason = \"Invalid\", node.conanfile.info.invalid\n            msg.append(\"{}: {}: {}\".format(node.conanfile, binary, reason))\n        raise ConanInvalidConfiguration(\"\\n\".join(msg))\n\n    def _raise_missing(self, missing):\n        # TODO: Remove out argument\n        # TODO: A bit dirty access to .pref\n        missing_prefs = set(n.nodes[0].pref for n in missing)  # avoid duplicated\n        missing_prefs_str = list(sorted([str(pref) for pref in missing_prefs]))\n        out = ConanOutput()\n        for pref_str in missing_prefs_str:\n            out.error(f\"Missing binary: {pref_str}\", error_type=\"exception\")\n        out.writeln(\"\")\n\n        # Report details just the first one\n        install_node = missing[0]\n        node = install_node.nodes[0]\n        package_id = node.package_id\n        ref, conanfile = node.ref, node.conanfile\n\n        msg = f\"Can't find a '{ref}' package binary '{package_id}' for the configuration:\\n\"\\\n              f\"{conanfile.info.dumps()}\"\n        conanfile.output.warning(msg)\n        missing_pkgs = \"', '\".join(list(sorted([str(pref.ref) for pref in missing_prefs])))\n        if self._is_test_package:\n            build_msg = \"This is a **test_package** missing binary. You can use --build (for \" \\\n                        \"all dependencies) or --build-test (exclusive for 'conan create' building \" \\\n                        \"test_package' dependencies) to define what can be built from sources\"\n        else:\n            if len(missing_prefs) >= 5:\n                build_str = \"--build=missing\"\n            else:\n                build_str = \" \".join(list(sorted([\"--build=%s\" % str(pref.ref)\n                                                  for pref in missing_prefs])))\n            build_msg = f\"Try to build locally from sources using the '{build_str}' argument\"\n\n        raise ConanException(textwrap.dedent(f'''\\\n           Missing prebuilt package for '{missing_pkgs}'. You can try:\n               - List all available packages using 'conan list \"{ref}:*\" -r=remote'\n               - Explain missing binaries: replace 'conan install ...' with 'conan graph explain ...'\n               - {build_msg}\n\n           More Info at 'https://docs.conan.io/2/knowledge/faq.html#error-missing-prebuilt-package'\n           '''))\n"
  },
  {
    "path": "conan/internal/graph/installer.py",
    "content": "import os\nimport shutil\nfrom multiprocessing.pool import ThreadPool\n\nfrom conan.api.output import ConanOutput, Color\nfrom conan.internal.methods import run_build_method, run_package_method\nfrom conan.internal.api.install.generators import write_generators\nfrom conan.internal.graph.graph import (BINARY_BUILD, BINARY_CACHE, BINARY_DOWNLOAD,\n                                        BINARY_EDITABLE, BINARY_UPDATE, BINARY_EDITABLE_BUILD,\n                                        BINARY_SKIP)\nfrom conan.internal.graph.install_graph import InstallGraph\nfrom conan.internal.source import retrieve_exports_sources, config_source\nfrom conan.internal.errors import conanfile_remove_attr, conanfile_exception_formatter\nfrom conan.errors import ConanException\nfrom conan.internal.model.cpp_info import CppInfo, MockInfoProperty\nfrom conan.api.model import PkgReference\nfrom conan.internal.paths import CONANINFO\nfrom conan.internal.util import cpu_count\nfrom conan.internal.util.files import clean_dirty, is_dirty, mkdir, rmdir, save, set_dirty, chdir\n\n\ndef build_id(conan_file):\n    if hasattr(conan_file, \"build_id\"):\n        # construct new ConanInfo\n        build_id_info = conan_file.info.clone()\n        conan_file.info_build = build_id_info\n        # effectively call the user function to change the package values\n        with conanfile_exception_formatter(conan_file, \"build_id\"):\n            conan_file.build_id()\n        # compute modified ID\n        return build_id_info.package_id()\n    return None\n\n\nclass _PackageBuilder:\n\n    def __init__(self, cache, remote_manager, cache_folder, hook_manager):\n        self._cache = cache\n        self._hook_manager = hook_manager\n        self._remote_manager = remote_manager\n        self._home_folder = cache_folder\n\n    def _get_build_folder(self, conanfile, package_layout):\n        # Build folder can use a different package_ID if build_id() is defined.\n        # This function decides if the build folder should be re-used (not build again)\n        # and returns the build folder\n        skip_build = False\n        build_folder = package_layout.build()\n        recipe_build_id = build_id(conanfile)\n        pref = package_layout.reference\n        if recipe_build_id is not None and pref.package_id != recipe_build_id:\n            conanfile.output.info(f\"build_id() computed {recipe_build_id}\")\n            # check if we already have a package with the calculated build_id\n            recipe_ref = pref.ref\n            build_prev = self._cache.get_matching_build_id(recipe_ref, recipe_build_id)\n            if build_prev is None:  # Only store build_id of the first one actually building it\n                package_layout.build_id = recipe_build_id\n            build_prev = build_prev or pref\n\n            # We are trying to build a package id different from the one that has the\n            # build_folder but belongs to the same recipe revision, so reuse the build_folder\n            # from the one that is already build\n            if build_prev.package_id != pref.package_id:\n                other_pkg_layout = self._cache.pkg_layout(build_prev)\n                build_folder = other_pkg_layout.build()\n                skip_build = True\n\n        if is_dirty(build_folder):\n            conanfile.output.warning(\"Build folder is dirty, removing it: %s\" % build_folder)\n            rmdir(build_folder)\n            clean_dirty(build_folder)\n            skip_build = False\n\n        if skip_build and os.path.exists(build_folder):\n            conanfile.output.info(\"Won't be built, using previous build folder as defined \"\n                                  f\"in build_id(): {build_folder}\")\n\n        return build_folder, skip_build\n\n    @staticmethod\n    def _copy_sources(conanfile, source_folder, build_folder):\n        # Copies the sources to the build-folder, unless no_copy_source is defined\n        rmdir(build_folder)\n        if not getattr(conanfile, 'no_copy_source', False):\n            conanfile.output.info('Copying sources to build folder')\n            try:\n                shutil.copytree(source_folder, build_folder, symlinks=True)\n            except Exception as e:\n                raise ConanException(f\"{e}\\nError copying sources to build folder\")\n\n    def _build(self, conanfile, pref):\n        write_generators(conanfile, self._hook_manager, self._home_folder)\n\n        try:\n            run_build_method(conanfile, self._hook_manager)\n            conanfile.output.success(\"Package '%s' built\" % pref.package_id)\n            conanfile.output.info(\"Build folder %s\" % conanfile.build_folder)\n        except Exception as exc:\n            conanfile.output.error(f\"\\nPackage '{pref.package_id}' build failed\",\n                                   error_type=\"exception\")\n            conanfile.output.warning(\"Build folder %s\" % conanfile.build_folder)\n            if isinstance(exc, ConanException):\n                raise exc\n            raise ConanException(exc)\n\n    def _package(self, conanfile, pref):\n        # Creating ***info.txt files\n        save(os.path.join(conanfile.folders.base_build, CONANINFO), conanfile.info.dumps())\n\n        package_id = pref.package_id\n        # Do the actual copy, call the conanfile.package() method\n        # While installing, the infos goes to build folder\n        prev = run_package_method(conanfile, package_id, self._hook_manager, pref.ref)\n\n        # FIXME: Conan 2.0 Clear the registry entry (package ref)\n        return prev\n\n    def build_package(self, node, recipe_layout, package_layout):\n        conanfile = node.conanfile\n        pref = node.pref\n\n        base_source = recipe_layout.source()\n        base_package = package_layout.package()\n\n        base_build, skip_build = self._get_build_folder(conanfile, package_layout)\n\n        # PREPARE SOURCES\n        if not skip_build:\n            # TODO: cache2.0 check locks\n            # with package_layout.conanfile_write_lock(self._output):\n            set_dirty(base_build)\n            self._copy_sources(conanfile, base_source, base_build)\n            mkdir(base_build)\n\n        # BUILD & PACKAGE\n        # TODO: cache2.0 check locks\n        # with package_layout.conanfile_read_lock(self._output):\n        with chdir(base_build):\n            try:\n                src = base_source if getattr(conanfile, 'no_copy_source', False) else base_build\n                conanfile.folders.set_base_source(src)\n                conanfile.folders.set_base_build(base_build)\n                conanfile.folders.set_base_package(base_package)\n                # In local cache, generators folder always in build_folder\n                conanfile.folders.set_base_generators(base_build)\n                conanfile.folders.set_base_pkg_metadata(package_layout.metadata())\n\n                if not skip_build:\n                    conanfile.output.info('Building your package in %s' % base_build)\n                    # In local cache, install folder always is build_folder\n                    self._build(conanfile, pref)\n                    clean_dirty(base_build)\n\n                prev = self._package(conanfile, pref)\n                assert prev\n                node.prev = prev\n            except ConanException as exc:  # TODO: Remove this? unnecessary?\n                raise exc\n\n        return node.pref\n\n\nclass BinaryInstaller:\n    \"\"\" main responsible of retrieving binary packages or building them from source\n    locally in case they are not found in remotes\n    \"\"\"\n\n    def __init__(self, api, global_conf, editable_packages, hook_manager):\n        helpers = api._api_helpers  # noqa\n        self._editable_packages = editable_packages\n        self._cache = helpers.cache\n        self._remote_manager = helpers.remote_manager\n        self._hook_manager = hook_manager\n        self._global_conf = global_conf\n        self._home_folder = api.home_folder\n\n    def _install_source(self, node, remotes, need_conf=False):\n        conanfile = node.conanfile\n        download_source = conanfile.conf.get(\"tools.build:download_source\", check_type=bool)\n\n        if not download_source and (need_conf or node.binary != BINARY_BUILD):\n            return\n\n        conanfile = node.conanfile\n        if node.binary in (BINARY_EDITABLE, BINARY_EDITABLE_BUILD):\n            return\n\n        recipe_layout = self._cache.recipe_layout(node.ref)\n        export_source_folder = recipe_layout.export_sources()\n        source_folder = recipe_layout.source()\n\n        retrieve_exports_sources(self._remote_manager, recipe_layout, conanfile, node.ref, remotes)\n\n        conanfile.folders.set_base_source(source_folder)\n        conanfile.folders.set_base_export_sources(source_folder)\n        conanfile.folders.set_base_recipe_metadata(recipe_layout.metadata())\n        config_source(export_source_folder, conanfile, self._hook_manager)\n        return recipe_layout\n\n    @staticmethod\n    def install_system_requires(graph, only_info=False, install_order=None):\n        if install_order is None:\n            install_graph = InstallGraph(graph)\n            install_order = install_graph.install_order()\n\n        for level in install_order:\n            for install_reference in level:\n                for package in install_reference.packages.values():\n                    if not only_info and package.binary == BINARY_SKIP:\n                        continue\n                    conanfile = package.nodes[0].conanfile\n                    # TODO: Refactor magic strings and use _SystemPackageManagerTool.mode_xxx ones\n                    mode = conanfile.conf.get(\"tools.system.package_manager:mode\")\n                    if only_info and mode is None:\n                        continue\n                    if hasattr(conanfile, \"system_requirements\"):\n                        with conanfile_exception_formatter(conanfile, \"system_requirements\"):\n                            conanfile.system_requirements()\n                    for n in package.nodes:\n                        n.conanfile.system_requires = conanfile.system_requires\n\n        conanfile = graph.root.conanfile\n        mode = conanfile.conf.get(\"tools.system.package_manager:mode\")\n        if only_info and mode is None:\n            return\n        if hasattr(conanfile, \"system_requirements\"):\n            with conanfile_exception_formatter(conanfile, \"system_requirements\"):\n                conanfile.system_requirements()\n\n    def install_sources(self, graph, remotes):\n        install_graph = InstallGraph(graph)\n        install_order = install_graph.install_order()\n\n        for level in install_order:\n            for install_reference in level:\n                for package in install_reference.packages.values():\n                    self._install_source(package.nodes[0], remotes, need_conf=True)\n\n    def install(self, deps_graph, remotes, install_order=None):\n        assert not deps_graph.error, \"This graph cannot be installed: {}\".format(deps_graph)\n        if install_order is None:\n            install_graph = InstallGraph(deps_graph)\n            install_graph.raise_errors()\n            install_order = install_graph.install_order()\n\n        ConanOutput().title(\"Installing packages\")\n\n        package_count = sum([sum(len(install_reference.packages.values())\n                                 for level in install_order\n                                 for install_reference in level)])\n        handled_count = 1\n\n        self._download_bulk(install_order)\n        for level in install_order:\n            for install_reference in level:\n                for package in install_reference.packages.values():\n                    recipe_layout = self._install_source(package.nodes[0], remotes)\n                    self._handle_package(recipe_layout, package, install_reference, handled_count,\n                                         package_count)\n                    handled_count += 1\n\n        MockInfoProperty.message()\n\n    def _download_bulk(self, install_order):\n        \"\"\" executes the download of packages (both download and update), only once for a given\n        PREF\n        \"\"\"\n        downloads = []\n        for level in install_order:\n            for node in level:\n                for package in node.packages.values():\n                    if package.binary in (BINARY_UPDATE, BINARY_DOWNLOAD):\n                        downloads.append(package)\n        if not downloads:\n            return\n\n        download_count = len(downloads)\n        plural = 's' if download_count != 1 else ''\n        ConanOutput().subtitle(f\"Downloading {download_count} package{plural}\")\n        parallel = self._global_conf.get(\"core.download:parallel\", check_type=int,\n                                         default=cpu_count())\n        if parallel:  # User can define core.download:parallel=0 to deactivate parallelism\n            ConanOutput().info(\"Downloading binary packages in %s parallel threads\" % parallel)\n            thread_pool = ThreadPool(parallel)\n            thread_pool.map(self._download_pkg, downloads)\n            thread_pool.close()\n            thread_pool.join()\n        else:\n            for node in downloads:\n                self._download_pkg(node)\n\n    def _download_pkg(self, package):\n        node = package.nodes[0]\n        assert node.pref.revision is not None\n        assert node.pref.timestamp is not None\n        self._remote_manager.get_package(node.pref, node.binary_remote)\n\n    def _handle_package(self, recipe_layout, package, install_reference, handled_count, total_count):\n        if package.binary in (BINARY_EDITABLE, BINARY_EDITABLE_BUILD):\n            self._handle_node_editable(package)\n            return\n\n        assert package.binary in (BINARY_CACHE, BINARY_BUILD, BINARY_DOWNLOAD, BINARY_UPDATE)\n        assert install_reference.ref.revision is not None, \"Installer should receive RREV always\"\n\n        pref = PkgReference(install_reference.ref, package.package_id, package.prev)\n\n        if package.binary == BINARY_BUILD:\n            assert pref.revision is None\n            ConanOutput()\\\n                .subtitle(f\"Installing package {pref.ref} ({handled_count} of {total_count})\")\n            ConanOutput(scope=str(pref.ref))\\\n                .highlight(\"Building from source\")\\\n                .info(f\"Package {pref}\")\n            compact_dumps = package.nodes[0].conanfile.info.summarize_compact()\n            for line in compact_dumps:\n                ConanOutput(scope=str(pref.ref)).info(line, fg=Color.BRIGHT_GREEN)\n            package_layout = self._cache.create_build_pkg_layout(pref)\n            self._handle_node_build(package, recipe_layout, package_layout)\n            # Just in case it was recomputed\n            package.package_id = package.nodes[0].pref.package_id  # Just in case it was recomputed\n            package.prev = package.nodes[0].pref.revision\n            package.binary = package.nodes[0].binary\n            pref = PkgReference(install_reference.ref, package.package_id, package.prev)\n        else:\n            assert pref.revision is not None\n            package_layout = self._cache.pkg_layout(pref)\n            if package.binary == BINARY_CACHE:\n                node = package.nodes[0]\n                pref = node.pref\n                assert node.prev, \"PREV for %s is None\" % str(pref)\n                msg = f'Already installed! ({handled_count} of {total_count})'\n                node.conanfile.output.success(msg)\n                os.utime(package_layout.base_folder, None)\n\n        # Make sure that all nodes with same pref compute package_info()\n        pkg_folder = package_layout.package()\n        pkg_metadata = package_layout.metadata()\n        assert os.path.isdir(pkg_folder), \"Pkg '%s' folder must exist: %s\" % (str(pref), pkg_folder)\n        for n in package.nodes:\n            n.prev = pref.revision  # Make sure the prev is assigned\n            conanfile = n.conanfile\n            # Call the info method\n            conanfile.folders.set_base_package(pkg_folder)\n            conanfile.folders.set_base_pkg_metadata(pkg_metadata)\n            self._call_finalize_method(conanfile, package_layout.finalize())\n            # Use package_folder which has been updated previously by install_method if necessary\n            self._call_package_info(conanfile, conanfile.package_folder, is_editable=False)\n\n    def _handle_node_editable(self, install_node):\n        # It will only run generation\n        node = install_node.nodes[0]\n        conanfile = node.conanfile\n        ref = node.ref\n        editable = self._editable_packages.get(ref)\n        conanfile_path = editable[\"path\"]\n        output_folder = editable.get(\"output_folder\")\n\n        base_path = os.path.dirname(conanfile_path)\n\n        conanfile.folders.set_base_folders(base_path, output_folder)\n\n        if node.binary == BINARY_EDITABLE_BUILD:\n            output = conanfile.output\n            output.info(\"Rewriting files of editable package \"\n                        \"'{}' at '{}'\".format(conanfile.name, conanfile.generators_folder))\n            write_generators(conanfile, self._hook_manager, self._home_folder)\n            run_build_method(conanfile, self._hook_manager)\n\n        rooted_base_path = base_path if conanfile.folders.root is None else \\\n            os.path.normpath(os.path.join(base_path, conanfile.folders.root))\n\n        for node in install_node.nodes:\n            # Get source of information\n            conanfile = node.conanfile\n            # New editables mechanism based on Folders\n            conanfile.folders.set_base_package(output_folder or rooted_base_path)\n            conanfile.folders.set_base_folders(base_path, output_folder)\n            conanfile.folders.set_base_pkg_metadata(os.path.join(conanfile.build_folder, \"metadata\"))\n            # Need a temporary package revision for package_revision_mode\n            # Cannot be PREV_UNKNOWN otherwise the consumers can't compute their packageID\n            node.prev = \"editable\"\n            # TODO: Check this base_path usage for editable when not defined\n            self._call_package_info(conanfile, package_folder=rooted_base_path, is_editable=True)\n\n    def _handle_node_build(self, package, recipe_layout, pkg_layout):\n        node = package.nodes[0]\n        pref = node.pref\n        assert pref.package_id, \"Package-ID without value\"\n        assert pkg_layout, \"The pkg_layout should be declared here\"\n        assert node.binary == BINARY_BUILD\n        assert node.prev is None, \"PREV for %s to be built should be None\" % str(pref)\n\n        with pkg_layout.package_lock():\n            pkg_layout.package_remove()\n            with pkg_layout.set_dirty_context_manager():\n                builder = _PackageBuilder(self._cache, self._remote_manager, self._home_folder,\n                                          self._hook_manager)\n                pref = builder.build_package(node, recipe_layout, pkg_layout)\n            assert node.prev, \"Node PREV shouldn't be empty\"\n            assert node.pref.revision, \"Node PREF revision shouldn't be empty\"\n            assert pref.revision is not None, \"PREV for %s to be built is None\" % str(pref)\n            # at this point the package reference should be complete\n            pkg_layout.reference = pref\n            self._cache.assign_prev(pkg_layout)\n            # Make sure the current conanfile.folders is updated (it is later in package_info(),\n            # but better make sure here, and be able to report the actual folder in case\n            # something fails)\n            node.conanfile.folders.set_base_package(pkg_layout.package())\n            node.conanfile.output.success(\"Package folder %s\" % node.conanfile.package_folder)\n\n    def _call_package_info(self, conanfile, package_folder, is_editable):\n\n        with chdir(package_folder):\n            with conanfile_exception_formatter(conanfile, \"package_info\"):\n                self._hook_manager.execute(\"pre_package_info\", conanfile=conanfile)\n\n                if hasattr(conanfile, \"package_info\"):\n                    with conanfile_remove_attr(conanfile, ['info', \"source_folder\", \"build_folder\"],\n                                               \"package_info\"):\n                        MockInfoProperty.package = str(conanfile)\n                        conanfile.package_info()\n\n                # TODO: Check this package_folder usage for editable when not defined\n                conanfile.cpp.package.set_relative_base_folder(package_folder)\n\n                if is_editable:\n                    # Adjust the folders of the layout to consolidate the rootfolder of the\n                    # cppinfos inside\n\n                    # convert directory entries to be relative to the declared folders.build\n                    build_cppinfo = conanfile.cpp.build\n                    build_cppinfo.set_relative_base_folder(conanfile.build_folder)\n                    conanfile.layouts.build.set_relative_base_folder(conanfile.build_folder)\n\n                    # convert directory entries to be relative to the declared folders.source\n                    source_cppinfo = conanfile.cpp.source\n                    source_cppinfo.set_relative_base_folder(conanfile.source_folder)\n                    conanfile.layouts.source.set_relative_base_folder(conanfile.source_folder)\n\n                    full_editable_cppinfo = CppInfo()\n                    full_editable_cppinfo.merge(source_cppinfo)\n                    full_editable_cppinfo.merge(build_cppinfo)\n                    # In editables if we defined anything in the cpp infos we want to discard\n                    # the one defined in the conanfile cpp_info\n                    conanfile.cpp_info.merge(full_editable_cppinfo, overwrite=True)\n\n                    # Paste the editable cpp_info but prioritizing it, only if a\n                    # variable is not declared at build/source, the package will keep the value\n                    full_buildenv_info = conanfile.layouts.source.buildenv_info.copy()\n                    full_buildenv_info.compose_env(conanfile.layouts.build.buildenv_info)\n                    full_buildenv_info.compose_env(conanfile.buildenv_info)\n                    conanfile.buildenv_info = full_buildenv_info\n\n                    full_runenv_info = conanfile.layouts.source.runenv_info.copy()\n                    full_runenv_info.compose_env(conanfile.layouts.build.runenv_info)\n                    full_runenv_info.compose_env(conanfile.runenv_info)\n                    conanfile.runenv_info = full_runenv_info\n\n                    full_conf_info = conanfile.layouts.source.conf_info.copy()\n                    full_conf_info.compose_conf(conanfile.layouts.build.conf_info)\n                    full_conf_info.compose_conf(conanfile.conf_info)\n                    conanfile.conf_info = full_conf_info\n                else:\n                    conanfile.layouts.package.set_relative_base_folder(conanfile.package_folder)\n                    conanfile.buildenv_info.compose_env(conanfile.layouts.package.buildenv_info)\n                    conanfile.runenv_info.compose_env(conanfile.layouts.package.runenv_info)\n                    conanfile.conf_info.compose_conf(conanfile.layouts.package.conf_info)\n\n                self._hook_manager.execute(\"post_package_info\", conanfile=conanfile)\n\n        conanfile.cpp_info.check_component_requires(conanfile)\n        try:\n            conanfile.conf_info.validate()\n        except ConanException as e:\n            raise ConanException(f\"{conanfile}: Error in package_info() method:\\n\\t{str(e)}\")\n\n    @staticmethod\n    def _call_finalize_method(conanfile, finalize_folder):\n        if hasattr(conanfile, \"finalize\"):\n            conanfile.folders.set_finalize_folder(finalize_folder)\n            if not os.path.exists(finalize_folder):\n                mkdir(finalize_folder)\n                conanfile.output.highlight(\"Calling finalize()\")\n                with conanfile_exception_formatter(conanfile, \"finalize\"):\n                    with conanfile_remove_attr(conanfile, ['cpp_info', 'settings', 'options'],\n                                               'finalize'):\n                        conanfile.finalize()\n\n            conanfile.output.success(f\"Finalized folder {finalize_folder}\")\n"
  },
  {
    "path": "conan/internal/graph/profile_node_definer.py",
    "content": "from conan.internal.graph.graph import CONTEXT_BUILD\nfrom conan.errors import ConanException\nfrom conan.internal.model.recipe_ref import ref_matches\n\n\ndef initialize_conanfile_profile(conanfile, profile_build, profile_host, base_context,\n                                 is_build_require, ref=None, parent=None):\n    \"\"\" this function fills conanfile information with the profile informaiton\n    It is called for:\n        - computing the root_node\n           - GraphManager.load_consumer_conanfile, for \"conan source\" command\n           - GraphManager._load_root_consumer for \"conan install <path to conanfile>\n           - GraphManager._load_root_test_package for \"conan create .\" with test_package folder\n        - computing each graph node:\n            GraphBuilder->create_new_node\n    \"\"\"\n    # NOTE: Need the context, as conanfile.context NOT defined yet\n\n    # settings_build=profile_build ALWAYS\n    # host -(r)-> host => settings_host=profile_host, settings_target=None\n    # host -(br)-> build => settings_host=profile_build, settings_target=profile_host\n    # build(gcc) -(r)-> build(openssl/zlib) => settings_host=profile_build, settings_target=None\n    # build(gcc) -(br)-> build(gcc) => settings_host=profile_build, settings_target=profile_build\n    # profile host\n    settings_host = _per_package_settings(conanfile, profile_host, ref)\n    settings_build = _per_package_settings(conanfile, profile_build, ref)\n    if is_build_require or base_context == CONTEXT_BUILD:\n        _initialize_conanfile(conanfile, profile_build, settings_build.copy(), ref)\n        conanfile.buildenv_build = None\n        conanfile.conf_build = None\n    else:\n        _initialize_conanfile(conanfile, profile_host, settings_host, ref)\n        # Host profile with some build profile information\n        is_consumer = conanfile._conan_is_consumer  # noqa\n        conanfile.buildenv_build = profile_build.buildenv.get_profile_env(ref, is_consumer)\n        conanfile.conf_build = profile_build.conf.get_conanfile_conf(ref, is_consumer)\n    conanfile.settings_build = settings_build\n    conanfile.settings_target = None\n\n    if is_build_require:\n        if base_context == CONTEXT_BUILD:\n            conanfile.settings_target = settings_build.copy()\n        else:\n            conanfile.settings_target = settings_host.copy()\n    else:\n        if base_context == CONTEXT_BUILD:\n            # if parent is first level tool-requires, required by HOST context\n            if parent is None or parent.settings_target is None:\n                conanfile.settings_target = settings_host.copy()\n            else:\n                conanfile.settings_target = parent.settings_target.copy()\n\n\ndef _per_package_settings(conanfile, profile, ref):\n    # Prepare the settings for the loaded conanfile\n    # Mixing the global settings with the specified for that name if exist\n    tmp_settings = profile.processed_settings.copy()\n    package_settings_values = profile.package_settings_values\n\n    if package_settings_values:\n        pkg_settings = []\n\n        for pattern, settings in package_settings_values.items():\n            if ref_matches(ref, pattern, conanfile._conan_is_consumer):  # noqa\n                pkg_settings.extend(settings)\n\n        if pkg_settings:\n            tmp_settings.update_values(pkg_settings)\n            # if the global settings are composed with per-package settings, need to preprocess\n\n    return tmp_settings\n\n\ndef _initialize_conanfile(conanfile, profile, settings, ref):\n    try:\n        settings.constrained(conanfile.settings)\n    except Exception as e:\n        raise ConanException(\"The recipe %s is constraining settings. %s\" % (\n            conanfile.display_name, str(e)))\n    conanfile.settings = settings\n    conanfile.settings._frozen = True\n    conanfile._conan_buildenv = profile.buildenv\n    conanfile._conan_runenv = profile.runenv\n    # Maybe this can be done lazy too\n    conanfile.conf = profile.conf.get_conanfile_conf(ref, conanfile._conan_is_consumer)  # noqa\n\n\ndef consumer_definer(conanfile, profile_host, profile_build):\n    \"\"\" conanfile.txt does not declare settings, but it assumes it uses all the profile settings\n    These settings are very necessary for helpers like generators to produce the right output\n    \"\"\"\n    tmp_settings = profile_host.processed_settings.copy()\n    package_settings_values = profile_host.package_settings_values\n\n    for pattern, settings in package_settings_values.items():\n        if ref_matches(ref=None, pattern=pattern, is_consumer=True):\n            tmp_settings.update_values(settings)\n\n    tmp_settings_build = profile_build.processed_settings.copy()\n    package_settings_values_build = profile_build.package_settings_values\n\n    for pattern, settings in package_settings_values_build.items():\n        if ref_matches(ref=None, pattern=pattern, is_consumer=True):\n            tmp_settings_build.update_values(settings)\n\n    conanfile.settings = tmp_settings\n    conanfile.settings_build = tmp_settings_build\n    conanfile.settings_target = None\n    conanfile.settings._frozen = True\n    conanfile._conan_buildenv = profile_host.buildenv\n    conanfile._conan_runenv = profile_host.runenv\n    conanfile.conf = profile_host.conf.get_conanfile_conf(None, is_consumer=True)\n    conanfile.conf_build = profile_build.conf.get_conanfile_conf(None, is_consumer=True)\n"
  },
  {
    "path": "conan/internal/graph/provides.py",
    "content": "from conan.internal.graph.graph_error import GraphProvidesError\nfrom conan.api.model import RecipeReference\n\n\ndef check_graph_provides(dep_graph):\n    if dep_graph.error:\n        return\n    for node in dep_graph.nodes:\n        provides = {}\n        current_provides = node.conanfile.provides\n        if isinstance(current_provides, str):  # Just in case it is defined in configure() as str\n            current_provides = [current_provides]\n        for dep in node.transitive_deps.values():\n            dep_node = dep.node\n            if node.ref is not None and dep_node.ref.name == node.ref.name:\n                continue  # avoid dependency to self (as tool-requires for cross-build)\n\n            dep_provides = dep_node.conanfile.provides\n            if dep_provides is None:\n                continue\n            if isinstance(dep_provides, str):\n                dep_provides = [dep_provides]\n            for provide in dep_provides:\n                # First check if collides with current node\n                if current_provides is not None and provide in current_provides:\n                    raise GraphProvidesError(node, dep_node)\n\n                # Then, check if collides with other requirements\n                new_req = dep.require.copy_requirement()\n                new_req.ref = RecipeReference(provide, new_req.ref.version, new_req.ref.user,\n                                              new_req.ref.channel)\n                existing = node.transitive_deps.get(new_req)\n                if existing is not None:\n                    raise GraphProvidesError(existing.node, dep_node)\n                else:\n                    existing_provide = provides.get(new_req)\n                    if existing_provide is not None:\n                        raise GraphProvidesError(existing_provide, dep_node)\n                    else:\n                        provides[new_req] = dep_node\n"
  },
  {
    "path": "conan/internal/graph/proxy.py",
    "content": "from conan.api.output import ConanOutput\nfrom conan.internal.cache.conan_reference_layout import BasicLayout\nfrom conan.internal.graph.graph import (RECIPE_DOWNLOADED, RECIPE_INCACHE, RECIPE_NEWER,\n                                        RECIPE_NOT_IN_REMOTE, RECIPE_UPDATED, RECIPE_EDITABLE,\n                                        RECIPE_INCACHE_DATE_UPDATED, RECIPE_UPDATEABLE)\nfrom conan.internal.errors import NotFoundException, ConanReferenceAlreadyExistsInDB\nfrom conan.errors import ConanException\n\n\nclass ConanProxy:\n    def __init__(self, cache, remote_manager, editable_packages, legacy_update=None):\n        # collaborators\n        self._editable_packages = editable_packages\n        self._cache = cache\n        self._remote_manager = remote_manager\n        self._resolved = {}  # Cache of the requested recipes to optimize calls\n        self._legacy_update = legacy_update\n\n    def get_recipe(self, ref, remotes, update, check_update):\n        \"\"\"\n        :return: Tuple (layout, status, remote)\n        \"\"\"\n        # TODO: cache2.0 Check with new locks\n        # with layout.conanfile_write_lock(self._out):\n        resolved = self._resolved.get(ref)\n        if resolved is None:\n            resolved = self._get_recipe(ref, remotes, update, check_update)\n            self._resolved[ref] = resolved\n        return resolved\n\n    # return the remote where the recipe was found or None if the recipe was not found\n    def _get_recipe(self, reference, remotes, update, check_update):\n        output = ConanOutput(scope=str(reference))\n\n        conanfile_path = self._editable_packages.get_path(reference)\n        if conanfile_path is not None:\n            return BasicLayout(reference, conanfile_path), RECIPE_EDITABLE, None\n\n        # check if it there's any revision of this recipe in the local cache\n        try:\n            # Just do 1 call to the DB, not 2\n            if reference.revision is None:\n                recipe_layout = self._cache.recipe_layout_latest(reference)\n            else:\n                recipe_layout = self._cache.recipe_layout(reference)\n            ref = recipe_layout.reference  # latest revision if it was not defined\n        except ConanException:\n            # NOT in disk, must be retrieved from remotes\n            # we will only check all servers for latest revision if we did a --update\n            layout, remote = self._download_recipe(reference, remotes, output, update, check_update)\n            status = RECIPE_DOWNLOADED\n            return layout, status, remote\n\n        # TODO: cache2.0: check with new --update flows\n        # TODO: If the revision is given, then we don't need to check for updates?\n        if not (check_update or should_update_reference(reference, update)):\n            status = RECIPE_INCACHE\n            return recipe_layout, status, None\n\n        # Need to check updates\n        remote, remote_ref = self._find_newest_recipe_in_remotes(reference, remotes,\n                                                                 update, check_update)\n        if remote_ref is None:  # Nothing found in remotes\n            status = RECIPE_NOT_IN_REMOTE\n            return recipe_layout, status, None\n\n        # Something found in remotes, check if we already have the latest in local cache\n        assert ref.timestamp\n        cache_time = ref.timestamp\n        if remote_ref.revision != ref.revision:\n            if cache_time < remote_ref.timestamp:\n                # the remote one is newer\n                if should_update_reference(remote_ref, update):\n                    output.info(f\"Updating to latest from remote '{remote.name}'...\")\n                    try:\n                        new_recipe_layout = self._download(remote_ref, remote)\n                    except ConanReferenceAlreadyExistsInDB:\n                        # When updating to a newer revision in the server, but it already exists\n                        # in the cache with an older timestamp\n                        output.info(f\"Latest from '{remote.name}' was found in \"\n                                    \"the cache, using it and updating its timestamp\")\n                        new_recipe_layout = self._cache.recipe_layout(remote_ref)\n                        self._cache.update_recipe_timestamp(remote_ref)  # make it latest\n                    status = RECIPE_UPDATED\n                    return new_recipe_layout, status, remote\n                else:\n                    status = RECIPE_UPDATEABLE\n            else:\n                status = RECIPE_NEWER\n                # If your recipe in cache is newer it does not make sense to return a remote?\n                remote = None\n        else:\n            # TODO: cache2.0 we are returning RECIPE_UPDATED just because we are updating\n            #  the date\n            if cache_time >= remote_ref.timestamp:\n                status = RECIPE_INCACHE\n            else:\n                self._cache.update_recipe_timestamp(remote_ref)\n                status = RECIPE_INCACHE_DATE_UPDATED\n        return recipe_layout, status, remote\n\n    def _find_newest_recipe_in_remotes(self, reference, remotes, update, check_update):\n        output = ConanOutput(scope=str(reference))\n\n        results = []\n        need_update = should_update_reference(reference, update) or check_update\n        for remote in remotes:\n            if remote.allowed_packages and not any(reference.matches(f, is_consumer=False)\n                                                   for f in remote.allowed_packages):\n                output.debug(f\"Excluding remote {remote.name} because recipe is filtered out\")\n                continue\n            output.info(f\"Checking remote: {remote.name}\")\n            try:\n                if self._legacy_update and need_update and reference.revision is None:\n                    if not getattr(ConanProxy, \"update_policy_legacy_warning\", None):\n                        ConanProxy.update_policy_legacy_warning = True\n                        ConanOutput().warning(\"The 'core:update_policy' conf is deprecated and will \"\n                                              \"be removed in future versions\", warn_tag=\"deprecated\")\n                    refs = self._remote_manager.get_recipe_revisions(reference, remote)\n                    results.extend([{'remote': remote, 'ref': ref} for ref in refs])\n                    continue\n                if not reference.revision:\n                    ref = self._remote_manager.get_latest_recipe_revision(reference, remote)\n                else:\n                    ref = self._remote_manager.get_recipe_revision(reference, remote)\n                if not need_update:\n                    return remote, ref\n                results.append({'remote': remote, 'ref': ref})\n            except NotFoundException:\n                pass\n\n        if len(results) == 0:\n            return None, None\n\n        if self._legacy_update and need_update:\n            # Use only the first occurence of each revision in the remotes\n            filtered_results = []\n            revisions = set()\n            for r in results:\n                ref = r[\"ref\"]\n                if ref.revision not in revisions:\n                    revisions.add(ref.revision)\n                    filtered_results.append(r)\n            results = filtered_results\n\n        remotes_results = sorted(results, key=lambda k: k['ref'].timestamp, reverse=True)\n        # get the latest revision from all remotes\n        found_rrev = remotes_results[0]\n        return found_rrev.get(\"remote\"), found_rrev.get(\"ref\")\n\n    def _download_recipe(self, ref, remotes, scoped_output, update, check_update):\n        # When a recipe doesn't existin local cache, it is retrieved from servers\n        scoped_output.info(\"Not found in local cache, looking in remotes...\")\n        if not remotes:\n            raise ConanException(\"No remote defined\")\n\n        remote, latest_rref = self._find_newest_recipe_in_remotes(ref, remotes, update, check_update)\n        if not latest_rref:\n            msg = \"Unable to find '%s' in remotes\" % repr(ref)\n            raise NotFoundException(msg)\n\n        recipe_layout = self._download(latest_rref, remote)\n        return recipe_layout, remote\n\n    def _download(self, ref, remote):\n        assert ref.revision\n        assert ref.timestamp\n        recipe_layout = self._remote_manager.get_recipe(ref, remote)\n        output = ConanOutput(scope=str(ref))\n        output.info(\"Downloaded recipe revision %s\" % ref.revision)\n        return recipe_layout\n\n\ndef should_update_reference(reference, update):\n    if update is None:\n        return False\n    # Old API usages only ever passed a bool\n    if isinstance(update, bool):\n        return update\n    # Legacy syntax had --update without pattern, it manifests as a \"*\" pattern\n    return any(name == \"*\" or reference.name == name for name in update)\n"
  },
  {
    "path": "conan/internal/graph/python_requires.py",
    "content": "import os\n\nfrom conan.errors import ConanException\nfrom conan.api.model import RecipeReference\nfrom conan.internal.model.requires import Requirement\n\n\nclass PyRequire:\n    def __init__(self, module, conanfile, ref, path, recipe_status, remote):\n        self.module = module\n        self.conanfile = conanfile\n        self.ref = ref\n        self.path = path\n        self.recipe = recipe_status\n        self.remote = remote\n\n    def serialize(self):\n        return {\"remote\": self.remote.name if self.remote is not None else None,\n                \"recipe\": self.recipe,\n                \"path\": self.path}\n\n\nclass PyRequires:\n    \"\"\" this is the object that replaces the declared conanfile.py_requires\"\"\"\n    def __init__(self):\n        self._pyrequires = {}  # {pkg-name: PythonRequire}\n\n    def serialize(self):\n        return {r.ref.repr_notime(): r.serialize() for r in self._pyrequires.values()}\n\n    def all_refs(self):\n        return [r.ref for r in self._pyrequires.values()]\n\n    def info_requires(self):\n        return {pyreq.ref: getattr(pyreq.conanfile, \"package_id_python_mode\", None)\n                for pyreq in self._pyrequires.values()}\n\n    def items(self):\n        return self._pyrequires.items()\n\n    def __getitem__(self, item):\n        try:\n            return self._pyrequires[item]\n        except KeyError:\n            raise ConanException(\"'%s' is not a python_require\" % item)\n\n    def add_pyrequire(self, py_require):\n        key = py_require.ref.name\n        # single item assignment, direct\n        existing = self._pyrequires.get(key)\n        if existing and existing is not py_require:  # if is the same one, can be added.\n            # TODO: Better test python_requires conflicts\n            raise ConanException(\"The python_require '%s' already exists\" % key)\n        self._pyrequires[key] = py_require\n\n        transitive = getattr(py_require.conanfile, \"python_requires\", None)\n        if transitive is None:\n            return\n        for name, transitive_py_require in transitive.items():\n            existing = self._pyrequires.get(name)\n            if existing and existing.ref != transitive_py_require.ref:\n                raise ConanException(\"Conflict in py_requires %s - %s\"\n                                     % (existing.ref, transitive_py_require.ref))\n            self._pyrequires[name] = transitive_py_require\n\n\nclass PyRequireLoader:\n    def __init__(self, proxy, range_resolver, global_conf):\n        self._proxy = proxy\n        self._range_resolver = range_resolver\n        self._cached_py_requires = {}\n        self._resolve_prereleases = global_conf.get(\"core.version_ranges:resolve_prereleases\")\n\n    def load_py_requires(self, conanfile, loader, graph_lock, remotes, update, check_update):\n        py_requires_refs = getattr(conanfile, \"python_requires\", None)\n        if py_requires_refs is None:\n            return\n        if isinstance(py_requires_refs, str):\n            py_requires_refs = [py_requires_refs, ]\n\n        py_requires = self._resolve_py_requires(py_requires_refs, graph_lock, loader, remotes,\n                                                update, check_update)\n        if hasattr(conanfile, \"python_requires_extend\"):\n            py_requires_extend = conanfile.python_requires_extend\n            if isinstance(py_requires_extend, str):\n                py_requires_extend = [py_requires_extend, ]\n            for p in py_requires_extend:\n                pkg_name, base_class_name = p.rsplit(\".\", 1)\n                base_class = getattr(py_requires[pkg_name].module, base_class_name)\n                conanfile.__bases__ = (base_class,) + conanfile.__bases__\n        conanfile.python_requires = py_requires\n\n    def _resolve_py_requires(self, py_requires_refs, graph_lock, loader, remotes, update,\n                             check_update):\n        result = PyRequires()\n        for py_requires_ref in py_requires_refs:\n            py_requires_ref = RecipeReference.loads(py_requires_ref)\n            requirement = Requirement(py_requires_ref)\n            resolved_ref = self._resolve_ref(requirement, graph_lock, remotes, update)\n            try:\n                py_require = self._cached_py_requires[resolved_ref]\n            except KeyError:\n                pyreq_conanfile = self._load_pyreq_conanfile(loader, graph_lock, resolved_ref,\n                                                             remotes, update, check_update)\n                conanfile, module, new_ref, path, recipe_status, remote = pyreq_conanfile\n                py_require = PyRequire(module, conanfile, new_ref, path, recipe_status, remote)\n                self._cached_py_requires[resolved_ref] = py_require\n            result.add_pyrequire(py_require)\n        return result\n\n    def _resolve_ref(self, requirement, graph_lock, remotes, update):\n        if requirement.alias:\n            raise ConanException(\"python-requires 'alias' are not supported in Conan 2.0. \"\n                                 \"Please use version ranges instead\")\n        if graph_lock:\n            graph_lock.resolve_locked_pyrequires(requirement, self._resolve_prereleases)\n        # If the lock hasn't resolved the range, and it hasn't failed (it is partial), resolve it\n        self._range_resolver.resolve(requirement, \"python_requires\", remotes, update)\n        ref = requirement.ref\n        return ref\n\n    def _load_pyreq_conanfile(self, loader, graph_lock, ref, remotes, update, check_update):\n        try:\n            recipe = self._proxy.get_recipe(ref, remotes, update, check_update)\n        except ConanException as e:\n            raise ConanException(f\"Cannot resolve python_requires '{ref}': {str(e)}\")\n        layout, recipe_status, remote = recipe\n        path = layout.conanfile()\n        new_ref = layout.reference\n        conanfile, module = loader.load_basic_module(path, graph_lock, remotes=remotes,\n                                                     update=update, check_update=check_update)\n        conanfile.name = new_ref.name\n        conanfile.version = str(new_ref.version)\n        conanfile.user = new_ref.user\n        # TODO: Is this really necessary?\n        conanfile.channel = new_ref.channel\n\n        if getattr(conanfile, \"alias\", None):\n            raise ConanException(\"python-requires 'alias' are not supported in Conan 2.0. \"\n                                 \"Please use version ranges instead\")\n        return conanfile, module, new_ref, os.path.dirname(path), recipe_status, remote\n"
  },
  {
    "path": "conan/internal/graph/range_resolver.py",
    "content": "from conan.api.output import ConanOutput\nfrom conan.internal.graph.proxy import should_update_reference\nfrom conan.errors import ConanException\nfrom conan.api.model import RecipeReference\nfrom conan.internal.model.version_range import VersionRange\n\n\nclass RangeResolver:\n\n    def __init__(self, cache, remote_manager, global_conf, editable_packages):\n        self._cache = cache\n        self._editable_packages = editable_packages\n        self._remote_manager = remote_manager\n        self._cached_cache = {}  # Cache caching of search result, so invariant wrt installations\n        self._cached_remote_found = {}  # dict {ref (pkg/*): {remote_name: results (pkg/1, pkg/2)}}\n        self.resolved_ranges = {}\n        self._resolve_prereleases = global_conf.get('core.version_ranges:resolve_prereleases')\n\n    def resolve(self, require, base_conanref, remotes, update):\n        try:\n            version_range = require.version_range\n        except Exception as e:\n            base = base_conanref or \"conanfile\"\n            raise ConanException(f\"\\n    Recipe '{base}' requires '{require.ref}' \"\n                                 f\"version-range definition error:\\n    {e}\")\n        if version_range is None:\n            return\n        assert isinstance(version_range, VersionRange)\n\n        if require.ref.revision is not None:\n            ConanOutput(base_conanref).warning(\"Specifying a revision for requirement \"\n                                               f\"'{require.ref.repr_notime()}' together with \"\n                                               \"a version range has no effect. \"\n                                               \"The revision will be ignored.\",\n                                               warn_tag=\"risk\")\n\n        # Check if this ref with version range was already solved\n        previous_ref = self.resolved_ranges.get(require.ref)\n        if previous_ref is not None:\n            require.ref = previous_ref\n            return\n\n        ref = require.ref\n        search_ref = RecipeReference(ref.name, \"*\", ref.user, ref.channel)\n\n        resolved_ref = self._resolve_local(search_ref, version_range)\n        if resolved_ref is None or should_update_reference(search_ref, update):\n            remote_resolved_ref = self._resolve_remote(search_ref, version_range, remotes, update)\n            if resolved_ref is None or (remote_resolved_ref is not None and\n                                        resolved_ref.version < remote_resolved_ref.version):\n                resolved_ref = remote_resolved_ref\n\n        if resolved_ref is None:\n            raise ConanException(f\"Version range '{version_range}' from requirement '{require.ref}' \"\n                                 f\"required by '{base_conanref}' could not be resolved\")\n\n        # To fix Cache behavior, we remove the revision information\n        resolved_ref.revision = None  # FIXME: Wasting information already obtained from server?\n        self.resolved_ranges[require.ref] = resolved_ref\n        require.ref = resolved_ref\n\n    def _resolve_local(self, search_ref, version_range):\n        pattern = str(search_ref)\n        local_found = self._cached_cache.get(pattern)\n        if local_found is None:\n            # This local_found is weird, it contains multiple revisions, not just latest\n            local_found = self._cache.search_recipes(pattern)\n            # TODO: This is still necessary to filter user/channel, until search_recipes is fixed\n            local_found = [ref for ref in local_found if ref.user == search_ref.user\n                           and ref.channel == search_ref.channel]\n            local_found.extend(r for r in self._editable_packages.edited_refs\n                               if r.name == search_ref.name and r.user == search_ref.user\n                               and r.channel == search_ref.channel)\n            self._cached_cache[pattern] = local_found\n        if local_found:\n            return self._resolve_version(version_range, local_found, self._resolve_prereleases)\n\n    def _search_remote_recipes(self, remote, search_ref):\n        if remote.allowed_packages and not any(search_ref.matches(f, is_consumer=False)\n                                               for f in remote.allowed_packages):\n            return []\n        pattern = str(search_ref)\n        pattern_cached = self._cached_remote_found.setdefault(pattern, {})\n        results = pattern_cached.get(remote.name)\n        if results is None:\n            results = self._remote_manager.search_recipes(remote, pattern)\n            # TODO: This is still necessary to filter user/channel, until search_recipes is fixed\n            results = [ref for ref in results if ref.user == search_ref.user\n                       and ref.channel == search_ref.channel]\n            pattern_cached.update({remote.name: results})\n        return results\n\n    def _resolve_remote(self, search_ref, version_range, remotes, update):\n        update_candidates = []\n        for remote in remotes:\n            remote_results = self._search_remote_recipes(remote, search_ref)\n            resolved_version = self._resolve_version(version_range, remote_results,\n                                                     self._resolve_prereleases)\n            if resolved_version:\n                if not should_update_reference(search_ref, update):\n                    return resolved_version  # Return first valid occurrence in first remote\n                else:\n                    update_candidates.append(resolved_version)\n        if len(update_candidates) > 0:  # pick latest from already resolved candidates\n            resolved_version = self._resolve_version(version_range, update_candidates,\n                                                     self._resolve_prereleases)\n            return resolved_version\n\n    @staticmethod\n    def _resolve_version(version_range, refs_found, resolve_prereleases):\n        for ref in reversed(sorted(refs_found)):\n            if version_range.contains(ref.version, resolve_prereleases):\n                return ref\n"
  },
  {
    "path": "conan/internal/hook_manager.py",
    "content": "import os\n\nfrom conan.internal.loader import load_python_file\nfrom conan.errors import ConanException, ConanInvalidConfiguration\n\nvalid_hook_methods = [\"pre_export\", \"post_export\",\n                      \"pre_validate\", \"post_validate\",\n                      \"pre_source\", \"post_source\",\n                      \"pre_generate\", \"post_generate\",\n                      \"pre_build\", \"post_build\", \"post_build_fail\",\n                      \"pre_package\", \"post_package\",\n                      \"pre_package_info\", \"post_package_info\",\n                      \"post_package_id\"]  # package_id is called a lot more than others, only post\n\n\nclass HookManager:\n\n    def __init__(self, hooks_folder):\n        self._hooks_folder = hooks_folder\n        self.hooks = {}\n        self.validate_hook = False  # Quick check for performance\n        self.post_package_id_hook = False  # Quick check for performance\n        self._load_hooks()  # A bit dirty, but avoid breaking tests\n\n    def execute(self, method_name, conanfile):\n        assert method_name in valid_hook_methods, \\\n            \"Method '{}' not in valid hooks methods\".format(method_name)\n        hooks = self.hooks.get(method_name)\n        if hooks is None:\n            return\n        for name, method in hooks:\n            # TODO: This display_name is ugly, improve it\n            display_name = conanfile.display_name\n            try:\n                conanfile.display_name = \"%s: [HOOK - %s] %s()\" % (conanfile.display_name, name,\n                                                                   method_name)\n                method(conanfile)\n            except ConanInvalidConfiguration:\n                raise\n            except Exception as e:\n                raise ConanException(\"[HOOK - %s] %s(): %s\" % (name, method_name, str(e)))\n            finally:\n                conanfile.display_name = display_name\n\n    def _load_hooks(self):\n        hooks = {}\n        for root, dirs, files in os.walk(self._hooks_folder):\n            for f in files:\n                if f.startswith(\"hook_\") and f.endswith(\".py\"):\n                    hook_path = os.path.join(root, f)\n                    name = os.path.relpath(hook_path, self._hooks_folder).replace(\"\\\\\", \"/\")\n                    hooks[name] = hook_path\n        # Load in alphabetical order, just in case the order is important there is a criteria\n        # This is difficult to test, apparently in most cases os.walk is alphabetical\n        for name, hook_path in sorted(hooks.items()):\n            self._load_hook(hook_path, name)\n        self.validate_hook = bool(self.hooks.get(\"pre_validate\") or self.hooks.get(\"post_validate\"))\n        self.post_package_id_hook = bool(self.hooks.get(\"post_package_id\"))\n\n    def _load_hook(self, hook_path, hook_name):\n        try:\n            hook, _ = load_python_file(hook_path)\n            for method in valid_hook_methods:\n                hook_method = getattr(hook, method, None)\n                if hook_method:\n                    self.hooks.setdefault(method, []).append((hook_name, hook_method))\n        except Exception as e:\n            raise ConanException(\"Error loading hook '%s': %s\" % (hook_path, str(e)))\n\n    def reinit(self):\n        self.hooks.clear()\n        self._load_hooks()\n"
  },
  {
    "path": "conan/internal/internal_tools.py",
    "content": "from conan.errors import ConanException\n\nuniversal_arch_separator = '|'\n\n\ndef is_universal_arch(settings_value, valid_definitions):\n    if (settings_value is None or valid_definitions is None\n            or universal_arch_separator not in settings_value):\n        return False\n\n    parts = settings_value.split(universal_arch_separator)\n\n    if parts != sorted(parts):\n        raise ConanException(f\"Architectures must be in alphabetical order separated by \"\n                             f\"{universal_arch_separator}\")\n\n    valid_macos_values = [val for val in valid_definitions if (\"arm\" in val or \"x86\" in val)]\n\n    return all(part in valid_macos_values for part in parts)\n\n\ndef raise_on_universal_arch(conanfile):\n    if is_universal_arch(conanfile.settings.get_safe(\"arch\"),\n                         conanfile.settings.possible_values().get(\"arch\")):\n        raise ConanException(\"Universal binaries not supported by toolchain.\")\n"
  },
  {
    "path": "conan/internal/loader.py",
    "content": "import traceback\nfrom importlib import invalidate_caches, util as imp_util\nimport inspect\nimport os\nimport re\nimport sys\nimport types\nimport uuid\nfrom threading import Lock\n\nimport yaml\n\nfrom pathlib import Path\n\nfrom conan.api.output import ConanOutput\nfrom conan.tools.cmake import cmake_layout\nfrom conan.tools.google import bazel_layout\nfrom conan.tools.microsoft import vs_layout\nfrom conan.internal.errors import conanfile_exception_formatter, NotFoundException\nfrom conan.errors import ConanException\nfrom conan.internal.model.conan_file import ConanFile\nfrom conan.internal.model.options import Options\nfrom conan.api.model import RecipeReference\nfrom conan.internal.paths import DATA_YML\nfrom conan.internal.model.version_range import validate_conan_version\nfrom conan.internal.util.config_parser import TextINIParse\nfrom conan.internal.util.files import load, chdir, load_user_encoded\n\n\nclass ConanFileLoader:\n\n    def __init__(self, pyreq_loader=None, conanfile_helpers=None):\n        self._pyreq_loader = pyreq_loader\n        self._cached_conanfile_classes = {}\n        self._conanfile_helpers = conanfile_helpers\n        invalidate_caches()\n\n    def load_basic(self, conanfile_path, graph_lock=None, display=\"\", remotes=None,\n                   update=None, check_update=None):\n        \"\"\" loads a conanfile basic object without evaluating anything\n        \"\"\"\n        return self.load_basic_module(conanfile_path, graph_lock, display, remotes,\n                                      update, check_update)[0]\n\n    def load_basic_module(self, conanfile_path, graph_lock=None, display=\"\", remotes=None,\n                          update=None, check_update=None, tested_python_requires=None):\n        \"\"\" loads a conanfile basic object without evaluating anything, returns the module too\n        \"\"\"\n        cached = self._cached_conanfile_classes.get(conanfile_path)\n        if cached:\n            conanfile = cached[0](display)\n            conanfile._conan_helpers = self._conanfile_helpers\n            if hasattr(conanfile, \"init\") and callable(conanfile.init):\n                with conanfile_exception_formatter(conanfile, \"init\"):\n                    conanfile.init()\n            return conanfile, cached[1]\n\n        try:\n            module, conanfile = _parse_conanfile(conanfile_path)\n            if isinstance(tested_python_requires, RecipeReference):\n                if getattr(conanfile, \"python_requires\", None) == \"tested_reference_str\":\n                    conanfile.python_requires = tested_python_requires.repr_notime()\n            elif tested_python_requires:\n                if getattr(conanfile, \"python_requires\", None) != \"tested_reference_str\":\n                    ConanOutput().warning(\"test_package/conanfile.py should declare 'python_requires\"\n                                          \" = \\\"tested_reference_str\\\"'\", warn_tag=\"deprecated\")\n                conanfile.python_requires = tested_python_requires\n\n            if self._pyreq_loader:\n                self._pyreq_loader.load_py_requires(conanfile, self, graph_lock, remotes,\n                                                    update, check_update)\n\n            conanfile.recipe_folder = os.path.dirname(conanfile_path)\n            conanfile.recipe_path = Path(conanfile.recipe_folder)\n\n            # Load and populate dynamic fields from the data file\n            conan_data = self._load_data(conanfile_path)\n            conanfile.conan_data = conan_data\n\n            self._cached_conanfile_classes[conanfile_path] = (conanfile, module)\n            result = conanfile(display)\n\n            result._conan_helpers = self._conanfile_helpers\n            if hasattr(result, \"init\") and callable(result.init):\n                with conanfile_exception_formatter(result, \"init\"):\n                    result.init()\n            return result, module\n        except ConanException as e:\n            raise ConanException(\"Error loading conanfile at '{}': {}\".format(conanfile_path, e))\n\n    @staticmethod\n    def _load_data(conanfile_path):\n        data_path = os.path.join(os.path.dirname(conanfile_path), DATA_YML)\n        if not os.path.exists(data_path):\n            return None\n\n        try:\n            data = yaml.safe_load(load(data_path))\n        except Exception as e:\n            raise ConanException(\"Invalid yml format at {}: {}\".format(DATA_YML, e))\n\n        return data or {}\n\n    def load_named(self, conanfile_path, name, version, user, channel, graph_lock=None,\n                   remotes=None, update=None, check_update=None, tested_python_requires=None):\n        \"\"\" loads the basic conanfile object and evaluates its name and version\n        \"\"\"\n        conanfile, _ = self.load_basic_module(conanfile_path, graph_lock, remotes=remotes,\n                                              update=update, check_update=check_update,\n                                              tested_python_requires=tested_python_requires)\n\n        # Export does a check on existing name & version\n        if name:\n            if conanfile.name and name != conanfile.name:\n                raise ConanException(\"Package recipe with name %s!=%s\" % (name, conanfile.name))\n            conanfile.name = name\n\n        if version:\n            if conanfile.version and version != conanfile.version:\n                raise ConanException(\"Package recipe with version %s!=%s\"\n                                     % (version, conanfile.version))\n            conanfile.version = version\n\n        if user:\n            if conanfile.user and user != conanfile.user:\n                raise ConanException(\"Package recipe with user %s!=%s\"\n                                     % (user, conanfile.user))\n            conanfile.user = user\n\n        if channel:\n            if conanfile.channel and channel != conanfile.channel:\n                raise ConanException(\"Package recipe with channel %s!=%s\"\n                                     % (channel, conanfile.channel))\n            conanfile.channel = channel\n\n        if conanfile.channel and not conanfile.user:\n            raise ConanException(f\"{conanfile_path}: Can't specify channel '{conanfile.channel}' without user\")\n\n        if hasattr(conanfile, \"set_name\"):\n            with conanfile_exception_formatter(\"conanfile.py\", \"set_name\"):\n                conanfile.set_name()\n        if hasattr(conanfile, \"set_version\"):\n            with conanfile_exception_formatter(\"conanfile.py\", \"set_version\"):\n                conanfile.set_version()\n\n        return conanfile\n\n    def load_export(self, conanfile_path, name, version, user, channel, graph_lock=None,\n                    remotes=None):\n        \"\"\" loads the conanfile and evaluates its name, version, and enforce its existence\n        \"\"\"\n        conanfile = self.load_named(conanfile_path, name, version, user, channel, graph_lock,\n                                    remotes=remotes)\n        if not conanfile.name:\n            raise ConanException(\"conanfile didn't specify name\")\n        if not conanfile.version:\n            raise ConanException(\"conanfile didn't specify version\")\n\n        ref = RecipeReference(conanfile.name, conanfile.version, conanfile.user, conanfile.channel)\n        conanfile.display_name = str(ref)\n        conanfile.output.scope = conanfile.display_name\n        return conanfile\n\n    def load_consumer(self, conanfile_path, name=None, version=None, user=None,\n                      channel=None, graph_lock=None,  remotes=None, update=None, check_update=None,\n                      tested_python_requires=None):\n        \"\"\" loads a conanfile.py in user space. Might have name/version or not\n        \"\"\"\n        conanfile = self.load_named(conanfile_path, name, version, user, channel, graph_lock,\n                                    remotes, update, check_update,\n                                    tested_python_requires=tested_python_requires)\n\n        ref = RecipeReference(conanfile.name, conanfile.version, conanfile.user, conanfile.channel)\n        if str(ref):\n            conanfile.display_name = \"%s (%s)\" % (os.path.basename(conanfile_path), str(ref))\n        else:\n            conanfile.display_name = os.path.basename(conanfile_path)\n        conanfile.output.scope = conanfile.display_name\n        conanfile._conan_is_consumer = True\n        return conanfile\n\n    def load_conanfile(self, conanfile_path, ref, graph_lock=None, remotes=None,\n                       update=None, check_update=None):\n        \"\"\" load a conanfile with a full reference, name, version, user and channel are obtained\n        from the reference, not evaluated. Main way to load from the cache\n        \"\"\"\n        try:\n            conanfile, _ = self.load_basic_module(conanfile_path, graph_lock, str(ref), remotes,\n                                                  update=update, check_update=check_update)\n        except Exception as e:\n            raise ConanException(\"%s: Cannot load recipe.\\n%s\" % (str(ref), str(e)))\n\n        conanfile.name = ref.name\n        conanfile.version = str(ref.version)\n        conanfile.user = ref.user\n        conanfile.channel = ref.channel\n        return conanfile\n\n    def load_conanfile_txt(self, conan_txt_path):\n        if not os.path.exists(conan_txt_path):\n            raise NotFoundException(\"Conanfile not found!\")\n\n        try:\n            contents = load_user_encoded(conan_txt_path)\n        except Exception as e:\n            raise ConanException(f\"Cannot load conanfile.txt:\\n{e}\")\n        path, basename = os.path.split(conan_txt_path)\n        display_name = basename\n        conanfile = self._parse_conan_txt(contents, path, display_name)\n        conanfile._conan_helpers = self._conanfile_helpers\n        conanfile._conan_is_consumer = True\n        return conanfile\n\n    @staticmethod\n    def _parse_conan_txt(contents, path, display_name):\n        conanfile = ConanFile(display_name)\n\n        try:\n            parser = ConanFileTextLoader(contents)\n        except Exception as e:\n            raise ConanException(\"%s:\\n%s\" % (path, str(e)))\n        for reference in parser.requirements:\n            conanfile.requires(reference)\n        for build_reference in parser.tool_requirements:\n            # TODO: Improve this interface\n            conanfile.requires.tool_require(build_reference)\n        for ref in parser.test_requirements:\n            # TODO: Improve this interface\n            conanfile.requires.test_require(ref)\n\n        if parser.layout:\n            layout_method = {\"cmake_layout\": cmake_layout,\n                             \"vs_layout\": vs_layout,\n                             \"bazel_layout\": bazel_layout}.get(parser.layout)\n            if not layout_method:\n                raise ConanException(\"Unknown predefined layout '{}' declared in \"\n                                     \"conanfile.txt\".format(parser.layout))\n\n            def layout(_self):\n                layout_method(_self)\n\n            conanfile.layout = types.MethodType(layout, conanfile)\n\n        conanfile.generators = parser.generators\n        try:\n            conanfile.options = Options.loads(parser.options)\n        except Exception:\n            raise ConanException(\"Error while parsing [options] in conanfile.txt\\n\"\n                                 \"Options should be specified as 'pkg/*:option=value'\")\n        return conanfile\n\n    def load_virtual(self, requires=None, tool_requires=None, python_requires=None, graph_lock=None,\n                     remotes=None, update=None, check_updates=None):\n        # If user don't specify namespace in options, assume that it is\n        # for the reference (keep compatibility)\n        conanfile = ConanFile(display_name=\"cli\")\n        conanfile._conan_helpers = self._conanfile_helpers\n\n        if tool_requires:\n            for reference in tool_requires:\n                conanfile.requires.tool_require(repr(reference))\n        if requires:\n            for reference in requires:\n                conanfile.requires(repr(reference))\n\n        if python_requires:\n            conanfile.python_requires = [pr.repr_notime() for pr in python_requires]\n\n        if self._pyreq_loader:\n            self._pyreq_loader.load_py_requires(conanfile, self, graph_lock, remotes,\n                                                update, check_updates)\n\n        conanfile._conan_is_consumer = True\n        conanfile.generators = []  # remove the default txt generator\n        return conanfile\n\n\ndef _parse_module(conanfile_module, module_id):\n    \"\"\" Parses a python in-memory module, to extract the classes, mainly the main\n    class defining the Recipe, but also process possible existing generators\n    @param conanfile_module: the module to be processed\n    @return: the main ConanFile class from the module\n    \"\"\"\n    result = None\n    for name, attr in conanfile_module.__dict__.items():\n        if (name.startswith(\"_\") or not inspect.isclass(attr) or\n                attr.__dict__.get(\"__module__\") != module_id):\n            continue\n\n        if issubclass(attr, ConanFile) and attr != ConanFile:\n            if result is None:\n                result = attr\n            else:\n                raise ConanException(\"More than 1 conanfile in the file\")\n\n    if result is None:\n        raise ConanException(\"No subclass of ConanFile\")\n\n    return result\n\n\n_load_python_lock = Lock()  # Loading our Python files is not thread-safe (modifies sys)\n\n\ndef _parse_conanfile(conanfile_path):\n    with _load_python_lock:\n        module, module_id = _load_python_file(conanfile_path)\n    try:\n        conanfile = _parse_module(module, module_id)\n        return module, conanfile\n    except Exception as e:  # re-raise with file name\n        raise ConanException(\"%s: %s\" % (conanfile_path, str(e)))\n\n\ndef load_python_file(conan_file_path):\n    \"\"\" From a given path, obtain the in memory python import module\n    \"\"\"\n    with _load_python_lock:\n        module, module_id = _load_python_file(conan_file_path)\n    return module, module_id\n\n\ndef _load_python_file(conan_file_path):\n    \"\"\" From a given path, obtain the in memory python import module\n    \"\"\"\n\n    if not os.path.exists(conan_file_path):\n        raise NotFoundException(\"%s not found!\" % conan_file_path)\n\n    def new_print(*args, **kwargs):  # Make sure that all user python files print() goes to stderr\n        kwargs.setdefault(\"file\", sys.stderr)\n        print(*args, **kwargs)\n\n    module_id = str(uuid.uuid1())\n    current_dir = os.path.dirname(conan_file_path)\n    sys.path.insert(0, current_dir)\n    try:\n        old_modules = list(sys.modules.keys())\n        with chdir(current_dir):\n            old_dont_write_bytecode = sys.dont_write_bytecode\n            try:\n                sys.dont_write_bytecode = True\n                spec = imp_util.spec_from_file_location(module_id, conan_file_path)\n                loaded = imp_util.module_from_spec(spec)\n                spec.loader.exec_module(loaded)\n                sys.dont_write_bytecode = old_dont_write_bytecode\n            except ImportError:\n                version_txt = _get_required_conan_version_without_loading(conan_file_path)\n                if version_txt:\n                    validate_conan_version(version_txt)\n                raise\n\n            required_conan_version = getattr(loaded, \"required_conan_version\", None)\n            if required_conan_version:\n                validate_conan_version(required_conan_version)\n\n        # These lines are necessary, otherwise local conanfile imports with same name\n        # collide, but no error, and overwrite other packages imports!!\n        added_modules = set(sys.modules).difference(old_modules)\n        for added in added_modules:\n            module = sys.modules[added]\n            if module:\n                try:\n                    try:\n                        # Most modules will have __file__ != None\n                        folder = os.path.dirname(module.__file__)\n                    except (AttributeError, TypeError):\n                        # But __file__ might not exist or equal None\n                        # Like some builtins and Namespace packages py3\n                        folder = module.__path__._path[0]\n                except AttributeError:  # In case the module.__path__ doesn't exist\n                    pass\n                else:\n                    if folder.startswith(current_dir):\n                        module = sys.modules.pop(added)\n                        module.print = new_print\n                        sys.modules[\"%s.%s\" % (module_id, added)] = module\n    except ConanException:\n        raise\n    except Exception:\n        trace = traceback.format_exc().split('\\n')\n        raise ConanException(\"Unable to load conanfile in %s\\n%s\" % (conan_file_path,\n                                                                     '\\n'.join(trace[3:])))\n    finally:\n        sys.path.pop(0)\n\n    loaded.print = new_print\n    return loaded, module_id\n\n\ndef _get_required_conan_version_without_loading(conan_file_path):\n    # First, try to detect the required_conan_version in \"text\" mode\n    # https://github.com/conan-io/conan/issues/11239\n    contents = load(conan_file_path)\n\n    txt_version = None\n\n    try:\n        found = re.search(r\"(.*)required_conan_version\\s*=\\s*[\\\"'](.*)[\\\"']\", contents)\n        if found and \"#\" not in found.group(1):\n            txt_version = found.group(2)\n    except:  # noqa this should be solid, cannot fail\n        pass\n\n    return txt_version\n\n\nclass ConanFileTextLoader:\n    \"\"\"Parse a conanfile.txt file\"\"\"\n\n    def __init__(self, input_text):\n        # Prefer composition over inheritance, the __getattr__ was breaking things\n        self._config_parser = TextINIParse(input_text,  [\"requires\", \"generators\", \"options\",\n                                                         \"imports\", \"tool_requires\", \"test_requires\",\n                                                         \"layout\"],\n                                           strip_comments=True)\n\n    @property\n    def layout(self):\n        \"\"\"returns the declared layout\"\"\"\n        tmp = [r.strip() for r in self._config_parser.layout.splitlines()]\n        if len(tmp) > 1:\n            raise ConanException(\"Only one layout can be declared in the [layout] section of \"\n                                 \"the conanfile.txt\")\n        return tmp[0] if tmp else None\n\n    @property\n    def requirements(self):\n        \"\"\"returns a list of requires\n        EX:  \"OpenCV/2.4.10@phil/stable\"\n        \"\"\"\n        return [r.strip() for r in self._config_parser.requires.splitlines()]\n\n    @property\n    def tool_requirements(self):\n        \"\"\"returns a list of tool_requires\n        EX:  \"OpenCV/2.4.10@phil/stable\"\n        \"\"\"\n\n        return [r.strip() for r in self._config_parser.tool_requires.splitlines()]\n\n    @property\n    def test_requirements(self):\n        \"\"\"returns a list of test_requires\n        EX:  \"gtest/2.4.10@phil/stable\"\n        \"\"\"\n\n        return [r.strip() for r in self._config_parser.test_requires.splitlines()]\n\n    @property\n    def options(self):\n        return self._config_parser.options\n\n    @property\n    def generators(self):\n        return self._config_parser.generators.splitlines()\n"
  },
  {
    "path": "conan/internal/methods.py",
    "content": "import os\n\nfrom conan.api.output import ConanOutput\nfrom conan.errors import ConanException\nfrom conan.internal.errors import conanfile_exception_formatter, conanfile_remove_attr\nfrom conan.internal.paths import CONANINFO\nfrom conan.internal.model.manifest import FileTreeManifest\nfrom conan.api.model import PkgReference\nfrom conan.internal.model.pkg_type import PackageType\nfrom conan.internal.model.requires import BuildRequirements, TestRequirements, ToolRequirements\nfrom conan.internal.util.files import mkdir, chdir, save\n\n\ndef run_source_method(conanfile, hook_manager):\n    mkdir(conanfile.source_folder)\n    with chdir(conanfile.source_folder):\n        hook_manager.execute(\"pre_source\", conanfile=conanfile)\n        if hasattr(conanfile, \"source\"):\n            conanfile.output.highlight(\"Calling source() in {}\".format(conanfile.source_folder))\n            with conanfile_exception_formatter(conanfile, \"source\"):\n                with conanfile_remove_attr(conanfile, ['info', 'settings', \"options\"], \"source\"):\n                    conanfile.source()\n        hook_manager.execute(\"post_source\", conanfile=conanfile)\n\n\ndef run_build_method(conanfile, hook_manager):\n    if os.path.isfile(conanfile.build_folder):\n        raise ConanException(f\"{conanfile}: Failed to create build folder, there is already a file \"\n                             f\"named: {conanfile.build_folder}\")\n    mkdir(conanfile.build_folder)\n    mkdir(conanfile.package_metadata_folder)\n    with chdir(conanfile.build_folder):\n        hook_manager.execute(\"pre_build\", conanfile=conanfile)\n        if hasattr(conanfile, \"build\"):\n            conanfile.output.highlight(\"Calling build()\")\n            with conanfile_exception_formatter(conanfile, \"build\"):\n                try:\n                    conanfile.build()\n                except Exception:\n                    hook_manager.execute(\"post_build_fail\", conanfile=conanfile)\n                    raise\n        hook_manager.execute(\"post_build\", conanfile=conanfile)\n\n\ndef run_package_method(conanfile, package_id, hook_manager, ref):\n    \"\"\" calls the recipe \"package()\" method\n    - Assigns folders to conanfile.package_folder, source_folder, install_folder, build_folder\n    - Calls pre-post package hook\n    \"\"\"\n\n    if conanfile.package_folder == conanfile.build_folder:\n        raise ConanException(\"Cannot 'conan package' to the build folder. \"\n                             \"--build-folder and package folder can't be the same\")\n\n    mkdir(conanfile.package_folder)\n    scoped_output = conanfile.output\n    # Make the copy of all the patterns\n    scoped_output.info(\"Generating the package\")\n    scoped_output.info(\"Packaging in folder %s\" % conanfile.package_folder)\n\n    hook_manager.execute(\"pre_package\", conanfile=conanfile)\n    if hasattr(conanfile, \"package\"):\n        scoped_output.highlight(\"Calling package()\")\n        with conanfile_exception_formatter(conanfile, \"package\"):\n            with chdir(conanfile.build_folder):\n                with conanfile_remove_attr(conanfile, ['info'], \"package\"):\n                    conanfile.package()\n    hook_manager.execute(\"post_package\", conanfile=conanfile)\n\n    save(os.path.join(conanfile.package_folder, CONANINFO), conanfile.info.dumps())\n    manifest = FileTreeManifest.create(conanfile.package_folder)\n    manifest.save(conanfile.package_folder)\n    package_output = ConanOutput(scope=\"%s: package()\" % scoped_output.scope)\n    manifest.report_summary(package_output, \"Packaged\")\n\n    prev = manifest.summary_hash\n    scoped_output.info(\"Created package revision %s\" % prev)\n    pref = PkgReference(ref, package_id)\n    pref.revision = prev\n    scoped_output.success(\"Package '%s' created\" % package_id)\n    scoped_output.success(\"Full package reference: {}\".format(pref.repr_notime()))\n    return prev\n\n\ndef run_configure_method(conanfile, down_options, profile_options, ref):\n    \"\"\" Run all the config-related functions for the given conanfile object \"\"\"\n\n    initial_requires_count = len(conanfile.requires)\n\n    if hasattr(conanfile, \"config_options\"):\n        with conanfile_exception_formatter(conanfile, \"config_options\"):\n            conanfile.config_options()\n    elif \"auto_shared_fpic\" in conanfile.implements:\n        auto_shared_fpic_config_options(conanfile)\n\n    auto_language(conanfile)  # default implementation removes `compiler.cstd`\n\n    # Assign only the current package options values, but none of the dependencies\n    is_consumer = conanfile._conan_is_consumer  # noqa\n    conanfile.options.apply_downstream(down_options, profile_options, ref, is_consumer)\n\n    if hasattr(conanfile, \"configure\"):\n        with conanfile_exception_formatter(conanfile, \"configure\"):\n            conanfile.configure()\n    elif \"auto_shared_fpic\" in conanfile.implements:\n        auto_shared_fpic_configure(conanfile)\n\n    if initial_requires_count != len(conanfile.requires):\n        conanfile.output.warning(\"Requirements should only be added in the requirements()/\"\n                                 \"build_requirements() methods, not configure()/config_options(), \"\n                                 \"which might raise errors in the future.\", warn_tag=\"deprecated\")\n\n    result = conanfile.options.get_upstream_options(down_options, ref, is_consumer)\n    self_options, up_options, private_up_options = result\n    # self_options are the minimum to reproduce state, as defined from downstream (not profile)\n    conanfile.self_options = self_options\n    # up_options are the minimal options that should be propagated to dependencies\n    conanfile.up_options = up_options\n    conanfile.private_up_options = private_up_options\n\n    PackageType.compute_package_type(conanfile)\n\n    conanfile.build_requires = BuildRequirements(conanfile.requires)\n    conanfile.test_requires = TestRequirements(conanfile.requires)\n    conanfile.tool_requires = ToolRequirements(conanfile.requires)\n\n    if hasattr(conanfile, \"requirements\"):\n        with conanfile_exception_formatter(conanfile, \"requirements\"):\n            conanfile.requirements()\n\n    if hasattr(conanfile, \"build_requirements\"):\n        with conanfile_exception_formatter(conanfile, \"build_requirements\"):\n            conanfile.build_requirements()\n\n\ndef auto_shared_fpic_config_options(conanfile):\n    if conanfile.settings.get_safe(\"os\") == \"Windows\":\n        conanfile.options.rm_safe(\"fPIC\")\n\n\ndef auto_shared_fpic_configure(conanfile):\n    if conanfile.options.get_safe(\"header_only\"):\n        conanfile.options.rm_safe(\"fPIC\")\n        conanfile.options.rm_safe(\"shared\")\n    elif conanfile.options.get_safe(\"shared\"):\n        conanfile.options.rm_safe(\"fPIC\")\n\n\ndef auto_header_only_package_id(conanfile):\n    if conanfile.options.get_safe(\"header_only\") or conanfile.package_type is PackageType.HEADER:\n        conanfile.info.clear()\n\n\ndef auto_language(conanfile):\n    if not conanfile.languages:\n        conanfile.settings.rm_safe(\"compiler.cstd\")\n        return\n    if \"C\" not in conanfile.languages:\n        conanfile.settings.rm_safe(\"compiler.cstd\")\n    if \"C++\" not in conanfile.languages:\n        conanfile.settings.rm_safe(\"compiler.cppstd\")\n        conanfile.settings.rm_safe(\"compiler.libcxx\")\n"
  },
  {
    "path": "conan/internal/model/__init__.py",
    "content": ""
  },
  {
    "path": "conan/internal/model/conan_file.py",
    "content": "import os\nimport subprocess\nfrom pathlib import Path\n\nfrom conan.api.output import ConanOutput, Color, LEVEL_QUIET\nfrom conan.internal.subsystems import command_env_wrapper\nfrom conan.errors import ConanException\nfrom conan.internal.model.cpp_info import MockInfoProperty\nfrom conan.internal.model.conf import Conf\nfrom conan.internal.model.dependencies import ConanFileDependencies\nfrom conan.internal.model.layout import Folders, Infos, Layouts\nfrom conan.internal.model.options import Options\nfrom conan.internal.model.requires import Requirements\nfrom conan.internal.model.settings import Settings\n\n\nclass ConanFile:\n    \"\"\"\n    The base class for all package recipes\n    \"\"\"\n\n    # Reference\n    name = None\n    version = None  # Any str, can be \"1.1\" or whatever\n    user = None\n    channel = None\n\n    # Metadata\n    url = None  # The URL where this File is located, as github, to collaborate in package\n    license = None\n    author = None\n    description = None\n    topics = None\n    homepage = None\n\n    build_policy = None\n    upload_policy = None\n\n    exports = None\n    exports_sources = None\n\n    generators = []\n    revision_mode = \"hash\"\n\n    # Binary model: Settings and Options\n    settings = None\n    options = None\n    default_options = None\n    default_build_options = None\n    package_type = None\n    vendor = False\n    languages = []\n    implements = []\n\n    provides = None\n    deprecated = None\n\n    win_bash = None\n    win_bash_run = None  # For run scope\n\n    _conan_is_consumer = False\n\n    # #### Requirements\n    requires = None\n    tool_requires = None\n    build_requires = None\n    test_requires = None\n    tested_reference_str = None\n\n    no_copy_source = False\n    recipe_folder = None\n\n    # Package information\n    cpp = None\n    buildenv_info = None\n    runenv_info = None\n    conf_info = None\n    generator_info = None\n    conan_data = None\n\n    def __init__(self, display_name=\"\"):\n        self.display_name = display_name\n        # something that can run commands, as os.sytem\n\n        self._conan_helpers = None\n        from conan.tools.env import Environment\n        self.buildenv_info = Environment()\n        self.runenv_info = Environment()\n        # At the moment only for build_requires, others will be ignored\n        self.conf_info = Conf()\n        self.info = None\n        self._conan_buildenv = None  # The profile buildenv, will be assigned initialize()\n        self._conan_runenv = None\n        self._conan_node = None  # access to container Node object, to access info, context, deps...\n\n        if isinstance(self.generators, str):\n            self.generators = [self.generators]\n        if isinstance(self.languages, str):\n            self.languages = [self.languages]\n        if not all(lang == \"C\" or lang == \"C++\" for lang in self.languages):\n            raise ConanException(\"Only 'C' and 'C++' languages are allowed in 'languages' attribute\")\n        if isinstance(self.settings, str):\n            self.settings = [self.settings]\n        self.requires = Requirements(self.requires, self.build_requires, self.test_requires,\n                                     self.tool_requires)\n\n        self.options = Options(self.options or {}, self.default_options)\n\n        if isinstance(self.topics, str):\n            self.topics = [self.topics]\n        if isinstance(self.provides, str):\n            self.provides = [self.provides]\n\n        # user declared variables\n        self.user_info = MockInfoProperty(\"user_info\")\n        self.env_info = MockInfoProperty(\"env_info\")\n        self._conan_dependencies = None\n\n        if not hasattr(self, \"virtualbuildenv\"):  # Allow the user to override it with True or False\n            self.virtualbuildenv = True\n        if not hasattr(self, \"virtualrunenv\"):  # Allow the user to override it with True or False\n            self.virtualrunenv = True\n\n        self.env_scripts = {}  # Accumulate the env scripts generated in order\n        self.system_requires = {}  # Read only, internal {\"apt\": []}\n\n        # layout() method related variables:\n        self.folders = Folders()\n        self.cpp = Infos()\n        self.layouts = Layouts()\n\n    def serialize(self):\n        result = {}\n\n        for a in (\"name\", \"user\", \"channel\", \"url\", \"license\",\n                  \"author\", \"description\", \"homepage\", \"build_policy\", \"upload_policy\",\n                  \"revision_mode\", \"provides\", \"deprecated\", \"win_bash\", \"win_bash_run\",\n                  \"default_options\", \"options_description\"):\n            v = getattr(self, a, None)\n            result[a] = v\n\n        result[\"version\"] = str(self.version) if self.version is not None else None\n        result[\"topics\"] = list(self.topics) if self.topics is not None else None\n        result[\"package_type\"] = str(self.package_type)\n        result[\"languages\"] = self.languages\n\n        settings = self.settings\n        if settings is not None:\n            result[\"settings\"] = settings.serialize() if isinstance(settings, Settings) else list(settings)\n\n        result[\"options\"] = self.options.serialize()\n        result[\"options_definitions\"] = self.options.possible_values\n\n        if self.generators is not None:\n            result[\"generators\"] = list(s.__name__ if isinstance(s, type) else s\n                                        for s in self.generators)\n        if self.license is not None:\n            result[\"license\"] = list(self.license) if not isinstance(self.license, str) else self.license\n\n        result[\"requires\"] = self.requires.serialize()\n\n        if hasattr(self, \"python_requires\"):\n            result[\"python_requires\"] = self.python_requires.serialize()\n        else:\n            result[\"python_requires\"] = None\n        result[\"system_requires\"] = self.system_requires\n\n        result[\"recipe_folder\"] = self.recipe_folder\n        result[\"source_folder\"] = self.source_folder\n        result[\"build_folder\"] = self.build_folder\n        result[\"generators_folder\"] = self.generators_folder\n        result[\"package_folder\"] = self.package_folder\n        result[\"immutable_package_folder\"] = self.immutable_package_folder\n\n        result[\"cpp_info\"] = self.cpp_info.serialize()\n        result[\"conf_info\"] = self.conf_info.serialize()\n        result[\"label\"] = self.display_name\n        if self.info is not None:\n            result[\"info\"] = self.info.serialize()\n        result[\"vendor\"] = self.vendor\n        if self.conan_data:\n            result[\"conandata\"] = self.conan_data\n        return result\n\n    @property\n    def output(self):\n        # an output stream (writeln, info, warn error)\n        scope = self.display_name\n        if not scope:\n            scope = self.ref if self._conan_node else \"\"\n        return ConanOutput(scope=scope)\n\n    @property\n    def context(self):\n        return self._conan_node.context\n\n    @property\n    def subgraph(self):\n        return self._conan_node.subgraph()\n\n    @property\n    def dependencies(self):\n        # Caching it, this object is requested many times\n        if self._conan_dependencies is None:\n            self._conan_dependencies = ConanFileDependencies.from_node(self._conan_node)\n        return self._conan_dependencies\n\n    @property\n    def ref(self):\n        return self._conan_node.ref\n\n    @property\n    def pref(self):\n        return self._conan_node.pref\n\n    @property\n    def buildenv(self):\n        # Lazy computation of the package buildenv based on the profileone\n        from conan.tools.env import Environment\n        if not isinstance(self._conan_buildenv, Environment):\n            self._conan_buildenv = self._conan_buildenv.get_profile_env(self.ref,\n                                                                        self._conan_is_consumer)\n        return self._conan_buildenv\n\n    @property\n    def runenv(self):\n        # Lazy computation of the package runenv based on the profile one\n        from conan.tools.env import Environment\n        if not isinstance(self._conan_runenv, Environment):\n            self._conan_runenv = self._conan_runenv.get_profile_env(self.ref,\n                                                                    self._conan_is_consumer)\n        return self._conan_runenv\n\n    @property\n    def cpp_info(self):\n        \"\"\"\n        Same as using ``self.cpp.package`` in the ``layout()`` method. Use it if you need to read\n        the ``package_folder`` to locate the already located artifacts.\n        \"\"\"\n        return self.cpp.package\n\n    @cpp_info.setter\n    def cpp_info(self, value):\n        self.cpp.package = value\n\n    @property\n    def source_folder(self):\n        \"\"\"\n        The folder in which the source code lives. The path is built joining the base directory\n        (a cache directory when running in the cache or the ``output folder`` when running locally)\n        with the value of ``folders.source`` if declared in the ``layout()`` method.\n\n        :return: A string with the path to the source folder.\n        \"\"\"\n        return self.folders.source_folder\n\n    @property\n    def source_path(self) -> Path:\n        self.output.warning(f\"Use of 'source_path' is deprecated, please use 'source_folder' instead\",\n                            warn_tag=\"deprecated\")\n        assert self.source_folder is not None, \"`source_folder` is `None`\"\n        return Path(self.source_folder)\n\n    @property\n    def export_sources_folder(self):\n        \"\"\"\n        The value depends on the method you access it:\n\n            - At ``source(self)``: Points to the base source folder (that means self.source_folder but\n              without taking into account the ``folders.source`` declared in the ``layout()`` method).\n              The declared `exports_sources` are copied to that base source folder always.\n            - At ``exports_sources(self)``: Points to the folder in the cache where the export sources\n              have to be copied.\n\n        :return: A string with the mentioned path.\n        \"\"\"\n        return self.folders.base_export_sources\n\n    @property\n    def export_sources_path(self) -> Path:\n        self.output.warning(f\"Use of 'export_sources_path' is deprecated, please use \"\n                            f\"'export_sources_folder' instead\", warn_tag=\"deprecated\")\n        assert self.export_sources_folder is not None, \"`export_sources_folder` is `None`\"\n        return Path(self.export_sources_folder)\n\n    @property\n    def export_folder(self):\n        return self.folders.base_export\n\n    @property\n    def export_path(self) -> Path:\n        self.output.warning(f\"Use of 'export_path' is deprecated, please use 'export_folder' instead\",\n                            warn_tag=\"deprecated\")\n\n        assert self.export_folder is not None, \"`export_folder` is `None`\"\n        return Path(self.export_folder)\n\n    @property\n    def build_folder(self):\n        \"\"\"\n        The folder used to build the source code. The path is built joining the base directory (a cache\n        directory when running in the cache or the ``output folder`` when running locally) with\n        the value of ``folders.build`` if declared in the ``layout()`` method.\n\n        :return: A string with the path to the build folder.\n        \"\"\"\n        return self.folders.build_folder\n\n    @property\n    def recipe_metadata_folder(self):\n        return self.folders.recipe_metadata_folder\n\n    @property\n    def package_metadata_folder(self):\n        return self.folders.package_metadata_folder\n\n    @property\n    def build_path(self) -> Path:\n        self.output.warning(f\"Use of 'build_path' is deprecated, please use 'build_folder' instead\",\n                            warn_tag=\"deprecated\")\n        assert self.build_folder is not None, \"`build_folder` is `None`\"\n        return Path(self.build_folder)\n\n    @property\n    def package_folder(self):\n        \"\"\"\n        The folder to copy the final artifacts for the binary package. In the local cache a package\n        folder is created for every different package ID.\n\n        :return: A string with the path to the package folder.\n        \"\"\"\n        return self.folders.base_package\n\n    @property\n    def immutable_package_folder(self):\n        return self.folders.immutable_package_folder\n\n    @property\n    def generators_folder(self):\n        return self.folders.generators_folder\n\n    @property\n    def package_path(self) -> Path:\n        self.output.warning(f\"Use of 'package_path' is deprecated, please use 'package_folder' instead\",\n                            warn_tag=\"deprecated\")\n\n        assert self.package_folder is not None, \"`package_folder` is `None`\"\n        return Path(self.package_folder)\n\n    @property\n    def generators_path(self) -> Path:\n        self.output.warning(f\"Use of 'generators_path' is deprecated, please use \"\n                            f\"'generators_folder' instead\", warn_tag=\"deprecated\")\n        assert self.generators_folder is not None, \"`generators_folder` is `None`\"\n        return Path(self.generators_folder)\n\n    def run(self, command: str, stdout=None, cwd=None, ignore_errors=False, env=\"\", quiet=False,\n            shell=True, scope=\"build\", stderr=None):\n        \"\"\" Run a command in the current package context.\n\n        :parameter command: The command to run.\n        :parameter stdout: The output stream to write the command output. If ``None``, it defaults to\n            the standard output stream.\n        :parameter stderr: The error output stream to write the command error output. If ``None``,\n            it defaults to the standard error stream.\n        :parameter cwd: The current working directory to run the command in.\n        :parameter ignore_errors: If ``True``, do not raise an error if the command returns a\n            non-zero exit code.\n        :parameter env: The environment file to use. If empty, it defaults to ``\"conanbuild\"`` for\n            when ``scope`` is ``build`` or ``\"conanrun\"`` for ``run``.\n            If set to ``None`` explicitly, no environment file will be applied,\n            which is useful for commands that do not require any environment.\n        :parameter quiet: If ``True``, suppress the output of the command.\n        :parameter shell: If ``True``, run the command in a shell. This is passed to the\n            underlying ``Popen`` function.\n        :parameter scope: The scope of the command, either ``\"build\"`` or ``\"run\"``.\n        \"\"\"\n        # NOTE: \"self.win_bash\" is the new parameter \"win_bash\" for Conan 2.0\n        command = self._conan_helpers.cmd_wrapper.wrap(command, conanfile=self)\n        if env == \"\":  # This default allows not breaking for users with ``env=None`` indicating\n            # they don't want any env-file applied\n            env = \"conanbuild\" if scope == \"build\" else \"conanrun\"\n\n        env = [env] if env and isinstance(env, str) else (env or [])\n        assert isinstance(env, list), \"env argument to ConanFile.run() should be a list\"\n        envfiles_folder = self.generators_folder or os.getcwd()\n        wrapped_cmd = command_env_wrapper(self, command, env, envfiles_folder=envfiles_folder,\n                                          scope=scope)\n        from conan.internal.util.runners import conan_run\n        if not quiet:\n            ConanOutput().info(f\"{self.display_name}: RUN: {command}\", fg=Color.BRIGHT_BLUE)\n        ConanOutput().debug(f\"{self.display_name}: Full command: {wrapped_cmd}\")\n        if quiet or ConanOutput.get_output_level() == LEVEL_QUIET:\n            stdout = subprocess.DEVNULL if stdout is None else stdout\n            stderr = subprocess.DEVNULL if stderr is None else stderr\n        retcode = conan_run(wrapped_cmd, cwd=cwd, stdout=stdout, stderr=stderr, shell=shell)\n        if not quiet:\n            ConanOutput().writeln(\"\")\n\n        if not ignore_errors and retcode != 0:\n            raise ConanException(\"Error %d while executing\" % retcode)\n\n        return retcode\n\n    def __repr__(self):\n        return self.display_name\n\n    def set_deploy_folder(self, deploy_folder):\n        self.cpp_info.deploy_base_folder(self.package_folder, deploy_folder)\n        self.buildenv_info.deploy_base_folder(self.package_folder, deploy_folder)\n        self.runenv_info.deploy_base_folder(self.package_folder, deploy_folder)\n        self.folders.set_base_package(deploy_folder)\n"
  },
  {
    "path": "conan/internal/model/conanconfig.py",
    "content": "import json\n\nimport yaml\n\nfrom conan.api.model import RecipeReference\nfrom conan.errors import ConanException\nfrom conan.internal.util.files import load, save\n\n\ndef loadconanconfig(filename):\n    try:\n        contents = json.loads(load(filename))\n        config_versions = contents[\"config_version\"]\n        config_versions = [RecipeReference.loads(r) for r in config_versions]\n    except Exception as e:\n        raise ConanException(f\"Error while loading config file {filename}: {str(e)}\")\n    return config_versions\n\n\ndef loadconanconfig_yml(filename):\n    try:\n        contents = yaml.safe_load(load(filename))\n        config_versions = contents[\"packages\"]\n        config_versions = [RecipeReference.loads(r) for r in config_versions]\n        urls = contents.get(\"urls\")\n    except Exception as e:\n        raise ConanException(f\"Error while loading config file {filename}: {str(e)}\")\n    return config_versions, urls\n\n\ndef saveconanconfig(filename, config_versions):\n    try:\n        config_versions = [r.repr_notime() for r in config_versions]\n        save(filename, json.dumps({\"config_version\": config_versions}, indent=4))\n    except Exception as e:\n        raise ConanException(f\"Error while saving config file {filename}: {str(e)}\")\n"
  },
  {
    "path": "conan/internal/model/conanfile_interface.py",
    "content": "from pathlib import Path\n\nfrom conan.internal.graph.graph import CONTEXT_BUILD\n\n\nclass ConanFileInterface:\n    \"\"\"\n    This is just a protective wrapper to give consumers\n    a limited view of conanfile dependencies, \"read\" only,\n    and only to some attributes, not methods\n    \"\"\"\n\n    def __str__(self):\n        return str(self._conanfile)\n\n    def __init__(self, conanfile):\n        self._conanfile = conanfile\n\n    def __eq__(self, other):\n        \"\"\"\n        The conanfile is a different entity per node, and conanfile equality is identity\n        :type other: ConanFileInterface\n        \"\"\"\n        return self._conanfile == other._conanfile\n\n    def __hash__(self):\n        return hash(self._conanfile)\n\n    @property\n    def options(self):\n        return self._conanfile.options\n\n    @property\n    def recipe_folder(self):\n        return self._conanfile.recipe_folder\n\n    @property\n    def recipe_metadata_folder(self):\n        return self._conanfile.recipe_metadata_folder\n\n    @property\n    def package_folder(self):\n        return self._conanfile.package_folder\n\n    @property\n    def immutable_package_folder(self):\n        return self._conanfile.immutable_package_folder\n\n    @property\n    def package_metadata_folder(self):\n        return self._conanfile.package_metadata_folder\n\n    @property\n    def package_path(self) -> Path:\n        assert self.package_folder is not None, \"`package_folder` is `None`\"\n        return Path(self.package_folder)\n\n    @property\n    def ref(self):\n        return self._conanfile.ref\n\n    @property\n    def pref(self):\n        return self._conanfile.pref\n\n    @property\n    def buildenv_info(self):\n        return self._conanfile.buildenv_info\n\n    @property\n    def runenv_info(self):\n        return self._conanfile.runenv_info\n\n    @property\n    def cpp_info(self):\n        return self._conanfile.cpp_info\n\n    @property\n    def settings(self):\n        return self._conanfile.settings\n\n    @property\n    def settings_build(self):\n        return self._conanfile.settings_build\n\n    @property\n    def context(self):\n        return self._conanfile.context\n\n    @property\n    def conf_info(self):\n        return self._conanfile.conf_info\n\n    @property\n    def generator_info(self):\n        return self._conanfile.generator_info\n\n    @property\n    def dependencies(self):\n        return self._conanfile.dependencies\n\n    @property\n    def folders(self):\n        return self._conanfile.folders\n\n    @property\n    def is_build_context(self):\n        return self._conanfile.context == CONTEXT_BUILD\n\n    @property\n    def package_type(self):\n        return self._conanfile.package_type\n\n    @property\n    def languages(self):\n        return self._conanfile.languages\n\n    @property\n    def info(self):\n        return self._conanfile.info\n\n    def set_deploy_folder(self, deploy_folder):\n        self._conanfile.set_deploy_folder(deploy_folder)\n\n    @property\n    def conan_data(self):\n        return self._conanfile.conan_data\n\n    @property\n    def license(self):\n        return self._conanfile.license\n\n    @property\n    def description(self):\n        return self._conanfile.description\n\n    @property\n    def author(self):\n        return self._conanfile.author\n\n    @property\n    def homepage(self):\n        return self._conanfile.homepage\n\n    @property\n    def url(self):\n        return self._conanfile.url\n\n    @property\n    def extension_properties(self):\n        return getattr(self._conanfile, \"extension_properties\", {})\n\n    @property\n    def recipe(self) -> str:\n        # IMPORTANT: this should be used only for \"informational\" purposes, see GH#18996.\n        return self._conanfile._conan_node.recipe\n\n    @property\n    def conf(self):\n        return self._conanfile.conf\n"
  },
  {
    "path": "conan/internal/model/conf.py",
    "content": "import copy\nimport hashlib\nimport numbers\nimport platform\nimport re\nimport os\nimport fnmatch\nimport textwrap\n\nfrom collections import OrderedDict\n\nfrom jinja2 import Environment, FileSystemLoader\n\nfrom conan.errors import ConanException\nfrom conan.internal.api.detect import detect_api\nfrom conan.internal.cache.home_paths import HomePaths\nfrom conan.internal.model.options import _PackageOption\nfrom conan.internal.model.recipe_ref import ref_matches\nfrom conan.internal.model.settings import SettingsItem\nfrom conan.internal.util.files import load, save\n\nBUILT_IN_CONFS = {\n    \"core:required_conan_version\": \"Raise if current version does not match the defined range.\",\n    \"core:non_interactive\": \"Disable interactive user input, raises error if input necessary\",\n    \"core:warnings_as_errors\": \"Treat warnings matching any of the patterns in this list as errors and then raise an exception. \"\n                               \"Current warning tags are 'network', 'deprecated'\",\n    \"core:skip_warnings\": \"Do not show warnings matching any of the patterns in this list. \"\n                          \"Current warning tags are 'network', 'deprecated', 'experimental'\",\n    \"core:default_profile\": \"Defines the default host profile ('default' by default)\",\n    \"core:default_build_profile\": \"Defines the default build profile ('default' by default)\",\n    \"core:allow_uppercase_pkg_names\": \"Temporarily (will be removed in 2.X) allow uppercase names\",\n    \"core.version_ranges:resolve_prereleases\": \"Whether version ranges can resolve to pre-releases or not\",\n    \"core.upload:retry\": \"Number of retries in case of failure when uploading to Conan server\",\n    \"core.upload:retry_wait\": \"Seconds to wait between upload attempts to Conan server\",\n    \"core.upload:parallel\": \"Number of concurrent threads to upload packages\",\n    \"core.download:parallel\": \"Number of concurrent threads to download packages\",\n    \"core.download:retry\": \"Number of retries in case of failure when downloading from Conan server\",\n    \"core.download:retry_wait\": \"Seconds to wait between download attempts from Conan server\",\n    \"core.download:download_cache\": \"Define path to a file download cache\",\n    \"core.cache:storage_path\": \"Absolute path where the packages and database are stored\",\n    \"core:update_policy\": \"(Legacy). If equal 'legacy' when multiple remotes, update based on order of remotes, only the timestamp of the first occurrence of each revision counts.\",\n    # Sources backup\n    \"core.sources:download_cache\": \"Folder to store the sources backup\",\n    \"core.sources:download_urls\": \"List of URLs to download backup sources from\",\n    \"core.sources:upload_url\": \"Remote URL to upload backup sources to\",\n    \"core.sources:exclude_urls\": \"URLs which will not be backed up\",\n    \"core.sources.patch:extra_path\": \"Extra path to search for patch files for conan create\",\n    # Package ID\n    \"core.package_id:default_unknown_mode\": \"By default, 'semver_mode'\",\n    \"core.package_id:default_non_embed_mode\": \"By default, 'minor_mode'\",\n    \"core.package_id:default_embed_mode\": \"By default, 'full_mode'\",\n    \"core.package_id:default_python_mode\": \"By default, 'minor_mode'\",\n    \"core.package_id:default_build_mode\": \"By default, 'None'\",\n    \"core.package_id:config_mode\": \"How the 'config_version' affects binaries. By default 'None'\",\n    # General HTTP(python-requests) configuration\n    \"core.net.http:max_retries\": \"Maximum number of connection retries (requests library)\",\n    \"core.net.http:timeout\": \"Number of seconds without response to timeout (requests library)\",\n    \"core.net.http:no_proxy_match\": \"List of urls to skip from proxies configuration\",\n    \"core.net.http:proxies\": \"Dictionary containing the proxy configuration\",\n    \"core.net.http:cacert_path\": \"Path containing a custom Cacert file\",\n    \"core.net.http:client_cert\": \"Path or tuple of files containing a client cert (and key)\",\n    \"core.net.http:clean_system_proxy\": \"If defined, the proxies system env-vars will be discarded\",\n    # Compression for `conan upload`\n    \"core.upload:compression_format\": \"The compression format used when uploading Conan packages. \"\n                                      \"Possible values: 'zst', 'xz', 'gz' (default=gz)\",\n    \"core.gzip:compresslevel\": \"The Gzip compression level for Conan artifacts (default=9)\",\n    \"core:compresslevel\": \"The compression level for Conan artifacts (default zstd=3, gz=9)\",\n    # Excluded from revision_mode = \"scm\" dirty and Git().is_dirty() checks\n    \"core.scm:excluded\": \"List of excluded patterns for builtin git dirty checks\",\n    \"core.scm:local_url\": \"By default allows to store local folders as remote url, but not upload them. Use 'allow' for allowing upload and 'block' to completely forbid it\",\n    # Compatibility opt-in, to be removed in future versions as optimized behavior becomes default\n    \"core.graph:compatibility_mode\": \"(Experimental) Set this to 'optimized' to enable the improved compatibility behaviour when querying multiple compatible binaries in remotes\",\n    # Tools\n    \"tools.android:ndk_path\": \"Argument for the CMAKE_ANDROID_NDK\",\n    \"tools.android:cmake_legacy_toolchain\": \"Define to explicitly pass ANDROID_USE_LEGACY_TOOLCHAIN_FILE in CMake toolchain\",\n    \"tools.build:skip_test\": \"Do not execute CMake.test() and Meson.test() when enabled\",\n    \"tools.build:download_source\": \"Force download of sources for every package\",\n    \"tools.build:jobs\": \"Default compile jobs number -jX Ninja, Make, /MP VS (default: max CPUs)\",\n    \"tools.build:sysroot\": \"Pass the --sysroot=<tools.build:sysroot> flag if available. (None by default)\",\n    \"tools.build:add_rpath_link\": \"Add -Wl,-rpath-link flags pointing to all lib directories for host dependencies (CMake and Meson toolchains)\",\n    \"tools.build.cross_building:can_run\": \"(boolean) Indicates whether is possible to run a non-native app on the same architecture. It's used by 'can_run' tool\",\n    \"tools.build.cross_building:cross_build\": \"(boolean) Decides whether cross-building or not regardless of arch/OS settings. Used by 'cross_building' tool\",\n    \"tools.build:verbosity\": \"Verbosity of build systems if set. Possible values are 'quiet' and 'verbose'\",\n    \"tools.compilation:verbosity\": \"Verbosity of compilation tools if set. Possible values are 'quiet' and 'verbose'\",\n    \"tools.cmake.cmaketoolchain:generator\": \"User defined CMake generator to use instead of default\",\n    \"tools.cmake.cmaketoolchain:find_package_prefer_config\": \"Argument for the CMAKE_FIND_PACKAGE_PREFER_CONFIG\",\n    \"tools.cmake.cmaketoolchain:toolchain_file\": \"Use other existing file rather than conan_toolchain.cmake one\",\n    \"tools.cmake.cmaketoolchain:user_toolchain\": \"Inject existing user toolchains at the beginning of conan_toolchain.cmake\",\n    \"tools.cmake.cmaketoolchain:system_name\": \"Define CMAKE_SYSTEM_NAME in CMakeToolchain\",\n    \"tools.cmake.cmaketoolchain:system_version\": \"Define CMAKE_SYSTEM_VERSION in CMakeToolchain\",\n    \"tools.cmake.cmaketoolchain:system_processor\": \"Define CMAKE_SYSTEM_PROCESSOR in CMakeToolchain\",\n    \"tools.cmake.cmaketoolchain:toolset_arch\": \"Toolset architecture to be used as part of CMAKE_GENERATOR_TOOLSET in CMakeToolchain\",\n    \"tools.cmake.cmaketoolchain:toolset_cuda\": \"(Experimental) Path to a CUDA toolset to use, or version if installed at the system level\",\n    \"tools.cmake.cmaketoolchain:presets_environment\": \"String to define wether to add or not the environment section to the CMake presets. Empty by default, will generate the environment section in CMakePresets. Can take values: 'disabled'.\",\n    \"tools.cmake.cmaketoolchain:extra_variables\": \"Dictionary with variables to be injected in CMakeToolchain (potential override of CMakeToolchain defined variables)\",\n    \"tools.cmake.cmaketoolchain:enabled_blocks\": \"Select the specific blocks to use in the conan_toolchain.cmake\",\n    \"tools.cmake.cmaketoolchain:user_presets\": \"(Experimental) Select a different name instead of CMakeUserPresets.json, empty to disable\",\n    \"tools.cmake.cmake_layout:build_folder_vars\": \"Settings and Options that will produce a different build folder and different CMake presets names\",\n    \"tools.cmake.cmake_layout:build_folder\": \"(Experimental) Allow configuring the base folder of the build for local builds\",\n    \"tools.cmake.cmake_layout:test_folder\": \"(Experimental) Allow configuring the base folder of the build for test_package\",\n    \"tools.cmake:cmake_program\": \"Path to CMake executable\",\n    \"tools.cmake.cmakedeps:new\": \"Use the new CMakeDeps generator\",\n    \"tools.cmake:ctest_args\": \"To inject list of arguments to CMake.ctest() runner\",\n    \"tools.cmake:install_strip\": \"(Deprecated) Add --strip to cmake.install(). Use tools.build:install_strip instead\",\n    \"tools.deployer:symlinks\": \"Set to False to disable deployers copying symlinks\",\n    \"tools.files.download:retry\": \"Number of retries in case of failure when downloading\",\n    \"tools.files.download:retry_wait\": \"Seconds to wait between download attempts\",\n    \"tools.files.download:verify\": \"If set, overrides recipes on whether to perform SSL verification for their downloaded files. Only recommended to be set while testing\",\n    \"tools.files.unzip:filter\": \"Define tar extraction filter: 'fully_trusted', 'tar', 'data'\",\n    \"tools.graph:vendor\": \"(Experimental) If 'build', enables the computation of dependencies of vendoring packages to build them\",\n    \"tools.graph:skip_binaries\": \"Allow the graph to skip binaries not needed in the current configuration (True by default)\",\n    \"tools.graph:skip_build\": \"(Experimental) Do not expand build/tool_requires\",\n    \"tools.graph:skip_test\": \"(Experimental) Do not expand test_requires. If building it might need 'tools.build:skip_test=True'\",\n    \"tools.gnu:make_program\": \"Indicate path to make program\",\n    \"tools.gnu:disable_flags\": \"Disable the automatic addition of flags to some build systems. List of possible values: ['arch', 'arch_link', 'libcxx', 'build_type', 'build_type_link', 'threads','cppstd', 'cstd']\",\n    \"tools.gnu:define_libcxx11_abi\": \"Force definition of GLIBCXX_USE_CXX11_ABI=1 for libstdc++11\",\n    \"tools.gnu:pkg_config\": \"Path to pkg-config executable used by PkgConfig build helper\",\n    \"tools.gnu:build_triplet\": \"Custom build triplet to pass to Autotools scripts\",\n    \"tools.gnu:host_triplet\": \"Custom host triplet to pass to Autotools scripts\",\n    \"tools.gnu:extra_configure_args\": \"List of extra arguments to pass to configure when using AutotoolsToolchain and GnuToolchain\",\n    \"tools.google.bazel:configs\": \"List of Bazel configurations to be used as 'bazel build --config=config1 ...'\",\n    \"tools.google.bazel:bazelrc_path\": \"List of paths to bazelrc files to be used as 'bazel --bazelrc=rcpath1 ... build'\",\n    \"tools.meson.mesontoolchain:backend\": \"Any Meson backend: ninja, vs, vs2010, vs2012, vs2013, vs2015, vs2017, vs2019, xcode\",\n    \"tools.meson.mesontoolchain:extra_machine_files\": \"List of paths for any additional native/cross file references to be appended to the existing Conan ones\",\n    \"tools.microsoft:winsdk_version\": \"Use this winsdk_version in vcvars\",\n    \"tools.microsoft:msvc_update\": \"Force the specific update irrespective of compiler.update (CMakeToolchain and VCVars)\",\n    \"tools.microsoft.msbuild:vs_version\": \"Defines the IDE version (15, 16, 17) when using the msvc compiler. Necessary if compiler.version specifies a toolset that is not the IDE default\",\n    \"tools.microsoft.msbuild:max_cpu_count\": \"Argument for the /m when running msvc to build parallel projects\",\n    \"tools.microsoft.msbuild:installation_path\": \"VS install path, to avoid auto-detect via vswhere, like C:/Program Files (x86)/Microsoft Visual Studio/2019/Community. Use empty string to disable\",\n    \"tools.microsoft.msbuilddeps:exclude_code_analysis\": \"Suppress MSBuild code analysis for patterns\",\n    \"tools.microsoft.msbuildtoolchain:compile_options\": \"Dictionary with MSBuild compiler options\",\n    \"tools.microsoft.bash:subsystem\": \"The subsystem to be used when conanfile.win_bash==True. Possible values: msys2, msys, cygwin, wsl, sfu\",\n    \"tools.microsoft.bash:path\": \"The path to the shell to run when conanfile.win_bash==True\",\n    \"tools.microsoft.bash:active\": \"Set True only when Conan runs in a POSIX Bash (MSYS2/Cygwin) where Python's subprocess (shell=True) uses a POSIX-compatible shell (e.g., /bin/sh). Do not set when using Conan from cmd/PowerShell or with native Windows Python ('win32').\",\n    \"tools.intel:installation_path\": \"Defines the Intel oneAPI installation root path\",\n    \"tools.intel:setvars_args\": \"Custom arguments to be passed onto the setvars.sh|bat script from Intel oneAPI\",\n    \"tools.system.package_manager:tool\": \"Default package manager tool: 'apk', 'apt-get', 'yum', 'dnf', 'brew', 'pacman', 'choco', 'zypper', 'pkg' or 'pkgutil'\",\n    \"tools.system.package_manager:mode\": \"Mode for package_manager tools: 'check', 'report', 'report-installed' or 'install'\",\n    \"tools.system.package_manager:sudo\": \"Use 'sudo' when invoking the package manager tools in Linux (False by default)\",\n    \"tools.system.package_manager:sudo_askpass\": \"Use the '-A' argument if using sudo in Linux to invoke the system package manager (False by default)\",\n    \"tools.system.pyenv:python_interpreter\": \"(Experimental) Path to the Python interpreter to be used to create the virtualenv\",\n    \"tools.system.pipenv:python_interpreter\": \"(Deprecated) Use 'tools.system.pyenv:python_interpreter' instead. Path to the Python interpreter to be used to create the virtualenv\",\n    \"tools.apple:sdk_path\": \"Path to the SDK to be used\",\n    \"tools.apple:enable_bitcode\": \"(boolean) Enable/Disable Bitcode Apple Clang flags\",\n    \"tools.apple:enable_arc\": \"(boolean) Enable/Disable ARC Apple Clang flags\",\n    \"tools.apple:enable_visibility\": \"(boolean) Enable/Disable Visibility Apple Clang flags\",\n    \"tools.env.virtualenv:powershell\": \"If specified, it generates PowerShell launchers (.ps1). Use this configuration setting the PowerShell executable you want to use (e.g., 'powershell.exe' or 'pwsh'). Setting it to True or False is deprecated as of Conan 2.11.0.\",\n    \"tools.env:dotenv\": \"(Experimental) Generate dotenv environment files\",\n    \"tools.env:deactivation_mode\": \"(Experimental) If 'function', generate a deactivate function instead of a script to unset the environment variables\",\n    # Compilers/Flags configurations\n    \"tools.build:compiler_executables\": \"Defines a Python dict-like with the compilers path to be used. Allowed keys {'c', 'cpp', 'cuda', 'objc', 'objcxx', 'rc', 'fortran', 'asm', 'hip', 'ispc'}\",\n    \"tools.build:cxxflags\": \"List of extra CXX flags used by different toolchains like CMakeToolchain, AutotoolsToolchain and MesonToolchain\",\n    \"tools.build:cflags\": \"List of extra C flags used by different toolchains like CMakeToolchain, AutotoolsToolchain and MesonToolchain\",\n    \"tools.build:defines\": \"List of extra definition flags used by different toolchains like CMakeToolchain, AutotoolsToolchain and MesonToolchain\",\n    \"tools.build:sharedlinkflags\": \"List of extra flags used by different toolchains like CMakeToolchain, AutotoolsToolchain and MesonToolchain\",\n    \"tools.build:exelinkflags\": \"List of extra flags used by different toolchains like CMakeToolchain, AutotoolsToolchain and MesonToolchain\",\n    \"tools.build:rcflags\": \"List of extra RC (resource compiler) flags used by different toolchains like CMakeToolchain, MSBuildToolchain and MesonToolchain\",\n    \"tools.build:linker_scripts\": \"List of linker script files to pass to the linker used by different toolchains like CMakeToolchain, AutotoolsToolchain, and MesonToolchain\",\n    # Toolchain installation\n    \"tools.build:install_strip\": \"(boolean) Strip the binaries when installing them with CMake, Meson and Autotools\",\n    # Package ID composition\n    \"tools.info.package_id:confs\": \"List of existing configuration to be part of the package ID\",\n}\n\nBUILT_IN_CONFS = {key: value for key, value in sorted(BUILT_IN_CONFS.items())}\n\n\n_BUILT_IN_CONFS_TYPES = {\n    \"core:required_conan_version\": str,\n    \"tools.microsoft:msvc_update\": str\n}\n\nCORE_CONF_PATTERN = re.compile(r\"^(core\\..+|core):.*\")\nTOOLS_CONF_PATTERN = re.compile(r\"^(tools\\..+|tools):.*\")\nUSER_CONF_PATTERN = re.compile(r\"^(user\\..+|user):.*\")\n\n\ndef _is_profile_module(module_name):\n    # These are the modules that are propagated to profiles and user recipes\n    return TOOLS_CONF_PATTERN.match(module_name) or USER_CONF_PATTERN.match(module_name)\n\n\n# FIXME: Refactor all the next classes because they are mostly the same as\n#        conan.tools.env.environment ones\nclass _ConfVarPlaceHolder:\n    pass\n\n\nclass _ConfValue:\n\n    def __init__(self, name, value, path=False, update=None, important=False):\n        self.name = name\n        self._important = important\n        self._value = value\n        self._value_type = type(value)\n        self._path = path\n        self._update = update\n\n    @staticmethod\n    def parse(name, value, path=False, update=None):\n        if name != name.lower():\n            raise ConanException(\"Conf '{}' must be lowercase\".format(name))\n        name, important = (name[:-1], True) if name[-1] == \"!\" else (name, False)\n        if isinstance(value, (_PackageOption, SettingsItem)):\n            raise ConanException(f\"Invalid 'conf' type, please use Python types (int, str, ...)\")\n        return _ConfValue(name, value, path=path, update=update, important=important)\n\n    def __repr__(self):\n        return repr(self._value)\n\n    @property\n    def value(self):\n        if self._value_type is list and _ConfVarPlaceHolder in self._value:\n            v = self._value[:]\n            v.remove(_ConfVarPlaceHolder)\n            return v\n        return self._value\n\n    def copy(self):\n        # Using copy for when self._value is a mutable list\n        return _ConfValue(self.name, copy.copy(self._value), self._path, self._update,\n                          self._important)\n\n    def dumps(self):\n        name = f\"{self.name}!\" if self._important else self.name\n        if self._value is None:\n            return \"{}=!\".format(name)  # unset\n        elif self._value_type is list and _ConfVarPlaceHolder in self._value:\n            v = self._value[:]\n            v.remove(_ConfVarPlaceHolder)\n            return \"{}={}\".format(name, v)\n        else:\n            return \"{}={}\".format(name, self._value)\n\n    def serialize(self):\n        name = f\"{self.name}!\" if self._important else self.name\n        if self._value is None:\n            _value = \"!\"  # unset\n        elif self._value_type is list and _ConfVarPlaceHolder in self._value:\n            v = self._value[:]\n            v.remove(_ConfVarPlaceHolder)\n            _value = v\n        else:\n            _value = self._value\n        return {name: _value}\n\n    def update(self, value):\n        assert self._value_type is dict, \"Only dicts can be updated\"\n        assert isinstance(value, dict), \"Only dicts can update\"\n        self._value.update(value)\n\n    def remove(self, value):\n        if self._value_type is list:\n            self._value.remove(value)\n        elif self._value_type is dict:\n            self._value.pop(value, None)\n\n    def append(self, value):\n        if self._value_type is not list:\n            raise ConanException(\"Only list-like values can append other values.\")\n\n        if isinstance(value, list):\n            self._value.extend(value)\n        else:\n            if isinstance(value, (_PackageOption, SettingsItem)):\n                raise ConanException(f\"Invalid 'conf' type, please use Python types (int, str, ...)\")\n            self._value.append(value)\n\n    def prepend(self, value):\n        if self._value_type is not list:\n            raise ConanException(\"Only list-like values can prepend other values.\")\n\n        if isinstance(value, list):\n            self._value = value + self._value\n        else:\n            if isinstance(value, (_PackageOption, SettingsItem)):\n                raise ConanException(f\"Invalid 'conf' type, please use Python types (int, str, ...)\")\n            self._value.insert(0, value)\n\n    def compose_conf_value(self, other):\n        \"\"\"\n        self has precedence, the \"other\" will add/append if possible and not conflicting, but\n        self mandates what to do. If self has define(), without placeholder, that will remain.\n        :type other: _ConfValue\n        \"\"\"\n        v_type = self._value_type\n        o_type = other._value_type\n\n        important = other._important and not self._important\n        if v_type is list and o_type is list:\n            # If important, we swap values to prioritize the other\n            v1, v2 = (other._value, self._value) if important else (self._value, other._value)\n            try:\n                index = v1.index(_ConfVarPlaceHolder)\n            except ValueError:  # It doesn't have placeholder\n                if important:\n                    self._value = other._value\n            else:\n                new_value = v1[:]  # do a copy\n                new_value[index:index + 1] = v2  # replace the placeholder\n                self._value = new_value\n        elif v_type is dict and o_type is dict:\n            if self._update:\n                # only if the current one is marked as \"*=\" update, otherwise it remains\n                # as this is a \"compose\" operation, self has priority, it is the one updating\n                # If important, we swap values to prioritize the other\n                v1, v2 = (other._value, self._value) if important else (self._value, other._value)\n                new_value = v2.copy()\n                new_value.update(v1)\n                self._value = new_value\n            elif important:\n                self._value = other._value\n        elif ((issubclass(v_type, numbers.Number) and issubclass(o_type, numbers.Number)) or\n              # They might be different kind of numbers, so skip the check below\n              self._value is None or other._value is None):\n            # It means any of those values were an \"unset\" so doing nothing because we don't\n            # really know the original value type\n            if important:\n                self._value = other._value\n                self._value_type = other._value_type\n        elif o_type != v_type:\n            raise ConanException(\"It's not possible to compose {} values \"\n                                 \"and {} ones.\".format(v_type.__name__, o_type.__name__))\n        # TODO: In case of any other object types?\n        elif important:  # equal type, but just string\n            self._value = other._value\n\n    def set_relative_base_folder(self, folder):\n        if not self._path:\n            return\n        if isinstance(self._value, list):\n            self._value = [os.path.join(folder, v) if v != _ConfVarPlaceHolder else v\n                           for v in self._value]\n        if isinstance(self._value, dict):\n            self._value = {k: os.path.join(folder, v) for k, v in self._value.items()}\n        elif isinstance(self._value, str):\n            self._value = os.path.join(folder, self._value)\n\n\nclass Conf:\n    # Putting some default expressions to check that any value could be false\n    boolean_false_expressions = (\"0\", '\"0\"', \"false\", '\"false\"', \"off\")\n    boolean_true_expressions = (\"1\", '\"1\"', \"true\", '\"true\"', \"on\")\n\n    def __init__(self):\n        # It being ordered allows for Windows case-insensitive composition\n        self._values = OrderedDict()  # {var_name: [] of values, including separators}\n\n    def __bool__(self):\n        return bool(self._values)\n\n    def __repr__(self):\n        return \"Conf: \" + repr(self._values)\n\n    def __eq__(self, other):\n        \"\"\"\n        :type other: Conf\n        \"\"\"\n        return other._values == self._values\n\n    def clear(self):\n        self._values.clear()\n\n    def validate(self):\n        for conf in self._values:\n            self._check_conf_name(conf)\n\n    def items(self):\n        # FIXME: Keeping backward compatibility\n        for k, v in self._values.items():\n            yield k, v.value\n\n    def get(self, conf_name, default=None, check_type=None, choices=None):\n        \"\"\"\n        Get all the values of the given configuration name.\n\n        :param conf_name: Name of the configuration.\n        :param default: Default value in case of conf does not have the conf_name key.\n        :param check_type: Check the conf type(value) is the same as the given by this param.\n                           There are two default smart conversions for bool and str types.\n        :param choices: list of possible values this conf can have, if value not in it, errors.\n        \"\"\"\n        # Skipping this check only the user.* configurations\n        self._check_conf_name(conf_name)\n\n        conf_value = self._values.get(conf_name)\n        if conf_value:\n            v = conf_value.value\n            if choices is not None and v not in choices and v is not None:\n                raise ConanException(f\"Unknown value '{v}' for '{conf_name}'\")\n            # Some smart conversions\n            if check_type is bool and not isinstance(v, bool):\n                if str(v).lower() in Conf.boolean_false_expressions:\n                    return False\n                if str(v).lower() in Conf.boolean_true_expressions:\n                    return True\n                raise ConanException(f\"[conf] {conf_name} must be a boolean-like object \"\n                                     f\"(true/false, 1/0, on/off) and value '{v}' does not match it.\")\n            elif check_type is str and not isinstance(v, str):\n                return str(v)\n            elif v is None:  # value was unset\n                return default\n            elif (check_type is not None and not isinstance(v, check_type) or\n                  check_type is int and isinstance(v, bool)):\n                raise ConanException(f\"[conf] {conf_name} must be a \"\n                                     f\"{check_type.__name__}-like object. The value '{v}' \"\n                                     f\"introduced is a {type(v).__name__} object\")\n            return v\n        else:\n            return default\n\n    def pop(self, conf_name, default=None):\n        \"\"\"\n        Remove the given configuration, returning its value.\n\n        :param conf_name: Name of the configuration.\n        :param default: Default value to return in case the configuration doesn't exist.\n        :return:\n        \"\"\"\n        value = self.get(conf_name, default=default)\n        self._values.pop(conf_name, None)\n        return value\n\n    def show(self, fnpattern, pattern=\"\"):\n        return {key: self.get(key)\n                for key in self._values.keys()\n                if fnmatch.fnmatch(pattern + key, fnpattern)}\n\n    def copy(self):\n        c = Conf()\n        c._values = OrderedDict((k, v.copy()) for k, v in self._values.items())\n        return c\n\n    def filter_core(self):\n        c = Conf()\n        c._values = OrderedDict((k, v.copy()) for k, v in self._values.items()\n                                if not CORE_CONF_PATTERN.match(k))\n        return c\n\n    def dumps(self):\n        \"\"\"\n        Returns a string with the format ``name=conf-value``\n        \"\"\"\n        return \"\\n\".join([v.dumps() for v in sorted(self._values.values(), key=lambda x: x.name)])\n\n    def serialize(self):\n        \"\"\"\n        Returns a dict-like object, e.g., ``{\"tools.xxxx\": \"value1\"}``\n        \"\"\"\n        ret = {}\n        for v in self._values.values():\n            ret.update(v.serialize())\n        return ret\n\n    def define(self, name, value):\n        \"\"\"\n        Define a value for the given configuration name.\n\n        :param name: Name of the configuration.\n        :param value: Value of the configuration.\n        \"\"\"\n        v = _ConfValue.parse(name, value)\n        self._values[v.name] = v\n\n    def define_path(self, name, value):\n        v = _ConfValue.parse(name, value, path=True)\n        self._values[v.name] = v\n\n    def unset(self, name):\n        \"\"\"\n        Clears the variable, equivalent to a unset or set XXX=\n\n        :param name: Name of the configuration.\n        \"\"\"\n        v = _ConfValue.parse(name, None)\n        self._values[v.name] = v\n\n    def update(self, name, value):\n        \"\"\"\n        Update the value to the given configuration name.\n\n        :param name: Name of the configuration.\n        :param value: Value of the configuration.\n        \"\"\"\n        # Placeholder trick is not good for dict update, so we need to explicitly update=True\n        conf_value = _ConfValue.parse(name, {}, update=True)\n        self._values.setdefault(conf_value.name, conf_value).update(value)\n\n    def update_path(self, name, value):\n        conf_value = _ConfValue.parse(name, {}, path=True, update=True)\n        self._values.setdefault(conf_value.name, conf_value).update(value)\n\n    def append(self, name, value):\n        \"\"\"\n        Append a value to the given configuration name.\n\n        :param name: Name of the configuration.\n        :param value: Value to append.\n        \"\"\"\n        conf_value = _ConfValue.parse(name, [_ConfVarPlaceHolder])\n        self._values.setdefault(conf_value.name, conf_value).append(value)\n\n    def append_path(self, name, value):\n        conf_value = _ConfValue.parse(name, [_ConfVarPlaceHolder], path=True)\n        self._values.setdefault(conf_value.name, conf_value).append(value)\n\n    def prepend(self, name, value):\n        \"\"\"\n        Prepend a value to the given configuration name.\n\n        :param name: Name of the configuration.\n        :param value: Value to prepend.\n        \"\"\"\n        conf_value = _ConfValue.parse(name, [_ConfVarPlaceHolder])\n        self._values.setdefault(conf_value.name, conf_value).prepend(value)\n\n    def prepend_path(self, name, value):\n        conf_value = _ConfValue.parse(name, [_ConfVarPlaceHolder], path=True)\n        self._values.setdefault(conf_value.name, conf_value).prepend(value)\n\n    def remove(self, name, value):\n        \"\"\"\n        Remove a value from the given configuration name.\n\n        :param name: Name of the configuration.\n        :param value: Value to remove.\n        \"\"\"\n        conf_value = self._values.get(name)\n        if conf_value:\n            conf_value.remove(value)\n        else:\n            raise ConanException(\"Conf {} does not exist.\".format(name))\n\n    def compose_conf(self, other):\n        \"\"\"\n        :param other: other has less priority than current one\n        :type other: Conf\n        \"\"\"\n        for k, v in other._values.items():\n            existing = self._values.get(k)\n            if existing is None:\n                self._values[k] = v.copy()\n            else:\n                existing.compose_conf_value(v)\n        return self\n\n    def copy_conaninfo_conf(self):\n        \"\"\"\n        Get a new `Conf()` object with all the configurations required by the consumer\n        to be included in the final `ConanInfo().package_id()` computation. For instance, let's\n        suppose that we have this Conan `profile`:\n\n        ```\n        ...\n        [conf]\n        tools.info.package_id:confs=[\"tools.build:cxxflags\", \"tools.build:cflags\"]\n        tools.build:cxxflags=[\"flag1xx\"]\n        tools.build:cflags=[\"flag1\"]\n        tools.build:defines=[\"DEF1\"]\n        ...\n\n        Then, the resulting `Conf()` will have only these configuration lines:\n\n        tools.build:cxxflags=[\"flag1xx\"]\n        tools.build:cflags=[\"flag1\"]\n        ```\n\n        :return: a new `< Conf object >` with the configuration selected by `tools.info.package_id:confs`.\n        \"\"\"\n        result = Conf()\n        # Reading the list of all the configurations selected by the user to use for the package_id\n        package_id_confs = self.get(\"tools.info.package_id:confs\", default=[], check_type=list)\n        for conf_name in package_id_confs:\n            matching_confs = [c for c in self._values if re.match(conf_name, c)]\n            for name in matching_confs:\n                value = self.get(name)\n                # Pruning any empty values, those should not affect package ID\n                if value:\n                    result.define(name, value)\n        return result\n\n    def set_relative_base_folder(self, folder):\n        for v in self._values.values():\n            v.set_relative_base_folder(folder)\n\n    @staticmethod\n    def _check_conf_name(conf):\n        if conf.startswith(\"user\"):\n            if USER_CONF_PATTERN.match(conf) is None:\n                raise ConanException(f\"User conf '{conf}' invalid format, not 'user.org.group:conf'\")\n        elif conf not in BUILT_IN_CONFS:\n            raise ConanException(f\"[conf] '{conf}' does not exist in configuration list. \"\n                                 \"Run 'conan config list' to see all the available confs.\")\n\n\nclass ConfDefinition:\n    # Order is important, \"define\" must be latest\n    actions = ((\"+=\", \"append\"), (\"=+\", \"prepend\"),\n               (\"=!\", \"unset\"), (\"*=\", \"update\"), (\"=\", \"define\"))\n\n    def __init__(self):\n        self._pattern_confs = OrderedDict()\n\n    def __repr__(self):\n        return \"ConfDefinition: \" + repr(self._pattern_confs)\n\n    def __bool__(self):\n        return bool(self._pattern_confs)\n\n    def get(self, conf_name, default=None, check_type=None, choices=None):\n        \"\"\"\n        Get the value of the conf name requested and convert it to the [type]-like passed.\n        \"\"\"\n        pattern, name = self._split_pattern_name(conf_name)\n        return self._pattern_confs.get(pattern, Conf()).get(name, default=default,\n                                                            check_type=check_type, choices=choices)\n\n    def show(self, fnpattern):\n        \"\"\"\n        Get the value of the confs that match the requested pattern\n        \"\"\"\n        result = {}\n\n        for patter_key, patter_conf in self._pattern_confs.items():\n            if patter_key is None:\n                patter_key = \"\"\n            else:\n                patter_key += \":\"\n\n            pattern_values = patter_conf.show(fnpattern, patter_key)\n            result.update({patter_key + pattern_subkey: pattern_subvalue\n                           for pattern_subkey, pattern_subvalue in pattern_values.items()})\n\n        return result\n\n    def pop(self, conf_name, default=None):\n        \"\"\"\n        Remove the conf name passed.\n        \"\"\"\n        pattern, name = self._split_pattern_name(conf_name)\n        return self._pattern_confs.get(pattern, Conf()).pop(name, default=default)\n\n    @staticmethod\n    def _split_pattern_name(pattern_name):\n        if pattern_name.count(\":\") >= 2:\n            pattern, name = pattern_name.split(\":\", 1)\n        else:\n            pattern, name = None, pattern_name\n        return pattern, name\n\n    def get_conanfile_conf(self, ref, is_consumer=False):\n        \"\"\" computes package-specific Conf\n        it is only called when conanfile.buildenv is called\n        the last one found in the profile file has top priority\n        \"\"\"\n        result = Conf()\n        for pattern, conf in self._pattern_confs.items():\n            if pattern is None or ref_matches(ref, pattern, is_consumer):\n                # Latest declared has priority, copy() necessary to not destroy data\n                result = conf.copy().compose_conf(result)\n        return result\n\n    def update_conf_definition(self, other):\n        \"\"\"\n        :type other: ConfDefinition\n        :param other: The argument profile has priority/precedence over the current one.\n        \"\"\"\n        for pattern, conf in other._pattern_confs.items():\n            self._update_conf_definition(pattern, conf)\n\n    def _update_conf_definition(self, pattern, conf):\n        existing = self._pattern_confs.get(pattern)\n        if existing:\n            self._pattern_confs[pattern] = conf.compose_conf(existing)\n        else:\n            self._pattern_confs[pattern] = conf\n\n    def rebase_conf_definition(self, global_conf):\n        \"\"\"\n        for taking the new global.conf and composing with the profile [conf]\n        :type global_conf: ConfDefinition\n        \"\"\"\n        result = ConfDefinition()\n        # Do not add ``core.xxx`` configuration to profiles\n        for k, v in global_conf._pattern_confs.items():\n            result._pattern_confs[k] = v.filter_core()\n        result.update_conf_definition(self)\n        self._pattern_confs = result._pattern_confs\n        return\n\n    def update(self, key, value, profile=False, method=\"define\"):\n        \"\"\"\n        Define/append/prepend/unset any Conf line\n        >> update(\"tools.build:verbosity\", \"verbose\")\n        \"\"\"\n        pattern, name = self._split_pattern_name(key)\n\n        if not _is_profile_module(name):\n            if profile:\n                raise ConanException(\"[conf] '{}' not allowed in profiles\".format(key))\n            if pattern is not None:\n                raise ConanException(\"Conf '{}' cannot have a package pattern\".format(key))\n\n        # strip whitespaces before/after =\n        # values are not strip() unless they are a path, to preserve potential whitespaces\n        name = name.strip()\n\n        # When loading from profile file, latest line has priority\n        conf = Conf()\n        if method == \"unset\":\n            conf.unset(name)\n        else:\n            getattr(conf, method)(name, value)\n        # Update\n        self._update_conf_definition(pattern, conf)\n\n    def dumps(self):\n        result = []\n        for pattern, conf in self._pattern_confs.items():\n            if pattern is None:\n                result.append(conf.dumps())\n            else:\n                result.append(\"\\n\".join(\"{}:{}\".format(pattern, line) if line else \"\"\n                                        for line in conf.dumps().splitlines()))\n        if result:\n            result.append(\"\")\n        return \"\\n\".join(result)\n\n    def serialize(self):\n        result = {}\n        for pattern, conf in self._pattern_confs.items():\n            if pattern is None:\n                result.update(conf.serialize())\n            else:\n                for k, v in conf.serialize().items():\n                    result[f\"{pattern}:{k}\"] = v\n        return result\n\n    @staticmethod\n    def _get_evaluated_value(_v):\n        \"\"\"\n        Function to avoid eval() catching local variables\n        \"\"\"\n        try:\n            value = eval(_v)  # This destroys Windows path strings with backslash\n        except (Exception,):  # It means eval() failed because of a string without quotes\n            value = _v.strip()\n        else:\n            if not isinstance(value, (numbers.Number, bool, dict, list, set, tuple)) \\\n                    and value is not None:\n                # If it is quoted string we respect it as-is\n                value = _v.strip()\n        return value\n\n    def loads(self, text, profile=False):\n        self._pattern_confs = {}\n\n        for line in text.splitlines():\n            line = line.strip()\n            if not line or line.startswith(\"#\"):\n                continue\n            for op, method in ConfDefinition.actions:\n                tokens = line.split(op, 1)\n                if len(tokens) != 2:\n                    continue\n                pattern_name, value = tokens\n                _, name = self._split_pattern_name(pattern_name)\n                # We only implement str type at the moment\n                isstr = _BUILT_IN_CONFS_TYPES.get(name) is str\n                parsed_value = value.strip() if isstr else ConfDefinition._get_evaluated_value(value)\n                self.update(pattern_name, parsed_value, profile=profile, method=method)\n                break\n            else:\n                raise ConanException(\"Bad conf definition: {}\".format(line))\n\n    def validate(self):\n        for conf in self._pattern_confs.values():\n            conf.validate()\n\n    def clear(self):\n        self._pattern_confs.clear()\n\n\ndef load_global_conf(home_folder):\n    home_paths = HomePaths(home_folder)\n    global_conf_path = home_paths.global_conf_path\n    new_config = ConfDefinition()\n    if os.path.exists(global_conf_path):\n        text = load(global_conf_path)\n        distro = None\n        if platform.system() in [\"Linux\", \"FreeBSD\"]:\n            import distro\n        template = Environment(loader=FileSystemLoader(home_folder)).from_string(text)\n        home_folder = home_folder.replace(\"\\\\\", \"/\")\n        from conan import conan_version\n        content = template.render({\"platform\": platform, \"os\": os, \"distro\": distro,\n                                   \"conan_version\": conan_version,\n                                   \"conan_home_folder\": home_folder,\n                                   \"detect_api\": detect_api,\n                                   \"hashlib\": hashlib})\n        new_config.loads(content)\n    else:  # creation of a blank global.conf file for user convenience\n        default_global_conf = textwrap.dedent(\"\"\"\\\n            # Core configuration (type 'conan config list' to list possible values)\n            # e.g, for CI systems, to raise if user input would block\n            # core:non_interactive = True\n            # some tools.xxx config also possible, though generally better in profiles\n            # tools.android:ndk_path = my/path/to/android/ndk\n            \"\"\")\n        save(global_conf_path, default_global_conf)\n    return new_config\n"
  },
  {
    "path": "conan/internal/model/cpp_info.py",
    "content": "import copy\nimport glob\nimport json\nimport os\nimport re\nfrom collections import OrderedDict, defaultdict\n\nfrom conan.api.output import ConanOutput\nfrom conan.errors import ConanException\nfrom conan.internal.model.pkg_type import PackageType\nfrom conan.internal.util.files import load, save\n\n_DIRS_VAR_NAMES = [\"_includedirs\", \"_srcdirs\", \"_libdirs\", \"_resdirs\", \"_bindirs\", \"_builddirs\",\n                   \"_frameworkdirs\", \"_objects\"]\n_FIELD_VAR_NAMES = [\"_system_libs\", \"_package_framework\", \"_frameworks\", \"_libs\", \"_defines\",\n                    \"_cflags\", \"_cxxflags\", \"_sharedlinkflags\", \"_exelinkflags\", \"_sources\"]\n_ALL_NAMES = _DIRS_VAR_NAMES + _FIELD_VAR_NAMES\n_SINGLE_VALUE_VARS = \"_type\", \"_exe\", \"_location\", \"_link_location\", \"_languages\"\n\n\nclass MockInfoProperty:\n    \"\"\"\n    # TODO: Remove in 2.X\n    to mock user_info and env_info\n    \"\"\"\n    counter = {}\n    package = None\n\n    def __init__(self, name):\n        self._name = name\n\n    @staticmethod\n    def message():\n        if not MockInfoProperty.counter:\n            return\n        ConanOutput().warning(\"Usage of deprecated Conan 1.X features that will be removed in \"\n                              \"Conan 2.X:\", warn_tag=\"deprecated\")\n        for k, v in MockInfoProperty.counter.items():\n            ConanOutput().warning(f\"    '{k}' used in: {', '.join(v)}\", warn_tag=\"deprecated\")\n        MockInfoProperty.counter = {}\n\n    def __getitem__(self, key):\n        MockInfoProperty.counter.setdefault(self._name, set()).add(self.package)\n        return []\n\n    def __setitem__(self, key, value):\n        MockInfoProperty.counter.setdefault(self._name, set()).add(self.package)\n\n    def __getattr__(self, attr):\n        MockInfoProperty.counter.setdefault(self._name, set()).add(self.package)\n        return []\n\n    def __setattr__(self, attr, value):\n        if attr != \"_name\":\n            MockInfoProperty.counter.setdefault(self._name, set()).add(self.package)\n        return super(MockInfoProperty, self).__setattr__(attr, value)\n\n\nclass _Component:\n\n    def __init__(self, set_defaults=False):\n        # ###### PROPERTIES\n        self._properties = None\n\n        # ###### DIRECTORIES\n        self._includedirs = None  # Ordered list of include paths\n        self._srcdirs = None  # Ordered list of source paths\n        self._libdirs = None  # Directories to find libraries\n        self._resdirs = None  # Directories to find resources, data, etc\n        self._bindirs = None  # Directories to find executables and shared libs\n        self._builddirs = None\n        self._frameworkdirs = None\n\n        # ##### FIELDS\n        self._system_libs = None  # Ordered list of system libraries\n        self._frameworks = None  # system Apple OS frameworks\n        self._package_framework = None  # any other frameworks\n        self._libs = None  # The libs to link against\n        self._defines = None  # preprocessor definitions\n        self._cflags = None  # pure C flags\n        self._cxxflags = None  # C++ compilation flags\n        self._sharedlinkflags = None  # linker flags\n        self._exelinkflags = None  # linker flags\n        self._objects = None  # linker flags\n        self._sources = None  # source files\n        self._exe = None  # application executable, only 1 allowed, following CPS\n        self._languages = None\n\n        self._sysroot = None\n        self._requires = None\n\n        # LEGACY 1.X fields, can be removed in 2.X\n        self.names = MockInfoProperty(\"cpp_info.names\")\n        self.filenames = MockInfoProperty(\"cpp_info.filenames\")\n        self.build_modules = MockInfoProperty(\"cpp_info.build_modules\")\n\n        if set_defaults:\n            self.includedirs = [\"include\"]\n            self.libdirs = [\"lib\"]\n            self.bindirs = [\"bin\"]\n\n        # CPS\n        self._type = None\n        self._location = None\n        self._link_location = None\n\n    def serialize(self):\n        return {\n            \"includedirs\": self._includedirs,\n            \"srcdirs\": self._srcdirs,\n            \"libdirs\": self._libdirs,\n            \"resdirs\": self._resdirs,\n            \"bindirs\": self._bindirs,\n            \"builddirs\": self._builddirs,\n            \"frameworkdirs\": self._frameworkdirs,\n            \"system_libs\": self._system_libs,\n            \"frameworks\": self._frameworks,\n            \"libs\": self._libs,\n            \"defines\": self._defines,\n            \"cflags\": self._cflags,\n            \"cxxflags\": self._cxxflags,\n            \"sharedlinkflags\": self._sharedlinkflags,\n            \"exelinkflags\": self._exelinkflags,\n            \"objects\": self._objects,\n            \"sources\": self._sources,\n            \"sysroot\": self._sysroot,\n            \"requires\": self._requires,\n            \"properties\": self._properties,\n            \"exe\": self._exe,  # single exe, incompatible with libs\n            \"type\": str(self._type) if self._type else None,\n            \"location\": self._location,\n            \"link_location\": self._link_location,\n            \"languages\": self._languages\n        }\n\n    @staticmethod\n    def deserialize(contents):\n        result = _Component()\n        for field, value in contents.items():\n            if hasattr(result, field):\n                setattr(result, field, value)\n            else:\n                # If there's on setter, use the internal field, e.g, _properties which has\n                # set_property method, but not a setter\n                setattr(result, f\"_{field}\", value)\n        return result\n\n    def clone(self):\n        # Necessary below for exploding a cpp_info.libs = [lib1, lib2] into components\n        result = _Component()\n        for k, v in vars(self).items():\n            if k.startswith(\"_\"):\n                setattr(result, k, copy.copy(v))\n        return result\n\n    @property\n    def includedirs(self):\n        if self._includedirs is None:\n            self._includedirs = []\n        return self._includedirs\n\n    @includedirs.setter\n    def includedirs(self, value):\n        self._includedirs = value\n\n    @property\n    def srcdirs(self):\n        if self._srcdirs is None:\n            self._srcdirs = []\n        return self._srcdirs\n\n    @srcdirs.setter\n    def srcdirs(self, value):\n        self._srcdirs = value\n\n    @property\n    def libdirs(self):\n        if self._libdirs is None:\n            self._libdirs = []\n        return self._libdirs\n\n    @libdirs.setter\n    def libdirs(self, value):\n        self._libdirs = value\n\n    @property\n    def resdirs(self):\n        if self._resdirs is None:\n            self._resdirs = []\n        return self._resdirs\n\n    @resdirs.setter\n    def resdirs(self, value):\n        self._resdirs = value\n\n    @property\n    def bindirs(self):\n        if self._bindirs is None:\n            self._bindirs = []\n        return self._bindirs\n\n    @bindirs.setter\n    def bindirs(self, value):\n        self._bindirs = value\n\n    @property\n    def builddirs(self):\n        if self._builddirs is None:\n            self._builddirs = []\n        return self._builddirs\n\n    @builddirs.setter\n    def builddirs(self, value):\n        self._builddirs = value\n\n    @property\n    def bindir(self):\n        bindirs = self.bindirs\n        if not bindirs or len(bindirs) != 1:\n            raise ConanException(f\"The bindir property is undefined because bindirs \"\n                                 f\"{'is empty' if not bindirs else 'has more than one element'}.\"\n                                 f\" Consider using the bindirs property.\")\n        return bindirs[0]\n\n    @property\n    def libdir(self):\n        libdirs = self.libdirs\n        if not libdirs or len(libdirs) != 1:\n            raise ConanException(f\"The libdir property is undefined because libdirs \"\n                                 f\"{'is empty' if not libdirs else 'has more than one element'}.\"\n                                 f\" Consider using the libdirs property.\")\n        return libdirs[0]\n\n    @property\n    def includedir(self):\n        includedirs = self.includedirs\n        if not includedirs or len(includedirs) != 1:\n            raise ConanException(f\"The includedir property is undefined because includedirs \"\n                                 f\"{'is empty' if not includedirs else 'has more than one element'}.\"\n                                 f\" Consider using the includedirs property.\")\n        return includedirs[0]\n\n    @property\n    def system_libs(self):\n        if self._system_libs is None:\n            self._system_libs = []\n        return self._system_libs\n\n    @system_libs.setter\n    def system_libs(self, value):\n        self._system_libs = value\n\n    @property\n    def package_framework(self):\n        return self._package_framework\n\n    @package_framework.setter\n    def package_framework(self, value):\n        self._package_framework = value\n\n    @property\n    def frameworks(self):\n        if self._frameworks is None:\n            self._frameworks = []\n        return self._frameworks\n\n    @frameworks.setter\n    def frameworks(self, value):\n        self._frameworks = value\n\n    @property\n    def frameworkdirs(self):\n        if self._frameworkdirs is None:\n            self._frameworkdirs = []\n        return self._frameworkdirs\n\n    @frameworkdirs.setter\n    def frameworkdirs(self, value):\n        self._frameworkdirs = value\n\n    @property\n    def libs(self):\n        if self._libs is None:\n            self._libs = []\n        return self._libs\n\n    @libs.setter\n    def libs(self, value):\n        self._libs = value\n\n    @property\n    def exe(self):\n        return self._exe\n\n    @exe.setter\n    def exe(self, value):\n        self._exe = value\n\n    @property\n    def type(self):\n        return self._type\n\n    @type.setter\n    def type(self, value):\n        self._type = PackageType(value) if value is not None else None\n\n    @property\n    def location(self):\n        return self._location\n\n    @location.setter\n    def location(self, value):\n        self._location = value\n\n    @property\n    def link_location(self):\n        return self._link_location\n\n    @link_location.setter\n    def link_location(self, value):\n        self._link_location = value\n\n    @property\n    def languages(self):\n        return self._languages\n\n    @languages.setter\n    def languages(self, value):\n        self._languages = value\n\n    @property\n    def defines(self):\n        if self._defines is None:\n            self._defines = []\n        return self._defines\n\n    @defines.setter\n    def defines(self, value):\n        self._defines = value\n\n    @property\n    def cflags(self):\n        if self._cflags is None:\n            self._cflags = []\n        return self._cflags\n\n    @cflags.setter\n    def cflags(self, value):\n        self._cflags = value\n\n    @property\n    def cxxflags(self):\n        if self._cxxflags is None:\n            self._cxxflags = []\n        return self._cxxflags\n\n    @cxxflags.setter\n    def cxxflags(self, value):\n        self._cxxflags = value\n\n    @property\n    def sharedlinkflags(self):\n        if self._sharedlinkflags is None:\n            self._sharedlinkflags = []\n        return self._sharedlinkflags\n\n    @sharedlinkflags.setter\n    def sharedlinkflags(self, value):\n        self._sharedlinkflags = value\n\n    @property\n    def exelinkflags(self):\n        if self._exelinkflags is None:\n            self._exelinkflags = []\n        return self._exelinkflags\n\n    @exelinkflags.setter\n    def exelinkflags(self, value):\n        self._exelinkflags = value\n\n    @property\n    def objects(self):\n        if self._objects is None:\n            self._objects = []\n        return self._objects\n\n    @objects.setter\n    def objects(self, value):\n        self._objects = value\n\n    @property\n    def sources(self):\n        if self._sources is None:\n            self._sources = []\n        return self._sources\n\n    @sources.setter\n    def sources(self, value):\n        self._sources = value\n\n    @property\n    def sysroot(self):\n        if self._sysroot is None:\n            self._sysroot = \"\"\n        return self._sysroot\n\n    @sysroot.setter\n    def sysroot(self, value):\n        self._sysroot = value\n\n    @property\n    def requires(self):\n        if self._requires is None:\n            self._requires = []\n        return self._requires\n\n    @requires.setter\n    def requires(self, value):\n        self._requires = value\n\n    @property\n    def required_component_names(self):\n        \"\"\" Names of the required INTERNAL components of the same package (not scoped with ::)\"\"\"\n        if self.requires is None:\n            return []\n        return [r for r in self.requires if \"::\" not in r]\n\n    def set_property(self, property_name, value):\n        if self._properties is None:\n            self._properties = {}\n        self._properties[property_name] = value\n\n    def get_property(self, property_name, check_type=None):\n        if self._properties is None:\n            return None\n        try:\n            value = self._properties[property_name]\n            if check_type is not None and not isinstance(value, check_type):\n                raise ConanException(\n                    f'The expected type for {property_name} is \"{check_type.__name__}\", but \"{type(value).__name__}\" was found')\n            return value\n        except KeyError:\n            pass\n\n    def get_init(self, attribute, default):\n        # Similar to dict.setdefault\n        item = getattr(self, attribute)\n        if item is not None:\n            return item\n        setattr(self, attribute, default)\n        return default\n\n    def merge(self, other, overwrite=False):\n        \"\"\"\n        @param overwrite:\n        @type other: _Component\n        \"\"\"\n        def merge_list(o, d):\n            d.extend(e for e in o if e not in d)\n\n        for varname in _ALL_NAMES:\n            other_values = getattr(other, varname)\n            if other_values is not None:\n                if not overwrite:\n                    current_values = self.get_init(varname, [])\n                    merge_list(other_values, current_values)\n                else:\n                    setattr(self, varname, other_values)\n\n        for varname in _SINGLE_VALUE_VARS:  # To allow editable of .exe/.location\n            other_values = getattr(other, varname)\n            if other_values is not None:\n                # Just overwrite the existing value, not possible to append\n                setattr(self, varname, other_values)\n\n        if other.requires:\n            current_values = self.get_init(\"requires\", [])\n            merge_list(other.requires, current_values)\n\n        if other._properties:\n            current_values = self.get_init(\"_properties\", {})\n            for k, v in other._properties.items():\n                existing = current_values.get(k)\n                if existing is not None and isinstance(existing, list) and not overwrite:\n                    existing.extend(v)\n                else:\n                    current_values[k] = copy.copy(v)\n\n    def set_relative_base_folder(self, folder):\n        for varname in _DIRS_VAR_NAMES:\n            origin = getattr(self, varname)\n            if origin is not None:\n                origin[:] = [os.path.join(folder, el) for el in origin]\n        properties = self._properties\n        if properties is not None:\n            modules = properties.get(\"cmake_build_modules\")  # Only this prop at this moment\n            if modules is not None:\n                assert isinstance(modules, list), \"cmake_build_modules must be a list\"\n                properties[\"cmake_build_modules\"] = [os.path.join(folder, v) for v in modules]\n\n    def deploy_base_folder(self, package_folder, deploy_folder):\n        def relocate(el):\n            rel_path = os.path.relpath(el, package_folder)\n            if rel_path.startswith(\"..\"):\n                # If it is pointing to a folder outside of the package, then do not relocate\n                return el\n            return os.path.join(deploy_folder, rel_path)\n\n        for varname in _DIRS_VAR_NAMES:\n            origin = getattr(self, varname)\n            if origin is not None:\n                origin[:] = [relocate(f) for f in origin]\n        properties = self._properties\n        if properties is not None:\n            modules = properties.get(\"cmake_build_modules\")  # Only this prop at this moment\n            if modules is not None:\n                assert isinstance(modules, list), \"cmake_build_modules must be a list\"\n                properties[\"cmake_build_modules\"] = [relocate(f) for f in modules]\n\n    def parsed_requires(self):\n        return [r.split(\"::\", 1) if \"::\" in r else (None, r) for r in self.requires]\n\n    def _auto_deduce_locations(self, conanfile, library_name):\n\n        def _lib_match_by_glob(dir_, filename):\n            # Run a glob.glob function to find the file given by the filename\n            matches = glob.glob(f\"{dir_}/{filename}\")\n            if matches:\n                return matches\n\n        def _lib_match_by_regex(dir_, pattern):\n            ret = set()\n            # pattern is a regex compiled pattern, so let's iterate each file to find the library\n            files = os.listdir(dir_)\n            for file_name in files:\n                full_path = os.path.join(dir_, file_name)\n                if os.path.isfile(full_path) and pattern.match(file_name):\n                    # Issue: https://github.com/conan-io/conan/issues/17721 (stop resolving symlinks)\n                    ret.add(full_path)\n            return list(ret)\n\n        def _find_matching(dirs, pattern):\n            for d in dirs:\n                if not os.path.exists(d):\n                    continue\n                # If pattern is an exact match\n                if isinstance(pattern, str):\n                    # pattern == filename\n                    lib_found = _lib_match_by_glob(d, pattern)\n                else:\n                    lib_found = _lib_match_by_regex(d, pattern)\n                if lib_found:\n                    if len(lib_found) > 1:\n                        lib_found.sort()\n                        found, _ = os.path.splitext(os.path.basename(lib_found[0]))\n                        if found != libname and found != f\"lib{libname}\":\n                            out.warning(f\"There were several matches for Lib {libname}: {lib_found}\")\n                    return lib_found[0].replace(\"\\\\\", \"/\")\n\n        out = ConanOutput(scope=str(conanfile))\n        pkg_type = conanfile.package_type\n        libdirs = self.libdirs\n        bindirs = self.bindirs\n        libname = self.libs[0]\n        static_location = None\n        shared_location = None\n        dll_location = None\n        deduced_type = None\n        # libname is exactly the pattern, e.g., [\"mylib.a\"] instead of [\"mylib\"]\n        _, ext = os.path.splitext(libname)\n        if ext in (\".lib\", \".a\", \".dll\", \".so\", \".dylib\"):\n            if ext in (\".lib\", \".a\"):\n                static_location = _find_matching(libdirs, libname)\n            elif ext in (\".so\", \".dylib\"):\n                shared_location = _find_matching(libdirs, libname)\n            elif ext == \".dll\":\n                dll_location = _find_matching(bindirs, libname)\n        else:\n            lib_sanitized = re.escape(libname)\n            component_sanitized = re.escape(library_name)\n            # At first, exact match\n            regex_static = re.compile(rf\"(?:lib)?{lib_sanitized}\\.(?:a|lib)\")\n            regex_shared = re.compile(rf\"(?:lib)?{lib_sanitized}\\.(?:so|dylib)\")\n            regex_dll = re.compile(rf\".*(?:{lib_sanitized}|{component_sanitized}).*\\.dll\")\n            static_location = _find_matching(libdirs, regex_static)\n            shared_location = _find_matching(libdirs, regex_shared)\n            if not any([static_location, shared_location]):\n                # Let's extend a little bit the pattern search\n                regex_wider_static = re.compile(rf\"(?:lib)?{lib_sanitized}(?:[._-].+)?\\.(?:a|lib)\")\n                regex_wider_shared = re.compile(rf\"(?:lib)?{lib_sanitized}(?:[._-].+)?\\.(?:so|dylib)\")\n                static_location = _find_matching(libdirs, regex_wider_static)\n                shared_location = _find_matching(libdirs, regex_wider_shared)\n            if static_location or not shared_location:\n                dll_location = _find_matching(bindirs, regex_dll)\n\n        if static_location:\n            if shared_location:\n                out.warning(f\"Lib {libname} has both static {static_location} and \"\n                            f\"shared {shared_location} in the same package\")\n                if self._type is PackageType.STATIC or pkg_type is PackageType.STATIC:\n                    self._location = static_location\n                    deduced_type = PackageType.STATIC\n                else:\n                    self._location = shared_location\n                    deduced_type = PackageType.SHARED\n            elif dll_location:\n                self._location = dll_location\n                self._link_location = static_location\n                deduced_type = PackageType.SHARED\n            else:\n                self._location = static_location\n                deduced_type = PackageType.STATIC\n        elif shared_location:\n            self._location = shared_location\n            deduced_type = PackageType.SHARED\n        elif dll_location:\n            # Only .dll but no link library\n            self._location = dll_location\n            deduced_type = PackageType.SHARED\n        if not self._location:\n            raise ConanException(f\"{conanfile}: Cannot obtain 'location' for library '{libname}' \"\n                                 f\"in {libdirs}. You can specify 'cpp_info.location' directly \"\n                                 f\"or report in github.com/conan-io/conan/issues if you think it \"\n                                 f\"should have been deduced correctly.\")\n        if self._type is not None and self._type != deduced_type:\n            ConanException(f\"{conanfile}: Incorrect deduced type '{deduced_type}' for library\"\n                           f\" '{libname}' that declared .type='{self._type}'\")\n        self._type = deduced_type\n        if self._type != pkg_type:\n            out.warning(f\"Lib {libname} deduced as '{self._type}, but 'package_type={pkg_type}'\")\n\n    def deduce_locations(self, conanfile, component_name=\"\"):\n        name = f'{conanfile} cpp_info.components[\"{component_name}\"]' if component_name \\\n            else f'{conanfile} cpp_info'\n        # executable\n        if self._exe:   # exe is a new field, it should have the correct location\n            if self._type is None:\n                self._type = PackageType.APP\n            if self._type is not PackageType.APP:\n                raise ConanException(f\"{name} incorrect .type {self._type} for .exe {self._exe}\")\n            if self.libs:\n                raise ConanException(f\"{name} has both .exe and .libs\")\n            if not self.location:\n                raise ConanException(f\"{name} has .exe and no .location\")\n            return\n        if self._type is PackageType.APP:\n            # old school Conan application packages without defining an exe, not an error\n            return\n\n        # libraries\n        if len(self.libs) > 1:  # it could be 0, as the libs itself is not necessary\n            raise ConanException(f\"{name} has more than 1 library in .libs: {self.libs}, \"\n                                 \"cannot deduce locations\")\n        # fully defined by user in conanfile, nothing to do.\n        if self._location or self._link_location:\n            if self._type is None or self._type not in [PackageType.SHARED, PackageType.STATIC]:\n                raise ConanException(f\"{name} location defined without defined library type\")\n            return\n\n        # possible header only, which allows also an empty header-only only for common flags\n        if len(self.libs) == 0:\n            if self._type is None:\n                self._type = PackageType.HEADER\n            return\n\n        # automatic location deduction from a single .lib=[\"lib\"]\n        if self._type is not None and self._type not in [PackageType.SHARED, PackageType.STATIC]:\n            raise ConanException(f\"{name} has a library but .type {self._type} is not static/shared\")\n\n        # If no location is defined, it's time to guess the location\n        self._auto_deduce_locations(conanfile, library_name=component_name or conanfile.ref.name)\n\n\nclass CppInfo:\n\n    def __init__(self, set_defaults=False):\n        self.components = defaultdict(lambda: _Component(set_defaults))\n        self.default_components = None\n        self._package = _Component(set_defaults)\n\n    def __getattr__(self, attr):\n        # all cpp_info.xxx of not defined things will go to the global package\n        return getattr(self._package, attr)\n\n    def __setattr__(self, attr, value):\n        if attr in (\"components\", \"default_components\", \"_package\", \"_aggregated\", \"required_components\"):\n            super(CppInfo, self).__setattr__(attr, value)\n        else:\n            setattr(self._package, attr, value)\n\n    def serialize(self):\n        ret = {\"root\": self._package.serialize()}\n        if self.default_components:\n            ret[\"default_components\"] = self.default_components\n        for component_name, info in self.components.items():\n            ret[component_name] = info.serialize()\n        return ret\n\n    def deserialize(self, content):\n        self._package = _Component.deserialize(content.pop(\"root\"))\n        self.default_components = content.get(\"default_components\")\n        for component_name, info in content.items():\n            self.components[component_name] = _Component.deserialize(info)\n        return self\n\n    def save(self, path):\n        save(path, json.dumps(self.serialize()))\n\n    def load(self, path):\n        content = json.loads(load(path))\n        return self.deserialize(content)\n\n    @property\n    def has_components(self):\n        return len(self.components) > 0\n\n    def merge(self, other, overwrite=False):\n        \"\"\"Merge 'other' into self. 'other' can be an old cpp_info object\n        Used to merge Layout source + build cpp objects info (editables)\n        @type other: CppInfo\n        @param other: The other CppInfo to merge\n        @param overwrite: New values from other overwrite the existing ones\n        \"\"\"\n        # Global merge\n        self._package.merge(other._package, overwrite)\n        # sysroot only of package, not components, first defined wins\n        self._package.sysroot = self._package.sysroot or other._package.sysroot\n        # COMPONENTS\n        for cname, c in other.components.items():\n            # Make sure each component created on the fly does not bring new defaults\n            self.components.setdefault(cname, _Component(set_defaults=False)).merge(c, overwrite)\n\n    def set_relative_base_folder(self, folder):\n        \"\"\"Prepend the folder to all the directories definitions, that are relative\"\"\"\n        self._package.set_relative_base_folder(folder)\n        for component in self.components.values():\n            component.set_relative_base_folder(folder)\n\n    def deploy_base_folder(self, package_folder, deploy_folder):\n        \"\"\"Prepend the folder to all the directories\"\"\"\n        self._package.deploy_base_folder(package_folder, deploy_folder)\n        for component in self.components.values():\n            component.deploy_base_folder(package_folder, deploy_folder)\n\n    def get_sorted_components(self):\n        \"\"\"\n        Order the components taking into account if they depend on another component in the\n        same package (not scoped with ::). First less dependant.\n\n        :return: ``OrderedDict`` {component_name: component}\n        \"\"\"\n        result = OrderedDict()\n        opened = self.components.copy()\n        while opened:\n            new_open = OrderedDict()\n            for name, c in opened.items():\n                if not any(n in opened for n in c.required_component_names):\n                    result[name] = c\n                else:\n                    new_open[name] = c\n            if len(opened) == len(new_open):\n                msg = [\"There is a dependency loop in 'self.cpp_info.components' requires:\"]\n                for name, c in opened.items():\n                    loop_reqs = \", \".join(n for n in c.required_component_names if n in opened)\n                    msg.append(f\"   {name} requires {loop_reqs}\")\n                raise ConanException(\"\\n\".join(msg))\n            opened = new_open\n        return result\n\n    def aggregated_components(self):\n        \"\"\"Aggregates all the components as global values, returning a new CppInfo\n        Used by many generators to obtain a unified, aggregated view of all components\n        \"\"\"\n        # This method had caching before, but after a ``--deployer``, the package changes\n        # location, and this caching was invalid, still pointing to the Conan cache instead of\n        # the deployed\n        if self.has_components:\n            result = _Component()\n            # Reversed to make more dependant first\n            for component in reversed(self.get_sorted_components().values()):\n                result.merge(component)\n            # NOTE: The properties are not aggregated because they might refer only to the\n            # component like \"cmake_target_name\" describing the target name FOR THE component\n            # not the namespace.\n            # FIXME: What to do about sysroot?\n            result._properties = copy.copy(self._package._properties)\n        else:\n            result = copy.copy(self._package)\n        aggregated = CppInfo()\n        aggregated._package = result\n        return aggregated\n\n    def check_component_requires(self, conanfile):\n        \"\"\" quality check for component requires, called by BinaryInstaller after package_info()\n        - Check that all recipe ``requires`` are used if consumer recipe explicit opt-in to use\n          component requires\n        - Check that component external dep::comp dependency \"dep\" is a recipe \"requires\"\n        - Check that every internal component require actually exist\n        It doesn't check that external components do exist\n        \"\"\"\n        if not self.has_components and not self._package.requires:\n            return\n        # Accumulate all external requires\n        comps = self.required_components\n        missing_internal = [c[1] for c in comps if c[0] is None and c[1] not in self.components]\n        if missing_internal:\n            msg = f\"{conanfile}: package_info(): There are '(cpp_info/components).requires' to \" \\\n                  f\"other internal components that are not defined: {missing_internal}\"\n            raise ConanException(msg)\n        external = [c[0] for c in comps if c[0] is not None]\n        if not external:\n            return\n        # Only direct host (not test) dependencies can define required components\n        # We use conanfile.dependencies to use the already replaced ones by \"replace_requires\"\n        # So consumers can keep their ``self.cpp_info.requires = [\"pkg_name::comp\"]``\n        direct_dependencies = [r.ref.name for r, d in conanfile.dependencies.items() if r.direct\n                               and not r.build and not r.is_test and r.visible and not r.override]\n\n        for e in external:\n            if e not in direct_dependencies:\n                msg = f\"{conanfile}: package_info(): There are '(cpp_info/components).requires' \" \\\n                      f\"that includes package '{e}::', but such package is not a a direct \" \\\n                      f\"requirement of the recipe\"\n                raise ConanException(msg)\n        # TODO: discuss if there are cases that something is required but not transitive\n        for e in direct_dependencies:\n            if e not in external:\n                msg = f\"{conanfile}: package_info(): The direct dependency '{e}' is not used by \" \\\n                      f\"any '(cpp_info/components).requires'.\"\n                raise ConanException(msg)\n\n    @property\n    def required_components(self):\n        \"\"\"Returns a list of tuples with (require, component_name) required by the package\n        If the require is internal (to another component), the require will be None\"\"\"\n        # FIXME: Cache the value\n        # First aggregate without repetition, respecting the order\n        ret = [r for r in self._package.requires]\n        for comp in self.components.values():\n            for r in comp.requires:\n                if r not in ret:\n                    ret.append(r)\n        # Then split the names\n        ret = [r.split(\"::\", 1) if \"::\" in r else (None, r) for r in ret]\n        return ret\n\n    def deduce_full_cpp_info(self, conanfile):\n        if conanfile.cpp_info.has_components and (conanfile.cpp_info.exe or conanfile.cpp_info.libs):\n            raise ConanException(f\"{conanfile}: 'cpp_info' contains components and .exe or .libs\")\n\n        result = CppInfo()  # clone it\n        if self.libs and len(self.libs) > 1:  # expand in multiple components\n            ConanOutput(scope=str(conanfile)).warning(\n                \"The 'cpp_info.libs' contain more than 1 library. \"\n                \"Define 'cpp_info.components' instead.\", warn_tag=\"deprecated\")\n            assert not self.components, f\"{conanfile} cpp_info shouldn't have .libs and .components\"\n            common = self._package.clone()\n            common.libs = []\n            common.type = str(PackageType.HEADER)  # the type of components is a string!\n            result.components[\"_common\"] = common\n\n            for lib in self.libs:\n                c = _Component()  # Do not do a full clone, we don't need the properties\n                c.type = self.type\n                c.includedirs = self.includedirs\n                c.libdirs = self.libdirs\n                c.bindirs = self.bindirs\n                c.libs = [lib]\n                c.requires = [\"_common\"]\n                result.components[f\"_{lib}\"] = c\n        else:\n            result._package = self._package.clone()\n            result.default_components = self.default_components\n            new_components = {}\n            for k, v in self.components.items():\n                if v.libs and len(v.libs) > 1:\n                    ConanOutput(scope=str(conanfile)).warning(\n                        f\"The 'cpp_info.components[{k}] contains more than 1 library. \"\n                        \"Define 1 component for each library instead.\", warn_tag=\"deprecated\")\n                    # Now the root, empty one\n                    common = v.clone()\n                    common.libs = []\n                    common.type = str(PackageType.HEADER)  # the type of components is a string!\n                    new_components[k] = common\n\n                    for lib in v.libs:\n                        c = _Component()\n                        c.type = v.type\n                        c.includedirs = v.includedirs\n                        c.libdirs = v.libdirs\n                        c.bindirs = v.bindirs\n                        c.libs = [lib]\n                        new_components[f\"_{k}_{lib}\"] = c\n                        common.requires.append(f\"_{k}_{lib}\")\n                else:\n                    new_components[k] = v.clone()\n            result.components = new_components\n\n        result._package.deduce_locations(conanfile)\n        for comp_name, comp in result.components.items():\n            comp.deduce_locations(conanfile, component_name=comp_name)\n\n        return result\n"
  },
  {
    "path": "conan/internal/model/dependencies.py",
    "content": "from collections import OrderedDict\n\nfrom conan.api.model import RecipeReference\nfrom conan.errors import ConanException\nfrom conan.internal.graph.graph import RECIPE_PLATFORM\nfrom conan.internal.model.conanfile_interface import ConanFileInterface\n\n\nclass UserRequirementsDict:\n    \"\"\" user facing dict to allow access of dependencies by name\n    \"\"\"\n    def __init__(self, data, require_filter=None):\n        self._data = data  # dict-like\n        self._require_filter = require_filter  # dict {trait: value} for requirements\n\n    def filter(self, require_filter):\n        def filter_fn(require):\n            for k, v in require_filter.items():\n                if getattr(require, k) != v:\n                    return False\n            return True\n        data = OrderedDict((k, v) for k, v in self._data.items() if filter_fn(k))\n        return UserRequirementsDict(data, require_filter)\n\n    def __bool__(self):\n        return bool(self._data)\n\n    def get(self, ref, build=None, **kwargs):\n        return self._get(ref, build, **kwargs)[1]\n\n    def _get(self, ref, build=None, **kwargs):\n        if build is None:\n            current_filters = self._require_filter or {}\n            if \"build\" not in current_filters:\n                # By default we search in the \"host\" context\n                kwargs[\"build\"] = False\n        else:\n            kwargs[\"build\"] = build\n        data = self.filter(kwargs)\n        ret = []\n        if \"/\" in ref:\n            # FIXME: Validate reference\n            ref = RecipeReference.loads(ref)\n            for require, value in data.items():\n                if require.ref == ref:\n                    ret.append((require, value))\n        else:\n            name = ref\n            for require, value in data.items():\n                if require.ref.name == name:\n                    ret.append((require, value))\n        if len(ret) > 1:\n            current_filters = data._require_filter or \"{}\"\n            requires = \"\\n\".join([\"- {}\".format(require) for require, _ in ret])\n            raise ConanException(\"There are more than one requires matching the specified filters:\"\n                                 \" {}\\n{}\".format(current_filters, requires))\n        if not ret:\n            raise KeyError(\"'{}' not found in the dependency set\".format(ref))\n\n        key, value = ret[0]\n        return key, value\n\n    def __getitem__(self, name):\n        return self.get(name)\n\n    def __delitem__(self, name):\n        r, _ = self._get(name)\n        del self._data[r]\n\n    def items(self):\n        return self._data.items()\n\n    def values(self):\n        return self._data.values()\n\n    def __contains__(self, item):\n        try:\n            self.get(item)\n            return True\n        except KeyError:\n            return False\n        except ConanException:\n            # ConanException is raised when there are more than one matching the filters\n            # so it's definitely in the dict\n            return True\n\n\nclass ConanFileDependencies(UserRequirementsDict):\n\n    @staticmethod\n    def from_node(node):\n        d = OrderedDict((require, ConanFileInterface(transitive.node.conanfile))\n                        for require, transitive in node.transitive_deps.items())\n        if node.replaced_requires:\n            cant_be_removed = set()\n            for old_req, new_req in node.replaced_requires.items():\n                # Two different replaced_requires can point to the same real requirement\n                existing = d[new_req]\n                added_req = new_req.copy_requirement()\n                added_req.ref = RecipeReference.loads(old_req)\n                d[added_req] = existing\n                if new_req.ref.name == added_req.ref.name:\n                    cant_be_removed.add(new_req)\n            # Now remove the replaced from dependencies dict\n            for new_req in node.replaced_requires.values():\n                if new_req not in cant_be_removed:\n                    d.pop(new_req, None)\n        return ConanFileDependencies(d)\n\n    def filter(self, require_filter, remove_system=True):\n        # FIXME: Copy of hte above, to return ConanFileDependencies class object\n        def filter_fn(require):\n            for k, v in require_filter.items():\n                if getattr(require, k) != v:\n                    return False\n            return True\n\n        data = OrderedDict((k, v) for k, v in self._data.items() if filter_fn(k))\n        if remove_system:\n            data = OrderedDict((k, v) for k, v in data.items() if v.recipe != RECIPE_PLATFORM)\n        return ConanFileDependencies(data, require_filter)\n\n    def transitive_requires(self, other):\n        \"\"\"\n        :type other: ConanFileDependencies\n        \"\"\"\n        data = OrderedDict()\n        for k, v in self._data.items():\n            for otherk, otherv in other._data.items():\n                if v == otherv:\n                    data[otherk] = v  # Use otherk to respect original replace_requires\n        return ConanFileDependencies(data)\n\n    @property\n    def topological_sort(self):\n        # Return first independent nodes, final ones are the more direct deps\n        result = OrderedDict()\n        opened = self._data.copy()\n\n        while opened:\n            opened_values = set(opened.values())\n            new_opened = OrderedDict()\n            for req, conanfile in opened.items():\n                deps_in_opened = any(d in opened_values for d in conanfile.dependencies.values())\n                if deps_in_opened:\n                    new_opened[req] = conanfile  # keep it for next iteration\n                else:\n                    result[req] = conanfile  # No dependencies in open set!\n\n            opened = new_opened\n        return ConanFileDependencies(result)\n\n    @property\n    def direct_host(self):\n        return self.filter({\"build\": False, \"direct\": True, \"test\": False, \"skip\": False})\n\n    @property\n    def direct_build(self):\n        return self.filter({\"build\": True, \"direct\": True})\n\n    @property\n    def host(self):\n        return self.filter({\"build\": False, \"test\": False, \"skip\": False})\n\n    @property\n    def test(self):\n        # Not needed a direct_test because they are visible=False so only the direct consumer\n        # will have them in the graph\n        return self.filter({\"build\": False, \"test\": True, \"skip\": False})\n\n    @property\n    def build(self):\n        return self.filter({\"build\": True})\n\n\ndef get_transitive_requires(consumer, dependency):\n    \"\"\" the transitive requires that we need are the consumer ones, not the current dependencey\n    ones, so we get the current ones, then look for them in the consumer, and return those\n    \"\"\"\n    # The build dependencies cannot be transitive in generators like CMakeDeps,\n    # even if users make them visible\n    pkg_deps = dependency.dependencies.filter({\"direct\": True, \"build\": False})\n    # First we filter the skipped dependencies\n    result = consumer.dependencies.filter({\"skip\": False})\n    # and we keep those that are really dependencies of the current package\n    result = result.transitive_requires(pkg_deps)\n    return result\n"
  },
  {
    "path": "conan/internal/model/info.py",
    "content": "import hashlib\n\nfrom conan.errors import ConanException\nfrom conan.internal.model.dependencies import UserRequirementsDict\nfrom conan.api.model import PkgReference\nfrom conan.api.model import RecipeReference\nfrom conan.internal.util.config_parser import TextINIParse\n\n\nclass _VersionRepr:\n    \"\"\"Class to return strings like 1.Y.Z from a Version object\"\"\"\n\n    def __init__(self, version):\n        self._version = version\n\n    def stable(self):\n        if self._version.major == 0:\n            return str(self._version)\n        else:\n            return self.major()\n\n    def major(self):\n        # This check is to avoid breaking non-integer major versions\n        # for legacy reasons. Users are warned against using them\n        if not isinstance(self._version.major.value, int):\n            return str(self._version.major)\n        return \".\".join([str(self._version.major), 'Y', 'Z'])\n\n    def minor(self):\n        # This check is to avoid breaking non-integer major versions\n        # for legacy reasons. Users are warned against using them\n        if not isinstance(self._version.major.value, int):\n            return str(self._version.major)\n\n        v0 = str(self._version.major)\n        v1 = str(self._version.minor) if self._version.minor is not None else \"0\"\n        return \".\".join([v0, v1, 'Z'])\n\n    def patch(self):\n        # This check is to avoid breaking non-integer major versions\n        # for legacy reasons. Users are warned against using them\n        if not isinstance(self._version.major.value, int):\n            return str(self._version.major)\n\n        v0 = str(self._version.major)\n        v1 = str(self._version.minor) if self._version.minor is not None else \"0\"\n        v2 = str(self._version.patch) if self._version.patch is not None else \"0\"\n        return \".\".join([v0, v1, v2])\n\n    def pre(self):\n        # This check is to avoid breaking non-integer major versions\n        # for legacy reasons. Users are warned against using them\n        if not isinstance(self._version.major.value, int):\n            return str(self._version.major)\n\n        v0 = str(self._version.major)\n        v1 = str(self._version.minor) if self._version.minor is not None else \"0\"\n        v2 = str(self._version.patch) if self._version.patch is not None else \"0\"\n        v = \".\".join([v0, v1, v2])\n        if self._version.pre is not None:\n            v += \"-%s\" % self._version.pre\n        return v\n\n    @property\n    def build(self):\n        return self._version.build if self._version.build is not None else \"\"\n\n\nclass RequirementInfo:\n\n    def __init__(self, ref, package_id, default_package_id_mode):\n        self._ref = ref\n        self._package_id = package_id\n        self.name = self.version = self.user = self.channel = self.package_id = None\n        self.recipe_revision = None\n        self.package_id_mode = default_package_id_mode\n\n        try:\n            func_package_id_mode = getattr(self, default_package_id_mode)\n        except AttributeError:\n            raise ConanException(f\"require {self._ref} package_id_mode='{default_package_id_mode}' \"\n                                 \"is not a known package_id_mode\")\n        else:\n            func_package_id_mode()\n\n    def copy(self):\n        # Useful for build_id()\n        result = RequirementInfo(self._ref, self._package_id, \"unrelated_mode\")\n        for f in (\"name\", \"version\", \"user\", \"channel\", \"recipe_revision\", \"package_id\"):\n            setattr(result, f, getattr(self, f))\n        return result\n\n    def pref(self):\n        ref = RecipeReference(self.name, self.version, self.user, self.channel, self.recipe_revision)\n        return PkgReference(ref, self.package_id)\n\n    def dumps(self):\n        return repr(self.pref())\n\n    def unrelated_mode(self):\n        self.name = self.version = self.user = self.channel = self.package_id = None\n        self.recipe_revision = None\n\n    def semver_mode(self):\n        self.name = self._ref.name\n        self.version = _VersionRepr(self._ref.version).stable()\n        self.user = self._ref.user\n        self.channel = self._ref.channel\n        self.package_id = None\n        self.recipe_revision = None\n\n    def full_version_mode(self):\n        self.name = self._ref.name\n        self.version = self._ref.version\n        self.user = self._ref.user\n        self.channel = self._ref.channel\n        self.package_id = None\n        self.recipe_revision = None\n\n    def patch_mode(self):\n        self.name = self._ref.name\n        self.version = _VersionRepr(self._ref.version).patch()\n        self.user = self._ref.user\n        self.channel = self._ref.channel\n        self.package_id = None\n        self.recipe_revision = None\n\n    def minor_mode(self):\n        self.name = self._ref.name\n        self.version = _VersionRepr(self._ref.version).minor()\n        self.user = self._ref.user\n        self.channel = self._ref.channel\n        self.package_id = None\n        self.recipe_revision = None\n\n    def major_mode(self):\n        self.name = self._ref.name\n        self.version = _VersionRepr(self._ref.version).major()\n        self.user = self._ref.user\n        self.channel = self._ref.channel\n        self.package_id = None\n        self.recipe_revision = None\n\n    def full_package_mode(self):\n        self.name = self._ref.name\n        self.version = self._ref.version\n        self.user = self._ref.user\n        self.channel = self._ref.channel\n        self.package_id = self._package_id\n        self.recipe_revision = None\n\n    def revision_mode(self):\n        self.name = self._ref.name\n        self.version = self._ref.version\n        self.user = self._ref.user\n        self.channel = self._ref.channel\n        self.package_id = None\n        self.recipe_revision = self._ref.revision if self._ref.revision != \"platform\" else None\n\n    def full_mode(self):\n        self.name = self._ref.name\n        self.version = self._ref.version\n        self.user = self._ref.user\n        self.channel = self._ref.channel\n        self.package_id = self._package_id\n        self.recipe_revision = self._ref.revision if self._ref.revision != \"platform\" else None\n\n    full_recipe_mode = full_version_mode\n    recipe_revision_mode = full_mode  # to not break everything and help in upgrade\n\n\nclass RequirementsInfo(UserRequirementsDict):\n\n    def copy(self):\n        # For build_id() implementation\n        data = {pref: req_info.copy() for pref, req_info in self._data.items()}\n        return RequirementsInfo(data)\n\n    def serialize(self):\n        return [r.dumps() for r in self._data.values()]\n\n    def __bool__(self):\n        return bool(self._data)\n\n    def clear(self):\n        self._data = {}\n\n    def remove(self, *args):\n        for name in args:\n            del self[name]\n\n    @property\n    def pkg_names(self):\n        return [r.ref.name for r in self._data.keys()]\n\n    def dumps(self):\n        result = []\n        for req_info in self._data.values():\n            dumped = req_info.dumps()\n            if dumped:\n                result.append(dumped)\n        return \"\\n\".join(sorted(result))\n\n    def unrelated_mode(self):\n        self.clear()\n\n    def semver_mode(self):\n        for r in self._data.values():\n            r.semver_mode()\n\n    def patch_mode(self):\n        for r in self._data.values():\n            r.patch_mode()\n\n    def minor_mode(self):\n        for r in self._data.values():\n            r.minor_mode()\n\n    def major_mode(self):\n        for r in self._data.values():\n            r.major_mode()\n\n    def full_version_mode(self):\n        for r in self._data.values():\n            r.full_version_mode()\n\n    def full_recipe_mode(self):\n        for r in self._data.values():\n            r.full_recipe_mode()\n\n    def full_package_mode(self):\n        for r in self._data.values():\n            r.full_package_mode()\n\n    def revision_mode(self):\n        for r in self._data.values():\n            r.revision_mode()\n\n    def full_mode(self):\n        for r in self._data.values():\n            r.full_mode()\n\n    recipe_revision_mode = full_mode  # to not break everything and help in upgrade\n\n\nclass PythonRequiresInfo:\n\n    def __init__(self, refs, default_package_id_mode):\n        self._default_package_id_mode = default_package_id_mode\n        if refs:\n            self._refs = [RequirementInfo(r, None,\n                                          default_package_id_mode=mode or default_package_id_mode)\n                          for r, mode in sorted(refs.items())]\n        else:\n            self._refs = None\n\n    def copy(self):\n        # For build_id() implementation\n        refs = {r._ref: r.package_id_mode for r in self._refs} if self._refs else None\n        return PythonRequiresInfo(refs, self._default_package_id_mode)\n\n    def serialize(self):\n        return [r.dumps() for r in self._refs or []]\n\n    def __bool__(self):\n        return bool(self._refs)\n\n    def clear(self):\n        self._refs = None\n\n    def dumps(self):\n        return '\\n'.join(r.dumps() for r in self._refs)\n\n    def unrelated_mode(self):\n        self._refs = None\n\n    def semver_mode(self):\n        for r in self._refs:\n            r.semver_mode()\n\n    def patch_mode(self):\n        for r in self._refs:\n            r.patch_mode()\n\n    def minor_mode(self):\n        for r in self._refs:\n            r.minor_mode()\n\n    def major_mode(self):\n        for r in self._refs:\n            r.major_mode()\n\n    def full_version_mode(self):\n        for r in self._refs:\n            r.full_version_mode()\n\n    def full_recipe_mode(self):\n        for r in self._refs:\n            r.full_recipe_mode()\n\n    def revision_mode(self):\n        for r in self._refs:\n            r.revision_mode()\n\n    def full_mode(self):\n        for r in self._refs:\n            r.full_mode()\n\n    recipe_revision_mode = full_mode\n\n\ndef load_binary_info(text):\n    # This is used for search functionality, search prints info from this file\n    parser = TextINIParse(text)\n    conan_info_json = {}\n    for section, lines in parser.line_items():\n        try:\n            items = [line.split(\"=\", 1) for line in lines]\n            conan_info_json[section] = {item[0].strip(): item[1].strip() for item in items}\n        except IndexError:\n            conan_info_json[section] = lines\n\n    return conan_info_json\n\n\nclass ConanInfo:\n\n    def __init__(self, settings=None, options=None, reqs_info=None, build_requires_info=None,\n                 python_requires=None, conf=None, config_version=None):\n        self.invalid = None\n        self.cant_build = False  # It will set to a str with a reason if the validate_build() fails\n        self.settings = settings\n        self.settings_target = None  # needs to be explicitly defined by recipe package_id()\n        self.options = options\n        self.requires = reqs_info\n        self.build_requires = build_requires_info\n        self.python_requires = python_requires\n        self.conf = conf\n        self.config_version = config_version\n        self.compatibility_delta = None\n\n    def clone(self):\n        \"\"\" Useful for build_id implementation and for compatibility()\n        \"\"\"\n        result = ConanInfo()\n        result.invalid = self.invalid\n        result.settings = self.settings.copy()\n        result.options = self.options.copy_conaninfo_options()\n        result.requires = self.requires.copy()\n        result.build_requires = self.build_requires.copy()\n        result.python_requires = self.python_requires.copy()\n        result.conf = self.conf.copy()\n        result.settings_target = self.settings_target.copy() if self.settings_target else None\n        result.config_version = self.config_version.copy() if self.config_version else None\n        return result\n\n    def serialize(self):\n        result = {}\n        settings_dumps = self.settings.serialize()\n        if settings_dumps:\n            result[\"settings\"] = settings_dumps\n        if self.settings_target is not None:\n            settings_target_dumps = self.settings_target.serialize()\n            if settings_target_dumps:\n                result[\"settings_target\"] = settings_target_dumps\n        options_dumps = self.options.serialize()\n        if options_dumps:\n            result[\"options\"] = options_dumps\n        requires_dumps = self.requires.serialize()\n        if requires_dumps:\n            result[\"requires\"] = requires_dumps\n        python_requires_dumps = self.python_requires.serialize()\n        if python_requires_dumps:\n            result[\"python_requires\"] = python_requires_dumps\n        build_requires_dumps = self.build_requires.serialize()\n        if build_requires_dumps:\n            result[\"build_requires\"] = build_requires_dumps\n        conf_dumps = self.conf.serialize()\n        if conf_dumps:\n            result[\"conf\"] = conf_dumps\n        config_version_dumps = self.config_version.serialize() if self.config_version else None\n        if config_version_dumps:\n            result[\"config_version\"] = config_version_dumps\n        if self.compatibility_delta:\n            result[\"compatibility_delta\"] = self.compatibility_delta\n        return result\n\n    def dumps(self):\n        \"\"\"\n        Get all the information contained in settings, options, requires,\n        python_requires, build_requires and conf.\n        :return: `str` with the result of joining all the information, e.g.,\n            `\"[settings]\\nos=Windows\\n[options]\\nuse_Qt=True\"`\n        \"\"\"\n        result = []\n        settings_dumps = self.settings.dumps()\n        if settings_dumps:\n            result.append(\"[settings]\")\n            result.append(settings_dumps)\n        if self.settings_target:\n            settings_target_dumps = self.settings_target.dumps()\n            if settings_target_dumps:\n                result.append(\"[settings_target]\")\n                result.append(settings_target_dumps)\n        options_dumps = self.options.dumps()\n        if options_dumps:\n            result.append(\"[options]\")\n            result.append(options_dumps)\n        requires_dumps = self.requires.dumps()\n        if requires_dumps:\n            result.append(\"[requires]\")\n            result.append(requires_dumps)\n        if self.python_requires:\n            python_reqs_dumps = self.python_requires.dumps()\n            if python_reqs_dumps:\n                result.append(\"[python_requires]\")\n                result.append(python_reqs_dumps)\n        if self.build_requires:\n            build_requires_dumps = self.build_requires.dumps()\n            if build_requires_dumps:\n                result.append(\"[build_requires]\")\n                result.append(build_requires_dumps)\n        if self.conf:\n            # TODO: Think about the serialization of Conf, not 100% sure if dumps() is the best\n            result.append(\"[conf]\")\n            result.append(self.conf.dumps())\n        config_version_dumps = self.config_version.dumps() if self.config_version else None\n        if config_version_dumps:\n            result.append(\"[config_version]\")\n            result.append(config_version_dumps)\n        result.append(\"\")  # Append endline so file ends with LF\n        return '\\n'.join(result)\n\n    def summarize_compact(self):\n        result = []\n        serialized = self.serialize()\n\n        for key, values in serialized.items():\n            if isinstance(values, dict):\n                result.append(f\"{key}: \" + \" \".join(f\"{k}={v}\" for k, v in values.items()))\n            elif isinstance(values, type([])):\n                result.append(f\"{key}: {' '.join(values)}\")\n\n        return result\n\n    def dump_diff(self, compatible):\n        self_dump = self.dumps()\n        compatible_dump = compatible.dumps()\n        result = []\n        for line in compatible_dump.splitlines():\n            if line not in self_dump:\n                result.append(line)\n        return ', '.join(result)\n\n    def package_id(self):\n        \"\"\"\n        Get the `package_id` that is the result of applying the has function SHA-1 to the\n        `self.dumps()` return.\n        :return: `str` the `package_id`, e.g., `\"040ce2bd0189e377b2d15eb7246a4274d1c63317\"`\n        \"\"\"\n        text = self.dumps()\n        md = hashlib.sha1()\n        md.update(text.encode())\n        package_id = md.hexdigest()\n        return package_id\n\n    def clear(self):\n        self.settings.clear()\n        self.options.clear()\n        self.requires.clear()\n        self.conf.clear()\n        self.build_requires.clear()\n        self.python_requires.clear()\n        if self.config_version is not None:\n            self.config_version.clear()\n\n    def validate(self):\n        # If the options are not fully defined, this is also an invalid case\n        try:\n            self.options.validate()\n        except ConanException as e:\n            self.invalid = str(e)\n\n        try:\n            self.settings.validate()\n        except ConanException as e:\n            self.invalid = str(e)\n"
  },
  {
    "path": "conan/internal/model/layout.py",
    "content": "import os\n\nfrom conan.internal.model.cpp_info import CppInfo\nfrom conan.internal.model.conf import Conf\n\n\nclass Infos:\n\n    def __init__(self):\n        self.source = CppInfo()\n        self.build = CppInfo()\n        self.package = CppInfo(set_defaults=True)\n\n\nclass PartialLayout:\n    def __init__(self):\n        from conan.tools.env import Environment\n        self.buildenv_info = Environment()\n        self.runenv_info = Environment()\n        self.conf_info = Conf()\n\n    def set_relative_base_folder(self, folder):\n        self.buildenv_info.set_relative_base_folder(folder)\n        self.runenv_info.set_relative_base_folder(folder)\n        self.conf_info.set_relative_base_folder(folder)\n\n\nclass Layouts:\n    def __init__(self):\n        self.source = PartialLayout()\n        self.build = PartialLayout()\n        self.package = PartialLayout()\n\n\nclass Folders:\n\n    def __init__(self):\n        self._base_source = None\n        self._base_build = None\n        self._base_package = None\n        self._base_generators = None\n\n        self._base_export = None\n        self._base_export_sources = None\n\n        self._base_recipe_metadata = None\n        self._base_pkg_metadata = None\n        self._immutable_package_folder = None\n\n        self.source = \"\"\n        self.build = \"\"\n        self.package = \"\"\n        self.generators = \"\"\n        # Relative location of the project root, if the conanfile is not in that project root, but\n        # in a subfolder: e.g: If the conanfile is in a subfolder then self.root = \"..\"\n        self.root = None\n        # The relative location with respect to the project root of the subproject containing the\n        # conanfile.py, that makes most of the output folders defined in layouts (cmake_layout, etc)\n        # start from the subproject again\n        self.subproject = None\n        self.build_folder_vars = None\n\n    def set_base_folders(self, conanfile_folder, output_folder):\n        \"\"\" this methods can be used for defining all the base folders in the\n        local flow (conan install, source, build), where only the current conanfile location\n        and the potential --output-folder user argument are the folders to take into account\n        If the \"layout()\" method defines a self.folders.root = \"xxx\" it will be used to compute\n        the base folder\n\n        @param conanfile_folder: the location where the current consumer conanfile is\n        @param output_folder: Can potentially be None (for export-pkg: TODO), in that case\n        the conanfile location is used\n        \"\"\"\n        # This must be called only after ``layout()`` has been called\n        base_folder = conanfile_folder if self.root is None else \\\n            os.path.normpath(os.path.join(conanfile_folder, self.root))\n\n        self._base_source = base_folder\n        self._base_build = output_folder or base_folder\n        self._base_generators = output_folder or base_folder\n        self._base_export_sources = output_folder or base_folder\n        self._base_recipe_metadata = os.path.join(base_folder, \"metadata\")\n        # TODO: It is likely that this base_pkg_metadata is not really used with this value\n        self._base_pkg_metadata = output_folder or base_folder\n\n    @property\n    def source_folder(self):\n        if self._base_source is None:\n            return None\n        if not self.source:\n            return os.path.normpath(self._base_source)\n\n        return os.path.normpath(os.path.join(self._base_source, self.source))\n\n    @property\n    def base_source(self):\n        return self._base_source\n\n    def set_base_source(self, folder):\n        self._base_source = folder\n\n    @property\n    def build_folder(self):\n        if self._base_build is None:\n            return None\n        if not self.build:\n            return os.path.normpath(self._base_build)\n        return os.path.normpath(os.path.join(self._base_build, self.build))\n\n    @property\n    def recipe_metadata_folder(self):\n        return self._base_recipe_metadata\n\n    def set_base_recipe_metadata(self, folder):\n        self._base_recipe_metadata = folder\n\n    @property\n    def package_metadata_folder(self):\n        return self._base_pkg_metadata\n\n    def set_base_pkg_metadata(self, folder):\n        self._base_pkg_metadata = folder\n\n    @property\n    def base_build(self):\n        return self._base_build\n\n    def set_base_build(self, folder):\n        self._base_build = folder\n\n    @property\n    def base_package(self):\n        return self._base_package\n\n    def set_base_package(self, folder):\n        self._base_package = folder\n\n    @property\n    def package_folder(self):\n        \"\"\"For the cache, the package folder is only the base\"\"\"\n        return self._base_package\n\n    def set_finalize_folder(self, folder):\n        self._immutable_package_folder = self.package_folder\n        self.set_base_package(folder)\n\n    @property\n    def immutable_package_folder(self):\n        return self._immutable_package_folder or self.package_folder\n\n    @property\n    def generators_folder(self):\n        if self._base_generators is None:\n            return None\n        if not self.generators:\n            return os.path.normpath(self._base_generators)\n        return os.path.normpath(os.path.join(self._base_generators, self.generators))\n\n    def set_base_generators(self, folder):\n        self._base_generators = folder\n\n    @property\n    def base_export(self):\n        return self._base_export\n\n    def set_base_export(self, folder):\n        self._base_export = folder\n\n    @property\n    def base_export_sources(self):\n        return self._base_export_sources\n\n    def set_base_export_sources(self, folder):\n        self._base_export_sources = folder\n"
  },
  {
    "path": "conan/internal/model/lockfile.py",
    "content": "import fnmatch\nimport json\nimport os\nfrom collections import OrderedDict\n\nfrom conan.api.output import ConanOutput\nfrom conan.internal.graph.graph import RECIPE_VIRTUAL, RECIPE_CONSUMER, CONTEXT_BUILD, Overrides\nfrom conan.errors import ConanException\nfrom conan.api.model import RecipeReference\nfrom conan.internal.model.version_range import VersionRange\nfrom conan.internal.util.files import load, save\n\nLOCKFILE = \"conan.lock\"\nLOCKFILE_VERSION = \"0.5\"\n\n\nclass _LockRequires:\n    \"\"\"\n    This is an ordered set of locked references.\n    It is implemented this way to allow adding package_id:prev information later,\n    otherwise it could be a bare list\n    \"\"\"\n    def __init__(self):\n        self._requires = OrderedDict()  # {require: package_ids}\n\n    def refs(self):\n        return self._requires.keys()\n\n    def get(self, item):\n        return self._requires.get(item)\n\n    def serialize(self):\n        result = []\n        for k, v in self._requires.items():\n            if v is None:\n                result.append(repr(k))\n            else:\n                result.append((repr(k), v))\n        return result\n\n    @staticmethod\n    def deserialize(data):\n        result = _LockRequires()\n        for d in data:\n            if isinstance(d, str):\n                result._requires[RecipeReference.loads(d)] = None\n            else:\n                result._requires[RecipeReference.loads(d[0])] = d[1]\n        return result\n\n    def add(self, ref, package_ids=None):\n        if ref.revision is not None:\n            old_package_ids = self._requires.pop(ref, None)  # Get existing one\n            if old_package_ids is not None:\n                if package_ids is not None:\n                    package_ids = old_package_ids.update(package_ids)\n                else:\n                    package_ids = old_package_ids\n            self._requires[ref] = package_ids\n        else:  # Manual addition of something without revision\n            existing = {r: r for r in self._requires}.get(ref)\n            if existing and existing.revision is not None:\n                raise ConanException(f\"Cannot add {ref} to lockfile, already exists\")\n            self._requires[ref] = package_ids\n\n    def remove(self, pattern):\n        ref = RecipeReference.loads(pattern)\n        version = str(ref.version)\n        remove = []\n        if version.startswith(\"[\") and version.endswith(\"]\"):\n            version_range = VersionRange(version[1:-1])\n            for k, v in self._requires.items():\n                if fnmatch.fnmatch(k.name, ref.name) and version_range.contains(k.version, None):\n                    new_pattern = f\"{k.name}/*@{ref.user or ''}\"\n                    new_pattern += f\"/{ref.channel}\" if ref.channel else \"\"\n                    if k.matches(new_pattern, False):\n                        remove.append(k)\n        else:\n            remove = [k for k in self._requires if k.matches(pattern, False)]\n        self._requires = OrderedDict((k, v) for k, v in self._requires.items() if k not in remove)\n        return remove\n\n    def update(self, refs, name):\n        if not refs:\n            return\n        for r in refs:\n            r = RecipeReference.loads(r)\n            new_reqs = {}\n            for k, v in self._requires.items():\n                if r.name == k.name:\n                    ConanOutput().info(f\"Replacing {name}: {k.repr_notime()} -> {repr(r)}\")\n                else:\n                    new_reqs[k] = v\n            self._requires = new_reqs\n            self._requires[r] = None  # No package-id at the moment\n        self.sort()\n\n    def sort(self):\n        self._requires = OrderedDict(reversed(sorted(self._requires.items())))\n\n    def merge(self, other):\n        \"\"\"\n        :type other: _LockRequires\n        \"\"\"\n        # TODO: What happens when merging incomplete refs? Probably str(ref) should be used\n        for k, v in other._requires.items():\n            if k in self._requires:\n                if v is not None:\n                    self._requires.setdefault(k, {}).update(v)\n            else:\n                self._requires[k] = v\n        self.sort()\n\n\nclass Lockfile:\n\n    def __init__(self, deps_graph=None, lock_packages=False):\n        self._requires = _LockRequires()\n        self._python_requires = _LockRequires()\n        self._build_requires = _LockRequires()\n        self._conf_requires = _LockRequires()\n        self._alias = {}\n        self._overrides = Overrides()\n        self.partial = False\n\n        if deps_graph is None:\n            return\n\n        self.update_lock(deps_graph, lock_packages)\n\n    def update_lock(self, deps_graph, lock_packages=False):\n        for graph_node in deps_graph.nodes:\n            try:\n                for r in graph_node.conanfile.python_requires.all_refs():\n                    self._python_requires.add(r)\n            except AttributeError:\n                pass\n            if graph_node.recipe in (RECIPE_VIRTUAL, RECIPE_CONSUMER) or graph_node.ref is None:\n                continue\n            assert graph_node.conanfile is not None\n\n            pids = {graph_node.package_id: graph_node.prev} if lock_packages else None\n            if graph_node.context == CONTEXT_BUILD:\n                self._build_requires.add(graph_node.ref, pids)\n            else:\n                self._requires.add(graph_node.ref, pids)\n\n        self._alias.update(deps_graph.aliased)\n        self._overrides.update(deps_graph.overrides())\n\n        self._requires.sort()\n        self._build_requires.sort()\n        self._python_requires.sort()\n        self._conf_requires.sort()\n\n    @staticmethod\n    def load(path):\n        if not path:\n            raise IOError(\"Invalid path\")\n        if not os.path.isfile(path):\n            raise ConanException(\"Missing lockfile in: %s\" % path)\n        content = load(path)\n        try:\n            return Lockfile.loads(content)\n        except Exception as e:\n            raise ConanException(\"Error parsing lockfile '{}': {}\".format(path, e))\n\n    @staticmethod\n    def loads(content):\n        return Lockfile.deserialize(json.loads(content))\n\n    def dumps(self):\n        return json.dumps(self.serialize(), indent=4)\n\n    def save(self, path):\n        save(path, self.dumps() + \"\\n\")\n\n    def merge(self, other):\n        \"\"\"\n        :type other: Lockfile\n        \"\"\"\n        self._requires.merge(other._requires)\n        self._build_requires.merge(other._build_requires)\n        self._python_requires.merge(other._python_requires)\n        self._conf_requires.merge(other._conf_requires)\n        self._alias.update(other._alias)\n        self._overrides.update(other._overrides)\n\n    def add(self, requires=None, build_requires=None, python_requires=None, config_requires=None):\n        \"\"\" adding new things manually will trigger the sort() of the locked list, so lockfiles\n        alwasys keep the ordered lists. This means that for some especial edge cases it might\n        be necessary to allow removing from a lockfile, for example to test an older version\n        than the one locked (in general adding works better for moving forward to newer versions)\n        \"\"\"\n        if requires:\n            for r in requires:\n                self._requires.add(r)\n            self._requires.sort()\n        if build_requires:\n            for r in build_requires:\n                self._build_requires.add(r)\n            self._build_requires.sort()\n        if python_requires:\n            for r in python_requires:\n                self._python_requires.add(r)\n            self._python_requires.sort()\n        if config_requires:\n            for r in config_requires:\n                self._conf_requires.add(r)\n            self._conf_requires.sort()\n\n    def remove(self, requires=None, build_requires=None, python_requires=None, config_requires=None):\n        def _remove(reqs, self_reqs, name):\n            if reqs:\n                removed = []\n                for r in reqs:\n                    removed.extend(self_reqs.remove(r))\n                for d in removed:\n                    ConanOutput().info(f\"Removed locked {name}: {d.repr_notime()}\")\n\n        _remove(requires, self._requires, \"require\")\n        _remove(build_requires, self._build_requires, \"build_require\")\n        _remove(python_requires, self._python_requires, \"python_require\")\n        _remove(config_requires, self._conf_requires, \"config_requires\")\n\n    def update(self, requires=None, build_requires=None, python_requires=None, config_requires=None):\n        self._requires.update(requires, \"require\")\n        self._build_requires.update(build_requires, \"build_requires\")\n        self._python_requires.update(python_requires, \"python_requires\")\n        self._conf_requires.update(config_requires, \"config_requires\")\n\n    @staticmethod\n    def deserialize(data):\n        \"\"\" constructs a GraphLock from a json like dict\n        \"\"\"\n        graph_lock = Lockfile()\n        version = data.get(\"version\")\n        if version and version != LOCKFILE_VERSION:\n            raise ConanException(\"This lockfile was created with an incompatible \"\n                                 \"version. Please regenerate the lockfile\")\n        if \"requires\" in data:\n            graph_lock._requires = _LockRequires.deserialize(data[\"requires\"])\n        if \"build_requires\" in data:\n            graph_lock._build_requires = _LockRequires.deserialize(data[\"build_requires\"])\n        if \"python_requires\" in data:\n            graph_lock._python_requires = _LockRequires.deserialize(data[\"python_requires\"])\n        if \"alias\" in data:\n            graph_lock._alias = {RecipeReference.loads(k): RecipeReference.loads(v)\n                                 for k, v in data[\"alias\"].items()}\n        if \"overrides\" in data:\n            graph_lock._overrides = Overrides.deserialize(data[\"overrides\"])\n        if \"config_requires\" in data:\n            graph_lock._conf_requires = _LockRequires.deserialize(data[\"config_requires\"])\n        return graph_lock\n\n    def serialize(self):\n        \"\"\" returns the object serialized as a dict of plain python types\n        that can be converted to json\n        \"\"\"\n        result = {\"version\": LOCKFILE_VERSION}\n        if self._requires:\n            result[\"requires\"] = self._requires.serialize()\n        if self._build_requires:\n            result[\"build_requires\"] = self._build_requires.serialize()\n        if self._python_requires:\n            result[\"python_requires\"] = self._python_requires.serialize()\n        if self._alias:\n            result[\"alias\"] = {repr(k): repr(v) for k, v in self._alias.items()}\n        if self._overrides:\n            result[\"overrides\"] = self._overrides.serialize()\n        if self._conf_requires:\n            result[\"config_requires\"] = self._conf_requires.serialize()\n        return result\n\n    def resolve_locked(self, node, require, resolve_prereleases):\n        if require.build or node.context == CONTEXT_BUILD:\n            locked_refs = self._build_requires.refs()\n            kind = \"build_requires\"\n        elif node.is_conf:\n            locked_refs = self._conf_requires.refs()\n            kind = \"config_requires\"\n        else:\n            locked_refs = self._requires.refs()\n            kind = \"requires\"\n        try:\n            self._resolve(require, locked_refs, resolve_prereleases, kind)\n        except ConanException:\n            overrides = self._overrides.get(require.ref)\n            if overrides is not None and len(overrides) > 1:\n                msg = f\"Override defined for {require.ref}, but multiple possible overrides\" \\\n                      f\" {overrides}. You might need to apply the 'conan graph build-order'\" \\\n                      f\" overrides for correctly building this package with this lockfile\"\n                ConanOutput().error(msg, error_type=\"exception\")\n            raise\n\n    def resolve_overrides(self, require, context):\n        \"\"\" The lockfile contains the overrides to be able to inject them when the lockfile is\n        applied to upstream dependencies, that have the overrides downstream\n        \"\"\"\n        if not self._overrides:\n            return\n\n        overriden = self._overrides.get(require.ref)\n        if overriden and len(overriden) == 1:\n            override_ref = next(iter(overriden))\n            locked_refs = self._build_requires.refs() if context == \"build\" else self._requires.refs()\n            if override_ref not in locked_refs:\n                return  # The override came from the other context\n            require.overriden_ref = require.overriden_ref or require.ref.copy()\n            require.override_ref = override_ref\n            require.ref = override_ref\n\n    def resolve_prev(self, node):\n        if node.context == CONTEXT_BUILD:\n            prevs = self._build_requires.get(node.ref)\n        else:\n            prevs = self._requires.get(node.ref)\n        if prevs:\n            return prevs.get(node.package_id)\n\n    def _resolve(self, require, locked_refs, resolve_prereleases, kind):\n        version_range = require.version_range\n        ref = require.ref\n        matches = [r for r in locked_refs if r.name == ref.name and r.user == ref.user and\n                   r.channel == ref.channel]\n        if version_range:\n            for m in matches:\n                if version_range.contains(m.version, resolve_prereleases):\n                    require.ref = m\n                    break\n            else:\n                if not self.partial:\n                    raise ConanException(f\"Requirement '{ref}' not in lockfile '{kind}'\")\n        else:\n            ref = require.ref\n            if ref.revision is None:\n                for m in matches:\n                    if m.version == ref.version:\n                        require.ref = m\n                        break\n                else:\n                    if not self.partial:\n                        raise ConanException(f\"Requirement '{ref}' not in lockfile '{kind}'\")\n            else:\n                if ref not in matches and not self.partial:\n                    raise ConanException(f\"Requirement '{repr(ref)}' not in lockfile '{kind}'\")\n\n    def replace_alias(self, require, alias):\n        locked_alias = self._alias.get(alias)\n        if locked_alias is not None:\n            require.ref = locked_alias\n            return True\n        elif not self.partial:\n            raise ConanException(f\"Requirement alias '{alias}' not in lockfile\")\n\n    def resolve_locked_pyrequires(self, require, resolve_prereleases=None):\n        locked_refs = self._python_requires.refs()  # CHANGE\n        self._resolve(require, locked_refs, resolve_prereleases, \"python_requires\")\n"
  },
  {
    "path": "conan/internal/model/manifest.py",
    "content": "import os\nfrom collections import defaultdict\n\nfrom conan.internal.paths import CONAN_MANIFEST, COMPRESSIONS, PACKAGE_FILE_NAME, EXPORT_FILE_NAME, \\\n    EXPORT_SOURCES_FILE_NAME\nfrom conan.internal.util.dates import timestamp_now, timestamp_to_str\nfrom conan.internal.util.files import load, md5, md5sum, save, gather_files\n\n\nclass FileTreeManifest:\n\n    def __init__(self, the_time, file_sums):\n        \"\"\"file_sums is a dict with filepaths and md5's: {filepath/to/file.txt: md5}\"\"\"\n        self.time = the_time\n        self.file_sums = file_sums\n\n    def files(self):\n        return self.file_sums.keys()\n\n    @property\n    def summary_hash(self):\n        s = [\"%s: %s\" % (f, fmd5) for f, fmd5 in sorted(self.file_sums.items())]\n        s.append(\"\")\n        return md5(\"\\n\".join(s))\n\n    @staticmethod\n    def loads(text):\n        \"\"\" parses a string representation, generated with __repr__\n        \"\"\"\n        tokens = text.split(\"\\n\")\n        the_time = int(tokens[0])\n        file_sums = {}\n        for md5line in tokens[1:]:\n            if md5line:\n                filename, file_md5 = md5line.rsplit(\": \", 1)\n                file_sums[filename] = file_md5\n        return FileTreeManifest(the_time, file_sums)\n\n    @staticmethod\n    def load(folder):\n        text = load(os.path.join(folder, CONAN_MANIFEST))\n        return FileTreeManifest.loads(text)\n\n    def __repr__(self):\n        # Used for serialization and saving it to disk\n        ret = [\"%s\" % self.time]\n        for file_path, file_md5 in sorted(self.file_sums.items()):\n            ret.append(\"%s: %s\" % (file_path, file_md5))\n        ret.append(\"\")\n        content = \"\\n\".join(ret)\n        return content\n\n    def __str__(self):\n        \"\"\"  Used for displaying the manifest in user readable format in Uploader, when the server\n        manifest is newer than the cache one (and not force)\n        \"\"\"\n        ret = [\"Time: %s\" % timestamp_to_str(self.time)]\n        for file_path, file_md5 in sorted(self.file_sums.items()):\n            ret.append(\"%s, MD5: %s\" % (file_path, file_md5))\n        ret.append(\"\")\n        content = \"\\n\".join(ret)\n        return content\n\n    def save(self, folder, filename=CONAN_MANIFEST):\n        path = os.path.join(folder, filename)\n        save(path, repr(self))\n\n    def report_summary(self, output, suffix=\"Copied\"):\n        ext_files = defaultdict(list)\n        for f in self.file_sums:\n            if f == \"conaninfo.txt\":\n                continue\n            _, ext = os.path.splitext(f)\n            ext_files[ext].append(os.path.basename(f))\n        if not ext_files:\n            if suffix != \"Copied\":\n                output.warning(\"No files in this package!\")\n            return\n\n        for ext, files in ext_files.items():\n            files_str = (\": \" + \", \".join(files)) if len(files) < 5 else \"\"\n            file_or_files = \"file\" if len(files) == 1 else \"files\"\n            if not ext:\n                output.info(\"%s %d %s%s\" % (suffix, len(files), file_or_files, files_str))\n            else:\n                output.info(\"%s %d '%s' %s%s\" % (suffix, len(files), ext, file_or_files, files_str))\n\n    @classmethod\n    def create(cls, folder, exports_sources_folder=None):\n        \"\"\" Walks a folder and create a FileTreeManifest for it, reading file contents\n        from disk, and capturing current time\n        \"\"\"\n        files, _ = gather_files(folder)\n        # The folders symlinks are discarded for the manifest\n        for f in (PACKAGE_FILE_NAME, EXPORT_FILE_NAME, EXPORT_SOURCES_FILE_NAME):\n            for e in COMPRESSIONS:\n                files.pop(f + e, None)\n        files.pop(CONAN_MANIFEST, None)\n\n        file_dict = {}\n        for name, filepath in files.items():\n            # For a symlink: md5 of the pointing path, no matter if broken, relative or absolute.\n            value = md5(os.readlink(filepath)) if os.path.islink(filepath) else md5sum(filepath)\n            file_dict[name] = value\n\n        if exports_sources_folder:\n            export_files, _ = gather_files(exports_sources_folder)\n            # The folders symlinks are discarded for the manifest\n            for name, filepath in export_files.items():\n                # For a symlink: md5 of the pointing path, no matter if broken, relative or absolute.\n                value = md5(os.readlink(filepath)) if os.path.islink(filepath) else md5sum(filepath)\n                file_dict[\"export_source/%s\" % name] = value\n\n        date = timestamp_now()\n\n        return cls(date, file_dict)\n\n    def __eq__(self, other):\n        \"\"\" Two manifests are equal if file_sums\n        \"\"\"\n        return self.file_sums == other.file_sums\n\n    def difference(self, other):\n        result = {}\n        for f, h in self.file_sums.items():\n            h2 = other.file_sums.get(f)\n            if h != h2:\n                result[f] = h, h2\n        for f, h in other.file_sums.items():\n            h2 = self.file_sums.get(f)\n            if h != h2:\n                result[f] = h2, h\n        return result\n"
  },
  {
    "path": "conan/internal/model/options.py",
    "content": "from conan.errors import ConanException\nfrom conan.internal.model.recipe_ref import ref_matches\n\n_falsey_options = [\"false\", \"none\", \"0\", \"off\", \"\"]\n\n\ndef option_not_exist_msg(option_name, existing_options):\n    \"\"\" Someone is referencing an option that is not available in the current package\n    options\n    \"\"\"\n    result = [\"option '%s' doesn't exist\" % option_name,\n              \"Possible options are %s\" % existing_options or \"none\"]\n    return \"\\n\".join(result)\n\n\nclass _PackageOption:\n    def __init__(self, name, value, possible_values=None):\n        self._name = name\n        self._value = value  # Value None = not defined\n        self.important = False\n        # possible_values only possible origin is recipes\n        if possible_values is None:\n            self._possible_values = None\n        else:\n            # This can contain \"ANY\"\n            self._possible_values = [str(v) if v is not None else None for v in possible_values]\n\n    def dumps(self, scope=None):\n        if self._value is None:\n            return None\n        important = \"!\" if self.important else \"\"\n        if scope:\n            return \"%s:%s%s=%s\" % (scope, self._name, important, self._value)\n        else:\n            return \"%s%s=%s\" % (self._name, important, self._value)\n\n    def copy_conaninfo_option(self):\n        # To generate a copy without validation, for package_id info.options value\n        assert self._possible_values is not None  # this should always come from recipe, with []\n        return _PackageOption(self._name, self._value, self._possible_values + [\"ANY\"])\n\n    def __bool__(self):\n        if self._value is None:\n            return False\n        return self._value.lower() not in _falsey_options\n\n    def __str__(self):\n        return str(self._value)\n\n    def __int__(self):\n        return int(self._value)\n\n    def _check_valid_value(self, value):\n        \"\"\" checks that the provided value is allowed by current restrictions\n        \"\"\"\n        if self._possible_values is None:  # validation not defined (profile)\n            return\n        if value in self._possible_values:\n            return\n        if value is not None and \"ANY\" in self._possible_values:\n            return\n        msg = (\"'%s' is not a valid 'options.%s' value.\\nPossible values are %s\"\n               % (value, self._name, self._possible_values))\n        raise ConanException(msg)\n\n    def __eq__(self, other):\n        # To promote the other to string, and always compare as strings\n        # if self.options.myoption == 1 => will convert 1 to \"1\"\n        if other is None:\n            return self._value is None\n        other = str(other)\n        self._check_valid_value(other)\n        if self._value is None:\n            return False  # Other is not None here\n        return other == self.__str__()\n\n    @property\n    def name(self):\n        return self._name\n\n    @property\n    def value(self):\n        return self._value\n\n    @value.setter\n    def value(self, v):\n        v = str(v) if v is not None else None\n        self._check_valid_value(v)\n        self._value = v\n\n    def validate(self):\n        # check that this has a valid option value defined\n        if self._value is not None:\n            return\n        if None not in self._possible_values:\n            raise ConanException(\"'options.%s' value not defined\" % self._name)\n\n\nclass _PackageOptions:\n    def __init__(self, recipe_options_definition=None):\n        if recipe_options_definition is None:\n            self._constrained = False\n            self._data = {}\n        else:\n            self._constrained = True\n            self._data = {str(option): _PackageOption(str(option), None, possible_values)\n                          for option, possible_values in recipe_options_definition.items()}\n        self._freeze = False\n\n    def dumps(self, scope=None):\n        result = []\n        for _, package_option in sorted(list(self._data.items())):\n            dump = package_option.dumps(scope)\n            if dump:\n                result.append(dump)\n        return \"\\n\".join(result)\n\n    @property\n    def possible_values(self):\n        return {k: v._possible_values for k, v in self._data.items()}\n\n    def update(self, options):\n        \"\"\"\n        @type options: _PackageOptions\n        \"\"\"\n        # Necessary for init() extending of options for python_requires_extend\n        for k, v in options._data.items():\n            self._data[k] = v\n\n    def clear(self):\n        # for header_only() clearing\n        self._data.clear()\n\n    def freeze(self):\n        self._freeze = True\n\n    def __contains__(self, option):\n        return str(option) in self._data\n\n    def get_safe(self, field, default=None):\n        return self._data.get(field, default)\n\n    def rm_safe(self, field):\n        # This should never raise any exception, in any case\n        self._data.pop(field, None)\n\n    def validate(self):\n        for child in self._data.values():\n            child.validate()\n\n    def copy_conaninfo_options(self):\n        # To generate a copy without validation, for package_id info.options value\n        result = _PackageOptions()\n        for k, v in self._data.items():\n            result._data[k] = v.copy_conaninfo_option()\n        return result\n\n    def _ensure_exists(self, field):\n        if self._constrained and field not in self._data:\n            raise ConanException(option_not_exist_msg(field, list(self._data.keys())))\n\n    def __getattr__(self, field):\n        assert field[0] != \"_\", \"ERROR %s\" % field\n        try:\n            return self._data[field]\n        except KeyError:\n            raise ConanException(option_not_exist_msg(field, list(self._data.keys())))\n\n    def __delattr__(self, field):\n        assert field[0] != \"_\", \"ERROR %s\" % field\n        # It is always possible to remove an option, even if it is frozen (freeze=True),\n        # and it got a value, because it is the only way an option could be removed\n        # conditionally to other option value (like fPIC if shared)\n        self._ensure_exists(field)\n        del self._data[field]\n\n    def __setattr__(self, field, value):\n        if field[0] == \"_\":\n            return super(_PackageOptions, self).__setattr__(field, value)\n        self._set(field, value)\n\n    def __setitem__(self, item, value):\n        self._set(item, value)\n\n    def _set(self, item, value):\n        # programmatic way to define values, for Conan codebase\n        important = item[-1] == \"!\"\n        item = item[:-1] if important else item\n\n        current_value = self._data.get(item)\n        if self._freeze and current_value.value is not None and current_value != value:\n            raise ConanException(f\"Incorrect attempt to modify option '{item}' \"\n                                 f\"from '{current_value}' to '{value}'\")\n        self._ensure_exists(item)\n        v = self._data.setdefault(item, _PackageOption(item, None))\n        new_value_important = important or (isinstance(value, _PackageOption) and value.important)\n        if new_value_important or not v.important:\n            v.value = value\n            v.important = new_value_important\n\n    def items(self):\n        result = []\n        for field, package_option in sorted(list(self._data.items())):\n            result.append((field, package_option.value))\n        return result\n\n    def update_options(self, other, is_pattern=False):\n        \"\"\"\n        @param is_pattern: if True, then the value might not exist and won't be updated\n        @type other: _PackageOptions\n        \"\"\"\n        for k, v in other._data.items():\n            if is_pattern and k not in self._data:\n                continue\n            self._set(k, v)\n\n\nclass Options:\n\n    def __init__(self, options=None, options_values=None):\n        # options=None means an unconstrained/profile definition\n        try:\n            self._package_options = _PackageOptions(options)\n            # Addressed only by name, as only 1 configuration is allowed\n            # if more than 1 is present, 1 should be \"private\" requirement and its options\n            # are not public, not overridable\n            self._deps_package_options = {}  # {name(\"Boost\": PackageOptions}\n            if options_values:\n                for k, v in options_values.items():\n                    if v is None:\n                        continue  # defining a None value means same as not giving value\n                    k = str(k).strip()\n                    v = str(v).strip()\n                    tokens = k.split(\":\", 1)\n                    if len(tokens) == 2:\n                        package, option = tokens\n                        if not package:\n                            raise ConanException(\"Invalid empty package name in options. \"\n                                                 f\"Use a pattern like `mypkg/*:{option}`\")\n                        if \"/\" not in package and \"*\" not in package and \"&\" not in package:\n                            msg = \"The usage of package names `{}` in options is \" \\\n                                  \"deprecated, use a pattern like `{}/*:{}` \" \\\n                                  \"instead\".format(k, package, option)\n                            raise ConanException(msg)\n                        if \"[\" in package:\n                            msg = (f\"Options pattern {package} contains a version range, which has no effect. \"\n                                   f\"Only '&' for consumer and '*' as wildcard are supported in this context.\")\n                            from conan.api.output import ConanOutput\n                            ConanOutput().warning(msg, warn_tag=\"risk\")\n                        self._deps_package_options.setdefault(package, _PackageOptions())[option] = v\n                    else:\n                        self._package_options[k] = v\n        except Exception as e:\n            raise ConanException(\"Error while initializing options. %s\" % str(e))\n\n    def __repr__(self):\n        return self.dumps()\n\n    @property\n    def possible_values(self):\n        return self._package_options.possible_values\n\n    def dumps(self):\n        \"\"\" produces a multiline text representation of all values, first self then others.\n        In alphabetical order, skipping real None (not string \"None\") values:\n            option1=value1\n            other_option=3\n            OtherPack:opt3=12.1\n        \"\"\"\n        result = []\n        pkg_options_dumps = self._package_options.dumps()\n        if pkg_options_dumps:\n            result.append(pkg_options_dumps)\n        for pkg_pattern, pkg_option in sorted(self._deps_package_options.items()):\n            dep_pkg_option = pkg_option.dumps(scope=pkg_pattern)\n            if dep_pkg_option:\n                result.append(dep_pkg_option)\n        return \"\\n\".join(result)\n\n    @staticmethod\n    def loads(text):\n        \"\"\" parses a multiline text in the form produced by dumps(), NO validation here\n        \"\"\"\n        values = {}\n        for line in text.splitlines():\n            line = line.strip()\n            if not line or line.startswith(\"#\"):\n                continue\n            try:\n                name, value = line.split(\"=\", 1)\n                values[name] = value\n            except ValueError:\n                raise ConanException(f\"Error while parsing option '{line}'. \"\n                                     f\"Options should be specified as 'pkg/*:option=value'\")\n        return Options(options_values=values)\n\n    def serialize(self):\n        # used by ConanInfo serialization, involved in \"list package-ids\" output\n        # we need to maintain the \"options\" and \"req_options\" first level or servers will break\n        # This happens always after reading from conaninfo.txt => all str and not None\n        result = {k: v for k, v in self._package_options.items()}\n        # Include the dependencies ones, in case they have been explicitly added in package_id()\n        # to the conaninfo.txt, we want to report them\n        for pkg_pattern, pkg_option in sorted(self._deps_package_options.items()):\n            for key, value in pkg_option.items():\n                result[\"%s:%s\" % (pkg_pattern, key)] = value\n        return result\n\n    def clear(self):\n        # for header_only() clearing\n        self._package_options.clear()\n        self._deps_package_options.clear()\n\n    def __contains__(self, option):\n        return option in self._package_options\n\n    def __getattr__(self, attr):\n        return getattr(self._package_options, attr)\n\n    def __setattr__(self, attr, value):\n        if attr[0] == \"_\" or attr == \"values\":\n            return super(Options, self).__setattr__(attr, value)\n        return setattr(self._package_options, attr, value)\n\n    def __delattr__(self, field):\n        self._package_options.__delattr__(field)\n\n    def __getitem__(self, item):\n        if isinstance(item, str):\n            if \"/\" not in item and \"*\" not in item:  # FIXME: To allow patterns like \"*\" or \"foo*\"\n                item += \"/*\"\n        return self._deps_package_options.setdefault(item, _PackageOptions())\n\n    def scope(self, ref):\n        \"\"\" when there are free options like \"shared=True\", they apply to the \"consumer\" package\n        Once we know the name of such consumer package, it can be defined in the data, so it will\n        be later correctly apply when processing options \"\"\"\n        package_options = self._deps_package_options.setdefault(str(ref), _PackageOptions())\n        package_options.update_options(self._package_options)\n        self._package_options = _PackageOptions()\n\n    def copy_conaninfo_options(self):\n        # To generate the package_id info.options copy, that can destroy, change and remove things\n        result = Options()\n        result._package_options = self._package_options.copy_conaninfo_options()\n        # In most scenarios this should be empty at this stage, because it was cleared\n        if self._deps_package_options:\n            raise ConanException(\"Dependencies options were defined incorrectly. Maybe you\"\n                                 \" tried to define options values in 'requirements()' or other\"\n                                 \" invalid place\")\n        return result\n\n    def update(self, options=None, options_values=None):\n        # Necessary for init() extending of options for python_requires_extend\n        new_options = Options(options, options_values)\n        self._package_options.update(new_options._package_options)\n        for pkg, pkg_option in new_options._deps_package_options.items():\n            self._deps_package_options.setdefault(pkg, _PackageOptions()).update(pkg_option)\n\n    def update_options(self, other):\n        \"\"\"\n        dict-like update of options, \"other\" has priority, overwrite existing\n        @type other: Options\n        \"\"\"\n        self._package_options.update_options(other._package_options)\n        for pkg, pkg_option in other._deps_package_options.items():\n            self._deps_package_options.setdefault(pkg, _PackageOptions()).update_options(pkg_option)\n\n    def apply_downstream(self, down_options, profile_options, own_ref, is_consumer):\n        \"\"\" compute the current package options, starting from the self defined ones and applying\n        the options defined by the downstrream consumers and the profile\n        Only modifies the current package_options, not the dependencies ones\n        \"\"\"\n        assert isinstance(down_options, Options)\n        assert isinstance(profile_options, Options)\n\n        for defined_options in down_options, profile_options:\n            if own_ref is None or own_ref.name is None:\n                # If the current package doesn't have a name defined, is a pure consumer without name\n                # Get the non-scoped options, plus the \"all-matching=*\" pattern\n                self._package_options.update_options(defined_options._package_options)\n                for pattern, options in defined_options._deps_package_options.items():\n                    if ref_matches(None, pattern, is_consumer=is_consumer):\n                        self._package_options.update_options(options, is_pattern=True)\n            else:\n                # If the current package has a name, there should be a match, either exact name\n                # match, or a fnmatch approximate one\n                for pattern, options in defined_options._deps_package_options.items():\n                    if ref_matches(own_ref, pattern, is_consumer=is_consumer):\n                        self._package_options.update_options(options, is_pattern=\"*\" in pattern)\n\n        self._package_options.freeze()\n\n    def get_upstream_options(self, down_options, own_ref, is_consumer):\n        \"\"\" compute which options should be propagated to the dependencies, a combination of the\n        downstream defined default_options with the current default_options ones. This happens\n        at \"configure()\" time, while building the graph. Also compute the minimum \"self_options\"\n        which is the state that a package should define in order to reproduce\n        \"\"\"\n        assert isinstance(down_options, Options)\n        # We need to store a copy for internal propagation for test_requires and tool_requires\n        private_deps_options = Options()\n        private_deps_options._deps_package_options = self._deps_package_options.copy()\n        # self_options are the minimal necessary for a build-order\n        # TODO: check this, isn't this just a copy?\n        self_options = Options()\n        self_options._deps_package_options = down_options._deps_package_options.copy()\n\n        # compute now the necessary to propagate all down - self + self deps\n        upstream_options = Options()\n        for pattern, options in down_options._deps_package_options.items():\n            if ref_matches(own_ref, pattern, is_consumer=is_consumer):\n                # Remove the exact match-name to this package, don't further propagate up\n                pattern_name = pattern.split(\"/\", 1)[0]\n                if \"*\" not in pattern_name:\n                    continue\n            self._deps_package_options.setdefault(pattern, _PackageOptions()).update_options(options)\n\n        upstream_options._deps_package_options = self._deps_package_options\n        # When the upstream is computed, the current dependencies are invalidated, so users will\n        # not be able to do ``self.options[\"mydep\"]`` because it will be empty. self.dependencies\n        # is the way to access dependencies (in other methods)\n        self._deps_package_options = {}\n        return self_options, upstream_options, private_deps_options\n"
  },
  {
    "path": "conan/internal/model/pkg_type.py",
    "content": "from enum import Enum\n\nfrom conan.errors import ConanException\n\n\nclass PackageType(Enum):\n    LIBRARY = \"library\"  # abstract type, should contain shared option to define\n    STATIC = \"static-library\"\n    SHARED = \"shared-library\"\n    HEADER = \"header-library\"\n    BUILD_SCRIPTS = \"build-scripts\"\n    APP = \"application\"\n    PYTHON = \"python-require\"\n    CONF = \"configuration\"\n    UNKNOWN = \"unknown\"\n\n    def __str__(self):\n        return self.value\n\n    def __eq__(self, other):\n        # This is useful for comparing with string type at user code, like ``package_type == \"xxx\"``\n        return super().__eq__(PackageType(other))\n\n    @staticmethod\n    def compute_package_type(conanfile):\n        # This doesnt implement the header_only option without shared one. Users should define\n        # their package_type as they wish in the configure() method\n\n        def deduce_from_options():\n            try:\n                header = conanfile.options.header_only\n            except ConanException:\n                pass\n            else:\n                if header:\n                    return PackageType.HEADER\n\n            try:\n                shared = conanfile.options.shared\n            except ConanException:\n                pass\n            else:\n                if shared:\n                    return PackageType.SHARED\n                else:\n                    return PackageType.STATIC\n            return PackageType.UNKNOWN\n\n        conanfile_type = conanfile.package_type\n        if conanfile_type is not None:  # Explicit definition in recipe\n            try:\n                conanfile_type = PackageType(conanfile_type)\n            except ValueError:\n                raise ConanException(f\"{conanfile}: Invalid package type '{conanfile_type}'. \"\n                                     f\"Valid types: {[i.value for i in PackageType]}\")\n            if conanfile_type is PackageType.LIBRARY:\n                conanfile_type = deduce_from_options()\n                if conanfile_type is PackageType.UNKNOWN:\n                    raise ConanException(f\"{conanfile}: Package type is 'library',\"\n                                         \" but no 'shared' option declared\")\n            elif any(option in conanfile.options for option in [\"shared\", \"header_only\"]):\n                conanfile.output.warning(f\"{conanfile}: package_type '{conanfile_type}' is defined, \"\n                                         \"but 'shared' and/or 'header_only' options are present. \"\n                                         \"The package_type will have precedence over the options \"\n                                         \"regardless of their value.\")\n            conanfile.package_type = conanfile_type\n        else:  # automatic default detection with option shared/header-only\n            conanfile.package_type = deduce_from_options()\n"
  },
  {
    "path": "conan/internal/model/profile.py",
    "content": "import copy\nfrom collections import OrderedDict, defaultdict\n\nfrom conan.errors import ConanException\nfrom conan.tools.env.environment import ProfileEnvironment\nfrom conan.internal.model.conf import ConfDefinition\nfrom conan.internal.model.options import Options\nfrom conan.api.model import RecipeReference\n\n\nclass Profile:\n    \"\"\"A profile contains a set of setting (with values), environment variables\n    \"\"\"\n\n    def __init__(self):\n        # Input sections, as defined by user profile files and command line\n        self.settings = OrderedDict()\n        self.package_settings = defaultdict(OrderedDict)\n        self.options = Options()\n        self.tool_requires = OrderedDict()  # ref pattern: list of ref\n        self.replace_requires = {}\n        self.replace_tool_requires = {}\n        self.platform_tool_requires = []\n        self.platform_requires = []\n        self.conf = ConfDefinition()\n        self.buildenv = ProfileEnvironment()\n        self.runenv = ProfileEnvironment()\n        self.runner = {}\n\n        # Cached processed values\n        self.processed_settings = None  # Settings with values, and smart completion\n        self._package_settings_values = None\n\n    def __repr__(self):\n        return self.dumps()\n\n    def serialize(self):\n        def _serialize_tool_requires():\n            return {pattern: [repr(ref) for ref in refs]\n                    for pattern, refs in self.tool_requires.items()}\n        result = {\n            \"settings\": self.settings,\n            \"package_settings\": self.package_settings,\n            \"options\": self.options.serialize(),\n            \"tool_requires\": _serialize_tool_requires(),\n            \"conf\": self.conf.serialize(),\n            # FIXME: Perform a serialize method for ProfileEnvironment\n            \"build_env\": self.buildenv.dumps()\n        }\n\n        if self.replace_requires:\n            result[\"replace_requires\"] = {str(pattern): str(replace) for pattern, replace in\n                                          self.replace_requires.items()}\n        if self.replace_tool_requires:\n            result[\"replace_tool_requires\"] = {str(pattern): str(replace) for pattern, replace in\n                                               self.replace_tool_requires.items()}\n        if self.platform_tool_requires:\n            result[\"platform_tool_requires\"] = [str(t) for t in self.platform_tool_requires]\n\n        if self.platform_requires:\n            result[\"platform_requires\"] = [str(t) for t in self.platform_requires]\n\n        return result\n\n    @property\n    def package_settings_values(self):\n        if self._package_settings_values is None:\n            self._package_settings_values = {}\n            for pkg, settings in self.package_settings.items():\n                self._package_settings_values[pkg] = list(settings.items())\n        return self._package_settings_values\n\n    def process_settings(self, cache_settings):\n        assert self.processed_settings is None, \"processed settings must be None\"\n        self.processed_settings = cache_settings.copy()\n        self.processed_settings.update_values(list(self.settings.items()))\n\n    def dumps(self):\n        result = [\"[settings]\"]\n        for name, value in sorted(self.settings.items()):\n            result.append(\"%s=%s\" % (name, value))\n        for package, values in self.package_settings.items():\n            for name, value in sorted(values.items()):\n                result.append(\"%s:%s=%s\" % (package, name, value))\n\n        options_str = self.options.dumps()\n        if options_str:\n            result.append(\"[options]\")\n            result.append(options_str)\n\n        if self.tool_requires:\n            result.append(\"[tool_requires]\")\n            for pattern, req_list in self.tool_requires.items():\n                result.append(\"%s: %s\" % (pattern, \", \".join(str(r) for r in req_list)))\n\n        if self.platform_tool_requires:\n            result.append(\"[platform_tool_requires]\")\n            result.extend(str(t) for t in self.platform_tool_requires)\n\n        if self.platform_requires:\n            result.append(\"[platform_requires]\")\n            result.extend(str(t) for t in self.platform_requires)\n\n        if self.replace_requires:\n            result.append(\"[replace_requires]\")\n            for pattern, ref in self.replace_requires.items():\n                result.append(f\"{pattern}: {ref}\")\n\n        if self.replace_tool_requires:\n            result.append(\"[replace_tool_requires]\")\n            for pattern, ref in self.replace_tool_requires.items():\n                result.append(f\"{pattern}: {ref}\")\n\n        if self.conf:\n            result.append(\"[conf]\")\n            result.append(self.conf.dumps())\n\n        if self.buildenv:\n            result.append(\"[buildenv]\")\n            result.append(self.buildenv.dumps())\n\n        if self.runenv:\n            result.append(\"[runenv]\")\n            result.append(self.runenv.dumps())\n\n        if result and result[-1] != \"\":\n            result.append(\"\")\n\n        return \"\\n\".join(result).replace(\"\\n\\n\", \"\\n\")\n\n    def compose_profile(self, other):\n        self.update_settings(other.settings)\n        self.update_package_settings(other.package_settings)\n        self.options.update_options(other.options)\n        # It is possible that build_requires are repeated, or same package but different versions\n        for pattern, req_list in other.tool_requires.items():\n            existing_build_requires = self.tool_requires.get(pattern)\n            existing = OrderedDict()\n            if existing_build_requires is not None:\n                for br in existing_build_requires:\n                    # TODO: Understand why sometimes they are str and other are RecipeReference\n                    r = RecipeReference.loads(br) \\\n                         if not isinstance(br, RecipeReference) else br\n                    existing[r.name] = br\n            for req in req_list:\n                r = RecipeReference.loads(req) \\\n                     if not isinstance(req, RecipeReference) else req\n                existing[r.name] = req\n            self.tool_requires[pattern] = list(existing.values())\n\n        self.replace_requires.update(other.replace_requires)\n        self.replace_tool_requires.update(other.replace_tool_requires)\n\n        runner_type = self.runner.get(\"type\")\n        other_runner_type = other.runner.get(\"type\")\n        if runner_type and other_runner_type and runner_type != other_runner_type:\n            raise ConanException(f\"Found different runner types in profile composition \"\n                                 f\"({runner_type} and {other_runner_type})\")\n        self.runner.update(other.runner)\n\n        current_platform_tool_requires = {r.name: r for r in self.platform_tool_requires}\n        current_platform_tool_requires.update({r.name: r for r in other.platform_tool_requires})\n        self.platform_tool_requires = list(current_platform_tool_requires.values())\n        current_platform_requires = {r.name: r for r in self.platform_requires}\n        current_platform_requires.update({r.name: r for r in other.platform_requires})\n        self.platform_requires = list(current_platform_requires.values())\n\n        self.conf.update_conf_definition(other.conf)\n        self.buildenv.update_profile_env(other.buildenv)  # Profile composition, last has priority\n        self.runenv.update_profile_env(other.runenv)\n\n    def update_settings(self, new_settings):\n        \"\"\"Mix the specified settings with the current profile.\n        Specified settings are prioritized to profile\"\"\"\n\n        assert isinstance(new_settings, OrderedDict)\n\n        # apply the current profile\n        res = copy.copy(self.settings)\n        if new_settings:\n            # Invalidate the current subsettings if the parent setting changes\n            # Example: new_settings declare a different \"compiler\",\n            # so invalidate the current \"compiler.XXX\"\n            for name, value in new_settings.items():\n                if \".\" not in name:\n                    if name in self.settings and self.settings[name] != value:\n                        for cur_name, _ in self.settings.items():\n                            if cur_name.startswith(\"%s.\" % name):\n                                del res[cur_name]\n            # Now merge the new values\n            res.update(new_settings)\n            self.settings = res\n\n    def update_package_settings(self, package_settings):\n        \"\"\"Mix the specified package settings with the specified profile.\n        Specified package settings are prioritized to profile\"\"\"\n        for package_name, settings in package_settings.items():\n            self.package_settings[package_name].update(settings)\n"
  },
  {
    "path": "conan/internal/model/recipe_ref.py",
    "content": "from conan.api.model import RecipeReference\n\n\ndef ref_matches(ref, pattern, is_consumer):\n    if not ref or not str(ref):\n        assert is_consumer\n        ref = RecipeReference.loads(\"*/*\")  # FIXME: ugly\n    return ref.matches(pattern, is_consumer=is_consumer)\n"
  },
  {
    "path": "conan/internal/model/requires.py",
    "content": "from conan.errors import ConanException\nfrom conan.internal.model.pkg_type import PackageType\nfrom conan.api.model import RecipeReference\nfrom conan.internal.model.version_range import VersionRange\n\n\nclass Requirement:\n    \"\"\" A user definition of a requires in a conanfile\n    \"\"\"\n    def __init__(self, ref, *, headers=None, libs=None, build=False, run=None, visible=None,\n                 transitive_headers=None, transitive_libs=None, test=None, package_id_mode=None,\n                 force=None, override=None, direct=None, options=None, no_skip=False):\n        # * prevents the usage of more positional parameters, always ref + **kwargs\n        # By default this is a generic library requirement\n        self.ref = ref\n        self._required_ref = ref  # Store the original reference\n        self._headers = headers  # This dependent node has headers that must be -I<headers-path>\n        self._libs = libs\n        self._build = build  # This dependent node is a build tool that runs at build time only\n        self._run = run  # node contains executables, shared libs or data necessary at host run time\n        self._visible = visible  # Even if not libsed or visible, the node is unique, can conflict\n        self._transitive_headers = transitive_headers\n        self._transitive_libs = transitive_libs\n        self._test = test\n        self._package_id_mode = package_id_mode\n        self._force = force\n        self._override = override\n        self._direct = direct\n        self.options = options\n        # Meta and auxiliary information\n        # The \"defining_require\" is the require that defines the current value. If this require is\n        # overriden/forced, this attribute will point to the overriding/forcing requirement.\n        self.defining_require = self  # if not overriden, it points to itself\n        self.overriden_ref = None  # to store if the requirement has been overriden (store old ref)\n        self.override_ref = None  # to store if the requirement has been overriden (store new ref)\n        self.is_test = test  # to store that it was a test, even if used as regular requires too\n        self.skip = False\n        self.required_nodes = set()  # store which intermediate nodes are required, to compute \"Skip\"\n        self.no_skip = no_skip\n\n    @property\n    def files(self):  # require needs some files in dependency package\n        return self.headers or self.libs or self.run or self.build\n\n    @staticmethod\n    def _default_if_none(field, default_value):\n        return field if field is not None else default_value\n\n    @property\n    def headers(self):\n        return self._default_if_none(self._headers, True)\n\n    @headers.setter\n    def headers(self, value):\n        self._headers = value\n\n    @property\n    def libs(self):\n        return self._default_if_none(self._libs, True)\n\n    @libs.setter\n    def libs(self, value):\n        self._libs = value\n\n    @property\n    def visible(self):\n        return self._default_if_none(self._visible, True)\n\n    @visible.setter\n    def visible(self, value):\n        self._visible = value\n\n    @property\n    def test(self):\n        return self._default_if_none(self._test, False)\n\n    @test.setter\n    def test(self, value):\n        self._test = value\n\n    @property\n    def force(self):\n        return self._default_if_none(self._force, False)\n\n    @force.setter\n    def force(self, value):\n        self._force = value\n\n    @property\n    def override(self):\n        return self._default_if_none(self._override, False)\n\n    @override.setter\n    def override(self, value):\n        self._override = value\n\n    @property\n    def direct(self):\n        return self._default_if_none(self._direct, True)\n\n    @direct.setter\n    def direct(self, value):\n        self._direct = value\n\n    @property\n    def build(self):\n        return self._build\n\n    @build.setter\n    def build(self, value):\n        self._build = value\n\n    @property\n    def run(self):\n        return self._default_if_none(self._run, False)\n\n    @run.setter\n    def run(self, value):\n        self._run = value\n\n    @property\n    def transitive_headers(self):\n        return self._transitive_headers\n\n    @transitive_headers.setter\n    def transitive_headers(self, value):\n        self._transitive_headers = value\n\n    @property\n    def transitive_libs(self):\n        return self._transitive_libs\n\n    @transitive_libs.setter\n    def transitive_libs(self, value):\n        self._transitive_libs = value\n\n    @property\n    def package_id_mode(self):\n        return self._package_id_mode\n\n    @package_id_mode.setter\n    def package_id_mode(self, value):\n        self._package_id_mode = value\n\n    def __repr__(self):\n        return repr(self.__dict__)\n\n    def __str__(self):\n        traits = 'build={}, headers={}, libs={}, '  \\\n                 'run={}, visible={}'.format(self.build, self.headers, self.libs, self.run,\n                                             self.visible)\n        return \"{}, Traits: {}\".format(self.ref, traits)\n\n    def serialize(self):\n        result = {\"ref\": str(self.ref),\n                  \"require\": str(self._required_ref)}\n        serializable = (\"run\", \"libs\", \"skip\", \"test\", \"force\", \"direct\", \"build\",\n                        \"transitive_headers\", \"transitive_libs\", \"headers\",\n                        \"package_id_mode\", \"visible\")\n        for attribute in serializable:\n            result[attribute] = getattr(self, attribute)\n        return result\n\n    def copy_requirement(self):\n        return Requirement(self.ref, headers=self.headers, libs=self.libs, build=self.build,\n                           run=self.run, visible=self.visible,\n                           transitive_headers=self.transitive_headers,\n                           transitive_libs=self.transitive_libs)\n\n    @property\n    def version_range(self):\n        \"\"\" returns the version range expression, without brackets []\n        or None if it is not an expression\n        \"\"\"\n        version = repr(self.ref.version)\n        if version[0] == \"[\" and version[-1] == \"]\":\n            return VersionRange(version[1:-1])\n\n    @property\n    def alias(self):\n        version = repr(self.ref.version)\n        if version.startswith(\"(\") and version.endswith(\")\"):\n            return RecipeReference(self.ref.name, version[1:-1], self.ref.user, self.ref.channel,\n                                   self.ref.revision)\n\n    def process_package_type(self, src_node, node):\n        \"\"\"If the requirement traits have not been adjusted, then complete them with package type\n        definition\"\"\"\n\n        pkg_type = node.conanfile.package_type\n\n        def set_if_none(field, value):\n            if getattr(self, field) is None:\n                setattr(self, field, value)\n\n        if pkg_type is PackageType.APP:\n            # Change the default requires headers&libs to False for APPS\n            set_if_none(\"_headers\", False)\n            set_if_none(\"_libs\", False)\n            set_if_none(\"_run\", True)\n        elif pkg_type is PackageType.SHARED:\n            set_if_none(\"_run\", True)\n        elif pkg_type is PackageType.STATIC:\n            set_if_none(\"_run\", False)\n        elif pkg_type is PackageType.HEADER:\n            set_if_none(\"_run\", False)\n            set_if_none(\"_libs\", False)\n            set_if_none(\"_headers\", True)\n        elif pkg_type is PackageType.BUILD_SCRIPTS:\n            set_if_none(\"_run\", True)\n            set_if_none(\"_libs\", False)\n            set_if_none(\"_headers\", False)\n            set_if_none(\"_visible\", False)  # Conflicts might be allowed for this kind of package\n\n        src_pkg_type = src_node.conanfile.package_type\n        if src_pkg_type is PackageType.HEADER:\n            set_if_none(\"_transitive_headers\", True)\n            set_if_none(\"_transitive_libs\", True)\n\n    def __hash__(self):\n        return hash((self.ref.name, self.build))\n\n    def __eq__(self, other):\n        \"\"\"If the name is the same and they are in the same context, and if both of them are\n        propagating includes or libs or run info or both are visible or the reference is the same,\n        we consider the requires equal, so they can conflict\"\"\"\n        return (self.ref.name == other.ref.name and self.build == other.build and\n                (self.override or  # an override with same name and context, always match\n                 (self.headers and other.headers) or\n                 (self.libs and other.libs) or\n                 (self.run and other.run) or\n                 ((self.visible or self.test) and (other.visible or other.test)) or\n                 (self.ref == other.ref and self.options == other.options)))\n\n    def aggregate(self, other):\n        \"\"\" when closing loop and finding the same dependency on a node, the information needs\n        to be aggregated\n        :param other: is the existing Require that the current node has, which information has to be\n        appended to \"self\", which is the requires that is being propagated to the current node\n        from upstream\n        \"\"\"\n        assert self.build == other.build\n        if other.override:\n            # If the other aggregated is an override, it shouldn't add information\n            # it already did override upstream, and the actual information used in this node is\n            # the propagated one.\n            self.force = True\n            return\n        self.headers |= other.headers\n        self.libs |= other.libs\n        self.run = self.run or other.run\n        self.visible |= other.visible\n        self.force |= other.force\n        self.direct |= other.direct\n        self.transitive_headers = self.transitive_headers or other.transitive_headers\n        self.transitive_libs = self.transitive_libs or other.transitive_libs\n        if not other.test:\n            self.test = False  # it it was previously a test, but also required by non-test\n        # necessary even if no propagation, order of requires matter\n        self.is_test = self.is_test or other.is_test\n        # package_id_mode is not being propagated downstream. So it is enough to check if the\n        # current require already defined it or not\n        if self.package_id_mode is None:\n            self.package_id_mode = other.package_id_mode\n        self.required_nodes.update(other.required_nodes)\n\n    def transform_downstream(self, pkg_type, require, dep_pkg_type):\n        \"\"\"\n        consumer ---self--->  foo<pkg_type> ---require---> bar<dep_pkg_type>\n            \\\\ -------------------????-------------------- /\n        Compute new Requirement to be applied to \"consumer\" translating the effect of the dependency\n        to such \"consumer\".\n        Result can be None if nothing is to be propagated\n        \"\"\"\n        if require.visible is False:\n            # TODO: We could implement checks in case private is violated (e.g shared libs)\n            return\n\n        if require.build:  # public!\n            # TODO: To discuss if this way of conflicting build_requires is actually useful or not\n            # Build-requires will propagate its main trait for running exes/shared to downstream\n            # consumers so run=require.run, irrespective of the 'self.run' trait\n            downstream_require = Requirement(require.ref, headers=False, libs=False, build=True,\n                                             run=require.run, visible=self.visible, direct=False)\n            return downstream_require\n\n        if self.build:  # Build-requires\n            # If the above is shared or the requirement is explicit run=True\n            # visible=self.visible will further propagate it downstream\n            if dep_pkg_type is PackageType.SHARED or require.run:\n                downstream_require = Requirement(require.ref, headers=False, libs=False, build=True,\n                                                 run=True, visible=self.visible, direct=False)\n                return downstream_require\n            return\n\n        # Regular and test requires\n        if dep_pkg_type is PackageType.SHARED or dep_pkg_type is PackageType.STATIC:\n            if pkg_type is PackageType.SHARED:\n                downstream_require = Requirement(require.ref, headers=False, libs=False, run=require.run)\n            elif pkg_type is PackageType.STATIC:\n                downstream_require = Requirement(require.ref, headers=False, libs=require.libs, run=require.run)\n            elif pkg_type is PackageType.APP:\n                downstream_require = Requirement(require.ref, headers=False, libs=False, run=require.run)\n            elif pkg_type is PackageType.HEADER:\n                downstream_require = Requirement(require.ref, headers=require.headers, libs=require.libs, run=require.run)\n            else:\n                if pkg_type != PackageType.UNKNOWN:\n                    raise ConanException(f\"Package '{self.ref}' with type '{pkg_type}' cannot have \"\n                                         f\"a '{dep_pkg_type}' dependency to '{require.ref}'\")\n                # TODO: This is undertested, changing it did not break tests\n                downstream_require = require.copy_requirement()\n        elif dep_pkg_type is PackageType.HEADER:\n            downstream_require = Requirement(require.ref, headers=False, libs=False, run=require.run)\n        else:\n            # Unknown, default. This happens all the time while check_downstream as shared is unknown\n            # FIXME\n            downstream_require = require.copy_requirement()\n            # This is faster than pkg_type in (pkg.shared, pkg.static, ....)\n            if pkg_type is PackageType.SHARED or pkg_type is PackageType.APP:\n                downstream_require.libs = False\n                downstream_require.headers = False\n            elif pkg_type is PackageType.STATIC:\n                downstream_require.headers = False\n\n        assert require.visible, \"at this point require should be visible\"\n\n        if require.transitive_headers is not None:\n            downstream_require.headers = require.headers and require.transitive_headers\n        if self.transitive_headers is not None:\n            downstream_require.transitive_headers = self.transitive_headers\n\n        if require.transitive_libs is not None:\n            downstream_require.libs = require.libs and require.transitive_libs\n        if self.transitive_libs is not None:\n            downstream_require.transitive_libs = self.transitive_libs\n\n        if self.visible is False:\n            downstream_require.visible = False\n\n        if pkg_type is not PackageType.HEADER:  # These rules are not valid for header-only\n            # If non-default, then the consumer requires has priority\n            if self.headers is False:\n                downstream_require.headers = False\n\n            if self.libs is False:\n                downstream_require.libs = False\n\n        # TODO: Automatic assignment invalidates user possibility of overriding default\n        # if required.run is not None:\n        #    downstream_require.run = required.run\n\n        if self.test:\n            downstream_require.test = True\n\n        # If the current one is resolving conflicts, the downstream one will be too\n        downstream_require.force = require.force\n        downstream_require.direct = False\n        return downstream_require\n\n    def deduce_package_id_mode(self, pkg_type, dep_node, non_embed_mode, embed_mode, build_mode,\n                               unknown_mode):\n        # If defined by the ``require(package_id_mode=xxx)`` trait, that is higher priority\n        # The \"conf\" values are defaults, no hard overrides\n        if self.package_id_mode:\n            return\n\n        if self.test:\n            return  # test_requires never affect the binary_id\n        dep_conanfile = dep_node.conanfile\n        dep_pkg_type = dep_conanfile.package_type\n        if self.build:\n            build_mode = getattr(dep_conanfile, \"build_mode\", build_mode)\n            if build_mode and self.direct:\n                self.package_id_mode = build_mode\n            return\n\n        if pkg_type is PackageType.HEADER:\n            self.package_id_mode = \"unrelated_mode\"\n            return\n\n        # If the dependency defines the mode, that has priority over default\n        embed_mode = getattr(dep_conanfile, \"package_id_embed_mode\", embed_mode)\n        non_embed_mode = getattr(dep_conanfile, \"package_id_non_embed_mode\", non_embed_mode)\n        unknown_mode = getattr(dep_conanfile, \"package_id_unknown_mode\", unknown_mode)\n        if self.headers or self.libs:  # only if linked\n            if pkg_type is PackageType.SHARED or pkg_type is PackageType.APP:\n                if dep_pkg_type is PackageType.SHARED:\n                    self.package_id_mode = non_embed_mode\n                else:\n                    self.package_id_mode = embed_mode\n            elif pkg_type is PackageType.STATIC:\n                if dep_pkg_type is PackageType.HEADER:\n                    self.package_id_mode = embed_mode\n                else:\n                    self.package_id_mode = non_embed_mode\n\n            if self.package_id_mode is None:\n                self.package_id_mode = unknown_mode\n\n        # For cases like Application->Application, without headers or libs, package_id_mode=None\n        # It will be independent by default\n\n\nclass BuildRequirements:\n    # Just a wrapper around requires for backwards compatibility with self.build_requires() syntax\n    def __init__(self, requires):\n        self._requires = requires\n\n    def __call__(self, ref, package_id_mode=None, visible=False, run=None, options=None,\n                 override=None):\n        # TODO: Check which arguments could be user-defined\n        self._requires.build_require(ref, package_id_mode=package_id_mode, visible=visible, run=run,\n                                     options=options, override=override)\n\n\nclass ToolRequirements:\n    # Just a wrapper around requires for backwards compatibility with self.build_requires() syntax\n    def __init__(self, requires):\n        self._requires = requires\n\n    def __call__(self, ref, package_id_mode=None, visible=False, run=True, options=None,\n                 override=None):\n        # TODO: Check which arguments could be user-defined\n        self._requires.tool_require(ref, package_id_mode=package_id_mode, visible=visible, run=run,\n                                    options=options, override=override)\n\n\nclass TestRequirements:\n    # Just a wrapper around requires for backwards compatibility with self.build_requires() syntax\n    def __init__(self, requires):\n        self._requires = requires\n\n    def __call__(self, ref, run=None, options=None, force=None):\n        self._requires.test_require(ref, run=run, options=options, force=force)\n\n\nclass Requirements:\n    \"\"\" User definitions of all requires in a conanfile\n    \"\"\"\n    def __init__(self, declared=None, declared_build=None, declared_test=None,\n                 declared_build_tool=None):\n        self._requires = {}\n        # Construct from the class definitions\n        if declared is not None:\n            if isinstance(declared, str):\n                self.__call__(declared)\n            else:\n                try:\n                    for item in declared:\n                        if not isinstance(item, str):\n                            # TODO (2.X): Remove protection after transition from 1.X\n                            raise ConanException(f\"Incompatible 1.X requires declaration '{item}'\")\n                        self.__call__(item)\n                except TypeError:\n                    raise ConanException(\"Wrong 'requires' definition, \"\n                                         \"did you mean 'requirements()'?\")\n        if declared_build is not None:\n            if isinstance(declared_build, str):\n                self.build_require(declared_build)\n            else:\n                try:\n                    for item in declared_build:\n                        self.build_require(item)\n                except TypeError:\n                    raise ConanException(\"Wrong 'build_requires' definition, \"\n                                         \"did you mean 'build_requirements()'?\")\n        if declared_test is not None:\n            if isinstance(declared_test, str):\n                self.test_require(declared_test)\n            else:\n                try:\n                    for item in declared_test:\n                        self.test_require(item)\n                except TypeError:\n                    raise ConanException(\"Wrong 'test_requires' definition, \"\n                                         \"did you mean 'build_requirements()'?\")\n        if declared_build_tool is not None:\n            if isinstance(declared_build_tool, str):\n                self.build_require(declared_build_tool, run=True)\n            else:\n                try:\n                    for item in declared_build_tool:\n                        self.build_require(item, run=True)\n                except TypeError:\n                    raise ConanException(\"Wrong 'tool_requires' definition, \"\n                                         \"did you mean 'build_requirements()'?\")\n\n    def reindex(self, require, new_name):\n        \"\"\" This operation is necessary when the reference name of a package is changed\n        as a result of an \"alternative\" replacement of the package name, otherwise the dictionary\n        gets broken by modified key\n        \"\"\"\n        result = {}\n        for k, v in self._requires.items():\n            if k is require:\n                k.ref.name = new_name\n            result[k] = v\n        self._requires = result\n\n    def values(self):\n        return self._requires.values()\n\n    # TODO: Plan the interface for smooth transition from 1.X\n    def __call__(self, str_ref, **kwargs):\n        if str_ref is None:\n            return\n        assert isinstance(str_ref, str)\n        ref = RecipeReference.loads(str_ref)\n        req = Requirement(ref, **kwargs)\n        if self._requires.get(req):\n            raise ConanException(\"Duplicated requirement: {}\".format(ref))\n        self._requires[req] = req\n\n    def build_require(self, ref, raise_if_duplicated=True, package_id_mode=None, visible=False,\n                      run=None, options=None, override=None):\n        \"\"\"\n             Represent a generic build require, could be a tool, like \"cmake\" or a bundle of build\n             scripts.\n\n             visible = False => Only the direct consumer can see it, won't conflict\n             build = True => They run in the build machine (e.g cmake)\n             libs = False => We won't link with it, is a tool, no propagate the libs.\n             headers = False => We won't include headers, is a tool, no propagate the includes.\n             run = None => It will be determined by the package_type of the ref\n        \"\"\"\n        if ref is None:\n            return\n        # FIXME: This raise_if_duplicated is ugly, possibly remove\n        ref = RecipeReference.loads(ref)\n        req = Requirement(ref, headers=False, libs=False, build=True, run=run, visible=visible,\n                          package_id_mode=package_id_mode, options=options, override=override)\n\n        if raise_if_duplicated and self._requires.get(req):\n            raise ConanException(\"Duplicated requirement: {}\".format(ref))\n        self._requires[req] = req\n\n    def test_require(self, ref, run=None, options=None, force=None):\n        \"\"\"\n             Represent a testing framework like gtest\n\n             visible = False => Only the direct consumer can see it, won't conflict\n             build = False => The test are linked in the host context to run in the host machine\n             libs = True => We need to link with gtest\n             headers = True => We need to include gtest.\n             run = None => It will be determined by the package_type of ref, maybe is gtest shared\n        \"\"\"\n        ref = RecipeReference.loads(ref)\n        # visible = False => Only the direct consumer can see it, won't conflict\n        # build = False => They run in host context, e.g the gtest application is a host app\n        # libs = True => We need to link with it\n        # headers = True => We need to include it\n        req = Requirement(ref, headers=True, libs=True, build=False, run=run, visible=False,\n                          test=True, package_id_mode=None, options=options, force=force)\n        if self._requires.get(req):\n            raise ConanException(\"Duplicated requirement: {}\".format(ref))\n        self._requires[req] = req\n\n    def tool_require(self, ref, raise_if_duplicated=True, package_id_mode=None, visible=False,\n                     run=True, options=None, override=None):\n        \"\"\"\n         Represent a build tool like \"cmake\".\n\n         visible = False => Only the direct consumer can see it, won't conflict\n         build = True => They run in the build machine (e.g cmake)\n         libs = False => We won't link with it, is a tool, no propagate the libs.\n         headers = False => We won't include headers, is a tool, no propagate the includes.\n        \"\"\"\n        if ref is None:\n            return\n        # FIXME: This raise_if_duplicated is ugly, possibly remove\n        ref = RecipeReference.loads(ref)\n        req = Requirement(ref, headers=False, libs=False, build=True, run=run, visible=visible,\n                          package_id_mode=package_id_mode, options=options, override=override)\n        if raise_if_duplicated and self._requires.get(req):\n            raise ConanException(\"Duplicated requirement: {}\".format(ref))\n        self._requires[req] = req\n\n    def __repr__(self):\n        return repr(self._requires.values())\n\n    def serialize(self):\n        return [v.serialize() for v in self._requires.values()]\n\n    def __len__(self):\n        return len(self._requires)\n"
  },
  {
    "path": "conan/internal/model/settings.py",
    "content": "import os\n\nimport yaml\n\nfrom conan.internal.cache.home_paths import HomePaths\nfrom conan.internal.default_settings import default_settings_yml\nfrom conan.internal.internal_tools import is_universal_arch\nfrom conan.errors import ConanException\nfrom conan.internal.util.files import save, load\n\n\ndef bad_value_msg(name, value, value_range):\n    return (\"Invalid setting '%s' is not a valid '%s' value.\\nPossible values are %s\\n\"\n            'Read \"http://docs.conan.io/2/knowledge/faq.html#error-invalid-setting\"'\n            # value range can be either a list or a dict, we only want to list the keys\n            % (value, name, [v for v in value_range if v is not None]))\n\n\ndef undefined_field(name, field, fields=None, value=None):\n    value_str = \" for '%s'\" % value if value else \"\"\n    result = [\"'%s.%s' doesn't exist%s\" % (name, field, value_str),\n              \"'%s' possible configurations are %s\" % (name, fields or \"none\")]\n    return ConanException(\"\\n\".join(result))\n\n\nclass SettingsItem:\n    \"\"\" represents a setting value and its child info, which could be:\n    - A range of valid values: [Debug, Release] (for settings.compiler.runtime of VS)\n    - List [None, \"ANY\"] to accept None or any value\n    - A dict {subsetting: definition}, e.g. {version: [], runtime: []} for VS\n    \"\"\"\n    def __init__(self, definition, name, value):\n        self._definition = definition  # range of possible values\n        self._name = name  # settings.compiler\n        self._value = value  # gcc\n\n    @staticmethod\n    def new(definition, name):\n        if definition is None:\n            raise ConanException(f\"Definition of settings.yml '{name}' cannot be null\")\n        if isinstance(definition, dict):\n            parsed_definitions = {}\n            # recursive\n            for k, v in definition.items():\n                # None string from yaml definition maps to python None, means not-defined value\n                k = str(k) if k is not None else None\n                parsed_definitions[k] = Settings(v, name, k)\n        else:\n            # list or tuple of possible values, it can include \"ANY\"\n            parsed_definitions = [str(v) if v is not None else None for v in definition]\n        return SettingsItem(parsed_definitions, name, None)\n\n    def __contains__(self, value):\n        return value in (self._value or \"\")\n\n    def copy(self):\n        \"\"\" deepcopy, recursive\n        \"\"\"\n        if not isinstance(self._definition, dict):\n            definition = self._definition  # Not necessary to copy this, not mutable\n        else:\n            definition = {k: v.copy() for k, v in self._definition.items()}\n        return SettingsItem(definition, self._name, self._value)\n\n    def copy_conaninfo_settings(self):\n        \"\"\" deepcopy, recursive\n        This function adds \"ANY\" to lists, to allow the ``package_id()`` method to modify some of\n        values, but not all, just the \"final\" values without subsettings.\n        We cannot let users manipulate to random strings\n        things that contain subsettings like ``compiler``, because that would leave the thing\n        in an undefined state, with some now inconsistent subsettings, that cannot be accessed\n        anymore. So with this change the options are:\n        - If you need more \"binary-compatible\" descriptions of a compiler, lets say like\n        \"gcc_or_clang\", then you need to add that string to settings.yml. And add the subsettings\n        that you want for it.\n        - Settings that are \"final\" (lists), like build_type, or arch or compiler.version they\n        can get any value without issues.\n        \"\"\"\n        if not isinstance(self._definition, dict):\n            definition = self._definition[:] + [\"ANY\"]\n        else:\n            definition = {k: v.copy_conaninfo_settings() for k, v in self._definition.items()}\n            definition[\"ANY\"] = Settings()\n        return SettingsItem(definition, self._name, self._value)\n\n    def __bool__(self):\n        if not self._value:\n            return False\n        return self._value.lower() not in [\"false\", \"none\", \"0\", \"off\"]\n\n    def __str__(self):\n        return str(self._value)\n\n    def __eq__(self, other):\n        if other is None:\n            return self._value is None\n        other = self._validate(other)\n        return other == self._value\n\n    def __delattr__(self, item):\n        \"\"\" This is necessary to remove libcxx subsetting from compiler in config()\n           del self.settings.compiler.stdlib\n        \"\"\"\n        child_setting = self._get_child(self._value)\n        delattr(child_setting, item)\n\n    def _validate(self, value):\n        value = str(value) if value is not None else None\n        is_universal = is_universal_arch(value, self._definition) if self._name == \"settings.arch\" else False\n        if \"ANY\" not in self._definition and value not in self._definition and not is_universal:\n            raise ConanException(bad_value_msg(self._name, value, self._definition))\n        return value\n\n    def _get_child(self, item):\n        if not isinstance(self._definition, dict):\n            raise undefined_field(self._name, item, None, self._value)\n        if self._value is None:\n            raise ConanException(\"'%s' value not defined\" % self._name)\n        return self._get_definition()\n\n    def _get_definition(self):\n        if self._value not in self._definition and \"ANY\" in self._definition:\n            return self._definition[\"ANY\"]\n        return self._definition[self._value]\n\n    def __getattr__(self, item):\n        item = str(item)\n        sub_config_dict = self._get_child(item)\n        return getattr(sub_config_dict, item)\n\n    def __setattr__(self, item, value):\n        if item[0] == \"_\" or item.startswith(\"value\"):\n            return super(SettingsItem, self).__setattr__(item, value)\n\n        item = str(item)\n        sub_config_dict = self._get_child(item)\n        return setattr(sub_config_dict, item, value)\n\n    @property\n    def value(self):\n        return self._value\n\n    @value.setter\n    def value(self, v):\n        self._value = self._validate(v)\n\n    @property\n    def values_range(self):\n        # This needs to support 2 operations: \"in\" and iteration. Beware it can return \"ANY\"\n        return self._definition\n\n    @property\n    def values_list(self):\n        if self._value is None:\n            return []\n        result = []\n        partial_name = \".\".join(self._name.split(\".\")[1:])\n        result.append((partial_name, self._value))\n        if isinstance(self._definition, dict):\n            sub_config_dict = self._get_definition()\n            result.extend(sub_config_dict.values_list)\n        return result\n\n    def validate(self):\n        if self._value is None and None not in self._definition:\n            raise ConanException(\"'%s' value not defined\" % self._name)\n        if isinstance(self._definition, dict):\n            self._get_definition().validate()\n\n    def possible_values(self):\n        if isinstance(self._definition, list):\n            return self.values_range.copy()\n        ret = {}\n        for key, value in self._definition.items():\n            ret[key] = value.possible_values()\n        return ret\n\n    def rm_safe(self, name):\n        \"\"\" Iterates all possible subsettings, calling rm_safe() for all of them. If removing\n        \"compiler.cppstd\", this will iterate msvc, gcc, clang, etc, calling rm_safe(cppstd) for\n        all of them\"\"\"\n        if isinstance(self._definition, list):\n            return\n        for subsetting in self._definition.values():\n            subsetting.rm_safe(name)\n\n\nclass Settings:\n    def __init__(self, definition=None, name=\"settings\", parent_value=\"settings\"):\n        if parent_value is None and definition:\n            raise ConanException(\"settings.yml: null setting can't have subsettings\")\n        definition = definition or {}\n        if not isinstance(definition, dict):\n            val = \"\" if parent_value == \"settings\" else f\"={parent_value}\"\n            raise ConanException(f\"Invalid settings.yml format: '{name}{val}' is not a dictionary\")\n        self._name = name  # settings, settings.compiler\n        self._parent_value = parent_value  # gcc, x86\n        self._data = {k: SettingsItem.new(v, f\"{name}.{k}\") for k, v in definition.items()}\n        self._frozen = False\n\n    def serialize(self):\n        \"\"\"\n        Returns a dictionary with all the settings (and sub-settings) as ``field: value``\n        \"\"\"\n        ret = []\n        for _, s in self._data.items():\n            # TODO: Refactor it and use s.serialize()\n            ret.extend(s.values_list)\n        return dict(ret)\n\n    def get_safe(self, name, default=None):\n        \"\"\"\n        Get the setting value avoiding throwing if it does not exist or has been removed\n        :param name:\n        :param default:\n        :return:\n        \"\"\"\n        try:\n            tmp = self\n            for prop in name.split(\".\"):\n                tmp = getattr(tmp, prop, None)\n        except ConanException:\n            return default\n        if tmp is not None and tmp.value is not None:  # In case of subsettings is None\n            return tmp.value\n        return default\n\n    def rm_safe(self, name):\n        \"\"\" Removes the setting or subsetting from the definition. For example,\n        rm_safe(\"compiler.cppstd\") remove all \"cppstd\" subsetting from all compilers, irrespective\n        of the current value of the \"compiler\"\n        \"\"\"\n        if \".\" in name:\n            setting, remainder = name.split(\".\", 1)  # setting=compiler, remainder = cppstd\n            try:\n                self._data[setting].rm_safe(remainder)  # call rm_safe(\"cppstd\") for the \"compiler\"\n            except KeyError:\n                pass\n        else:\n            if name == \"*\":\n                self.clear()\n            else:\n                self._data.pop(name, None)\n\n    def copy(self):\n        \"\"\" deepcopy, recursive\n        \"\"\"\n        result = Settings({}, name=self._name, parent_value=self._parent_value)\n        result._data = {k: v.copy() for k, v in self._data.items()}\n        return result\n\n    def copy_conaninfo_settings(self):\n        result = Settings({}, name=self._name, parent_value=self._parent_value)\n        result._data = {k: v.copy_conaninfo_settings() for k, v in self._data.items()}\n        return result\n\n    @staticmethod\n    def loads(text):\n        try:\n            return Settings(yaml.safe_load(text) or {})\n        except (yaml.YAMLError, AttributeError) as ye:\n            raise ConanException(\"Invalid settings.yml format: {}\".format(ye))\n\n    def validate(self):\n        for child in self._data.values():\n            child.validate()\n\n    @property\n    def fields(self):\n        return sorted(list(self._data.keys()))\n\n    def clear(self):\n        self._data = {}\n\n    def _check_field(self, field):\n        if field not in self._data:\n            raise undefined_field(self._name, field, self.fields, self._parent_value)\n\n    def __getattr__(self, field):\n        assert field[0] != \"_\", \"ERROR %s\" % field\n        self._check_field(field)\n        return self._data[field]\n\n    def __delattr__(self, field):\n        assert field[0] != \"_\", \"ERROR %s\" % field\n        self._check_field(field)\n        del self._data[field]\n\n    def __setattr__(self, field, value):\n        if field[0] == \"_\":\n            return super(Settings, self).__setattr__(field, value)\n\n        self._check_field(field)\n        if self._frozen:\n            raise ConanException(f\"Tried to define '{field}' setting inside recipe\")\n        self._data[field].value = value\n\n    @property\n    def values_list(self):\n        # TODO: make it private, leave .items accessor only\n        result = []\n        for field in self.fields:\n            config_item = self._data[field]\n            result.extend(config_item.values_list)\n        return result\n\n    def items(self):\n        return self.values_list\n\n    def update_values(self, values, raise_undefined=True):\n        \"\"\"\n        Receives a list of tuples (compiler.version, value)\n        This is more an updater than a setter.\n        \"\"\"\n        self._frozen = False  # Could be restored at the end, but not really necessary\n        assert isinstance(values, (list, tuple)), values\n        for (name, value) in values:\n            list_settings = name.split(\".\")\n            attr = self\n            try:\n                for setting in list_settings[:-1]:\n                    attr = getattr(attr, setting)\n                value = str(value) if value is not None else None\n                setattr(attr, list_settings[-1], value)\n            except ConanException:  # fails if receiving settings doesn't have it defined\n                if raise_undefined:\n                    raise\n\n    def constrained(self, constraint_def):\n        \"\"\" allows to restrict a given Settings object with the input of another Settings object\n        1. The other Settings object MUST be exclusively a subset of the former.\n           No additions allowed\n        2. If the other defines {\"compiler\": None} means to keep the full specification\n        \"\"\"\n        constraint_def = constraint_def or []\n        if not isinstance(constraint_def, (list, tuple, set)):\n            raise ConanException(\"Please defines settings as a list or tuple\")\n\n        for field in constraint_def:\n            self._check_field(field)\n\n        to_remove = [k for k in self._data if k not in constraint_def]\n        for k in to_remove:\n            del self._data[k]\n\n    def dumps(self):\n        \"\"\" produces a text string with lines containing a flattened version:\n        compiler.arch = XX\n        compiler.arch.speed = YY\n        \"\"\"\n        result = []\n        for (name, value) in self.values_list:\n            # It is important to discard None values, so migrations in settings can be done\n            # without breaking all existing packages SHAs, by adding a first None option\n            # that doesn't change the final sha\n            if value is not None:\n                result.append(\"%s=%s\" % (name, value))\n        return '\\n'.join(result)\n\n    def possible_values(self):\n        \"\"\"Check the range of values of the definition of a setting\n        \"\"\"\n        ret = {}\n        for key, element in self._data.items():\n            ret[key] = element.possible_values()\n        return ret\n\n\ndef load_settings_yml(home_folder):\n    \"\"\"Returns {setting: [value, ...]} defining all the possible\n               settings without values\"\"\"\n    _home_paths = HomePaths(home_folder)\n    settings_path = _home_paths.settings_path\n    if not os.path.exists(settings_path):\n        save(settings_path, default_settings_yml)\n        save(settings_path + \".orig\", default_settings_yml)  # stores a copy, to check migrations\n\n    def _load_settings(path):\n        try:\n            return yaml.safe_load(load(path)) or {}\n        except yaml.YAMLError as ye:\n            raise ConanException(\"Invalid settings.yml format: {}\".format(ye))\n\n    settings = _load_settings(settings_path)\n    user_settings_file = _home_paths.settings_path_user\n    if os.path.exists(user_settings_file):\n        settings_user = _load_settings(user_settings_file)\n\n        def appending_recursive_dict_update(d, u):\n            # Not the same behavior as conandata_update, because this append lists\n            for k, v in u.items():\n                if isinstance(v, list):\n                    current = d.get(k) or []\n                    d[k] = current + [value for value in v if value not in current]\n                elif isinstance(v, dict):\n                    current = d.get(k) or {}\n                    if isinstance(current, list):  # convert to dict lists\n                        current = {k: None for k in current}\n                    d[k] = appending_recursive_dict_update(current, v)\n                else:\n                    d[k] = v\n            return d\n\n        appending_recursive_dict_update(settings, settings_user)\n\n    return Settings(settings)\n"
  },
  {
    "path": "conan/internal/model/version.py",
    "content": "from functools import total_ordering\nfrom typing import Optional\n\nfrom conan.errors import ConanException\n\n\n@total_ordering\nclass _VersionItem:\n    \"\"\" a single \"digit\" in a version, like X.Y.Z all X and Y and Z are VersionItems\n    They can be int or strings\n    \"\"\"\n    def __init__(self, item):\n        try:\n            self._v = int(item)\n        except ValueError:\n            self._v = item\n\n    @property\n    def value(self):\n        return self._v\n\n    def __str__(self):\n        return str(self._v)\n\n    def __add__(self, other):\n        # necessary for the \"bump()\" functionality. Other aritmetic operations are missing\n        return self._v + other\n\n    def __eq__(self, other):\n        if not isinstance(other, _VersionItem):\n            other = _VersionItem(other)\n        return self._v == other._v\n\n    def __hash__(self):\n        return hash(self._v)\n\n    def __lt__(self, other):\n        \"\"\"\n        @type other: _VersionItem\n        \"\"\"\n        if not isinstance(other, _VersionItem):\n            other = _VersionItem(other)\n        try:\n            return self._v < other._v\n        except TypeError:\n            return str(self._v) < str(other._v)\n\n\n@total_ordering\nclass Version:\n    \"\"\"\n    This is NOT an implementation of semver, as users may use any pattern in their versions.\n    It is just a helper to parse \".\" or \"-\" and compare taking into account integers when possible\n    \"\"\"\n    def __init__(self, value, qualifier=False):\n        value = str(value)\n        self._value = value\n        self._build = None\n        self._pre = None\n        self._qualifier = qualifier  # it is a prerelease or build qualifier, not a main version\n\n        if not qualifier:\n            items = value.rsplit(\"+\", 1)  # split for build\n            if len(items) == 2:\n                value, build = items\n                self._build = Version(build, qualifier=True)  # This is a nested version by itself\n\n            # split for pre-release, from the left, semver allows hyphens in identifiers :(\n            items = value.split(\"-\", 1)\n            if len(items) == 2:\n                value, pre = items\n                self._pre = Version(pre, qualifier=True)  # This is a nested version by itself\n\n        items = value.split(\".\")\n        items = [_VersionItem(item) for item in items]\n        self._items = tuple(items)\n        while items and items[-1].value == 0:\n            del items[-1]\n        self._nonzero_items = tuple(items)\n\n    def bump(self, index):\n        \"\"\"\n        :meta private:\n            Bump the version\n            Increments by 1 the version field at the specified index, setting to 0 the fields\n            on the right.\n            2.5 => bump(1) => 2.6\n            1.5.7 => bump(0) => 2.0.0\n\n        :param index:\n        \"\"\"\n        # this method is used to compute version ranges from tilde ~1.2 and caret ^1.2.1 ranges\n        # TODO: at this moment it only works for digits, cannot increment pre-release or builds\n        # better not make it public yet, keep it internal\n        items = list(self._items[:index])\n        try:\n            items.append(self._items[index]+1)\n        except TypeError:\n            raise ConanException(f\"Cannot bump '{self._value} version index {index}, not an int\")\n        items.extend([0] * (len(items) - index - 1))\n        v = \".\".join(str(i) for i in items)\n        # prerelease and build are dropped while bumping digits\n        return Version(v)\n\n    def upper_bound(self, index):\n        items = list(self._items[:index])\n        try:\n            items.append(self._items[index] + 1)\n        except TypeError:\n            raise ConanException(f\"Cannot bump '{self._value} version index {index}, not an int\")\n        items.extend([0] * (len(items) - index - 1))\n        v = \".\".join(str(i) for i in items)\n        v += \"-\"  # Exclude prereleases\n        return Version(v)\n\n    @property\n    def pre(self):\n        return self._pre\n\n    @property\n    def build(self):\n        return self._build\n\n    @property\n    def main(self):\n        return self._items\n\n    @property\n    def major(self):\n        try:\n            return self.main[0]\n        except IndexError:\n            return None\n\n    @property\n    def minor(self):\n        try:\n            return self.main[1]\n        except IndexError:\n            return None\n\n    @property\n    def patch(self):\n        try:\n            return self.main[2]\n        except IndexError:\n            return None\n\n    @property\n    def micro(self):\n        try:\n            return self.main[3]\n        except IndexError:\n            return None\n\n    def __str__(self):\n        return self._value\n\n    def __repr__(self):\n        return self._value\n\n    def __eq__(self, other):\n        if other is None:\n            return False\n        if not isinstance(other, Version):\n            other = Version(other, self._qualifier)\n\n        return (self._nonzero_items, self._pre, self._build) ==\\\n               (other._nonzero_items, other._pre, other._build)\n\n    def __hash__(self):\n        return hash((self._nonzero_items, self._pre, self._build))\n\n    def __lt__(self, other):\n        if other is None:\n            return False\n        if not isinstance(other, Version):\n            other = Version(other)\n\n        if self._pre:\n            if other._pre:  # both are pre-releases\n                return (self._nonzero_items, self._pre, self._build) < \\\n                       (other._nonzero_items, other._pre, other._build)\n            else:  # Left hand is pre-release, right side is regular\n                if self._nonzero_items == other._nonzero_items:  # Problem only happens if both equal\n                    return True\n                else:\n                    return self._nonzero_items < other._nonzero_items\n        else:\n            if other._pre:  # Left hand is regular, right side is pre-release\n                if self._nonzero_items == other._nonzero_items:  # Problem only happens if both equal\n                    return False\n                else:\n                    return self._nonzero_items < other._nonzero_items\n            else:  # None of them is pre-release\n                return (self._nonzero_items, self._build) < (other._nonzero_items, other._build)\n\n    def in_range(self, version_range: str, resolve_prerelease: Optional[bool] = None):\n        \"\"\" Check if the version is in the specified range \"\"\"\n        from conan.internal.model.version_range import VersionRange\n        return VersionRange(version_range).contains(self, resolve_prerelease=resolve_prerelease)\n"
  },
  {
    "path": "conan/internal/model/version_range.py",
    "content": "from functools import total_ordering\nfrom typing import Optional\n\nfrom conan.internal.model.version import Version\nfrom conan.errors import ConanException\n\n\n@total_ordering\nclass _Condition:\n    def __init__(self, operator, version):\n        self.operator = operator\n        self.display_version = version\n\n        value = str(version)\n        if (operator == \">=\" or operator == \"<\") and \"-\" not in value and version.build is None:\n            value += \"-\"\n        self.version = Version(value)\n\n    def __str__(self):\n        return f\"{self.operator}{self.display_version}\"\n\n    def __repr__(self):\n        return self.__str__()\n\n    def __hash__(self):\n        return hash((self.operator, self.version))\n\n    def __lt__(self, other):\n        # Notice that this is done on the modified version, might contain extra prereleases\n        if self.version < other.version:\n            return True\n        elif self.version == other.version:\n            if self.operator == \"<\":\n                if other.operator == \"<\":\n                    return self.display_version.pre is not None\n                else:\n                    return True\n            elif self.operator == \"<=\":\n                if other.operator == \"<\":\n                    return False\n                else:\n                    return self.display_version.pre is None\n            elif self.operator == \">\":\n                if other.operator == \">\":\n                    return self.display_version.pre is None\n                else:\n                    return False\n            else:\n                if other.operator == \">\":\n                    return True\n                # There's a possibility of getting here while validating if a range is non-void\n                # by comparing >= & <= for lower limit <= upper limit\n                elif other.operator == \"<=\":\n                    return True\n                else:\n                    return self.display_version.pre is not None\n        return False\n\n    def __eq__(self, other):\n        return (self.display_version == other.display_version and\n                self.operator == other.operator)\n\n\nclass _ConditionSet:\n\n    def __init__(self, expression, prerelease):\n        expressions = expression.split()\n        if not expressions:\n            # Guarantee at least one expression\n            expressions = [\"\"]\n\n        self.prerelease = prerelease\n        self.conditions = []\n        for e in expressions:\n            e = e.strip()\n            self.conditions.extend(self._parse_expression(e))\n\n    @staticmethod\n    def _parse_expression(expression):\n        if expression in (\"\", \"*\"):\n            return [_Condition(\">=\", Version(\"0.0.0\"))]\n        elif len(expression) == 1:\n            raise ConanException(f'Error parsing version range \"{expression}\"')\n\n        operator = expression[0]\n        if operator not in (\">\", \"<\", \"^\", \"~\", \"=\"):\n            if expression[-1] == \"*\":  # Handle patterns like \"1.2.*\"\n                operator = \"*\"\n                expression = expression[:-1]\n            else:\n                operator = \"=\"\n            index = 0\n        else:\n            index = 1\n        if operator in (\">\", \"<\"):\n            if expression[1] == \"=\":\n                operator += \"=\"\n                index = 2\n        elif expression[1] == \"=\":\n            raise ConanException(f\"Invalid version range operator '{operator}=' in {expression}, you should probably use {operator} instead.\")\n        version = expression[index:]\n        if version == \"\":\n            raise ConanException(f'Error parsing version range \"{expression}\"')\n        if operator == \"~\":  # tilde minor\n            if \"-\" not in version:\n                version += \"-\"\n            v = Version(version)\n            index = 1 if len(v.main) > 1 else 0\n            return [_Condition(\">=\", v), _Condition(\"<\", v.upper_bound(index))]\n        elif operator == \"^\":  # caret major\n            v = Version(version)\n\n            def first_non_zero(main):\n                for i, m in enumerate(main):\n                    if m != 0:\n                        return i\n                return len(main)\n\n            initial_index = first_non_zero(v.main)\n            return [_Condition(\">=\", v), _Condition(\"<\", v.upper_bound(initial_index))]\n        else:\n            return [_Condition(operator, Version(version))]\n\n    def valid(self, version, conf_resolve_prepreleases):\n        if version.pre:\n            # Follow the expression desires only if core.version_ranges:resolve_prereleases is None,\n            # else force to the conf's value\n            if conf_resolve_prepreleases is None:\n                if not self.prerelease:\n                    return False\n            elif conf_resolve_prepreleases is False:\n                return False\n        for condition in self.conditions:\n            if condition.operator == \">\":\n                if not version > condition.version:\n                    return False\n            elif condition.operator == \"<\":\n                if not version < condition.version:\n                    return False\n            elif condition.operator == \">=\":\n                if not version >= condition.version:\n                    return False\n            elif condition.operator == \"<=\":\n                if not version <= condition.version:\n                    return False\n            elif condition.operator == \"=\":\n                if not version == condition.version:\n                    return False\n            elif condition.operator == \"*\":\n                if not str(version).startswith(str(condition.version)):\n                    return False\n        return True\n\n\nclass VersionRange:\n    def __init__(self, expression):\n        self._expression = expression\n        tokens = expression.split(\",\")\n        prereleases = False\n        for t in tokens[1:]:\n            if \"include_prerelease\" in t:\n                if \"include_prerelease=\" in t:\n                    from conan.api.output import ConanOutput\n                    ConanOutput().warning(\n                        f'include_prerelease version range option in \"{expression}\" does not take an attribute, '\n                        'its presence unconditionally enables prereleases')\n                prereleases = True\n                break\n            else:\n                t = t.strip()\n                if len(t) > 0 and t[0].isalpha():\n                    from conan.api.output import ConanOutput\n                    ConanOutput().warning(f'Unrecognized version range option \"{t}\" in \"{expression}\"')\n                else:\n                    raise ConanException(f'\"{t}\" in version range \"{expression}\" is not a valid option')\n        version_expr = tokens[0]\n        self.condition_sets = []\n        for alternative in version_expr.split(\"||\"):\n            self.condition_sets.append(_ConditionSet(alternative, prereleases))\n\n    def __str__(self):\n        return self._expression\n\n    def contains(self, version: Version, resolve_prerelease: Optional[bool]):\n        \"\"\"\n        Whether <version> is inside the version range\n\n        :param version: Version to check against\n        :param resolve_prerelease: If ``True``, ensure prereleases can be resolved in this range\n        If ``False``, prerelases can NOT be resolved in this range\n        If ``None``, prereleases are resolved only if this version range expression says so\n        :return: Whether the version is inside the range\n        \"\"\"\n        assert isinstance(version, Version), type(version)\n        for condition_set in self.condition_sets:\n            if condition_set.valid(version, resolve_prerelease):\n                return True\n        return False\n\n    def intersection(self, other):\n        conditions = []\n\n        def _calculate_limits(operator, lhs, rhs):\n            limits = ([c for c in lhs.conditions if operator in c.operator]\n                      + [c for c in rhs.conditions if operator in c.operator])\n            if limits:\n                return sorted(limits, reverse=operator == \">\")[0]\n\n        prerelease = True\n        for lhs_conditions in self.condition_sets:\n            for rhs_conditions in other.condition_sets:\n                internal_conditions = []\n                lower_limit = _calculate_limits(\">\", lhs_conditions, rhs_conditions)\n                upper_limit = _calculate_limits(\"<\", lhs_conditions, rhs_conditions)\n                if lower_limit:\n                    internal_conditions.append(lower_limit)\n                if upper_limit:\n                    internal_conditions.append(upper_limit)\n                if internal_conditions and (not lower_limit or not upper_limit or lower_limit <= upper_limit):\n                    conditions.append(internal_conditions)\n                # conservative approach: if any of the conditions forbid prereleases, forbid them in the result\n                if not lhs_conditions.prerelease or not rhs_conditions.prerelease:\n                    prerelease = False\n\n        if not conditions:\n            return None\n        expression = ' || '.join(' '.join(str(c) for c in cs) for cs in conditions) + (', include_prerelease' if prerelease else '')\n        result = VersionRange(expression)\n        # TODO: Direct definition of conditions not reparsing\n        # result.condition_sets = self.condition_sets + other.condition_sets\n        return result\n\n    def version(self):\n        return Version(f\"[{self._expression}]\")\n\n\ndef validate_conan_version(required_range):\n    from conan import __version__  # To avoid circular imports\n    clientver = Version(__version__)\n    version_range = VersionRange(required_range)\n    for conditions in version_range.condition_sets:\n        conditions.prerelease = True\n    if not version_range.contains(clientver, resolve_prerelease=None):\n        raise ConanException(\"Current Conan version ({}) does not satisfy \"\n                             \"the defined one ({}).\".format(clientver, required_range))\n"
  },
  {
    "path": "conan/internal/model/workspace.py",
    "content": "import os\nimport shutil\n\nimport yaml\n\nfrom conan.api.output import ConanOutput\nfrom conan.errors import ConanException\nfrom conan.internal.errors import scoped_traceback\nfrom conan.internal.util.files import load, save\n\n# Related folder\nWORKSPACE_FOLDER = \"conanws\"\n# Related files\nWORKSPACE_YML = \"conanws.yml\"\nWORKSPACE_PY = \"conanws.py\"\n\n\nclass Workspace:\n    \"\"\"\n    The base class for all workspaces\n    \"\"\"\n\n    def __init__(self, folder, conan_api):\n        self.folder = folder\n        self.conan_data = self._conan_load_data()\n        self._conan_api = conan_api\n        self.output = ConanOutput(scope=f\"Workspace '{self.name()}'\")\n\n    def __getattribute__(self, item):\n        # Return a protected wrapper around workspace overridable callables in order to\n        # be able to have clean errors if user errors in conanws.py code\n        myattr = object.__getattribute__(self, item)\n        if item not in (\"name\", \"packages\", \"add\", \"remove\", \"clean\", \"build_order\"):\n            return myattr\n\n        def wrapper(*args, **kwargs):\n            try:\n                return myattr(*args, **kwargs)\n            except ConanException:\n                raise\n            except Exception as e:\n                m = scoped_traceback(f\"Error in {item}() method\", e, scope=\"conanws.py\")\n                raise ConanException(f\"Workspace conanws.py file: {m}\")\n        return wrapper\n\n    def name(self):\n        return self.conan_data.get(\"name\") or os.path.basename(self.folder)\n\n    def _conan_load_data(self):\n        data_path = os.path.join(self.folder, WORKSPACE_YML)\n        if not os.path.exists(data_path):\n            return {}\n        try:\n            data = yaml.safe_load(load(data_path))\n        except Exception as e:\n            raise ConanException(\"Invalid yml format at {}: {}\".format(WORKSPACE_YML, e))\n        return data or {}\n\n    def add(self, ref, path, output_folder):\n        if not path or not os.path.isfile(path):\n            raise ConanException(f\"Cannot add to workspace. File not found: {path}\")\n        path = self._conan_rel_path(os.path.dirname(path))\n        editable = {\n            \"path\": path,\n            \"ref\": str(ref)\n        }\n        if output_folder:\n            editable[\"output_folder\"] = self._conan_rel_path(output_folder)\n        packages = self.conan_data.setdefault(\"packages\", [])\n        for p in packages:\n            if p[\"path\"] == path:\n                self.output.warning(f\"Package {path} already exists, updating its reference\")\n                p[\"ref\"] = editable[\"ref\"]\n                break\n        else:\n            packages.append(editable)\n        save(os.path.join(self.folder, WORKSPACE_YML), yaml.dump(self.conan_data))\n\n    def remove(self, path):\n        path = self._conan_rel_path(path)\n        package_found = next((package_info for package_info in self.conan_data.get(\"packages\", [])\n                              if package_info[\"path\"].replace(\"\\\\\", \"/\") == path), None)\n        if not package_found:\n            raise ConanException(f\"No editable package to remove from this path: {path}\")\n        self.conan_data[\"packages\"].remove(package_found)\n        save(os.path.join(self.folder, WORKSPACE_YML), yaml.dump(self.conan_data))\n        return path\n\n    def clean(self):\n        self.output.info(\"Default workspace clean: Removing the output-folder of each editable\")\n        for package_info in self.conan_data.get(\"packages\", []):\n            editable_label = package_info.get(\"ref\", \"\") or package_info['path']\n            if not package_info.get(\"output_folder\"):\n                self.output.info(f\"Editable {editable_label} doesn't have an output_folder defined\")\n                continue\n            of = os.path.join(self.folder, package_info[\"output_folder\"])\n            try:\n                self.output.info(f\"Removing {editable_label} output folder: {of}\")\n                shutil.rmtree(of)\n            except OSError as e:\n                self.output.warning(f\"Error removing {editable_label} output folder: {str(e)}\")\n\n    def _conan_rel_path(self, path):\n        if path is None:\n            return None\n        if not os.path.isabs(path):\n            raise ConanException(f\"Editable path must be absolute: {path}\")\n        path = os.path.relpath(path, self.folder)\n        return path.replace(\"\\\\\", \"/\")  # Normalize to unix path\n\n    def packages(self):\n        return self.conan_data.get(\"packages\", [])\n\n    def load_conanfile(self, conanfile_path):\n        conanfile_path = os.path.join(self.folder, conanfile_path, \"conanfile.py\")\n        from conan.internal.loader import ConanFileLoader\n        from conan.internal.cache.home_paths import HomePaths\n        from conan.internal.conan_app import ConanFileHelpers, CmdWrapper\n        cmd_wrap = CmdWrapper(HomePaths(self._conan_api.home_folder).wrapper_path)\n        helpers = ConanFileHelpers(None, cmd_wrap, self._conan_api._api_helpers.global_conf,\n                                   cache=None, home_folder=self._conan_api.home_folder, conan_api=self._conan_api)\n        loader = ConanFileLoader(pyreq_loader=None, conanfile_helpers=helpers)\n        conanfile = loader.load_named(conanfile_path, name=None, version=None, user=None,\n                                      channel=None, remotes=None, graph_lock=None)\n        return conanfile\n\n    def root_conanfile(self):  # noqa\n        return None\n\n    def build_order(self, order):  # noqa\n        msg = [\"Packages build order:\"]\n        for level in order:\n            for item in level:\n                msg.append(f\"    {item['ref']}: {item['folder']}\")\n        self.output.info(\"\\n\".join(msg))\n"
  },
  {
    "path": "conan/internal/paths.py",
    "content": "import os\nimport platform\nfrom pathlib import Path\n\nfrom conan.errors import ConanException\n\nif platform.system() == \"Windows\":\n    def _conan_expand_user(path):\n        \"\"\" wrapper to the original expanduser function, to workaround python returning\n        verbatim %USERPROFILE% when some other app (git for windows) sets HOME envvar\n        \"\"\"\n        path = str(path)\n        if path[0] != '~':\n            return path\n        # In win these variables should exist and point to user directory, which\n        # must exist.\n        home = os.environ.get(\"HOME\")\n        try:\n            # Problematic cases of wrong HOME variable\n            # - HOME = %USERPROFILE% verbatim, as messed by some other tools\n            # - MSYS console, that defines a different user home in /c/mingw/msys/users/xxx\n            # In these cases, it is safe to remove it and rely on USERPROFILE directly\n            if home and (not os.path.exists(home) or\n                         (os.getenv(\"MSYSTEM\") and os.getenv(\"USERPROFILE\"))):\n                del os.environ[\"HOME\"]\n            result = os.path.expanduser(path)\n        finally:\n            if home is not None:\n                os.environ[\"HOME\"] = home\n        return result\nelse:\n    _conan_expand_user = os.path.expanduser\n\nDEFAULT_CONAN_HOME = \".conan2\"\n\n\ndef find_file_walk_up(start, filename, end=None):\n    path = Path(start)\n    end = Path(end) if end else None\n    while True:\n        file = path / filename\n        if file.is_file():\n            return file\n        if len(path.parts) == 1:  # finish at '/'\n            break\n        if end and path == end:\n            break\n        path = path.parent\n    return None\n\n\ndef get_conan_user_home():\n\n    def _user_home_from_conanrc_file():\n        try:\n            conanrc_path = find_file_walk_up(os.getcwd(), \".conanrc\")\n\n            with open(conanrc_path) as conanrc_file:\n                values = {k: str(v) for k, v in\n                          (line.split('=') for line in conanrc_file.read().splitlines() if\n                           not line.startswith(\"#\"))}\n\n            conan_home = values[\"conan_home\"]\n            # check if it's a local folder\n            if conan_home[:2] in (\"./\", \".\\\\\") or conan_home.startswith(\"..\"):\n                conan_home = conanrc_path.parent.absolute() / conan_home\n            return conan_home\n        except (OSError, KeyError, TypeError):\n            return None\n\n    user_home = _user_home_from_conanrc_file() or os.getenv(\"CONAN_HOME\")\n    if user_home is None:\n        # the default, in the user home\n        user_home = os.path.join(_conan_expand_user(\"~\"), DEFAULT_CONAN_HOME)\n    else:  # Do an expansion, just in case the user is using ~/something/here\n        user_home = _conan_expand_user(user_home)\n    if not os.path.isabs(user_home):\n        raise ConanException(\"Invalid CONAN_HOME value '%s', \"\n                             \"please specify an absolute or path starting with ~/ \"\n                             \"(relative to user home)\" % user_home)\n    return user_home\n\n\n# Files\nCONANFILE = 'conanfile.py'\nCONANFILE_TXT = \"conanfile.txt\"\nCONAN_MANIFEST = \"conanmanifest.txt\"\nCONANINFO = \"conaninfo.txt\"\nPACKAGE_FILE_NAME = \"conan_package.t\"\nEXPORT_FILE_NAME = \"conan_export.t\"\nEXPORT_SOURCES_FILE_NAME = \"conan_sources.t\"\nCOMPRESSIONS = \"gz\", \"xz\", \"zst\"\nDATA_YML = \"conandata.yml\"\n"
  },
  {
    "path": "conan/internal/rest/__init__.py",
    "content": "import json\n\n\ndef response_to_str(response):\n    content = response.content\n    try:\n        # A bytes message, decode it as str\n        if isinstance(content, bytes):\n            content = content.decode()\n\n        content_type = response.headers.get(\"content-type\")\n\n        if content_type == \"application/json\":\n            # Errors from Artifactory looks like:\n            #  {\"errors\" : [ {\"status\" : 400, \"message\" : \"Bla bla bla\"}]}\n            try:\n                data = json.loads(content)[\"errors\"][0]\n                content = \"{}: {}\".format(data[\"status\"], data[\"message\"])\n            except Exception:\n                pass\n        elif \"text/html\" in content_type:\n            content = \"{}: {}\".format(response.status_code, response.reason)\n\n        return content\n\n    except Exception:\n        return response.content\n"
  },
  {
    "path": "conan/internal/rest/auth_manager.py",
    "content": "\"\"\"\nCollaborate with RestApiClient to make remote anonymous and authenticated calls.\nUses user_input to request user's login and password and obtain a token for calling authenticated\nmethods if receives AuthenticationException from RestApiClient.\n\n\nFlow:\n    Directly invoke a REST method in RestApiClient, example: get_conan.\n    if receives AuthenticationException (not open method) will ask user for login and password\n    (with LOGIN_RETRIES retries) and retry to call with the new token.\n\"\"\"\n\nfrom conan.api.output import ConanOutput\nfrom conan.internal.rest.remote_credentials import RemoteCredentials\nfrom conan.internal.rest.rest_client import RestApiClient\nfrom conan.internal.errors import AuthenticationException, ForbiddenException\nfrom conan.errors import ConanException\n\nLOGIN_RETRIES = 3\n\n\nclass _RemoteCreds:\n    def __init__(self, localdb):\n        self._localdb = localdb\n\n    def get(self, remote, msg=True):\n        creds = getattr(remote, \"_creds\", None)\n        if creds is None:\n            user, token, _ = self._localdb.get_login(remote.url)\n            creds = user, token\n            if msg:\n                usermsg = f\"with user '{user}'\" if user else \"anonymously\"\n                ConanOutput().info(f\"Connecting to remote '{remote.name}' {usermsg}\")\n            setattr(remote, \"_creds\", creds)\n        return creds\n\n    def set(self, remote, user, token):\n        setattr(remote, \"_creds\", (user, token))\n        ConanOutput().success(f\"Authenticated in remote '{remote.name}' with user '{user}'\")\n        self._localdb.store(user, token, None, remote.url)\n\n\nclass ConanApiAuthManager:\n\n    def __init__(self, requester, cache_folder, localdb, global_conf):\n        self._requester = requester\n        self._creds = _RemoteCreds(localdb)\n        self._global_conf = global_conf\n        self._cache_folder = cache_folder\n\n    def call_rest_api_method(self, remote, method_name, *args, **kwargs):\n        \"\"\"Handles AuthenticationException and request user to input a user and a password\"\"\"\n        user, token = self._creds.get(remote, msg=(method_name != \"authenticate\"))\n        rest_client = RestApiClient(remote, token, self._requester, self._global_conf)\n\n        if method_name == \"authenticate\":\n            return self._authenticate(rest_client, remote, *args, **kwargs)\n\n        try:\n            ret = getattr(rest_client, method_name)(*args, **kwargs)\n            return ret\n        except ForbiddenException as e:\n            raise ForbiddenException(f\"Permission denied for user: '{user}': {e}\")\n        except AuthenticationException:\n            # User valid but not enough permissions\n            # token is None when you change user with user command\n            # Anonymous is not enough, ask for a user\n            ConanOutput().info(f\"Remote '{remote.name}' needs authentication, obtaining credentials\")\n            if self._get_credentials_and_authenticate(rest_client, user, remote):\n                return self.call_rest_api_method(remote, method_name, *args, **kwargs)\n\n    def _get_credentials_and_authenticate(self, rest_client, user, remote):\n        \"\"\"Try LOGIN_RETRIES to obtain a password from user input for which\n        we can get a valid token from api_client. If a token is returned,\n        credentials are stored in localdb and rest method is called\"\"\"\n        creds = RemoteCredentials(self._cache_folder, self._global_conf)\n        for _ in range(LOGIN_RETRIES):\n            input_user, input_password, interactive = creds.auth(remote)\n            try:\n                self._authenticate(rest_client, remote, input_user, input_password)\n            except AuthenticationException:\n                out = ConanOutput()\n                if user is None:\n                    out.error('Wrong user or password', error_type=\"exception\")\n                else:\n                    out.error(f'Wrong password for user \"{user}\"', error_type=\"exception\")\n                if not interactive:\n                    raise AuthenticationException(f\"Authentication error in remote '{remote.name}'\")\n            else:\n                return True\n        raise AuthenticationException(\"Too many failed login attempts, bye!\")\n\n    def _authenticate(self, rest_client, remote, user, password):\n        try:\n            token = rest_client.authenticate(user, password)\n        except UnicodeDecodeError:\n            raise ConanException(\"Password contains not allowed symbols\")\n\n        # Store result in DB\n        self._creds.set(remote, user, token)\n"
  },
  {
    "path": "conan/internal/rest/caching_file_downloader.py",
    "content": "import os\nimport shutil\n\nfrom urllib.parse import urlparse\nfrom urllib.request import url2pathname\n\nfrom conan.api.output import ConanOutput\nfrom conan.internal.cache.home_paths import HomePaths\nfrom conan.internal.rest.file_downloader import FileDownloader\nfrom conan.internal.rest.download_cache import DownloadCache\nfrom conan.internal.errors import AuthenticationException, ForbiddenException, NotFoundException\nfrom conan.errors import ConanException\nfrom conan.internal.util.files import mkdir, set_dirty_context_manager, remove_if_dirty, human_size\n\n\nclass SourcesCachingDownloader:\n    \"\"\" Class for downloading recipe download() urls\n    if the config is active, it can use caching/backup-sources\n    \"\"\"\n    def __init__(self, conanfile):\n        helpers = getattr(conanfile, \"_conan_helpers\")\n        self._global_conf = helpers.global_conf\n        self._file_downloader = FileDownloader(helpers.requester, scope=conanfile.display_name,\n                                               source_credentials=True)\n        self._home_folder = helpers.home_folder\n        self._output = conanfile.output\n        self._conanfile = conanfile\n\n    def download(self, urls, file_path,\n                 retry, retry_wait, verify_ssl, auth, headers, md5, sha1, sha256):\n        download_cache_folder = self._global_conf.get(\"core.sources:download_cache\")\n        backups_urls = self._global_conf.get(\"core.sources:download_urls\", check_type=list)\n        if not (backups_urls or download_cache_folder) or not sha256:\n            # regular, non backup/caching download\n            if backups_urls or download_cache_folder:\n                self._output.warning(\"Cannot cache download() without sha256 checksum\")\n            self._download_from_urls(urls, file_path, retry, retry_wait, verify_ssl, auth, headers,\n                                     md5, sha1, sha256)\n        else:\n            self._caching_download(urls, file_path,\n                                   retry, retry_wait, verify_ssl, auth, headers, md5, sha1, sha256,\n                                   download_cache_folder, backups_urls)\n\n    def _caching_download(self, urls, file_path,\n                          retry, retry_wait, verify_ssl, auth, headers, md5, sha1, sha256,\n                          download_cache_folder, backups_urls):\n        \"\"\"\n        this download will first check in the local cache, if not there, it will go to the list\n        of backup_urls defined by user conf (by default [\"origin\"]), and iterate it until\n        something is found.\n        \"\"\"\n        # We are going to use the download_urls definition for backups\n        download_cache_folder = download_cache_folder or HomePaths(self._home_folder).default_sources_backup_folder\n        # regular local shared download cache, not using Conan backup sources servers\n        backups_urls = backups_urls or [\"origin\"]\n        if download_cache_folder and not os.path.isabs(download_cache_folder):\n            raise ConanException(\"core.download:download_cache must be an absolute path\")\n\n        download_cache = DownloadCache(download_cache_folder)\n        cached_path = download_cache.source_path(sha256)\n        with download_cache.lock(sha256):\n            remove_if_dirty(cached_path)\n\n            if os.path.exists(cached_path):\n                self._output.info(f\"Source {urls} retrieved from local download cache\")\n            else:\n                with set_dirty_context_manager(cached_path):\n                    if None in backups_urls:\n                        raise ConanException(\"Trying to download sources from None backup remote.\"\n                                             f\" Remotes were: {backups_urls}\")\n                    for backup_url in backups_urls:\n                        is_last = backup_url is backups_urls[-1]\n                        if backup_url == \"origin\":  # recipe defined URLs\n                            if self._origin_download(urls, cached_path, retry, retry_wait,\n                                                     verify_ssl, auth, headers, md5, sha1, sha256,\n                                                     is_last):\n                                break\n                        else:\n                            if self._backup_download(backup_url, backups_urls, sha256, cached_path,\n                                                     urls, is_last):\n                                break\n\n            download_cache.update_backup_sources_json(cached_path, self._conanfile, urls)\n            # Everything good, file in the cache, just copy it to final destination\n            mkdir(os.path.dirname(file_path))\n            shutil.copy2(cached_path, file_path)\n\n    def _origin_download(self, urls, cached_path, retry, retry_wait,\n                         verify_ssl, auth, headers, md5, sha1, sha256, is_last):\n        \"\"\" download from the internet, the urls provided by the recipe (mirrors).\n        \"\"\"\n        try:\n            self._download_from_urls(urls, cached_path, retry, retry_wait,\n                                     verify_ssl, auth, headers, md5, sha1, sha256)\n        except ConanException as e:\n            if is_last:\n                raise\n            else:\n                # TODO: Improve printing of AuthenticationException\n                self._output.warning(f\"Sources for {urls} failed in 'origin': {e}\")\n                self._output.warning(\"Checking backups\")\n        else:\n            if not is_last:\n                self._output.info(f\"Sources for {urls} found in origin\")\n            return True\n\n    def _backup_download(self, backup_url, backups_urls, sha256, cached_path, urls, is_last):\n        \"\"\" download from a Conan backup sources file server, like an Artifactory generic repo\n        All failures are bad, except NotFound. The server must be live, working and auth, we\n        don't want silently skipping a backup because it is down.\n        \"\"\"\n        try:\n            backup_url = backup_url if backup_url.endswith(\"/\") else backup_url + \"/\"\n            self._file_downloader.download(backup_url + sha256, cached_path, sha256=sha256)\n            self._file_downloader.download(backup_url + sha256 + \".json\", cached_path + \".json\")\n            self._output.info(f\"Sources for {urls} found in remote backup {backup_url}\")\n            return True\n        except NotFoundException:\n            if is_last:\n                raise NotFoundException(f\"File {urls} not found in {backups_urls}\")\n            else:\n                self._output.warning(f\"File {urls} not found in {backup_url}\")\n        except (AuthenticationException, ForbiddenException) as e:\n            raise ConanException(f\"Authentication to source backup server '{backup_url}' \"\n                                 f\"failed: {e}. \"\n                                 f\"Please check your 'source_credentials.json'\")\n\n    def _download_from_urls(self, urls, file_path, retry, retry_wait, verify_ssl, auth, headers,\n                            md5, sha1, sha256):\n        \"\"\" iterate the recipe provided list of urls (mirrors, all with same checksum) until\n        one succeed\n        \"\"\"\n        os.makedirs(os.path.dirname(file_path), exist_ok=True)  # filename in subfolder must exist\n        if not isinstance(urls, (list, tuple)):\n            urls = [urls]\n        for url in urls:\n            try:\n                if url.startswith(\"file:\"):  # plain copy from local disk, no real download\n                    file_origin = url2pathname(urlparse(url).path)\n                    shutil.copyfile(file_origin, file_path)\n                    self._file_downloader.check_checksum(file_path, md5, sha1, sha256)\n                else:\n                    self._file_downloader.download(url, file_path, retry, retry_wait, verify_ssl,\n                                                   auth, True, headers, md5, sha1, sha256)\n                return  # Success! Return to caller\n            except Exception as error:\n                if url != urls[-1]:  # If it is not the last one, do not raise, warn and move to next\n                    msg = f\"Could not download from the URL {url}: {error}.\"\n                    self._output.warning(msg)\n                    self._output.info(\"Trying another mirror.\")\n                else:\n                    raise\n\n\nclass ConanInternalCacheDownloader:\n    \"\"\" This is used for the download of Conan packages from server, not for sources/backup sources\n    \"\"\"\n    def __init__(self, requester, config, scope=None):\n        self._download_cache = config.get(\"core.download:download_cache\")\n        if self._download_cache and not os.path.isabs(self._download_cache):\n            raise ConanException(\"core.download:download_cache must be an absolute path\")\n        self._file_downloader = FileDownloader(requester, scope=scope)\n        self._scope = scope\n\n    def download(self, url, file_path, auth, verify_ssl, retry, retry_wait, metadata=False):\n        if not self._download_cache or metadata:  # Metadata not cached and can be overwritten\n            self._file_downloader.download(url, file_path, retry=retry, retry_wait=retry_wait,\n                                           verify_ssl=verify_ssl, auth=auth, overwrite=metadata)\n            return\n\n        download_cache = DownloadCache(self._download_cache)\n        cached_path, h = download_cache.cached_path(url)\n        with download_cache.lock(h):\n            remove_if_dirty(cached_path)\n\n            if not os.path.exists(cached_path):\n                with set_dirty_context_manager(cached_path):\n                    self._file_downloader.download(url, cached_path, retry=retry,\n                                                   retry_wait=retry_wait, verify_ssl=verify_ssl,\n                                                   auth=auth, overwrite=False)\n            else:  # Found in cache!\n                total_length = os.path.getsize(cached_path)\n                is_large_file = total_length > 10000000  # 10 MB\n                if is_large_file:\n                    base_name = os.path.basename(file_path)\n                    hs = human_size(total_length)\n                    ConanOutput(scope=self._scope).info(f\"Copying {hs} {base_name} from download \"\n                                                        f\"cache, instead of downloading it\")\n\n            # Everything good, file in the cache, just copy it to final destination\n            mkdir(os.path.dirname(file_path))\n            shutil.copy2(cached_path, file_path)\n"
  },
  {
    "path": "conan/internal/rest/client_routes.py",
    "content": "from urllib.parse import urlencode\n\nfrom conan.api.model import RecipeReference\nfrom conan.internal.rest.rest_routes import RestRoutes\n\n\ndef _format_ref(url, ref):\n    url = url.format(name=ref.name, version=ref.version, username=ref.user or \"_\",\n                     channel=ref.channel or \"_\", revision=ref.revision)\n    return url\n\n\ndef _format_pref(url, pref):\n    ref = pref.ref\n    url = url.format(name=ref.name, version=ref.version, username=ref.user or \"_\",\n                     channel=ref.channel or \"_\", revision=ref.revision, package_id=pref.package_id,\n                     p_revision=pref.revision)\n    return url\n\n\nclass ClientV2Router:\n    \"\"\"Builds urls for v2\"\"\"\n\n    def __init__(self, root_url):\n        self.root_url = root_url\n        self.base_url = \"{}/v2/\".format(root_url)\n        self.routes = RestRoutes()\n\n    def ping(self):\n        # FIXME: The v2 ping is not returning capabilities\n        return \"{}/v1/\".format(self.root_url) + self.routes.ping\n\n    def search(self, pattern, ignorecase):\n        \"\"\"URL search recipes\"\"\"\n        query = ''\n        if pattern:\n            if isinstance(pattern, RecipeReference):\n                pattern = repr(pattern)\n            params = {\"q\": pattern}\n            if not ignorecase:\n                params[\"ignorecase\"] = \"False\"\n            query = \"?%s\" % urlencode(params)\n        return self.base_url + \"%s%s\" % (self.routes.common_search, query)\n\n    def search_packages(self, ref, list_only):\n        \"\"\"URL search packages for a recipe\"\"\"\n        route = self.routes.common_search_packages_revision \\\n            if ref.revision else self.routes.common_search_packages\n        url = _format_ref(route, ref)\n\n        params = {\"list_only\": list_only}\n        query = \"?%s\" % urlencode(params)\n        return self.base_url + url + query\n\n    def common_authenticate(self):\n        return self.base_url + self.routes.common_authenticate\n\n    def common_check_credentials(self):\n        return self.base_url + self.routes.common_check_credentials\n\n    def recipe_file(self, ref, path):\n        \"\"\"Recipe file url\"\"\"\n        return self.base_url + self._for_recipe_file(ref, path)\n\n    def package_file(self, pref, path):\n        \"\"\"Package file url\"\"\"\n        return self.base_url + self._for_package_file(pref, path)\n\n    def remove_recipe(self, ref):\n        \"\"\"Remove recipe url\"\"\"\n        return self.base_url + self._for_recipe(ref)\n\n    def recipe_revisions(self, ref):\n        \"\"\"Get revisions for a recipe url\"\"\"\n        return self.base_url + _format_ref(self.routes.recipe_revisions, ref)\n\n    def remove_package(self, pref):\n        \"\"\"Remove package url\"\"\"\n        assert pref.revision is not None, \"remove_package v2 needs PREV\"\n        return self.base_url + self._for_package(pref)\n\n    def remove_all_packages(self, ref):\n        \"\"\"Remove package url\"\"\"\n        return self.base_url + self._for_packages(ref)\n\n    def recipe_snapshot(self, ref):\n        \"\"\"get recipe manifest url\"\"\"\n        return self.base_url + self._for_recipe_files(ref)\n\n    def package_snapshot(self, pref):\n        \"\"\"get recipe manifest url\"\"\"\n        return self.base_url + self._for_package_files(pref)\n\n    def package_revisions(self, pref):\n        \"\"\"get revisions for a package url\"\"\"\n        return self.base_url + _format_pref(self.routes.package_revisions, pref)\n\n    def package_latest(self, pref):\n        \"\"\"Get the latest of a package\"\"\"\n        assert pref.ref.revision is not None, \"Cannot get the latest package without RREV\"\n        return self.base_url + _format_pref(self.routes.package_revision_latest, pref)\n\n    def recipe_latest(self, ref):\n        \"\"\"Get the latest of a recipe\"\"\"\n        assert ref.revision is None, \"for_recipe_latest shouldn't receive RREV\"\n        return self.base_url + _format_ref(self.routes.recipe_latest, ref)\n\n    def _for_package_file(self, pref, path):\n        \"\"\"url for getting a file from a package, with revisions\"\"\"\n        assert pref.ref.revision is not None, \"_for_package_file needs RREV\"\n        assert pref.revision is not None, \"_for_package_file needs PREV\"\n        return ClientV2Router._format_pref_path(self.routes.package_revision_file, pref, path)\n\n    def _for_package_files(self, pref):\n        \"\"\"url for getting the recipe list\"\"\"\n        assert pref.revision is not None, \"_for_package_files needs PREV\"\n        assert pref.ref.revision is not None, \"_for_package_files needs RREV\"\n        return _format_pref(self.routes.package_revision_files, pref)\n\n    def _for_recipe_file(self, ref, path):\n        \"\"\"url for a recipe file, with or without revisions\"\"\"\n        assert ref.revision is not None, \"for_recipe_file needs RREV\"\n        return ClientV2Router._format_ref_path(self.routes.recipe_revision_file, ref, path)\n\n    def _for_recipe_files(self, ref):\n        \"\"\"url for getting the recipe list\"\"\"\n        assert ref.revision is not None, \"for_recipe_files needs RREV\"\n        return _format_ref(self.routes.recipe_revision_files, ref)\n\n    def _for_recipe(self, ref):\n        \"\"\"url for a recipe with or without revisions (without rev,\n        only for delete the root recipe, or v1)\"\"\"\n        return _format_ref(self.routes.recipe_revision, ref)\n\n    def _for_packages(self, ref):\n        \"\"\"url for a recipe with or without revisions\"\"\"\n        return _format_ref(self.routes.packages_revision, ref)\n\n    def _for_package(self, pref):\n        \"\"\"url for the package with or without revisions\"\"\"\n        return _format_pref(self.routes.package_revision, pref)\n\n    @staticmethod\n    def _format_ref_path(url, ref, path):\n        ret = url.format(name=ref.name, version=ref.version, username=ref.user or \"_\",\n                         channel=ref.channel or \"_\", revision=ref.revision, path=path)\n        return ret\n\n    @staticmethod\n    def _format_pref_path(url, pref, path):\n        ref = pref.ref\n        return url.format(name=ref.name, version=ref.version, username=ref.user or \"_\",\n                          channel=ref.channel or \"_\", revision=ref.revision,\n                          package_id=pref.package_id,\n                          p_revision=pref.revision, path=path)\n"
  },
  {
    "path": "conan/internal/rest/conan_requester.py",
    "content": "import fnmatch\nimport json\nimport logging\nimport os\nimport platform\n\nimport requests\nimport urllib3\nfrom jinja2 import Template\nfrom requests.adapters import HTTPAdapter\n\nfrom conan.api.output import ConanOutput\nfrom conan.internal.cache.home_paths import HomePaths\n\nfrom conan import __version__\nfrom conan.internal.loader import load_python_file\nfrom conan.internal.errors import scoped_traceback\nfrom conan.errors import ConanException\n\n# Capture SSL warnings as pointed out here:\n# https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning\n# TODO: Fix this security warning\nfrom conan.internal.util.files import load\n\nlogging.captureWarnings(True)\n\n\nDEFAULT_TIMEOUT = (30, 60)  # connect, read timeouts\nINFINITE_TIMEOUT = -1\n\n\nclass _SourceURLCredentials:\n    \"\"\"\n    Only for sources download (get(), download(), conan config install\n    \"\"\"\n    def __init__(self, cache_folder):\n        self._urls = {}\n        self._auth_source_plugin = None\n        if not cache_folder:\n            return\n        auth_source_plugin_path = HomePaths(cache_folder).auth_source_plugin_path\n        self._auth_source_plugin = _load_auth_source_plugin(auth_source_plugin_path)\n        creds_path = os.path.join(cache_folder, \"source_credentials.json\")\n        if not os.path.exists(creds_path):\n            return\n\n        def _get_auth(credentials):\n            if \"token\" in credentials or (\"user\" in credentials and \"password\" in credentials):\n                return credentials\n            raise ConanException(f\"Unknown credentials method for '{credentials['url']}'\")\n\n        try:\n            template = Template(load(creds_path))\n            content = template.render({\"platform\": platform, \"os\": os})\n            content = json.loads(content)\n            self._urls = {credentials[\"url\"]: _get_auth(credentials)\n                          for credentials in content[\"credentials\"]}\n        except Exception as e:\n            raise ConanException(f\"Error loading 'source_credentials.json' {creds_path}: {repr(e)}\")\n\n    def add_auth(self, url, kwargs):\n        # First, try to use \"auth_source_plugin\"\n        if self._auth_source_plugin:\n            try:\n                c = self._auth_source_plugin(url)\n            except Exception as e:\n                msg = f\"Error while processing 'auth_source_remote.py' plugin\"\n                msg = scoped_traceback(msg, e, scope=\"/extensions/plugins\")\n                raise ConanException(msg)\n            if c:\n                if c.get(\"token\"):\n                    kwargs[\"headers\"][\"Authorization\"] = f\"Bearer {c.get('token')}\"\n                if c.get(\"user\") and c.get(\"password\"):\n                    kwargs[\"auth\"] = (c.get(\"user\"), c.get(\"password\"))\n                if c.get(\"headers\"):\n                    kwargs.setdefault(\"headers\", {}).update(c[\"headers\"])\n                return\n\n        # Then, try to find the credentials in \"_urls\"\n        for u, creds in self._urls.items():\n            if url.startswith(u):\n                token = creds.get(\"token\")\n                if token:\n                    kwargs[\"headers\"][\"Authorization\"] = f\"Bearer {token}\"\n                user = creds.get(\"user\")\n                password = creds.get(\"password\")\n                if user and password:\n                    kwargs[\"auth\"] = (user, password)\n                headers = creds.get(\"headers\")\n                if headers:\n                    kwargs.setdefault(\"headers\", {}).update(headers)\n                break\n\n\nclass ConanRequester:\n\n    def __init__(self, config, cache_folder=None):\n        self._url_creds = _SourceURLCredentials(cache_folder)\n        _max_retries = config.get(\"core.net.http:max_retries\", default=2, check_type=int)\n        self._http_requester = requests.Session()\n        _adapter = HTTPAdapter(max_retries=self._get_retries(_max_retries))\n        self._http_requester.mount(\"http://\", _adapter)\n        self._http_requester.mount(\"https://\", _adapter)\n        self._timeout = config.get(\"core.net.http:timeout\", default=DEFAULT_TIMEOUT)\n        self._no_proxy_match = config.get(\"core.net.http:no_proxy_match\", check_type=list)\n        self._proxies = config.get(\"core.net.http:proxies\")\n        self._cacert_path = config.get(\"core.net.http:cacert_path\", check_type=str)\n        self._client_certificates = config.get(\"core.net.http:client_cert\")\n        self._clean_system_proxy = config.get(\"core.net.http:clean_system_proxy\", default=False,\n                                              check_type=bool)\n        platform_info = \"; \".join([\" \".join([platform.system(), platform.release()]),\n                                   \"Python \" + platform.python_version(),\n                                   platform.machine()])\n        self._user_agent = \"Conan/%s (%s)\" % (__version__, platform_info)\n\n    @staticmethod\n    def _get_retries(max_retries):\n        retry = max_retries\n        if retry == 0:\n            return 0\n        retry_status_code_set = {\n            requests.codes.internal_server_error,\n            requests.codes.bad_gateway,\n            requests.codes.service_unavailable,\n            requests.codes.gateway_timeout,\n            requests.codes.variant_also_negotiates,\n            requests.codes.insufficient_storage,\n            requests.codes.bandwidth_limit_exceeded\n        }\n        return urllib3.Retry(\n            total=retry,\n            backoff_factor=0.05,\n            status_forcelist=retry_status_code_set\n        )\n\n    def _should_skip_proxy(self, url):\n        if self._no_proxy_match:\n            for entry in self._no_proxy_match:\n                if fnmatch.fnmatch(url, entry):\n                    return True\n        return False\n\n    def _add_kwargs(self, url, kwargs):\n        # verify is the kwargs that comes from caller, RestAPI, it is defined in\n        # Conan remote \"verify_ssl\"\n        source_credentials = kwargs.pop(\"source_credentials\", None)\n        if kwargs.get(\"verify\", None) is not False:  # False means de-activate\n            if self._cacert_path is not None:\n                kwargs[\"verify\"] = self._cacert_path\n        kwargs[\"cert\"] = self._client_certificates\n        if self._proxies:\n            if not self._should_skip_proxy(url):\n                kwargs[\"proxies\"] = self._proxies\n        if self._timeout and self._timeout != INFINITE_TIMEOUT:\n            kwargs[\"timeout\"] = self._timeout\n        if not kwargs.get(\"headers\"):\n            kwargs[\"headers\"] = {}\n\n        if source_credentials:\n            self._url_creds.add_auth(url, kwargs)\n\n        # Only set User-Agent if none was provided\n        if not kwargs[\"headers\"].get(\"User-Agent\"):\n            kwargs[\"headers\"][\"User-Agent\"] = self._user_agent\n\n        return kwargs\n\n    def get(self, url, **kwargs):\n        return self._call_method(\"get\", url, **kwargs)\n\n    def head(self, url, **kwargs):\n        return self._call_method(\"head\", url, **kwargs)\n\n    def put(self, url, **kwargs):\n        return self._call_method(\"put\", url, **kwargs)\n\n    def delete(self, url, **kwargs):\n        return self._call_method(\"delete\", url, **kwargs)\n\n    def post(self, url, **kwargs):\n        return self._call_method(\"post\", url, **kwargs)\n\n    def _call_method(self, method, url, **kwargs):\n        popped = False\n        if self._clean_system_proxy:\n            old_env = dict(os.environ)\n            # Clean the proxies from the environ and use the conan specified proxies\n            for var_name in (\"http_proxy\", \"https_proxy\", \"ftp_proxy\", \"all_proxy\", \"no_proxy\"):\n                popped = True if os.environ.pop(var_name, None) else popped\n                popped = True if os.environ.pop(var_name.upper(), None) else popped\n        ConanOutput(scope=\"HttpRequest\").trace(f\"{method}: {url}\")\n        try:\n            all_kwargs = self._add_kwargs(url, kwargs)\n            tmp = getattr(self._http_requester, method)(url, **all_kwargs)\n            return tmp\n        finally:\n            if popped:\n                os.environ.clear()\n                os.environ.update(old_env)\n\n\ndef _load_auth_source_plugin(auth_source_plugin_path):\n    if os.path.exists(auth_source_plugin_path):\n        mod, _ = load_python_file(auth_source_plugin_path)\n        return getattr(mod, \"auth_source_plugin\", None)\n"
  },
  {
    "path": "conan/internal/rest/download_cache.py",
    "content": "import hashlib\nimport json\nimport os\nfrom contextlib import contextmanager\nfrom threading import Lock\n\nimport fasteners\n\nfrom conan.errors import ConanException\nfrom conan.internal.util.dates import timestamp_now\nfrom conan.internal.util.files import load, save, remove_if_dirty\n\n\nclass DownloadCache:\n    \"\"\" The download cache has 3 folders\n    - \"s\": SOURCE_BACKUP for the files.download(internet_url) backup sources feature\n    - \"c\": CONAN_CACHE: for caching Conan packages artifacts\n    - \"locks\": The LOCKS folder containing the file locks for concurrent access to the cache\n    \"\"\"\n    _LOCKS = \"locks\"\n    _SOURCE_BACKUP = \"s\"\n    _CONAN_CACHE = \"c\"\n\n    def __init__(self, path: str):\n        self._path: str = path\n\n    def source_path(self, sha256):\n        return os.path.join(self._path, self._SOURCE_BACKUP, sha256)\n\n    def cached_path(self, url):\n        md = hashlib.sha256()\n        md.update(url.encode())\n        h = md.hexdigest()\n        return os.path.join(self._path, self._CONAN_CACHE, h), h\n\n    _thread_locks = {}  # Needs to be shared among all instances\n\n    @contextmanager\n    def lock(self, lock_id):\n        lock = os.path.join(self._path, self._LOCKS, lock_id)\n        with fasteners.InterProcessLock(lock):  # TODO: Abstract away when necessary for concurrency\n            # Once the process has access, make sure multithread is locked too\n            # as SimpleLock doesn't work multithread\n            thread_lock = self._thread_locks.setdefault(lock, Lock())\n            thread_lock.acquire()\n            try:\n                yield\n            finally:\n                thread_lock.release()\n\n    def get_backup_sources_files(self, excluded_urls, package_list=None, only_upload=True):\n        \"\"\"Get list of backup source files currently present in the cache,\n        either all of them if no package_list is give, or filtered by those belonging to the references in the package_list\n\n        Will exclude the sources that come from URLs present in excluded_urls\n\n        @param excluded_urls: a list of URLs to exclude backup sources files if they come from any of these URLs\n        @param package_list: a PackagesList object to filter backup files from (The files should have been downloaded form any of the references in the package_list)\n        @param only_upload: if True, only return the files for packages that are set to be uploaded\"\"\"\n        path_backups = os.path.join(self._path, self._SOURCE_BACKUP)\n\n        if not os.path.exists(path_backups):\n            return []\n\n        if excluded_urls is None:\n            excluded_urls = []\n\n        def has_excluded_urls(backup_urls):\n            return all(any(url.startswith(excluded_url)\n                           for excluded_url in excluded_urls)\n                       for url in backup_urls)\n\n        all_refs = set()\n        if package_list is not None:\n            for ref, packages in package_list.items():\n                ref_info = package_list.recipe_dict(ref)\n                if (not only_upload or ref_info.get(\"upload\")\n                        or any(package_list.package_dict(p).get(\"upload\") for p in packages)):\n                    all_refs.add(str(ref))\n\n        path_backups_contents = []\n\n        dirty_ext = \".dirty\"\n        for path in os.listdir(path_backups):\n            if remove_if_dirty(os.path.join(path_backups, path)):\n                continue\n            if path.endswith(dirty_ext):\n                if not os.path.exists(os.path.join(path_backups, os.path.splitext(path)[0])):\n                    if os.path.exists(os.path.join(path_backups, path)):\n                        os.remove(os.path.join(path_backups, path))\n                continue\n            if not path.endswith(\".json\"):\n                path_backups_contents.append(path)\n\n        files_to_upload = []\n\n        for path in path_backups_contents:\n            blob_path = os.path.join(path_backups, path)\n            metadata_path = os.path.join(blob_path + \".json\")\n            if not os.path.exists(metadata_path):\n                raise ConanException(f\"Missing metadata file for backup source {blob_path}\")\n            metadata = json.loads(load(metadata_path))\n            refs = metadata[\"references\"]\n            for ref, urls in refs.items():\n                if not has_excluded_urls(urls) and (not only_upload\n                                                    or package_list is None\n                                                    or ref in all_refs):\n                    files_to_upload.append(metadata_path)\n                    files_to_upload.append(blob_path)\n                    break\n        return files_to_upload\n\n    @staticmethod\n    def update_backup_sources_json(cached_path, conanfile, urls):\n        \"\"\" create or update the sha256.json file with the references and new urls used\n        \"\"\"\n        summary_path = cached_path + \".json\"\n        if os.path.exists(summary_path):\n            summary = json.loads(load(summary_path))\n        else:\n            summary = {\"references\": {}, \"timestamp\": timestamp_now()}\n\n        try:\n            summary_key = str(conanfile.ref)\n        except AttributeError:\n            # If there's no node associated with the conanfile,\n            # try to construct a reference from the conanfile itself.\n            # We accept it if we have a name and a version at least.\n            if conanfile.name and conanfile.version:\n                user = f\"@{conanfile.user}\" if conanfile.user else \"\"\n                channel = f\"/{conanfile.channel}\" if conanfile.channel else \"\"\n                summary_key = f\"{conanfile.name}/{conanfile.version}{user}{channel}\"\n            else:\n                # The recipe path would be different between machines\n                # So best we can do is to set this as unknown\n                summary_key = \"unknown\"\n\n        if not isinstance(urls, (list, tuple)):\n            urls = [urls]\n        existing_urls = summary[\"references\"].setdefault(summary_key, [])\n        existing_urls.extend(url for url in urls if url not in existing_urls)\n        conanfile.output.verbose(f\"Updating ${summary_path} summary file\")\n        summary_dump = json.dumps(summary)\n        conanfile.output.debug(f\"New summary: ${summary_dump}\")\n        save(summary_path, json.dumps(summary))\n"
  },
  {
    "path": "conan/internal/rest/file_downloader.py",
    "content": "import os\nimport re\nimport time\n\n\nfrom conan.api.output import ConanOutput, TimedOutput\nfrom conan.internal.rest import response_to_str\nfrom conan.internal.errors import (ConanConnectionError, RequestErrorException,\n                                   AuthenticationException, ForbiddenException, NotFoundException)\nfrom conan.errors import ConanException\nfrom conan.internal.util.files import human_size, check_with_algorithm_sum\n\n\nclass FileDownloader:\n\n    def __init__(self, requester, scope=None, source_credentials=None):\n        self._output = ConanOutput(scope=scope)\n        self._requester = requester\n        self._source_credentials = source_credentials\n\n    def download(self, url, file_path, retry=2, retry_wait=0, verify_ssl=True, auth=None,\n                 overwrite=False, headers=None, md5=None, sha1=None, sha256=None):\n        \"\"\" in order to make the download concurrent, the folder for file_path MUST exist\n        \"\"\"\n        assert file_path, \"Conan 2.0 always downloads files to disk, not to memory\"\n        assert os.path.isabs(file_path), \"Target file_path must be absolute\"\n\n        if os.path.exists(file_path):\n            if overwrite:\n                self._output.warning(\"file '%s' already exists, overwriting\" % file_path)\n            else:\n                # Should not happen, better to raise, probably we had to remove\n                # the dest folder before\n                raise ConanException(\"Error, the file to download already exists: '%s'\" % file_path)\n\n        try:\n            for counter in range(retry + 1):\n                try:\n                    self._download_file(url, auth, headers, file_path, verify_ssl)\n                    break\n                except (NotFoundException, ForbiddenException, AuthenticationException,\n                        RequestErrorException):\n                    raise\n                except ConanException as exc:\n                    if counter == retry:\n                        raise\n                    else:\n                        self._output.warning(exc, warn_tag=\"network\")\n                        self._output.info(f\"Waiting {retry_wait} seconds to retry...\")\n                        time.sleep(retry_wait)\n\n            self.check_checksum(file_path, md5, sha1, sha256)\n            self._output.debug(f\"Downloaded {file_path} from {url}\")\n        except Exception:\n            if os.path.exists(file_path):\n                os.remove(file_path)\n            raise\n\n    @staticmethod\n    def check_checksum(file_path, md5, sha1, sha256):\n        if md5 is not None:\n            check_with_algorithm_sum(\"md5\", file_path, md5)\n        if sha1 is not None:\n            check_with_algorithm_sum(\"sha1\", file_path, sha1)\n        if sha256 is not None:\n            check_with_algorithm_sum(\"sha256\", file_path, sha256)\n\n    def _download_file(self, url, auth, headers, file_path, verify_ssl, try_resume=False):\n        if try_resume and os.path.exists(file_path):\n            range_start = os.path.getsize(file_path)\n            headers = headers.copy() if headers else {}\n            headers[\"range\"] = \"bytes={}-\".format(range_start)\n        else:\n            range_start = 0\n\n        try:\n            response = self._requester.get(url, stream=True, verify=verify_ssl, auth=auth,\n                                           headers=headers,\n                                           source_credentials=self._source_credentials)\n        except Exception as exc:\n            raise ConanException(\"Error downloading file %s: '%s'\" % (url, exc))\n\n        if not response.ok:\n            if response.status_code == 404:\n                raise NotFoundException(\"Not found: %s\" % url)\n            elif response.status_code == 403:\n                if auth is None or (hasattr(auth, \"bearer\") and auth.bearer is None):\n                    # TODO: This is a bit weird, why this conversion? Need to investigate\n                    raise AuthenticationException(response_to_str(response))\n                raise ForbiddenException(response_to_str(response))\n            elif response.status_code == 401:\n                raise AuthenticationException(response_to_str(response))\n            raise ConanException(\"Error %d downloading file %s\" % (response.status_code, url))\n\n        def get_total_length():\n            if range_start:\n                content_range = response.headers.get(\"Content-Range\", \"\")\n                match = re.match(r\"^bytes (\\d+)-(\\d+)/(\\d+)\", content_range)\n                if not match or range_start != int(match.group(1)):\n                    raise ConanException(\"Error in resumed download from %s\\n\"\n                                         \"Incorrect Content-Range header %s\" % (url, content_range))\n                return int(match.group(3))\n            else:\n                total_size = response.headers.get('Content-Length') or len(response.content)\n                return int(total_size)\n\n        try:\n            total_length = get_total_length()\n            is_large_file = total_length > 10000000  # 10 MB\n            base_name = os.path.basename(file_path)\n\n            def msg_format(msg, downloaded):\n                perc = int(total_downloaded_size * 100 / total_length)\n                return msg + f\" {human_size(downloaded)} {perc}% {base_name}\"\n            timed_output = TimedOutput(10, out=self._output, msg_format=msg_format)\n\n            if is_large_file:\n                hs = human_size(total_length)\n                action = \"Downloading\" if range_start == 0 else \"Continuing download of\"\n                self._output.info(f\"{action} {hs} {base_name}\")\n\n            chunk_size = 1024 * 100\n            total_downloaded_size = range_start\n            mode = \"ab\" if range_start else \"wb\"\n            with open(file_path, mode) as file_handler:\n                for chunk in response.iter_content(chunk_size):\n                    file_handler.write(chunk)\n                    total_downloaded_size += len(chunk)\n                    if is_large_file:\n                        timed_output.info(\"Downloaded\", total_downloaded_size)\n\n            gzip = (response.headers.get(\"content-encoding\") == \"gzip\")\n            response.close()\n            # it seems that if gzip we don't know the size, cannot resume and shouldn't raise\n            if total_downloaded_size != total_length and not gzip:\n                if (total_length > total_downloaded_size > range_start\n                        and response.headers.get(\"Accept-Ranges\") == \"bytes\"):\n                    self._download_file(url, auth, headers, file_path, verify_ssl, try_resume=True)\n                else:\n                    raise ConanException(\"Transfer interrupted before complete: %s < %s\"\n                                         % (total_downloaded_size, total_length))\n        except Exception as e:\n            # If this part failed, it means problems with the connection to server\n            raise ConanConnectionError(\"Download failed, check server, possibly try again\\n%s\"\n                                       % str(e))\n"
  },
  {
    "path": "conan/internal/rest/file_uploader.py",
    "content": "import io\nimport os\nimport time\n\nfrom conan.api.output import ConanOutput, TimedOutput\nfrom conan.internal.rest import response_to_str\nfrom conan.internal.errors import InternalErrorException, RequestErrorException, AuthenticationException, \\\n    ForbiddenException, NotFoundException\nfrom conan.errors import ConanException\nfrom conan.internal.util.files import sha1sum\n\n\nclass FileUploader:\n\n    def __init__(self, requester, verify, config, source_credentials=None):\n        self._requester = requester\n        self._config = config\n        self._verify_ssl = verify\n        self._source_credentials = source_credentials\n\n    @staticmethod\n    def _handle_400_response(response, auth):\n        if response.status_code == 400:\n            raise RequestErrorException(response_to_str(response))\n\n        if response.status_code == 401:\n            raise AuthenticationException(response_to_str(response))\n\n        if response.status_code == 403:\n            if auth is None or auth.bearer is None:\n                raise AuthenticationException(response_to_str(response))\n            raise ForbiddenException(response_to_str(response))\n\n    def _dedup(self, url, headers, auth):\n        \"\"\" send the headers to see if it is possible to skip uploading the file, because it\n        is already in the server. Artifactory support file deduplication\n        \"\"\"\n        dedup_headers = {\"X-Checksum-Deploy\": \"true\"}\n        if headers:\n            dedup_headers.update(headers)\n        response = self._requester.put(url, data=\"\", verify=self._verify_ssl, headers=dedup_headers,\n                                       auth=auth, source_credentials=self._source_credentials)\n        if response.status_code == 500:\n            raise InternalErrorException(response_to_str(response))\n\n        self._handle_400_response(response, auth)\n\n        if response.status_code == 201:  # Artifactory returns 201 if the file is there\n            return response\n\n    def exists(self, url, auth):\n        response = self._requester.head(url, verify=self._verify_ssl, auth=auth,\n                                        source_credentials=self._source_credentials)\n        return bool(response.ok)\n\n    def upload(self, url, abs_path, auth=None, dedup=False, retry=None, retry_wait=None,\n               ref=None):\n        retry = retry if retry is not None else self._config.get(\"core.upload:retry\", default=1,\n                                                                 check_type=int)\n        retry_wait = retry_wait if retry_wait is not None else \\\n            self._config.get(\"core.upload:retry_wait\", default=5, check_type=int)\n\n        # Send always the header with the Sha1\n        headers = {\"X-Checksum-Sha1\": sha1sum(abs_path)}\n        if dedup:\n            response = self._dedup(url, headers, auth)\n            if response:\n                return response\n\n        for counter in range(retry + 1):\n            try:\n                return self._upload_file(url, abs_path, headers, auth, ref)\n            except (NotFoundException, ForbiddenException, AuthenticationException,\n                    RequestErrorException):\n                raise\n            except ConanException as exc:\n                if counter == retry:\n                    raise\n                else:\n                    ConanOutput().warning(exc, warn_tag=\"network\")\n                    ConanOutput().info(\"Waiting %d seconds to retry...\" % retry_wait)\n                    time.sleep(retry_wait)\n\n    def _upload_file(self, url, abs_path, headers, auth, ref):\n        with FileProgress(abs_path, mode='rb', msg=f\"{ref}: Uploading\") as file_handler:\n            try:\n                response = self._requester.put(url, data=file_handler, verify=self._verify_ssl,\n                                               headers=headers, auth=auth,\n                                               source_credentials=self._source_credentials)\n                self._handle_400_response(response, auth)\n                response.raise_for_status()  # Raise HTTPError for bad http response status\n                return response\n            except ConanException:\n                raise\n            except Exception as exc:\n                raise ConanException(exc)\n\n\nclass FileProgress(io.FileIO):\n    def __init__(self, path: str, msg: str = \"Uploading\", interval: float = 10, *args, **kwargs):\n        super().__init__(path, *args, **kwargs)\n        self._size = os.path.getsize(path)\n        self._filename = os.path.basename(path)\n        # Report only on big sizes (>100MB)\n        self._reporter = TimedOutput(interval=interval) if self._size > 100_000_000 else None\n        self._bytes_read = 0\n        self.msg = msg\n\n    def read(self, size: int = -1) -> bytes:\n        block = super().read(size)\n        self._bytes_read += len(block)\n        if self._reporter:\n            current_percentage = int(self._bytes_read * 100.0 / self._size) if self._size != 0 else 0\n            self._reporter.info(f\"{self.msg} {self._filename}: {current_percentage}%\")\n        return block\n"
  },
  {
    "path": "conan/internal/rest/pkg_sign.py",
    "content": "import os\nimport json\n\nfrom conan.api.output import ConanOutput\nfrom conan.errors import ConanException\nfrom conan.internal.cache.conan_reference_layout import METADATA\nfrom conan.internal.cache.home_paths import HomePaths\nfrom conan.internal.loader import load_python_file\nfrom conan.internal.util.files import load, mkdir, save, sha256sum\n\n\nPKGSIGN_MANIFEST = \"pkgsign-manifest.json\"\nPKGSIGN_SIGNATURES = \"pkgsign-signatures.json\"\n\n\ndef _save_manifest(artifacts_folder, signature_folder):\n    \"\"\"\n    Creates the summary content as a dictionary for manipulation.\n\n    Returns a structure like:\n        {\n            \"files\": [\n                {\"file\": \"conan_package.tgz\", \"sha256\": \"abc123\"},\n                {\"file\": \"other_file.bin\", \"sha256\": \"fff999\"},\n                ...\n            ]\n        }\n    \"\"\"\n    files_list = []\n\n    # Sort files by filename to ensure consistent order\n    for fname in sorted(os.listdir(artifacts_folder)):\n        file_path = os.path.join(artifacts_folder, fname)\n\n        if os.path.isfile(file_path):\n            entry = {\n                \"file\": fname,\n                \"sha256\": sha256sum(file_path)\n            }\n            files_list.append(entry)\n\n    save(os.path.join(signature_folder, PKGSIGN_MANIFEST),\n         json.dumps({\"files\": files_list}, indent=2))\n\n\ndef _save_signatures(signature_folder, signatures):\n    \"\"\"\n    Saves the content of signatures file in the signature folder\n    :param signature_folder: Signature folder path\n    :param signatures: dict of {filename: signature_value}\n    \"\"\"\n    for signature in signatures:\n        for key in [\"method\", \"provider\", \"sign_artifacts\"]:\n            if not signature.get(key):\n                raise ConanException(f\"[Package sign] Signature '{key}' is missing in signature data\")\n        if not isinstance(signature.get(\"sign_artifacts\"), dict):\n            raise ConanException(\"[Package sign] Signature 'sign_artifacts' must be a dict of \"\n                                 \"{name: filename}\")\n    content = {\n        \"signatures\": signatures\n    }\n    save(os.path.join(signature_folder, PKGSIGN_SIGNATURES), json.dumps(content, indent=2))\n\n\ndef _verify_files_checksums(signature_folder, files):\n    \"\"\"\n    Verifies that the files' checksums match those stored in the summary.\n    :param signature_folder: Signature folder path\n    :param files: dict of {filename: filepath} of files in artifact folder to verify\n    \"\"\"\n    if not os.path.isfile(os.path.join(signature_folder, PKGSIGN_MANIFEST)):\n        ConanOutput().warning(f\"[Package sign] Manifest file '{PKGSIGN_MANIFEST}' does not exist in \"\n                              f\"signature folder '{signature_folder}'. Please update your plugin \"\n                              f\"according to the docs at https://docs.conan.io/2/reference/extensions/package_signing.html\"\n                              f\". Skipping checksum verification!\", warn_tag=\"deprecated\")\n        return\n\n    manifest_content = load(os.path.join(signature_folder, PKGSIGN_MANIFEST))\n    expected_list = json.loads(manifest_content).get(\"files\", [])\n    expected_files = {item[\"file\"]: item[\"sha256\"] for item in expected_list}\n\n    # This is checking that the files of the package exist in the manifest instead of the opposite\n    # because some files might be missing such as conan_sources.tgz\n    for filename, file_path in files.items():\n        expected_checksum = expected_files.get(filename)\n        actual_checksum = sha256sum(file_path)\n\n        if actual_checksum != expected_checksum:\n            raise ConanException(\n                f\"[Package sign] Checksum mismatch for file {filename}: \"\n                f\"expected {expected_checksum}, got {actual_checksum}.\"\n            )\n        else:\n            ConanOutput().info(f\"[Package sign] Checksum verified for file {filename} ({actual_checksum}).\")\n\n\nclass PkgSignaturesPlugin:\n    def __init__(self, cache, home_folder):\n        self._cache = cache\n        signer = HomePaths(home_folder).sign_plugin_path\n        if os.path.isfile(signer):\n            mod, _ = load_python_file(signer)\n            self._plugin_sign_function = getattr(mod, \"sign\", None)\n            self._plugin_verify_function = getattr(mod, \"verify\", None)\n        else:\n            self._plugin_sign_function = self._plugin_verify_function = None\n\n    @property\n    def is_sign_configured(self):\n        return self._plugin_sign_function is not None\n\n    @property\n    def is_verify_configured(self):\n        return self._plugin_verify_function is not None\n\n    def sign_pkg(self, ref, files, folder):\n        metadata_sign = os.path.join(folder, METADATA, \"sign\")\n        mkdir(metadata_sign)\n        # Generate the package sign manifest before calling the plugin\n        _save_manifest(folder, metadata_sign)\n        signatures = self._plugin_sign_function(ref, artifacts_folder=folder,\n                                                signature_folder=metadata_sign)\n        if isinstance(signatures, list):\n            # Save signatures file with the plugin's returned signatures data\n            if signatures:\n                _save_signatures(metadata_sign, signatures)\n        else:\n            # Fallback to old behavior (plugin sign() returns None)\n            ConanOutput().warning(\"[Package sign] The signature plugin sign() function must return \"\n                                  \"a list of signature dicts. See the documentation at \"\n                                  \"https://docs.conan.io/2/reference/extensions/package_signing.html\",\n                                  warn_tag=\"deprecated\")\n\n    def sign(self, upload_data):\n        if not self.is_sign_configured:\n            return\n\n        for rref, packages in upload_data.items():\n            recipe_bundle = upload_data.recipe_dict(rref)\n            if recipe_bundle[\"upload\"]:\n                self.sign_pkg(rref, recipe_bundle[\"files\"],\n                              self._cache.recipe_layout(rref).download_export())\n            for pref in packages:\n                pkg_bundle = upload_data.package_dict(pref)\n                if pkg_bundle[\"upload\"]:\n                    self.sign_pkg(pref, pkg_bundle[\"files\"],\n                                  self._cache.pkg_layout(pref).download_package())\n\n    def verify(self, ref, folder, metadata_folder, files):\n        if self._plugin_verify_function is None:\n            return\n        metadata_sign = os.path.join(metadata_folder, \"sign\")\n        _verify_files_checksums(metadata_sign, files)  # Verify package files checksums before calling the plugin\n        self._plugin_verify_function(ref, artifacts_folder=folder, signature_folder=metadata_sign,\n                                     files=files)\n"
  },
  {
    "path": "conan/internal/rest/remote_credentials.py",
    "content": "import json\nimport os\nimport platform\n\nfrom jinja2 import Template\n\nfrom conan.api.input import UserInput\nfrom conan.internal.cache.home_paths import HomePaths\n\nfrom conan.internal.loader import load_python_file\nfrom conan.api.output import ConanOutput\nfrom conan.internal.errors import scoped_traceback\nfrom conan.errors import ConanException\nfrom conan.internal.util.files import load\n\n\nclass RemoteCredentials:\n    def __init__(self, cache_folder, global_conf):\n        self._global_conf = global_conf\n        self._urls = {}\n        auth_plugin_path = HomePaths(cache_folder).auth_remote_plugin_path\n        self._auth_remote_plugin = _load_auth_remote_plugin(auth_plugin_path)\n        creds_path = os.path.join(cache_folder, \"credentials.json\")\n        if not os.path.exists(creds_path):\n            return\n        try:\n            template = Template(load(creds_path))\n            content = template.render({\"platform\": platform, \"os\": os})\n            content = json.loads(content)\n\n            self._urls = {credentials[\"remote\"]: {\"user\": credentials[\"user\"],\n                                                  \"password\": credentials[\"password\"]}\n                          for credentials in content[\"credentials\"]}\n        except Exception as e:\n            raise ConanException(f\"Error loading 'credentials.json' {creds_path}: {repr(e)}\")\n\n    def auth(self, remote, user=None):\n        # First get the auth_remote_plugin\n        if self._auth_remote_plugin is not None:\n            try:\n                plugin_user, plugin_password = self._auth_remote_plugin(remote, user=user)\n            except Exception as e:\n                msg = f\"Error while processing 'auth_remote.py' plugin\"\n                msg = scoped_traceback(msg, e, scope=\"/extensions/plugins\")\n                raise ConanException(msg)\n            if plugin_user and plugin_password:\n                return plugin_user, plugin_password, False\n\n        # Then prioritize the cache \"credentials.json\" file\n        creds = self._urls.get(remote.name)\n        if creds is not None:\n            try:\n                return creds[\"user\"], creds[\"password\"], False\n            except KeyError as e:\n                raise ConanException(f\"Authentication error, wrong credentials.json: {e}\")\n\n        # Then, check environment definition\n        env_user, env_passwd = self._get_env(remote.name, user)\n        if env_passwd is not None:\n            if env_user is None:\n                raise ConanException(\"Found password in env-var, but not defined user\")\n            return env_user, env_passwd, False\n\n        # If not found, then interactive prompt\n        ui = UserInput(self._global_conf.get(\"core:non_interactive\", check_type=bool))\n        input_user, input_password = ui.request_login(remote.name, user)\n        return input_user, input_password, True\n\n    @staticmethod\n    def _get_env(remote, user):\n        \"\"\"\n        Try get creds from env-vars\n        \"\"\"\n        remote = remote.replace(\"-\", \"_\").upper()\n        if user is None:\n            user = os.getenv(f\"CONAN_LOGIN_USERNAME_{remote}\") or os.getenv(\"CONAN_LOGIN_USERNAME\")\n            if user:\n                ConanOutput().info(\"Got username '%s' from environment\" % user)\n        passwd = os.getenv(f\"CONAN_PASSWORD_{remote}\") or os.getenv(\"CONAN_PASSWORD\")\n        if passwd:\n            ConanOutput().info(\"Got password '******' from environment\")\n        return user, passwd\n\n\ndef _load_auth_remote_plugin(auth_remote_plugin_path):\n    if os.path.exists(auth_remote_plugin_path):\n        mod, _ = load_python_file(auth_remote_plugin_path)\n        return getattr(mod, \"auth_remote_plugin\", None)\n"
  },
  {
    "path": "conan/internal/rest/remote_manager.py",
    "content": "import os\nimport shutil\nimport sys\n\nfrom collections import namedtuple\nfrom typing import List\n\nfrom requests.exceptions import ConnectionError\n\nfrom conan.api.model import LOCAL_RECIPES_INDEX\nfrom conan.internal.paths import CONANINFO, CONAN_MANIFEST, PACKAGE_FILE_NAME, EXPORT_FILE_NAME\nfrom conan.internal.rest.rest_client_local_recipe_index import RestApiClientLocalRecipesIndex\nfrom conan.api.model import Remote\nfrom conan.api.output import ConanOutput\nfrom conan.internal.cache.conan_reference_layout import METADATA\nfrom conan.internal.rest.pkg_sign import PkgSignaturesPlugin\nfrom conan.internal.errors import ConanConnectionError, NotFoundException, PackageNotFoundException\nfrom conan.errors import ConanException\nfrom conan.internal.model.info import load_binary_info\nfrom conan.api.model import PkgReference\nfrom conan.api.model import RecipeReference\nfrom conan.internal.util.files import rmdir, human_size\nfrom conan.internal.util.files import mkdir, tar_extract\n\n\nclass RemoteManager:\n    \"\"\" Will handle the remotes to get recipes, packages etc \"\"\"\n\n    _ErrorMsg = namedtuple(\"ErrorMsg\", [\"message\"])\n\n    def __init__(self, cache, auth_manager, home_folder):\n        self._cache = cache\n        self._auth_manager = auth_manager\n        self._signer = PkgSignaturesPlugin(cache, home_folder)\n        self._home_folder = home_folder\n\n    def _local_folder_remote(self, remote):\n        if remote.remote_type == LOCAL_RECIPES_INDEX:\n            return RestApiClientLocalRecipesIndex(remote, self._home_folder)\n\n    def check_credentials(self, remote, force_auth=False):\n        self._call_remote(remote, \"check_credentials\", force_auth)\n\n    def upload_recipe(self, ref, files_to_upload, remote):\n        assert isinstance(ref, RecipeReference)\n        assert ref.revision, \"upload_recipe requires RREV\"\n        remote.invalidate_cache()\n        self._call_remote(remote, \"upload_recipe\", ref, files_to_upload)\n\n    def upload_package(self, pref, files_to_upload, remote):\n        assert pref.ref.revision, \"upload_package requires RREV\"\n        assert pref.revision, \"upload_package requires PREV\"\n        remote.invalidate_cache()\n        self._call_remote(remote, \"upload_package\", pref, files_to_upload)\n\n    def get_recipe(self, ref, remote, metadata=None):\n        assert ref.revision, \"get_recipe without revision specified\"\n        assert ref.timestamp, \"get_recipe without ref.timestamp specified\"\n\n        # This fails if there is a DB entry for this ref\n        layout = self._cache.create_ref_layout(ref)\n\n        export_folder = layout.export()\n        local_folder_remote = self._local_folder_remote(remote)\n        if local_folder_remote is not None:\n            local_folder_remote.get_recipe(ref, export_folder)\n        else:\n            self._download_recipe(layout, ref, remote, metadata)\n        # Make sure that the source dir is deleted, but it seems unnecessary\n        rmdir(layout.source())\n        mkdir(layout.metadata())\n\n        return layout\n\n    def _download_recipe(self, layout, ref, remote, metadata):\n        download_export = layout.download_export()\n        try:\n            zipped_files = self._call_remote(remote, \"get_recipe\", ref, download_export, metadata,\n                                             only_metadata=False)\n            # The timestamp of the ``ref`` from the server has been already obtained by ConanProxy\n            # or it will be obtained explicitly by the ``conan download``\n            # filter metadata files\n            # This could be also optimized in download, avoiding downloading them, for performance\n            zipped_files = {k: v for k, v in zipped_files.items() if not k.startswith(METADATA)}\n            # quick server package integrity check:\n            if \"conanfile.py\" not in zipped_files:\n                raise ConanException(f\"Corrupted {ref} in '{remote.name}' remote: no conanfile.py\")\n            if \"conanmanifest.txt\" not in zipped_files:\n                raise ConanException(f\"Corrupted {ref} in '{remote.name}' remote: \"\n                                     f\"no conanmanifest.txt\")\n            self._signer.verify(ref, download_export, layout.metadata(), files=zipped_files)\n        except BaseException:  # So KeyboardInterrupt also cleans things\n            ConanOutput(scope=str(ref)).error(f\"Error downloading from remote '{remote.name}'\",\n                                              error_type=\"exception\")\n            self._cache.remove_recipe_layout(layout)\n            raise\n        export_folder = layout.export()\n        export_file = next((f for f in zipped_files if f.startswith(EXPORT_FILE_NAME)), None)\n        tgz_file = zipped_files.pop(export_file, None)\n\n        if tgz_file:\n            uncompress_file(tgz_file, export_folder, scope=str(ref))\n        mkdir(export_folder)\n        for file_name, file_path in zipped_files.items():  # copy CONANFILE\n            shutil.move(file_path, os.path.join(export_folder, file_name))\n\n    def get_recipe_metadata(self, recipe_layout, ref, remote, metadata):\n        \"\"\"\n        Get only the metadata for a locally existing recipe in Cache\n        \"\"\"\n        assert ref.revision, \"get_recipe without revision specified\"\n        output = ConanOutput(scope=str(ref))\n        output.info(\"Retrieving recipe metadata from remote '%s' \" % remote.name)\n        download_export = recipe_layout.download_export()\n        try:\n            self._call_remote(remote, \"get_recipe\", ref, download_export, metadata,\n                              only_metadata=True)\n        except BaseException:  # So KeyboardInterrupt also cleans things\n            output.error(f\"Error downloading metadata from remote '{remote.name}'\",\n                         error_type=\"exception\")\n            raise\n\n    def get_recipe_sources(self, ref, layout, remote):\n        assert ref.revision, \"get_recipe_sources requires RREV\"\n\n        download_folder = layout.download_export()\n        export_sources_folder = layout.export_sources()\n        local_folder_remote = self._local_folder_remote(remote)\n        if local_folder_remote is not None:\n            local_folder_remote.get_recipe_sources(ref, export_sources_folder)\n        else:\n            zipped_files = self._call_remote(remote, \"get_recipe_sources\", ref, download_folder)\n            if not zipped_files:\n                mkdir(export_sources_folder)  # create the folder even if no source files\n            else:\n                self._signer.verify(ref, download_folder, layout.metadata(), files=zipped_files)\n                # Only 1 file is guaranteed\n                tgz_file = next(iter(zipped_files.values()))\n                uncompress_file(tgz_file, export_sources_folder, scope=str(ref))\n\n    def get_package(self, pref, remote, metadata=None):\n        output = ConanOutput(scope=str(pref.ref))\n        output.info(\"Retrieving package %s from remote '%s' \" % (pref.package_id, remote.name))\n\n        assert pref.revision is not None\n\n        pkg_layout = self._cache.create_pkg_layout(pref)\n        with pkg_layout.set_dirty_context_manager():\n            mkdir(pkg_layout.metadata())\n            self._get_package(pkg_layout, pref, remote, output, metadata)\n\n    def get_package_metadata(self, pref, remote, metadata):\n        \"\"\"\n        only download the metadata, not the packge itself\n        \"\"\"\n        output = ConanOutput(scope=str(pref.ref))\n        output.info(\"Retrieving package metadata %s from remote '%s' \"\n                    % (pref.package_id, remote.name))\n\n        assert pref.revision is not None\n        pkg_layout = self._cache.pkg_layout(pref)\n        try:\n            download_pkg_folder = pkg_layout.download_package()\n            self._call_remote(remote, \"get_package\", pref, download_pkg_folder,\n                              metadata, only_metadata=True)\n        except BaseException as e:  # So KeyboardInterrupt also cleans things\n            output.error(f\"Exception while getting package metadata: {str(pref.package_id)}\",\n                         error_type=\"exception\")\n            output.error(f\"Exception: {type(e)} {str(e)}\", error_type=\"exception\")\n            raise\n\n    def _get_package(self, layout, pref, remote, scoped_output, metadata):\n        try:\n            assert pref.revision is not None\n            if remote.recipes_only:\n                raise NotFoundException(f\"Remote '{remote.name}' doesn't allow binary downloads\")\n\n            download_pkg_folder = layout.download_package()\n            # Download files to the pkg_tgz folder, not to the final one\n            zipped_files = self._call_remote(remote, \"get_package\", pref, download_pkg_folder,\n                                             metadata, only_metadata=False)\n            zipped_files = {k: v for k, v in zipped_files.items() if not k.startswith(METADATA)}\n            # quick server package integrity check:\n            for f in (CONANINFO, CONAN_MANIFEST):\n                if f not in zipped_files:\n                    raise ConanException(f\"Corrupted {pref} in '{remote.name}' remote: no {f}\")\n\n            # This is guaranteed to exists, otherwise RestClient would have raised already\n            package_file = next(f for f in zipped_files if PACKAGE_FILE_NAME in f)\n            self._signer.verify(pref, download_pkg_folder, layout.metadata(), zipped_files)\n\n            tgz_file = zipped_files.pop(package_file)\n            package_folder = layout.package()\n            uncompress_file(tgz_file, package_folder, scope=str(pref.ref))\n            mkdir(package_folder)  # Just in case it doesn't exist, because uncompress did nothing\n            for file_name, file_path in zipped_files.items():  # copy CONANINFO and CONANMANIFEST\n                shutil.move(file_path, os.path.join(package_folder, file_name))\n\n            scoped_output.success('Package installed %s' % pref.package_id)\n            scoped_output.info(\"Downloaded package revision %s\" % pref.revision)\n        except NotFoundException:\n            raise PackageNotFoundException(pref)\n        except BaseException as e:  # So KeyboardInterrupt also cleans things\n            self._cache.remove_package_layout(layout)\n            scoped_output.error(f\"Exception while getting package: {str(pref.package_id)}\",\n                                error_type=\"exception\")\n            scoped_output.error(f\"Exception: {type(e)} {str(e)}\", error_type=\"exception\")\n            raise\n\n    def search_recipes(self, remote, pattern):\n        # Used by ListAPI to \"conan list *\" recipes, and by RangeResolver to resolve version-ranges\n        cached_method = remote._caching.setdefault(\"search_recipes\", {})\n        try:\n            return cached_method[pattern]\n        except KeyError:\n            result = self._call_remote(remote, \"search\", pattern)\n            cached_method[pattern] = result\n            return result\n\n    def search_packages(self, remote, ref, list_only=False):\n        # Used only by ListAPI to list the different package_ids for a reference\n        if remote.recipes_only:\n            return {}\n        packages = self._call_remote(remote, \"search_packages\", ref, list_only)\n        if list_only:\n            packages = {PkgReference(ref, pid): None for pid, data in packages.items()}\n        else:\n            # Avoid serializing conaninfo in server side\n            packages = {PkgReference(ref, pid): load_binary_info(data[\"content\"])\n                        if \"content\" in data else data\n                        for pid, data in packages.items() if not data.get(\"recipe_hash\")}\n        return packages\n\n    def remove_recipe(self, ref, remote):\n        remote.invalidate_cache()\n        return self._call_remote(remote, \"remove_recipe\", ref)\n\n    def remove_packages(self, prefs, remote):\n        remote.invalidate_cache()\n        return self._call_remote(remote, \"remove_packages\", prefs)\n\n    def remove_all_packages(self, ref, remote):\n        remote.invalidate_cache()\n        return self._call_remote(remote, \"remove_all_packages\", ref)\n\n    def authenticate(self, remote, name, password):\n        return self._call_remote(remote, 'authenticate', name, password, enforce_disabled=False)\n\n    def get_recipe_revisions(self, ref: RecipeReference, remote: Remote) -> List[RecipeReference]:\n        # Used by ListAPI to list recipe revisions for a ref without revision\n        # and by ConanProxy resolving legacy_update Conan 1 logic\n        assert ref.revision is None, \"get_recipe_revisions_references of a reference with revision\"\n        return self._call_remote(remote, \"get_recipe_revisions_references\", ref)\n\n    def get_recipe_revision(self, ref: RecipeReference, remote: Remote) -> RecipeReference:\n        # Used by UploadUpstreamChecker to see if the revision exist in the server\n        # Used by Download, to get timestamp from server and respect it\n        # Used by ConanProxy to confirm existence of specific revision\n        assert ref.revision is not None, \"recipe_exists needs a revision\"\n        return self._call_remote(remote, \"get_recipe_revision_reference\", ref)\n\n    def get_latest_recipe_revision(self, ref: RecipeReference, remote: Remote) -> RecipeReference:\n        # Used by ListAPI to retrieve the latest revision\n        # Used by ConanProxy to resolve to the latest revision\n        assert ref.revision is None, \"get_latest_recipe_reference of a reference with revision\"\n        return self._call_remote(remote, \"get_latest_recipe_reference\", ref)\n\n    def get_package_revisions(self, pref: PkgReference, remote: Remote) -> List[PkgReference]:\n        # Used by ListAPI to retrieve multiple package revisions\n        assert pref.revision is None, \"get_package_revisions_references of a reference with revision\"\n        if remote.recipes_only:\n            return []\n        return self._call_remote(remote, \"get_package_revisions_references\", pref)\n\n    def get_package_revision(self, pref: PkgReference, remote: Remote) -> PkgReference:\n        # Used by UploadUpstreamChecker to see if the revision exist in the server\n        # Used by Download, to get timestamp from server and respect it\n        assert pref.revision is not None, \"get_package_revision_reference needs a revision\"\n        return self._call_remote(remote, \"get_package_revision_reference\", pref)\n\n    def get_latest_package_revision(self, pref: PkgReference, remote: Remote,\n                                    info=None) -> PkgReference:\n        # Used by List to resolve the latest package revision\n        # Used by GraphBinariesAnalyzer to resolve to latest package revision\n        assert pref.revision is None, \"get_latest_package_reference of a reference with revision\"\n        if remote.recipes_only:\n            raise NotFoundException(f\"Remote '{remote.name}' doesn't allow binary downloads\")\n        # These headers are useful to know what configurations are being requested in the server\n        headers = None\n        if info:\n            headers = {}\n            settings = [f'{k}={v}' for k, v in info.settings.items()]\n            if settings:\n                headers['Conan-PkgID-Settings'] = ';'.join(settings)\n            options = [f'{k}={v}' for k, v in info.options.serialize().items()\n                       if k in (\"shared\", \"fPIC\", \"header_only\")]\n            if options:\n                headers['Conan-PkgID-Options'] = ';'.join(options)\n\n        cached_method = remote._caching.setdefault(\"get_latest_package_reference\", {})\n        try:\n            result = cached_method[pref]\n        except KeyError:\n            try:\n                result = self._call_remote(remote, \"get_latest_package_reference\", pref,\n                                           headers=headers)\n                cached_method[pref] = result\n                return result\n            except NotFoundException as e:\n                # Let's avoid leaking memory by saving all the exception objects,\n                # which translates to a ~2x memory increase. Now, it only saves the type and the\n                # final message. For now, let's cache only the NotFoundException one.\n                cached_method[pref] = self._ErrorMsg(str(e))\n                raise e\n        else:\n            if isinstance(result, self._ErrorMsg):\n                # Let's raise it\n                raise NotFoundException(result.message)\n            return result\n\n    def _call_remote(self, remote, method, *args, **kwargs):\n        assert (isinstance(remote, Remote))\n        enforce_disabled = kwargs.pop(\"enforce_disabled\", True)\n        if remote.disabled and enforce_disabled:\n            raise ConanException(\"Remote '%s' is disabled\" % remote.name)\n        local_folder_remote = self._local_folder_remote(remote)\n        try:\n            if local_folder_remote is not None:\n                return local_folder_remote.call_method(method, *args, **kwargs)\n            return self._auth_manager.call_rest_api_method(remote, method, *args, **kwargs)\n        except ConnectionError as exc:\n            raise ConanConnectionError((\"%s\\n\\nUnable to connect to remote %s=%s\\n\"\n                                        \"1. Make sure the remote is reachable or,\\n\"\n                                        \"2. Disable it with 'conan remote disable <remote>' or,\\n\"\n                                        \"3. Use the '-nr/--no-remote' argument\\n\"\n                                        \"Then try again.\"\n                                        ) % (str(exc), remote.name, remote.url))\n        except ConanException as exc:\n            exc.remote = remote\n            raise\n        except Exception as exc:\n            raise ConanException(exc, remote=remote)\n\n\ndef uncompress_file(src_path, dest_folder, scope=None):\n    if sys.version_info.minor < 14 and src_path.endswith(\"zst\"):\n        raise ConanException(f\"File {os.path.basename(src_path)} compressed with 'zst', \"\n                             f\"unsupported for Python<3.14 \")\n    try:\n        filesize = os.path.getsize(src_path)\n        big_file = filesize > 10000000  # 10 MB\n        if big_file:\n            hs = human_size(filesize)\n            ConanOutput(scope=scope).info(f\"Decompressing {hs} {os.path.basename(src_path)}\")\n        with open(src_path, mode='rb') as file_handler:\n            tar_extract(file_handler, dest_folder)\n    except Exception as e:\n        error_msg = \"Error while extracting downloaded file '%s' to %s\\n%s\\n\"\\\n                    % (src_path, dest_folder, str(e))\n        # try to remove the files\n        try:\n            if os.path.exists(dest_folder):\n                shutil.rmtree(dest_folder)\n                error_msg += \"Folder removed\"\n        except Exception:\n            error_msg += \"Folder not removed, files/package might be damaged, remove manually\"\n        raise ConanException(error_msg)\n"
  },
  {
    "path": "conan/internal/rest/rest_client.py",
    "content": "from conan.internal import REVISIONS\nfrom conan.internal.rest.rest_client_v2 import RestV2Methods\nfrom conan.errors import ConanException\n\nCHECKSUM_DEPLOY = \"checksum_deploy\"  # capability\n\n\nclass RestApiClient:\n    \"\"\"\n        Rest Api Client for handle remote.\n    \"\"\"\n\n    def __init__(self, remote, token, requester, config):\n        self._token = token\n        self._remote_url = remote.url\n        self._requester = requester\n        self._verify_ssl = remote.verify_ssl\n        self._config = config\n        self._remote = remote\n\n    def _capable(self, capability):\n        # Caching of capabilities per-remote\n        capabilities = getattr(self._remote, \"_capabilities\", None)\n        if capabilities is None:\n            tmp = RestV2Methods(self._remote_url, self._token,\n                                self._requester, self._config, self._verify_ssl)\n            capabilities = tmp.server_capabilities()\n            setattr(self._remote, \"_capabilities\", capabilities)\n        return capability in capabilities\n\n    def _get_api(self):\n        revisions = self._capable(REVISIONS)\n\n        if not revisions:\n            raise ConanException(\"The remote doesn't support revisions. \"\n                                 \"Conan 2.0 is no longer compatible with \"\n                                 \"remotes that don't accept revisions.\")\n        checksum_deploy = self._capable(CHECKSUM_DEPLOY)\n        return RestV2Methods(self._remote_url, self._token,\n                             self._requester, self._config, self._verify_ssl,\n                             checksum_deploy)\n\n    def get_recipe(self, ref, dest_folder, metadata, only_metadata):\n        return self._get_api().get_recipe(ref, dest_folder, metadata, only_metadata)\n\n    def get_recipe_sources(self, ref, dest_folder):\n        return self._get_api().get_recipe_sources(ref, dest_folder)\n\n    def get_package(self, pref, dest_folder, metadata, only_metadata):\n        return self._get_api().get_package(pref, dest_folder, metadata, only_metadata)\n\n    def upload_recipe(self, ref, files_to_upload):\n        return self._get_api().upload_recipe(ref, files_to_upload)\n\n    def upload_package(self, pref, files_to_upload):\n        return self._get_api().upload_package(pref, files_to_upload)\n\n    def authenticate(self, user, password):\n        # BYPASS capabilities, in case v1/ping is protected\n        api_v2 = RestV2Methods(self._remote_url, self._token,\n                               self._requester, self._config, self._verify_ssl)\n        token = api_v2.authenticate(user, password)\n        return token\n\n    def check_credentials(self, force_auth=False):\n        return self._get_api().check_credentials(force_auth)\n\n    def search(self, pattern=None, ignorecase=True):\n        return self._get_api().search(pattern, ignorecase)\n\n    def search_packages(self, reference, list_only=False):\n        return self._get_api().search_packages(reference, list_only)\n\n    def remove_recipe(self, ref):\n        return self._get_api().remove_recipe(ref)\n\n    def remove_all_packages(self, ref):\n        return self._get_api().remove_all_packages(ref)\n\n    def remove_packages(self, prefs):\n        return self._get_api().remove_packages(prefs)\n\n    def get_recipe_revisions_references(self, ref):\n        return self._get_api().get_recipe_revisions_references(ref)\n\n    def get_package_revisions_references(self, pref):\n        return self._get_api().get_package_revisions_references(pref)\n\n    def get_latest_recipe_reference(self, ref):\n        return self._get_api().get_latest_recipe_reference(ref)\n\n    def get_latest_package_reference(self, pref, headers):\n        return self._get_api().get_latest_package_reference(pref, headers=headers)\n\n    def get_recipe_revision_reference(self, ref):\n        return self._get_api().get_recipe_revision_reference(ref)\n\n    def get_package_revision_reference(self, pref):\n        return self._get_api().get_package_revision_reference(pref)\n"
  },
  {
    "path": "conan/internal/rest/rest_client_local_recipe_index.py",
    "content": "import os\nimport sys\nimport textwrap\nfrom fnmatch import fnmatch\nfrom io import StringIO\n\nimport yaml\n\nfrom conan.api.model import LOCAL_RECIPES_INDEX\nfrom conan.api.output import ConanOutput\nfrom conan.internal.cache.home_paths import HomePaths\nfrom conan.internal.api.export import cmd_export\nfrom conan.internal.hook_manager import HookManager\nfrom conan.internal.loader import ConanFileLoader\nfrom conan.internal.errors import ConanReferenceDoesNotExistInDB, RecipeNotFoundException, \\\n    PackageNotFoundException\nfrom conan.errors import ConanException\nfrom conan.internal.model.conf import ConfDefinition\nfrom conan.api.model import RecipeReference\nfrom conan.internal.util.files import load, save, rmdir, copytree_compat\n\n\ndef add_local_recipes_index_remote(home_folder, remote):\n    if remote.remote_type != LOCAL_RECIPES_INDEX:\n        return\n    local_recipes_index_path = HomePaths(home_folder).local_recipes_index_path\n    repo_folder = os.path.join(local_recipes_index_path, remote.name)\n\n    output = ConanOutput()\n    if os.path.exists(repo_folder):\n        output.warning(f\"The cache folder for remote {remote.name} existed, removing it\")\n        rmdir(repo_folder)\n\n    cache_path = os.path.join(repo_folder, \".conan\")\n    hook_folder = HomePaths(cache_path).hooks_path\n    trim_hook = os.path.join(hook_folder, \"hook_trim_conandata.py\")\n    hook_content = textwrap.dedent(\"\"\"\\\n        from conan.tools.files import trim_conandata\n        def post_export(conanfile):\n            if conanfile.conan_data:\n                trim_conandata(conanfile)\n        \"\"\")\n    save(trim_hook, hook_content)\n\n\ndef remove_local_recipes_index_remote(home_folder, remote):\n    if remote.remote_type == LOCAL_RECIPES_INDEX:\n        local_recipes_index_path = HomePaths(home_folder).local_recipes_index_path\n        local_recipes_index_path = os.path.join(local_recipes_index_path, remote.name)\n        ConanOutput().info(f\"Removing temporary files for '{remote.name}' \"\n                           f\"local-recipes-index remote\")\n        rmdir(local_recipes_index_path)\n\n\nclass RestApiClientLocalRecipesIndex:\n    \"\"\"\n    Implements the RestAPI but instead of over HTTP for a remote server, using just\n    a local folder assuming the conan-center-index repo layout\n    \"\"\"\n\n    def __init__(self, remote, home_folder):\n        self._remote = remote\n        local_recipes_index_path = HomePaths(home_folder).local_recipes_index_path\n        local_recipes_index_path = os.path.join(local_recipes_index_path, remote.name, \".conan\")\n        repo_folder = self._remote.url\n\n        from conan.internal.conan_app import LocalRecipesIndexApp\n        self._app = LocalRecipesIndexApp(local_recipes_index_path)\n        self._hook_manager = HookManager(HomePaths(local_recipes_index_path).hooks_path)\n        self._layout = _LocalRecipesIndexLayout(repo_folder)\n\n    def call_method(self, method_name, *args, **kwargs):\n        return getattr(self, method_name)(*args, **kwargs)\n\n    def get_recipe(self, ref, dest_folder):\n        export_folder = self._app.cache.recipe_layout(ref).export()\n        return self._copy_files(export_folder, dest_folder)\n\n    def get_recipe_sources(self, ref, dest_folder):\n        try:\n            export_sources = self._app.cache.recipe_layout(ref).export_sources()\n        except ConanReferenceDoesNotExistInDB:\n            # This can happen when there a local-recipes-index is being queried for sources it\n            # doesn't contain\n            # If that is the case, check if they are in the repo, try to export\n            exported_ref = self._export_recipe(ref)  # This will raise NotFound if non existing\n            export_sources = self._app.cache.recipe_layout(exported_ref).export_sources()\n        return self._copy_files(export_sources, dest_folder)\n\n    def get_package(self, pref, dest_folder, metadata, only_metadata):\n        raise ConanException(f\"Remote local-recipes-index '{self._remote.name}' doesn't support \"\n                             \"binary packages\")\n\n    def upload_recipe(self, ref, files_to_upload):\n        raise ConanException(f\"Remote local-recipes-index '{self._remote.name}' doesn't support upload\")\n\n    def upload_package(self, pref, files_to_upload):\n        raise ConanException(f\"Remote local-recipes-index '{self._remote.name}' doesn't support upload\")\n\n    def authenticate(self, user, password):\n        raise ConanException(f\"Remote local-recipes-index '{self._remote.name}' doesn't support \"\n                             \"authentication\")\n\n    def check_credentials(self, force_auth=False):\n        raise ConanException(f\"Remote local-recipes-index '{self._remote.name}' doesn't support upload\")\n\n    def search(self, pattern=None):\n        return self._layout.get_recipes_references(pattern)\n\n    def search_packages(self, reference, _=False):\n        assert self and reference\n        return {}\n\n    def remove_recipe(self, ref):\n        raise ConanException(f\"Remote local-recipes-index '{self._remote.name}' doesn't support remove\")\n\n    def remove_all_packages(self, ref):\n        raise ConanException(f\"Remote local-recipes-index '{self._remote.name}' doesn't support remove\")\n\n    def remove_packages(self, prefs):\n        raise ConanException(f\"Remote local-recipes-index '{self._remote.name}' doesn't support remove\")\n\n    def get_recipe_revisions_references(self, ref):\n        ref = self._export_recipe(ref)\n        return [ref]\n\n    def get_package_revisions_references(self, pref):\n        raise PackageNotFoundException(pref)\n\n    def get_latest_recipe_reference(self, ref):\n        ref = self._export_recipe(ref)\n        return ref\n\n    def get_latest_package_reference(self, pref, headers):\n        raise PackageNotFoundException(pref)\n\n    def get_recipe_revision_reference(self, ref):\n        new_ref = self._export_recipe(ref)\n        return new_ref\n\n    def get_package_revision_reference(self, pref):\n        raise PackageNotFoundException(pref)\n\n    # Helper methods to implement the interface\n    def _export_recipe(self, ref):\n        folder = self._layout.get_recipe_folder(ref)\n        conanfile_path = os.path.join(folder, \"conanfile.py\")\n        original_stderr = sys.stderr\n        sys.stderr = StringIO()\n        try:\n            global_conf = ConfDefinition()\n            new_ref, _ = cmd_export(self._app.loader, self._app.cache, self._hook_manager,\n                                    global_conf, conanfile_path,\n                                    ref.name, str(ref.version), None, None, remotes=[self._remote])\n        except Exception as e:\n            raise ConanException(f\"Error while exporting recipe from remote: {self._remote.name}\\n\"\n                                 f\"{str(e)}\")\n        finally:\n            export_err = sys.stderr.getvalue()\n            sys.stderr = original_stderr\n            ConanOutput(scope=\"local-recipes-index\").debug(f\"Internal export for {ref}:\\n\"\n                                                           f\"{textwrap.indent(export_err, '    ')}\")\n        if new_ref.user != ref.user or new_ref.channel != ref.channel:\n            raise RecipeNotFoundException(ref)\n        if ref.revision is not None and new_ref.revision != ref.revision:\n            ConanOutput().warning(f\"A specific revision '{ref.repr_notime()}' was requested, but it \"\n                                  \"doesn't match the current available revision in source. The \"\n                                  \"local-recipes-index can't provide a specific revision\")\n            raise RecipeNotFoundException(ref)\n        return new_ref\n\n    @staticmethod\n    def _copy_files(source_folder, dest_folder):\n        if not os.path.exists(source_folder):\n            return {}\n        copytree_compat(source_folder, dest_folder)\n        ret = {}\n        for root, _, _files in os.walk(dest_folder):\n            for _f in _files:\n                rel = os.path.relpath(os.path.join(root, _f), dest_folder)\n                ret[rel] = os.path.join(dest_folder, root, _f)\n        return ret\n\n\nclass _LocalRecipesIndexLayout:\n\n    def __init__(self, base_folder):\n        self._base_folder = base_folder\n\n    def _get_base_folder(self, recipe_name):\n        return os.path.join(self._base_folder, \"recipes\", recipe_name)\n\n    @staticmethod\n    def _load_config_yml(folder):\n        config = os.path.join(folder, \"config.yml\")\n        if not os.path.isfile(config):\n            return None\n        return yaml.safe_load(load(config))\n\n    def get_recipes_references(self, pattern):\n        name_pattern = pattern.split(\"/\", 1)[0]\n        recipes_dir = os.path.join(self._base_folder, \"recipes\")\n        if not os.path.isdir(recipes_dir):\n            raise ConnectionError(\"Cannot connect to 'local-recipes-index' repository, missing \"\n                                  f\"'recipes' folder: {recipes_dir}\")\n        recipes = os.listdir(recipes_dir)\n        recipes.sort()\n        ret = []\n        excluded = set()\n\n        original_pattern = pattern\n        try:\n            pattern_ref = RecipeReference.loads(pattern)\n            # We don't care about user/channel for now, we'll check for those below,\n            # just add all candidates for now\n            pattern = f\"{pattern_ref.name}/{pattern_ref.version}\"\n        except:\n            # pattern = pattern\n            pattern = f\"{name_pattern}/*\"\n            original_pattern = pattern\n            pass\n\n        loader = ConanFileLoader(None)\n        for r in recipes:\n            if r.startswith(\".\"):\n                # Skip hidden folders, no recipes should start with a dot\n                continue\n            if not fnmatch(r, name_pattern):\n                continue\n            folder = self._get_base_folder(r)\n            config_yml = self._load_config_yml(folder)\n            if config_yml is None:\n                raise ConanException(f\"Corrupted repo, folder {r} without 'config.yml'\")\n            versions = config_yml[\"versions\"]\n            for v in versions:\n                # TODO: Check the search pattern is the same as remotes and cache\n                ref = f\"{r}/{v}\"\n                if not fnmatch(ref, pattern):\n                    continue\n                subfolder = versions[v][\"folder\"]\n                # This check can be removed after compatibility with 2.0\n                conanfile = os.path.join(recipes_dir, r, subfolder, \"conanfile.py\")\n                conanfile_content = load(conanfile)\n\n                if \"from conans\" in conanfile_content or \"import conans\" in conanfile_content:\n                    excluded.add(r)\n                    continue\n                ref = RecipeReference.loads(ref)\n                try:\n                    recipe = loader.load_basic(conanfile)\n                    ref.user = recipe.user\n                    ref.channel = recipe.channel\n                except Exception as e:\n                    ConanOutput().warning(f\"Couldn't load recipe {conanfile}: {e}\")\n                if ref.matches(original_pattern, None):\n                    # Check again the pattern with the user/channel\n                    ret.append(ref)\n        if excluded:\n            ConanOutput().warning(f\"Excluding recipes not Conan 2.0 ready: {', '.join(excluded)}\")\n        return ret\n\n    def get_recipe_folder(self, ref):\n        folder = self._get_base_folder(ref.name)\n        data = self._load_config_yml(folder)\n        if data is None:\n            raise RecipeNotFoundException(ref)\n        versions = data[\"versions\"]\n        if str(ref.version) not in versions:\n            raise RecipeNotFoundException(ref)\n        subfolder = versions[str(ref.version)][\"folder\"]\n        return os.path.join(folder, subfolder)\n"
  },
  {
    "path": "conan/internal/rest/rest_client_v2.py",
    "content": "import copy\nimport fnmatch\nimport hashlib\nimport json\nimport os\nfrom threading import Thread\n\nfrom requests.auth import AuthBase, HTTPBasicAuth\nfrom uuid import getnode as get_mac\n\nfrom conan.api.output import ConanOutput\nfrom conan.internal.paths import EXPORT_SOURCES_FILE_NAME, CONANINFO, CONAN_MANIFEST, \\\n    EXPORT_FILE_NAME, PACKAGE_FILE_NAME\nfrom conan.internal.rest.caching_file_downloader import ConanInternalCacheDownloader\nfrom conan.internal.rest import response_to_str\nfrom conan.internal.rest.client_routes import ClientV2Router\nfrom conan.internal.rest.file_uploader import FileUploader\nfrom conan.internal.errors import AuthenticationException, ForbiddenException, NotFoundException, \\\n    RecipeNotFoundException, PackageNotFoundException, EXCEPTION_CODE_MAPPING\nfrom conan.errors import ConanException\nfrom conan.api.model import PkgReference\nfrom conan.api.model import RecipeReference\nfrom conan.internal.util.dates import from_iso8601_to_timestamp\n\n\n# TODO: We might want to replace this raw Thread for a ThreadPool, to align with other code usages\nclass ExceptionThread(Thread):\n    def run(self):\n        self._exc = None\n        try:\n            super().run()\n        except Exception as e:\n            self._exc = e\n\n    def join(self, timeout=None):\n        super().join(timeout=timeout)\n\n    def raise_errors(self):\n        if self._exc:\n            raise self._exc\n\n\nclass JWTAuth(AuthBase):\n    \"\"\"Attaches JWT Authentication to the given Request object.\"\"\"\n\n    def __init__(self, token):\n        self.bearer = \"Bearer %s\" % str(token) if token else None\n\n    def __call__(self, request):\n        if self.bearer:\n            request.headers['Authorization'] = self.bearer\n        return request\n\n\ndef _raise_exception_from_error(error_code, text):\n    tmp = {v: k for k, v in EXCEPTION_CODE_MAPPING.items()  # All except NotFound\n           if k not in (RecipeNotFoundException, PackageNotFoundException)}\n    try:\n        raise tmp[error_code](text)\n    except KeyError:\n        raise ConanException(f\"Server exception {error_code}: {text}\")\n\n\ndef _get_mac_digest():  # To avoid re-hashing all the time the same mac\n    cached = getattr(_get_mac_digest, \"_cached_value\", None)\n    if cached is not None:\n        return cached\n    sha1 = hashlib.sha1()\n    sha1.update(str(get_mac()).encode())\n    cached = str(sha1.hexdigest())\n    _get_mac_digest._cached_value = cached\n    return cached\n\n\nclass RestV2Methods:\n\n    def __init__(self, remote_url, token, requester, config, verify_ssl, checksum_deploy=False):\n        self.remote_url = remote_url\n        self.custom_headers = {'X-Client-Anonymous-Id': _get_mac_digest()}\n        self.requester = requester\n        self._config = config\n        self.verify_ssl = verify_ssl\n        self._checksum_deploy = checksum_deploy\n        self.router = ClientV2Router(self.remote_url.rstrip(\"/\"))\n        self.auth = JWTAuth(token)\n\n    @staticmethod\n    def _check_error_response(ret):\n        if ret.status_code == 401:\n            raise AuthenticationException(\"Wrong user or password\")\n        # Cannot check content-type=text/html, conan server is doing it wrong\n        if not ret.ok or \"html>\" in str(ret.content):\n            raise ConanException(\"%s\\n\\nInvalid server response, check remote URL and \"\n                                 \"try again\" % str(ret.content))\n\n    def authenticate(self, user, password):\n        \"\"\"Sends user + password to get:\n          - A plain response with a regular token (not supported refresh in the remote) and None\n        \"\"\"\n        auth = HTTPBasicAuth(user, password)\n        url = self.router.common_authenticate()\n        # logger.debug(\"REST: Authenticate to get access_token: %s\" % url)\n        ret = self.requester.get(url, auth=auth, headers=self.custom_headers,\n                                 verify=self.verify_ssl)\n\n        self._check_error_response(ret)\n        return ret.content.decode()\n\n    def check_credentials(self, force_auth=False):\n        \"\"\"If token is not valid will raise AuthenticationException.\n        User will be asked for new user/pass\"\"\"\n        url = self.router.common_check_credentials()\n        auth = self.auth\n        if force_auth and auth.bearer is None:\n            auth = JWTAuth(\"unset\")\n\n        # logger.debug(\"REST: Check credentials: %s\" % url)\n        ret = self.requester.get(url, auth=auth, headers=self.custom_headers,\n                                 verify=self.verify_ssl)\n        if ret.status_code != 200:\n            ret.charset = \"utf-8\"  # To be able to access ret.text (ret.content are bytes)\n            text = ret.text if ret.status_code != 404 else \"404 Not found\"\n            _raise_exception_from_error(ret.status_code, text)\n        return ret.content.decode()\n\n    def server_capabilities(self):\n        \"\"\"Get information about the server: status, version, type and capabilities\"\"\"\n        url = self.router.ping()\n        auth = self.auth\n        ret = self.requester.get(url, auth=auth, headers=self.custom_headers, verify=self.verify_ssl)\n\n        server_capabilities = ret.headers.get('X-Conan-Server-Capabilities')\n        if not server_capabilities and not ret.ok:\n            # Old Artifactory might return 401/403 without capabilities, we don't want\n            # to cache them #5687, so raise the exception and force authentication\n            _raise_exception_from_error(ret.status_code, response_to_str(ret))\n        if server_capabilities is None:\n            # Some servers returning 200-ok, even if not valid repo\n            raise ConanException(f\"Remote {self.remote_url} doesn't seem like a valid Conan remote\")\n\n        return [cap.strip() for cap in server_capabilities.split(\",\") if cap]\n\n    def _get_json(self, url, headers=None):\n        req_headers = self.custom_headers.copy()\n        req_headers.update(headers or {})\n        response = self.requester.get(url, auth=self.auth, headers=req_headers,\n                                      verify=self.verify_ssl, stream=True)\n\n        if response.status_code != 200:  # Error message is text\n            response.charset = \"utf-8\"  # To be able to access ret.text (ret.content are bytes)\n            _raise_exception_from_error(response.status_code, response_to_str(response))\n\n        content = response.content.decode()\n        content_type = response.headers.get(\"Content-Type\")\n        if content_type != 'application/json' and content_type != 'application/json; charset=utf-8':\n            raise ConanException(\"%s\\n\\nResponse from remote is not json, but '%s'\"\n                                 % (content, content_type))\n\n        try:  # This can fail, if some proxy returns 200 and an html message\n            result = json.loads(content)\n        except Exception:\n            raise ConanException(\"Remote responded with broken json: %s\" % content)\n        if not isinstance(result, dict):\n            raise ConanException(\"Unexpected server response %s\" % result)\n        return result\n\n    def upload_recipe(self, ref, files_to_upload):\n        if files_to_upload:\n            urls = {fn: self.router.recipe_file(ref, fn)\n                    for fn in files_to_upload}\n            self._upload_files(files_to_upload, urls, str(ref))\n\n    def upload_package(self, pref, files_to_upload):\n        urls = {fn: self.router.package_file(pref, fn)\n                for fn in files_to_upload}\n        self._upload_files(files_to_upload, urls, str(pref))\n\n    def search(self, pattern=None, ignorecase=True):\n        \"\"\"\n        the_files: dict with relative_path: content\n        \"\"\"\n        url = self.router.search(pattern, ignorecase)\n        response = self._get_json(url)[\"results\"]\n        # We need to filter the \"_/_\" user and channel from Artifactory\n        ret = []\n        for reference in response:\n            ref = RecipeReference.loads(reference)\n            if ref.user == \"_\":\n                ref.user = None\n            if ref.channel == \"_\":\n                ref.channel = None\n            ret.append(ref)\n        return ret\n\n    def search_packages(self, ref, list_only):\n        \"\"\"Client is filtering by the query\"\"\"\n        url = self.router.search_packages(ref, list_only)\n        package_infos = self._get_json(url)\n        return package_infos\n\n    def _get_file_list_json(self, url):\n        data = self._get_json(url)\n        # Discarding (.keys()) still empty metadata for files\n        # and make sure the paths like metadata/sign/signature are normalized to /\n        data[\"files\"] = list(d.replace(\"\\\\\", \"/\") for d in data[\"files\"].keys())\n        return data\n\n    def get_recipe(self, ref, dest_folder, metadata, only_metadata):\n        url = self.router.recipe_snapshot(ref)\n        data = self._get_file_list_json(url)\n        server_files = data[\"files\"]\n        result = {}\n\n        if not only_metadata:\n            accepted_files = [\"conanfile.py\", CONAN_MANIFEST,  \"metadata/sign\"]\n            files = [f for f in server_files if any(f.startswith(m) for m in accepted_files)]\n            export_file = self._find_compressed_file(ref, server_files, EXPORT_FILE_NAME)\n            if export_file is not None:\n                files.append(export_file)\n            # If we didn't indicated reference, server got the latest, use absolute now, it's safer\n            urls = {fn: self.router.recipe_file(ref, fn) for fn in files}\n            self._download_and_save_files(urls, dest_folder, files, parallel=True)\n            result.update({fn: os.path.join(dest_folder, fn) for fn in files})\n        if metadata:\n            metadata = [f\"metadata/{m}\" for m in metadata]\n            files = [f for f in server_files if any(fnmatch.fnmatch(f, m) for m in metadata)]\n            urls = {fn: self.router.recipe_file(ref, fn) for fn in files}\n            self._download_and_save_files(urls, dest_folder, files, parallel=True, metadata=True)\n            result.update({fn: os.path.join(dest_folder, fn) for fn in files})\n        return result\n\n    def get_recipe_sources(self, ref, dest_folder):\n        # If revision not specified, check latest\n        assert ref.revision, f\"get_recipe_sources() called without revision {ref}\"\n        url = self.router.recipe_snapshot(ref)\n        data = self._get_file_list_json(url)\n        files = data[\"files\"]\n        src_file = self._find_compressed_file(ref, files, EXPORT_SOURCES_FILE_NAME)\n        if src_file is None:\n            return None\n\n        # If we didn't indicated reference, server got the latest, use absolute now, it's safer\n        urls = {src_file: self.router.recipe_file(ref, src_file)}\n        self._download_and_save_files(urls, dest_folder, [src_file, ], scope=str(ref))\n        ret = {src_file: os.path.join(dest_folder, src_file)}\n        return ret\n\n    @staticmethod\n    def _find_compressed_file(ref, server_files, artifact, exists=False):\n        pkg_files = [f for f in server_files if f.startswith(artifact)]\n        if len(pkg_files) > 1:\n            raise ConanException(f\"{ref} is corrupted in the server, it contains \"\n                                 f\"more than one compressed file: {sorted(pkg_files)}\")\n        if not pkg_files:\n            if not exists:\n                return None\n            raise ConanException(f\"Recipe {ref} is corrupted in the server, it doesn't contain \"\n                                 f\"a {artifact} file\")\n        return pkg_files[0]\n\n    def get_package(self, pref, dest_folder, metadata, only_metadata):\n        url = self.router.package_snapshot(pref)\n        data = self._get_file_list_json(url)\n        server_files = data[\"files\"]\n        result = {}\n        # Download only known files, but not metadata (except sign)\n        if not only_metadata:  # Retrieve package first, then metadata\n            pkg_file = self._find_compressed_file(pref, server_files, PACKAGE_FILE_NAME, exists=True)\n            accepted_files = [CONANINFO, pkg_file, CONAN_MANIFEST, \"metadata/sign\"]\n            files = [f for f in server_files if any(f.startswith(m) for m in accepted_files)]\n            # If we didn't indicated reference, server got the latest, use absolute now, it's safer\n            urls = {fn: self.router.package_file(pref, fn) for fn in files}\n            self._download_and_save_files(urls, dest_folder, files, scope=str(pref.ref))\n            result.update({fn: os.path.join(dest_folder, fn) for fn in files})\n\n        if metadata:\n            metadata = [f\"metadata/{m}\" for m in metadata]\n            files = [f for f in server_files if any(fnmatch.fnmatch(f, m) for m in metadata)]\n            urls = {fn: self.router.package_file(pref, fn) for fn in files}\n            self._download_and_save_files(urls, dest_folder, files, scope=str(pref.ref),\n                                          metadata=True)\n            result.update({fn: os.path.join(dest_folder, fn) for fn in files})\n        return result\n\n    def _upload_files(self, files, urls, ref):\n        failed = []\n        uploader = FileUploader(self.requester, self.verify_ssl, self._config)\n        # conan_package.tgz and conan_export.tgz are uploaded first to avoid uploading conaninfo.txt\n        # or conanamanifest.txt with missing files due to a network failure\n        for filename in sorted(files):\n            # As the filenames are sorted, the last one is always \"conanmanifest.txt\"\n            resource_url = urls[filename]\n            try:\n                uploader.upload(resource_url, files[filename], auth=self.auth,\n                                dedup=self._checksum_deploy, ref=ref)\n            except (AuthenticationException, ForbiddenException):\n                raise\n            except Exception as exc:\n                ConanOutput().error(f\"\\nError uploading file: {filename}, '{exc}'\",\n                                    error_type=\"exception\")\n                failed.append(filename)\n\n        if failed:\n            raise ConanException(\"Execute upload again to retry upload the failed files: %s\"\n                                 % \", \".join(failed))\n\n    def _download_and_save_files(self, urls, dest_folder, files, parallel=False, scope=None,\n                                 metadata=False):\n        # Take advantage of filenames ordering, so that conan_package.tgz and conan_export.tgz\n        # can be < conanfile, conaninfo, and sent always the last, so smaller files go first\n        retry = self._config.get(\"core.download:retry\", check_type=int, default=2)\n        retry_wait = self._config.get(\"core.download:retry_wait\", check_type=int, default=0)\n        downloader = ConanInternalCacheDownloader(self.requester, self._config, scope=scope)\n        threads = []\n\n        for filename in sorted(files, reverse=True):\n            resource_url = urls[filename]\n            abs_path = os.path.join(dest_folder, filename)\n            os.makedirs(os.path.dirname(abs_path), exist_ok=True)  # filename in subfolder must exist\n            if parallel:\n                kwargs = {\"url\": resource_url, \"file_path\": abs_path, \"retry\": retry,\n                          \"retry_wait\": retry_wait, \"verify_ssl\": self.verify_ssl,\n                          \"auth\": self.auth, \"metadata\": metadata}\n                thread = ExceptionThread(target=downloader.download, kwargs=kwargs)\n                threads.append(thread)\n                thread.start()\n            else:\n                downloader.download(url=resource_url, file_path=abs_path, auth=self.auth,\n                                    verify_ssl=self.verify_ssl, retry=retry, retry_wait=retry_wait,\n                                    metadata=metadata)\n        for t in threads:\n            t.join()\n        for t in threads:  # Need to join all before raising errors\n            t.raise_errors()\n\n    def remove_all_packages(self, ref):\n        \"\"\" Remove all packages from the specified reference\"\"\"\n        self.check_credentials()\n        assert ref.revision is not None, \"remove_packages needs RREV\"\n\n        url = self.router.remove_all_packages(ref)\n        response = self.requester.delete(url, auth=self.auth, verify=self.verify_ssl,\n                                         headers=self.custom_headers)\n        if response.status_code == 404:\n            # Double check if it is a 404 because there are no packages\n            try:\n                package_search_url = self.router.search_packages(ref, list_only=True)\n                if not self._get_json(package_search_url):\n                    return\n            except Exception:\n                pass\n        if response.status_code != 200:  # Error message is text\n            # To be able to access ret.text (ret.content are bytes)\n            response.charset = \"utf-8\"\n            _raise_exception_from_error(response.status_code, response.text)\n\n    def remove_packages(self, prefs):\n        self.check_credentials()\n        for pref in prefs:\n            if not pref.revision:\n                prevs = self.get_package_revisions_references(pref)\n            else:\n                prevs = [pref]\n            for prev in prevs:\n                url = self.router.remove_package(prev)\n                response = self.requester.delete(url, auth=self.auth, headers=self.custom_headers,\n                                                 verify=self.verify_ssl)\n                if response.status_code == 404:\n                    raise PackageNotFoundException(pref)\n                if response.status_code != 200:  # Error message is text\n                    # To be able to access ret.text (ret.content are bytes)\n                    response.charset = \"utf-8\"\n                    _raise_exception_from_error(response.status_code, response.text)\n\n    def remove_recipe(self, ref):\n        \"\"\" Remove a recipe and packages \"\"\"\n        self.check_credentials()\n        if ref.revision is None:  # FIXME: This is unused at the moment, check server implementation\n            # Remove all the RREVs\n            refs = self.get_recipe_revisions_references(ref)\n        else:\n            refs = [ref]\n\n        for ref in refs:\n            url = self.router.remove_recipe(ref)\n            response = self.requester.delete(url, auth=self.auth, headers=self.custom_headers,\n                                             verify=self.verify_ssl)\n            if response.status_code == 404:\n                raise RecipeNotFoundException(ref)\n            if response.status_code != 200:  # Error message is text\n                # To be able to access ret.text (ret.content are bytes)\n                response.charset = \"utf-8\"\n                _raise_exception_from_error(response.status_code, response.text)\n\n    def get_recipe_revision_reference(self, ref):\n        # FIXME: implement this new endpoint in the remotes?\n        assert ref.revision, \"recipe_exists has to be called with a complete reference\"\n        ref_without_rev = copy.copy(ref)\n        ref_without_rev.revision = None\n        try:\n            remote_refs = self.get_recipe_revisions_references(ref_without_rev)\n        except NotFoundException:\n            raise RecipeNotFoundException(ref)\n        for r in remote_refs:\n            if r == ref:\n                return r\n        raise RecipeNotFoundException(ref)\n\n    def get_package_revision_reference(self, pref):\n        # FIXME: implement this endpoint in the remotes?\n        assert pref.revision, \"get_package_revision_reference has to be called with a complete reference\"\n        pref_without_rev = copy.copy(pref)\n        pref_without_rev.revision = None\n        try:\n            remote_prefs = self.get_package_revisions_references(pref_without_rev)\n        except NotFoundException:\n            raise PackageNotFoundException(pref)\n        for p in remote_prefs:\n            if p == pref:\n                return p\n        raise PackageNotFoundException(pref)\n\n    def get_recipe_revisions_references(self, ref):\n        assert ref.revision is None\n        url = self.router.recipe_revisions(ref)\n        tmp = self._get_json(url)[\"revisions\"]\n        remote_refs = []\n        for item in tmp:\n            _tmp = copy.copy(ref)\n            _tmp.revision = item.get(\"revision\")\n            _tmp.timestamp = from_iso8601_to_timestamp(item.get(\"time\"))\n            remote_refs.append(_tmp)\n        return remote_refs\n\n    def get_latest_recipe_reference(self, ref):\n        url = self.router.recipe_latest(ref)\n        data = self._get_json(url)\n        remote_ref = copy.copy(ref)\n        remote_ref.revision = data.get(\"revision\")\n        remote_ref.timestamp = from_iso8601_to_timestamp(data.get(\"time\"))\n        return remote_ref\n\n    def get_package_revisions_references(self, pref):\n        assert pref.revision is None\n        url = self.router.package_revisions(pref)\n        tmp = self._get_json(url)[\"revisions\"]\n        remote_prefs = [PkgReference(pref.ref, pref.package_id, item.get(\"revision\"),\n                        from_iso8601_to_timestamp(item.get(\"time\"))) for item in tmp]\n        return remote_prefs\n\n    def get_latest_package_reference(self, pref: PkgReference, headers):\n        url = self.router.package_latest(pref)\n        data = self._get_json(url, headers=headers)\n        remote_pref = copy.copy(pref)\n        remote_pref.revision = data.get(\"revision\")\n        remote_pref.timestamp = from_iso8601_to_timestamp(data.get(\"time\"))\n        return remote_pref\n"
  },
  {
    "path": "conan/internal/rest/rest_routes.py",
    "content": "class RestRoutes:\n    ping = \"ping\"\n    common_search = \"conans/search\"\n    common_authenticate = \"users/authenticate\"\n    common_check_credentials = \"users/check_credentials\"\n\n    def __init__(self):\n        self.base = 'conans'\n\n    @property\n    def recipe(self):\n        return self.base + '/{name}/{version}/{username}/{channel}'\n\n    @property\n    def recipe_latest(self):\n        return '%s/latest' % self.recipe\n\n    @property\n    def recipe_revision(self):\n        return '%s/revisions/{revision}' % self.recipe\n\n    @property\n    def recipe_revision_files(self):\n        return '%s/files' % self.recipe_revision\n\n    @property\n    def recipe_revisions(self):\n        return '%s/revisions' % self.recipe\n\n    @property\n    def recipe_revision_file(self):\n        return '%s/files/{path}' % self.recipe_revision\n\n    @property\n    def packages_revision(self):\n        return '%s/packages' % self.recipe_revision\n\n    @property\n    def package_recipe_revision(self):\n        \"\"\"Route for a package specifying the recipe revision but not the package revision\"\"\"\n        return '%s/{package_id}' % self.packages_revision\n\n    @property\n    def package_revisions(self):\n        return '%s/revisions' % self.package_recipe_revision\n\n    @property\n    def package_revision(self):\n        return '%s/{p_revision}' % self.package_revisions\n\n    @property\n    def package_revision_files(self):\n        return '%s/files' % self.package_revision\n\n    @property\n    def package_revision_latest(self):\n        return '%s/latest' % self.package_recipe_revision\n\n    @property\n    def package_revision_file(self):\n        return '%s/files/{path}' % self.package_revision\n\n    @property\n    def common_search_packages(self):\n        return \"%s/search\" % self.recipe\n\n    @property\n    def common_search_packages_revision(self):\n        return \"%s/search\" % self.recipe_revision\n"
  },
  {
    "path": "conan/internal/runner/__init__.py",
    "content": "class RunnerException(Exception):\n    def __init__(self, *args, **kwargs):\n        self.command = kwargs.pop(\"command\", None)\n        self.stdout_log = kwargs.pop(\"stdout_log\", None)\n        self.stderr_log = kwargs.pop(\"stderr_log\", None)\n        super(RunnerException, self).__init__(*args, **kwargs)"
  },
  {
    "path": "conan/internal/runner/docker.py",
    "content": "from argparse import Namespace\nimport os\nimport sys\nimport json\nimport platform\nimport shutil\nfrom typing import Optional, NamedTuple, Dict, List\nimport yaml\nfrom conan.api.conan_api import ConanAPI\nfrom conan.api.model import ListPattern\nfrom conan.api.output import Color, ConanOutput\nfrom conan.cli import make_abs_path\nfrom conan.internal.runner import RunnerException\nfrom conan.errors import ConanException\nfrom pathlib import Path\nfrom conan.internal.model.profile import Profile\nfrom conan.internal.model.version import Version\nfrom conan.internal.runner.output import RunnerOutput\nfrom conan.internal.conan_app import ConanApp\n\n\nclass _ContainerConfig(NamedTuple):\n    class Build(NamedTuple):\n        dockerfile: Optional[str] = None\n        build_context: Optional[str] = None\n        build_args: Optional[Dict[str, str]] = None\n        cache_from: Optional[List[str]] = None\n        platform: Optional[str] = None\n\n    class Run(NamedTuple):\n        name: Optional[str] = None\n        environment: Optional[Dict[str, str]] = None\n        user: Optional[str] = None\n        privileged: Optional[bool] = None\n        cap_add: Optional[List[str]] = None\n        security_opt: Optional[List[str]] = None\n        volumes: Optional[Dict[str, str]] = None\n        network: Optional[str] = None\n\n    image: Optional[str] = None\n    build: Build = Build()\n    run: Run = Run()\n\n    @staticmethod\n    def load(file_path: Optional[str]) -> '_ContainerConfig':\n        # Container config\n        # https://containers.dev/implementors/json_reference/\n        if not file_path:\n            return _ContainerConfig()\n\n        def _instans_or_error(value, obj):\n            if value and (not isinstance(value, obj)):\n                raise ConanException(f\"docker runner configfile syntax error: {value} must be a {obj.__name__}\")\n            return value\n        with open(file_path, 'r') as f:\n            runnerfile = yaml.safe_load(f)\n        return _ContainerConfig(\n            image=_instans_or_error(runnerfile.get('image'), str),\n            build=_ContainerConfig.Build(\n                dockerfile=_instans_or_error(runnerfile.get('build', {}).get('dockerfile'), str),\n                build_context=_instans_or_error(runnerfile.get('build', {}).get('build_context'), str),\n                build_args=_instans_or_error(runnerfile.get('build', {}).get('build_args'), dict),\n                cache_from=_instans_or_error(runnerfile.get('build', {}).get('cacheFrom'), list),\n                platform=_instans_or_error(runnerfile.get('build', {}).get('platform'), str),\n            ),\n            run=_ContainerConfig.Run(\n                name=_instans_or_error(runnerfile.get('run', {}).get('name'), str),\n                environment=_instans_or_error(runnerfile.get('run', {}).get('containerEnv'), dict),\n                user=_instans_or_error(runnerfile.get('run', {}).get('containerUser'), str),\n                privileged=_instans_or_error(runnerfile.get('run', {}).get('privileged'), bool),\n                cap_add=_instans_or_error(runnerfile.get('run', {}).get('capAdd'), list),\n                security_opt=_instans_or_error(runnerfile.get('run', {}).get('securityOpt'), list),\n                volumes=_instans_or_error(runnerfile.get('run', {}).get('mounts'), dict),\n                network=_instans_or_error(runnerfile.get('run', {}).get('network'), str),\n            )\n        )\n\n\nclass DockerRunner:\n    def __init__(self, conan_api: ConanAPI, command: str, host_profile: Profile, build_profile: Profile, args: Namespace, raw_args: list[str]):\n        self.logger = ConanOutput()\n        self.docker_client = self._initialize_docker_client()\n        self.docker_api = self.docker_client.api\n        self.conan_api = conan_api\n        self.build_profile = build_profile\n        self.abs_host_path = self._get_abs_host_path(args.path)\n        self.args = args\n        if args.format:\n            raise ConanException(\"format argument is forbidden if running in a docker runner\")\n\n        self.configfile = _ContainerConfig.load(host_profile.runner.get('configfile'))\n        self.dockerfile = host_profile.runner.get('dockerfile') or self.configfile.build.dockerfile\n        self.docker_build_context = host_profile.runner.get('build_context') or self.configfile.build.build_context\n        self.platform = host_profile.runner.get('platform') or self.configfile.build.platform\n        self.image = host_profile.runner.get('image') or self.configfile.image\n        if not (self.dockerfile or self.image):\n            raise ConanException(\"'dockerfile' or docker image name is needed\")\n        self.image = self.image or 'conan-runner-default'\n        self.name = self.configfile.run.name or host_profile.runner.get(\"name\", \"conan-runner-docker\")\n        self.remove = str(host_profile.runner.get('remove', 'false')).lower() == 'true'\n        self.cache = str(host_profile.runner.get('cache', 'clean'))\n        if self.cache not in ['clean', 'copy', 'shared']:\n            raise ConanException(f'Invalid cache value: \"{self.cache}\". Valid values are: clean, copy, shared')\n        self.container = None\n        self.raw_args = raw_args\n        self.command = command\n        self.runner_logger = RunnerOutput(self.name)\n\n    def run(self) -> None:\n        \"\"\"\n        Run conan inside a Docker container\n        \"\"\"\n        self._build_image()\n        self._start_container()\n        try:\n            self._init_container()\n            self._run_command(self.command)\n            self._update_local_cache()\n        except RunnerException as e:\n            raise ConanException(f'\"{e.command}\" inside docker fail')\n        finally:\n            if self.container:\n                error = sys.exc_info()[0] is not None  # Check if error has been raised\n                log = self.logger.error if error else self.logger.status\n                log('Stopping container')\n                self.container.stop()\n                if self.remove:\n                    log('Removing container')\n                    self.container.remove()\n\n    def _initialize_docker_client(self):\n        import docker\n        import docker.api.build\n\n        docker_base_urls = [\n            None,  # Default docker configuration\n            os.environ.get('DOCKER_HOST'),  # From DOCKER_HOST environment variable\n            'unix:///var/run/docker.sock',  # Default Linux socket\n            f'unix://{os.path.expanduser(\"~\")}/.rd/docker.sock'  # Rancher Linux socket\n        ]\n\n        for base_url in docker_base_urls:\n            try:\n                self.logger.verbose(f'Trying to connect to Docker: \"{base_url or \"default\"}\"')\n                client = docker.DockerClient(base_url=base_url, version='auto')\n                self.logger.verbose(f'Connected to Docker: \"{base_url or \"default\"}\"')\n                docker.api.build.process_dockerfile = lambda dockerfile, path: ('Dockerfile', dockerfile)\n                return client\n            except Exception:\n                continue\n        raise ConanException(\"Docker Client failed to initialize.\"\n                             \"\\n - Check if docker is installed and running\"\n                             \"\\n - Run 'pip install conan[runners]'\")\n\n    def _get_abs_host_path(self, path: str) -> Path:\n        abs_path = make_abs_path(path)\n        if abs_path is None:\n            raise ConanException(\"Could not determine the absolute path.\")\n        return Path(abs_path)\n\n    def _build_image(self) -> None:\n        if not self.dockerfile:\n            return\n        self.logger.status(f'Building the Docker image: {self.image}')\n        dockerfile_file_path = self.dockerfile\n        if os.path.isdir(self.dockerfile):\n            dockerfile_file_path = os.path.join(self.dockerfile, 'Dockerfile')\n        with open(dockerfile_file_path) as f:\n            build_path = self.docker_build_context or os.path.dirname(dockerfile_file_path)\n            self.logger.highlight(f\"Dockerfile path: '{dockerfile_file_path}'\")\n            self.logger.highlight(f\"Docker build context: '{build_path}'\\n\")\n            docker_build_logs = self.docker_api.build(\n                path=build_path,\n                dockerfile=f.read(),\n                tag=self.image,\n                platform=self.platform,\n                buildargs=self.configfile.build.build_args,\n                cache_from=self.configfile.build.cache_from,\n            )\n        for chunk in docker_build_logs:\n            for line in chunk.decode(\"utf-8\").split('\\r\\n'):\n                if line:\n                    stream = json.loads(line).get('stream')\n                    if stream:\n                        self.logger.status(stream.strip())\n\n    def _start_container(self) -> None:\n        volumes, environment = self._create_runner_environment()\n        try:\n            if self.docker_client.containers.list(all=True, filters={'name': self.name}):\n                self.logger.status('Starting the docker container', fg=Color.BRIGHT_MAGENTA)\n                self.container = self.docker_client.containers.get(self.name)\n                self.container.start()\n            else:\n                if self.configfile.run.environment:\n                    environment.update(self.configfile.run.environment)\n                if self.configfile.run.volumes:\n                    volumes.update(self.configfile.run.volumes)\n                self.logger.status('Creating the docker container', fg=Color.BRIGHT_MAGENTA)\n                self.container = self.docker_client.containers.run(\n                    self.image,\n                    \"/bin/bash -c 'while true; do sleep 30; done;'\",\n                    name=self.name,\n                    volumes=volumes,\n                    environment=environment,\n                    user=self.configfile.run.user,\n                    privileged=self.configfile.run.privileged,\n                    cap_add=self.configfile.run.cap_add,\n                    security_opt=self.configfile.run.security_opt,\n                    detach=True,\n                    auto_remove=False,\n                    network=self.configfile.run.network)\n            self.logger.status(f'Container {self.name} running', fg=Color.BRIGHT_MAGENTA)\n        except Exception as e:\n            raise ConanException(f'Imposible to run the container \"{self.name}\" with image \"{self.image}\"'\n                                 f'\\n\\n{str(e)}')\n\n    def _run_command(self, command: str, workdir: Optional[str] = None, verbose: bool = True) -> tuple[str, str]:\n        workdir = workdir or self.abs_docker_path\n        log = self.runner_logger.status if verbose else self.runner_logger.verbose\n        log(f'$ {command}', fg=Color.BLUE)\n        exec_instance = self.docker_api.exec_create(self.container.id, f\"/bin/bash -c '{command}'\", workdir=workdir, tty=True)\n        exec_output = self.docker_api.exec_start(exec_instance['Id'], tty=True, stream=True, demux=True,)\n        stderr_log, stdout_log = '', ''\n        try:\n            for (stdout_out, stderr_out) in exec_output:\n                if stdout_out is not None:\n                    decoded = stdout_out.decode('utf-8', errors='ignore').strip()\n                    stdout_log += decoded\n                    log(decoded)\n                if stderr_out is not None:\n                    decoded = stderr_out.decode('utf-8', errors='ignore').strip()\n                    stderr_log += decoded\n                    log(decoded)\n        except Exception as e:\n            if platform.system() == 'Windows':\n                import pywintypes\n                if isinstance(e, pywintypes.error):\n                    pass\n            else:\n                raise e\n        exit_metadata = self.docker_api.exec_inspect(exec_instance['Id'])\n        if exit_metadata['Running'] or exit_metadata['ExitCode'] > 0:\n            raise RunnerException(command=command, stdout_log=stdout_log, stderr_log=stderr_log)\n        return stdout_log, stderr_log\n\n    def _get_volumes_and_docker_path(self) -> tuple[dict, str]:\n        app = ConanApp(self.conan_api)\n        remotes = self.conan_api.remotes.list(self.args.remote) if not self.args.no_remote else []\n        conanfile = app.loader.load_consumer(self.abs_host_path / \"conanfile.py\", remotes=remotes)\n        abs_docker_base_path = Path('/') / self.docker_user_name / 'conanrunner'\n        # Check if recipe has defined a root folder\n        # In this case, mount the root folder as the base path and update the abs_docker_path to the\n        # new relative path\n        if hasattr(conanfile, \"layout\"):\n            try:\n                conanfile.layout()\n                if conanfile.folders.root:\n                    abs_path = self._get_abs_host_path(conanfile.folders.root)\n                    if self.abs_host_path.is_relative_to(abs_path):\n                        abs_docker_base_path /= abs_path.name\n                        volumes = {abs_path: {'bind': abs_docker_base_path.as_posix(), 'mode': 'rw'}}\n                        abs_docker_path = abs_docker_base_path / self.abs_host_path.relative_to(abs_path)\n                        return volumes, abs_docker_path.as_posix()\n            except:\n                pass\n        abs_docker_path = (abs_docker_base_path / self.abs_host_path.name).as_posix()\n        volumes = {self.abs_host_path: {'bind': abs_docker_path, 'mode': 'rw'}}\n        return volumes, abs_docker_path\n\n    def _create_runner_environment(self) -> tuple[dict, dict]:\n        # Runner configuration\n        self.abs_runner_home_path = self.abs_host_path / '.conanrunner'\n        self.docker_user_name = self.configfile.run.user or 'root'\n        volumes, self.abs_docker_path = self._get_volumes_and_docker_path()\n        shutil.rmtree(self.abs_runner_home_path, ignore_errors=True)\n        environment = {'CONAN_RUNNER_ENVIRONMENT': '1'}\n\n        # Update conan command and some paths to run inside the container\n        self.raw_args[self.raw_args.index(self.args.path)] = self.abs_docker_path\n        self.command = ' '.join([f'conan {self.command}'] + [f'\"{raw_arg}\"' if ' ' in raw_arg else raw_arg for raw_arg in self.raw_args] + ['-f json > create.json'])\n\n        if self.cache == 'shared':\n            volumes[self.conan_api.home_folder] = {'bind': f'/{self.docker_user_name}/.conan2', 'mode': 'rw'}\n\n        if self.cache in ['clean', 'copy']:\n            # Copy all conan profiles and config files to docker workspace\n            for profile in set(self.args.profile_host + (self.args.profile_build or [])):\n                profile_path = self.conan_api.profiles.get_path(profile)\n                dest_filename = self.abs_runner_home_path / 'profiles' / Path(profile)\n                if not dest_filename.exists():\n                    dest_filename.parent.mkdir(parents=True, exist_ok=True)\n                self.logger.verbose(f\"Copying profile '{profile}': {profile_path} -> {dest_filename}\")\n                shutil.copy(profile_path, dest_filename)\n            if not self.args.profile_build:\n                dest_filename = self.abs_runner_home_path / 'profiles' / \"default\"\n                default_build_profile = self.conan_api.profiles.get_default_build()\n                self.logger.verbose(f\"Copying default profile: {default_build_profile} -> {dest_filename}\")\n                shutil.copy(default_build_profile, dest_filename.as_posix())\n\n            for file_name in ['global.conf', 'settings.yml', 'remotes.json']:\n                src_file = Path(self.conan_api.home_folder) / file_name\n                if src_file.exists():\n                    self.logger.verbose(f\"Copying {src_file} -> {self.abs_runner_home_path / file_name}\")\n                    shutil.copy(src_file, self.abs_runner_home_path / file_name)\n\n            if self.cache == 'copy':\n                tgz_path = self.abs_runner_home_path / 'local_cache_save.tgz'\n                self.logger.status(f'Save host cache in: {tgz_path}')\n                self.conan_api.cache.save(self.conan_api.list.select(ListPattern(\"*:*\")), tgz_path)\n        return volumes, environment\n\n    def _init_container(self) -> None:\n        min_conan_version = '2.1'\n        stdout, _ = self._run_command('conan --version', verbose=True)\n        docker_conan_version = str(stdout.split('Conan version ')[1].replace('\\n', '').replace('\\r', '')) # Remove all characters and color\n        if Version(docker_conan_version) <= Version(min_conan_version):\n            raise ConanException(f'conan version inside the container must be greater than {min_conan_version}')\n        if self.cache != 'shared':\n            self._run_command('mkdir -p ${HOME}/.conan2/profiles', verbose=False)\n            self._run_command('cp -r \"'+self.abs_docker_path+'/.conanrunner/profiles/.\" ${HOME}/.conan2/profiles/.', verbose=False)\n\n            for file_name in ['global.conf', 'settings.yml', 'remotes.json']:\n                if (self.abs_runner_home_path / file_name).exists():\n                    self._run_command('cp \"'+self.abs_docker_path+'/.conanrunner/'+file_name+'\" ${HOME}/.conan2/'+file_name, verbose=False)\n            if self.cache in ['copy']:\n                self._run_command('conan cache restore \"'+self.abs_docker_path+'/.conanrunner/local_cache_save.tgz\"')\n\n    def _update_local_cache(self) -> None:\n        if self.cache != 'shared':\n            self._run_command('conan list --graph=create.json --graph-binaries=build --format=json > pkglist.json', verbose=False)\n            self._run_command('conan cache save --list=pkglist.json --file \"'+self.abs_docker_path+'\"/.conanrunner/docker_cache_save.tgz')\n            tgz_path = self.abs_runner_home_path / 'docker_cache_save.tgz'\n            self.logger.status(f'Restore host cache from: {tgz_path}')\n            self.conan_api.cache.restore(tgz_path)\n"
  },
  {
    "path": "conan/internal/runner/output.py",
    "content": "from conan.api.output import Color, ConanOutput\n\n\nclass RunnerOutput(ConanOutput):\n    def __init__(self, runner_info: str):\n        super().__init__()\n        self.set_warnings_as_errors(True) # Make log errors blocker\n        self._prefix = f\"{runner_info} | \"\n\n    def _write_message(self, msg, fg=None, bg=None, newline=True):\n        for line in msg.splitlines():\n            super()._write_message(self._prefix, Color.BLACK, Color.BRIGHT_YELLOW, newline=False)\n            super()._write_message(line, fg, bg, newline)\n"
  },
  {
    "path": "conan/internal/runner/ssh.py",
    "content": "from pathlib import Path\nimport pathlib\nimport tempfile\n\nfrom conan.api.output import Color, ConanOutput\nfrom conan.errors import ConanException\n\nimport os\nfrom io import BytesIO\nimport sys\n\ndef ssh_info(msg, error=False):\n    fg=Color.BRIGHT_MAGENTA\n    if error:\n        fg=Color.BRIGHT_RED\n    ConanOutput().status('\\n┌'+'─'*(2+len(msg))+'┐', fg=fg)\n    ConanOutput().status(f'| {msg} |', fg=fg)\n    ConanOutput().status('└'+'─'*(2+len(msg))+'┘\\n', fg=fg)\n\nclass SSHRunner:\n\n    def __init__(self, conan_api, command, host_profile, build_profile, args, raw_args):\n        try:\n            from paramiko.config import SSHConfig\n            from paramiko.client import SSHClient\n        except ImportError:\n            raise ConanException(\n                \"Paramiko is required for SSH runner. If conan is installed in a virtual environment, try to install \"\n                \"the 'paramiko' package, or consider installing conan package with extra requires 'conan[runners]'\"\n            )\n        self.conan_api = conan_api\n        self.command = command\n        self.host_profile = host_profile\n        self.build_profile = build_profile\n        self.remote_host_profile = None\n        self.remote_build_profile = None\n        self.remote_python_command = None\n        self.remote_create_dir = None\n        self.remote_is_windows = None\n        self.args = args\n        self.raw_args = raw_args\n        self.ssh_config = None\n        self.remote_workspace = None\n        self.remote_conan = None\n        self.remote_conan_home = None\n        if host_profile.runner.get('use_ssh_config', False):\n            ssh_config_file = Path.home() / \".ssh\" / \"config\"\n            ssh_config = SSHConfig.from_file(open(ssh_config_file))\n\n        hostname = host_profile.runner.get(\"host\") # TODO: this one is required\n        if ssh_config and ssh_config.lookup(hostname):\n            hostname = ssh_config.lookup(hostname)['hostname']\n\n        self.client = SSHClient()\n        self.client.load_system_host_keys()\n        self.client.connect(hostname)\n\n\n    def run(self, use_cache=True):\n        ssh_info('Got to SSHRunner.run(), doing nothing')\n\n        self.ensure_runner_environment()\n        self.copy_working_conanfile_path()\n\n        raw_args = self.raw_args\n        raw_args[raw_args.index(self.args.path)] = self.remote_create_dir\n        raw_args = \" \".join(raw_args)\n\n        _Path = pathlib.PureWindowsPath if self.remote_is_windows else pathlib.PurePath\n        remote_json_output = _Path(self.remote_create_dir).joinpath(\"conan_create.json\").as_posix()\n        command = f\"{self.remote_conan} create {raw_args} --format json > {remote_json_output}\"\n\n        ssh_info(f\"Remote command: {command}\")\n\n        stdout, _ = self._run_command(command)\n        first_line = True\n        while not stdout.channel.exit_status_ready():\n            line = stdout.channel.recv(1024)\n            if first_line and self.remote_is_windows:\n                # Avoid clearing and moving the cursor when the remote server is Windows\n                # https://github.com/PowerShell/Win32-OpenSSH/issues/1738#issuecomment-789434169\n                line = line.replace(b\"\\x1b[2J\\x1b[m\\x1b[H\",b\"\")\n            sys.stdout.buffer.write(line)\n            sys.stdout.buffer.flush()\n            first_line = False\n\n        if stdout.channel.recv_exit_status() == 0:\n            self.update_local_cache(remote_json_output)\n\n        # self.client.close()\n    def ensure_runner_environment(self):\n        has_python3_command = False\n        python_is_python3 = False\n\n        _, _stdout, _stderr = self.client.exec_command(\"python3 --version\")\n        has_python3_command = _stdout.channel.recv_exit_status() == 0\n        if not has_python3_command:\n            _, _stdout, _stderr = self.client.exec_command(\"python --version\")\n            if _stdout.channel.recv_exit_status() == 0 and \"Python 3\" in _stdout.read().decode():\n                python_is_python3 = True\n\n        python_command = \"python\" if python_is_python3 else \"python3\"\n        self.remote_python_command = python_command\n\n        if not has_python3_command and not python_is_python3:\n            raise ConanException(\"Unable to locate working Python 3 executable in remote SSH environment\")\n\n        # Determine if remote host is Windows\n        _, _stdout, _ = self.client.exec_command(f'{python_command} -c \"import os; print(os.name)\"')\n        if _stdout.channel.recv_exit_status() != 0:\n            raise ConanException(\"Unable to determine remote OS type\")\n        is_windows = _stdout.read().decode().strip() == \"nt\"\n        self.remote_is_windows = is_windows\n\n        # Get remote user home folder\n        _, _stdout, _ = self.client.exec_command(f'{python_command} -c \"from pathlib import Path; print(Path.home())\"')\n        if _stdout.channel.recv_exit_status() != 0:\n            raise ConanException(\"Unable to determine remote home user folder\")\n        home_folder = _stdout.read().decode().strip()\n\n        # Expected remote paths\n        remote_folder = Path(home_folder) / \".conan2remote\"\n        remote_folder = remote_folder.as_posix().replace(\"\\\\\", \"/\")\n        self.remote_workspace = remote_folder\n        remote_conan_home = Path(home_folder) / \".conan2remote\" / \"conanhome\"\n        remote_conan_home = remote_conan_home.as_posix().replace(\"\\\\\", \"/\")\n        self.remote_conan_home = remote_conan_home\n        ssh_info(f\"Remote workfolder: {remote_folder}\")\n\n        # Ensure remote folders exist\n        for folder in [remote_folder, remote_conan_home]:\n            _, _stdout, _stderr = self.client.exec_command(f\"\"\"{python_command} -c \"import os; os.makedirs('{folder}', exist_ok=True)\"\"\")\n            if _stdout.channel.recv_exit_status() != 0:\n                ssh_info(f\"Error creating remote folder: {_stderr.read().decode()}\")\n                raise ConanException(f\"Unable to create remote workfolder at {folder}\")\n\n        conan_venv = remote_folder + \"/venv\"\n        if is_windows:\n            conan_cmd = remote_folder + \"/venv/Scripts/conan.exe\"\n        else:\n            conan_cmd = remote_folder + \"/venv/bin/conan\"\n\n        ssh_info(f\"Expected remote conan home: {remote_conan_home}\")\n        ssh_info(f\"Expected remote conan command: {conan_cmd}\")\n\n        # Check if remote Conan executable exists, otherwise invoke pip inside venv\n        sftp = self.client.open_sftp()\n        try:\n            sftp.stat(conan_cmd)\n            has_remote_conan = True\n        except FileNotFoundError:\n            has_remote_conan = False\n        finally:\n            sftp.close()\n\n        if not has_remote_conan:\n            _, _stdout, _stderr = self.client.exec_command(f\"{python_command} -m venv {conan_venv}\")\n            if _stdout.channel.recv_exit_status() != 0:\n                ssh_info(f\"Unable to create remote venv: {_stderr.read().decode().strip()}\")\n\n            if is_windows:\n                python_command = remote_folder + \"/venv\" + \"/Scripts\" + \"/python.exe\"\n            else:\n                python_command = remote_folder + \"/venv\" + \"/bin\" + \"/python\"\n\n            _, _stdout, _stderr = self.client.exec_command(f\"{python_command} -m pip install git+https://github.com/conan-io/conan@feature/docker_wrapper\")\n            if _stdout.channel.recv_exit_status() != 0:\n                # Note: this may fail on windows\n                ssh_info(f\"Unable to install conan in venv: {_stderr.read().decode().strip()}\")\n\n        remote_env = {\n            'CONAN_HOME': remote_conan_home,\n            'CONAN_RUNNER_ENVIRONMENT': \"1\"\n        }\n        if is_windows:\n            # Wrapper script with environment variables preset\n            env_lines = \"\\n\".join([f\"set {k}={v}\" for k,v in remote_env.items()])\n            conan_bat_contents = f\"\"\"@echo off\\n{env_lines}\\n{conan_cmd} %*\\n\"\"\"\n            conan_bat = remote_folder + \"/conan.bat\"\n            try:\n                sftp = self.client.open_sftp()\n                sftp.putfo(BytesIO(conan_bat_contents.encode()), conan_bat)\n            except:\n                raise ConanException(\"unable to set up Conan remote script\")\n            finally:\n                sftp.close()\n\n            self.remote_conan = conan_bat\n        _, _stdout, _stderr = self.client.exec_command(f\"{self.remote_conan} config home\")\n        ssh_info(f\"Remote conan config home returned: {_stdout.read().decode().strip()}\")\n        _, _stdout, _stderr = self.client.exec_command(f\"{self.remote_conan} profile detect --force\")\n        self._copy_profiles()\n\n\n    def _copy_profiles(self):\n        sftp = self.client.open_sftp()\n\n        # TODO: very questionable choices here\n        try:\n            profiles = {\n                self.args.profile_host[0]: self.host_profile.dumps(),\n                self.args.profile_build[0]: self.build_profile.dumps()\n            }\n\n            for name, contents in profiles.items():\n                dest_filename = self.remote_conan_home + f\"/profiles/{name}\"\n                sftp.putfo(BytesIO(contents.encode()), dest_filename)\n        except:\n            raise ConanException(\"Unable to copy profiles to remote\")\n        finally:\n            sftp.close()\n\n    def copy_working_conanfile_path(self):\n        resolved_path = Path(self.args.path).resolve()\n        if resolved_path.is_file():\n            resolved_path = resolved_path.parent\n\n        if not resolved_path.is_dir():\n            return ConanException(\"Error determining conanfile directory\")\n\n        # Create temporary destination directory\n        temp_dir_create_cmd = f\"\"\"{self.remote_python_command} -c \"import tempfile; print(tempfile.mkdtemp(dir='{self.remote_workspace}'))\"\"\"\n        _, _stdout, _ = self.client.exec_command(temp_dir_create_cmd)\n        if _stdout.channel.recv_exit_status() != 0:\n            raise ConanException(\"Unable to create remote temporary directory\")\n        self.remote_create_dir = _stdout.read().decode().strip().replace(\"\\\\\", '/')\n\n        # Copy current folder to destination using sftp\n        _Path = pathlib.PureWindowsPath if self.remote_is_windows else pathlib.PurePath\n        sftp = self.client.open_sftp()\n        for root, dirs, files in os.walk(resolved_path.as_posix()):\n            relative_root = Path(root).relative_to(resolved_path)\n            for dir in dirs:\n                    dst = _Path(self.remote_create_dir).joinpath(relative_root).joinpath(dir).as_posix()\n                    sftp.mkdir(dst)\n            for file in files:\n                orig = os.path.join(root, file)\n                dst = _Path(self.remote_create_dir).joinpath(relative_root).joinpath(file).as_posix()\n                sftp.put(orig, dst)\n        sftp.close()\n\n    def _run_command(self, command):\n        ''' Run a command in an SSH session.\n            When requesting a pseudo-terminal from the server,\n            ensure we pass width and height that matches the current\n            terminal\n        '''\n        channel = self.client.get_transport().open_session()\n        if sys.stdout.isatty():\n            width, height = os.get_terminal_size()\n            channel.get_pty(width=width, height=height)\n\n        channel.exec_command(command)\n\n        stdout = channel.makefile(\"r\")\n        stderr = channel.makefile(\"r\")\n        return stdout, stderr\n\n    def update_local_cache(self, json_result):\n        # ('conan list --graph=create.json --graph-binaries=build --format=json > pkglist.json'\n        _Path = pathlib.PureWindowsPath if self.remote_is_windows else pathlib.PurePath\n        pkg_list_json = _Path(self.remote_create_dir).joinpath(\"pkg_list.json\").as_posix()\n        pkg_list_command = f\"{self.remote_conan} list --graph={json_result} --graph-binaries=build --format=json > {pkg_list_json}\"\n        _, stdout, _ = self.client.exec_command(pkg_list_command)\n        if stdout.channel.recv_exit_status() != 0:\n            raise ConanException(\"Unable to generate remote package list\")\n\n        conan_cache_tgz = _Path(self.remote_create_dir).joinpath(\"cache.tgz\").as_posix()\n        cache_save_command = f\"{self.remote_conan} cache save --list {pkg_list_json} --file {conan_cache_tgz}\"\n        _, stdout, _ = self.client.exec_command(cache_save_command)\n        if stdout.channel.recv_exit_status() != 0:\n            raise ConanException(\"Unable to save remote conan cache state\")\n\n        sftp = self.client.open_sftp()\n        with tempfile.TemporaryDirectory() as tmp:\n            local_cache_tgz = os.path.join(tmp, 'cache.tgz')\n            sftp.get(conan_cache_tgz, local_cache_tgz)\n            package_list = self.conan_api.cache.restore(local_cache_tgz)\n"
  },
  {
    "path": "conan/internal/runner/wsl.py",
    "content": "from pathlib import PurePosixPath, PureWindowsPath, Path\nfrom conan.api.output import Color, ConanOutput\nfrom conan.internal.util.runners import conan_run\nfrom conan.internal.subsystems import subsystem_path\nfrom conan.tools.files import save\nfrom io import StringIO\nimport tempfile\nimport os\n\ndef wsl_info(msg, error=False):\n    fg=Color.BRIGHT_MAGENTA\n    if error:\n        fg=Color.BRIGHT_RED\n    ConanOutput().status('\\n┌'+'─'*(2+len(msg))+'┐', fg=fg)\n    ConanOutput().status(f'| {msg} |', fg=fg)\n    ConanOutput().status('└'+'─'*(2+len(msg))+'┘\\n', fg=fg)\n\n\nclass WSLRunner:\n    def __init__(self, conan_api, command, host_profile, build_profile, args, raw_args):\n        self.conan_api = conan_api\n        self.command = command\n        self.host_profile = host_profile\n        self.build_profile = build_profile\n        self.remote_host_profile = None\n        self.remote_build_profile = None\n        self.remote_python_command = None\n        self.remote_conan = None\n        self.remote_conan_home = None\n        self.args = args\n        self.raw_args = raw_args\n\n        # to pass to wsl.exe (optional, otherwise run with defaults)\n        distro = host_profile.runner.get(\"distribution\", None)\n        user = host_profile.runner.get(\"user\", None)\n\n        self.shared_cache = host_profile.runner.get(\"shared_cache\", False)\n        if self.shared_cache:\n            storage_path = Path(conan_api.config.home()) / 'p' # TODO: there's an API for this!!\n            self.remote_conan_cache = subsystem_path(\"wsl\", storage_path.as_posix())\n\n    def run(self):\n        self.ensure_runner_environment()\n\n        raw_args = self.raw_args\n        current_path = Path(self.args.path).resolve()\n        current_path_wsl = subsystem_path(\"wsl\", current_path.as_posix())\n\n        raw_args[raw_args.index(self.args.path)] = current_path_wsl\n        raw_args = \" \".join(raw_args)\n\n        with tempfile.TemporaryDirectory() as tmp_dir:\n            if not self.shared_cache:\n                create_json = PureWindowsPath(tmp_dir).joinpath(\"create.json\").as_posix()\n                raw_args += f\" --format=json > {create_json}\"\n            tmp_dir_wsl = subsystem_path(\"wsl\", tmp_dir)\n            command = f\"wsl.exe --cd {tmp_dir_wsl} -- CONAN_RUNNER_ENVIRONMENT=1 CONAN_HOME={self.remote_conan_home} {self.remote_conan} create {raw_args}\"\n            rc = conan_run(command)\n            if rc == 0 and not self.shared_cache:\n                create_json_wsl = subsystem_path(\"wsl\", create_json)\n                pkglist_json = PureWindowsPath(tmp_dir).joinpath(\"pkglist.json\").as_posix()\n                pkglist_json_wsl = subsystem_path(\"wsl\", pkglist_json)\n\n                saved_cache = PureWindowsPath(tmp_dir).joinpath(\"saved_cache.tgz\").as_posix()\n                saved_cache_wsl = subsystem_path(\"wsl\", saved_cache)\n                conan_run(f\"wsl.exe --cd {tmp_dir_wsl} -- CONAN_RUNNER_ENVIRONMENT=1 CONAN_HOME={self.remote_conan_home} {self.remote_conan} list --graph={create_json_wsl} --format=json > {pkglist_json}\")\n                conan_run(f\"wsl.exe --cd {tmp_dir_wsl} -- CONAN_RUNNER_ENVIRONMENT=1 CONAN_HOME={self.remote_conan_home} {self.remote_conan} cache save --list={pkglist_json_wsl} --file {saved_cache_wsl}\")\n                self.conan_api.cache.restore(saved_cache)\n            else:\n                pass\n        #print(command)\n\n    def ensure_runner_environment(self):\n        stdout = StringIO()\n        stderr = StringIO()\n\n        ret = conan_run('wsl.exe echo $HOME', stdout=stdout)\n        if ret == 0:\n            remote_home = PurePosixPath(stdout.getvalue().strip())\n            stdout = StringIO()\n\n        remote_conan = remote_home / \".conan2remote\" / \"venv\" / \"bin\" / \"conan\"\n        self.remote_conan = remote_conan.as_posix()\n\n        wsl_info(self.remote_conan)\n\n        conan_home = remote_home / \".conan2remote\" / \"conan_home\"\n        self.remote_conan_home = conan_home\n\n        has_conan = conan_run(f\"wsl.exe CONAN_HOME={conan_home.as_posix()} {remote_conan} --version\", stdout=stdout, stderr=stderr) == 0\n\n        if not has_conan:\n            wsl_info(\"Bootstrapping Conan in remote\")\n            conan_run(f\"wsl.exe mkdir -p {remote_home}/.conan2remote\")\n            venv = remote_home / \".conan2remote\"/ \"venv\"\n            python = venv / \"bin\" / \"python\"\n            self.remote_python_command = python\n            conan_run(f\"wsl.exe python3 -m venv {venv.as_posix()}\")\n            conan_run(f\"wsl.exe {python} -m pip install pip wheel --upgrade\")\n            conan_run(f\"wsl.exe {python} -m pip install git+https://github.com/conan-io/conan@feature/docker_wrapper\")\n            conan_run(f\"wsl.exe CONAN_HOME={conan_home.as_posix()} {remote_conan} --version\", stdout=stdout)\n\n        remote_conan_version = stdout.getvalue().strip()\n        wsl_info(f\"Remote conan version: {remote_conan_version}\")\n        stdout = StringIO()\n        stderr = StringIO()\n\n        # If this command succeeds, great - if not because it already exists, ignore\n        conan_run(f\"wsl.exe CONAN_HOME={conan_home.as_posix()} {remote_conan} profile detect\", stdout=stdout, stderr=stderr)\n\n\n        conf_content = f\"core.cache:storage_path={self.remote_conan_cache}\\n\"  if self.shared_cache else \"\"\n        with tempfile.TemporaryDirectory() as tmp:\n            global_conf = os.path.join(tmp, \"global.conf\")\n            save(None, path=global_conf, content=conf_content)\n            global_conf_wsl = subsystem_path(\"wsl\", global_conf)\n            remote_global_conf = self.remote_conan_home.joinpath(\"global.conf\")\n            conan_run(f\"wsl.exe cp {global_conf_wsl} {remote_global_conf}\")\n\n        self._copy_profiles()\n\n    def _copy_profiles(self):\n        # TODO: questionable choices, may fail\n\n        # Note: see the use of \\\\wsl$\\<DistroName>\\, we could place the files\n        #       directly. We would need to work out the exact distro name first\n        profiles = {\n            self.args.profile_host[0]: self.host_profile.dumps(),\n            self.args.profile_build[0]: self.build_profile.dumps()\n        }\n\n        with tempfile.TemporaryDirectory() as tmp:\n            # path = os.path.join(tmp, 'something')\n            for name, contents in profiles.items():\n                outfile = os.path.join(tmp, name)\n                save(None, path=outfile, content=contents)\n                outfile_wsl = subsystem_path(\"wsl\", outfile)\n                remote_profile = self.remote_conan_home.joinpath(\"profiles\").as_posix() + \"/\"\n\n                # This works but copies the file with executable attribute\n                conan_run(f\"wsl.exe cp {outfile_wsl} {remote_profile}\")\n\n\n"
  },
  {
    "path": "conan/internal/source.py",
    "content": "import os\n\nfrom conan.api.output import ConanOutput\nfrom conan.internal.methods import run_source_method\nfrom conan.tools.env import VirtualBuildEnv\nfrom conan.internal.errors import NotFoundException\nfrom conan.errors import ConanException\nfrom conan.internal.util.files import is_dirty, mkdir, rmdir, set_dirty_context_manager, merge_directories, clean_dirty\n\n\ndef _try_get_sources(ref, remote_manager, recipe_layout, remote):\n    try:\n        remote_manager.get_recipe_sources(ref, recipe_layout, remote)\n    except NotFoundException:\n        return\n    except Exception as e:\n        msg = (\"The '%s' package has 'exports_sources' but sources not found in local cache.\\n\"\n               \"Probably it was installed from a remote that is no longer available.\\n\"\n               % str(ref))\n        raise ConanException(\"\\n\".join([str(e), msg]))\n    return remote\n\n\ndef retrieve_exports_sources(remote_manager, recipe_layout, conanfile, ref, remotes):\n    \"\"\" the \"exports_sources\" sources are not retrieved unless necessary to build. In some\n    occassions, conan needs to get them too, like if uploading to a server, to keep the recipes\n    complete\n    \"\"\"\n    if conanfile.exports_sources is None and not hasattr(conanfile, \"export_sources\"):\n        return None\n\n    export_sources_folder = recipe_layout.export_sources()\n    if os.path.exists(export_sources_folder):\n        return None\n\n    for r in remotes:\n        sources_remote = _try_get_sources(ref, remote_manager, recipe_layout, r)\n        if sources_remote:\n            break\n    else:\n        msg = (\"The '%s' package has 'exports_sources' but sources not found in local cache.\\n\"\n               \"Probably it was installed from a remote that is no longer available.\\n\"\n               % str(ref))\n        raise ConanException(msg)\n\n    ConanOutput(scope=str(ref)).info(\"Sources downloaded from '{}'\".format(sources_remote.name))\n\n\ndef config_source(export_source_folder, conanfile, hook_manager):\n    \"\"\" Implements the sources configuration when a package is going to be built in the\n    local cache:\n    - remove old sources if dirty\n    - do a copy of the exports_sources folders to the source folder in the cache\n    - run the source() recipe method\n    \"\"\"\n\n    if is_dirty(conanfile.folders.base_source):\n        conanfile.output.warning(\"Trying to remove corrupted source folder\")\n        conanfile.output.warning(\"This can take a while for big packages\")\n        rmdir(conanfile.folders.base_source)\n        clean_dirty(conanfile.folders.base_source)\n\n    if not os.path.exists(conanfile.folders.base_source):  # No source folder, need to get it\n        with set_dirty_context_manager(conanfile.folders.base_source):\n            mkdir(conanfile.source_folder)\n            mkdir(conanfile.recipe_metadata_folder)\n\n            # First of all get the exported scm sources (if auto) or clone (if fixed)\n            # Now move the export-sources to the right location\n            merge_directories(export_source_folder, conanfile.folders.base_source)\n            if getattr(conanfile, \"source_buildenv\", False):\n                with VirtualBuildEnv(conanfile, auto_generate=True).vars().apply():\n                    run_source_method(conanfile, hook_manager)\n            else:\n                run_source_method(conanfile, hook_manager)\n"
  },
  {
    "path": "conan/internal/subsystems.py",
    "content": "\"\"\"\nPotential scenarios:\n\n- Running from a Windows native \"cmd\"\n  - Targeting Windows native (os.subsystem = None)\n    - No need of bash (no conf at all)\n    - Need to build in bash (tools.microsoft.bash:subsystem=xxx,\n                             tools.microsoft.bash:path=<path>,\n                             conanfile.win_bash)\n    - Need to run (tests) in bash (tools.microsoft.bash:subsystem=xxx,\n                                   tools.microsoft.bash:path=<path>,\n                                   conanfile.win_bash_run)\n  - Targeting Subsystem (os.subsystem = msys2/cygwin)\n    - Always builds and runs in bash (tools.microsoft.bash:path)\n\n- Running from a subsytem terminal (tools.microsoft.bash:subsystem=xxx,\n                                    tools.microsoft.bash:path=None) NO ERROR mode for not specifying it? =CURRENT?\n  - Targeting Windows native (os.subsystem = None)\n  - Targeting Subsystem (os.subsystem = msys2/cygwin)\n\n\"\"\"\nimport os\nimport platform\nimport re\n\nfrom conan.tools.build import cmd_args_to_string\nfrom conan.errors import ConanException\n\nWINDOWS = \"windows\"\nMSYS2 = 'msys2'\nMSYS = 'msys'\nCYGWIN = 'cygwin'\nWSL = 'wsl'  # Windows Subsystem for Linux\n\n\ndef command_env_wrapper(conanfile, command, envfiles, envfiles_folder, scope=\"build\"):\n    from conan.tools.env.environment import environment_wrap_command\n    if getattr(conanfile, \"conf\", None) is None:\n        # TODO: No conf, no profile defined!! This happens at ``export()`` time\n        #  Is it possible to run a self.run() in export() in bash?\n        #  Is it necessary? Shouldn't be\n        return command\n\n    active = conanfile.conf.get(\"tools.microsoft.bash:active\", check_type=bool)\n    subsystem = conanfile.conf.get(\"tools.microsoft.bash:subsystem\")\n    if platform.system() == \"Windows\" and (\n            (conanfile.win_bash and scope == \"build\") or\n            (conanfile.win_bash_run and scope == \"run\")):\n        if subsystem is None:\n            raise ConanException(\"win_bash/win_bash_run defined but no \"\n                                 \"tools.microsoft.bash:subsystem\")\n        if active:\n            wrapped_cmd = environment_wrap_command(conanfile, envfiles, envfiles_folder, command)\n        else:\n            wrapped_cmd = _windows_bash_wrapper(conanfile, command, envfiles, envfiles_folder)\n    else:\n        wrapped_cmd = environment_wrap_command(conanfile, envfiles, envfiles_folder, command)\n    return wrapped_cmd\n\n\ndef _windows_bash_wrapper(conanfile, command, env, envfiles_folder):\n    from conan.tools.env import Environment\n    from conan.tools.env.environment import environment_wrap_command\n    \"\"\" Will wrap a unix command inside a bash terminal It requires to have MSYS2, CYGWIN, or WSL\"\"\"\n\n    subsystem = conanfile.conf.get(\"tools.microsoft.bash:subsystem\")\n    if not platform.system() == \"Windows\":\n        raise ConanException(\"Command only for Windows operating system\")\n\n    shell_path = conanfile.conf.get(\"tools.microsoft.bash:path\")\n    if not shell_path:\n        raise ConanException(\"The config 'tools.microsoft.bash:path' is \"\n                             \"needed to run commands in a Windows subsystem\")\n    shell_path = shell_path.replace(\"\\\\\", \"/\")  # Should work in all terminals\n    env = env or []\n    if subsystem == MSYS2:\n        # Configure MSYS2 to inherith the PATH\n        msys2_mode_env = Environment()\n        _msystem = {\"x86\": \"MINGW32\"}.get(conanfile.settings.get_safe(\"arch\"), \"MINGW64\")\n        # https://www.msys2.org/wiki/Launchers/ dictates that the shell should be launched with\n        # - MSYSTEM defined\n        # - CHERE_INVOKING is necessary to keep the CWD and not change automatically to the user home\n        msys2_mode_env.define(\"MSYSTEM\", _msystem)\n        msys2_mode_env.define(\"MSYS2_PATH_TYPE\", \"inherit\")\n        msys2_mode_env.unset(\"ORIGINAL_PATH\")\n        # So --login do not change automatically to the user home\n        msys2_mode_env.define(\"CHERE_INVOKING\", \"1\")\n        path = os.path.join(conanfile.generators_folder, \"msys2_mode.bat\")\n        # Make sure we save pure .bat files, without sh stuff\n        wb, conanfile.win_bash = conanfile.win_bash, None\n        msys2_mode_env.vars(conanfile, \"build\").save_bat(path)\n        conanfile.win_bash = wb\n        env.append(path)\n\n    wrapped_shell = '\"%s\"' % shell_path if \" \" in shell_path else shell_path\n    wrapped_shell = environment_wrap_command(conanfile, env, envfiles_folder, wrapped_shell,\n                                             accepted_extensions=(\"bat\", \"ps1\"))\n\n    # Wrapping the inside_command enable to prioritize our environment, otherwise /usr/bin go\n    # first and there could be commands that we want to skip\n    wrapped_user_cmd = environment_wrap_command(conanfile, env, envfiles_folder, command,\n                                                accepted_extensions=(\"sh\", ))\n    wrapped_user_cmd = _escape_windows_cmd(wrapped_user_cmd)\n    # according to https://www.msys2.org/wiki/Launchers/, it is necessary to use --login shell\n    # running without it is discouraged\n    final_command = '{} --login -c {}'.format(wrapped_shell, wrapped_user_cmd)\n    return final_command\n\n\ndef _escape_windows_cmd(command):\n    \"\"\" To use in a regular windows cmd.exe\n        1. Adds escapes so the argument can be unpacked by CommandLineToArgvW()\n        2. Adds escapes for cmd.exe so the argument survives cmd.exe's substitutions.\n\n        Useful to escape commands to be executed in a windows bash (msys2, cygwin etc)\n    \"\"\"\n    quoted_arg = cmd_args_to_string([command])\n    return \"\".join([\"^%s\" % arg if arg in r'()%!^\"<>&|' else arg for arg in quoted_arg])\n\n\ndef deduce_subsystem(conanfile, scope):\n    \"\"\" used by:\n    - EnvVars: to decide if using :  ; as path separator, translate paths to subsystem\n               and decide to generate a .bat or .sh\n    - Autotools: to define the full abs path to the \"configure\" script\n    - GnuDeps: to map all the paths from dependencies\n    - Aggregation of envfiles: to map each aggregated path to the subsystem\n    - unix_path: util for recipes\n    \"\"\"\n    scope = \"build\" if scope is None else scope  # let's assume build context if scope=None\n    if scope.startswith(\"build\"):\n        the_os = conanfile.settings_build.get_safe(\"os\")\n        if the_os is None:\n            raise ConanException(\"The 'build' profile must have a 'os' declared\")\n    else:\n        the_os = conanfile.settings.get_safe(\"os\")\n\n    if not str(the_os).startswith(\"Windows\"):\n        return None\n\n    subsystem = conanfile.conf.get(\"tools.microsoft.bash:subsystem\")\n    if not subsystem:\n        if conanfile.win_bash:\n            raise ConanException(\"win_bash=True but tools.microsoft.bash:subsystem \"\n                                 \"configuration not defined\")\n        if conanfile.win_bash_run:\n            raise ConanException(\"win_bash_run=True but tools.microsoft.bash:subsystem \"\n                                 \"configuration not defined\")\n        return WINDOWS\n    active = conanfile.conf.get(\"tools.microsoft.bash:active\", check_type=bool)\n    if active:\n        return subsystem\n\n    if scope.startswith(\"build\"):  # \"run\" scope do not follow win_bash\n        if conanfile.win_bash:\n            return subsystem\n    elif scope.startswith(\"run\"):\n        if conanfile.win_bash_run:\n            return subsystem\n\n    return WINDOWS\n\n\ndef subsystem_path(subsystem, path):\n    \"\"\"\"Used to translate windows paths to MSYS unix paths like\n    c/users/path/to/file. Not working in a regular console or MinGW!\n    \"\"\"\n    if subsystem is None or subsystem == WINDOWS:\n        return path\n\n    if os.path.exists(path):\n        # if the path doesn't exist (and abs) we cannot guess the casing\n        path = get_cased_path(path)\n\n    if path.startswith('\\\\\\\\?\\\\'):\n        path = path[4:]\n    path = path.replace(\":/\", \":\\\\\")\n    append_prefix = re.match(r'[a-z]:\\\\', path, re.IGNORECASE)\n    pattern = re.compile(r'([a-z]):\\\\', re.IGNORECASE)\n    path = pattern.sub('/\\\\1/', path).replace('\\\\', '/')\n\n    if append_prefix:\n        if subsystem in (MSYS, MSYS2):\n            return path.lower()\n        elif subsystem == CYGWIN:\n            return '/cygdrive' + path.lower()\n        elif subsystem == WSL:\n            return '/mnt' + path[0:2].lower() + path[2:]\n    else:\n        return path if subsystem == WSL else path.lower()\n    return None\n\n\ndef get_cased_path(name):\n    if platform.system() != \"Windows\":\n        return name\n    if not os.path.isabs(name):\n        name = os.path.abspath(name)\n\n    result = []\n    current = name\n    while True:\n        parent, child = os.path.split(current)\n        if parent == current:\n            break\n\n        child_cased = child\n        if os.path.exists(parent):\n            children = os.listdir(parent)\n            for c in children:\n                if c.upper() == child.upper():\n                    child_cased = c\n                    break\n        result.append(child_cased)\n        current = parent\n    drive, _ = os.path.splitdrive(current)\n    result.append(drive)\n    return os.sep.join(reversed(result))\n"
  },
  {
    "path": "conan/internal/util/__init__.py",
    "content": "import math\nimport multiprocessing\nimport os\n\nfrom conan.internal.util.files import load\n\n\ndef cpu_count():\n    try:\n        try:\n            # This is necessary to deduce docker cpu_count\n            cfs_quota_us = cfs_period_us = 0\n            # cgroup2\n            if os.path.exists(\"/sys/fs/cgroup/cgroup.controllers\"):\n                cpu_max = load(\"/sys/fs/cgroup/cpu.max\").split()\n                if cpu_max and cpu_max[0] != \"max\":\n                    if len(cpu_max) == 1:\n                        cfs_quota_us, cfs_period_us = int(cpu_max[0]), 100_000\n                    else:\n                        cfs_quota_us, cfs_period_us = map(int, cpu_max)\n            else:  # cgroup1\n                cfs_quota_us = int(load(\"/sys/fs/cgroup/cpu/cpu.cfs_quota_us\"))\n                cfs_period_us = int(load(\"/sys/fs/cgroup/cpu/cpu.cfs_period_us\"))\n            if cfs_quota_us > 0 and cfs_period_us > 0:\n                return int(math.ceil(cfs_quota_us / cfs_period_us))\n        except (EnvironmentError, TypeError):\n            pass\n        return multiprocessing.cpu_count()\n    except NotImplementedError:\n        # print(\"multiprocessing.cpu_count() not implemented. Defaulting to 1 cpu\")\n        return 1  # Safe guess\n"
  },
  {
    "path": "conan/internal/util/config_parser.py",
    "content": "import re\n\nfrom conan.errors import ConanException\n\n\nclass TextINIParse:\n    \"\"\" util class to load a file with sections as [section1]\n    checking the values of those sections, and returns each section\n    as parser.section\n    Currently used in ConanInfo and ConanFileTextLoader\n    \"\"\"\n    def __init__(self, text, allowed_fields=None, strip_comments=False):\n        self._sections = {}\n        self._allowed_fields = allowed_fields or []\n        pattern = re.compile(r\"^\\[([a-z_]{2,50})]\")\n        current_lines = None\n        for line in text.splitlines():\n            line = line.strip()\n            if not line or line[0] == '#':\n                continue\n            if line[0] == '[':\n                m = pattern.match(line)\n                if not m:\n                    raise ConanException(\"ConfigParser: Bad syntax '%s'\" % line)\n                field = m.group(1)\n                if self._allowed_fields and field not in self._allowed_fields:\n                    raise ConanException(\"ConfigParser: Unrecognized field '%s'\" % field)\n                current_lines = []\n                # Duplicated section\n                if field in self._sections:\n                    raise ConanException(f\"ConfigParser: Duplicated section: [{field}]\")\n                self._sections[field] = current_lines\n            else:\n                if current_lines is None:\n                    raise ConanException(\"ConfigParser: Unexpected line '%s'\" % line)\n                if strip_comments:\n                    line = line.split(' #', 1)[0]\n                    line = line.split('    #', 1)[0]\n                    line = line.strip()\n                current_lines.append(line)\n\n    def line_items(self):\n        # Used atm by load_binary_info()\n        return self._sections.items()\n\n    def __getattr__(self, name):\n        if name in self._sections:\n            return \"\\n\".join(self._sections[name])\n        else:\n            if self._allowed_fields and name not in self._allowed_fields:\n                raise ConanException(\"ConfigParser: Unrecognized field '%s'\" % name)\n            return \"\"\n"
  },
  {
    "path": "conan/internal/util/dates.py",
    "content": "import calendar\nimport datetime\nimport time\n\nfrom dateutil import parser\n\n\ndef from_timestamp_to_iso8601(timestamp):\n    # Used exclusively by conan_server to return the date in iso format (same as artifactory)\n    return \"%s\" % datetime.datetime.fromtimestamp(timestamp, datetime.timezone.utc).isoformat()\n\n\ndef _from_iso8601_to_datetime(iso_str):\n    return parser.isoparse(iso_str)\n\n\ndef from_iso8601_to_timestamp(iso_str):\n    # used by RestClient v2 to transform from HTTP API (iso) to Conan internal timestamp\n    datetime_time = _from_iso8601_to_datetime(iso_str)\n    return datetime_time.timestamp()\n\n\ndef timestamp_now():\n    # seconds since epoch 0, easy to store, in UTC\n    # Used in Manifest timestamp, in packagesDB LRU and in timestamp of backup-sources json\n    return calendar.timegm(time.gmtime())\n\n\ndef revision_timestamp_now():\n    return time.time()\n\n\ndef timestamp_to_str(timestamp):\n    # used by ref.repr_humantime() to print human readable time\n    assert timestamp is not None\n    return datetime.datetime.fromtimestamp(int(timestamp), datetime.timezone.utc).strftime('%Y-%m-%d %H:%M:%S UTC')\n"
  },
  {
    "path": "conan/internal/util/files.py",
    "content": "import errno\nimport hashlib\nimport os\nimport platform\nimport shutil\nimport stat\nimport sys\nimport tarfile\nimport time\n\nfrom contextlib import contextmanager\n\nfrom conan.api.output import ConanOutput\nfrom conan.errors import ConanException\n\n_DIRTY_FOLDER = \".dirty\"\n\n\ndef set_dirty(folder):\n    dirty_file = os.path.normpath(folder) + _DIRTY_FOLDER\n    assert not os.path.exists(dirty_file), \"Folder '{}' is already dirty\".format(folder)\n    save(dirty_file, \"\")\n\n\ndef clean_dirty(folder):\n    dirty_file = os.path.normpath(folder) + _DIRTY_FOLDER\n    os.remove(dirty_file)\n\n\ndef is_dirty(folder):\n    dirty_file = os.path.normpath(folder) + _DIRTY_FOLDER\n    return os.path.exists(dirty_file)\n\n\ndef remove_if_dirty(item):\n    # TODO: Apply to other places this pattern is common\n    if is_dirty(item):\n        if os.path.exists(item):\n            # To avoid circular import in conan_server\n            from conan.api.output import ConanOutput\n            ConanOutput().warning(f\"{item} is dirty, removing it\")\n            if os.path.isfile(item):\n                os.remove(item)\n            else:\n                rmdir(item)\n        clean_dirty(item)\n        return True\n    return False\n\n\n@contextmanager\ndef set_dirty_context_manager(folder):\n    set_dirty(folder)\n    yield\n    clean_dirty(folder)\n\n\n@contextmanager\ndef chdir(newdir):\n    old_path = os.getcwd()\n    os.chdir(newdir)\n    try:\n        yield\n    finally:\n        os.chdir(old_path)\n\n\ndef md5(content):\n    try:\n        md5alg = hashlib.md5()\n    except ValueError:  # FIPS error https://github.com/conan-io/conan/issues/7800\n        md5alg = hashlib.md5(usedforsecurity=False)\n    if isinstance(content, bytes):\n        tmp = content\n    else:\n        tmp = content.encode(\"utf-8\")\n    md5alg.update(tmp)\n    return md5alg.hexdigest()\n\n\ndef md5sum(file_path):\n    return _generic_algorithm_sum(file_path, \"md5\")\n\n\ndef sha1sum(file_path):\n    return _generic_algorithm_sum(file_path, \"sha1\")\n\n\ndef sha256sum(file_path):\n    return _generic_algorithm_sum(file_path, \"sha256\")\n\n\ndef _generic_algorithm_sum(file_path, algorithm_name):\n\n    with open(file_path, 'rb') as fh:\n        try:\n            m = hashlib.new(algorithm_name)\n        except ValueError:  # FIPS error https://github.com/conan-io/conan/issues/7800\n            m = hashlib.new(algorithm_name, usedforsecurity=False)\n        while True:\n            data = fh.read(8192)\n            if not data:\n                break\n            m.update(data)\n        return m.hexdigest()\n\n\ndef check_with_algorithm_sum(algorithm_name, file_path, provided_hash):\n    real_hash = _generic_algorithm_sum(file_path, algorithm_name)\n    if real_hash != provided_hash.lower():\n        raise ConanException(\"%s hash failed for '%s' file. \\n\"\n                             \" Provided hash: %s  \\n\"\n                             \" Computed hash: %s\" % (algorithm_name,\n                                                          os.path.basename(file_path),\n                                                          provided_hash,\n                                                          real_hash))\n\n\ndef save(path, content, encoding=\"utf-8\"):\n    \"\"\"\n    Saves a file with given content\n    Params:\n        path: path to write file to\n        content: contents to save in the file\n        encoding: target file text encoding\n    \"\"\"\n\n    dir_path = os.path.dirname(path)\n    if dir_path:\n        os.makedirs(dir_path, exist_ok=True)\n    with open(path, \"w\", encoding=encoding, newline=\"\") as handle:\n        handle.write(content)\n\n\ndef save_files(path, files, encoding=\"utf-8\"):\n    for name, content in files.items():\n        save(os.path.join(path, name), content, encoding=encoding)\n\n\ndef load(path, encoding=\"utf-8\"):\n    \"\"\" Loads a file content \"\"\"\n    with open(path, 'r', encoding=encoding, newline=\"\") as handle:\n        tmp = handle.read()\n    return tmp\n\n\ndef load_user_encoded(path):\n    \"\"\" Exclusive for user side read-only files:\n     - conanfile.txt\n     - profile files\n     \"\"\"\n    with open(path, 'rb') as handle:\n        text = handle.read()\n\n    import codecs\n    encodings = {codecs.BOM_UTF8: \"utf_8_sig\",\n                 codecs.BOM_UTF32_BE: \"utf_32_be\",\n                 codecs.BOM_UTF32_LE: \"utf_32_le\",\n                 codecs.BOM_UTF16_BE: \"utf_16_be\",\n                 codecs.BOM_UTF16_LE: \"utf_16_le\",\n                 b'\\x2b\\x2f\\x76\\x38': \"utf_7\",\n                 b'\\x2b\\x2f\\x76\\x39': \"utf_7\",\n                 b'\\x2b\\x2f\\x76\\x2b': \"utf_7\",\n                 b'\\x2b\\x2f\\x76\\x2f': \"utf_7\",\n                 b'\\x2b\\x2f\\x76\\x38\\x2d': \"utf_7\"}\n    for bom, encoding in encodings.items():\n        if text.startswith(bom):\n            return text[len(bom):].decode(encoding)\n\n    for decoder in [\"utf-8\", \"Windows-1252\"]:\n        try:\n            return text.decode(decoder)\n        except UnicodeDecodeError:\n            continue\n    raise Exception(f\"Unknown encoding of file: {path}\\nIt is recommended to use utf-8 encoding\")\n\n\ndef _change_permissions(func, path, exc_info):\n    if not os.access(path, os.W_OK):\n        os.chmod(path, stat.S_IWUSR)\n        func(path)\n    else:\n        raise OSError(\"Cannot change permissions for {}! Exception info: {}\".format(path, exc_info))\n\n\nif platform.system() == \"Windows\":\n    def rmdir(path):\n        if not os.path.isdir(path):\n            return\n\n        retries = 3\n        delay = 0.5\n        for i in range(retries):\n            try:\n                shutil.rmtree(path, onerror=_change_permissions)\n                break\n            except OSError as err:\n                if i == retries - 1:\n                    raise ConanException(f\"Couldn't remove folder: {path}\\n{str(err)}\\n\"\n                                         \"Folder might be busy or open. \"\n                                         \"Close any app using it and retry.\")\n                time.sleep(delay)\n\n\n    def renamedir(old_path, new_path):\n        retries = 3\n        delay = 0.5\n        for i in range(retries):\n            try:\n                shutil.move(old_path, new_path)\n                break\n            except OSError as err:\n                if i == retries - 1:\n                    raise ConanException(f\"Couldn't move folder: {old_path}->{new_path}\\n\"\n                                         f\"{str(err)}\\n\"\n                                         \"Folder might be busy or open. \"\n                                         \"Close any app using it and retry.\")\n                time.sleep(delay)\nelse:\n    def rmdir(path):\n        if not os.path.isdir(path):\n            return\n        try:\n            shutil.rmtree(path, onerror=_change_permissions)\n        except OSError as err:\n            raise ConanException(f\"Couldn't remove folder: {path}\\n{str(err)}\\n\"\n                                 \"Folder might be busy or open. \"\n                                 \"Close any app using it and retry.\")\n\n    def renamedir(old_path, new_path):\n        try:\n            shutil.move(old_path, new_path)\n        except OSError as err:\n            raise ConanException(\n                f\"Couldn't move folder: {old_path}->{new_path}\\n{str(err)}\\n\"\n                \"Folder might be busy or open. \"\n                \"Close any app using it and retry.\")\n\n\ndef remove(path):\n    try:\n        assert os.path.isfile(path)\n        os.remove(path)\n    except (IOError, OSError) as e:  # for py3, handle just PermissionError\n        if e.errno == errno.EPERM or e.errno == errno.EACCES:\n            os.chmod(path, stat.S_IRWXU)\n            os.remove(path)\n            return\n        raise\n\n\ndef mkdir(path):\n    \"\"\"Recursive mkdir, doesnt fail if already existing\"\"\"\n    if os.path.exists(path):\n        return\n    os.makedirs(path)\n\n\ndef tar_extract(fileobj, destination_dir):\n    the_tar = tarfile.open(fileobj=fileobj)\n    # NOTE: The errorlevel=2 has been removed because it was failing in Win10, it didn't allow to\n    # \"could not change modification time\", with time=0\n    # the_tar.errorlevel = 2  # raise exception if any error\n    the_tar.extraction_filter = (lambda member, path: member)  # fully_trusted, avoid Py3.14 break\n    the_tar.extractall(path=destination_dir)\n    the_tar.close()\n\n\ndef merge_directories(src, dst):\n    from conan.tools.files import copy\n    copy(None, pattern=\"*\", src=src, dst=dst)\n\n\ndef gather_files(folder):\n    file_dict = {}\n    symlinked_folders = {}\n    for root, dirs, files in os.walk(folder):\n        if root != folder and not dirs and not files:  # empty folder\n            rel_path = root[len(folder) + 1:].replace(\"\\\\\", \"/\")\n            symlinked_folders[rel_path] = root\n            continue\n        for d in dirs:\n            abs_path = os.path.join(root, d)\n            if os.path.islink(abs_path):\n                rel_path = abs_path[len(folder) + 1:].replace(\"\\\\\", \"/\")\n                symlinked_folders[rel_path] = abs_path\n        for f in files:\n            if f == \".DS_Store\":\n                continue\n            abs_path = os.path.join(root, f)\n            rel_path = abs_path[len(folder) + 1:].replace(\"\\\\\", \"/\")\n            file_dict[rel_path] = abs_path\n\n    return file_dict, symlinked_folders\n\n\ndef human_size(size_bytes):\n    \"\"\"\n    format a size in bytes into a 'human' file size, e.g. B, KB, MB, GB, TB, PB\n    Note that bytes will be reported in whole numbers but KB and above will have\n    greater precision.  e.g. 43 B, 443 KB, 4.3 MB, 4.43 GB, etc\n    \"\"\"\n    unit_size = 1000.0\n    suffixes_table = [('B', 0), ('KB', 1), ('MB', 1), ('GB', 2), ('TB', 2), ('PB', 2)]\n\n    num = float(size_bytes)\n    the_precision = None\n    the_suffix = None\n    for suffix, precision in suffixes_table:\n        the_precision = precision\n        the_suffix = suffix\n        if num < unit_size:\n            break\n        num /= unit_size\n\n    if the_precision == 0:\n        formatted_size = \"%d\" % num\n    else:\n        formatted_size = str(round(num, ndigits=the_precision))\n\n    return \"%s%s\" % (formatted_size, the_suffix)\n\n\n# FIXME: completely remove disutils once we don't support <3.8 any more\ndef copytree_compat(source_folder, dest_folder):\n    if sys.version_info >= (3, 8):\n        shutil.copytree(source_folder, dest_folder, dirs_exist_ok=True)\n    else:\n        from distutils.dir_util import copy_tree\n        copy_tree(source_folder, dest_folder)\n"
  },
  {
    "path": "conan/internal/util/runners.py",
    "content": "import os\nimport subprocess\nimport sys\nimport tempfile\nfrom contextlib import contextmanager\nfrom io import StringIO\n\nfrom conan.errors import ConanException\nfrom conan.internal.util.files import load\n\n\nif getattr(sys, 'frozen', False) and 'LD_LIBRARY_PATH' in os.environ:\n\n    # http://pyinstaller.readthedocs.io/en/stable/runtime-information.html#ld-library-path-libpath-considerations\n    pyinstaller_bundle_dir = os.environ['LD_LIBRARY_PATH'].replace(\n        os.environ.get('LD_LIBRARY_PATH_ORIG', ''), ''\n    ).strip(';:')\n\n    @contextmanager\n    def pyinstaller_bundle_env_cleaned():\n        \"\"\"Removes the pyinstaller bundle directory from LD_LIBRARY_PATH\n        \"\"\"\n        ld_library_path = os.environ['LD_LIBRARY_PATH']\n        os.environ['LD_LIBRARY_PATH'] = ld_library_path.replace(pyinstaller_bundle_dir,\n                                                                '').strip(';:')\n        yield\n        os.environ['LD_LIBRARY_PATH'] = ld_library_path\n\nelse:\n    @contextmanager\n    def pyinstaller_bundle_env_cleaned():\n        yield\n\n\ndef conan_run(command, stdout=None, stderr=None, cwd=None, shell=True):\n    \"\"\"\n    @param shell:\n    @param stderr:\n    @param command: Command to execute\n    @param stdout: Instead of print to sys.stdout print to that stream. Could be None\n    @param cwd: Move to directory to execute\n    \"\"\"\n    stdout = stdout or sys.stderr\n    stderr = stderr or sys.stderr\n\n    out = subprocess.PIPE if isinstance(stdout, StringIO) else stdout\n    err = subprocess.PIPE if isinstance(stderr, StringIO) else stderr\n\n    with pyinstaller_bundle_env_cleaned():\n        try:\n            proc = subprocess.Popen(command, shell=shell, stdout=out, stderr=err, cwd=cwd)\n        except Exception as e:\n            raise ConanException(\"Error while running cmd\\nError: %s\" % (str(e)))\n\n        proc_stdout, proc_stderr = proc.communicate()\n        # If the output is piped, like user provided a StringIO or testing, the communicate\n        # will capture and return something when thing finished\n        if proc_stdout:\n            stdout.write(proc_stdout.decode(\"utf-8\", errors=\"ignore\"))\n        if proc_stderr:\n            stderr.write(proc_stderr.decode(\"utf-8\", errors=\"ignore\"))\n        return proc.returncode\n\n\ndef detect_runner(command):\n    # Running detect.py automatic detection of profile\n    proc = subprocess.Popen(command, shell=True, bufsize=1, universal_newlines=True,\n                            stdout=subprocess.PIPE, stderr=subprocess.STDOUT)\n\n    output_buffer = []\n    while True:\n        line = proc.stdout.readline()\n        if not line:\n            break\n        # output.write(line)\n        output_buffer.append(str(line))\n\n    proc.communicate()\n    return proc.returncode, \"\".join(output_buffer)\n\n\ndef check_output_runner(cmd, stderr=None, ignore_error=False):\n    # Used to run several utilities, like Pacman detect, AIX version, uname, SCM\n    assert isinstance(cmd, str)\n    d = tempfile.mkdtemp()\n    tmp_file = os.path.join(d, \"output\")\n    try:\n        # We don't want stderr to print warnings that will mess the pristine outputs\n        stderr = stderr or subprocess.PIPE\n        command = '{} > \"{}\"'.format(cmd, tmp_file)\n        process = subprocess.Popen(command, shell=True, stderr=stderr)\n        stdout, stderr = process.communicate()\n\n        if process.returncode and not ignore_error:\n            # Only in case of error, we print also the stderr to know what happened\n            msg = f\"Command '{cmd}' failed with errorcode '{process.returncode}'\\n{stderr}\"\n            raise ConanException(msg)\n\n        output = load(tmp_file)\n        return output\n    finally:\n        try:\n            os.unlink(tmp_file)\n        except OSError:\n            pass\n"
  },
  {
    "path": "conan/test/__init__.py",
    "content": ""
  },
  {
    "path": "conan/test/assets/__init__.py",
    "content": ""
  },
  {
    "path": "conan/test/assets/autotools.py",
    "content": "import textwrap\n\nfrom jinja2 import Template\n\n_makefile_am = \"\"\"\n{% if main %}\nbin_PROGRAMS = {{ main }}\n{{main}}_SOURCES = {{ main_srcs }}\n{% endif %}\n{% if lib %}\nlib_LIBRARIES = {{ lib }}\n{{lib.replace(\".\", \"_\")}}_SOURCES = {{ lib_srcs }}\n{% endif %}\n{% if main and lib %}\n{{main}}_LDADD = {{ lib }}\n{% endif %}\n\n\"\"\"\n# newline at the end is important: m4: INTERNAL ERROR: recursive push_string!\n\n\ndef gen_makefile_am(**context):\n    t = Template(_makefile_am)\n    return t.render(**context)\n\n\n_configure_ac = \"\"\"\nAC_INIT([main], [1.0], [some@email.com])\nAM_INIT_AUTOMAKE([-Wall -Werror foreign])\nAC_PROG_CXX\nAC_PROG_RANLIB\nAM_PROG_AR\nAC_CONFIG_FILES([Makefile])\nAC_OUTPUT\n\n\"\"\"\n# newline at the end is important: m4: INTERNAL ERROR: recursive push_string!\n\n\ndef gen_configure_ac(**context):\n    t = Template(_configure_ac)\n    return t.render(**context)\n\n\ndef gen_makefile(**context):\n    makefile = textwrap.dedent(\"\"\"\\\n        .PHONY: all\n        all: apps libs\n\n        apps: {% for s in apps %} {{s}} {% endfor %}\n\n        libs: {% for s in libs %} lib{{s}}.a {% endfor %}\n\n        {%- set link_libs = namespace(str='') %}\n        {% for lib in libs %}\n        {%- set link_libs.str = link_libs.str + ' -l' + lib|string  %}\n        lib{{lib}}.a: {{lib}}.o\n        \t$(AR) rcs lib{{lib}}.a {{lib}}.o {%if static_runtime%}--static{%endif%}\n        {% endfor %}\n\n        {% for s in apps %}\n        {{s}}: {{s}}.o libs\n        \t$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) -o {{s}} {{s}}.o $(LIBS) {{link_libs.str}} -L. {%if static_runtime%}--static{%endif%}\n        {% endfor %}\n        \"\"\")\n\n    t = Template(makefile)\n    return t.render(**context)\n"
  },
  {
    "path": "conan/test/assets/cmake.py",
    "content": "import textwrap\n\nfrom jinja2 import Template\n\n\ndef gen_cmakelists(language=\"CXX\", verify=True, project=\"project\", libname=\"mylibrary\",\n                   libsources=None, appname=\"myapp\", appsources=None, cmake_version=\"3.15\",\n                   install=False, find_package=None, libtype=\"\", deps=None, public_header=None,\n                   custom_content=None):\n    \"\"\"\n    language: C, C++, C/C++\n    project: the project name\n    \"\"\"\n    cmake = textwrap.dedent(\"\"\"\\\n        {% if verify %}\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        set(CMAKE_C_COMPILER_WORKS 1)\n        set(CMAKE_C_ABI_COMPILED 1)\n        {% endif %}\n\n        cmake_minimum_required(VERSION {{cmake_version}})\n        project({{project}} {{language}})\n\n        {% if find_package is mapping %}\n        {% for s, c in find_package.items() %}\n        find_package({{s}} COMPONENTS {{c}} )\n        {% endfor %}\n        {% else %}\n        {% for s in find_package %}\n        find_package({{s}})\n        {% endfor %}\n        {% endif %}\n\n        {% if libsources %}\n        add_library({{libname}} {{libtype}} {% for s in libsources %} {{s}} {% endfor %})\n        target_include_directories({{libname}} PUBLIC \"include\")\n        {% endif %}\n\n        {% if libsources and find_package %}\n        {% if find_package is mapping %}\n        target_link_libraries({{libname}} {% for s, c in find_package.items() %} {{s}}::{{c}} {% endfor %})\n        {% else %}\n        target_link_libraries({{libname}} {% for s in find_package %} {{s}}::{{s}} {% endfor %})\n        {% endif %}\n        {% endif %}\n\n        {% if libsources and deps %}\n        target_link_libraries({{libname}} {% for s in deps %} {{s}} {% endfor %})\n        {% endif %}\n\n        {% if appsources %}\n        add_executable({{appname}} {% for s in appsources %} {{s}} {% endfor %})\n        target_include_directories({{appname}} PUBLIC \"include\")\n        {% endif %}\n\n        {% if appsources and libsources %}\n        target_link_libraries({{appname}} {{libname}})\n        {% endif %}\n\n        {% if appsources and not libsources and find_package %}\n        {% if find_package is mapping %}\n         target_link_libraries({{appname}} {% for s, c in find_package.items() %} {{s}}::{{c}} {% endfor %})\n        {% else %}\n        target_link_libraries({{appname}} {% for s in find_package %} {{s}}::{{s}} {% endfor %})\n        {% endif %}\n        {% endif %}\n\n        {% if appsources and deps %}\n        target_link_libraries({{appname}} {% for s in deps %} {{s}} {% endfor %})\n        {% endif %}\n\n        {% if libsources and public_header %}\n        set_target_properties({{libname}} PROPERTIES PUBLIC_HEADER \"{{public_header}}\")\n        {% endif %}\n\n        {% if install %}\n        {% if appsources %}\n        install(TARGETS {{appname}})\n        {% endif %}\n        {% if libsources %}\n        install(TARGETS {{libname}})\n        {% endif %}\n        {% endif %}\n\n        {% if custom_content %}\n        {{custom_content}}\n        {% endif %}\n\n        \"\"\")\n\n    t = Template(cmake, trim_blocks=True, lstrip_blocks=True)\n    return t.render({\"verify\": verify,\n                     \"language\": language,\n                     \"project\": project,\n                     \"libname\": libname,\n                     \"libsources\": libsources,\n                     \"appname\": appname,\n                     \"appsources\": appsources,\n                     \"cmake_version\": cmake_version,\n                     \"install\": install,\n                     \"find_package\": find_package or [],\n                     \"libtype\": libtype,\n                     \"public_header\": public_header,\n                     \"deps\": deps,\n                     \"custom_content\": custom_content\n                     })\n"
  },
  {
    "path": "conan/test/assets/genconanfile.py",
    "content": "from conan.api.model import RecipeReference\n\n\nclass GenConanfile:\n    \"\"\"\n    USAGE:\n\n    x = GenConanfile().with_import(\"import os\").\\\n        with_setting(\"os\").\\\n        with_option(\"shared\", [True, False]).\\\n        with_default_option(\"shared\", True).\\\n        with_build_msg(\"holaaa\").\\\n        with_build_msg(\"adiooos\").\\\n        with_package_file(\"file.txt\", \"hola\").\\\n        with_package_file(\"file2.txt\", \"hola\")\n    \"\"\"\n\n    def __init__(self, name=None, version=None):\n        self._imports = [\"from conan import ConanFile\"]\n        self._name = name\n        self._version = version\n        self._package_type = None\n        self._settings = None\n        self._options = None\n        self._generators = None\n        self._default_options = None\n        self._provides = None\n        self._deprecated = None\n        self._package_lines = None\n        self._finalize_lines = None\n        self._package_files = None\n        self._package_files_env = None\n        self._build_messages = None\n        self._requires = None\n        self._requirements = None\n        self._python_requires = None\n        self._build_requires = None\n        self._build_requirements = None\n        self._tool_requires = None\n        self._tool_requirements = None\n        self._test_requirements = None\n        self._test_requires = None\n        self._revision_mode = None\n        self._package_info = None\n        self._package_id_lines = None\n        self._test_lines = None\n        self._exports_sources = None\n        self._exports = None\n        self._cmake_build = False\n        self._class_attributes = None\n\n        self._is_tested_ref_build_require = None\n\n    def with_package_type(self, value):\n        self._package_type = value\n        return self\n\n    def with_name(self, name):\n        self._name = name\n        return self\n\n    def with_version(self, version):\n        self._version = version\n        return self\n\n    def with_provides(self, provides):\n        self._provides = self._provides or []\n        self._provides.append(provides)\n        return self\n\n    def with_deprecated(self, deprecated):\n        self._deprecated = deprecated\n        return self\n\n    def with_revision_mode(self, revision_mode):\n        self._revision_mode = revision_mode\n        return self\n\n    def with_generator(self, generator):\n        self._generators = self._generators or []\n        self._generators.append(generator)\n        return self\n\n    def with_exports_sources(self, *exports):\n        self._exports_sources = self._exports_sources or []\n        for export in exports:\n            self._exports_sources.append(export)\n        return self\n\n    def with_exports(self, *exports):\n        self._exports = self._exports or []\n        for export in exports:\n            self._exports.append(export)\n        return self\n\n    def with_require(self, ref):\n        self._requires = self._requires or []\n        ref_str = self._get_full_ref_str(ref)\n        self._requires.append(ref_str)\n        return self\n\n    def with_requires(self, *refs):\n        for ref in refs:\n            self.with_require(ref)\n        return self\n\n    @staticmethod\n    def _get_full_ref_str(ref):\n        if isinstance(ref, RecipeReference):\n            ref_str = ref.repr_notime()\n        else:\n            ref_str = ref\n        return ref_str\n\n    def with_requirement(self, ref, **kwargs):\n        self._requirements = self._requirements or []\n        ref_str = self._get_full_ref_str(ref)\n        self._requirements.append((ref_str, kwargs))\n        return self\n\n    def with_build_requires(self, *refs):\n        self._build_requires = self._build_requires or []\n        for ref in refs:\n            ref_str = self._get_full_ref_str(ref)\n            self._build_requires.append(ref_str)\n        return self\n\n    def with_python_requires(self, *refs):\n        self._python_requires = self._python_requires or []\n        for ref in refs:\n            ref_str = self._get_full_ref_str(ref)\n            self._python_requires.append(ref_str)\n        return self\n\n    def with_tool_requires(self, *refs):\n        self._tool_requires = self._tool_requires or []\n        for ref in refs:\n            ref_str = self._get_full_ref_str(ref)\n            self._tool_requires.append(ref_str)\n        return self\n\n    def with_test_requires(self, *refs):\n        self._test_requires = self._test_requires or []\n        for ref in refs:\n            ref_str = self._get_full_ref_str(ref)\n            self._test_requires.append(ref_str)\n        return self\n\n    def with_test_reference_as_build_require(self):\n        self._is_tested_ref_build_require = True\n        return self\n\n    def with_build_requirement(self, ref, **kwargs):\n        self._build_requirements = self._build_requirements or []\n        ref_str = self._get_full_ref_str(ref)\n        self._build_requirements.append((ref_str, kwargs))\n        return self\n\n    def with_tool_requirement(self, ref, **kwargs):\n        self._tool_requirements = self._tool_requirements or []\n        ref_str = self._get_full_ref_str(ref)\n        self._tool_requirements.append((ref_str, kwargs))\n        return self\n\n    def with_test_requirement(self, ref, **kwargs):\n        self._test_requirements = self._test_requirements or []\n        ref_str = self._get_full_ref_str(ref)\n        self._test_requirements.append((ref_str, kwargs))\n        return self\n\n    def with_import(self, *imports):\n        for i in imports:\n            if i not in self._imports:\n                self._imports.append(i)\n        return self\n\n    def with_setting(self, setting):\n        self._settings = self._settings or []\n        self._settings.append(setting)\n        return self\n\n    def with_settings(self, *settings):\n        self._settings = self._settings or []\n        self._settings.extend(settings)\n        return self\n\n    def with_option(self, option_name, values, default=None):\n        self._options = self._options or {}\n        self._options[option_name] = values\n        if default is not None:\n            self.with_default_option(option_name, default)\n        return self\n\n    def with_default_option(self, option_name, value):\n        self._default_options = self._default_options or {}\n        self._default_options[option_name] = value\n        return self\n\n    def with_shared_option(self, default=False):\n        return self.with_option(\"shared\", [True, False]).with_default_option(\"shared\", default)\n\n    def with_package_file(self, file_name, contents=None, env_var=None):\n        assert contents is not None or env_var\n        self._package_files = self._package_files or {}\n\n        self._package_files_env = self._package_files_env or {}\n        self.with_import(\"import os\")\n        self.with_import(\"from conan.tools.files import save, chdir\")\n        if contents:\n            self._package_files[file_name] = contents\n        if env_var:\n            self._package_files_env[file_name] = env_var\n        return self\n\n    def with_package(self, *lines):\n        self._package_lines = self._package_lines or []\n        for line in lines:\n            self._package_lines.append(line)\n        return self\n\n    def with_finalize(self, *lines):\n        self._finalize_lines = self._finalize_lines or []\n        for line in lines:\n            self._finalize_lines.append(line)\n        return self\n\n    def with_build_msg(self, msg):\n        self._build_messages = self._build_messages or []\n        self._build_messages.append(msg)\n        return self\n\n    def with_package_info(self, cpp_info=None):\n        assert cpp_info is None or isinstance(cpp_info, dict)\n        self._package_info = self._package_info or {}\n        if cpp_info:\n            self._package_info[\"cpp_info\"] = cpp_info\n        return self\n\n    def with_package_id(self, *lines):\n        self._package_id_lines = self._package_id_lines or []\n        for line in lines:\n            self._package_id_lines.append(line)\n        return self\n\n    def with_test(self, *lines):\n        self._test_lines = self._test_lines or []\n        for line in lines:\n            self._test_lines.append(line)\n        return self\n\n    def with_cmake_build(self):\n        self._imports.append(\"from conan.tools.cmake import CMake\")\n        self._generators = self._generators or []\n        self._generators.append(\"CMakeDeps\")\n        self._generators.append(\"CMakeToolchain\")\n        self.with_settings(\"os\", \"compiler\", \"arch\", \"build_type\")\n        self._cmake_build = True\n        return self\n\n    def with_class_attribute(self, attr):\n        \"\"\".with_class_attribute(\"no_copy_sources=True\") \"\"\"\n        self._class_attributes = self._class_attributes or []\n        self._class_attributes.append(attr)\n        return self\n\n    @property\n    def _name_render(self):\n        return \"name = '{}'\".format(self._name)\n\n    @property\n    def _version_render(self):\n        return \"version = '{}'\".format(self._version)\n\n    @property\n    def _package_type_render(self):\n        return \"package_type = '{}'\".format(self._package_type)\n\n    @property\n    def _provides_render(self):\n        line = \", \".join('\"{}\"'.format(provide) for provide in self._provides)\n        return \"provides = {}\".format(line)\n\n    @property\n    def _deprecated_render(self):\n        return \"deprecated = {}\".format(self._deprecated)\n\n    @property\n    def _generators_render(self):\n        line = \", \".join('\"{}\"'.format(generator) for generator in self._generators)\n        return \"generators = {}\".format(line)\n\n    @property\n    def _revision_mode_render(self):\n        line = \"revision_mode=\\\"{}\\\"\".format(self._revision_mode)\n        return line\n\n    @property\n    def _settings_render(self):\n        line = \", \".join('\"%s\"' % s for s in self._settings)\n        return \"settings = {}\".format(line)\n\n    @property\n    def _options_render(self):\n        line = \", \".join('\"%s\": %s' % (k, v) for k, v in self._options.items())\n        tmp = \"options = {%s}\" % line\n        return tmp\n\n    @property\n    def _default_options_render(self):\n        line = \", \".join('\"%s\": %s' % (k, v) for k, v in self._default_options.items())\n        tmp = \"default_options = {%s}\" % line\n        return tmp\n\n    @property\n    def _build_requires_render(self):\n        line = \", \".join(['\"{}\"'.format(r) for r in self._build_requires])\n        tmp = \"build_requires = %s\" % line\n        return tmp\n\n    @property\n    def _python_requires_render(self):\n        line = \", \".join(['\"{}\"'.format(r) for r in self._python_requires])\n        tmp = \"python_requires = %s\" % line\n        return tmp\n\n    @property\n    def _tool_requires_render(self):\n        line = \", \".join(['\"{}\"'.format(r) for r in self._tool_requires])\n        tmp = \"tool_requires = %s\" % line\n        return tmp\n\n    @property\n    def _requires_render(self):\n        items = []\n        for ref in self._requires:\n            items.append('\"{}\"'.format(ref))\n        return \"requires = ({}, )\".format(\", \".join(items))\n\n    @property\n    def _test_requires_render(self):\n        line = \", \".join(['\"{}\"'.format(r) for r in self._test_requires])\n        tmp = \"test_requires = {}\".format(line)\n        return tmp\n\n    @property\n    def _requirements_render(self):\n        lines = [\"\", \"    def requirements(self):\"]\n        for ref, kwargs in self._requirements or []:\n            args = \", \".join(\"{}={}\".format(k, f'\"{v}\"' if isinstance(v, str) else v)\n                             for k, v in kwargs.items())\n            lines.append('        self.requires(\"{}\", {})'.format(ref, args))\n\n        for ref, kwargs in self._build_requirements or []:\n            args = \", \".join(\"{}={}\".format(k, f'\"{v}\"' if not isinstance(v, (bool, dict)) else v)\n                             for k, v in kwargs.items())\n            lines.append('        self.build_requires(\"{}\", {})'.format(ref, args))\n\n        for ref, kwargs in self._tool_requirements or []:\n            args = \", \".join(\"{}={}\".format(k, f'\"{v}\"' if not isinstance(v, (bool, dict)) else v)\n                             for k, v in kwargs.items())\n            lines.append('        self.tool_requires(\"{}\", {})'.format(ref, args))\n\n        for ref, kwargs in self._test_requirements or []:\n            args = \", \".join(\"{}={}\".format(k, f'\"{v}\"' if not isinstance(v, (bool, dict)) else v)\n                             for k, v in kwargs.items())\n            lines.append('        self.test_requires(\"{}\", {})'.format(ref, args))\n\n        return \"\\n\".join(lines)\n\n    @property\n    def _package_method(self):\n        return self._package_lines or self._package_files or self._package_files_env\n\n    @property\n    def _finalize_method(self):\n        return self._finalize_lines\n\n    @property\n    def _package_method_render(self):\n        lines = []\n        if self._package_lines:\n            lines.extend(\"        {}\".format(line) for line in self._package_lines)\n        if self._package_files:\n            lines = ['        save(self, os.path.join(self.package_folder, \"{}\"), \"{}\")'\n                     ''.format(key, value)\n                     for key, value in self._package_files.items()]\n\n        if self._package_files_env:\n            lines.extend(['        save(self, os.path.join(self.package_folder, \"{}\"), '\n                          'os.getenv(\"{}\"))'.format(key, value)\n                          for key, value in self._package_files_env.items()])\n        return \"\"\"\n    def package(self):\n{}\n    \"\"\".format(\"\\n\".join(lines))\n\n    @property\n    def _finalize_method_render(self):\n        lines = []\n        if self._finalize_lines:\n            lines.extend(\"        {}\".format(line) for line in self._finalize_lines)\n\n        return \"\"\"\n    def finalize(self):\n{}\n        \"\"\".format(\"\\n\".join(lines))\n\n    @property\n    def _build_render(self):\n        if not self._build_messages and not self._cmake_build:\n            return None\n        lines = []\n        if self._build_messages:\n            lines = ['        self.output.warning(\"{}\")'.format(m) for m in self._build_messages]\n        if self._cmake_build:\n            lines.extend(['        cmake = CMake(self)',\n                          '        cmake.configure()',\n                          '        cmake.build()'])\n        return \"\"\"\n    def build(self):\n{}\n    \"\"\".format(\"\\n\".join(lines))\n\n    @property\n    def _package_info_render(self):\n        lines = []\n        if \"cpp_info\" in self._package_info:\n            for k, v in self._package_info[\"cpp_info\"].items():\n                if k == \"components\":\n                    for comp_name, comp in v.items():\n                        for comp_attr_name, comp_attr_value in comp.items():\n                            lines.append('        self.cpp_info.components[\"{}\"].{} = {}'.format(\n                                comp_name, comp_attr_name, str(comp_attr_value)))\n                else:\n                    lines.append('        self.cpp_info.{} = {}'.format(k, str(v)))\n\n        return \"\"\"\n    def package_info(self):\n{}\n        \"\"\".format(\"\\n\".join(lines))\n\n    @property\n    def _package_id_lines_render(self):\n        lines = ['        {}'.format(line) for line in self._package_id_lines]\n        return \"\"\"\n    def package_id(self):\n{}\n        \"\"\".format(\"\\n\".join(lines))\n\n    @property\n    def _test_lines_render(self):\n        if self._is_tested_ref_build_require:\n            lines = [\"\",\n                     \"    def build_requirements(self):\",\n                     '         self.tool_requires(self.tested_reference_str)',\n                     \"\",\n                     '    def test(self):']\n        else:\n            lines = [\"\",\n                     \"    def requirements(self):\",\n                     '         self.requires(self.tested_reference_str)',\n                     \"\",\n                     '    def test(self):']\n\n        lines += ['        %s' % m for m in self._test_lines]\n        return \"\\n\".join(lines)\n\n    @property\n    def _exports_sources_render(self):\n        line = \", \".join('\"{}\"'.format(e) for e in self._exports_sources)\n        return \"exports_sources = {}\".format(line)\n\n    @property\n    def _exports_render(self):\n        line = \", \".join('\"{}\"'.format(e) for e in self._exports)\n        return \"exports = {}\".format(line)\n\n    @property\n    def _class_attributes_render(self):\n        self._class_attributes = self._class_attributes or []\n        return [\"    {}\".format(a) for a in self._class_attributes]\n\n    def __repr__(self):\n        ret = []\n        ret.extend(self._imports)\n        ret.append(\"class HelloConan(ConanFile):\")\n\n        for member in (\"name\", \"version\", \"package_type\", \"provides\", \"deprecated\",\n                       \"exports_sources\", \"exports\", \"generators\", \"requires\", \"build_requires\",\n                       \"tool_requires\", \"test_requires\", \"requirements\", \"python_requires\",\n                       \"revision_mode\", \"settings\", \"options\", \"default_options\", \"build\",\n                       \"package_method\", \"package_info\", \"package_id_lines\", \"test_lines\",\n                       \"finalize_method\"\n                       ):\n            if member == \"requirements\":\n                # FIXME: This seems exclusive, but we could mix them?\n                v = self._requirements or self._tool_requirements or self._build_requirements\n            else:\n                v = getattr(self, \"_{}\".format(member), None)\n            if v is not None:\n                ret.append(\"    {}\".format(getattr(self, \"_{}_render\".format(member))))\n\n        ret.extend(self._class_attributes_render)\n        build = self._build_render\n        if build is not None:\n            ret.append(\"    {}\".format(self._build_render))\n        if ret[-1] == \"class HelloConan(ConanFile):\":\n            ret.append(\"    pass\")\n        return \"\\n\".join(ret)\n"
  },
  {
    "path": "conan/test/assets/premake.py",
    "content": "import textwrap\n\nfrom jinja2 import Template\n\n\ndef gen_premake5(workspace, projects, includedirs=None, configurations=None):\n    includedirs = includedirs if includedirs is not None else [\".\"]\n    premake5 = textwrap.dedent(\"\"\"\\\n        workspace \"{{workspace}}\"\n            cppdialect \"C++17\"\n            configurations {{premake_quote(configurations)}}\n            fatalwarnings {\"All\"}\n            floatingpoint \"Fast\"\n            includedirs {{premake_quote(includedirs)}}\n            filter \"configurations:Debug\"\n               defines { \"DEBUG\" }\n               symbols \"On\"\n\n            filter \"configurations:Release\"\n               defines { \"NDEBUG\" }\n               optimize \"On\"\n\n        {% for project in projects %}\n        project \"{{project[\"name\"]}}\"\n            kind \"{{project[\"kind\"] or 'StaticLib'}}\"\n            language \"{{project[\"language\"] or 'C++'}}\"\n            files {{premake_quote(project[\"files\"])}}\n            links {{premake_quote(project[\"links\"])}}\n        {% endfor %}\n        \"\"\")\n\n    t = Template(premake5, trim_blocks=True, lstrip_blocks=True)\n\n    def premake_quote(s):\n        return '{' + ', '.join(['\"{}\"'.format(s) for s in s]) + '}'\n\n    return t.render(\n        {\n            \"premake_quote\": premake_quote,\n            \"workspace\": workspace,\n            \"configurations\": configurations or [\"Debug\", \"Release\"],\n            \"includedirs\": includedirs,\n            \"projects\": projects,\n        }\n    )\n"
  },
  {
    "path": "conan/test/assets/sources.py",
    "content": "from jinja2 import Template\n\n_function_cpp = r\"\"\"\n{% if name != \"main\" %}\n#include \"{{name}}.h\"\n{% endif %}\n\n#include <iostream>\n\n{% for it in includes -%}\n#include \"{{it}}.h\"\n{% endfor %}\n\nint {{name}}(){\n    #ifdef NDEBUG\n    std::cout << \"{{ msg or name }}: Release!\\n\";\n    #else\n    std::cout << \"{{ msg or name }}: Debug!\\n\";\n    #endif\n\n    // ARCHITECTURES\n    #ifdef _M_X64\n    std::cout << \"  {{ msg or name }} _M_X64 defined\\n\";\n    #endif\n\n    #ifdef _M_IX86\n    std::cout << \"  {{ msg or name }} _M_IX86 defined\\n\";\n    #endif\n\n    #ifdef _M_ARM64\n    std::cout << \"  {{ msg or name }}: _M_ARM64 defined\\n\";\n    #endif\n\n    #if __i386__\n    std::cout << \"  {{ msg or name }} __i386__ defined\\n\";\n    #endif\n\n    #if __x86_64__\n    std::cout << \"  {{ msg or name }} __x86_64__ defined\\n\";\n    #endif\n\n    #if __aarch64__\n    std::cout << \"  {{ msg or name }} __aarch64__ defined\\n\";\n    #endif\n\n    // Libstdc++\n    #if defined _GLIBCXX_USE_CXX11_ABI\n    std::cout << \"  {{ msg or name }} _GLIBCXX_USE_CXX11_ABI \"<< _GLIBCXX_USE_CXX11_ABI << \"\\n\";\n    #endif\n\n    // COMPILER VERSIONS\n    #if _MSC_VER\n    std::cout << \"  {{ msg or name }} _MSC_VER\" << _MSC_VER<< \"\\n\";\n    #endif\n\n    #if _MSVC_LANG\n    std::cout << \"  {{ msg or name }} _MSVC_LANG\" << _MSVC_LANG<< \"\\n\";\n    #endif\n\n    #if __cplusplus\n    std::cout << \"  {{ msg or name }} __cplusplus\" << __cplusplus<< \"\\n\";\n    #endif\n\n    #if __INTEL_COMPILER\n    std::cout << \"  {{ msg or name }} __INTEL_COMPILER\" << __INTEL_COMPILER<< \"\\n\";\n    #endif\n\n    #if __GNUC__\n    std::cout << \"  {{ msg or name }} __GNUC__\" << __GNUC__<< \"\\n\";\n    #endif\n\n    #if __GNUC_MINOR__\n    std::cout << \"  {{ msg or name }} __GNUC_MINOR__\" << __GNUC_MINOR__<< \"\\n\";\n    #endif\n\n    #if __clang_major__\n    std::cout << \"  {{ msg or name }} __clang_major__\" << __clang_major__<< \"\\n\";\n    #endif\n\n    #if __clang_minor__\n    std::cout << \"  {{ msg or name }} __clang_minor__\" << __clang_minor__<< \"\\n\";\n    #endif\n\n    #if __apple_build_version__\n    std::cout << \"  {{ msg or name }} __apple_build_version__\" << __apple_build_version__<< \"\\n\";\n    #endif\n\n    // SUBSYSTEMS\n\n    #if __MSYS__\n    std::cout << \"  {{ msg or name }} __MSYS__\" << __MSYS__<< \"\\n\";\n    #endif\n\n    #if __MINGW32__\n    std::cout << \"  {{ msg or name }} __MINGW32__\" << __MINGW32__<< \"\\n\";\n    #endif\n\n    #if __MINGW64__\n    std::cout << \"  {{ msg or name }} __MINGW64__\" << __MINGW64__<< \"\\n\";\n    #endif\n\n    #if __CYGWIN__\n    std::cout << \"  {{ msg or name }} __CYGWIN__\" << __CYGWIN__<< \"\\n\";\n    #endif\n\n    {% for it in preprocessor -%}\n    std::cout << \"  {{msg}} {{it}}: \" <<  {{it}} << \"\\n\";\n    {%- endfor %}\n\n    {% for it in calls -%}\n    {{it}}();\n    {% endfor %}\n    return 0;\n}\n\"\"\"\n\n\ndef gen_function_cpp(**context):\n    t = Template(_function_cpp)\n    return t.render(**context)\n\n\n_function_c = r\"\"\"\n\n#define STRINGIFY_(x) #x\n#define STRINGIFY(y) STRINGIFY_(y)\n\n{% if name != \"main\" %}\n#include \"{{name}}.h\"\n{% endif %}\n\n#include <stdio.h>\n\n{% for it in includes -%}\n#include \"{{it}}.h\"\n{% endfor %}\n\nint {{name}}(){\n    #ifdef NDEBUG\n    printf(\"{{ msg or name }}: Release!\\n\");\n    #else\n    printf(\"{{ msg or name }}: Debug!\\n\");\n    #endif\n\n    // ARCHITECTURES\n    #ifdef _M_X64\n    printf(\"  {{ msg or name }} _M_X64 defined\\n\");\n    #endif\n\n    #ifdef _M_IX86\n    printf(\"  {{ msg or name }} _M_IX86 defined\\n\");\n    #endif\n\n    #ifdef _M_ARM64\n    printf(\"  {{ msg or name }} _M_ARM64 defined\\n\");\n    #endif\n\n    #if __i386__\n    printf(\"  {{ msg or name }} __i386__ defined\\n\");\n    #endif\n\n    #if __x86_64__\n    printf(\"  {{ msg or name }} __x86_64__ defined\\n\");\n    #endif\n\n    #if __aarch64__\n    printf(\"  {{ msg or name }} __aarch64__ defined\\n\");\n    #endif\n\n    // Libstdc++\n    #if defined _GLIBCXX_USE_CXX11_ABI\n    printf(\"  {{ msg or name }} _GLIBCXX_USE_CXX11_ABI %s\\n\",  STRINGIFY(_GLIBCXX_USE_CXX11_ABI));\n    #endif\n\n    // COMPILER VERSIONS\n    #if _MSC_VER\n    printf(\"  {{ msg or name }} _MSC_VER%s\\n\", STRINGIFY(_MSC_VER));\n    #endif\n\n    #if _MSVC_LANG\n    printf(\"  {{ msg or name }} _MSVC_LANG%s\\n\", STRINGIFY(_MSVC_LANG));\n    #endif\n\n    #if __cplusplus\n    printf(\"  {{ msg or name }} __cplusplus%s\\n\", STRINGIFY(__cplusplus));\n    #endif\n\n    #if __INTEL_COMPILER\n    printf(\"  {{ msg or name }} __INTEL_COMPILER%s\\n\", STRINGIFY(__INTEL_COMPILER));\n    #endif\n\n    #if __GNUC__\n    printf(\"  {{ msg or name }} __GNUC__%s\\n\", STRINGIFY(__GNUC__));\n    #endif\n\n    #if __GNUC_MINOR__\n    printf(\"  {{ msg or name }} __GNUC_MINOR__%s\\n\", STRINGIFY(__GNUC_MINOR__));\n    #endif\n\n    #if __clang_major__\n    printf(\"  {{ msg or name }} __clang_major__%s\\n\", STRINGIFY(__clang_major__));\n    #endif\n\n    #if __clang_minor__\n    printf(\"  {{ msg or name }} __clang_minor__%s\\n\", STRINGIFY(__clang_minor__));\n    #endif\n\n    #if __apple_build_version__\n    printf(\"  {{ msg or name }} __apple_build_version__%s\\n\", STRINGIFY(__apple_build_version__));\n    #endif\n\n    // SUBSYSTEMS\n\n    #if __MSYS__\n    printf(\"  {{ msg or name }} __MSYS__%s\\n\", STRINGIFY(__MSYS__));\n    #endif\n\n    #if __MINGW32__\n    printf(\"  {{ msg or name }} __MINGW32__%s\\n\", STRINGIFY(__MINGW32__));\n    #endif\n\n    #if __MINGW64__\n    printf(\"  {{ msg or name }} __MINGW64__%s\\n\", STRINGIFY(__MINGW64__));\n    #endif\n\n    #if __CYGWIN__\n    printf(\"  {{ msg or name }} __CYGWIN__%s\\n\", STRINGIFY(__CYGWIN__));\n    #endif\n\n    {% for it in preprocessor -%}\n    printf(\"  {{msg}} {{it}}:  %s\\n\",   {{it}} );\n    {%- endfor %}\n\n    {% for it in calls -%}\n    {{it}}();\n    {% endfor %}\n    return 0;\n}\n\"\"\"\n\n\ndef gen_function_c(**context):\n    t = Template(_function_c)\n    return t.render(**context)\n\n\n_function_h = \"\"\"\n#pragma once\n\n{% for it in includes -%}\n#include \"{{it}}.h\"\n{%- endfor %}\n\n#ifdef _WIN32\n  #define {{name.upper()}}_EXPORT __declspec(dllexport)\n#else\n  #define {{name.upper()}}_EXPORT\n#endif\n{{name.upper()}}_EXPORT int {{name}}();\n\"\"\"\n\n\ndef gen_function_h(**context):\n    t = Template(_function_h)\n    return t.render(**context)\n"
  },
  {
    "path": "conan/test/assets/visual_project_files.py",
    "content": "# All harcoded (names, paths etc), refactor it if needed\n\nsln_file = r'''\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio 2013\nVisualStudioVersion = 12.0.31101.0\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"MyProject\", \"MyProject\\MyProject.vcxproj\", \"{143D99A7-C9F3-434F-BA39-514BB63835E8}\"\nEndProject\nGlobal\n    GlobalSection(SolutionConfigurationPlatforms) = preSolution\n        Debug|ARM = Debug|ARM\n        Debug|x64 = Debug|x64\n        Debug|x86 = Debug|x86\n        Release|ARM = Release|ARM\n        Release|x64 = Release|x64\n        Release|x86 = Release|x86\n    EndGlobalSection\n    GlobalSection(ProjectConfigurationPlatforms) = postSolution\n        {143D99A7-C9F3-434F-BA39-514BB63835E8}.Debug|ARM.ActiveCfg = Debug|ARM\n        {143D99A7-C9F3-434F-BA39-514BB63835E8}.Debug|ARM.Build.0 = Debug|ARM\n        {143D99A7-C9F3-434F-BA39-514BB63835E8}.Debug|x64.ActiveCfg = Debug|x64\n        {143D99A7-C9F3-434F-BA39-514BB63835E8}.Debug|x64.Build.0 = Debug|x64\n        {143D99A7-C9F3-434F-BA39-514BB63835E8}.Debug|x86.ActiveCfg = Debug|Win32\n        {143D99A7-C9F3-434F-BA39-514BB63835E8}.Debug|x86.Build.0 = Debug|Win32\n        {143D99A7-C9F3-434F-BA39-514BB63835E8}.Release|ARM.ActiveCfg = Release|ARM\n        {143D99A7-C9F3-434F-BA39-514BB63835E8}.Release|ARM.Build.0 = Release|ARM\n        {143D99A7-C9F3-434F-BA39-514BB63835E8}.Release|x64.ActiveCfg = Release|x64\n        {143D99A7-C9F3-434F-BA39-514BB63835E8}.Release|x64.Build.0 = Release|x64\n        {143D99A7-C9F3-434F-BA39-514BB63835E8}.Release|x86.ActiveCfg = Release|Win32\n        {143D99A7-C9F3-434F-BA39-514BB63835E8}.Release|x86.Build.0 = Release|Win32\n    EndGlobalSection\n    GlobalSection(SolutionProperties) = preSolution\n        HideSolutionNode = FALSE\n    EndGlobalSection\nEndGlobal\n'''\n\nvcxproj_file = r'''<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"14.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"Debug|ARM\">\n      <Configuration>Debug</Configuration>\n      <Platform>ARM</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Debug|x64\">\n      <Configuration>Debug</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|ARM\">\n      <Configuration>Release</Configuration>\n      <Platform>ARM</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|x64\">\n      <Configuration>Release</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>{143D99A7-C9F3-434F-BA39-514BB63835E8}</ProjectGuid>\n    <RootNamespace>MyProject</RootNamespace>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v140</PlatformToolset>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v140</PlatformToolset>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|ARM'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v140</PlatformToolset>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v140</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v140</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|ARM'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v140</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|ARM'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|ARM'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup />\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>Disabled</Optimization>\n      <SDLCheck>true</SDLCheck>\n    </ClCompile>\n    <Link>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>Disabled</Optimization>\n      <SDLCheck>true</SDLCheck>\n    </ClCompile>\n    <Link>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|ARM'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>Disabled</Optimization>\n      <SDLCheck>true</SDLCheck>\n    </ClCompile>\n    <Link>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>MaxSpeed</Optimization>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <SDLCheck>true</SDLCheck>\n    </ClCompile>\n    <Link>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>MaxSpeed</Optimization>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <SDLCheck>true</SDLCheck>\n    </ClCompile>\n    <Link>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|ARM'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>MaxSpeed</Optimization>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <SDLCheck>true</SDLCheck>\n    </ClCompile>\n    <Link>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <ClCompile Include=\"main.cpp\" />\n  </ItemGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n</Project>'''\n\nfilters_file = '''<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <Filter Include=\"Source Files\">\n      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>\n      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>\n    </Filter>\n    <Filter Include=\"Header Files\">\n      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>\n      <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>\n    </Filter>\n    <Filter Include=\"Resource Files\">\n      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>\n      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>\n    </Filter>\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"main.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n  </ItemGroup>\n</Project>'''\n\nmain_file = '''#include <iostream>\n\nint main()\n{\n    std::cout << \"Hello World!\" << std::endl;\n    return 0;\n}\n'''\n\n\ndef get_vs_project_files():\n    return {\"MyProject.sln\": sln_file,\n            \"MyProject/MyProject.vcxproj\": vcxproj_file,\n            \"MyProject/MyProject.vcxproj.filters\": filters_file,\n            \"MyProject/main.cpp\": main_file}\n"
  },
  {
    "path": "conan/test/utils/__init__.py",
    "content": ""
  },
  {
    "path": "conan/test/utils/artifactory.py",
    "content": "import os\nimport time\nimport uuid\n\nimport requests\n\nfrom conan.internal.errors import RecipeNotFoundException, PackageNotFoundException\nfrom conans.server.revision_list import _RevisionEntry\n\nARTIFACTORY_DEFAULT_USER = os.getenv(\"ARTIFACTORY_DEFAULT_USER\", \"admin\")\nARTIFACTORY_DEFAULT_PASSWORD = os.getenv(\"ARTIFACTORY_DEFAULT_PASSWORD\", \"password\")\nARTIFACTORY_DEFAULT_URL = os.getenv(\"ARTIFACTORY_DEFAULT_URL\", \"http://localhost:8090/artifactory\")\n\n\nclass _ArtifactoryServerStore:\n\n    def __init__(self, repo_url, user, password):\n        self._user = user or ARTIFACTORY_DEFAULT_USER\n        self._password = password or ARTIFACTORY_DEFAULT_PASSWORD\n        self._repo_url = repo_url\n\n    @property\n    def _auth(self):\n        return self._user, self._password\n\n    @staticmethod\n    def _root_recipe(ref):\n        return \"{}/{}/{}/{}\".format(ref.user or \"_\", ref.name, ref.version, ref.channel or \"_\")\n\n    @staticmethod\n    def _ref_index(ref):\n        return \"{}/index.json\".format(_ArtifactoryServerStore._root_recipe(ref))\n\n    @staticmethod\n    def _pref_index(pref):\n        tmp = _ArtifactoryServerStore._root_recipe(pref.ref)\n        return \"{}/{}/package/{}/index.json\".format(tmp, pref.ref.revision, pref.package_id)\n\n    def get_recipe_revisions_references(self, ref):\n        time.sleep(0.1)  # Index appears to not being updated immediately after a remove\n        url = \"{}/{}\".format(self._repo_url, self._ref_index(ref))\n        response = requests.get(url, auth=self._auth)\n        response.raise_for_status()\n        the_json = response.json()\n        if not the_json[\"revisions\"]:\n            raise RecipeNotFoundException(ref)\n        tmp = [_RevisionEntry(i[\"revision\"], i[\"time\"]) for i in the_json[\"revisions\"]]\n        return tmp\n\n    def get_package_revisions_references(self, pref):\n        time.sleep(0.1)  # Index appears to not being updated immediately\n        url = \"{}/{}\".format(self._repo_url, self._pref_index(pref))\n        response = requests.get(url, auth=self._auth)\n        response.raise_for_status()\n        the_json = response.json()\n        if not the_json[\"revisions\"]:\n            raise PackageNotFoundException(pref)\n        tmp = [_RevisionEntry(i[\"revision\"], i[\"time\"]) for i in the_json[\"revisions\"]]\n        return tmp\n\n    def get_last_revision(self, ref):\n        revisions = self.get_recipe_revisions_references(ref)\n        return revisions[0]\n\n    def get_last_package_revision(self, ref):\n        revisions = self.get_package_revisions_references(ref)\n        return revisions[0]\n\n\nclass ArtifactoryServer:\n\n    def __init__(self, *args, **kwargs):\n        self._user = ARTIFACTORY_DEFAULT_USER\n        self._password = ARTIFACTORY_DEFAULT_PASSWORD\n        self._url = ARTIFACTORY_DEFAULT_URL\n        self._repo_name = \"conan_{}\".format(str(uuid.uuid4()).replace(\"-\", \"\"))\n        self.create_repository()\n        self.server_store = _ArtifactoryServerStore(self.repo_url, self._user, self._password)\n\n    @property\n    def _auth(self):\n        return self._user, self._password\n\n    @property\n    def repo_url(self):\n        return \"{}/{}\".format(self._url, self._repo_name)\n\n    @property\n    def repo_api_url(self):\n        return \"{}/api/conan/{}\".format(self._url, self._repo_name)\n\n    def package_revision_time(self, pref):\n        revs = self.server_store.get_package_revisions_references(pref)\n        for r in revs:\n            if r.revision == pref.revision:\n                return r.time\n        return None\n\n    def create_repository(self):\n        url = \"{}/api/repositories/{}\".format(self._url, self._repo_name)\n        config = {\"key\": self._repo_name, \"rclass\": \"local\", \"packageType\": \"conan\"}\n        ret = requests.put(url, auth=self._auth, json=config)\n        ret.raise_for_status()\n\n    def package_exists(self, pref):\n        try:\n            revisions = self.server_store.get_package_revisions_references(pref)\n            if pref.revision:\n                for r in revisions:\n                    if pref.revision == r.revision:\n                        return True\n                return False\n            return True\n        except Exception:  # When resolves the latest and there is no package\n            return False\n\n    def recipe_exists(self, ref):\n        try:\n            revisions = self.server_store.get_recipe_revisions_references(ref)\n            if ref.revision:\n                for r in revisions:\n                    if ref.revision == r.revision:\n                        return True\n                return False\n            return True\n        except Exception:  # When resolves the latest and there is no package\n            return False\n"
  },
  {
    "path": "conan/test/utils/env.py",
    "content": "import os\nfrom contextlib import contextmanager\n\n\n@contextmanager\ndef environment_update(env_vars):\n    old_env = dict(os.environ)\n    sets = {k: v for k, v in env_vars.items() if v is not None}\n    unsets = [k for k, v in env_vars.items() if v is None]\n    os.environ.update(sets)\n    for var in unsets:\n        os.environ.pop(var, None)\n    try:\n        yield\n    finally:\n        os.environ.clear()\n        os.environ.update(old_env)\n"
  },
  {
    "path": "conan/test/utils/file_server.py",
    "content": "import os\nimport uuid\n\nimport bottle\nfrom webtest import TestApp\n\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.internal.util.files import mkdir\n\n\nclass TestFileServer:\n    __test__ = False\n\n    def __init__(self, store=None):\n        self.store = store or temp_folder(path_with_spaces=False)\n        mkdir(self.store)\n        self.fake_url = \"http://fake%s.com\" % str(uuid.uuid4()).replace(\"-\", \"\")\n        self.root_app = bottle.Bottle()\n        self.app = TestApp(self.root_app)\n        self._attach_to(self.root_app, self.store)\n\n    @staticmethod\n    def _attach_to(app, store):\n        @app.route(\"/<file>\", method=[\"GET\"])\n        def get(file):\n            if bottle.request.query:  # For a test using ?q\n                file = bottle.request.query[\"q\"]\n            mimetype = \"application/octet-stream\" if file.endswith(\"tgz\") else None\n            return bottle.static_file(file, store, mimetype=mimetype)\n\n        @app.route(\"/<folder>/<file>\", method=[\"PUT\"])\n        def put(folder, file):\n            content = bottle.request.body.read()\n            folder = os.path.join(store, folder)\n            mkdir(folder)\n            with open(os.path.join(folder, file), 'wb') as f:\n                f.write(content)\n\n        @app.route(\"/<folder>/<file>\", method=[\"HEAD\"])\n        def head(folder, file):\n            exists = os.path.exists(os.path.join(store, folder, file))\n            if exists:\n                return bottle.HTTPResponse(status=200)\n            return bottle.HTTPError(404, \"Not found\")\n\n        @app.route(\"/forbidden\", method=[\"GET\"])\n        def get_forbidden():\n            return bottle.HTTPError(403, \"Access denied.\")\n\n        @app.route(\"/basic-auth/<file>\", method=[\"GET\"])\n        def get_user_passwd(file):\n            auth = bottle.request.auth\n            if auth is not None:\n                if auth != (\"user\", \"password\"):\n                    return bottle.HTTPError(401, \"Bad credentials\")\n                return bottle.static_file(file, store)\n\n            auth = bottle.request.headers.get(\"Authorization\")\n            if auth is None or auth != \"Bearer password\":\n                return bottle.HTTPError(401, \"Not authorized\")\n            return bottle.static_file(file, store)\n\n        @app.route(\"/internal_error/<rest>\", method=[\"GET\"])\n        @app.route(\"/internal_error\", method=[\"GET\"])\n        def internal_error():\n            return bottle.HTTPError(500, \"Internal error\")\n\n        @app.route(\"/gz/<file>\", method=[\"GET\"])\n        def get_gz(file):\n            return bottle.static_file(file, store + \"/gz\", mimetype=\"application/octet-stream\")\n\n        @app.route(\"/<folder>/<file>\", method=[\"GET\"])\n        def get_folder(folder, file):\n            return bottle.static_file(file, os.path.join(store, folder))\n\n    def __repr__(self):\n        return \"TestFileServer @ \" + self.fake_url\n"
  },
  {
    "path": "conan/test/utils/mocks.py",
    "content": "from collections import defaultdict\nfrom io import StringIO\n\nfrom conan import ConanFile\nfrom conan.errors import ConanException\nfrom conan.internal.conan_app import ConanFileHelpers\nfrom conan.internal.model.conf import Conf\nfrom conan.internal.model.layout import Folders, Infos\nfrom conan.internal.model.options import Options\n\n\nclass RedirectedInputStream:\n    \"\"\"\n    Mock for testing. If get_username or get_password is requested will raise\n    an exception except we have a value to return.\n    \"\"\"\n\n    def __init__(self, answers: list):\n        self.answers = answers\n\n    def readline(self):\n        if not self.answers:\n            raise Exception(\"\\n\\n**********\\n\\nClass MockedInputStream: \"\n                            \"There are no more inputs to be returned.\\n\"\n                            \"CHECK THE 'inputs=[]' ARGUMENT OF THE TESTCLIENT\\n**********+*\\n\\n\\n\")\n        ret = self.answers.pop(0)\n        return ret\n\n\nclass MockSettings:\n\n    def __init__(self, values):\n        self.values = values\n\n    def get_safe(self, value, default=None):\n        return self.values.get(value, default)\n\n    def __getattr__(self, name):\n        try:\n            return self.values[name]\n        except KeyError:\n            raise ConanException(\"'%s' value not defined\" % name)\n\n    def rm_safe(self, name):\n        self.values.pop(name, None)\n\n    def possible_values(self):\n        return defaultdict(lambda: [])\n\n\nclass ConanFileMock(ConanFile):\n    def __init__(self, settings=None, options=None, runner=None, display_name=\"\"):\n        self.display_name = display_name\n        self._conan_node = None\n        self.package_type = \"unknown\"\n        self.settings = settings or MockSettings({\"os\": \"Linux\", \"arch\": \"x86_64\"})\n        self.settings_build = settings or MockSettings({\"os\": \"Linux\", \"arch\": \"x86_64\"})\n        self.settings_target = None\n        self.runner = runner\n        self.options = options or Options()\n        self.generators = []\n        self.conf = Conf()\n        self.conf_build = Conf()\n        self.folders = Folders()\n        self.folders.set_base_source(\".\")\n        self.folders.set_base_export_sources(\".\")\n        self.folders.set_base_build(\".\")\n        self.folders.set_base_generators(\".\")\n        self.cpp = Infos()\n        self.env_scripts = {}\n        self.system_requires = {}\n        self.win_bash = None\n        self.command = None\n        self._commands = []\n        self._conan_helpers = ConanFileHelpers(None, None, self.conf, None, None, None)\n\n    def run(self, *args, **kwargs):\n        self.command = args[0]\n        self._commands.append(args[0])\n        if self.runner:\n            kwargs.pop(\"quiet\", None)\n            return self.runner(*args, **kwargs)\n        return 0  # simulating it was OK!\n\n    @property\n    def commands(self):\n        result = self._commands\n        self._commands = []\n        return result\n\n\nMockOptions = MockSettings\n\n\nclass RedirectedTestOutput(StringIO):\n    def __init__(self):\n        # Chage to super() for Py3\n        StringIO.__init__(self)\n\n    def clear(self):\n        self.seek(0)\n        self.truncate(0)\n\n    def __repr__(self):\n        return self.getvalue()\n\n    def __str__(self, *args, **kwargs):\n        return self.__repr__()\n\n    def __eq__(self, value):\n        return self.__repr__() == value\n\n    def __contains__(self, value):\n        return value in self.__repr__()\n"
  },
  {
    "path": "conan/test/utils/profiles.py",
    "content": "import os\n\nfrom conan.internal.model.options import Options\nfrom conan.internal.model.profile import Profile\nfrom conan.internal.util.files import save\n\n\ndef create_profile(folder, name, settings=None, package_settings=None, options=None):\n    profile = Profile()\n    profile.settings = settings or {}\n\n    if package_settings:\n        profile.package_settings = package_settings\n\n    if options:\n        profile.options = Options(options_values=options)\n\n    save(os.path.join(folder, name), profile.dumps())\n"
  },
  {
    "path": "conan/test/utils/scm.py",
    "content": "import os\n\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.internal.util.files import save_files, chdir\nfrom conan.internal.util.runners import detect_runner\n\n\ndef git_create_bare_repo(folder=None, reponame=\"repo.git\"):\n    folder = folder or temp_folder()\n    cwd = os.getcwd()\n    try:\n        os.chdir(folder)\n        detect_runner('git init --bare {}'.format(reponame))\n        return os.path.join(folder, reponame).replace(\"\\\\\", \"/\")\n    finally:\n        os.chdir(cwd)\n\n\ndef create_local_git_repo(files=None, branch=None, submodules=None, folder=None, commits=1,\n                          tags=None, origin_url=None, main_branch=\"master\"):\n    tmp = folder or temp_folder()\n    if files:\n        save_files(tmp, files)\n\n    def _run(cmd, p):\n        with chdir(p):\n            _, out = detect_runner(\"git {}\".format(cmd))\n            return out.strip()\n\n    _run(\"init .\", tmp)\n    _run('config user.name \"Your Name\"', tmp)\n    _run('config user.email \"you@example.com\"', tmp)\n    _run(\"checkout -b {}\".format(branch or main_branch), tmp)\n\n    _run(\"add .\", tmp)\n    for i in range(0, commits):\n        _run('commit --allow-empty -m \"commiting\"', tmp)\n\n    tags = tags or []\n    for tag in tags:\n        _run(\"tag %s\" % tag, tmp)\n\n    if submodules:\n        for submodule in submodules:\n            _run('submodule add \"%s\"' % submodule, tmp)\n        _run('commit -m \"add submodules\"', tmp)\n\n    if origin_url:\n        _run('remote add origin {}'.format(origin_url), tmp)\n\n    commit = _run('rev-list HEAD -n 1', tmp)\n    return tmp.replace(\"\\\\\", \"/\"), commit\n\n\ndef git_add_changes_commit(folder, msg=\"fix\"):\n    cwd = os.getcwd()\n    try:\n        os.chdir(folder)\n        # Make sure user and email exist, otherwise it can error\n        detect_runner('git config user.name \"Your Name\"')\n        detect_runner('git config user.email \"you@example.com\"')\n        detect_runner('git add . && git commit -m \"{}\"'.format(msg))\n        _, out = detect_runner(\"git rev-parse HEAD\")\n        return out.strip()\n    finally:\n        os.chdir(cwd)\n"
  },
  {
    "path": "conan/test/utils/server_launcher.py",
    "content": "#!/usr/bin/python\nimport os\nimport shutil\nimport time\n\nfrom conan.internal import REVISIONS\nfrom conans.server import SERVER_CAPABILITIES\nfrom conans.server.conf import get_server_store\nfrom conans.server.crypto.jwt.jwt_credentials_manager import JWTCredentialsManager\nfrom conans.server.migrate import migrate_and_get_server_config\nfrom conans.server.rest.server import ConanServer\nfrom conans.server.service.authorize import BasicAuthenticator, BasicAuthorizer\nfrom conan.test.utils.test_files import temp_folder\n\n\nTESTING_REMOTE_PRIVATE_USER = \"private_user\"\nTESTING_REMOTE_PRIVATE_PASS = \"private_pass\"\n\n\nclass TestServerLauncher:\n\n    def __init__(self, base_path=None, read_permissions=None,\n                 write_permissions=None, users=None, base_url=None, plugins=None,\n                 server_capabilities=None):\n\n        plugins = plugins or []\n        if not base_path:\n            base_path = temp_folder()\n\n        if not os.path.exists(base_path):\n            raise Exception(\"Base path not exist! %s\")\n\n        self._base_path = base_path\n\n        server_config = migrate_and_get_server_config(base_path)\n        if server_capabilities is None:\n            server_capabilities = set(SERVER_CAPABILITIES)\n        elif REVISIONS not in server_capabilities:\n            server_capabilities.append(REVISIONS)\n\n        base_url = base_url or server_config.public_url\n        self.server_store = get_server_store(server_config.disk_storage_path, base_url)\n\n        # Prepare some test users\n        if not read_permissions:\n            read_permissions = server_config.read_permissions\n            read_permissions.append((\"private_library/1.0.0@private_user/testing\", \"*\"))\n            read_permissions.append((\"*/*@*/*\", \"*\"))\n\n        if not write_permissions:\n            write_permissions = server_config.write_permissions\n\n        if not users:\n            users = dict(server_config.users)\n\n        users[TESTING_REMOTE_PRIVATE_USER] = TESTING_REMOTE_PRIVATE_PASS\n\n        authorizer = BasicAuthorizer(read_permissions, write_permissions)\n        authenticator = BasicAuthenticator(users)\n        credentials_manager = JWTCredentialsManager(server_config.jwt_secret,\n                                                    server_config.jwt_expire_time)\n\n        self.port = server_config.port\n        self.ra = ConanServer(self.port, credentials_manager, authorizer, authenticator,\n                              self.server_store, server_capabilities)\n        for plugin in plugins:\n            self.ra.api_v2.install(plugin)\n\n    def start(self, daemon=True):\n        \"\"\"from multiprocessing import Process\n        self.p1 = Process(target=ra.run, kwargs={\"host\": \"0.0.0.0\"})\n        self.p1.start()\n        self.p1\"\"\"\n        import threading\n\n        class StoppableThread(threading.Thread):\n            \"\"\"Thread class with a stop() method. The thread itself has to check\n            regularly for the stopped() condition.\"\"\"\n\n            def __init__(self, *args, **kwargs):\n                super(StoppableThread, self).__init__(*args, **kwargs)\n                self._stop = threading.Event()\n\n            def stop(self):\n                self._stop.set()\n\n            def stopped(self):\n                return self._stop.is_set()\n\n        self.t1 = StoppableThread(target=self.ra.run, kwargs={\"host\": \"0.0.0.0\", \"quiet\": True})\n        self.t1.daemon = daemon\n        self.t1.start()\n        time.sleep(1)\n\n    def stop(self):\n        self.ra.root_app.close()\n        self.t1.stop()\n\n    def clean(self):\n        if os.path.exists(self._base_path):\n            try:\n                shutil.rmtree(self._base_path)\n            except Exception:\n                print(\"Can't clean the test server data, probably a server process is still opened\")\n\n\nif __name__ == \"__main__\":\n    server = TestServerLauncher()\n    server.start(daemon=False)\n"
  },
  {
    "path": "conan/test/utils/test_files.py",
    "content": "import copy\nimport os\nimport platform\nimport shutil\nimport tarfile\nimport tempfile\n\nimport time\nfrom io import BytesIO\n\nfrom conan.internal.api.uploader import gzopen_without_timestamps\nfrom conan.tools.files.files import untargz\nfrom conan.internal.subsystems import get_cased_path\nfrom conan.errors import ConanException\n\n\ndef wait_until_removed(folder):\n    latest_exception = None\n    for _ in range(50):  # Max 5 seconds\n        time.sleep(0.1)\n        try:\n            shutil.rmtree(folder)\n            break\n        except Exception as e:\n            latest_exception = e\n    else:\n        raise Exception(\"Could remove folder %s: %s\" % (folder, latest_exception))\n\n\nCONAN_TEST_FOLDER = os.getenv('CONAN_TEST_FOLDER', None)\nif CONAN_TEST_FOLDER and not os.path.exists(CONAN_TEST_FOLDER):\n    os.makedirs(CONAN_TEST_FOLDER)\n\n\ndef temp_folder(path_with_spaces=True, create_dir=True):\n    t = tempfile.mkdtemp(suffix='conans', dir=CONAN_TEST_FOLDER)\n    # Make sure that the temp folder is correctly cased, as tempfile return lowercase for Win\n    t = get_cased_path(t)\n    # necessary for Mac OSX, where the temp folders in /var/ are symlinks to /private/var/\n    t = os.path.realpath(t)\n    # FreeBSD and Solaris do not use GNU Make as a the default 'make' program which has trouble\n    # with spaces in paths generated by CMake\n    if not path_with_spaces or platform.system() == \"FreeBSD\" or platform.system() == \"SunOS\":\n        path = \"pathwithoutspaces\"\n    else:\n        path = \"path with spaces\"\n    nt = os.path.join(t, path)\n    if create_dir:\n        os.makedirs(nt)\n    return nt\n\n\ndef uncompress_packaged_files(paths, pref):\n    _tmp = copy.copy(pref)\n    _tmp.revision = None\n    prev = paths.get_last_package_revision(_tmp).revision\n    pref.revision = prev\n\n    package_path = paths.package(pref)\n    PACKAGE_TGZ_NAME = \"conan_package.tgz\"\n    if not (os.path.exists(os.path.join(package_path, PACKAGE_TGZ_NAME))):\n        raise ConanException(\"%s not found in %s\" % (PACKAGE_TGZ_NAME, package_path))\n    tmp = temp_folder()\n    untargz(os.path.join(package_path, PACKAGE_TGZ_NAME), tmp)\n    return tmp\n\n\ndef scan_folder(folder):\n    scanned_files = []\n    for root, dirs, files in os.walk(folder):\n        dirs[:] = [d for d in dirs if d != \"__pycache__\"]\n        relative_path = os.path.relpath(root, folder)\n        for f in files:\n            if f.endswith(\".pyc\"):\n                continue\n            relative_name = os.path.normpath(os.path.join(relative_path, f)).replace(\"\\\\\", \"/\")\n            scanned_files.append(relative_name)\n\n    return sorted(scanned_files)\n\n\ndef tgz_with_contents(files, output_path=None):\n    folder = temp_folder()\n    file_path = output_path or os.path.join(folder, \"myfile.tar.gz\")\n\n    with open(file_path, \"wb\") as tgz_handle:\n        tgz = gzopen_without_timestamps(\"myfile.tar.gz\", fileobj=tgz_handle)\n\n        for name, content in files.items():\n            info = tarfile.TarInfo(name=name)\n            data = content.encode('utf-8')\n            info.size = len(data)\n            tgz.addfile(tarinfo=info, fileobj=BytesIO(data))\n\n        tgz.close()\n\n    return file_path\n"
  },
  {
    "path": "conan/test/utils/tools.py",
    "content": "import copy\nimport json\nimport os\nimport platform\nimport re\nimport shlex\nimport shutil\nimport socket\nimport sys\nimport textwrap\nimport traceback\nimport uuid\nimport zipfile\nimport subprocess\nfrom contextlib import contextmanager\nfrom inspect import getframeinfo, stack\nfrom urllib.parse import urlsplit, urlunsplit\n\nfrom unittest import mock\nimport pytest\nimport requests\nfrom unittest.mock import Mock\nfrom requests.exceptions import HTTPError\nfrom webtest.app import TestApp\n\nfrom conan.api.subapi.audit import CONAN_CENTER_AUDIT_PROVIDER_NAME, _save_providers\nfrom conan.api.subapi.remotes import _save\nfrom conan.cli.exit_codes import SUCCESS\nfrom conan.internal.cache.cache import PackageLayout, RecipeLayout, PkgCache\nfrom conan.internal.cache.home_paths import HomePaths\nfrom conan.internal import REVISIONS\nfrom conan.api.conan_api import ConanAPI\nfrom conan.api.model import Remote\nfrom conan.cli.cli import Cli, _CONAN_INTERNAL_CUSTOM_COMMANDS_PATH\nfrom conan.internal.model.conf import load_global_conf\nfrom conan.test.utils.env import environment_update\nfrom conan.internal.errors import NotFoundException\nfrom conan.api.model import PkgReference\nfrom conan.api.model import RecipeReference\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.artifactory import ArtifactoryServer\nfrom conan.test.utils.mocks import RedirectedInputStream\nfrom conan.test.utils.mocks import RedirectedTestOutput\nfrom conan.test.utils.scm import create_local_git_repo\nfrom conan.test.utils.server_launcher import (TestServerLauncher)\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.internal.util.files import mkdir, save_files, save, load\n\nNO_SETTINGS_PACKAGE_ID = \"da39a3ee5e6b4b0d3255bfef95601890afd80709\"\n\narch = platform.machine()\narch_setting = \"armv8\" if arch in [\"arm64\", \"aarch64\"] else arch\ndefault_profiles = {\n    \"Windows\": textwrap.dedent(\"\"\"\\\n        [settings]\n        os=Windows\n        arch=x86_64\n        compiler=msvc\n        compiler.version=191\n        compiler.runtime=dynamic\n        build_type=Release\n        \"\"\"),\n    \"Linux\": textwrap.dedent(f\"\"\"\\\n        [settings]\n        os=Linux\n        arch={arch_setting}\n        compiler=gcc\n        compiler.version=8\n        compiler.libcxx=libstdc++11\n        build_type=Release\n        \"\"\"),\n    \"Darwin\": textwrap.dedent(f\"\"\"\\\n        [settings]\n        os=Macos\n        arch={arch_setting}\n        compiler=apple-clang\n        compiler.version=17\n        compiler.libcxx=libc++\n        build_type=Release\n        \"\"\")\n}\n\n\nclass TestingResponse:\n    \"\"\"Wraps a response from TestApp external tool\n    to guarantee the presence of response.ok, response.content\n    and response.status_code, as it was a requests library object.\n\n    Is instanced by TestRequester on each request\"\"\"\n\n    def __init__(self, test_response):\n        self.test_response = test_response\n\n    def close(self):\n        pass  # Compatibility with close() method of a requests when stream=True\n\n    @property\n    def headers(self):\n        return self.test_response.headers\n\n    @property\n    def ok(self):\n        return self.test_response.status_code == 200\n\n    def raise_for_status(self):\n        \"\"\"Raises stored :class:`HTTPError`, if one occurred.\"\"\"\n        http_error_msg = ''\n        if 400 <= self.status_code < 500:\n            http_error_msg = u'%s Client Error: %s' % (self.status_code, self.content)\n\n        elif 500 <= self.status_code < 600:\n            http_error_msg = u'%s Server Error: %s' % (self.status_code, self.content)\n\n        if http_error_msg:\n            raise HTTPError(http_error_msg, response=self)\n\n    @property\n    def content(self):\n        return self.test_response.body\n\n    @property\n    def charset(self):\n        return self.test_response.charset\n\n    @charset.setter\n    def charset(self, newcharset):\n        self.test_response.charset = newcharset\n\n    @property\n    def text(self):\n        return self.test_response.text\n\n    def iter_content(self, chunk_size=1):  # @UnusedVariable\n        return [self.content]\n\n    @property\n    def status_code(self):\n        return self.test_response.status_code\n\n    def json(self):\n        try:\n            return json.loads(self.test_response.content)\n        except:\n            raise ValueError(\"The response is not a JSON\")\n\n\nclass TestRequester:\n    \"\"\"Fake requests module calling server applications\n    with TestApp\"\"\"\n\n    def __init__(self, test_servers):\n        self.test_servers = test_servers\n        self.utils = Mock()\n        self.utils.default_user_agent.return_value = \"TestRequester Agent\"\n\n    @staticmethod\n    def _get_url_path(url):\n        # Remove schema from url\n        _, _, path, query, _ = urlsplit(url)\n        url = urlunsplit((\"\", \"\", path, query, \"\"))\n        return url\n\n    def _get_wsgi_app(self, url):\n        for test_server in self.test_servers.values():\n            if url.startswith(test_server.fake_url):\n                return test_server.app\n\n        raise Exception(\"Testing error: Not remote found\")\n\n    def get(self, url, **kwargs):\n        app, url = self._prepare_call(url, kwargs)\n        if app:\n            response = app.get(url, **kwargs)\n            return TestingResponse(response)\n        else:\n            return requests.get(url, **kwargs)\n\n    def put(self, url, **kwargs):\n        app, url = self._prepare_call(url, kwargs)\n        if app:\n            response = app.put(url, **kwargs)\n            return TestingResponse(response)\n        else:\n            return requests.put(url, **kwargs)\n\n    def head(self, url, **kwargs):\n        app, url = self._prepare_call(url, kwargs)\n        if app:\n            response = app.head(url, **kwargs)\n            return TestingResponse(response)\n        else:\n            return requests.head(url, **kwargs)\n\n    def delete(self, url, **kwargs):\n        app, url = self._prepare_call(url, kwargs)\n        if app:\n            response = app.delete(url, **kwargs)\n            return TestingResponse(response)\n        else:\n            return requests.delete(url, **kwargs)\n\n    def post(self, url, **kwargs):\n        app, url = self._prepare_call(url, kwargs)\n        if app:\n            response = app.post(url, **kwargs)\n            return TestingResponse(response)\n        else:\n            requests.post(url, **kwargs)\n\n    def _prepare_call(self, url, kwargs):\n        if not url.startswith(\"http://fake\"):  # Call to S3 (or external), perform a real request\n            return None, url\n        app = self._get_wsgi_app(url)\n        url = self._get_url_path(url)  # Remove http://server.com\n\n        self._set_auth_headers(kwargs)\n\n        if app:\n            kwargs[\"expect_errors\"] = True\n            kwargs.pop(\"stream\", None)\n            kwargs.pop(\"verify\", None)\n            kwargs.pop(\"source_credentials\", None)\n            auth = kwargs.pop(\"auth\", None)\n            if auth and isinstance(auth, tuple):\n                app.set_authorization((\"Basic\", auth))\n            kwargs.pop(\"cert\", None)\n            kwargs.pop(\"timeout\", None)\n            if \"data\" in kwargs:\n                total_data = kwargs[\"data\"].read()\n                kwargs[\"params\"] = total_data\n                del kwargs[\"data\"]  # Parameter in test app is called \"params\"\n            if kwargs.get(\"json\"):\n                # json is a high level parameter of requests, not a generic one\n                # translate it to data and content_type\n                kwargs[\"params\"] = json.dumps(kwargs[\"json\"])\n                kwargs[\"content_type\"] = \"application/json\"\n            kwargs.pop(\"json\", None)\n\n        return app, url\n\n    @staticmethod\n    def _set_auth_headers(kwargs):\n        if kwargs.get(\"auth\"):\n            if isinstance(kwargs.get(\"auth\"), tuple):  # For download(..., auth=(user, paswd))\n                return\n            mock_request = Mock()\n            mock_request.headers = {}\n            kwargs[\"auth\"](mock_request)\n            if kwargs.get(\"headers\") is None:\n                kwargs[\"headers\"] = {}\n            kwargs[\"headers\"].update(mock_request.headers)\n\n    def mount(self, *args, **kwargs):\n        pass\n\n    def Session(self):\n        return self\n\n    @property\n    def codes(self):\n        return requests.codes\n\n\nclass TestServer:\n    __test__ = False\n\n    def __init__(self, read_permissions=None,\n                 write_permissions=None, users=None, plugins=None, base_path=None,\n                 server_capabilities=None, complete_urls=False):\n        \"\"\"\n             'read_permissions' and 'write_permissions' is a list of:\n                 [(\"opencv/2.3.4@lasote/testing\", \"user1, user2\")]\n\n             'users':  {username: plain-text-passwd}\n        \"\"\"\n        # Unique identifier for this server, will be used by TestRequester\n        # to determine where to call. Why? remote_manager just assing an url\n        # to the rest_client, so rest_client doesn't know about object instances,\n        # just urls, so testing framework performs a map between fake urls and instances\n        if read_permissions is None:\n            read_permissions = [(\"*/*@*/*\", \"*\")]\n        if write_permissions is None:\n            write_permissions = [(\"*/*@*/*\", \"*\")]\n        if users is None:\n            users = {\"admin\": \"password\"}\n\n        if server_capabilities is None:\n            server_capabilities = [REVISIONS]\n        elif REVISIONS not in server_capabilities:\n            server_capabilities.append(REVISIONS)\n\n        self.fake_url = \"http://fake%s.com\" % str(uuid.uuid4()).replace(\"-\", \"\")\n        base_url = \"%s/v1\" % self.fake_url if complete_urls else \"v1\"\n        self.test_server = TestServerLauncher(base_path, read_permissions,\n                                              write_permissions, users,\n                                              base_url=base_url,\n                                              plugins=plugins,\n                                              server_capabilities=server_capabilities)\n        self.app = TestApp(self.test_server.ra.root_app)\n\n    @property\n    def server_store(self):\n        return self.test_server.server_store\n\n    def __repr__(self):\n        return \"TestServer @ \" + self.fake_url\n\n    def __str__(self):\n        return self.fake_url\n\n    def recipe_exists(self, ref):\n        try:\n            if not ref.revision:\n                path = self.test_server.server_store.conan_revisions_root(ref)\n            else:\n                path = self.test_server.server_store.base_folder(ref)\n            return self.test_server.server_store.path_exists(path)\n        except NotFoundException:  # When resolves the latest and there is no package\n            return False\n\n    def package_exists(self, pref):\n        try:\n            if pref.revision:\n                path = self.test_server.server_store.package(pref)\n            else:\n                path = self.test_server.server_store.package_revisions_root(pref)\n            return self.test_server.server_store.path_exists(path)\n        except NotFoundException:  # When resolves the latest and there is no package\n            return False\n\n    def latest_recipe(self, ref):\n        ref = self.test_server.server_store.get_last_revision(ref)\n        return ref\n\n    def latest_package(self, pref):\n        if not pref.ref.revision:\n            raise Exception(\"Pass a pref with .rev.revision (Testing framework)\")\n        prev = self.test_server.server_store.get_last_package_revision(pref)\n        _tmp = copy.copy(prev)\n        _tmp.revision = prev\n        return _tmp\n\n    def package_revision_time(self, pref):\n        if not pref:\n            raise Exception(\"Pass a pref with revision (Testing framework)\")\n        tmp = self.test_server.server_store.get_package_revision_time(pref)\n        return tmp\n\n\nif os.environ.get(\"CONAN_TEST_WITH_ARTIFACTORY\"):\n    TestServer = ArtifactoryServer\n\n\n@contextmanager\ndef redirect_output(stderr, stdout=None):\n    original_stdout = sys.stdout\n    original_stderr = sys.stderr\n    # TODO: change in 2.0\n    # redirecting both of them to the same target for the moment\n    # to assign to Testclient out\n    sys.stdout = stdout or stderr\n    sys.stderr = stderr\n    try:\n        yield\n    finally:\n        sys.stdout = original_stdout\n        sys.stderr = original_stderr\n\n\n@contextmanager\ndef redirect_input(target):\n    original_stdin = sys.stdin\n    sys.stdin = target\n    try:\n        yield\n    finally:\n        sys.stdin = original_stdin\n\n\nclass TestClient:\n    \"\"\" Test wrap of the conans application to launch tests in the same way as\n    in command line\n    \"\"\"\n    # Preventing Pytest collects any tests from here\n    __test__ = False\n\n    def __init__(self, cache_folder=None, current_folder=None, servers=None, inputs=None,\n                 requester_class=None, path_with_spaces=True,\n                 default_server_user=None, light=False, custom_commands_folder=None):\n        \"\"\"\n        current_folder: Current execution folder\n        servers: dict of {remote_name: TestServer}\n        logins is a list of (user, password) for auto input in order\n        if required==> [(\"lasote\", \"mypass\"), (\"other\", \"otherpass\")]\n        \"\"\"\n        if default_server_user is not None:\n            assert isinstance(default_server_user, bool), \\\n                \"default_server_user has to be True or False\"\n            if servers is not None:\n                raise Exception(\"Cannot define both 'servers' and 'default_server_user'\")\n            if inputs is not None:\n                raise Exception(\"Cannot define both 'inputs' and 'default_server_user'\")\n\n            server_users = {\"admin\": \"password\"}\n            inputs = [\"admin\", \"password\"]\n\n            # Allow writing permissions to users\n            server = TestServer(users=server_users, write_permissions=[(\"*/*@*/*\", \"*\")])\n            servers = {\"default\": server}\n\n        # Adding the .conan2, so we know clearly while debugging this is a cache folder\n        self.cache_folder = cache_folder or os.path.join(temp_folder(path_with_spaces), \".conan2\")\n\n        self.requester_class = requester_class\n        self.servers = servers or {}\n        if servers is not False:  # Do not mess with registry remotes\n            self.update_servers()\n\n        self.update_providers()\n        self.current_folder = current_folder or temp_folder(path_with_spaces)\n\n        # Once the client is ready, modify the configuration\n        mkdir(self.current_folder)\n\n        self.out = \"\"\n        self.stdout = RedirectedTestOutput()\n        self.stderr = RedirectedTestOutput()\n        self.user_inputs = RedirectedInputStream([])\n        self.inputs = inputs or []\n\n        # create default profile\n        if light:\n            text = \"[settings]\\nos=Linux\"  # Needed at least build-os\n            save(self.paths.settings_path, \"os: [Linux, Windows]\")\n        else:\n            text = default_profiles[platform.system()]\n        save(os.path.join(self.cache_folder, \"profiles\", \"default\"), text)\n        # Using internal env variable to add another custom commands folder\n        self._custom_commands_folder = custom_commands_folder\n\n    def load(self, filename):\n        return load(os.path.join(self.current_folder, filename))\n\n    def load_home(self, filename):\n        try:\n            return load(os.path.join(self.cache_folder, filename))\n        except IOError:\n            return None\n\n    def open(self, filename):\n        # CI is set by default by GitHub Actions\n        if os.environ.get(\"CI\", False):\n            assert False, \"TestClient::open should not be used in CI\"\n\n        current_path = os.path.join(self.current_folder, filename)\n        if platform.system() == \"Windows\":\n            os.startfile(os.path.normpath(current_path))\n        elif platform.system() == \"Darwin\":\n            subprocess.call([\"open\", current_path])\n        else:\n            subprocess.call([\"xdg-open\", current_path])\n\n    def open_home(self, filename):\n        return self.open(os.path.join(self.cache_folder, filename))\n\n    @property\n    def cache(self) -> PkgCache:\n        # Returns a temporary cache object intended for inspecting it\n        return PkgCache(self.cache_folder, load_global_conf(self.cache_folder))\n\n    @property\n    def paths(self):\n        return HomePaths(self.cache_folder)\n\n    @property\n    def base_folder(self):\n        # Temporary hack to refactor ConanApp with less changes\n        return self.cache_folder\n\n    @property\n    def storage_folder(self):\n        return self.cache.store\n\n    def update_servers(self):\n        remotes = []\n        for name, server in self.servers.items():\n            if isinstance(server, ArtifactoryServer):\n                remotes.append(Remote(name, server.repo_api_url))\n            elif isinstance(server, TestServer):\n                remotes.append(Remote(name, server.fake_url))\n            else:\n                remotes.append(Remote(name, server))\n        _save(HomePaths(self.cache_folder).remotes_path, remotes)\n\n\n    def update_providers(self):\n        default_providers = {\n            CONAN_CENTER_AUDIT_PROVIDER_NAME: {\n                \"url\": \"https://fakeurl/\",\n                \"type\": \"conan-center-proxy\"\n            }\n        }\n        _save_providers(HomePaths(self.cache_folder).providers_path, default_providers)\n\n    @contextmanager\n    def chdir(self, newdir):\n        old_dir = self.current_folder\n        if not os.path.isabs(newdir):\n            newdir = os.path.join(old_dir, newdir)\n        mkdir(newdir)\n        self.current_folder = newdir\n        try:\n            yield\n        finally:\n            self.current_folder = old_dir\n\n    @contextmanager\n    def mocked_servers(self, requester=None):\n        _req = requester or TestRequester(self.servers)\n        with mock.patch(\"conan.internal.rest.conan_requester.requests\", _req):\n            yield\n\n    @contextmanager\n    def mocked_io(self):\n        def mock_get_pass(*args, **kwargs):\n            return self.user_inputs.readline()\n\n        with redirect_output(self.stderr, self.stdout):\n            with redirect_input(self.user_inputs):\n                with mock.patch(\"getpass.getpass\", mock_get_pass):\n                    yield\n\n    def _run_cli(self, command_line, assert_error=False):\n        args = shlex.split(command_line)\n        error = SUCCESS\n        trace = None\n        # save state\n        current_dir = os.getcwd()\n        os.chdir(self.current_folder)\n        old_path = sys.path[:]\n        old_modules = list(sys.modules.keys())\n        try:\n            self.api = ConanAPI(cache_folder=self.cache_folder)\n            command = Cli(self.api)\n            if self._custom_commands_folder:\n                with environment_update({_CONAN_INTERNAL_CUSTOM_COMMANDS_PATH:\n                                         self._custom_commands_folder}):\n                    command.run(args)\n            else:\n                command.run(args)\n        except BaseException as e:  # Capture all exceptions as argparse\n            trace = traceback.format_exc()\n            error = Cli.exception_exit_error(e)\n        finally:\n            sys.path = old_path\n            os.chdir(current_dir)\n            # Reset sys.modules to its prev state. A .copy() DOES NOT WORK\n            added_modules = set(sys.modules).difference(old_modules)\n            for added in added_modules:\n                sys.modules.pop(added, None)\n        self._handle_cli_result(command_line, assert_error=assert_error, error=error, trace=trace)\n        return error\n\n    def run(self, command_line, assert_error=False, redirect_stdout=None, redirect_stderr=None, inputs=None):\n        \"\"\" run a single command as in the command line.\n            If user or password is filled, user_io will be mocked to return this\n            tuple if required\n        \"\"\"\n        from conan.test.utils.mocks import RedirectedTestOutput\n        with environment_update({\"NO_COLOR\": \"1\"}):  # Not initialize colorama in testing\n            self.user_inputs = RedirectedInputStream(inputs or self.inputs)\n            self.stdout = RedirectedTestOutput()  # Initialize each command\n            self.stderr = RedirectedTestOutput()\n            self.out = \"\"\n            with self.mocked_io():\n                real_servers = any(isinstance(s, (str, ArtifactoryServer))\n                                   for s in self.servers.values())\n                http_requester = None\n                if not real_servers:\n                    if self.requester_class:\n                        http_requester = self.requester_class(self.servers)\n                    else:\n                        http_requester = TestRequester(self.servers)\n\n                try:\n                    if http_requester:\n                        with self.mocked_servers(http_requester):\n                            return self._run_cli(command_line, assert_error=assert_error)\n                    else:\n                        return self._run_cli(command_line, assert_error=assert_error)\n                finally:\n                    self.stdout = str(self.stdout)\n                    self.stderr = str(self.stderr)\n                    self.out = self.stderr + self.stdout\n                    if redirect_stdout:\n                        save(os.path.join(self.current_folder, redirect_stdout), self.stdout)\n                    if redirect_stderr:\n                        save(os.path.join(self.current_folder, redirect_stderr), self.stderr)\n\n    def run_command(self, command, cwd=None, assert_error=False):\n        from conan.test.utils.mocks import RedirectedTestOutput\n        self.stdout = RedirectedTestOutput()  # Initialize each command\n        self.stderr = RedirectedTestOutput()\n        try:\n            with redirect_output(self.stderr, self.stdout):\n                from conan.internal.util.runners import conan_run\n                ret = conan_run(command, cwd=cwd or self.current_folder)\n        finally:\n            self.stdout = str(self.stdout)\n            self.stderr = str(self.stderr)\n            self.out = self.stderr + self.stdout\n        self._handle_cli_result(command, assert_error=assert_error, error=ret)\n        return ret\n\n    def _handle_cli_result(self, command, assert_error, error, trace=None):\n        if (assert_error and not error) or (not assert_error and error):\n            if assert_error:\n                msg = \" Command succeeded (failure expected): \"\n            else:\n                msg = \" Command failed (unexpectedly): \"\n\n            output = str(self.stderr) + str(self.stdout) + \"\\n\"\n            exc_message = f\"\\n{msg:=^80}\\n{command}\\n{' Output: ':=^80}\\n{output}\\n\"\n            if trace:\n                exc_message += f'{\" Traceback: \":=^80}\\n{trace}'\n\n            caller = getframeinfo(stack()[3][0])\n            exc_message = f\"{caller.filename}:{caller.lineno}\" + exc_message\n            pytest.fail(exc_message, pytrace=False)\n\n    def save(self, files, path=None, clean_first=False):\n        \"\"\" helper metod, will store files in the current folder\n        param files: dict{filename: filecontents}\n        \"\"\"\n        path = path or self.current_folder\n        if clean_first:\n            shutil.rmtree(self.current_folder, ignore_errors=True)\n        files = {f: str(content) for f, content in files.items()}\n        save_files(path, files)\n        if not files:\n            mkdir(self.current_folder)\n\n    def save_home(self, files):\n        self.save(files, path=self.cache_folder)\n\n    # Higher level operations\n    def remove_all(self):\n        self.run(\"remove '*' -c\")\n\n    def export(self, ref, conanfile=GenConanfile(), args=None):\n        \"\"\" export a ConanFile with as \"ref\" and return the reference with recipe revision\n        \"\"\"\n        if conanfile:\n            self.save({\"conanfile.py\": conanfile})\n        if ref:\n            self.run(f\"export . --name={ref.name} --version={ref.version} --user={ref.user} --channel={ref.channel}\")\n        else:\n            self.run(\"export .\")\n        tmp = copy.copy(ref)\n        tmp.revision = None\n        rrev = self.cache.get_latest_recipe_revision(tmp).revision\n        tmp = copy.copy(ref)\n        tmp.revision = rrev\n        return tmp\n\n    def alias(self, source, target):\n        \"\"\"\n        creates a new recipe with \"conan new alias\" template, \"conan export\" it, and remove it\n        @param source: the reference of the current recipe\n        @param target: the target reference that this recipe is pointing (aliasing to)\n        \"\"\"\n        source = RecipeReference.loads(source)\n        target = target.split(\"/\", 1)[1]\n        self.run(f\"new alias -d name={source.name} -d version={source.version} \"\n                 f\"-d target={target} -f\")\n        user = f\"--user={source.user}\" if source.user else \"\"\n        channel = f\"--channel={source.channel}\" if source.channel else \"\"\n        self.run(f\"export . {user} {channel}\")\n        os.remove(os.path.join(self.current_folder, \"conanfile.py\"))\n\n    def init_git_repo(self, files=None, branch=None, submodules=None, folder=None, origin_url=None,\n                      main_branch=\"master\"):\n        if folder is not None:\n            folder = os.path.join(self.current_folder, folder)\n        else:\n            folder = self.current_folder\n        _, commit = create_local_git_repo(files, branch, submodules, folder=folder,\n                                          origin_url=origin_url, main_branch=main_branch)\n        return commit\n\n    def get_latest_package_reference(self, ref, package_id=None) -> PkgReference:\n        \"\"\"Get the latest PkgReference given a ConanReference\"\"\"\n        ref_ = RecipeReference.loads(ref) if isinstance(ref, str) else ref\n        latest_rrev = self.cache.get_latest_recipe_revision(ref_)\n        if package_id:\n            pref = PkgReference(latest_rrev, package_id)\n        else:\n            package_ids = self.cache.get_package_references(latest_rrev)\n            # Let's check if there are several packages because we don't want random behaviours\n            assert len(package_ids) == 1, f\"There are several packages for {latest_rrev}, please, \" \\\n                                          f\"provide a single package_id instead\" \\\n                                          if len(package_ids) > 0 else \"No binary packages found\"\n            pref = package_ids[0]\n        return self.cache.get_latest_package_revision(pref)\n\n    def get_latest_pkg_layout(self, pref: PkgReference) -> PackageLayout:\n        \"\"\"Get the latest PackageLayout given a file reference\"\"\"\n        # Let's make it easier for all the test clients\n        latest_prev = self.cache.get_latest_package_revision(pref)\n        pkg_layout = self.cache.pkg_layout(latest_prev)\n        return pkg_layout\n\n    def get_latest_ref_layout(self, ref) -> RecipeLayout:\n        \"\"\"Get the latest RecipeLayout given a file reference\"\"\"\n        if not ref.revision:\n            ref = self.cache.get_latest_recipe_revision(ref)\n        ref_layout = self.cache.recipe_layout(ref)\n        return ref_layout\n\n    def get_default_host_profile(self):\n        api = ConanAPI(cache_folder=self.cache_folder)\n        return api.profiles.get_profile([api.profiles.get_default_host()])\n\n    def get_default_build_profile(self):\n        api = ConanAPI(cache_folder=self.cache_folder)\n        return api.profiles.get_profile([api.profiles.get_default_build()])\n\n    def recipe_exists(self, ref):\n        rrev = self.cache.get_recipe_revisions(ref)\n        return True if rrev else False\n\n    def package_exists(self, pref):\n        prev = self.cache.get_package_revisions(pref)\n        return True if prev else False\n\n    def assert_listed_require(self, requires, build=False, python=False, test=False,\n                              test_package=False):\n        \"\"\" parses the current command output, and extract the first \"Requirements\" section\n        \"\"\"\n        lines = self.out.splitlines()\n        if test_package:\n            line_req = lines.index(\"======== Launching test_package ========\")\n            lines = lines[line_req:]\n        header = \"Requirements\" if not build else \"Build requirements\"\n        if python:\n            header = \"Python requires\"\n        if test:\n            header = \"Test requirements\"\n        line_req = lines.index(header)\n        reqs = []\n        for line in lines[line_req+1:]:\n            if not line.startswith(\"    \"):\n                break\n            reqs.append(line.strip())\n        for r, kind in requires.items():\n            for req in reqs:\n                if req.startswith(r) and req.endswith(kind):\n                    break\n            else:\n                raise AssertionError(f\"Cant find {r}-{kind} in {reqs}\")\n\n    def assert_overrides(self, overrides):\n        \"\"\" parses the current command output, and extract the first \"Requirements\" section\n        \"\"\"\n        lines = self.out.splitlines()\n        header = \"Overrides\"\n        line_req = lines.index(header)\n        reqs = []\n        for line in lines[line_req+1:]:\n            if not line.startswith(\"    \"):\n                break\n            reqs.append(line.strip())\n        for r, o in overrides.items():\n            msg = f\"{r}: {o}\"\n            if msg not in reqs:\n                raise AssertionError(f\"Cant find {msg} in {reqs}\")\n\n    def assert_listed_binary(self, requires, build=False, test=False, test_package=False):\n        \"\"\" parses the current command output, and extract the second \"Requirements\" section\n        belonging to the computed package binaries\n        \"\"\"\n        lines = self.out.splitlines()\n        if test_package:\n            line_req = lines.index(\"======== Launching test_package ========\")\n            lines = lines[line_req:]\n        line_req = lines.index(\"======== Computing necessary packages ========\")\n        header = \"Requirements\" if not build else \"Build requirements\"\n        if test:\n            header = \"Test requirements\"\n        line_req = lines.index(header, line_req)\n\n        reqs = []\n        for line in lines[line_req+1:]:\n            if not line.startswith(\"    \"):\n                break\n            reqs.append(line.strip())\n        for r, kind in requires.items():\n            package_id, binary = kind\n            for req in reqs:\n                if req.startswith(r) and package_id in req and req.endswith(binary):\n                    break\n            else:\n                raise AssertionError(f\"Cant find {r}-{kind} in {reqs}\")\n\n    def created_test_build_folder(self, ref):\n        build_folder = re.search(r\"{} \\(test package\\): Test package build: (.*)\".format(str(ref)),\n                                 str(self.out)).group(1)\n        return build_folder.replace(\"\\\\\", \"/\")\n\n    def created_package_id(self, ref):\n        package_id = re.search(r\"{}: Package '(\\S+)' created\".format(str(ref)),\n                               str(self.out)).group(1)\n        return package_id\n\n    def created_package_revision(self, ref):\n        package_id = re.search(r\"{}: Created package revision (\\S+)\".format(str(ref)),\n                               str(self.out)).group(1)\n        return package_id\n\n    def created_package_reference(self, ref):\n        pref = re.search(r\"{}: Full package reference: (\\S+)\".format(str(ref)),\n                               str(self.out)).group(1)\n        return PkgReference.loads(pref)\n\n    def exported_recipe_revision(self):\n        return re.search(r\": Exported: .*#(\\S+)\", str(self.out)).group(1)\n\n    def exported_layout(self):\n        m = re.search(r\": Exported: (\\S+)\", str(self.out)).group(1)\n        ref = RecipeReference.loads(m)\n        return self.cache.recipe_layout(ref)\n\n    def created_layout(self):\n        pref = re.search(r\"(?s:.*)Full package reference: (\\S+)\", str(self.out)).group(1)\n        pref = PkgReference.loads(pref)\n        return self.cache.pkg_layout(pref)\n\n\ndef get_free_port():\n    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n    sock.bind(('localhost', 0))\n    ret = sock.getsockname()[1]\n    sock.close()\n    return ret\n\n\ndef zipdir(path, zipfilename):\n    with zipfile.ZipFile(zipfilename, 'w', zipfile.ZIP_DEFLATED) as z:\n        for root, _, files in os.walk(path):\n            for f in files:\n                file_path = os.path.join(root, f)\n                if file_path == zipfilename:\n                    continue\n                relpath = os.path.relpath(file_path, path)\n                z.write(file_path, relpath)\n"
  },
  {
    "path": "conan/tools/__init__.py",
    "content": "from conan.internal.model.cpp_info import CppInfo as _CppInfo\n\n\ndef CppInfo(conanfile):\n    # Creation of a CppInfo object, to decouple the creation from the actual internal location\n    # that at the moment doesn't require a ``conanfile`` argument, but might require in the future\n    # and allow us to refactor the location of conans.model.build_info import CppInfo\n    return _CppInfo()\n"
  },
  {
    "path": "conan/tools/android/__init__.py",
    "content": "from conan.tools.android.utils import android_abi\n"
  },
  {
    "path": "conan/tools/android/utils.py",
    "content": "from conan.errors import ConanException\n\n\ndef android_abi(conanfile, context=\"host\"):\n    \"\"\"\n    Returns Android-NDK ABI\n\n    :param conanfile: ConanFile instance\n    :param context: either \"host\", \"build\" or \"target\"\n    :return: Android-NDK ABI\n    \"\"\"\n    if context not in (\"host\", \"build\", \"target\"):\n        raise ConanException(f\"context argument must be either 'host', 'build' or 'target', \"\n                             f\"was '{context}'\")\n\n    try:\n        settings = getattr(conanfile, f\"settings_{context}\")\n    except AttributeError:\n        if context == \"host\":\n            settings = conanfile.settings\n        else:\n            raise ConanException(f\"settings_{context} not declared in recipe\")\n    if settings is None:\n        raise ConanException(f\"settings_{context}=None in recipe\")\n    arch = settings.get_safe(\"arch\")\n    # https://cmake.org/cmake/help/latest/variable/CMAKE_ANDROID_ARCH_ABI.html\n    return {\n        \"armv5el\": \"armeabi\",\n        \"armv5hf\": \"armeabi\",\n        \"armv5\": \"armeabi\",\n        \"armv6\": \"armeabi-v6\",\n        \"armv7\": \"armeabi-v7a\",\n        \"armv7hf\": \"armeabi-v7a\",\n        \"armv8\": \"arm64-v8a\",\n    }.get(arch, arch)\n"
  },
  {
    "path": "conan/tools/apple/__init__.py",
    "content": "# Keep everything private until we review what is really needed and refactor passing \"conanfile\"\n# from conan.tools.apple.apple import apple_dot_clean\n# from conan.tools.apple.apple import apple_sdk_name\n# from conan.tools.apple.apple import apple_deployment_target_flag\nfrom conan.tools.apple.apple import fix_apple_shared_install_name, is_apple_os, to_apple_arch, XCRun\nfrom conan.tools.apple.xcodedeps import XcodeDeps\nfrom conan.tools.apple.xcodebuild import XcodeBuild\nfrom conan.tools.apple.xcodetoolchain import XcodeToolchain\n"
  },
  {
    "path": "conan/tools/apple/apple.py",
    "content": "import os\nfrom io import StringIO\n\nfrom conan.internal.internal_tools import universal_arch_separator\nfrom conan.internal.util.runners import check_output_runner\nfrom conan.tools.build import cmd_args_to_string\nfrom conan.errors import ConanException\n\n\ndef is_apple_os(conanfile, build_context=False):\n    \"\"\"returns True if OS is Apple one (Macos, iOS, watchOS, tvOS or visionOS)\"\"\"\n    settings = conanfile.settings_build if build_context else conanfile.settings\n    return str(settings.get_safe(\"os\")) in ['Macos', 'iOS', 'watchOS', 'tvOS', 'visionOS']\n\n\ndef _to_apple_arch(arch, default=None):\n    \"\"\"converts conan-style architecture into Apple-style arch\"\"\"\n    return {'x86': 'i386',\n            'x86_64': 'x86_64',\n            'armv7': 'armv7',\n            'armv8': 'arm64',\n            'armv8_32': 'arm64_32',\n            'armv8.3': 'arm64e',\n            'armv7s': 'armv7s',\n            'armv7k': 'armv7k'}.get(str(arch), default)\n\n\ndef to_apple_arch(conanfile, default=None):\n    \"\"\"converts conan-style architecture into Apple-style arch\"\"\"\n    arch_ = conanfile.settings.get_safe(\"arch\")\n    return _to_apple_arch(arch_, default)\n\n\ndef apple_sdk_path(conanfile, is_cross_building=True):\n    sdk_path = conanfile.conf.get(\"tools.apple:sdk_path\")\n    if not sdk_path:\n        # XCRun already knows how to extract os.sdk from conanfile.settings\n        sdk_path = XCRun(conanfile).sdk_path\n    if not sdk_path and is_cross_building:\n        raise ConanException(\n            \"Apple SDK path not found. For cross-compilation, you must \"\n            \"provide a valid SDK path in 'tools.apple:sdk_path' config.\"\n        )\n    return sdk_path\n\n\ndef get_apple_sdk_fullname(conanfile):\n    \"\"\"\n    Returns the 'os.sdk' + 'os.sdk_version ' value. Every user should specify it because\n    there could be several ones depending on the OS architecture.\n\n    Note: In case of MacOS it'll be the same for all the architectures.\n    \"\"\"\n    os_ = conanfile.settings.get_safe('os')\n    os_sdk = conanfile.settings.get_safe('os.sdk')\n    os_sdk_version = conanfile.settings.get_safe('os.sdk_version') or \"\"\n    if os_sdk:\n        return \"{}{}\".format(os_sdk, os_sdk_version)\n    elif os_ == \"Macos\":  # it has only a single value for all the architectures\n        return \"{}{}\".format(\"macosx\", os_sdk_version)\n    elif is_apple_os(conanfile):\n        raise ConanException(\"Please, specify a suitable value for os.sdk.\")\n\n\ndef apple_min_version_flag(conanfile):\n    \"\"\"compiler flag name which controls deployment target\"\"\"\n    os_ = conanfile.settings.get_safe('os')\n    os_sdk = conanfile.settings.get_safe('os.sdk')\n    os_sdk = os_sdk or (\"macosx\" if os_ == \"Macos\" else None)\n    os_version = conanfile.settings.get_safe(\"os.version\")\n    if not os_sdk or not os_version:\n        # Legacy behavior\n        return \"\"\n    if conanfile.settings.get_safe(\"os.subsystem\") == 'catalyst':\n        os_sdk = \"iphoneos\"\n    return {\n        \"macosx\": f\"-mmacosx-version-min={os_version}\",\n        \"iphoneos\": f\"-mios-version-min={os_version}\",\n        \"iphonesimulator\": f\"-mios-simulator-version-min={os_version}\",\n        \"watchos\": f\"-mwatchos-version-min={os_version}\",\n        \"watchsimulator\": f\"-mwatchos-simulator-version-min={os_version}\",\n        \"appletvos\": f\"-mtvos-version-min={os_version}\",\n        \"appletvsimulator\": f\"-mtvos-simulator-version-min={os_version}\",\n        \"xros\": f\"--target=arm64-apple-xros{os_version}\",\n        \"xrsimulator\": f\"--target=arm64-apple-xros{os_version}-simulator\",\n    }.get(os_sdk, \"\")\n\n\ndef resolve_apple_flags(conanfile, is_cross_building=False, is_universal=False):\n    \"\"\"\n    Gets the most common flags in Apple systems. If it's a cross-building context\n    SDK path is mandatory so if it could raise an exception if SDK is not found.\n\n    :param conanfile: <ConanFile> instance.\n    :param is_cross_building: boolean to indicate if it's a cross-building context.\n    :param is_universal: boolean to indicate if it's a universal binary.\n    :return: tuple of Apple flags (apple_min_version_flag, apple_arch_flags, apple_isysroot_flag).\n    \"\"\"\n    if not is_apple_os(conanfile):\n        # Keeping legacy defaults\n        return \"\", None, None\n\n    apple_arch_flags = apple_isysroot_flag = None\n\n    if is_universal:\n        arch_ = conanfile.settings.get_safe(\"arch\")\n        apple_arch_flags = \" \".join([f\"-arch {_to_apple_arch(arch, default=arch)}\" for arch in\n                                     arch_.split(universal_arch_separator)])\n        sdk_path = conanfile.conf.get(\"tools.apple:sdk_path\")\n        if sdk_path:\n            # Ideally, -isysroot should be added whenever sdk_path is defined.\n            # For now, we only set it in this case to avoid changing existing behavior.\n            apple_isysroot_flag = f\"-isysroot {sdk_path}\"\n    elif is_cross_building:\n        arch = to_apple_arch(conanfile)\n        sdk_path = apple_sdk_path(conanfile, is_cross_building=is_cross_building)\n        apple_isysroot_flag = f\"-isysroot {sdk_path}\" if sdk_path else \"\"\n        apple_arch_flags = f\"-arch {arch}\" if arch else \"\"\n\n    min_version_flag = apple_min_version_flag(conanfile)\n    return min_version_flag, apple_arch_flags, apple_isysroot_flag\n\n\ndef xcodebuild_deployment_target_key(os_name):\n    return {\n        \"Macos\": \"MACOSX_DEPLOYMENT_TARGET\",\n        \"iOS\": \"IPHONEOS_DEPLOYMENT_TARGET\",\n        \"tvOS\": \"TVOS_DEPLOYMENT_TARGET\",\n        \"watchOS\": \"WATCHOS_DEPLOYMENT_TARGET\",\n        \"visionOS\": \"XROS_DEPLOYMENT_TARGET\",\n    }.get(os_name) if os_name else None\n\n\nclass XCRun:\n    \"\"\"\n    XCRun is a wrapper for the Apple **xcrun** tool used to get information for building.\n    \"\"\"\n\n    def __init__(self, conanfile, sdk=None, use_settings_target=False):\n        \"\"\"\n        :param conanfile: Conanfile instance.\n        :param sdk: Will skip the flag when ``False`` is passed and will try to adjust the\n            sdk it automatically if ``None`` is passed.\n        :param use_settings_target: Try to use ``settings_target`` in case they exist\n                                    (``False`` by default)\n        \"\"\"\n        settings = conanfile.settings\n        if use_settings_target and conanfile.settings_target is not None:\n            settings = conanfile.settings_target\n\n        if sdk is None and settings:\n            sdk = settings.get_safe('os.sdk')\n\n        self._conanfile = conanfile\n        self.settings = settings\n        self.sdk = sdk\n\n    def _invoke(self, args):\n        command = ['xcrun']\n        if self.sdk:\n            command.extend(['-sdk', self.sdk])\n        command.extend(args)\n        output = StringIO()\n        cmd_str = cmd_args_to_string(command)\n        self._conanfile.run(f\"{cmd_str}\", stdout=output, quiet=True)\n        return output.getvalue().strip()\n\n    def find(self, tool):\n        \"\"\"find SDK tools (e.g. clang, ar, ranlib, lipo, codesign, etc.)\"\"\"\n        return self._invoke(['--find', tool])\n\n    @property\n    def sdk_path(self):\n        \"\"\"obtain sdk path (aka apple sysroot or -isysroot\"\"\"\n        return self._invoke(['--show-sdk-path'])\n\n    @property\n    def sdk_version(self):\n        \"\"\"obtain sdk version\"\"\"\n        return self._invoke(['--show-sdk-version'])\n\n    @property\n    def sdk_platform_path(self):\n        \"\"\"obtain sdk platform path\"\"\"\n        return self._invoke(['--show-sdk-platform-path'])\n\n    @property\n    def sdk_platform_version(self):\n        \"\"\"obtain sdk platform version\"\"\"\n        return self._invoke(['--show-sdk-platform-version'])\n\n    @property\n    def cc(self):\n        \"\"\"path to C compiler (CC)\"\"\"\n        return self.find('clang')\n\n    @property\n    def cxx(self):\n        \"\"\"path to C++ compiler (CXX)\"\"\"\n        return self.find('clang++')\n\n    @property\n    def ar(self):\n        \"\"\"path to archiver (AR)\"\"\"\n        return self.find('ar')\n\n    @property\n    def ranlib(self):\n        \"\"\"path to archive indexer (RANLIB)\"\"\"\n        return self.find('ranlib')\n\n    @property\n    def strip(self):\n        \"\"\"path to symbol removal utility (STRIP)\"\"\"\n        return self.find('strip')\n\n    @property\n    def libtool(self):\n        \"\"\"path to libtool\"\"\"\n        return self.find('libtool')\n\n    @property\n    def otool(self):\n        \"\"\"path to otool\"\"\"\n        return self.find('otool')\n\n    @property\n    def install_name_tool(self):\n        \"\"\"path to install_name_tool\"\"\"\n        return self.find('install_name_tool')\n\n\ndef _get_dylib_install_name(otool, path_to_dylib):\n    command = f\"{otool} -D {path_to_dylib}\"\n    output = iter(check_output_runner(command).splitlines())\n    # Note: if otool return multiple entries for different architectures\n    # assume they are the same and pick the first one.\n    for line in output:\n        if \":\" in line:\n            return next(output)\n    raise ConanException(f\"Unable to extract install_name for {path_to_dylib}\")\n\n\ndef fix_apple_shared_install_name(conanfile):\n    \"\"\"\n    Search for all the *dylib* files in the conanfile's *package_folder* and fix\n    both the ``LC_ID_DYLIB`` and ``LC_LOAD_DYLIB`` fields on those files using the\n    *install_name_tool* utility available in macOS to set ``@rpath``.\n    \"\"\"\n\n    if not is_apple_os(conanfile):\n        return\n\n    xcrun = XCRun(conanfile)\n    otool = xcrun.otool\n    install_name_tool = xcrun.install_name_tool\n\n    def _darwin_is_binary(file, binary_type):\n        if binary_type not in (\"DYLIB\", \"EXECUTE\") or os.path.islink(file) or os.path.isdir(file):\n            return False\n        check_file = f\"{otool} -hv {file}\"\n        return binary_type in check_output_runner(check_file)\n\n    def _darwin_collect_binaries(folder, binary_type):\n        return [os.path.join(folder, f) for f in os.listdir(folder)\n                if _darwin_is_binary(os.path.join(folder, f), binary_type)]\n\n    def _fix_install_name(dylib_path, new_name):\n        command = f\"{install_name_tool} {dylib_path} -id {new_name}\"\n        conanfile.run(command)\n\n    def _fix_dep_name(dylib_path, old_name, new_name):\n        command = f\"{install_name_tool} {dylib_path} -change {old_name} {new_name}\"\n        conanfile.run(command)\n\n    def _get_rpath_entries(binary_file):\n        entries = []\n        command = f\"{otool} -l {binary_file}\"\n        otool_output = check_output_runner(command).splitlines()\n        for count, text in enumerate(otool_output):\n            pass\n            if \"LC_RPATH\" in text:\n                rpath_entry = otool_output[count+2].split(\"path \")[1].split(\" \")[0]\n                entries.append(rpath_entry)\n        return entries\n\n    def _get_shared_dependencies(binary_file):\n        command = f\"{otool} -L {binary_file}\"\n        all_shared = check_output_runner(command).strip().split(\":\")[1].strip()\n        ret = [s.split(\"(\")[0].strip() for s in all_shared.splitlines()]\n        return ret\n\n    def _fix_dylib_files():\n        substitutions = {}\n        libdirs = getattr(conanfile.cpp.package, \"libdirs\")\n        for libdir in libdirs:\n            full_folder = os.path.join(conanfile.package_folder, libdir)\n            if not os.path.exists(full_folder):\n                raise ConanException(f\"Trying to locate shared libraries, but `{libdir}` \"\n                                     f\" not found inside package folder {conanfile.package_folder}\")\n            shared_libs = _darwin_collect_binaries(full_folder, \"DYLIB\")\n            # fix LC_ID_DYLIB in first pass\n            for shared_lib in shared_libs:\n                install_name = _get_dylib_install_name(otool, shared_lib)\n                # TODO: we probably only want to fix the install the name if\n                # it starts with `/`.\n                rpath_name = f\"@rpath/{os.path.basename(install_name)}\"\n                _fix_install_name(shared_lib, rpath_name)\n                substitutions[install_name] = rpath_name\n\n            # fix dependencies in second pass\n            for shared_lib in shared_libs:\n                for old, new in substitutions.items():\n                    _fix_dep_name(shared_lib, old, new)\n\n        return substitutions\n\n    def _fix_executables(substitutions):\n        # Fix the install name for executables inside the package\n        # that reference libraries we just patched\n        bindirs = getattr(conanfile.cpp.package, \"bindirs\")\n        for bindir in bindirs:\n            full_folder = os.path.join(conanfile.package_folder, bindir)\n            if not os.path.exists(full_folder):\n                # Skip if the folder does not exist inside the package\n                # (e.g. package does not contain executables but bindirs is defined)\n                continue\n            executables = _darwin_collect_binaries(full_folder, \"EXECUTE\")\n            for executable in executables:\n\n                # Fix install names of libraries from within the same package\n                deps = _get_shared_dependencies(executable)\n                for dep in deps:\n                    dep_base = os.path.join(os.path.dirname(dep),\n                                            os.path.basename(dep).split('.')[0])\n                    match = [k for k in substitutions.keys() if k.startswith(dep_base)]\n                    if match:\n                        _fix_dep_name(executable, dep, substitutions[match[0]])\n\n                # Add relative rpath to library directories, avoiding possible\n                # existing duplicates\n                libdirs = getattr(conanfile.cpp.package, \"libdirs\")\n                libdirs = [os.path.join(conanfile.package_folder, libdir) for libdir in libdirs]\n                rel_paths = [f\"@executable_path/{os.path.relpath(libdir, full_folder)}\"\n                             for libdir in libdirs]\n                existing_rpaths = _get_rpath_entries(executable)\n                rpaths_to_add = list(set(rel_paths) - set(existing_rpaths))\n                for entry in rpaths_to_add:\n                    command = f\"{install_name_tool} {executable} -add_rpath {entry}\"\n                    conanfile.run(command)\n\n    substitutes = _fix_dylib_files()\n\n    # Only \"fix\" executables if dylib files were patched, otherwise\n    # there is nothing to do.\n    if substitutes:\n        _fix_executables(substitutes)\n\n\ndef apple_extra_flags(conanfile):\n    if not is_apple_os(conanfile):\n        return []\n    enable_bitcode = conanfile.conf.get(\"tools.apple:enable_bitcode\", check_type=bool)\n    enable_visibility = conanfile.conf.get(\"tools.apple:enable_visibility\", check_type=bool)\n    is_debug = conanfile.settings.get_safe('build_type') == \"Debug\"\n    flags = []\n    if enable_bitcode:\n        if is_debug:\n            flags.append(\"-fembed-bitcode-marker\")\n        else:\n            flags.append(\"-fembed-bitcode\")\n    if enable_visibility:\n        flags.append(\"-fvisibility=default\")\n    if enable_visibility is False:\n        flags.extend([\"-fvisibility=hidden\", \"-fvisibility-inlines-hidden\"])\n    return flags\n"
  },
  {
    "path": "conan/tools/apple/xcodebuild.py",
    "content": "from conan.tools.apple.apple import to_apple_arch, xcodebuild_deployment_target_key\nfrom conan.tools.build import cmd_args_to_string\n\n\nclass XcodeBuild:\n    def __init__(self, conanfile):\n        self._conanfile = conanfile\n        self._build_type = conanfile.settings.get_safe(\"build_type\")\n        self._arch = to_apple_arch(self._conanfile)\n        self._sdk = conanfile.settings.get_safe(\"os.sdk\") or \"\"\n        self._sdk_version = conanfile.settings.get_safe(\"os.sdk_version\") or \"\"\n        self._os = conanfile.settings.get_safe(\"os\")\n        self._os_version = conanfile.settings.get_safe(\"os.version\")\n\n    @property\n    def _verbosity(self):\n        verbosity = self._conanfile.conf.get(\"tools.build:verbosity\", choices=(\"quiet\", \"verbose\")) \\\n                    or self._conanfile.conf.get(\"tools.compilation:verbosity\",\n                                                choices=(\"quiet\", \"verbose\"))\n        return \"-\" + verbosity if verbosity is not None else \"\"\n\n    @property\n    def _sdkroot(self):\n        # User's sdk_path has priority, then if specified try to compose sdk argument\n        # with sdk/sdk_version settings, leave blank otherwise and the sdk will be automatically\n        # chosen by the build system\n        sdk = self._conanfile.conf.get(\"tools.apple:sdk_path\")\n        if not sdk and self._sdk:\n            sdk = \"{}{}\".format(self._sdk, self._sdk_version)\n        return \"SDKROOT={}\".format(sdk) if sdk else \"\"\n\n    def build(self, xcodeproj, target=None, configuration=None, cli_args=None):\n        \"\"\"\n        Call to ``xcodebuild`` to build a Xcode project.\n\n        :param xcodeproj: the *xcodeproj* file to build.\n        :param target: the target to build, in case this argument is passed to the ``build()``\n                       method it will add the ``-target`` argument to the build system call. If not passed, it\n                       will build all the targets passing the ``-alltargets`` argument instead.\n        :param configuration: Build configuration to use (e.g., ``Debug``, ``Release``).\n                              Defaults to the recipe's ``settings.build_type``.\n        :param cli_args: Extra options to pass directly to ``xcodebuild`` (list of strings).\n                              Examples: ``[\"-xcconfig\", \"<path/to/file.xcconfig>\"]`` or custom\n                              Xcode build settings like ``[\"BUILD_LIBRARY_FOR_DISTRIBUTION=YES\"]``.\n        :return: the return code for the launched ``xcodebuild`` command.\n        \"\"\"\n        target = \"-target '{}'\".format(target) if target else \"-alltargets\"\n        build_config = configuration or self._build_type\n        cmd = \"xcodebuild -project '{}' -configuration {} -arch {} \" \\\n              \"{} {} {}\".format(xcodeproj, build_config, self._arch, self._sdkroot,\n                                self._verbosity, target)\n        deployment_target_key = xcodebuild_deployment_target_key(self._os)\n        if deployment_target_key and self._os_version:\n            cmd += f\" {deployment_target_key}={self._os_version}\"\n\n        if cli_args:\n            cmd += \" \" + cmd_args_to_string(cli_args)\n\n        self._conanfile.run(cmd)\n"
  },
  {
    "path": "conan/tools/apple/xcodedeps.py",
    "content": "import os\nimport re\nimport textwrap\nfrom collections import OrderedDict\n\nfrom jinja2 import Template\n\nfrom conan.internal import check_duplicated_generator\nfrom conan.errors import ConanException\nfrom conan.internal.model.dependencies import get_transitive_requires\nfrom conan.internal.util.files import load, save\nfrom conan.tools.apple.apple import _to_apple_arch\n\nGLOBAL_XCCONFIG_TEMPLATE = textwrap.dedent(\"\"\"\\\n    // Includes both the toolchain and the dependencies\n    // files if they exist\n\n    \"\"\")\n\nGLOBAL_XCCONFIG_FILENAME = \"conan_config.xcconfig\"\n\n\ndef _format_name(name):\n    return re.sub(r'[^A-Za-z0-9_]', '_', name).lower()\n\n\ndef _xcconfig_settings_filename(settings, configuration):\n    arch = settings.get_safe(\"arch\")\n    architecture = _to_apple_arch(arch) or arch\n    props = [(\"configuration\", configuration),\n             (\"architecture\", architecture),\n             (\"sdk name\", settings.get_safe(\"os.sdk\")),\n             (\"sdk version\", settings.get_safe(\"os.sdk_version\"))]\n    name = \"\".join(\"_{}\".format(v) for _, v in props if v is not None and v)\n    return _format_name(name)\n\n\ndef _xcconfig_conditional(settings, configuration):\n    sdk_condition = \"*\"\n    arch = settings.get_safe(\"arch\")\n    architecture = _to_apple_arch(arch) or arch\n    sdk = settings.get_safe(\"os.sdk\") if settings.get_safe(\"os\") != \"Macos\" else \"macosx\"\n    if sdk:\n        sdk_condition = \"{}{}\".format(sdk, settings.get_safe(\"os.sdk_version\") or \"*\")\n\n    return \"[config={}][arch={}][sdk={}]\".format(configuration, architecture, sdk_condition)\n\n\ndef _add_includes_to_file_or_create(filename, template, files_to_include):\n    if os.path.isfile(filename):\n        content = load(filename)\n    else:\n        content = template\n\n    for include in files_to_include:\n        if include not in content:\n            content = content + '#include \"{}\"\\n'.format(include)\n\n    return content\n\n\nclass XcodeDeps:\n    general_name = \"conandeps.xcconfig\"\n\n    _conf_xconfig = textwrap.dedent(\"\"\"\\\n        PACKAGE_ROOT_{{pkg_name}}{{condition}} = {{root}}\n        // Compiler options for {{pkg_name}}::{{comp_name}}\n        SYSTEM_HEADER_SEARCH_PATHS_{{pkg_name}}_{{comp_name}}{{condition}} = {{include_dirs}}\n        GCC_PREPROCESSOR_DEFINITIONS_{{pkg_name}}_{{comp_name}}{{condition}} = {{definitions}}\n        OTHER_CFLAGS_{{pkg_name}}_{{comp_name}}{{condition}} = {{c_compiler_flags}}\n        OTHER_CPLUSPLUSFLAGS_{{pkg_name}}_{{comp_name}}{{condition}} = {{cxx_compiler_flags}}\n        FRAMEWORK_SEARCH_PATHS_{{pkg_name}}_{{comp_name}}{{condition}} = {{frameworkdirs}}\n\n        // Link options for {{pkg_name}}::{{comp_name}}\n        LIBRARY_SEARCH_PATHS_{{pkg_name}}_{{comp_name}}{{condition}} = {{lib_dirs}}\n        OTHER_LDFLAGS_{{pkg_name}}_{{comp_name}}{{condition}} = {{linker_flags}} {{libs}} {{system_libs}} {{frameworks}}\n        \"\"\")\n\n    _dep_xconfig = textwrap.dedent(\"\"\"\\\n        // Conan XcodeDeps generated file for {{pkg_name}}::{{comp_name}}\n        // Includes all configurations for each dependency\n        {% for include in deps_includes %}\n        #include \"{{include}}\"\n        {% endfor %}\n        #include \"{{dep_xconfig_filename}}\"\n\n        SYSTEM_HEADER_SEARCH_PATHS = $(inherited) $(SYSTEM_HEADER_SEARCH_PATHS_{{pkg_name}}_{{comp_name}})\n        GCC_PREPROCESSOR_DEFINITIONS = $(inherited) $(GCC_PREPROCESSOR_DEFINITIONS_{{pkg_name}}_{{comp_name}})\n        OTHER_CFLAGS = $(inherited) $(OTHER_CFLAGS_{{pkg_name}}_{{comp_name}})\n        OTHER_CPLUSPLUSFLAGS = $(inherited) $(OTHER_CPLUSPLUSFLAGS_{{pkg_name}}_{{comp_name}})\n        FRAMEWORK_SEARCH_PATHS = $(inherited) $(FRAMEWORK_SEARCH_PATHS_{{pkg_name}}_{{comp_name}})\n\n        // Link options for {{pkg_name}}_{{comp_name}}\n        LIBRARY_SEARCH_PATHS = $(inherited) $(LIBRARY_SEARCH_PATHS_{{pkg_name}}_{{comp_name}})\n        OTHER_LDFLAGS = $(inherited) $(OTHER_LDFLAGS_{{pkg_name}}_{{comp_name}})\n        \"\"\")\n\n    _all_xconfig = textwrap.dedent(\"\"\"\\\n        // Conan XcodeDeps generated file\n        // Includes all direct dependencies\n        \"\"\")\n\n    _pkg_xconfig = textwrap.dedent(\"\"\"\\\n        // Conan XcodeDeps generated file\n        // Includes all components for the package\n        \"\"\")\n\n    def __init__(self, conanfile):\n        self._conanfile = conanfile\n        self.configuration = conanfile.settings.get_safe(\"build_type\")\n        arch = conanfile.settings.get_safe(\"arch\")\n        self.architecture = _to_apple_arch(arch, default=arch)\n        self.os_version = conanfile.settings.get_safe(\"os.version\")\n        self.sdk = conanfile.settings.get_safe(\"os.sdk\")\n        self.sdk_version = conanfile.settings.get_safe(\"os.sdk_version\")\n\n    def generate(self):\n        check_duplicated_generator(self, self._conanfile)\n        if self.configuration is None:\n            raise ConanException(\"XcodeDeps.configuration is None, it should have a value\")\n        if self.architecture is None:\n            raise ConanException(\"XcodeDeps.architecture is None, it should have a value\")\n        generator_files = self._content()\n        for generator_file, content in generator_files.items():\n            save(generator_file, content)\n\n    def _conf_xconfig_file(self, require, pkg_name, comp_name, package_folder, transitive_cpp_infos):\n        \"\"\"\n        content for conan_poco_x86_release.xcconfig, containing the activation\n        \"\"\"\n        def _merged_vars(name):\n            merged = [var for cpp_info in transitive_cpp_infos for var in getattr(cpp_info, name)]\n            return list(OrderedDict.fromkeys(merged).keys())\n\n        # TODO: Investigate if paths can be made relative to \"root\" folder\n        fields = {\n            'pkg_name': pkg_name,\n            'comp_name': comp_name,\n            'root': package_folder,\n            'include_dirs': \" \".join('\"{}\"'.format(p) for p in _merged_vars(\"includedirs\")),\n            'lib_dirs': \" \".join('\"{}\"'.format(p) for p in _merged_vars(\"libdirs\")),\n            'libs': \" \".join(\"-l{}\".format(lib) for lib in _merged_vars(\"libs\")),\n            'system_libs': \" \".join(\"-l{}\".format(sys_lib) for sys_lib in _merged_vars(\"system_libs\")),\n            'frameworkdirs': \" \".join('\"{}\"'.format(p) for p in _merged_vars(\"frameworkdirs\")),\n            'frameworks': \" \".join(\"-framework {}\".format(framework) for framework in _merged_vars(\"frameworks\")),\n            'definitions': \" \".join('\"{}\"'.format(p.replace('\"', '\\\\\"')) for p in _merged_vars(\"defines\")),\n            'c_compiler_flags': \" \".join('\"{}\"'.format(p.replace('\"', '\\\\\"')) for p in _merged_vars(\"cflags\")),\n            'cxx_compiler_flags': \" \".join('\"{}\"'.format(p.replace('\"', '\\\\\"')) for p in _merged_vars(\"cxxflags\")),\n            'linker_flags': \" \".join('\"{}\"'.format(p.replace('\"', '\\\\\"')) for p in _merged_vars(\"sharedlinkflags\")),\n            'exe_flags': \" \".join('\"{}\"'.format(p.replace('\"', '\\\\\"')) for p in _merged_vars(\"exelinkflags\")),\n            'condition': _xcconfig_conditional(self._conanfile.settings, self.configuration)\n        }\n\n        if not require.headers:\n            fields[\"include_dirs\"] = \"\"\n\n        if not require.libs:\n            fields[\"lib_dirs\"] = \"\"\n            fields[\"libs\"] = \"\"\n            fields[\"system_libs\"] = \"\"\n            fields[\"frameworkdirs\"] = \"\"\n            fields[\"frameworks\"] = \"\"\n\n        if not require.libs and not require.headers:\n            fields[\"definitions\"] = \"\"\n            fields[\"c_compiler_flags\"] = \"\"\n            fields[\"cxx_compiler_flags\"] = \"\"\n            fields[\"linker_flags\"] = \"\"\n            fields[\"exe_flags\"] = \"\"\n\n        template = Template(self._conf_xconfig)\n        content_multi = template.render(**fields)\n        return content_multi\n\n    def _dep_xconfig_file(self, pkg_name, comp_name, name_general, dep_xconfig_filename, reqs):\n        # Current directory is the generators_folder\n        multi_path = name_general\n        if os.path.isfile(multi_path):\n            content_multi = load(multi_path)\n        else:\n            content_multi = self._dep_xconfig\n\n            def _get_includes(components):\n                # if we require the root component dep::dep include conan_dep.xcconfig\n                # for components (dep::component) include conan_dep_component.xcconfig\n                return [f\"conan_{_format_name(component[0])}.xcconfig\" if component[0] == component[1]\n                        else f\"conan_{_format_name(component[0])}_{_format_name(component[1])}.xcconfig\"\n                        for component in components]\n\n            content_multi = Template(content_multi).render({\"pkg_name\": pkg_name,\n                                                            \"comp_name\": comp_name,\n                                                            \"dep_xconfig_filename\": dep_xconfig_filename,\n                                                            \"deps_includes\": _get_includes(reqs)})\n\n        if dep_xconfig_filename not in content_multi:\n            content_multi = content_multi.replace('.xcconfig\"',\n                                                  '.xcconfig\"\\n#include \"{}\"'.format(dep_xconfig_filename),\n                                                  1)\n\n        return content_multi\n\n    def _all_xconfig_file(self, deps, content):\n        \"\"\"\n        this is a .xcconfig file including all declared dependencies\n        \"\"\"\n        content_multi = content or self._all_xconfig\n\n        for dep in deps.values():\n            include_file = f'conan_{_format_name(dep.ref.name)}.xcconfig'\n            if include_file not in content_multi:\n                content_multi = content_multi + f'\\n#include \"{include_file}\"\\n'\n        return content_multi\n\n    def _pkg_xconfig_file(self, components):\n        \"\"\"\n        this is a .xcconfig file including the components for each package\n        \"\"\"\n        content_multi = self._pkg_xconfig\n        for pkg_name, comp_name in components:\n            content_multi = content_multi + '\\n#include \"conan_{}_{}.xcconfig\"\\n'.format(pkg_name,\n                                                                                         comp_name)\n        return content_multi\n\n    @property\n    def _global_xconfig_content(self):\n        return _add_includes_to_file_or_create(GLOBAL_XCCONFIG_FILENAME,\n                                               GLOBAL_XCCONFIG_TEMPLATE,\n                                               [self.general_name])\n\n    def get_content_for_component(self, require, pkg_name, component_name, package_folder, transitive_internal, transitive_external):\n        result = {}\n\n        conf_name = _xcconfig_settings_filename(self._conanfile.settings, self.configuration)\n\n        props_name = \"conan_{}_{}{}.xcconfig\".format(pkg_name, component_name, conf_name)\n        result[props_name] = self._conf_xconfig_file(require, pkg_name, component_name, package_folder, transitive_internal)\n\n        # The entry point for each package\n        file_dep_name = \"conan_{}_{}.xcconfig\".format(pkg_name, component_name)\n        dep_content = self._dep_xconfig_file(pkg_name, component_name, file_dep_name, props_name, transitive_external)\n\n        result[file_dep_name] = dep_content\n        return result\n\n    def _content(self):\n        result = {}\n\n        # Generate the config files for each component with name conan_pkgname_compname.xcconfig\n        # If a package has no components the name is conan_pkgname_pkgname.xcconfig\n        # All components are included in the conan_pkgname.xcconfig file\n        host_req = self._conanfile.dependencies.host\n        test_req = self._conanfile.dependencies.test\n        requires = list(host_req.items()) + list(test_req.items())\n        for require, dep in requires:\n\n            dep_name = _format_name(dep.ref.name)\n\n            include_components_names = []\n            transitive_requires = [r for r, _ in\n                                   get_transitive_requires(self._conanfile, dep).items()]\n            if dep.cpp_info.has_components:\n                transitive_dep_names = [_format_name(dep.ref.name) for dep in transitive_requires]\n\n                sorted_components = dep.cpp_info.get_sorted_components().items()\n                for comp_name, comp_cpp_info in sorted_components:\n                    comp_name = _format_name(comp_name)\n\n                    # returns: (\"list of cpp infos from required components in same package\",\n                    #           \"list of names from required components from other packages\")\n                    def _get_component_requires(component):\n                        requires_external = [(req.split(\"::\")[0], req.split(\"::\")[1]) for req in\n                                             component.requires if \"::\" in req\n                                             and req.split(\"::\")[0] in transitive_dep_names]\n                        requires_internal = [dep.cpp_info.components.get(req) for req in\n                                             component.requires if \"::\" not in req]\n                        return requires_internal, requires_external\n\n                    # these are the transitive dependencies between components of the same package\n                    transitive_internal = []\n                    # these are the transitive dependencies to components from other packages\n                    transitive_external = []\n\n                    # return the internal cpp_infos and external components names\n                    def _transitive_components(component):\n                        requires_internal, requires_external = _get_component_requires(component)\n                        transitive_internal.append(component)\n                        transitive_internal.extend(requires_internal)\n                        transitive_external.extend(requires_external)\n                        for treq in requires_internal:\n                            _transitive_components(treq)\n\n                    _transitive_components(comp_cpp_info)\n\n                    # remove duplicates\n                    transitive_internal = list(OrderedDict.fromkeys(transitive_internal).keys())\n                    transitive_external = list(OrderedDict.fromkeys(transitive_external).keys())\n\n                    # In case dep is editable and package_folder=None\n                    pkg_folder = dep.package_folder or dep.recipe_folder\n                    component_content = self.get_content_for_component(require, dep_name, comp_name,\n                                                                       pkg_folder,\n                                                                       transitive_internal,\n                                                                       transitive_external)\n                    include_components_names.append((dep_name, comp_name))\n                    result.update(component_content)\n            else:\n                public_deps = []\n                for r, d in dep.dependencies.direct_host.items():\n                    if r not in transitive_requires:\n                        continue\n                    if d.cpp_info.has_components:\n                        sorted_components = d.cpp_info.get_sorted_components().items()\n                        for comp_name, comp_cpp_info in sorted_components:\n                            public_deps.append((_format_name(d.ref.name), _format_name(comp_name)))\n                    else:\n                        public_deps.append((_format_name(d.ref.name),) * 2)\n\n                required_components = dep.cpp_info.required_components if dep.cpp_info.required_components else public_deps\n                # In case dep is editable and package_folder=None\n                pkg_folder = dep.package_folder or dep.recipe_folder\n                root_content = self.get_content_for_component(require, dep_name, dep_name, pkg_folder, [dep.cpp_info],\n                                                              required_components)\n                include_components_names.append((dep_name, dep_name))\n                result.update(root_content)\n\n            result[\"conan_{}.xcconfig\".format(dep_name)] = self._pkg_xconfig_file(include_components_names)\n\n        all_file_content = \"\"\n\n        # Include direct requires\n        direct_deps = self._conanfile.dependencies.filter({\"direct\": True, \"build\": False, \"skip\": False})\n        result[self.general_name] = self._all_xconfig_file(direct_deps, all_file_content)\n\n        result[GLOBAL_XCCONFIG_FILENAME] = self._global_xconfig_content\n\n        return result\n"
  },
  {
    "path": "conan/tools/apple/xcodetoolchain.py",
    "content": "import textwrap\n\nfrom conan.internal import check_duplicated_generator\nfrom conan.tools.apple.apple import to_apple_arch, xcodebuild_deployment_target_key\nfrom conan.tools.apple.xcodedeps import GLOBAL_XCCONFIG_FILENAME, GLOBAL_XCCONFIG_TEMPLATE, \\\n    _add_includes_to_file_or_create, _xcconfig_settings_filename, _xcconfig_conditional\nfrom conan.internal.util.files import save\n\n\nclass XcodeToolchain:\n    filename = \"conantoolchain\"\n    extension = \".xcconfig\"\n\n    _vars_xconfig = textwrap.dedent(\"\"\"\\\n        // Definition of toolchain variables\n        {apple_deployment_target}\n        {clang_cxx_library}\n        {clang_cxx_language_standard}\n        \"\"\")\n\n    _flags_xconfig = textwrap.dedent(\"\"\"\\\n        // Global flags\n        {defines}\n        {cflags}\n        {cppflags}\n        {ldflags}\n        \"\"\")\n\n    _agreggated_xconfig = textwrap.dedent(\"\"\"\\\n        // Conan XcodeToolchain generated file\n        // Includes all installed configurations\n\n        \"\"\")\n\n    def __init__(self, conanfile):\n        self._conanfile = conanfile\n        arch = conanfile.settings.get_safe(\"arch\")\n        self.architecture = to_apple_arch(self._conanfile, default=arch)\n        self.configuration = conanfile.settings.build_type\n        self.libcxx = conanfile.settings.get_safe(\"compiler.libcxx\")\n        self.os_version = conanfile.settings.get_safe(\"os.version\")\n        self._global_defines = self._conanfile.conf.get(\"tools.build:defines\", default=[], check_type=list)\n        self._global_cxxflags = self._conanfile.conf.get(\"tools.build:cxxflags\", default=[], check_type=list)\n        self._global_cflags = self._conanfile.conf.get(\"tools.build:cflags\", default=[], check_type=list)\n        sharedlinkflags = self._conanfile.conf.get(\"tools.build:sharedlinkflags\", default=[], check_type=list)\n        exelinkflags = self._conanfile.conf.get(\"tools.build:exelinkflags\", default=[], check_type=list)\n        self._global_ldflags = sharedlinkflags + exelinkflags\n\n    def generate(self):\n        check_duplicated_generator(self, self._conanfile)\n        save(self._agreggated_xconfig_filename, self._agreggated_xconfig_content)\n        save(self._vars_xconfig_filename, self._vars_xconfig_content)\n        if self._check_if_extra_flags:\n            save(self._flags_xcconfig_filename, self._flags_xcconfig_content)\n        save(GLOBAL_XCCONFIG_FILENAME, self._global_xconfig_content)\n\n    @property\n    def _cppstd(self):\n        from conan.tools.build.flags import cppstd_flag\n        cppstd = cppstd_flag(self._conanfile)\n        if cppstd.startswith(\"-std=\"):\n            return cppstd[5:]\n        return cppstd\n\n    @property\n    def _apple_deployment_target(self):\n        deployment_target_key = xcodebuild_deployment_target_key(self._conanfile.settings.get_safe(\"os\"))\n        return '{}{}={}'.format(deployment_target_key,\n                                _xcconfig_conditional(self._conanfile.settings, self.configuration),\n                                self.os_version) if deployment_target_key and self.os_version else \"\"\n\n    @property\n    def _clang_cxx_library(self):\n        return 'CLANG_CXX_LIBRARY{}={}'.format(_xcconfig_conditional(self._conanfile.settings,\n                                                                     self.configuration),\n                                               self.libcxx) if self.libcxx else \"\"\n\n    @property\n    def _clang_cxx_language_standard(self):\n        return 'CLANG_CXX_LANGUAGE_STANDARD{}={}'.format(_xcconfig_conditional(self._conanfile.settings, self.configuration),\n                                                         self._cppstd) if self._cppstd else \"\"\n\n    @property\n    def _vars_xconfig_filename(self):\n        return \"conantoolchain{}{}\".format(_xcconfig_settings_filename(self._conanfile.settings,\n                                                                       self.configuration),\n                                           self.extension)\n\n    @property\n    def _vars_xconfig_content(self):\n        ret = self._vars_xconfig.format(apple_deployment_target=self._apple_deployment_target,\n                                        clang_cxx_library=self._clang_cxx_library,\n                                        clang_cxx_language_standard=self._clang_cxx_language_standard)\n        return ret\n\n    @property\n    def _agreggated_xconfig_content(self):\n        return _add_includes_to_file_or_create(self._agreggated_xconfig_filename,\n                                               self._agreggated_xconfig,\n                                               [self._vars_xconfig_filename])\n\n    @property\n    def _global_xconfig_content(self):\n        files_to_include = [self._agreggated_xconfig_filename]\n        if self._check_if_extra_flags:\n            files_to_include.append(self._flags_xcconfig_filename)\n        content = _add_includes_to_file_or_create(GLOBAL_XCCONFIG_FILENAME, GLOBAL_XCCONFIG_TEMPLATE,\n                                                  files_to_include)\n        return content\n\n    @property\n    def _agreggated_xconfig_filename(self):\n        return self.filename + self.extension\n\n    @property\n    def _check_if_extra_flags(self):\n        return self._global_cflags or self._global_cxxflags or self._global_ldflags or self._global_defines\n\n    @property\n    def _flags_xcconfig_content(self):\n        defines = \"GCC_PREPROCESSOR_DEFINITIONS = $(inherited) {}\".format(\" \".join(self._global_defines)) if self._global_defines else \"\"\n        cflags = \"OTHER_CFLAGS = $(inherited) {}\".format(\" \".join(self._global_cflags)) if self._global_cflags else \"\"\n        cppflags = \"OTHER_CPLUSPLUSFLAGS = $(inherited) {}\".format(\" \".join(self._global_cxxflags)) if self._global_cxxflags else \"\"\n        ldflags = \"OTHER_LDFLAGS = $(inherited) {}\".format(\" \".join(self._global_ldflags)) if self._global_ldflags else \"\"\n        ret = self._flags_xconfig.format(defines=defines, cflags=cflags, cppflags=cppflags, ldflags=ldflags)\n        return ret\n\n    @property\n    def _flags_xcconfig_filename(self):\n        return \"conan_global_flags\" + self.extension\n"
  },
  {
    "path": "conan/tools/build/__init__.py",
    "content": "import configparser\nimport os\nimport sys\nfrom shlex import quote\n\nfrom conan.tools.build.flags import cppstd_flag\nfrom conan.tools.build.cppstd import check_max_cppstd, check_min_cppstd, \\\n    valid_max_cppstd, valid_min_cppstd, default_cppstd, supported_cppstd\nfrom conan.tools.build.cstd import check_max_cstd, check_min_cstd, \\\n    valid_max_cstd, valid_min_cstd, default_cstd, supported_cstd\nfrom conan.tools.build.cpu import build_jobs\nfrom conan.tools.build.cross_building import cross_building, can_run\nfrom conan.tools.build.stdcpp_library import stdcpp_library\nfrom conan.tools.build.compiler import check_min_compiler_version\nfrom conan.errors import ConanException\n\nCONAN_TOOLCHAIN_ARGS_FILE = \"conanbuild.conf\"\nCONAN_TOOLCHAIN_ARGS_SECTION = \"toolchain\"\n\n\ndef use_win_mingw(conanfile):\n    os_build = conanfile.settings_build.get_safe('os')\n    if os_build == \"Windows\":\n        compiler = conanfile.settings.get_safe(\"compiler\")\n        sub = conanfile.settings.get_safe(\"os.subsystem\")\n        if sub in (\"cygwin\", \"msys2\", \"msys\") or compiler == \"qcc\":\n            return False\n        else:\n            return True\n    return False\n\n\ndef cmd_args_to_string(args):\n    if not args:\n        return \"\"\n    if sys.platform == 'win32':\n        return _windows_cmd_args_to_string(args)\n    else:\n        return _unix_cmd_args_to_string(args)\n\n\ndef _unix_cmd_args_to_string(args):\n    \"\"\"Return a shell-escaped string from *split_command*.\"\"\"\n    return ' '.join(quote(arg) for arg in args)\n\n\ndef _windows_cmd_args_to_string(args):\n    # FIXME: This is not managing all the parsing from list2cmdline, but covering simplified cases\n    ret = []\n    for arg in args:\n        # escaped quotes have to escape the \\ and then the \". Replace with <QUOTE> so next\n        # replace doesn't interfere\n        arg = arg.replace(r'\\\"', r'\\\\\\<QUOTE>')\n        # quotes have to be escaped\n        arg = arg.replace(r'\"', r'\\\"')\n\n        # restore the quotes\n        arg = arg.replace(\"<QUOTE>\", '\"')\n        # if argument have spaces, quote it\n        if ' ' in arg or '\\t' in arg:\n            ret.append('\"{}\"'.format(arg))\n        else:\n            ret.append(arg)\n    return \" \".join(ret)\n\n\ndef load_toolchain_args(generators_folder=None, namespace=None):\n    \"\"\"\n    Helper function to load the content of any CONAN_TOOLCHAIN_ARGS_FILE\n\n    :param generators_folder: `str` folder where is located the CONAN_TOOLCHAIN_ARGS_FILE.\n    :param namespace: `str` namespace to be prepended to the filename.\n    :return: <class 'configparser.SectionProxy'>\n    \"\"\"\n    namespace_name = \"{}_{}\".format(namespace, CONAN_TOOLCHAIN_ARGS_FILE) if namespace \\\n        else CONAN_TOOLCHAIN_ARGS_FILE\n    args_file = os.path.join(generators_folder, namespace_name) if generators_folder \\\n        else namespace_name\n    toolchain_config = configparser.ConfigParser()\n    toolchain_file = toolchain_config.read(args_file)\n    if not toolchain_file:\n        raise ConanException(\"The file %s does not exist. Please, make sure that it was not\"\n                             \" generated in another folder.\" % args_file)\n    try:\n        return toolchain_config[CONAN_TOOLCHAIN_ARGS_SECTION]\n    except KeyError:\n        raise ConanException(\"The primary section [%s] does not exist in the file %s. Please, add it\"\n                             \" as the default one of all your configuration variables.\" %\n                             (CONAN_TOOLCHAIN_ARGS_SECTION, args_file))\n\n\ndef save_toolchain_args(content, generators_folder=None, namespace=None):\n    \"\"\"\n    Helper function to save the content into the CONAN_TOOLCHAIN_ARGS_FILE\n\n    :param content: `dict` all the information to be saved into the toolchain file.\n    :param namespace: `str` namespace to be prepended to the filename.\n    :param generators_folder: `str` folder where is located the CONAN_TOOLCHAIN_ARGS_FILE\n    \"\"\"\n    # Let's prune None values\n    content_ = {k: v for k, v in content.items() if v is not None}\n    namespace_name = \"{}_{}\".format(namespace, CONAN_TOOLCHAIN_ARGS_FILE) if namespace \\\n        else CONAN_TOOLCHAIN_ARGS_FILE\n    args_file = os.path.join(generators_folder, namespace_name) if generators_folder \\\n        else namespace_name\n    toolchain_config = configparser.ConfigParser()\n    toolchain_config[CONAN_TOOLCHAIN_ARGS_SECTION] = content_\n    with open(args_file, \"w\") as f:\n        toolchain_config.write(f)\n"
  },
  {
    "path": "conan/tools/build/compiler.py",
    "content": "from conan.errors import ConanInvalidConfiguration, ConanException\nfrom conan.internal.model.version import Version\n\n\ndef check_min_compiler_version(conanfile, compiler_restrictions):\n    \"\"\"(Experimental) Checks if the current compiler and its version meet the minimum requirements.\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :param compiler_restrictions:\n        A list of tuples, where each tuple contains:\n\n        - **compiler** (*str*): The name of the compiler (e.g., \"gcc\", \"msvc\").\n        - **min_version** (*str*): The minimum required version as a string (e.g., \"14\", \"19.0\").\n        - **reason** (*str*): A string explaining the reason for the version requirement.\n    :raises ConanException:\n        If the 'compiler' or 'compiler.version' settings are not defined.\n    :raises ConanInvalidConfiguration:\n        If the found compiler version is less than the specified minimum version for that compiler.\n\n    :Example:\n        .. code-block:: python\n\n            def validate(self):\n                compiler_restrictions = [\n                    (\"clang\", \"14\", \"requires C++20 coroutines support\"),\n                    (\"gcc\", \"12\", \"requires C++20 modules support\")\n                ]\n                check_min_compiler_version(self, compiler_restrictions)\n    \"\"\"\n    compiler_value = conanfile.settings.get_safe(\"compiler\")\n    if not compiler_value:\n        raise ConanException(\"Called check_min_compiler_version with no compiler defined\")\n    compiler_version = conanfile.settings.get_safe(\"compiler.version\")\n    if not compiler_version:\n        raise ConanException(\"Called check_min_compiler_version with no compiler.version defined\")\n\n    for compiler, min_version, reason in compiler_restrictions:\n        if compiler_value == compiler:\n            if Version(compiler_version) < Version(min_version):\n                ref = conanfile.ref if hasattr(conanfile, \"ref\") else conanfile.name\n                raise ConanInvalidConfiguration(\n                    f\"{ref} requires {compiler} >= {min_version}, but {compiler} {compiler_version} was found\\n\"\n                    f\"Reason: {reason}\")\n            break\n"
  },
  {
    "path": "conan/tools/build/cppstd.py",
    "content": "import operator\n\nfrom conan.errors import ConanInvalidConfiguration, ConanException\nfrom conan.internal.api.detect.detect_api import default_cppstd as default_cppstd_\nfrom conan.internal.model.version import Version\n\n\ndef check_min_cppstd(conanfile, cppstd, gnu_extensions=False):\n    \"\"\" Check if current cppstd fits the minimal version required.\n\n        In case the current cppstd doesn't fit the minimal version required\n        by cppstd, a ConanInvalidConfiguration exception will be raised.\n\n        settings.compiler.cppstd must be defined, otherwise ConanInvalidConfiguration is raised\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :param cppstd: Minimal cppstd version required\n    :param gnu_extensions: GNU extension is required (e.g gnu17)\n    \"\"\"\n    _check_cppstd(conanfile, cppstd, operator.lt, gnu_extensions)\n\n\ndef check_max_cppstd(conanfile, cppstd, gnu_extensions=False):\n    \"\"\" Check if current cppstd fits the maximum version required.\n\n        In case the current cppstd doesn't fit the maximum version required\n        by cppstd, a ConanInvalidConfiguration exception will be raised.\n\n        settings.compiler.cppstd must be defined, otherwise ConanInvalidConfiguration is raised\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :param cppstd: Maximum cppstd version required\n    :param gnu_extensions: GNU extension is required (e.g gnu17)\n    \"\"\"\n    _check_cppstd(conanfile, cppstd, operator.gt, gnu_extensions)\n\n\ndef valid_min_cppstd(conanfile, cppstd, gnu_extensions=False):\n    \"\"\" Validate if current cppstd fits the minimal version required.\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :param cppstd: Minimal cppstd version required\n    :param gnu_extensions: GNU extension is required (e.g gnu17). This option ONLY works on Linux.\n    :return: True, if current cppstd matches the required cppstd version. Otherwise, False.\n    \"\"\"\n    try:\n        check_min_cppstd(conanfile, cppstd, gnu_extensions)\n    except ConanInvalidConfiguration:\n        return False\n    return True\n\n\ndef valid_max_cppstd(conanfile, cppstd, gnu_extensions=False):\n    \"\"\" Validate if current cppstd fits the maximum version required.\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :param cppstd: Maximum cppstd version required\n    :param gnu_extensions: GNU extension is required (e.g gnu17). This option ONLY works on Linux.\n    :return: True, if current cppstd matches the required cppstd version. Otherwise, False.\n    \"\"\"\n    try:\n        check_max_cppstd(conanfile, cppstd, gnu_extensions)\n    except ConanInvalidConfiguration:\n        return False\n    return True\n\n\ndef default_cppstd(conanfile, compiler=None, compiler_version=None):\n    \"\"\"\n    Get the default ``compiler.cppstd`` for the \"conanfile.settings.compiler\" and \"conanfile\n    settings.compiler_version\" or for the parameters \"compiler\" and \"compiler_version\" if specified.\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :param compiler: Name of the compiler e.g. gcc\n    :param compiler_version: Version of the compiler e.g. 12\n    :return: The default ``compiler.cppstd`` for the specified compiler\n    \"\"\"\n    compiler = compiler or conanfile.settings.get_safe(\"compiler\")\n    compiler_version = compiler_version or conanfile.settings.get_safe(\"compiler.version\")\n    if not compiler or not compiler_version:\n        raise ConanException(\"Called default_cppstd with no compiler or no compiler.version\")\n    return default_cppstd_(compiler, Version(compiler_version))\n\n\ndef supported_cppstd(conanfile, compiler=None, compiler_version=None):\n    \"\"\"\n    Get a list of supported ``compiler.cppstd`` for the \"conanfile.settings.compiler\" and\n    \"conanfile.settings.compiler_version\" or for the parameters \"compiler\" and \"compiler_version\"\n    if specified.\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :param compiler: Name of the compiler e.g: gcc\n    :param compiler_version: Version of the compiler e.g: 12\n    :return: a list of supported ``cppstd`` values.\n    \"\"\"\n    compiler = compiler or conanfile.settings.get_safe(\"compiler\")\n    compiler_version = compiler_version or conanfile.settings.get_safe(\"compiler.version\")\n    if not compiler or not compiler_version:\n        raise ConanException(\"Called supported_cppstd with no compiler or no compiler.version\")\n\n    func = {\"apple-clang\": _apple_clang_supported_cppstd,\n            \"gcc\": _gcc_supported_cppstd,\n            \"msvc\": _msvc_supported_cppstd,\n            \"clang\": _clang_supported_cppstd,\n            \"mcst-lcc\": _mcst_lcc_supported_cppstd,\n            \"qcc\": _qcc_supported_cppstd,\n            \"emcc\": _emcc_supported_cppstd,\n            }.get(compiler)\n    if func:\n        return func(Version(compiler_version))\n    return None\n\n\ndef _check_cppstd(conanfile, cppstd, comparator, gnu_extensions):\n    \"\"\" Check if current cppstd fits the version required according to a given comparator.\n\n        In case the current cppstd doesn't fit the maximum version required\n        by cppstd, a ConanInvalidConfiguration exception will be raised.\n\n        settings.compiler.cppstd must be defined, otherwise ConanInvalidConfiguration is raised\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :param cppstd: Required cppstd version.\n    :param comparator: Operator to use to compare the detected and the required cppstd versions.\n    :param gnu_extensions: GNU extension is required (e.g gnu17)\n    \"\"\"\n    if not str(cppstd).isdigit():\n        raise ConanException(\"cppstd parameter must be a number\")\n\n    def compare(lhs, rhs, comp):\n        def extract_cpp_version(_cppstd):\n            return str(_cppstd).replace(\"gnu\", \"\")\n\n        def add_millennium(_cppstd):\n            return \"19%s\" % _cppstd if _cppstd == \"98\" else \"20%s\" % _cppstd\n\n        lhs = add_millennium(extract_cpp_version(lhs))\n        rhs = add_millennium(extract_cpp_version(rhs))\n        return not comp(lhs, rhs)\n\n    current_cppstd = conanfile.settings.get_safe(\"compiler.cppstd\")\n    if current_cppstd is None:\n        raise ConanInvalidConfiguration(\"The compiler.cppstd is not defined for this configuration\")\n\n    if gnu_extensions and \"gnu\" not in current_cppstd:\n        raise ConanInvalidConfiguration(\"The cppstd GNU extension is required\")\n\n    if not compare(current_cppstd, cppstd, comparator):\n        raise ConanInvalidConfiguration(\n            \"Current cppstd ({}) is {} than the required C++ standard ({}).\".format(\n                current_cppstd, \"higher\" if comparator == operator.gt else \"lower\", cppstd))\n\n\ndef _apple_clang_supported_cppstd(version):\n    \"\"\"\n    [\"98\", \"gnu98\", \"11\", \"gnu11\", \"14\", \"gnu14\", \"17\", \"gnu17\", \"20\", \"gnu20\"]\n    \"\"\"\n    if version < \"4.0\":\n        return []\n    if version < \"5.1\":\n        return [\"98\", \"gnu98\", \"11\", \"gnu11\"]\n    if version < \"6.1\":\n        return [\"98\", \"gnu98\", \"11\", \"gnu11\", \"14\", \"gnu14\"]\n    if version < \"10.0\":\n        return [\"98\", \"gnu98\", \"11\", \"gnu11\", \"14\", \"gnu14\", \"17\", \"gnu17\"]\n    if version < \"13.0\":\n        return [\"98\", \"gnu98\", \"11\", \"gnu11\", \"14\", \"gnu14\", \"17\", \"gnu17\", \"20\", \"gnu20\"]\n    # https://github.com/conan-io/conan/pull/17092 doesn't show c++23 full support until 16\n    # but it was this before Conan 2.9, so keeping it to not break\n    if version < \"16.0\":\n        return [\"98\", \"gnu98\", \"11\", \"gnu11\", \"14\", \"gnu14\", \"17\", \"gnu17\", \"20\", \"gnu20\",\n                \"23\", \"gnu23\"]\n\n    return [\"98\", \"gnu98\", \"11\", \"gnu11\", \"14\", \"gnu14\", \"17\", \"gnu17\", \"20\", \"gnu20\", \"23\", \"gnu23\",\n            \"26\", \"gnu26\"]\n\n\ndef _gcc_supported_cppstd(version):\n    \"\"\"\n    [\"98\", \"gnu98\", \"11\", \"gnu11\", \"14\", \"gnu14\", \"17\", \"gnu17\", \"20\", \"gnu20\", \"23\", \"gnu23\"]\n    \"\"\"\n    if version < \"3.4\":\n        return []\n    if version < \"4.3\":\n        return [\"98\", \"gnu98\"]\n    if version < \"4.8\":\n        return [\"98\", \"gnu98\", \"11\", \"gnu11\"]\n    if version < \"5\":\n        return [\"98\", \"gnu98\", \"11\", \"gnu11\", \"14\", \"gnu14\"]\n    if version < \"8\":\n        return [\"98\", \"gnu98\", \"11\", \"gnu11\", \"14\", \"gnu14\", \"17\", \"gnu17\"]\n    if version < \"11\":\n        return [\"98\", \"gnu98\", \"11\", \"gnu11\", \"14\", \"gnu14\", \"17\", \"gnu17\", \"20\", \"gnu20\"]\n    # https://github.com/conan-io/conan/pull/17092\n    if version < \"14.0\":\n        return [\"98\", \"gnu98\", \"11\", \"gnu11\", \"14\", \"gnu14\", \"17\", \"gnu17\", \"20\", \"gnu20\",\n                \"23\", \"gnu23\"]\n\n    return [\"98\", \"gnu98\", \"11\", \"gnu11\", \"14\", \"gnu14\", \"17\", \"gnu17\", \"20\", \"gnu20\", \"23\", \"gnu23\",\n            \"26\", \"gnu26\"]\n\n\ndef _msvc_supported_cppstd(version):\n    \"\"\"\n    https://learn.microsoft.com/en-us/cpp/build/reference/std-specify-language-standard-version?view=msvc-170\n    - /std:c++14 starting in Visual Studio 2015 Update 3 (190)\n    - /std:c++17 starting in Visual Studio 2017 version 15.3. (191)\n    - /std:c++20 starting in Visual Studio 2019 version 16.11 (192)\n    [14, 17, 20, 23]\n    \"\"\"\n    if version < \"190\":  # pre VS 2015\n        return []\n    if version < \"191\":  # VS 2015\n        return [\"14\"]\n    if version < \"192\":  # VS 2017\n        return [\"14\", \"17\"]\n    if version < \"193\":\n        return [\"14\", \"17\", \"20\"]\n\n    return [\"14\", \"17\", \"20\", \"23\"]\n\n\ndef _clang_supported_cppstd(version):\n    \"\"\"\n    [\"98\", \"gnu98\", \"11\", \"gnu11\", \"14\", \"gnu14\", \"17\", \"gnu17\", \"20\", \"gnu20\", \"23\", \"gnu23\"]\n    \"\"\"\n    if version < \"2.1\":\n        return []\n    if version < \"3.4\":\n        return [\"98\", \"gnu98\", \"11\", \"gnu11\"]\n    if version < \"3.5\":\n        return [\"98\", \"gnu98\", \"11\", \"gnu11\", \"14\", \"gnu14\"]\n    if version < \"6\":\n        return [\"98\", \"gnu98\", \"11\", \"gnu11\", \"14\", \"gnu14\", \"17\", \"gnu17\"]\n    if version < \"12\":\n        return [\"98\", \"gnu98\", \"11\", \"gnu11\", \"14\", \"gnu14\", \"17\", \"gnu17\", \"20\", \"gnu20\"]\n    # https://github.com/conan-io/conan/pull/17092\n    if version < \"17.0\":\n        return [\"98\", \"gnu98\", \"11\", \"gnu11\", \"14\", \"gnu14\", \"17\", \"gnu17\", \"20\", \"gnu20\",\n                \"23\", \"gnu23\"]\n    return [\"98\", \"gnu98\", \"11\", \"gnu11\", \"14\", \"gnu14\", \"17\", \"gnu17\", \"20\", \"gnu20\", \"23\", \"gnu23\",\n            \"26\", \"gnu26\"]\n\n\ndef _mcst_lcc_supported_cppstd(version):\n    \"\"\"\n    [\"98\", \"gnu98\", \"11\", \"gnu11\", \"14\", \"gnu14\", \"17\", \"gnu17\", \"20\", \"gnu20\", \"23\", \"gnu23\"]\n    \"\"\"\n\n    if version < \"1.21\":\n        return [\"98\", \"gnu98\"]\n    if version < \"1.24\":\n        return [\"98\", \"gnu98\", \"11\", \"gnu11\", \"14\", \"gnu14\"]\n    if version < \"1.25\":\n        return [\"98\", \"gnu98\", \"11\", \"gnu11\", \"14\", \"gnu14\", \"17\", \"gnu17\"]\n\n    # FIXME: When cppstd 23 was introduced????\n\n    return [\"98\", \"gnu98\", \"11\", \"gnu11\", \"14\", \"gnu14\", \"17\", \"gnu17\", \"20\", \"gnu20\"]\n\n\ndef _qcc_supported_cppstd(version):\n    \"\"\"\n    [98, gnu98, 11, gnu11, 14, gnu14, 17, gnu17]\n    \"\"\"\n\n    if version < \"5\":\n        return [\"98\", \"gnu98\"]\n    elif version < \"12\":\n        return [\"98\", \"gnu98\", \"11\", \"gnu11\", \"14\", \"gnu14\", \"17\", \"gnu17\"]\n    else:\n        return [\"98\", \"gnu98\", \"11\", \"gnu11\", \"14\", \"gnu14\", \"17\", \"gnu17\", \"20\", \"gnu20\"]\n\n\ndef _emcc_supported_cppstd(version):\n    \"\"\"\n    emcc is based on clang but follow different versioning scheme.\n    \"\"\"\n    if version <= \"3.0.1\":\n        return _clang_supported_cppstd(Version(\"14\"))\n    if version <= \"3.1.50\":\n        return _clang_supported_cppstd(Version(\"18\"))\n    if version <= \"4.0.1\":\n        return _clang_supported_cppstd(Version(\"20\"))\n    # Since emcc 4.0.2 clang version is 21\n    return _clang_supported_cppstd(Version(\"21\"))\n"
  },
  {
    "path": "conan/tools/build/cpu.py",
    "content": "from conan.internal.util import cpu_count\n\n\ndef build_jobs(conanfile):\n    \"\"\"\n    Returns the number of CPUs available for parallel builds.\n    It returns the configuration value for ``tools.build:jobs`` if exists, otherwise,\n    it defaults to the helper function ``_cpu_count()``.\n    ``_cpu_count()`` reads cgroup to detect the configured number of CPUs.\n    Currently, there are two versions of cgroup available.\n\n    In the case of cgroup v1, if the data in cgroup is invalid, processor detection comes into play.\n    Whenever processor detection is not enabled, ``build_jobs()`` will safely return 1.\n\n    In the case of cgroup v2, if no limit is set, processor detection is used. When the limit is set,\n    the behavior is as described in cgroup v1.\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :return: ``int`` with the number of jobs\n    \"\"\"\n    return conanfile.conf.get(\"tools.build:jobs\", default=cpu_count(), check_type=int)\n"
  },
  {
    "path": "conan/tools/build/cross_building.py",
    "content": "\ndef cross_building(conanfile=None, skip_x64_x86=False):\n    \"\"\"\n    Check if we are cross building comparing the *build* and *host* settings. Returns ``True``\n    in the case that we are cross-building.\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :param skip_x64_x86: Do not consider cross building when building to 32 bits from 64 bits:\n           x86_64 to x86, sparcv9 to sparc or ppc64 to ppc32\n    :return: ``bool`` value from ``tools.build.cross_building:cross_build`` if exists, otherwise,\n             it returns ``True`` if we are cross-building, else, ``False``.\n    \"\"\"\n    cross_build = conanfile.conf.get(\"tools.build.cross_building:cross_build\", check_type=bool)\n    if cross_build is not None:\n        return cross_build\n\n    build_os = conanfile.settings_build.get_safe('os')\n    build_arch = conanfile.settings_build.get_safe('arch')\n    host_os = conanfile.settings.get_safe(\"os\")\n    host_arch = conanfile.settings.get_safe(\"arch\")\n\n    if skip_x64_x86 and host_os is not None and (build_os == host_os) and \\\n            host_arch is not None and ((build_arch == \"x86_64\") and (host_arch == \"x86\") or\n                                       (build_arch == \"sparcv9\") and (host_arch == \"sparc\") or\n                                       (build_arch == \"ppc64\") and (host_arch == \"ppc32\")):\n        return False\n\n    if host_os is not None and (build_os != host_os):\n        return True\n    if host_arch is not None and (build_arch != host_arch):\n        return True\n\n    return False\n\n\ndef can_run(conanfile):\n    \"\"\"\n    Validates whether is possible to run a non-native app on the same architecture.\n    It’s a useful feature for the case your architecture can run more than one target.\n    For instance, Mac M1 machines can run both `armv8` and `x86_64`.\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :return: ``bool`` value from ``tools.build.cross_building:can_run`` if exists, otherwise,\n             it returns ``False`` if we are cross-building, else, ``True``.\n    \"\"\"\n    # Issue related: https://github.com/conan-io/conan/issues/11035\n    allowed = conanfile.conf.get(\"tools.build.cross_building:can_run\", check_type=bool)\n    if allowed is None:\n        return not cross_building(conanfile)\n    return allowed\n"
  },
  {
    "path": "conan/tools/build/cstd.py",
    "content": "import operator\n\nfrom conan.errors import ConanInvalidConfiguration, ConanException\nfrom conan.internal.api.detect.detect_api import default_cstd as default_cstd_\nfrom conan.internal.model.version import Version\n\n\ndef check_min_cstd(conanfile, cstd, gnu_extensions=False):\n    \"\"\" Check if current cstd fits the minimal version required.\n\n        In case the current cstd doesn't fit the minimal version required\n        by cstd, a ConanInvalidConfiguration exception will be raised.\n\n        1. If settings.compiler.cstd, the tool will use settings.compiler.cstd to compare\n        2. It not settings.compiler.cstd, the tool will use compiler to compare (reading the\n           default from cstd_default)\n        3. If not settings.compiler is present (not declared in settings) will raise because it\n           cannot compare.\n        4. If can not detect the default cstd for settings.compiler, a exception will be raised.\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :param cstd: Minimal cstd version required\n    :param gnu_extensions: GNU extension is required (e.g gnu17)\n    \"\"\"\n    _check_cstd(conanfile, cstd, operator.lt, gnu_extensions)\n\n\ndef check_max_cstd(conanfile, cstd, gnu_extensions=False):\n    \"\"\" Check if current cstd fits the maximum version required.\n\n        In case the current cstd doesn't fit the maximum version required\n        by cstd, a ConanInvalidConfiguration exception will be raised.\n\n        1. If settings.compiler.cstd, the tool will use settings.compiler.cstd to compare\n        2. It not settings.compiler.cstd, the tool will use compiler to compare (reading the\n           default from cstd_default)\n        3. If not settings.compiler is present (not declared in settings) will raise because it\n           cannot compare.\n        4. If can not detect the default cstd for settings.compiler, a exception will be raised.\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :param cstd: Maximum cstd version required\n    :param gnu_extensions: GNU extension is required (e.g gnu17)\n    \"\"\"\n    _check_cstd(conanfile, cstd, operator.gt, gnu_extensions)\n\n\ndef valid_min_cstd(conanfile, cstd, gnu_extensions=False):\n    \"\"\" Validate if current cstd fits the minimal version required.\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :param cstd: Minimal cstd version required\n    :param gnu_extensions: GNU extension is required (e.g gnu17). This option ONLY works on Linux.\n    :return: True, if current cstd matches the required cstd version. Otherwise, False.\n    \"\"\"\n    try:\n        check_min_cstd(conanfile, cstd, gnu_extensions)\n    except ConanInvalidConfiguration:\n        return False\n    return True\n\n\ndef valid_max_cstd(conanfile, cstd, gnu_extensions=False):\n    \"\"\" Validate if current cstd fits the maximum version required.\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :param cstd: Maximum cstd version required\n    :param gnu_extensions: GNU extension is required (e.g gnu17). This option ONLY works on Linux.\n    :return: True, if current cstd matches the required cstd version. Otherwise, False.\n    \"\"\"\n    try:\n        check_max_cstd(conanfile, cstd, gnu_extensions)\n    except ConanInvalidConfiguration:\n        return False\n    return True\n\n\ndef default_cstd(conanfile, compiler=None, compiler_version=None):\n    \"\"\"\n    Get the default ``compiler.cstd`` for the \"conanfile.settings.compiler\" and \"conanfile\n    settings.compiler_version\" or for the parameters \"compiler\" and \"compiler_version\" if specified.\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :param compiler: Name of the compiler e.g. gcc\n    :param compiler_version: Version of the compiler e.g. 12\n    :return: The default ``compiler.cstd`` for the specified compiler\n    \"\"\"\n    compiler = compiler or conanfile.settings.get_safe(\"compiler\")\n    compiler_version = compiler_version or conanfile.settings.get_safe(\"compiler.version\")\n    if not compiler or not compiler_version:\n        raise ConanException(\"Called default_cppstd with no compiler or no compiler.version\")\n    return default_cstd_(compiler, Version(compiler_version))\n\n\ndef supported_cstd(conanfile, compiler=None, compiler_version=None):\n    \"\"\"\n    Get a list of supported ``compiler.cstd`` for the \"conanfile.settings.compiler\" and\n    \"conanfile.settings.compiler_version\" or for the parameters \"compiler\" and \"compiler_version\"\n    if specified.\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :param compiler: Name of the compiler e.g: gcc\n    :param compiler_version: Version of the compiler e.g: 12\n    :return: a list of supported ``cstd`` values.\n    \"\"\"\n    compiler = compiler or conanfile.settings.get_safe(\"compiler\")\n    compiler_version = compiler_version or conanfile.settings.get_safe(\"compiler.version\")\n    if not compiler or not compiler_version:\n        raise ConanException(\"Called supported_cstd with no compiler or no compiler.version\")\n\n    func = {\"apple-clang\": _apple_clang_supported_cstd,\n            \"gcc\": _gcc_supported_cstd,\n            \"msvc\": _msvc_supported_cstd,\n            \"clang\": _clang_supported_cstd,\n            \"emcc\": _emcc_supported_cstd,\n            }.get(compiler)\n    if func:\n        return func(Version(compiler_version))\n    return None\n\n\ndef _check_cstd(conanfile, cstd, comparator, gnu_extensions):\n    \"\"\" Check if current cstd fits the version required according to a given comparator.\n\n        In case the current cstd doesn't fit the maximum version required\n        by cstd, a ConanInvalidConfiguration exception will be raised.\n\n        1. If settings.compiler.cstd, the tool will use settings.compiler.cstd to compare\n        2. It not settings.compiler.cstd, the tool will use compiler to compare (reading the\n           default from cstd_default)\n        3. If not settings.compiler is present (not declared in settings) will raise because it\n           cannot compare.\n        4. If can not detect the default cstd for settings.compiler, a exception will be raised.\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :param cstd: Required cstd version.\n    :param comparator: Operator to use to compare the detected and the required cstd versions.\n    :param gnu_extensions: GNU extension is required (e.g gnu17)\n    \"\"\"\n    if not str(cstd).isdigit():\n        raise ConanException(\"cstd parameter must be a number\")\n\n    def compare(lhs, rhs, comp):\n        def extract_cpp_version(_cstd):\n            return str(_cstd).replace(\"gnu\", \"\")\n\n        def add_millennium(_cstd):\n            return \"19%s\" % _cstd if _cstd == \"99\" else \"20%s\" % _cstd\n\n        lhs = add_millennium(extract_cpp_version(lhs))\n        rhs = add_millennium(extract_cpp_version(rhs))\n        return not comp(lhs, rhs)\n\n    current_cstd = conanfile.settings.get_safe(\"compiler.cstd\")\n    if current_cstd is None:\n        raise ConanInvalidConfiguration(\"The compiler.cstd is not defined for this configuration\")\n\n    if gnu_extensions and \"gnu\" not in current_cstd:\n        raise ConanInvalidConfiguration(\"The cstd GNU extension is required\")\n\n    if not compare(current_cstd, cstd, comparator):\n        raise ConanInvalidConfiguration(\n            \"Current cstd ({}) is {} than the required C standard ({}).\".format(\n                current_cstd, \"higher\" if comparator == operator.gt else \"lower\", cstd))\n\n\ndef _apple_clang_supported_cstd(version):\n    # TODO: Per-version support\n    return [\"99\", \"gnu99\", \"11\", \"gnu11\", \"17\", \"gnu17\", \"23\", \"gnu23\"]\n\n\ndef _gcc_supported_cstd(version):\n    if version < \"4.7\":\n        return [\"99\", \"gnu99\"]\n    if version < \"8\":\n        return [\"99\", \"gnu99\", \"11\", \"gnu11\"]\n    if version < \"14\":\n        return [\"99\", \"gnu99\", \"11\", \"gnu11\", \"17\", \"gnu17\"]\n    return [\"99\", \"gnu99\", \"11\", \"gnu11\", \"17\", \"gnu17\", \"23\", \"gnu23\"]\n\n\ndef _msvc_supported_cstd(version):\n    if version < \"192\":\n        return []\n    return [\"11\", \"17\"]\n\n\ndef _clang_supported_cstd(version):\n    if version < \"3\":\n        return [\"99\", \"gnu99\"]\n    if version < \"6\":\n        return [\"99\", \"gnu99\", \"11\", \"gnu11\"]\n    if version < \"18\":\n        return [\"99\", \"gnu99\", \"11\", \"gnu11\", \"17\", \"gnu17\"]\n    return [\"99\", \"gnu99\", \"11\", \"gnu11\", \"17\", \"gnu17\", \"23\", \"gnu23\"]\n\n\ndef _emcc_supported_cstd(version):\n    \"\"\"\n    emcc is based on clang but follow different versioning scheme.\n    \"\"\"\n    if version <= \"3.0.1\":\n        return _clang_supported_cstd(Version(\"14\"))\n    if version <= \"3.1.50\":\n        return _clang_supported_cstd(Version(\"18\"))\n    if version <= \"4.0.1\":\n        return _clang_supported_cstd(Version(\"20\"))\n    # Since emcc 4.0.2 clang version is 21\n    return _clang_supported_cstd(Version(\"21\"))\n\n\n"
  },
  {
    "path": "conan/tools/build/flags.py",
    "content": "from conan.errors import ConanException\nfrom conan.internal.model.version import Version\n\n\ndef disable_flag(conanfile, flag):\n    disable_flags = conanfile.conf.get(\"tools.gnu:disable_flags\", check_type=list)\n    if disable_flags is None:\n        return False\n    valid = [\"arch\", \"arch_link\", \"libcxx\", \"build_type\", \"build_type_link\", \"threads\",\n             \"cppstd\", \"cstd\"]\n    for v in disable_flags:\n        if v not in valid:\n            raise ConanException(f\"tools.gnu:disable_flags value '{v}', must be one of: {valid}\")\n    return flag in disable_flags\n\n\ndef architecture_flag(conanfile):\n    \"\"\"\n    returns flags specific to the target architecture and compiler\n    Used by CMakeToolchain and AutotoolsToolchain\n    \"\"\"\n    if disable_flag(conanfile, \"arch\"):\n        return \"\"\n    settings = conanfile.settings\n    from conan.tools.apple.apple import _to_apple_arch\n    compiler = settings.get_safe(\"compiler\")\n    arch = settings.get_safe(\"arch\")\n    the_os = settings.get_safe(\"os\")\n    subsystem = settings.get_safe(\"os.subsystem\")\n    subsystem_ios_version = settings.get_safe(\"os.subsystem.ios_version\")\n    if not compiler or not arch:\n        return \"\"\n\n    if the_os == \"Android\":\n        return \"\"\n\n    if compiler == \"clang\" and the_os == \"Windows\":\n        comp_exes = conanfile.conf.get(\"tools.build:compiler_executables\", check_type=dict,\n                                       default={})\n        clangcl = \"clang-cl\" in (comp_exes.get(\"c\") or comp_exes.get(\"cpp\", \"\"))\n        if clangcl:\n            return \"\"  # Do not add arch flags for clang-cl, can happen in cross-build runtime=None\n        # LLVM/Clang and VS/Clang must define runtime. msys2 clang won't\n        runtime = settings.get_safe(\"compiler.runtime\")  # runtime is Windows only\n        if runtime is not None:\n            return \"\"\n        # TODO: Maybe Clang-Mingw runtime does, but with C++ is impossible to test\n        return {\"x86_64\": \"-m64\",\n                \"x86\": \"-m32\"}.get(arch, \"\")\n    elif compiler in ['gcc', 'apple-clang', 'clang', 'sun-cc']:\n        if the_os == 'Macos' and subsystem == 'catalyst':\n            # FIXME: This might be conflicting with Autotools --target cli arg\n            apple_arch = _to_apple_arch(arch)\n            if apple_arch:\n                # TODO: Could we define anything like `to_apple_target()`?\n                #       Check https://github.com/rust-lang/rust/issues/48862\n                return f'--target={apple_arch}-apple-ios{subsystem_ios_version}-macabi'\n        elif arch in ['x86_64', 'sparcv9', 's390x']:\n            return '-m64'\n        elif arch in ['x86', 'sparc']:\n            return '-m32'\n        elif arch in ['s390']:\n            return '-m31'\n        elif arch in ['tc131', 'tc16', 'tc161', 'tc162', 'tc18']:\n            return '-m{}'.format(arch)\n        elif the_os == 'AIX':\n            if arch in ['ppc32']:\n                return '-maix32'\n            elif arch in ['ppc64']:\n                return '-maix64'\n    elif compiler == \"intel-cc\":\n        # https://software.intel.com/en-us/cpp-compiler-developer-guide-and-reference-m32-m64-qm32-qm64\n        if arch == \"x86\":\n            return \"/Qm32\" if the_os == \"Windows\" else \"-m32\"\n        elif arch == \"x86_64\":\n            return \"/Qm64\" if the_os == \"Windows\" else \"-m64\"\n    elif compiler == \"mcst-lcc\":\n        return {\"e2k-v2\": \"-march=elbrus-v2\",\n                \"e2k-v3\": \"-march=elbrus-v3\",\n                \"e2k-v4\": \"-march=elbrus-v4\",\n                \"e2k-v5\": \"-march=elbrus-v5\",\n                \"e2k-v6\": \"-march=elbrus-v6\",\n                \"e2k-v7\": \"-march=elbrus-v7\"}.get(arch, \"\")\n    elif compiler == \"emcc\":\n        if arch == \"wasm64\":\n            return \"-sMEMORY64=1\"\n    return \"\"\n\n\ndef architecture_link_flag(conanfile):\n    \"\"\"\n    returns exclusively linker flags specific to the target architecture and compiler\n    \"\"\"\n    if disable_flag(conanfile, \"arch_link\"):\n        return \"\"\n    compiler = conanfile.settings.get_safe(\"compiler\")\n    arch = conanfile.settings.get_safe(\"arch\")\n    if compiler == \"emcc\":\n        # Emscripten default output is WASM since 1.37.x (long time ago)\n        # Deactivate WASM output forcing asm.js output instead\n        if arch == \"asm.js\":\n            return \"-sWASM=0\"\n    return \"\"\n\n\ndef libcxx_flags(conanfile):\n    libcxx = conanfile.settings.get_safe(\"compiler.libcxx\")\n    if not libcxx:\n        return None, None\n    if disable_flag(conanfile, \"libcxx\"):\n        return None, None\n    compiler = conanfile.settings.get_safe(\"compiler\")\n    lib = stdlib11 = None\n    if compiler == \"apple-clang\":\n        # In apple-clang 2 only values atm are \"libc++\" and \"libstdc++\"\n        lib = f'-stdlib={libcxx}'\n    elif compiler in (\"clang\", \"intel-cc\", \"emcc\"):\n        if libcxx == \"libc++\":\n            lib = \"-stdlib=libc++\"\n        elif libcxx == \"libstdc++\" or libcxx == \"libstdc++11\":\n            lib = \"-stdlib=libstdc++\"\n        # FIXME, something to do with the other values? Android c++_shared?\n    elif compiler == \"sun-cc\":\n        lib = {\"libCstd\": \"-library=Cstd\",\n               \"libstdcxx\": \"-library=stdcxx4\",\n               \"libstlport\": \"-library=stlport4\",\n               \"libstdc++\": \"-library=stdcpp\"\n               }.get(libcxx)\n    elif compiler == \"qcc\":\n        lib = f'-Y _{libcxx}'\n\n    if compiler in ['clang', 'apple-clang', 'gcc', 'emcc']:\n        if libcxx == \"libstdc++\":\n            stdlib11 = \"_GLIBCXX_USE_CXX11_ABI=0\"\n        elif libcxx == \"libstdc++11\" and conanfile.conf.get(\"tools.gnu:define_libcxx11_abi\",\n                                                            check_type=bool):\n            stdlib11 = \"_GLIBCXX_USE_CXX11_ABI=1\"\n    return lib, stdlib11\n\n\ndef build_type_link_flags(settings):\n    \"\"\"\n    returns link flags specific to the build type (Debug, Release, etc.)\n    [-debug]\n    \"\"\"\n    compiler = settings.get_safe(\"compiler\")\n    build_type = settings.get_safe(\"build_type\")\n    if not compiler or not build_type:\n        return []\n\n    # https://github.com/Kitware/CMake/blob/d7af8a34b67026feaee558433db3a835d6007e06/\n    # Modules/Platform/Windows-MSVC.cmake\n    if compiler == \"msvc\":\n        if build_type in (\"Debug\", \"RelWithDebInfo\"):\n            return [\"-debug\"]\n\n    return []\n\n\ndef build_type_flags(conanfile):\n    \"\"\"\n    returns flags specific to the build type (Debug, Release, etc.)\n    (-s, -g, /Zi, etc.)\n    Used only by AutotoolsToolchain\n    \"\"\"\n    if disable_flag(conanfile, \"build_type\"):\n        return []\n    settings = conanfile.settings\n    compiler = settings.get_safe(\"compiler\")\n    build_type = settings.get_safe(\"build_type\")\n    vs_toolset = settings.get_safe(\"compiler.toolset\")\n    if not compiler or not build_type:\n        return []\n\n    comp_exes = conanfile.conf.get(\"tools.build:compiler_executables\", check_type=dict,\n                                   default={})\n    clangcl = \"clang-cl\" in (comp_exes.get(\"c\") or comp_exes.get(\"cpp\", \"\"))\n\n    if compiler == \"msvc\" or clangcl:\n        # https://github.com/Kitware/CMake/blob/d7af8a34b67026feaee558433db3a835d6007e06/\n        # Modules/Platform/Windows-MSVC.cmake\n        # FIXME: This condition seems legacy, as no more \"clang\" exists in Conan toolsets\n        if vs_toolset and \"clang\" in vs_toolset:\n            flags = {\"Debug\": [\"-gline-tables-only\", \"-fno-inline\", \"-O0\"],\n                     \"Release\": [\"-O2\"],\n                     \"RelWithDebInfo\": [\"-gline-tables-only\", \"-O2\", \"-fno-inline\"],\n                     \"MinSizeRel\": []\n                     }.get(build_type, [\"-O2\", \"-Ob2\"])\n        else:\n            flags = {\"Debug\": [\"-Zi\", \"-Ob0\", \"-Od\"],\n                     \"Release\": [\"-O2\", \"-Ob2\"],\n                     \"RelWithDebInfo\": [\"-Zi\", \"-O2\", \"-Ob1\"],\n                     \"MinSizeRel\": [\"-O1\", \"-Ob1\"],\n                     }.get(build_type, [])\n        return flags\n    else:\n        # https://github.com/Kitware/CMake/blob/f3bbb37b253a1f4a26809d6f132b3996aa2e16fc/\n        # Modules/Compiler/GNU.cmake\n        # clang include the gnu (overriding some things, but not build type) and apple clang\n        # overrides clang but it doesn't touch clang either\n        if compiler in [\"clang\", \"gcc\", \"apple-clang\", \"qcc\", \"mcst-lcc\"]:\n            flags = {\"Debug\": [\"-g\"],\n                     \"Release\": [\"-O3\"],\n                     \"RelWithDebInfo\": [\"-O2\", \"-g\"],\n                     \"MinSizeRel\": [\"-Os\"],\n                     }.get(build_type, [])\n            return flags\n        elif compiler == \"sun-cc\":\n            # https://github.com/Kitware/CMake/blob/f3bbb37b253a1f4a26809d6f132b3996aa2e16fc/\n            # Modules/Compiler/SunPro-CXX.cmake\n            flags = {\"Debug\": [\"-g\"],\n                     \"Release\": [\"-xO3\"],\n                     \"RelWithDebInfo\": [\"-xO2\", \"-g\"],\n                     \"MinSizeRel\": [\"-xO2\", \"-xspace\"],\n                     }.get(build_type, [])\n            return flags\n    return []\n\n\ndef threads_flags(conanfile):\n    \"\"\"\n    returns flags specific to the threading model used by the compiler\n    \"\"\"\n    if disable_flag(conanfile, \"threads\"):\n        return []\n    compiler = conanfile.settings.get_safe(\"compiler\")\n    threads = conanfile.settings.get_safe(\"compiler.threads\")\n    if compiler == \"emcc\":\n        if threads == \"posix\":\n            return [\"-pthread\"]\n        elif threads == \"wasm_workers\":\n            return [\"-sWASM_WORKERS=1\"]\n    return []\n\n\ndef llvm_clang_front(conanfile):\n    # Only Windows clang with MSVC backend (LLVM/Clang, not MSYS2 clang)\n    if (conanfile.settings.get_safe(\"os\") != \"Windows\" or\n            conanfile.settings.get_safe(\"compiler\") != \"clang\" or\n            not conanfile.settings.get_safe(\"compiler.runtime\")):\n        return\n    compilers = conanfile.conf.get(\"tools.build:compiler_executables\", default={})\n    if \"clang-cl\" in compilers.get(\"c\", \"\") or \"clang-cl\" in compilers.get(\"cpp\", \"\"):\n        return \"clang-cl\"  # The MSVC-compatible front\n    return \"clang\"  # The GNU-compatible front\n\n\ndef cppstd_flag(conanfile) -> str:\n    \"\"\"\n    Returns flags specific to the C++ standard based on the ``conanfile.settings.compiler``,\n    ``conanfile.settings.compiler.version`` and ``conanfile.settings.compiler.cppstd``.\n\n    It also considers when using GNU extension in ``settings.compiler.cppstd``, reflecting it in the\n    compiler flag. Currently, it supports GCC, Clang, AppleClang, MSVC, Intel, MCST-LCC.\n\n    In case there is no ``settings.compiler`` or ``settings.cppstd`` in the profile, the result will\n    be an **empty string**.\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :return: ``str`` with the standard C++ flag used by the compiler. e.g. \"-std=c++11\", \"/std:c++latest\"\n    \"\"\"\n    compiler = conanfile.settings.get_safe(\"compiler\")\n    compiler_version = conanfile.settings.get_safe(\"compiler.version\")\n    cppstd = conanfile.settings.get_safe(\"compiler.cppstd\")\n\n    if not compiler or not compiler_version or not cppstd:\n        return \"\"\n\n    if disable_flag(conanfile, \"cppstd\"):\n        return \"\"\n\n    func = {\"gcc\": _cppstd_gcc,\n            \"clang\": _cppstd_clang,\n            \"apple-clang\": _cppstd_apple_clang,\n            \"msvc\": _cppstd_msvc,\n            \"intel-cc\": _cppstd_intel_cc,\n            \"mcst-lcc\": _cppstd_mcst_lcc}.get(compiler)\n    flag = None\n    if func:\n        flag = func(Version(compiler_version), str(cppstd))\n    if flag and llvm_clang_front(conanfile) == \"clang-cl\":\n        flag = flag.replace(\"=\", \":\")\n    return flag\n\n\ndef cppstd_msvc_flag(visual_version, cppstd):\n    # https://docs.microsoft.com/en-us/cpp/build/reference/std-specify-language-standard-version\n    if cppstd == \"23\":\n        if visual_version >= \"193\":\n            return \"c++latest\"\n    elif cppstd == \"20\":\n        if visual_version >= \"192\":\n            return \"c++20\"\n        elif visual_version >= \"191\":\n            return \"c++latest\"\n    elif cppstd == \"17\":\n        if visual_version >= \"191\":\n            return \"c++17\"\n        elif visual_version >= \"190\":\n            return \"c++latest\"\n    elif cppstd == \"14\":\n        if visual_version >= \"190\":\n            return \"c++14\"\n\n    return None\n\n\ndef _cppstd_msvc(visual_version, cppstd):\n    flag = cppstd_msvc_flag(visual_version, cppstd)\n    return f'/std:{flag}' if flag else None\n\n\ndef _cppstd_apple_clang(clang_version, cppstd):\n    \"\"\"\n    Inspired in:\n    https://github.com/Kitware/CMake/blob/master/Modules/Compiler/AppleClang-CXX.cmake\n    \"\"\"\n\n    v98 = vgnu98 = v11 = vgnu11 = v14 = vgnu14 = v17 = vgnu17 = v20 = vgnu20 = v23 = vgnu23 = v26 = vgnu26 = None\n\n    if clang_version >= \"4.0\":\n        v98 = \"c++98\"\n        vgnu98 = \"gnu++98\"\n        v11 = \"c++11\"\n        vgnu11 = \"gnu++11\"\n\n    if clang_version >= \"6.1\":\n        v14 = \"c++14\"\n        vgnu14 = \"gnu++14\"\n    elif clang_version >= \"5.1\":\n        v14 = \"c++1y\"\n        vgnu14 = \"gnu++1y\"\n\n    # Not confirmed that it didn't work before 9.1 but 1z is still valid, so we are ok\n    # Note: cmake allows c++17 since version 10.0\n    if clang_version >= \"9.1\":\n        v17 = \"c++17\"\n        vgnu17 = \"gnu++17\"\n    elif clang_version >= \"6.1\":\n        v17 = \"c++1z\"\n        vgnu17 = \"gnu++1z\"\n\n    if clang_version >= \"13.0\":\n        v20 = \"c++20\"\n        vgnu20 = \"gnu++20\"\n    elif clang_version >= \"10.0\":\n        v20 = \"c++2a\"\n        vgnu20 = \"gnu++2a\"\n\n    if clang_version >= \"16.0\":\n        v23 = \"c++23\"\n        vgnu23 = \"gnu++23\"\n\n        v26 = \"c++26\"\n        vgnu26 = \"gnu++26\"\n    elif clang_version >= \"13.0\":\n        v23 = \"c++2b\"\n        vgnu23 = \"gnu++2b\"\n\n    flag = {\"98\": v98, \"gnu98\": vgnu98,\n            \"11\": v11, \"gnu11\": vgnu11,\n            \"14\": v14, \"gnu14\": vgnu14,\n            \"17\": v17, \"gnu17\": vgnu17,\n            \"20\": v20, \"gnu20\": vgnu20,\n            \"23\": v23, \"gnu23\": vgnu23,\n            \"26\": v26, \"gnu26\": vgnu26}.get(cppstd)\n\n    return f'-std={flag}' if flag else None\n\n\ndef _cppstd_clang(clang_version, cppstd):\n    \"\"\"\n    Inspired in:\n    https://github.com/Kitware/CMake/blob/\n    1fe2dc5ef2a1f262b125a2ba6a85f624ce150dd2/Modules/Compiler/Clang-CXX.cmake\n\n    https://clang.llvm.org/cxx_status.html\n    \"\"\"\n    v98 = vgnu98 = v11 = vgnu11 = v14 = vgnu14 = v17 = vgnu17 = v20 = vgnu20 = v23 = vgnu23 = v26 = vgnu26 = None\n\n    if clang_version >= \"2.1\":\n        v98 = \"c++98\"\n        vgnu98 = \"gnu++98\"\n\n    if clang_version >= \"3.1\":\n        v11 = \"c++11\"\n        vgnu11 = \"gnu++11\"\n    elif clang_version >= \"2.1\":\n        v11 = \"c++0x\"\n        vgnu11 = \"gnu++0x\"\n\n    if clang_version >= \"3.5\":\n        v14 = \"c++14\"\n        vgnu14 = \"gnu++14\"\n    elif clang_version >= \"3.4\":\n        v14 = \"c++1y\"\n        vgnu14 = \"gnu++1y\"\n\n    if clang_version >= \"5\":\n        v17 = \"c++17\"\n        vgnu17 = \"gnu++17\"\n    elif clang_version >= \"3.5\":\n        v17 = \"c++1z\"\n        vgnu17 = \"gnu++1z\"\n\n    if clang_version >= \"6\":\n        v20 = \"c++2a\"\n        vgnu20 = \"gnu++2a\"\n\n    if clang_version >= \"12\":\n        v20 = \"c++20\"\n        vgnu20 = \"gnu++20\"\n\n        v23 = \"c++2b\"\n        vgnu23 = \"gnu++2b\"\n\n    if clang_version >= \"17\":\n        v23 = \"c++23\"\n        vgnu23 = \"gnu++23\"\n\n        v26 = \"c++26\"\n        vgnu26 = \"gnu++26\"\n\n    flag = {\"98\": v98, \"gnu98\": vgnu98,\n            \"11\": v11, \"gnu11\": vgnu11,\n            \"14\": v14, \"gnu14\": vgnu14,\n            \"17\": v17, \"gnu17\": vgnu17,\n            \"20\": v20, \"gnu20\": vgnu20,\n            \"23\": v23, \"gnu23\": vgnu23,\n            \"26\": v26, \"gnu26\": vgnu26}.get(cppstd)\n    return f'-std={flag}' if flag else None\n\n\ndef _cppstd_gcc(gcc_version, cppstd):\n    \"\"\"https://github.com/Kitware/CMake/blob/master/Modules/Compiler/GNU-CXX.cmake\"\"\"\n    # https://gcc.gnu.org/projects/cxx-status.html\n    v98 = vgnu98 = v11 = vgnu11 = v14 = vgnu14 = v17 = vgnu17 = v20 = vgnu20 = v23 = vgnu23 = v26 = vgnu26 = None\n\n    if gcc_version >= \"3.4\":\n        v98 = \"c++98\"\n        vgnu98 = \"gnu++98\"\n\n    if gcc_version >= \"4.7\":\n        v11 = \"c++11\"\n        vgnu11 = \"gnu++11\"\n    elif gcc_version >= \"4.3\":\n        v11 = \"c++0x\"\n        vgnu11 = \"gnu++0x\"\n\n    if gcc_version >= \"4.9\":\n        v14 = \"c++14\"\n        vgnu14 = \"gnu++14\"\n    elif gcc_version >= \"4.8\":\n        v14 = \"c++1y\"\n        vgnu14 = \"gnu++1y\"\n\n    if gcc_version >= \"5\":\n        v17 = \"c++1z\"\n        vgnu17 = \"gnu++1z\"\n\n    if gcc_version >= \"5.2\":  # Not sure if even in 5.1 gnu17 is valid, but gnu1z is\n        v17 = \"c++17\"\n        vgnu17 = \"gnu++17\"\n\n    if gcc_version >= \"8\":\n        v20 = \"c++2a\"\n        vgnu20 = \"gnu++2a\"\n\n    if gcc_version >= \"10\":\n        v20 = \"c++20\"\n        vgnu20 = \"gnu++20\"\n\n    if gcc_version >= \"11\":\n        v23 = \"c++23\"\n        vgnu23 = \"gnu++23\"\n\n    if gcc_version >= \"14\":\n        v26 = \"c++26\"\n        vgnu26 = \"gnu++26\"\n\n    flag = {\"98\": v98, \"gnu98\": vgnu98,\n            \"11\": v11, \"gnu11\": vgnu11,\n            \"14\": v14, \"gnu14\": vgnu14,\n            \"17\": v17, \"gnu17\": vgnu17,\n            \"20\": v20, \"gnu20\": vgnu20,\n            \"23\": v23, \"gnu23\": vgnu23,\n            \"26\": v26, \"gnu26\": vgnu26}.get(cppstd)\n    return f'-std={flag}' if flag else None\n\n\ndef _cppstd_mcst_lcc(mcst_lcc_version, cppstd):\n    v11 = vgnu11 = v14 = vgnu14 = v17 = vgnu17 = v20 = vgnu20 = None\n\n    if mcst_lcc_version >= \"1.21\":\n        v11 = \"c++11\"\n        vgnu11 = \"gnu++11\"\n        v14 = \"c++14\"\n        vgnu14 = \"gnu++14\"\n\n    if mcst_lcc_version >= \"1.24\":\n        v17 = \"c++17\"\n        vgnu17 = \"gnu++17\"\n\n    if mcst_lcc_version >= \"1.25\":\n        v20 = \"c++2a\"\n        vgnu20 = \"gnu++2a\"\n\n    # FIXME: What is this \"03\"?? that is not a valid cppstd in the settings.yml\n    flag = {\"98\": \"c++98\", \"gnu98\": \"gnu++98\",\n            \"03\": \"c++03\", \"gnu03\": \"gnu++03\",\n            \"11\": v11, \"gnu11\": vgnu11,\n            \"14\": v14, \"gnu14\": vgnu14,\n            \"17\": v17, \"gnu17\": vgnu17,\n            \"20\": v20, \"gnu20\": vgnu20}.get(cppstd)\n    return f'-std={flag}' if flag else None\n\n\ndef _cppstd_intel_cc(_, cppstd):\n    \"\"\"\n    Inspired in:\n    https://software.intel.com/content/www/us/en/develop/documentation/\n    oneapi-dpcpp-cpp-compiler-dev-guide-and-reference/top/compiler-reference/\n    compiler-options/compiler-option-details/language-options/std-qstd.html\n    \"\"\"\n    # Note: for now, we don't care about compiler version\n    v98 = \"c++98\"\n    vgnu98 = \"gnu++98\"\n    v03 = \"c++03\"\n    vgnu03 = \"gnu++03\"\n    v11 = \"c++11\"\n    vgnu11 = \"gnu++11\"\n    v14 = \"c++14\"\n    vgnu14 = \"gnu++14\"\n    v17 = \"c++17\"\n    vgnu17 = \"gnu++17\"\n    v20 = \"c++20\"\n    vgnu20 = \"gnu++20\"\n    v23 = \"c++2b\"\n    vgnu23 = \"gnu++2b\"\n\n    flag = {\"98\": v98, \"gnu98\": vgnu98,\n            \"03\": v03, \"gnu03\": vgnu03,\n            \"11\": v11, \"gnu11\": vgnu11,\n            \"14\": v14, \"gnu14\": vgnu14,\n            \"17\": v17, \"gnu17\": vgnu17,\n            \"20\": v20, \"gnu20\": vgnu20,\n            \"23\": v23, \"gnu23\": vgnu23}.get(cppstd)\n    return f'-std={flag}' if flag else None\n\n\ndef cstd_flag(conanfile) -> str:\n    \"\"\"\n    Returns flags specific to the C+standard based on the ``conanfile.settings.compiler``,\n    ``conanfile.settings.compiler.version`` and ``conanfile.settings.compiler.cstd``.\n\n    It also considers when using GNU extension in ``settings.compiler.cstd``, reflecting it in the\n    compiler flag. Currently, it supports GCC, Clang, AppleClang, MSVC, Intel, MCST-LCC.\n\n    In case there is no ``settings.compiler`` or ``settings.cstd`` in the profile, the result will\n    be an **empty string**.\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :return: ``str`` with the standard C flag used by the compiler.\n    \"\"\"\n    compiler = conanfile.settings.get_safe(\"compiler\")\n    compiler_version = conanfile.settings.get_safe(\"compiler.version\")\n    cstd = conanfile.settings.get_safe(\"compiler.cstd\")\n\n    if not compiler or not compiler_version or not cstd:\n        return \"\"\n\n    if disable_flag(conanfile, \"cstd\"):\n        return \"\"\n\n    func = {\"gcc\": _cstd_gcc,\n            \"clang\": _cstd_clang,\n            \"apple-clang\": _cstd_apple_clang,\n            \"msvc\": _cstd_msvc}.get(compiler)\n    flag = None\n    if func:\n        flag = func(Version(compiler_version), str(cstd))\n    return flag\n\n\ndef _cstd_gcc(gcc_version, cstd):\n    # TODO: Verify flags per version\n    flag = {\"99\": \"c99\",\n            \"11\": \"c11\",\n            \"17\": \"c17\",\n            \"23\": \"c23\"}.get(cstd, cstd)\n    return f'-std={flag}' if flag else None\n\n\ndef _cstd_clang(gcc_version, cstd):\n    # TODO: Verify flags per version\n    flag = {\"99\": \"c99\",\n            \"11\": \"c11\",\n            \"17\": \"c17\",\n            \"23\": \"c23\"}.get(cstd, cstd)\n    return f'-std={flag}' if flag else None\n\n\ndef _cstd_apple_clang(gcc_version, cstd):\n    # TODO: Verify flags per version\n    flag = {\"99\": \"c99\",\n            \"11\": \"c11\",\n            \"17\": \"c17\",\n            \"23\": \"c23\"}.get(cstd, cstd)\n    return f'-std={flag}' if flag else None\n\n\ndef cstd_msvc_flag(visual_version, cstd):\n    if cstd == \"17\":\n        if visual_version >= \"192\":\n            return \"c17\"\n    elif cstd == \"11\":\n        if visual_version >= \"192\":\n            return \"c11\"\n    return None\n\n\ndef _cstd_msvc(visual_version, cstd):\n    flag = cstd_msvc_flag(visual_version, cstd)\n    return f'/std:{flag}' if flag else None\n"
  },
  {
    "path": "conan/tools/build/stdcpp_library.py",
    "content": "\ndef stdcpp_library(conanfile):\n    \"\"\" Returns the name of the C++ standard library that can be passed\n    to the linker, based on the current settings. Returs None if the name \n    of the C++ standard library file is not known.\n    \"\"\"\n    libcxx = conanfile.settings.get_safe(\"compiler.libcxx\")\n    if libcxx in [\"libstdc++\", \"libstdc++11\"]:\n        return \"stdc++\"\n    elif libcxx in [\"libc++\"]:\n        return \"c++\"\n    elif libcxx in [\"c++_shared\"]:\n        return \"c++_shared\"\n    elif libcxx in [\"c++_static\"]:\n        return \"c++_static\"\n    return None\n"
  },
  {
    "path": "conan/tools/cmake/__init__.py",
    "content": "from conan.tools.cmake.toolchain.toolchain import CMakeToolchain\nfrom conan.tools.cmake.cmake import CMake\nfrom conan.tools.cmake.cmakeconfigdeps.cmakeconfigdeps import CMakeConfigDeps\nfrom conan.tools.cmake.layout import cmake_layout\n\n\ndef CMakeDeps(conanfile):  # noqa\n    if conanfile.conf.get(\"tools.cmake.cmakedeps:new\",\n                          choices=[\"will_break_next\", \"recipe_will_break\"]) == \"will_break_next\":\n        conanfile.output.warning(\"On the fly replacement of CMakeDeps by CMakeConfigDeps generator, \"\n                                 \"because 'tools.cmake.cmakedeps:new' incubating conf activated. \"\n                                 \"This conf is incubating and will break in next releases. \"\n                                 \"CMakeConfigDeps is now experimental and can be used as such in \"\n                                 \"recipes.\")\n        return CMakeConfigDeps(conanfile)\n    from conan.tools.cmake.cmakedeps.cmakedeps import CMakeDeps as _CMakeDeps\n    return _CMakeDeps(conanfile)\n"
  },
  {
    "path": "conan/tools/cmake/cmake.py",
    "content": "import os\n\nfrom conan.tools.build import build_jobs, cmd_args_to_string\nfrom conan.tools.cmake.presets import load_cmake_presets\nfrom conan.tools.cmake.utils import is_multi_configuration\nfrom conan.tools.files import chdir, mkdir\nfrom conan.tools.microsoft.msbuild import msbuild_verbosity_cmd_line_arg\nfrom conan.errors import ConanException\n\n\ndef _cmake_cmd_line_args(conanfile, generator):\n    args = []\n    if not generator:\n        return args\n\n    # Arguments related to parallel\n    njobs = build_jobs(conanfile)\n    if njobs and (\"Makefiles\" in generator or \"Ninja\" in generator) and \"NMake\" not in generator:\n        args.append(\"-j{}\".format(njobs))\n\n    maxcpucount = conanfile.conf.get(\"tools.microsoft.msbuild:max_cpu_count\", check_type=int)\n    if maxcpucount is not None and \"Visual Studio\" in generator:\n        args.append(f\"/m:{maxcpucount}\" if maxcpucount > 0 else \"/m\")\n\n    # Arguments for verbosity\n    if \"Visual Studio\" in generator:\n        verbosity = msbuild_verbosity_cmd_line_arg(conanfile)\n        if verbosity:\n            # trying to avoid issues with powershell and - : characters preceded by --\n            # -verbosity -> /verbosity\n            # https://github.com/PowerShell/PowerShell/issues/17399\n            if conanfile.conf.get(\"tools.env.virtualenv:powershell\"):\n                verbosity = verbosity.replace('-', '/', 1)\n            args.append(verbosity)\n\n    return args\n\n\nclass CMake:\n    \"\"\" CMake helper to use together with the CMakeToolchain feature \"\"\"\n\n    def __init__(self, conanfile):\n        \"\"\"\n        :param conanfile: The current recipe object. Always use ``self``.\n        \"\"\"\n        # Store a reference to useful data\n        self._conanfile = conanfile\n\n        cmake_presets = load_cmake_presets(conanfile.generators_folder)\n        # Conan generated presets will have exactly 1 configurePresets, no more\n        configure_preset = cmake_presets[\"configurePresets\"][0]\n\n        self._generator = configure_preset[\"generator\"]\n        self._toolchain_file = configure_preset.get(\"toolchainFile\")\n        self._cache_variables = configure_preset[\"cacheVariables\"]\n\n        self._cmake_program = conanfile.conf.get(\"tools.cmake:cmake_program\", default=\"cmake\")\n\n    @property\n    def is_multi_configuration(self):\n        return is_multi_configuration(self._generator)\n\n    def configure(self, variables=None, build_script_folder=None, cli_args=None,\n                  stdout=None, stderr=None, subfolder=None):\n        \"\"\"\n\n        Reads the ``CMakePresets.json`` file generated by the\n        :ref:`CMakeToolchain<conan-cmake-toolchain>` to get:\n\n           - The generator, to append ``-G=\"xxx\"``.\n           - Toolchain path to append ``-DCMAKE_TOOLCHAIN_FILE=/path/conan_toolchain.cmake``\n           - The declared ``cache variables`` to append ``-Dxxx``.\n\n        and call ``cmake``.\n\n        :param variables: Should be a dictionary of CMake variables and values, that will be mapped\n                          to command line ``-DVAR=VALUE`` arguments.\n                          Recall that in the general case information to CMake should be passed in\n                          ``CMakeToolchain`` to be provided in the ``conan_toolchain.cmake`` file.\n                          This ``variables`` argument is intended for exceptional cases that wouldn't\n                          work in the toolchain approach.\n        :param build_script_folder: Path to the CMakeLists.txt in case it is not in the declared\n                                    ``self.folders.source`` at the ``layout()`` method.\n        :param cli_args: List of arguments ``[arg1, arg2, ...]`` that will be passed\n                         as extra CLI arguments to pass to cmake invocation\n        :param subfolder: (Experimental): subfolder to be created inside the ``build_folder`` and\n                                          the ``package_folder``. If not provided, files will be\n                                          placed in the ``build_folder`` and ``package_folder`` root.\n        :param stdout: Use it to redirect stdout to this stream\n        :param stderr: Use it to redirect stderr to this stream\n        \"\"\"\n        self._conanfile.output.info(\"Running CMake.configure()\")\n        cmakelist_folder = self._conanfile.source_folder\n        if build_script_folder:\n            cmakelist_folder = os.path.join(self._conanfile.source_folder, build_script_folder)\n        cmakelist_folder = cmakelist_folder.replace(\"\\\\\", \"/\")\n\n        build_folder = self._conanfile.build_folder\n        if subfolder:\n            build_folder = os.path.join(self._conanfile.build_folder, subfolder)\n        mkdir(self._conanfile, build_folder)\n\n        arg_list = [self._cmake_program]\n        if self._generator:\n            arg_list.append('-G \"{}\"'.format(self._generator))\n        if self._toolchain_file:\n            toolpath = self._toolchain_file\n            if subfolder:\n                toolpath = os.path.relpath(self._toolchain_file, start=subfolder)\n            toolpath = toolpath.replace(\"\\\\\", \"/\")\n            arg_list.append('-DCMAKE_TOOLCHAIN_FILE=\"{}\"'.format(toolpath))\n        if self._conanfile.package_folder:\n            pkg_folder = self._conanfile.package_folder.replace(\"\\\\\", \"/\")\n            arg_list.append('-DCMAKE_INSTALL_PREFIX=\"{}\"'.format(pkg_folder))\n\n        if not variables:\n            variables = {}\n        self._cache_variables.update(variables)\n\n        arg_list.extend(['-D{}=\"{}\"'.format(k, v) for k, v in self._cache_variables.items()])\n\n        arg_list.append('\"{}\"'.format(cmakelist_folder))\n\n        if not cli_args or (\"--log-level\" not in cli_args and \"--loglevel\" not in cli_args):\n            arg_list.extend(self._cmake_log_levels_args)\n\n        if cli_args:\n            arg_list.extend(cli_args)\n\n        command = \" \".join(arg_list)\n        with chdir(self, build_folder):\n            self._conanfile.run(command, stdout=stdout, stderr=stderr)\n\n    def _config_arg(self, build_type):\n        \"\"\" computes the '--config Release' arg when necessary, or warn or error if wrong\n        \"\"\"\n        is_multi = is_multi_configuration(self._generator)\n        if build_type and not is_multi:\n            self._conanfile.output.error(\"Don't specify 'build_type' at build time for \"\n                                         \"single-config build systems\")\n        if not build_type:\n            try:\n                build_type = self._conanfile.settings.build_type  # declared, but can be None\n                if not build_type:\n                    raise ConanException(\"CMake: build_type setting should be defined.\")\n            except ConanException:\n                if is_multi:\n                    raise ConanException(\"CMake: build_type setting should be defined.\")\n        build_config = \"--config {}\".format(build_type) if build_type and is_multi else \"\"\n        return build_config\n\n    def _build(self, build_type=None, target=None, cli_args=None, build_tool_args=None, env=\"\",\n               stdout=None, stderr=None, subfolder=None):\n        bf = self._conanfile.build_folder\n        if subfolder:\n            bf = os.path.join(self._conanfile.build_folder, subfolder)\n        build_config = self._config_arg(build_type)\n\n        args = []\n        if target is not None:\n            target_list = [target] if isinstance(target, str) else target\n            args.extend([\"--target\"] + target_list)\n\n        if cli_args:\n            args.extend(cli_args)\n\n        cmd_line_args = _cmake_cmd_line_args(self._conanfile, self._generator)\n        if build_tool_args:\n            cmd_line_args.extend(build_tool_args)\n\n        args.extend(self._compilation_verbosity_arg)\n\n        if cmd_line_args:\n            args += ['--'] + cmd_line_args\n\n        arg_list = ['\"{}\"'.format(bf), build_config, cmd_args_to_string(args)]\n        arg_list = \" \".join(filter(None, arg_list))\n        command = \"%s --build %s\" % (self._cmake_program, arg_list)\n        self._conanfile.run(command, env=env, stdout=stdout, stderr=stderr)\n\n    def build(self, build_type=None, target=None, cli_args=None, build_tool_args=None,\n              stdout=None, stderr=None, subfolder=None):\n        \"\"\"\n\n        :param build_type: Use it only to override the value defined in the ``settings.build_type``\n                           for a multi-configuration generator (e.g. Visual Studio, XCode).\n                           This value will be ignored for single-configuration generators, they will\n                           use the one defined in the toolchain file during the install step.\n        :param target: The name of a single build target as a string, or names of multiple build\n                       targets in a list of strings to be passed to the ``--target`` argument.\n        :param cli_args: A list of arguments ``[arg1, arg2, ...]`` that will be passed to the\n                         ``cmake --build ... arg1 arg2`` command directly.\n        :param build_tool_args: A list of arguments ``[barg1, barg2, ...]`` for the underlying\n                                build system that will be passed to the command\n                                line after the ``--`` indicator: ``cmake --build ... -- barg1 barg2``\n        :param subfolder: (Experimental): subfolder to be created inside the ``build_folder`` and\n                                          the ``package_folder``. If not provided, files will be\n                                          placed in the ``build_folder`` and ``package_folder`` root.\n        :param stdout: Use it to redirect stdout to this stream\n        :param stderr: Use it to redirect stderr to this stream\n        \"\"\"\n        self._conanfile.output.info(\"Running CMake.build()\")\n        self._build(build_type, target, cli_args, build_tool_args, subfolder=subfolder,\n                    stdout=stdout, stderr=stderr)\n\n    def install(self, build_type=None, component=None, cli_args=None, stdout=None, stderr=None,\n                subfolder=None):\n        \"\"\"\n        Equivalent to running ``cmake --install``\n\n        :param component: The specific component to install, if any\n        :param build_type: Use it only to override the value defined in the settings.build_type.\n                           It can fail if the build is single configuration (e.g. Unix Makefiles),\n                           as in that case the build type must be specified at configure time,\n                           not build type.\n        :param cli_args: A list of arguments ``[arg1, arg2, ...]`` for the underlying build system\n                         that will be passed to the command line: ``cmake --install ... arg1 arg2``\n        :param subfolder: (Experimental): subfolder to be created inside the ``build_folder`` and\n                                          the ``package_folder``. If not provided, files will be\n                                          placed in the ``build_folder`` and ``package_folder`` root.\n        :param stdout: Use it to redirect stdout to this stream\n        :param stderr: Use it to redirect stderr to this stream\n        \"\"\"\n        self._conanfile.output.info(\"Running CMake.install()\")\n        package_folder = self._conanfile.package_folder\n        build_folder = self._conanfile.build_folder\n        if subfolder:\n            package_folder = os.path.join(self._conanfile.package_folder, subfolder)\n            build_folder = os.path.join(self._conanfile.build_folder, subfolder)\n        mkdir(self._conanfile, package_folder)\n\n        build_config = self._config_arg(build_type)\n\n        pkg_folder = '\"{}\"'.format(package_folder.replace(\"\\\\\", \"/\"))\n        build_folder = '\"{}\"'.format(build_folder.replace(\"\\\\\", \"/\"))\n        arg_list = [\"--install\", build_folder, build_config, \"--prefix\", pkg_folder]\n        if component:\n            arg_list.extend([\"--component\", component])\n        arg_list.extend(self._compilation_verbosity_arg)\n\n        deprecated_install_strip = self._conanfile.conf.get(\"tools.cmake:install_strip\",\n                                                            check_type=bool)\n        if deprecated_install_strip:\n            self._conanfile.output.warning(\"The 'tools.cmake:install_strip' configuration is \"\n                                           \"deprecated, use 'tools.build:install_strip' instead.\",\n                                           warn_tag=\"deprecated\")\n\n        do_strip = self._conanfile.conf.get(\"tools.build:install_strip\", check_type=bool)\n        if do_strip or deprecated_install_strip:\n            arg_list.append(\"--strip\")\n\n        if cli_args:\n            if \"--install\" in cli_args:\n                raise ConanException(\"Do not pass '--install' argument to 'install()'\")\n            arg_list.extend(cli_args)\n\n        arg_list = \" \".join(filter(None, arg_list))\n        command = \"%s %s\" % (self._cmake_program, arg_list)\n        self._conanfile.run(command, stdout=stdout, stderr=stderr)\n\n    def test(self, build_type=None, target=None, cli_args=None, build_tool_args=None, env=\"\",\n             stdout=None, stderr=None):\n        \"\"\"\n        Equivalent to running cmake --build . --target=RUN_TESTS.\n\n        :param build_type: Use it only to override the value defined in the ``settings.build_type``.\n                           It can fail if the build is single configuration (e.g. Unix Makefiles), as\n                           in that case the build type must be specified at configure time, not build\n                           time.\n        :param target: Name of the build target to run, by default ``RUN_TESTS`` or ``test``\n        :param cli_args: Same as above ``build()``, a list of arguments ``[arg1, arg2, ...]``\n                         to be passed as extra arguments for the underlying build system\n        :param build_tool_args: Same as above ``build()``\n        :param stdout: Use it to redirect stdout to this stream\n        :param stderr: Use it to redirect stderr to this stream\n        \"\"\"\n        if self._conanfile.conf.get(\"tools.build:skip_test\", check_type=bool):\n            return\n        if not target:\n            is_multi = is_multi_configuration(self._generator)\n            is_ninja = \"Ninja\" in self._generator\n            target = \"RUN_TESTS\" if is_multi and not is_ninja else \"test\"\n\n        # CTest behavior controlled by CTEST_ env-vars should be directly defined in [buildenv]\n        # The default for ``test()`` is both the buildenv and the runenv\n        env = [\"conanbuild\", \"conanrun\"] if env == \"\" else env\n        self._build(build_type=build_type, target=target, cli_args=cli_args,\n                    build_tool_args=build_tool_args, env=env, stdout=stdout, stderr=stderr)\n\n    def ctest(self, cli_args=None, env=\"\", stdout=None, stderr=None):\n        \"\"\"\n        Equivalent to running ctest ...\n\n        :param cli_args: List of arguments ``[arg1, arg2, ...]`` to be passed as extra ctest\n                         command line arguments\n        :param env: the environment files to activate, by default conanbuild + conanrun\n        :param stdout: Use it to redirect stdout to this stream\n        :param stderr: Use it to redirect stderr to this stream\n        \"\"\"\n        if self._conanfile.conf.get(\"tools.build:skip_test\", check_type=bool):\n            return\n\n        arg_list = []\n        bt = self._conanfile.settings.get_safe(\"build_type\")\n        is_multi = is_multi_configuration(self._generator)\n        if bt and is_multi:\n            arg_list.append(f\"--build-config {bt}\")\n        njobs = build_jobs(self._conanfile)\n        if njobs:\n            arg_list.append(f\"--parallel {njobs}\")\n\n        arg_list.extend(cli_args or [])\n\n        verbosity = self._conanfile.conf.get(\"tools.build:verbosity\", choices=(\"quiet\", \"verbose\"))\n        if verbosity:\n            # https://cmake.org/cmake/help/latest/manual/ctest.1.html\n            # Options such as --verbose, --extra-verbose, and --debug are\n            # ignored if --quiet is specified.\n            arg_list.append(f\"--{verbosity}\")\n\n        extra_args = self._conanfile.conf.get(\"tools.cmake:ctest_args\", check_type=list)\n        if extra_args:\n            arg_list.extend(extra_args)\n\n        arg_list = \" \".join(filter(None, arg_list))\n        command = f\"ctest {arg_list}\"\n\n        env = [\"conanbuild\", \"conanrun\"] if env == \"\" else env\n        self._conanfile.run(command, env=env, stdout=stdout, stderr=stderr)\n\n    @property\n    def _compilation_verbosity_arg(self):\n        \"\"\"\n        Controls build tool verbosity, that is, those controlled by -DCMAKE_VERBOSE_MAKEFILE\n        See https://cmake.org/cmake/help/latest/manual/cmake.1.html#cmdoption-cmake-build-v\n        \"\"\"\n        verbosity = self._conanfile.conf.get(\"tools.compilation:verbosity\",\n                                             choices=(\"quiet\", \"verbose\"))\n        return [\"--verbose\"] if verbosity == \"verbose\" else []\n\n    @property\n    def _cmake_log_levels_args(self):\n        \"\"\"\n        Controls CMake's own verbosity levels.\n        See https://cmake.org/cmake/help/latest/manual/cmake.1.html#cmdoption-cmake-log-level\n        :return:\n        \"\"\"\n        log_level = self._conanfile.conf.get(\"tools.build:verbosity\", choices=(\"quiet\", \"verbose\"))\n        if log_level == \"quiet\":\n            log_level = \"error\"\n        return [\"--loglevel=\" + log_level.upper()] if log_level is not None else []\n"
  },
  {
    "path": "conan/tools/cmake/cmakeconfigdeps/__init__.py",
    "content": ""
  },
  {
    "path": "conan/tools/cmake/cmakeconfigdeps/cmakeconfigdeps.py",
    "content": "import glob\nimport os\nimport re\nimport textwrap\n\nfrom jinja2 import Template\n\nfrom conan.api.output import Color, ConanOutput\nfrom conan.errors import ConanException\nfrom conan.internal import check_duplicated_generator\nfrom conan.internal.api.install.generators import relativize_path\nfrom conan.internal.model.dependencies import get_transitive_requires\nfrom conan.tools.cmake.cmakeconfigdeps.config import ConfigTemplate2\nfrom conan.tools.cmake.cmakeconfigdeps.config_version import ConfigVersionTemplate2\nfrom conan.tools.cmake.cmakeconfigdeps.target_configuration import TargetConfigurationTemplate2\nfrom conan.tools.cmake.cmakeconfigdeps.targets import TargetsTemplate2\nfrom conan.tools.files import save\nfrom conan.internal.util.files import load\n\nFIND_MODE_MODULE = \"module\"\nFIND_MODE_CONFIG = \"config\"\nFIND_MODE_NONE = \"none\"\nFIND_MODE_BOTH = \"both\"\n\n\nclass CMakeConfigDeps:\n\n    def __init__(self, conanfile):\n        \"\"\"\n        :param conanfile: ``< ConanFile object >`` The current recipe object. Always use ``self``.\n        \"\"\"\n        self._conanfile = conanfile\n        self.configuration = str(self._conanfile.settings.build_type)\n\n        # These are just for legacy compatibility, but not use at al\n        self._build_context_activated = []\n        self._build_context_build_modules = []\n        self._build_context_suffix = {}\n        # Enable/Disable checking if a component target exists or not\n        self._check_components_exist = False\n\n        self._properties = {}\n\n    @property\n    def build_context_activated(self):\n        return self._build_context_activated\n\n    @build_context_activated.setter\n    def build_context_activated(self, value):\n        self._conanfile.output.warning(\"CMakeConfigDeps.build_context_activated is deprecated, \"\n                                       \"not used anymore\", warn_tag=\"deprecated\")\n        self._build_context_activated = value\n\n    @property\n    def build_context_build_modules(self):\n        return self._build_context_build_modules\n\n    @build_context_build_modules.setter\n    def build_context_build_modules(self, value):\n        self._conanfile.output.warning(\"CMakeConfigDeps.build_context_build_modules is deprecated, \"\n                                       \"not used anymore\", warn_tag=\"deprecated\")\n        self._build_context_build_modules = value\n\n    @property\n    def build_context_suffix(self):\n        return self._build_context_suffix\n\n    @build_context_suffix.setter\n    def build_context_suffix(self, value):\n        self._conanfile.output.warning(\"CMakeConfigDeps.build_context_suffix is deprecated, \"\n                                       \"not used anymore\", warn_tag=\"deprecated\")\n        self._build_context_suffix = value\n\n    @property\n    def check_components_exist(self):\n        return self._check_components_exist\n\n    @check_components_exist.setter\n    def check_components_exist(self, value):\n        self._conanfile.output.warning(\"CMakeConfigDeps.check_components_exist is deprecated, \"\n                                       \"not used anymore\", warn_tag=\"deprecated\")\n        self._check_components_exist = value\n\n    def generate(self):\n        \"\"\"\n        This method will save the generated files to the ``conanfile.generators_folder`` folder\n        \"\"\"\n        self._conanfile.output.warning(\"CMakeConfigDeps is experimental, and might get \"\n                                       \"breaking changes in future releases\",\n                                       warn_tag=\"experimental\")\n        check_duplicated_generator(self, self._conanfile)\n        # Current directory is the generators_folder\n        generator_files = self._content()\n        for generator_file, content in generator_files.items():\n            save(self._conanfile, generator_file, content)\n        _PathGenerator(self, self._conanfile).generate()\n\n    def _content(self):\n        host_req = self._conanfile.dependencies.host\n        build_req = self._conanfile.dependencies.direct_build\n        test_req = self._conanfile.dependencies.test\n\n        # Iterate all the transitive requires\n        ret = {}\n        direct_deps = []\n        for require, dep in list(host_req.items()) + list(build_req.items()) + list(test_req.items()):\n            cmake_find_mode = self.get_property(\"cmake_find_mode\", dep)\n            cmake_find_mode = cmake_find_mode or FIND_MODE_CONFIG\n            cmake_find_mode = cmake_find_mode.lower()\n            if cmake_find_mode == FIND_MODE_NONE:\n                continue\n            if cmake_find_mode in (FIND_MODE_MODULE, FIND_MODE_BOTH):\n                ConanOutput(self._conanfile.ref).warning(\"CMakeConfigDeps does not support \"\n                                                         f\"module find mode in {dep}.\\n\"\n                                                         f\"Config mode will be used regardless.\",\n                                                         # Should this be risk?\n                                                         warn_tag=\"deprecated\")\n\n            if require.direct:\n                direct_deps.append((require, dep))\n            full_cpp_info = dep.cpp_info.deduce_full_cpp_info(dep)\n            config = ConfigTemplate2(self, require, dep, full_cpp_info)\n            ret[config.filename] = config.content()\n            config_version = ConfigVersionTemplate2(self, dep)\n            ret[config_version.filename] = config_version.content()\n\n            targets = TargetsTemplate2(self, dep)\n            ret[targets.filename] = targets.content()\n            target_configuration = TargetConfigurationTemplate2(self, dep, require, full_cpp_info)\n            ret[target_configuration.filename] = target_configuration.content()\n\n        self._print_help(direct_deps)\n        return ret\n\n    def _print_help(self, direct_deps):\n        if direct_deps:\n            msg = [\"CMakeDeps necessary find_package() and targets for your CMakeLists.txt\"]\n            link_targets = []\n            for (require, dep) in direct_deps:\n                note = \" # Optional. This is a tool-require, can't link its targets\" \\\n                    if require.build else \"\"\n                msg.append(f\"    find_package({self.get_cmake_filename(dep)}){note}\")\n                if not require.build and not dep.cpp_info.exe:\n                    target_name = self.get_property(\"cmake_target_name\", dep)\n                    link_targets.append(target_name or f\"{dep.ref.name}::{dep.ref.name}\")\n            if link_targets:\n                msg.append(f\"    target_link_libraries(... {' '.join(link_targets)})\")\n            self._conanfile.output.info(\"\\n\".join(msg), fg=Color.CYAN)\n\n    def set_property(self, dep, prop, value, build_context=False):\n        \"\"\"\n        Using this method you can overwrite the :ref:`property<CMakeConfigDeps Properties>` values\n        set by the Conan recipes from the consumer.\n\n        :param dep: Name of the dependency to set the :ref:`property<CMakeConfigDeps Properties>`.\n         For components use the syntax: ``dep_name::component_name``.\n        :param prop: Name of the :ref:`property<CMakeDeps Properties>`.\n        :param value: Value of the property. Use ``None`` to invalidate any value set by the\n         upstream recipe.\n        :param build_context: Set to ``True`` if you want to set the property for a dependency that\n         belongs to the build context (``False`` by default).\n        \"\"\"\n        build_suffix = \"&build\" if build_context else \"\"\n        self._properties.setdefault(f\"{dep}{build_suffix}\", {}).update({prop: value})\n\n    def get_property(self, prop, dep, comp_name=None, check_type=None):\n        dep_name = dep.ref.name\n        # Find the requirement that points to this \"dep\".\n        # TODO: It would probably be more explicit if it was an argument as \"dep\", but to keep\n        #   diff minimal\n        require = next(iter(r for r, d in self._conanfile.dependencies.items() if d is dep))\n        build_suffix = \"&build\" if require.build else \"\"\n        dep_comp = f\"{str(dep_name)}::{comp_name}\" if comp_name else f\"{str(dep_name)}\"\n        try:\n            value = self._properties[f\"{dep_comp}{build_suffix}\"][prop]\n            if check_type is not None and not isinstance(value, check_type):\n                raise ConanException(f'The expected type for {prop} is \"{check_type.__name__}\", '\n                                     f'but \"{type(value).__name__}\" was found')\n            return value\n        except KeyError:\n            # Here we are not using the cpp_info = deduce_cpp_info(dep) because it is not\n            # necessary for the properties\n            if not comp_name:\n                return dep.cpp_info.get_property(prop, check_type=check_type)\n            comp = dep.cpp_info.components.get(comp_name)  # it is a default dict\n            if comp is not None:\n                return comp.get_property(prop, check_type=check_type)\n\n    def get_cmake_filename(self, dep):\n        # Get the name of the file for the find_package(XXX)\n        # This is used by CMakeDeps to determine:\n        # - The filename to generate (XXX-config.cmake or FindXXX.cmake)\n        # - The name of the defined XXX_DIR variables\n        # - The name of transitive dependencies for calls to find_dependency\n        ret = self.get_property(\"cmake_file_name\", dep)\n        return ret or dep.ref.name\n\n    def _get_find_mode(self, dep):\n        tmp = self.get_property(\"cmake_find_mode\", dep)\n        if tmp is None:\n            return \"config\"\n        return tmp.lower()\n\n    def get_transitive_requires(self, conanfile):\n        # Prepared to filter transitive tool-requires with visible=True\n        return get_transitive_requires(self._conanfile, conanfile)\n\n\n# TODO: Repeated from CMakeToolchain blocks\ndef _join_paths(conanfile, paths):\n    paths = [p.replace('\\\\', '/').replace('$', '\\\\$').replace('\"', '\\\\\"') for p in paths]\n    paths = [relativize_path(p, conanfile, \"${CMAKE_CURRENT_LIST_DIR}\") for p in paths]\n    return \" \".join([f'\"{p}\"' for p in paths])\n\n\nclass _PathGenerator:\n    _conan_cmakedeps_paths = \"conan_cmakedeps_paths.cmake\"\n\n    def __init__(self, cmakedeps, conanfile):\n        self._conanfile = conanfile\n        self._cmakedeps = cmakedeps\n\n    def _get_cmake_paths(self, requirements, dirs_name):\n        paths = {}\n        cmake_vars = {\n            \"bindirs\": \"CMAKE_PROGRAM_PATH\",\n            \"libdirs\": \"CMAKE_LIBRARY_PATH\",\n            \"includedirs\": \"CMAKE_INCLUDE_PATH\",\n            \"frameworkdirs\": \"CMAKE_FRAMEWORK_PATH\",\n            \"builddirs\": \"CMAKE_MODULE_PATH\"\n        }\n        for req, dep in requirements:\n            cppinfo = dep.cpp_info.aggregated_components()\n            cppinfo_dirs = getattr(cppinfo, dirs_name, [])\n            if not cppinfo_dirs:\n                continue\n            previous = paths.get(req.ref.name)\n            if previous:\n                self._conanfile.output.info(f\"There is already a '{req.ref}' package contributing\"\n                                            f\" to {cmake_vars[dirs_name]}. Using the one\"\n                                            f\" defined by the context={dep.context}.\")\n            paths[req.ref.name] = cppinfo_dirs\n        return [d for dirs in paths.values() for d in dirs]\n\n    def generate(self):\n        template = textwrap.dedent(\"\"\"\\\n        set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON)\n\n        {% for pkg_name, folder in pkg_paths.items() %}\n        set({{pkg_name}}_DIR \"{{folder}}\")\n        {% endfor %}\n        {% for pkg_name, folders in pkg_paths_multi.items() %}\n        {% for folder in folders %}\n        list(APPEND CONAN_{{pkg_name}}_DIR_MULTI \"{{folder}}\")\n        {% endfor %}\n        {% endfor %}\n        {% if host_runtime_dirs %}\n        set(CONAN_RUNTIME_LIB_DIRS {{ host_runtime_dirs }} )\n        # Only for VS, needs CMake>=3.27\n        set(CMAKE_VS_DEBUGGER_ENVIRONMENT \"PATH=${CONAN_RUNTIME_LIB_DIRS};%PATH%\")\n        {% endif %}\n        {% if cmake_program_path %}\n        list(PREPEND CMAKE_PROGRAM_PATH {{ cmake_program_path }})\n        {% endif %}\n        {% if cmake_library_path %}\n        list(PREPEND CMAKE_LIBRARY_PATH {{ cmake_library_path }})\n        {% endif %}\n        {% if cmake_include_path %}\n        list(PREPEND CMAKE_INCLUDE_PATH {{ cmake_include_path }})\n        {% endif %}\n        {% if cmake_framework_path %}\n        list(PREPEND CMAKE_FRAMEWORK_PATH {{ cmake_framework_path }})\n        {% endif %}\n        # Definition of CMAKE_MODULE_PATH to be able to include(module)\n        {% if cmake_module_path %}\n        list(PREPEND CMAKE_MODULE_PATH {{ cmake_module_path }})\n        {% endif %}\n        \"\"\")\n        host_req = self._conanfile.dependencies.host\n        build_req = self._conanfile.dependencies.direct_build\n        test_req = self._conanfile.dependencies.test\n        host_test_reqs = list(host_req.items()) + list(test_req.items())\n        all_reqs = host_test_reqs + list(build_req.items())\n        # gen_folder = self._conanfile.generators_folder.replace(\"\\\\\", \"/\")\n        # if not, test_cmake_add_subdirectory test fails\n        # content.append('set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON)')\n        pkg_paths = {}\n\n        pkg_paths_multi = {}\n        if os.path.exists(self._conan_cmakedeps_paths):\n            existing_toolchain = load(self._conan_cmakedeps_paths)\n            pattern_paths = r\"list\\(APPEND CONAN_([A-Za-z0-9-_]*)_DIR_MULTI \\\"([^)]*)\\\"\\)\"\n            variable_match = re.findall(pattern_paths, existing_toolchain)\n            for (captured_name, captured_path) in variable_match:\n                path_list = pkg_paths_multi.setdefault(captured_name, [])\n                if captured_path not in path_list:\n                    path_list.append(captured_path)\n\n        for req, dep in all_reqs:\n            cmake_find_mode = self._cmakedeps.get_property(\"cmake_find_mode\", dep)\n            cmake_find_mode = cmake_find_mode or FIND_MODE_CONFIG\n            cmake_find_mode = cmake_find_mode.lower()\n\n            cmake_filename = self._cmakedeps.get_cmake_filename(dep)\n            extra_variants = self._cmakedeps.get_property(\"cmake_file_name_variants\", dep,\n                                                          check_type=list) or []\n            lowercase_variants = {variant.lower() for variant in extra_variants}\n            if len(lowercase_variants) > 1:\n                raise ConanException(f\"'{dep.ref}' 'cmake_file_name_variants' property contains different words. \"\n                                     \"They should be the same with different upper/lower cases only.\")\n            if lowercase_variants:\n                if cmake_filename.lower() not in lowercase_variants:\n                    is_cmake_filename_defined = self._cmakedeps.get_property(\"cmake_file_name\", dep) is not None\n                    if is_cmake_filename_defined:\n                        extra_variants = []\n                        msg = (f\"'{dep.ref}' 'cmake_file_name_variants' property contains names \"\n                               f\"with different casings than the defined name '{cmake_filename}'. \"\n                               f\"The specified 'cmake_file_name'='{cmake_filename}' property \"\n                               f\"will be used as the only name and the variants will be ignored.\")\n                        self._conanfile.output.warning(msg)\n                    else:\n                        msg = (f\"'{dep.ref}' 'cmake_file_name_variants' property contains entries \"\n                               f\"that differ from the default 'cmake_file_name'='{cmake_filename}'. \"\n                               f\"They should be the same with different upper/lower cases only.\")\n                        raise ConanException(msg)\n            pkg_names = set([cmake_filename] + extra_variants)\n            # https://cmake.org/cmake/help/v3.22/guide/using-dependencies/index.html\n            if cmake_find_mode == FIND_MODE_NONE:\n                cps = glob.glob(os.path.join(dep.package_folder, f\"**/{cmake_filename}.cps\"),\n                                recursive=True)\n                if cps:\n                    loc = os.path.dirname(os.path.join(dep.package_folder, cps[0]))\n                    loc = loc.replace(\"\\\\\", \"/\")\n                    relative_path = relativize_path(loc, self._conanfile,\n                                                    \"${CMAKE_CURRENT_LIST_DIR}\")\n                    for pkg_name in pkg_names:\n                        pkg_paths[pkg_name] = relative_path\n                    continue\n\n                try:\n                    # This is irrespective of the components, it should be in the root cpp_info\n                    # To define the location of the pkg-config.cmake file\n                    build_dir = dep.cpp_info.builddirs[0]\n                except IndexError:\n                    build_dir = dep.package_folder\n                pkg_folder = build_dir.replace(\"\\\\\", \"/\") if build_dir else None\n                if pkg_folder:\n                    if any(os.path.isfile(os.path.join(pkg_folder, f + ext)) for f in pkg_names\n                           for ext in (\"-config.cmake\", \"Config.cmake\")):\n                        relative_path = relativize_path(pkg_folder, self._conanfile,\n                                                        \"${CMAKE_CURRENT_LIST_DIR}\")\n                        for pkg_name in pkg_names:\n                            pkg_paths[pkg_name] = relative_path\n\n                    for pkg_name in pkg_names:\n                        existing_paths = pkg_paths_multi.setdefault(pkg_name, [])\n                        if pkg_folder not in existing_paths:\n                            existing_paths.append(pkg_folder)\n                continue\n\n            # If CMakeDeps generated, the folder is this one\n            # content.append(f'set({pkg_name}_ROOT \"{gen_folder}\")')\n            for pkg_name in pkg_names:\n                pkg_paths[pkg_name] = \"${CMAKE_CURRENT_LIST_DIR}\"\n\n        # CMAKE_PROGRAM_PATH | CMAKE_LIBRARY_PATH | CMAKE_INCLUDE_PATH\n        cmake_program_path = self._get_cmake_paths([(req, dep) for req, dep in all_reqs if req.direct], \"bindirs\")\n        cmake_library_path = self._get_cmake_paths(host_test_reqs, \"libdirs\")\n        cmake_include_path = self._get_cmake_paths(host_test_reqs, \"includedirs\")\n        cmake_framework_path = self._get_cmake_paths(host_test_reqs, \"frameworkdirs\")\n        cmake_module_path = self._get_cmake_paths(all_reqs, \"builddirs\")\n        context = {\"host_runtime_dirs\": self._get_host_runtime_dirs(),\n                   \"pkg_paths\": pkg_paths,\n                   \"pkg_paths_multi\": pkg_paths_multi,\n                   \"cmake_program_path\": _join_paths(self._conanfile, cmake_program_path),\n                   \"cmake_library_path\": _join_paths(self._conanfile, cmake_library_path),\n                   \"cmake_include_path\": _join_paths(self._conanfile, cmake_include_path),\n                   \"cmake_framework_path\": _join_paths(self._conanfile, cmake_framework_path),\n                   \"cmake_module_path\": _join_paths(self._conanfile, cmake_module_path)\n                   }\n        content = Template(template, trim_blocks=True, lstrip_blocks=True).render(context)\n        save(self._conanfile, self._conan_cmakedeps_paths, content)\n\n    def _get_host_runtime_dirs(self):\n        host_runtime_dirs = {}\n\n        # Get the previous configuration\n        if os.path.exists(self._conan_cmakedeps_paths):\n            existing_toolchain = load(self._conan_cmakedeps_paths)\n            pattern_lib_dirs = r\"set\\(CONAN_RUNTIME_LIB_DIRS ([^)]*)\\)\"\n            variable_match = re.search(pattern_lib_dirs, existing_toolchain)\n            if variable_match:\n                capture = variable_match.group(1)\n                matches = re.findall(r'\"\\$<\\$<CONFIG:([A-Za-z]*)>:([^>]*)>\"', capture)\n                for config, paths in matches:\n                    host_runtime_dirs.setdefault(config, []).append(paths)\n\n        is_win = self._conanfile.settings.get_safe(\"os\") == \"Windows\"\n\n        host_req = self._conanfile.dependencies.host\n        test_req = self._conanfile.dependencies.test\n        for req in list(host_req.values()) + list(test_req.values()):\n            config = req.settings.get_safe(\"build_type\", self._cmakedeps.configuration)\n            aggregated_cppinfo = req.cpp_info.aggregated_components()\n            runtime_dirs = aggregated_cppinfo.bindirs if is_win else aggregated_cppinfo.libdirs\n            for d in runtime_dirs:\n                d = d.replace(\"\\\\\", \"/\")\n                d = relativize_path(d, self._conanfile, \"${CMAKE_CURRENT_LIST_DIR}\")\n                existing = host_runtime_dirs.setdefault(config, [])\n                if d not in existing:\n                    existing.append(d)\n\n        return ' '.join(f'\"$<$<CONFIG:{c}>:{i}>\"' for c, v in host_runtime_dirs.items() for i in v)\n"
  },
  {
    "path": "conan/tools/cmake/cmakeconfigdeps/config.py",
    "content": "import textwrap\n\nimport jinja2\nfrom jinja2 import Template\nfrom conan.tools.cmake.utils import parse_extra_variable, cmake_escape_value\nfrom conan.internal.api.install.generators import relativize_path\n\n\nclass ConfigTemplate2:\n    \"\"\"\n    FooConfig.cmake\n    foo-config.cmake\n    \"\"\"\n    def __init__(self, cmakedeps, require, conanfile, full_cpp_info):\n        self._cmakedeps = cmakedeps\n        self._require = require\n        self._conanfile = conanfile\n        self._full_cpp_info = full_cpp_info\n\n    def content(self):\n        t = Template(self._template, trim_blocks=True, lstrip_blocks=True,\n                     undefined=jinja2.StrictUndefined)\n        return t.render(self._context)\n\n    @property\n    def filename(self):\n        f = self._cmakedeps.get_cmake_filename(self._conanfile)\n        return f\"{f}-config.cmake\" if f == f.lower() else f\"{f}Config.cmake\"\n\n    @property\n    def _context(self):\n        f = self._cmakedeps.get_cmake_filename(self._conanfile)\n        targets_include = f\"{f}Targets.cmake\"\n        pkg_name = self._conanfile.ref.name\n        build_modules_paths = self._cmakedeps.get_property(\"cmake_build_modules\", self._conanfile,\n                                                           check_type=list) or []\n        # FIXME: Proper escaping of paths for CMake and relativization\n        # FIXME: build_module_paths coming from last config only\n        build_modules_paths = [f.replace(\"\\\\\", \"/\") for f in build_modules_paths]\n        build_modules_paths = [relativize_path(p, self._cmakedeps._conanfile,\n                                               \"${CMAKE_CURRENT_LIST_DIR}\")\n                               for p in build_modules_paths]\n        components = self._cmakedeps.get_property(\"cmake_components\", self._conanfile,\n                                                  check_type=list)\n        if components is None:  # Lets compute the default components names\n            components = []\n            # This assumes that cmake_components is only defined with not multi .libs=[lib1, lib2]\n            for name in self._conanfile.cpp_info.components:\n                if name.startswith(\"_\"):  # Skip private components\n                    continue\n                comp_components = self._cmakedeps.get_property(\"cmake_components\", self._conanfile,\n                                                               name, check_type=list)\n                if comp_components:\n                    components.extend(comp_components)\n                else:\n                    cmakename = self._cmakedeps.get_property(\"cmake_target_name\", self._conanfile,\n                                                             name)\n                    if cmakename and \"::\" in cmakename:  # Remove package namespace\n                        cmakename = cmakename.split(\"::\", 1)[1]\n                    components.append(cmakename or name)\n        components = \" \".join(components) if components else \"\"\n\n        result = {\"filename\": f,\n                  \"components\": components,\n                  \"pkg_name\": pkg_name,\n                  \"targets_include_file\": targets_include,\n                  \"build_modules_paths\": build_modules_paths}\n\n        conf_extra_variables = self._conanfile.conf.get(\"tools.cmake.cmaketoolchain:extra_variables\",\n                                                        default={}, check_type=dict)\n        dep_extra_variables = self._cmakedeps.get_property(\"cmake_extra_variables\", self._conanfile,\n                                                           check_type=dict) or {}\n        # The configuration variables have precedence over the dependency ones\n        extra_variables = {dep: value for dep, value in dep_extra_variables.items()\n                           if dep not in conf_extra_variables}\n        parsed_extra_variables = {}\n        for key, value in extra_variables.items():\n            parsed_extra_variables[key] = parse_extra_variable(\"cmake_extra_variables\",\n                                                               key, value)\n        result[\"extra_variables\"] = parsed_extra_variables\n\n        result.update(self._get_legacy_vars())\n        return result\n\n    def _get_legacy_vars(self):\n        # Auxiliary variables for legacy consumption and try_compile cases\n        pkg_name = self._conanfile.ref.name\n        prefixes = self._cmakedeps.get_property(\"cmake_additional_variables_prefixes\",\n                                                self._conanfile, check_type=list) or []\n\n        f = self._cmakedeps.get_cmake_filename(self._conanfile)\n        prefixes = [f] + prefixes\n        include_dirs = definitions = libraries = None\n        if not self._require.build:  # To add global variables for try_compile and legacy\n            aggregated_cppinfo = self._full_cpp_info.aggregated_components()\n            # FIXME: Proper escaping of paths for CMake\n            incdirs = [i.replace(\"\\\\\", \"/\") for i in aggregated_cppinfo.includedirs]\n            incdirs = [relativize_path(i, self._cmakedeps._conanfile, \"${CMAKE_CURRENT_LIST_DIR}\")\n                       for i in incdirs]\n            include_dirs = \";\".join(incdirs)\n            definitions = \";\".join(\"-D\" + cmake_escape_value(d) for d in aggregated_cppinfo.defines)\n            root_target_name = self._cmakedeps.get_property(\"cmake_target_name\", self._conanfile)\n            libraries = root_target_name or f\"{pkg_name}::{pkg_name}\"\n\n        return {\"additional_variables_prefixes\": prefixes,\n                \"version\": self._conanfile.ref.version,\n                \"include_dirs\": include_dirs,\n                \"definitions\": definitions,\n                \"libraries\": libraries}\n\n    @property\n    def _template(self):\n        return textwrap.dedent(\"\"\"\\\n        # Requires CMake > 3.15\n        if(${CMAKE_VERSION} VERSION_LESS \"3.15\")\n            message(FATAL_ERROR \"The 'CMakeDeps' generator only works with CMake >= 3.15\")\n        endif()\n\n        include(${CMAKE_CURRENT_LIST_DIR}/{{ targets_include_file }})\n\n        get_property(isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)\n        if(NOT isMultiConfig AND NOT CMAKE_BUILD_TYPE)\n           message(FATAL_ERROR \"Please, set the CMAKE_BUILD_TYPE variable when calling to CMake \"\n                               \"adding the '-DCMAKE_BUILD_TYPE=<build_type>' argument.\")\n        endif()\n\n        {% if components %}\n        set({{filename}}_PACKAGE_PROVIDED_COMPONENTS {{components}})\n        foreach(comp {%raw%}${{%endraw%}{{filename}}_FIND_COMPONENTS})\n          if(NOT ${comp} IN_LIST {{filename}}_PACKAGE_PROVIDED_COMPONENTS)\n            if({%raw%}${{%endraw%}{{filename}}_FIND_REQUIRED_${comp}})\n              message(STATUS \"Conan: Error: '{{pkg_name}}' required COMPONENT '${comp}' not found\")\n              set({{filename}}_FOUND FALSE)\n            endif()\n          endif()\n        endforeach()\n        {% endif %}\n\n        ################# Global variables for try compile and legacy ##############\n        {% for prefix in additional_variables_prefixes %}\n        set({{ prefix }}_VERSION_STRING \"{{ version }}\")\n        {% if include_dirs is not none %}\n        set({{ prefix }}_INCLUDE_DIRS \"{{ include_dirs }}\" )\n        set({{ prefix }}_INCLUDE_DIR \"{{ include_dirs }}\" )\n        {% endif %}\n        {% if libraries is not none %}\n        set({{ prefix }}_LIBRARIES {{ libraries }} )\n        {% endif %}\n        {% if definitions is not none %}\n        set({{ prefix }}_DEFINITIONS \"{{ definitions}}\" )\n        {% endif %}\n        {% endfor %}\n\n        # build_modules_paths comes from last configuration only\n        # Some build modules in ConanCenter use try_compile variables and legacy, so this\n        # include() needs to happen after the above variables are defined\n        {% for build_module in build_modules_paths %}\n        message(STATUS \"Conan: Including build module from '{{build_module}}'\")\n        include(\"{{ build_module }}\")\n        {% endfor %}\n\n        # Definition of extra CMake variables from cmake_extra_variables\n\n        {% for key, value in extra_variables.items() %}\n        set({{ key }} {{ value }})\n        {% endfor %}\n        \"\"\")\n"
  },
  {
    "path": "conan/tools/cmake/cmakeconfigdeps/config_version.py",
    "content": "import textwrap\n\nimport jinja2\nfrom jinja2 import Template\n\nfrom conan.errors import ConanException\n\n\nclass ConfigVersionTemplate2:\n    \"\"\"\n    foo-config-version.cmake\n    \"\"\"\n    def __init__(self, cmakedeps, conanfile):\n        self._cmakedeps = cmakedeps\n        self._conanfile = conanfile\n\n    def content(self):\n        t = Template(self._template, trim_blocks=True, lstrip_blocks=True,\n                     undefined=jinja2.StrictUndefined)\n        return t.render(self._context)\n\n    @property\n    def filename(self):\n        f = self._cmakedeps.get_cmake_filename(self._conanfile)\n        return f\"{f}-config-version.cmake\" if f == f.lower() else f\"{f}ConfigVersion.cmake\"\n\n    @property\n    def _context(self):\n        policy = self._cmakedeps.get_property(\"cmake_config_version_compat\", self._conanfile)\n        if policy is None:\n            policy = \"SameMajorVersion\"\n        if policy not in (\"AnyNewerVersion\", \"SameMajorVersion\", \"SameMinorVersion\", \"ExactVersion\"):\n            raise ConanException(f\"Unknown cmake_config_version_compat={policy} in {self._conanfile}\")\n        version = self._cmakedeps.get_property(\"system_package_version\", self._conanfile)\n        version = version or self._conanfile.ref.version\n        return {\"version\": version,\n                \"policy\": policy}\n\n    @property\n    def _template(self):\n        # https://gitlab.kitware.com/cmake/cmake/blob/master/Modules/BasicConfigVersion-SameMajorVersion.cmake.in\n        # This will be at XXX-config-version.cmake\n        # AnyNewerVersion|SameMajorVersion|SameMinorVersion|ExactVersion\n        ret = textwrap.dedent(\"\"\"\\\n            set(PACKAGE_VERSION \"{{ version }}\")\n\n            if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION)\n                set(PACKAGE_VERSION_COMPATIBLE FALSE)\n            else()\n                {% if policy == \"AnyNewerVersion\" %}\n                set(PACKAGE_VERSION_COMPATIBLE TRUE)\n                {% elif policy == \"SameMajorVersion\" %}\n                if(\"{{ version }}\" MATCHES \"^([0-9]+)\\\\\\\\.\")\n                    set(CVF_VERSION_MAJOR {{ '${CMAKE_MATCH_1}' }})\n                else()\n                    set(CVF_VERSION_MAJOR \"{{ version }}\")\n                endif()\n\n                if(PACKAGE_FIND_VERSION_MAJOR STREQUAL CVF_VERSION_MAJOR)\n                    set(PACKAGE_VERSION_COMPATIBLE TRUE)\n                else()\n                    set(PACKAGE_VERSION_COMPATIBLE FALSE)\n                endif()\n                {% elif policy == \"SameMinorVersion\" %}\n                if(\"{{ version }}\" MATCHES \"^([0-9]+)\\\\.([0-9]+)\")\n                    set(CVF_VERSION_MAJOR \"${CMAKE_MATCH_1}\")\n                    set(CVF_VERSION_MINOR \"${CMAKE_MATCH_2}\")\n                else()\n                    set(CVF_VERSION_MAJOR \"{{ version }}\")\n                    set(CVF_VERSION_MINOR \"\")\n                endif()\n                if((PACKAGE_FIND_VERSION_MAJOR STREQUAL CVF_VERSION_MAJOR) AND\n                    (PACKAGE_FIND_VERSION_MINOR STREQUAL CVF_VERSION_MINOR))\n                  set(PACKAGE_VERSION_COMPATIBLE TRUE)\n                else()\n                  set(PACKAGE_VERSION_COMPATIBLE FALSE)\n                endif()\n                {% elif policy == \"ExactVersion\" %}\n                if(\"{{ version }}\" MATCHES \"^([0-9]+)\\\\.([0-9]+)\\\\.([0-9]+)\")\n                    set(CVF_VERSION_MAJOR \"${CMAKE_MATCH_1}\")\n                    set(CVF_VERSION_MINOR \"${CMAKE_MATCH_2}\")\n                    set(CVF_VERSION_MINOR \"${CMAKE_MATCH_3}\")\n                else()\n                    set(CVF_VERSION_MAJOR \"{{ version }}\")\n                    set(CVF_VERSION_MINOR \"\")\n                    set(CVF_VERSION_PATCH \"\")\n                endif()\n                if((PACKAGE_FIND_VERSION_MAJOR STREQUAL CVF_VERSION_MAJOR) AND\n                    (PACKAGE_FIND_VERSION_MINOR STREQUAL CVF_VERSION_MINOR) AND\n                    (PACKAGE_FIND_VERSION_PATCH STREQUAL CVF_VERSION_PATCH))\n                  set(PACKAGE_VERSION_COMPATIBLE TRUE)\n                else()\n                  set(PACKAGE_VERSION_COMPATIBLE FALSE)\n                endif()\n                {% endif %}\n\n                if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION)\n                    set(PACKAGE_VERSION_EXACT TRUE)\n                endif()\n            endif()\n            \"\"\")\n        return ret\n"
  },
  {
    "path": "conan/tools/cmake/cmakeconfigdeps/target_configuration.py",
    "content": "import os\nimport textwrap\n\nimport jinja2\nfrom jinja2 import Template\n\nfrom conan.errors import ConanException\nfrom conan.internal.api.install.generators import relativize_path\nfrom conan.internal.model.pkg_type import PackageType\nfrom conan.internal.graph.graph import CONTEXT_BUILD, CONTEXT_HOST\nfrom conan.tools.cmake.utils import cmake_escape_value\n\n\nclass TargetConfigurationTemplate2:\n    \"\"\"\n    FooTarget-release.cmake\n    \"\"\"\n    def __init__(self, cmakedeps, conanfile, require, full_cpp_info):\n        self._cmakedeps = cmakedeps\n        self._conanfile = conanfile  # The dependency conanfile, not the consumer one\n        self._require = require\n        self._full_cpp_info = full_cpp_info\n\n    def content(self):\n        auto_link = self._cmakedeps.get_property(\"cmake_set_interface_link_directories\",\n                                                 self._conanfile, check_type=bool)\n        if auto_link:\n            out = self._cmakedeps._conanfile.output  # noqa\n            out.warning(\"CMakeConfigDeps: cmake_set_interface_link_directories deprecated and \"\n                        \"invalid. The package 'package_info()' must correctly define the (CPS) \"\n                        \"information\", warn_tag=\"deprecated\")\n        t = Template(self._template, trim_blocks=True, lstrip_blocks=True,\n                     undefined=jinja2.StrictUndefined)\n        return t.render(self._context)\n\n    @property\n    def filename(self):\n        f = self._cmakedeps.get_cmake_filename(self._conanfile)\n        # Fallback to consumer configuration if it doesn't have build_type\n        config = self._conanfile.settings.get_safe(\"build_type\", self._cmakedeps.configuration)\n        config = (config or \"none\").lower()\n        build = \"Build\" if self._conanfile.context == CONTEXT_BUILD else \"\"\n        return f\"{f}-Targets{build}-{config}.cmake\"\n\n    def _requires(self, info, components):\n        result = {}\n        requires = info.parsed_requires()\n        pkg_name = self._conanfile.ref.name\n        pkg_type = info.type\n        assert isinstance(pkg_type, PackageType), f\"Pkg type {pkg_type} {type(pkg_type)}\"\n        transitive_reqs = self._cmakedeps.get_transitive_requires(self._conanfile)\n\n        if not requires and not components:  # global cpp_info without components definition\n            # require the pkgname::pkgname base (user defined) or INTERFACE base target\n            for d in transitive_reqs.values():\n                if d.package_type is PackageType.APP:\n                    continue\n                dep_target = self._cmakedeps.get_property(\"cmake_target_name\", d)\n                dep_target = dep_target or f\"{d.ref.name}::{d.ref.name}\"\n                link_feature = self._cmakedeps.get_property(\"cmake_link_feature\", d)\n                link = not (pkg_type is PackageType.SHARED and d.package_type is PackageType.SHARED)\n                result[dep_target] = {\n                    \"link\": link,\n                    \"link_feature\": link_feature\n                }\n            return result\n\n        for required_pkg, required_comp in requires:\n            if required_pkg is None:  # Points to a component of same package\n                dep_comp = components.get(required_comp)\n                assert dep_comp, f\"Component {required_comp} not found in {self._conanfile}\"\n                dep_target = self._cmakedeps.get_property(\"cmake_target_name\", self._conanfile,\n                                                          required_comp)\n                dep_target = dep_target or f\"{pkg_name}::{required_comp}\"\n                link = not (pkg_type is PackageType.SHARED and\n                            dep_comp.type is PackageType.SHARED)\n                link_feature = self._cmakedeps.get_property(\"cmake_link_feature\", self._conanfile,\n                                                              required_comp)\n                result[dep_target] = {\n                    \"link\": link,\n                    \"link_feature\": link_feature\n                }\n            else:  # Different package\n                try:\n                    dep = transitive_reqs[required_pkg]\n                except KeyError:  # The transitive dep might have been skipped\n                    pass\n                else:\n                    # To check if the component exist, it is ok to use the standard cpp_info\n                    # No need to use the cpp_info = deduce_cpp_info(dep)\n                    dep_comp = dep.cpp_info.components.get(required_comp)\n                    if dep_comp is None:\n                        # It must be the interface pkgname::pkgname target\n                        if required_pkg != required_comp:\n                            msg = (f\"{self._conanfile} recipe cpp_info did .requires to \"\n                                   f\"'{required_pkg}::{required_comp}' but component \"\n                                   f\"'{required_comp}' not found in {required_pkg}\")\n                            raise ConanException(msg)\n                        if dep.package_type is PackageType.APP:\n                            continue  # It doesn't make sense to link a package that is an App\n                        comp = None\n                        default_target = f\"{dep.ref.name}::{dep.ref.name}\"  # replace_requires\n                        link = pkg_type is not PackageType.SHARED\n                    else:\n                        if dep_comp.type is PackageType.APP or dep_comp.exe:\n                            continue  # It doesn't make sense to link a package that is an App\n                        comp = required_comp\n                        default_target = f\"{required_pkg}::{required_comp}\"\n                        link = not (pkg_type is PackageType.SHARED and\n                                    dep_comp.type is PackageType.SHARED)\n\n                    dep_target = self._cmakedeps.get_property(\"cmake_target_name\", dep, comp)\n                    dep_target = dep_target or default_target\n                    link_feature = self._cmakedeps.get_property(\"cmake_link_feature\", dep, comp)\n\n                    result[dep_target] = {\n                        \"link\": link,\n                        \"link_feature\": link_feature\n                    }\n        return result\n\n    @property\n    def _context(self):\n        cpp_info = self._full_cpp_info\n        assert isinstance(cpp_info.type, PackageType)\n        pkg_name = self._conanfile.ref.name\n        # fallback to consumer configuration if it doesn't have build_type\n        config = self._conanfile.settings.get_safe(\"build_type\", self._cmakedeps.configuration)\n        config = config.upper() if config else None\n        pkg_folder = self._conanfile.package_folder.replace(\"\\\\\", \"/\")\n        config_folder = f\"_{config}\" if config else \"\"\n        build = \"_BUILD\" if self._conanfile.context == CONTEXT_BUILD else \"\"\n        pkg_folder_var = f\"{pkg_name}_PACKAGE_FOLDER{config_folder}{build}\"\n\n        libs = {}\n        # The BUILD context does not generate libraries targets atm\n        if not self._require.build:\n            libs = self._get_libs(cpp_info, pkg_name, pkg_folder, pkg_folder_var)\n            self._add_root_lib_target(libs, pkg_name, cpp_info)\n        exes = self._get_exes(cpp_info, pkg_name, pkg_folder, pkg_folder_var)\n\n        seen_aliases = set()\n        root_target_name = self._cmakedeps.get_property(\"cmake_target_name\", self._conanfile)\n        root_target_name = root_target_name or f\"{pkg_name}::{pkg_name}\"\n        for lib in libs.values():\n            for alias in lib.get(\"cmake_target_aliases\", []):\n                if alias == root_target_name:\n                    raise ConanException(f\"Can't define an alias '{alias}' for the \"\n                                         f\"root target '{root_target_name}' in {self._conanfile}. \"\n                                         f\"Changing the default target should be done with the \"\n                                         f\"'cmake_target_name' property.\")\n                if alias in seen_aliases:\n                    raise ConanException(f\"Alias '{alias}' already defined in {self._conanfile}. \")\n                seen_aliases.add(alias)\n                if alias in libs:\n                    raise ConanException(f\"Alias '{alias}' already defined as a target in \"\n                                         f\"{self._conanfile}. \")\n\n        pkg_folder = relativize_path(pkg_folder, self._cmakedeps._conanfile,\n                                     \"${CMAKE_CURRENT_LIST_DIR}\")\n        dependencies = self._get_dependencies()\n        return {\"dependencies\": dependencies,\n                \"pkg_folder\": pkg_folder,\n                \"pkg_folder_var\": pkg_folder_var,\n                \"config\": config,\n                \"exes\": exes,\n                \"libs\": libs,\n                \"context\": self._conanfile.context\n                }\n\n    def _get_libs(self, cpp_info, pkg_name, pkg_folder, pkg_folder_var) -> dict:\n        libs = {}\n        if cpp_info.has_components:\n            for name, component in cpp_info.components.items():\n                target_name = self._cmakedeps.get_property(\"cmake_target_name\", self._conanfile,\n                                                           name)\n                target_name = target_name or f\"{pkg_name}::{name}\"\n                target = self._get_cmake_lib(component, cpp_info.components, pkg_folder,\n                                             pkg_folder_var, comp_name=name)\n                if target is not None:\n                    cmake_target_aliases = self._get_aliases(name)\n                    target[\"cmake_target_aliases\"] = cmake_target_aliases\n                    libs[target_name] = target\n        else:\n            target_name = self._cmakedeps.get_property(\"cmake_target_name\", self._conanfile)\n            target_name = target_name or f\"{pkg_name}::{pkg_name}\"\n            target = self._get_cmake_lib(cpp_info, None, pkg_folder, pkg_folder_var)\n            if target is not None:\n                cmake_target_aliases = self._get_aliases()\n                target[\"cmake_target_aliases\"] = cmake_target_aliases\n                libs[target_name] = target\n        return libs\n\n    def _get_cmake_lib(self, info, components, pkg_folder, pkg_folder_var, comp_name=None):\n        if info.exe or not (info.package_framework or info.frameworks or info.includedirs or info.libs\n                            or info.system_libs or info.defines or info.requires):\n            return\n\n        includedirs = \";\".join(self._path(i, pkg_folder, pkg_folder_var)\n                               for i in info.includedirs) if info.includedirs else \"\"\n        requires = self._requires(info, components)\n        assert isinstance(requires, dict)\n        defines = \";\".join(cmake_escape_value(f) for f in info.defines)\n        # FIXME: Filter by lib traits!!!!!\n        if not self._require.headers:  # If not depending on headers, paths and\n            includedirs = defines = None\n        extra_libs = self._cmakedeps.get_property(\"cmake_extra_interface_libs\", self._conanfile,\n                                                  comp_name=comp_name, check_type=list) or []\n        sources = [self._path(source, pkg_folder, pkg_folder_var) for source in info.sources]\n        target = {\"type\": \"INTERFACE\",\n                  \"comp_name\": comp_name,\n                  \"includedirs\": includedirs,\n                  \"defines\": defines,\n                  \"requires\": requires,\n                  \"cxxflags\": \";\".join(cmake_escape_value(f) for f in info.cxxflags),\n                  \"cflags\": \";\".join(cmake_escape_value(f) for f in info.cflags),\n                  \"sharedlinkflags\": \";\".join(cmake_escape_value(v) for v in info.sharedlinkflags),\n                  \"exelinkflags\": \";\".join(cmake_escape_value(v) for v in info.exelinkflags),\n                  \"system_libs\": \" \".join(info.system_libs + extra_libs),\n                  \"sources\": \" \".join(sources)\n                  }\n        # System frameworks (only Apple OS)\n        if info.frameworks:\n            target['frameworks'] = \" \".join([f\"-framework {frw}\" for frw in info.frameworks])\n        # FIXME: We're ignoring this value at this moment. It relies on cmake_target_name or lib name\n        #        Revisit when cpp.exe value is used too.\n        if info.package_framework:\n            target[\"package_framework\"] = {}\n            lib_type = \"SHARED\" if info.type is PackageType.SHARED else \\\n                \"STATIC\" if info.type is PackageType.STATIC else \"STATIC\"\n            assert lib_type, f\"Unknown package type {info.type}\"\n            assert info.location, f\"cpp_info.location missing for framework {info.package_framework}\"\n            target[\"type\"] = lib_type\n            target[\"package_framework\"][\"location\"] = self._path(info.location, pkg_folder,\n                                                                 pkg_folder_var)\n            target[\"includedirs\"] = []  # empty as frameworks have their own way to inject headers\n            # FIXME: This is not needed for CMake < 3.24. Remove it when Conan requires CMake >= 3.24\n            target[\"package_framework\"][\"frameworkdir\"] = self._path(pkg_folder, pkg_folder,\n                                                                     pkg_folder_var)\n        if info.libs:\n            if len(info.libs) != 1:\n                raise ConanException(f\"New CMakeDeps only allows 1 lib per component:\\n\"\n                                     f\"{self._conanfile}: {info.libs}\")\n            assert info.location, \"info.location missing for .libs, it should have been deduced\"\n            location = self._path(info.location, pkg_folder, pkg_folder_var)\n            link_location = self._path(info.link_location, pkg_folder, pkg_folder_var) \\\n                if info.link_location else None\n            lib_type = \"SHARED\" if info.type is PackageType.SHARED else \\\n                \"STATIC\" if info.type is PackageType.STATIC else None\n            assert lib_type, f\"Unknown package type {info.type}\"\n            target[\"type\"] = lib_type\n            target[\"location\"] = location\n            target[\"link_location\"] = link_location\n            link_languages = info.languages or self._conanfile.languages or []\n            link_languages = [\"CXX\" if c == \"C++\" else c for c in link_languages]\n            target[\"link_languages\"] = link_languages\n        return target\n\n    def _get_aliases(self, comp_name=None):\n        aliases = self._cmakedeps.get_property(\"cmake_target_aliases\", self._conanfile,\n                                               comp_name, check_type=list) or []\n        return aliases\n\n    def _add_root_lib_target(self, libs, pkg_name, cpp_info):\n        \"\"\"\n        Add a new pkgname::pkgname INTERFACE target that depends on default_components or\n        on all other library targets (not exes)\n        It will not be added if there exists already a pkgname::pkgname target (Or an alias exists).\n        \"\"\"\n        root_target_name = self._cmakedeps.get_property(\"cmake_target_name\", self._conanfile)\n        root_target_name = root_target_name or f\"{pkg_name}::{pkg_name}\"\n        # TODO: What if an exe target is called like the pkg_name::pkg_name\n        if libs and root_target_name not in libs:\n            # Add a generic interface target for the package depending on the others\n            if cpp_info.default_components is not None:\n                all_requires = {}\n                for defaultc in cpp_info.default_components:\n                    target_name = self._cmakedeps.get_property(\"cmake_target_name\", self._conanfile,\n                                                               defaultc)\n                    comp_name = target_name or f\"{pkg_name}::{defaultc}\"\n                    link_feature = self._cmakedeps.get_property(\"cmake_link_feature\", self._conanfile,\n                                                                defaultc)\n                    all_requires[comp_name] = {\n                        \"link\": True,  # It is an interface, full link\n                        \"link_feature\": link_feature\n                    }\n            else:\n                all_requires = {k: {\n                    \"link\": True,\n                    \"link_feature\": self._cmakedeps.get_property(\"cmake_link_feature\", self._conanfile,\n                                                                 v.get(\"comp_name\"))\n                }\n                    for k, v in libs.items()}\n            # This target might have an alias, so we need to check it\n            cmake_target_aliases = self._get_aliases()\n            libs[root_target_name] = {\"type\": \"INTERFACE\",\n                                      \"requires\": all_requires,\n                                      \"cmake_target_aliases\": cmake_target_aliases}\n\n    def _get_exes(self, cpp_info, pkg_name, pkg_folder, pkg_folder_var):\n        exes = {}\n\n        if cpp_info.has_components:\n            for name, comp in cpp_info.components.items():\n                if comp.exe or comp.type is PackageType.APP:\n                    target_name = self._cmakedeps.get_property(\"cmake_target_name\", self._conanfile,\n                                                               name)\n                    target = target_name or f\"{pkg_name}::{name}\"\n                    exe_location = self._path(comp.location, pkg_folder, pkg_folder_var)\n                    exes[target] = exe_location\n        else:\n            if cpp_info.exe:\n                target_name = self._cmakedeps.get_property(\"cmake_target_name\", self._conanfile)\n                target = target_name or f\"{pkg_name}::{pkg_name}\"\n                exe_location = self._path(cpp_info.location, pkg_folder, pkg_folder_var)\n                exes[target] = exe_location\n\n        return exes\n\n    def _get_dependencies(self):\n        \"\"\" transitive dependencies Filenames for find_dependency()\n        \"\"\"\n        # Build requires are already filtered by the get_transitive_requires\n        transitive_reqs = self._cmakedeps.get_transitive_requires(self._conanfile)\n        # FIXME: Hardcoded CONFIG\n        ret = {self._cmakedeps.get_cmake_filename(r): \"CONFIG\" for r in transitive_reqs.values()}\n        extra_mods = self._cmakedeps.get_property(\"cmake_extra_dependencies\", self._conanfile,\n                                                  check_type=list) or []\n        ret.update({extra_mod: \"\" for extra_mod in extra_mods})\n        return ret\n\n    @staticmethod\n    def _path(p, pkg_folder, pkg_folder_var):\n        def escape(p_):\n            return p_.replace(\"$\", \"\\\\$\").replace('\"', '\\\\\"')\n\n        p = p.replace(\"\\\\\", \"/\")\n        if os.path.isabs(p):\n            if p.startswith(pkg_folder):\n                rel = p[len(pkg_folder):].lstrip(\"/\")\n                return f\"${{{pkg_folder_var}}}/{escape(rel)}\"\n            return escape(p)\n        return f\"${{{pkg_folder_var}}}/{escape(p)}\"\n\n    @property\n    def _template(self):\n        # TODO: CMake 3.24: Apple Frameworks: https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html#genex:LINK_LIBRARY\n        # TODO: Check why not set_property instead of target_link_libraries\n        return textwrap.dedent(\"\"\"\\\n        {%- macro config_wrapper(config, value) -%}\n             {% if config -%}\n             $<$<CONFIG:{{config}}>:{{value}}>\n             {%- else -%}\n             {{value}}\n             {%- endif %}\n        {%- endmacro -%}\n        set({{pkg_folder_var}} \"{{pkg_folder}}\")\n\n        # Dependencies finding\n        include(CMakeFindDependencyMacro)\n\n        {% for dep, dep_find_mode in dependencies.items() %}\n        if(NOT {{dep}}_FOUND)\n            find_dependency({{dep}} REQUIRED {{dep_find_mode}})\n        endif()\n        {% endfor %}\n\n        ################# Libs information ##############\n        {% for lib, lib_info in libs.items() %}\n        #################### {{lib}} ####################\n        if(NOT TARGET {{ lib }})\n            message(STATUS \"Conan: Target declared imported {{lib_info[\"type\"]}} library '{{lib}}'\")\n            add_library({{lib}} {{lib_info[\"type\"]}} IMPORTED)\n        endif()\n        {% for alias in lib_info.get(\"cmake_target_aliases\", []) %}\n        if(NOT TARGET {{alias}})\n            message(STATUS \"Conan: Target declared alias '{{alias}}' for '{{lib}}'\")\n            add_library({{alias}} ALIAS {{lib}})\n        endif()\n        {% endfor %}\n        {% if lib_info.get(\"includedirs\") %}\n        set_property(TARGET {{lib}} APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES\n                     {{config_wrapper(config, lib_info[\"includedirs\"])}})\n        {% endif %}\n        {% if lib_info.get(\"defines\") %}\n        set_property(TARGET {{lib}} APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS\n                     \"{{config_wrapper(config, lib_info[\"defines\"])}}\")\n        {% endif %}\n        {% if lib_info.get(\"cxxflags\") %}\n        set_property(TARGET {{lib}} APPEND PROPERTY INTERFACE_COMPILE_OPTIONS\n                     \"$<$<COMPILE_LANGUAGE:CXX>:{{config_wrapper(config, lib_info[\"cxxflags\"])}}>\")\n        {% endif %}\n        {% if lib_info.get(\"cflags\") %}\n        set_property(TARGET {{lib}} APPEND PROPERTY INTERFACE_COMPILE_OPTIONS\n                     \"$<$<COMPILE_LANGUAGE:C>:{{config_wrapper(config, lib_info[\"cflags\"])}}>\")\n        {% endif %}\n        {% if lib_info.get(\"sharedlinkflags\") %}\n        {% set linkflags = config_wrapper(config, lib_info[\"sharedlinkflags\"]) %}\n        set_property(TARGET {{lib}} APPEND PROPERTY INTERFACE_LINK_OPTIONS\n                     \"$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,SHARED_LIBRARY>:{{linkflags}}>\"\n                     \"$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,MODULE_LIBRARY>:{{linkflags}}>\")\n        {% endif %}\n        {% if lib_info.get(\"exelinkflags\") %}\n        {% set exeflags = config_wrapper(config, lib_info[\"exelinkflags\"]) %}\n        set_property(TARGET {{lib}} APPEND PROPERTY INTERFACE_LINK_OPTIONS\n                     \"$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:{{exeflags}}>\")\n        {% endif %}\n\n        {% if lib_info.get(\"link_languages\") %}\n        get_property(_languages GLOBAL PROPERTY ENABLED_LANGUAGES)\n        if(\"CXX\" IN_LIST _languages)\n            list(APPEND _languages \"C\")\n        endif()\n        if(\"CUDA\" IN_LIST _languages)\n            list(APPEND _languages \"C\" \"CXX\")\n        endif()\n        {% for lang in lib_info[\"link_languages\"] %}\n        if(NOT \"{{lang}}\" IN_LIST _languages)\n            message(SEND_ERROR\n                    \"Target {{lib}} has {{lang}} linkage but {{lang}} not enabled in project()\")\n        endif()\n        set_property(TARGET {{lib}} APPEND PROPERTY\n                     IMPORTED_LINK_INTERFACE_LANGUAGES_{{config}} {{lang}})\n        {% endfor %}\n        {% endif %}\n        {% if lib_info.get(\"location\") %}\n        set_property(TARGET {{lib}} APPEND PROPERTY IMPORTED_CONFIGURATIONS {{config}})\n        set_target_properties({{lib}} PROPERTIES IMPORTED_LOCATION_{{config}}\n                              \"{{lib_info[\"location\"]}}\")\n        {% elif lib_info.get(\"type\") == \"INTERFACE\" %}\n        set_property(TARGET {{lib}} APPEND PROPERTY IMPORTED_CONFIGURATIONS {{config}})\n        {% endif %}\n        {% if lib_info.get(\"link_location\") %}\n        set_target_properties({{lib}} PROPERTIES IMPORTED_IMPLIB_{{config}}\n                              \"{{lib_info[\"link_location\"]}}\")\n        {% endif %}\n\n        {% if lib_info.get(\"requires\") %}\n        # Information of transitive dependencies\n        {% for require_target, link_info in lib_info[\"requires\"].items() %}\n\n        # Requirement {{lib}} -> {{require_target}} (Full link: {{link_info[\"link\"]}})\n        {% if link_info[\"link\"] %}\n        {% if link_info[\"link_feature\"] %}\n        # Link feature: {{link_info[\"link_feature\"]}}\n        if(CMAKE_VERSION VERSION_LESS \"3.24\")\n            message(FATAL_ERROR \"The 'CMakeConfigDeps' generator LINK_FEATURE property only works with CMake >= 3.24\")\n        endif()\n        {% endif %}\n        # set property allows to append, and lib_info[requires] will iterate\n        set_property(TARGET {{lib}} APPEND PROPERTY INTERFACE_LINK_LIBRARIES\n            {% if link_info[\"link_feature\"] %}\n                     \"$<LINK_LIBRARY:{{link_info[\"link_feature\"]}},{{config_wrapper(config, require_target)}}>\")\n            {% else %}\n                     \"{{config_wrapper(config, require_target)}}\")\n            {% endif %}\n        {% else %}\n        if(CMAKE_VERSION VERSION_LESS \"3.27\")\n            message(FATAL_ERROR \"The 'CMakeConfigDeps' generator COMPILE_ONLY expression only works with CMake >= 3.27\")\n        endif()\n        # If the headers trait is not there, this will do nothing\n        target_link_libraries({{lib}} INTERFACE\n                              $<COMPILE_ONLY:{{config_wrapper(config, require_target)}}> )\n        set_property(TARGET {{lib}} APPEND PROPERTY IMPORTED_LINK_DEPENDENT_LIBRARIES_{{config}}\n                     {{require_target}})\n        {% endif %}\n        {% endfor %}\n        {% endif %}\n\n        {% if lib_info.get(\"system_libs\") %}\n        set_property(TARGET {{lib}} APPEND PROPERTY INTERFACE_LINK_LIBRARIES\n                     {{config_wrapper(config, lib_info[\"system_libs\"])}})\n        {% endif %}\n        {% if lib_info.get(\"frameworks\") %}\n        set_property(TARGET {{lib}} APPEND PROPERTY INTERFACE_LINK_LIBRARIES\n                     \"{{config_wrapper(config, lib_info[\"frameworks\"])}}\")\n        {% endif %}\n        {% if lib_info.get(\"package_framework\") %}\n        set_target_properties({{lib}} PROPERTIES\n            IMPORTED_LOCATION_{{config}} \"{{lib_info[\"package_framework\"][\"location\"]}}\"\n            FRAMEWORK TRUE)\n        if(CMAKE_VERSION VERSION_LESS \"3.24\")\n            set_property(TARGET {{lib}} APPEND PROPERTY INTERFACE_COMPILE_OPTIONS\n                         $<$<COMPILE_LANGUAGE:CXX>:-F{{lib_info[\"package_framework\"][\"frameworkdir\"]}}>)\n            set_property(TARGET {{lib}} APPEND PROPERTY INTERFACE_COMPILE_OPTIONS\n                         $<$<COMPILE_LANGUAGE:C>:-F{{lib_info[\"package_framework\"][\"frameworkdir\"]}}>)\n        endif()\n        {% endif %}\n\n        {% if lib_info.get(\"sources\") %}\n        set_property(TARGET {{lib}} APPEND PROPERTY INTERFACE_SOURCES\n                     {{config_wrapper(config, lib_info[\"sources\"] )}})\n        {% endif %}\n        {% endfor %}\n\n        ################# Exes information ##############\n        {% for exe, location in exes.items() %}\n        #################### {{exe}} ####################\n        if(NOT TARGET {{ exe }})\n            message(STATUS \"Conan: Target declared imported executable '{{exe}}' {{context}}\")\n            add_executable({{exe}} IMPORTED)\n        else()\n            get_property(_context TARGET {{exe}} PROPERTY CONAN_CONTEXT)\n            if(NOT $${_context} STREQUAL \"{{context}}\")\n                message(STATUS \"Conan: Exe {{exe}} was already defined in ${_context}\")\n                get_property(_configurations TARGET {{exe}} PROPERTY IMPORTED_CONFIGURATIONS)\n                message(STATUS \"Conan: Exe {{exe}} defined configurations: ${_configurations}\")\n                foreach(_config ${_configurations})\n                    set_property(TARGET {{exe}} PROPERTY IMPORTED_LOCATION_${_config})\n                endforeach()\n                set_property(TARGET {{exe}} PROPERTY IMPORTED_CONFIGURATIONS)\n            endif()\n        endif()\n        set_property(TARGET {{exe}} APPEND PROPERTY IMPORTED_CONFIGURATIONS {{config}})\n        set_target_properties({{exe}} PROPERTIES IMPORTED_LOCATION_{{config}} \"{{location}}\")\n        set_property(TARGET {{exe}} PROPERTY CONAN_CONTEXT \"{{context}}\")\n        {% endfor %}\n        \"\"\")\n"
  },
  {
    "path": "conan/tools/cmake/cmakeconfigdeps/targets.py",
    "content": "import textwrap\n\nimport jinja2\nfrom jinja2 import Template\n\n\nclass TargetsTemplate2:\n    \"\"\"\n    FooTargets.cmake\n    \"\"\"\n    def __init__(self, cmakedeps, conanfile):\n        self._cmakedeps = cmakedeps\n        self._conanfile = conanfile\n\n    def content(self):\n        t = Template(self._template, trim_blocks=True, lstrip_blocks=True,\n                     undefined=jinja2.StrictUndefined)\n        return t.render(self._context)\n\n    @property\n    def filename(self):\n        f = self._cmakedeps.get_cmake_filename(self._conanfile)\n        return f\"{f}Targets.cmake\"\n\n    @property\n    def _context(self):\n        filename = self._cmakedeps.get_cmake_filename(self._conanfile)\n        ret = {\"ref\": str(self._conanfile.ref),\n               \"filename\": filename}\n        return ret\n\n    @property\n    def _template(self):\n        return textwrap.dedent(\"\"\"\\\n            include_guard()\n            message(STATUS \"Conan: Configuring Targets for {{ ref }}\")\n\n            # Load information for each installed configuration.\n            file(GLOB _target_files \"${CMAKE_CURRENT_LIST_DIR}/{{filename}}-Targets-*.cmake\")\n            foreach(_target_file IN LISTS _target_files)\n              include(\"${_target_file}\")\n            endforeach()\n\n            file(GLOB _build_files \"${CMAKE_CURRENT_LIST_DIR}/{{filename}}-TargetsBuild-*.cmake\")\n            foreach(_build_file IN LISTS _build_files)\n              include(\"${_build_file}\")\n            endforeach()\n            \"\"\")\n"
  },
  {
    "path": "conan/tools/cmake/cmakedeps/__init__.py",
    "content": "FIND_MODE_MODULE = \"module\"\nFIND_MODE_CONFIG = \"config\"\nFIND_MODE_NONE = \"none\"\nFIND_MODE_BOTH = \"both\"\n"
  },
  {
    "path": "conan/tools/cmake/cmakedeps/cmakedeps.py",
    "content": "import textwrap\n\nimport jinja2\nfrom jinja2 import Template\n\nfrom conan.api.output import Color\nfrom conan.internal import check_duplicated_generator\nfrom conan.tools.cmake.cmakedeps import FIND_MODE_CONFIG, FIND_MODE_NONE, FIND_MODE_BOTH, \\\n    FIND_MODE_MODULE\nfrom conan.tools.cmake.cmakedeps.templates.config import ConfigTemplate\nfrom conan.tools.cmake.cmakedeps.templates.config_version import ConfigVersionTemplate\nfrom conan.tools.cmake.cmakedeps.templates.macros import MacrosTemplate\nfrom conan.tools.cmake.cmakedeps.templates.target_configuration import TargetConfigurationTemplate\nfrom conan.tools.cmake.cmakedeps.templates.target_data import ConfigDataTemplate\nfrom conan.tools.cmake.cmakedeps.templates.targets import TargetsTemplate\nfrom conan.tools.files import save\nfrom conan.errors import ConanException\nfrom conan.internal.model.dependencies import get_transitive_requires\n\n\nclass CMakeDeps:\n\n    def __init__(self, conanfile):\n        self._conanfile = conanfile\n        self.arch = self._conanfile.settings.get_safe(\"arch\")\n        self.configuration = str(self._conanfile.settings.build_type)\n\n        # Activate the build config files for the specified libraries\n        self.build_context_activated = []\n        # By default, the build modules are generated for host context only\n        self.build_context_build_modules = []\n        # If specified, the files/targets/variables for the build context will be renamed appending\n        # a suffix. It is necessary in case of same require and build_require and will cause an error\n        self.build_context_suffix = {}\n\n        # Enable/Disable checking if a component target exists or not\n        self.check_components_exist = False\n        self._properties = {}\n\n    def generate(self):\n        \"\"\"\n        This method will save the generated files to the ``conanfile.generators_folder`` folder\n        \"\"\"\n        check_duplicated_generator(self, self._conanfile)\n\n        # Current directory is the generators_folder\n        generator_files = self.content\n        for generator_file, content in generator_files.items():\n            save(self._conanfile, generator_file, content)\n        self.generate_aggregator()\n\n    @property\n    def content(self):\n        macros = MacrosTemplate()\n        ret = {macros.filename: macros.render()}\n\n        host_req = self._conanfile.dependencies.host\n        build_req = self._conanfile.dependencies.direct_build\n        test_req = self._conanfile.dependencies.test\n\n        # Check if the same package is at host and build and the same time\n        activated_br = {r.ref.name for r in build_req.values()\n                        if r.ref.name in self.build_context_activated}\n        common_names = {r.ref.name for r in host_req.values()}.intersection(activated_br)\n        for common_name in common_names:\n            suffix = self.build_context_suffix.get(common_name)\n            if not suffix:\n                raise ConanException(\"The package '{}' exists both as 'require' and as \"\n                                     \"'build require'. You need to specify a suffix using the \"\n                                     \"'build_context_suffix' attribute at the CMakeDeps \"\n                                     \"generator.\".format(common_name))\n\n        # Iterate all the transitive requires\n        direct_configs = []\n        for require, dep in list(host_req.items()) + list(build_req.items()) + list(test_req.items()):\n            # Require is not used at the moment, but its information could be used,\n            # and will be used in Conan 2.0\n            # Filter the build_requires not activated with cmakedeps.build_context_activated\n            if require.build and dep.ref.name not in self.build_context_activated:\n                continue\n\n            cmake_find_mode = self.get_property(\"cmake_find_mode\", dep)\n            cmake_find_mode = cmake_find_mode or FIND_MODE_CONFIG\n            cmake_find_mode = cmake_find_mode.lower()\n            # Skip from the requirement\n            if cmake_find_mode == FIND_MODE_NONE:\n                # Skip the generation of config files for this node, it will be located externally\n                continue\n\n            if cmake_find_mode in (FIND_MODE_CONFIG, FIND_MODE_BOTH):\n                self._generate_files(require, dep, ret, find_module_mode=False)\n\n            if cmake_find_mode in (FIND_MODE_MODULE, FIND_MODE_BOTH):\n                self._generate_files(require, dep, ret, find_module_mode=True)\n\n            if require.direct:  # aggregate config information for user convenience\n                find_module_mode = True if cmake_find_mode == FIND_MODE_MODULE else False\n                config = ConfigTemplate(self, require, dep, find_module_mode)\n                direct_configs.append(config)\n\n        if direct_configs:\n            # Some helpful verbose messages about generated files\n            msg = [\"CMakeDeps necessary find_package() and targets for your CMakeLists.txt\"]\n            for config in direct_configs:\n                msg.append(f\"    find_package({config.file_name})\")\n            targets = ' '.join(c.root_target_name for c in direct_configs)\n            msg.append(f\"    target_link_libraries(... {targets})\")\n            if self._conanfile._conan_is_consumer:  # noqa\n                self._conanfile.output.info(\"\\n\".join(msg), fg=Color.CYAN)\n            else:\n                self._conanfile.output.verbose(\"\\n\".join(msg))\n\n        return ret\n\n    def _generate_files(self, require, dep, ret, find_module_mode):\n        if not find_module_mode:\n            config_version = ConfigVersionTemplate(self, require, dep)\n            ret[config_version.filename] = config_version.render()\n\n        data_target = ConfigDataTemplate(self, require, dep, find_module_mode)\n        data_content = data_target.render()\n        ret[data_target.filename] = data_content\n\n        target_configuration = TargetConfigurationTemplate(self, require, dep, find_module_mode)\n        ret[target_configuration.filename] = target_configuration.render()\n\n        targets = TargetsTemplate(self, require, dep, find_module_mode)\n        ret[targets.filename] = targets.render()\n\n        config = ConfigTemplate(self, require, dep, find_module_mode)\n        # Only the latest configuration BUILD_MODULES and additional_variables will be used\n        # in multi-config they will be overwritten by the latest install\n        ret[config.filename] = config.render()\n\n    def set_property(self, dep, prop, value, build_context=False):\n        \"\"\"\n        Using this method you can overwrite the :ref:`property<CMakeDeps Properties>` values set by\n        the Conan recipes from the consumer. This can be done for ``cmake_file_name``, ``cmake_target_name``,\n        ``cmake_find_mode``, ``cmake_module_file_name``, ``cmake_module_target_name``, ``cmake_additional_variables_prefixes``,\n        ``cmake_config_version_compat``, ``system_package_version``,\n        ``cmake_build_modules``, ``nosoname``, ``cmake_target_aliases`` and ``cmake_extra_variables``.\n\n        :param dep: Name of the dependency to set the :ref:`property<CMakeDeps Properties>`. For\n         components use the syntax: ``dep_name::component_name``.\n        :param prop: Name of the :ref:`property<CMakeDeps Properties>`.\n        :param value: Value of the property. Use ``None`` to invalidate any value set by the\n         upstream recipe.\n        :param build_context: Set to ``True`` if you want to set the property for a dependency that\n         belongs to the build context (``False`` by default).\n        \"\"\"\n        build_suffix = \"&build\" if build_context else \"\"\n        self._properties.setdefault(f\"{dep}{build_suffix}\", {}).update({prop: value})\n\n    def get_property(self, prop, dep, comp_name=None, check_type=None):\n        dep_name = dep.ref.name\n        build_suffix = \"&build\" if str(\n            dep_name) in self.build_context_activated and dep.context == \"build\" else \"\"\n        dep_comp = f\"{str(dep_name)}::{comp_name}\" if comp_name else f\"{str(dep_name)}\"\n        try:\n            value = self._properties[f\"{dep_comp}{build_suffix}\"][prop]\n            if check_type is not None and not isinstance(value, check_type):\n                raise ConanException(\n                    f'The expected type for {prop} is \"{check_type.__name__}\", but \"{type(value).__name__}\" was found')\n            return value\n        except KeyError:\n            return dep.cpp_info.get_property(prop, check_type=check_type) if not comp_name \\\n                else dep.cpp_info.components[comp_name].get_property(prop, check_type=check_type)\n\n    def get_cmake_package_name(self, dep, module_mode=None):\n        \"\"\"Get the name of the file for the ``find_package(XXX)`` call\"\"\"\n        # This is used by CMakeDeps to determine:\n        # - The filename to generate (XXX-config.cmake or FindXXX.cmake)\n        # - The name of the defined XXX_DIR variables\n        # - The name of transitive dependencies for calls to find_dependency\n        if module_mode and self.get_find_mode(dep) in [FIND_MODE_MODULE, FIND_MODE_BOTH]:\n            ret = self.get_property(\"cmake_module_file_name\", dep)\n            if ret:\n                return ret\n        ret = self.get_property(\"cmake_file_name\", dep)\n        return ret or dep.ref.name\n\n    def get_find_mode(self, dep):\n        \"\"\"\n        :param dep: requirement\n        :return: One of ``\"none\"``, ``\"config\"``, ``\"module\"`` or ``\"both\"``. Defaults to ``\"config\"`` when not set\n        \"\"\"\n        tmp = self.get_property(\"cmake_find_mode\", dep)\n        if tmp is None:\n            return \"config\"\n        return tmp.lower()\n\n    def generate_aggregator(self):\n        host = self._conanfile.dependencies.host\n        build_req = self._conanfile.dependencies.direct_build\n        test_req = self._conanfile.dependencies.test\n\n        configs = []\n        for require, dep in list(host.items()) + list(build_req.items()) + list(test_req.items()):\n            if not require.direct:\n                continue\n            if require.build and dep.ref.name not in self.build_context_activated:\n                continue\n            cmake_find_mode = self.get_property(\"cmake_find_mode\", dep)\n            cmake_find_mode = cmake_find_mode or FIND_MODE_CONFIG\n            cmake_find_mode = cmake_find_mode.lower()\n            find_module_mode = True if cmake_find_mode == FIND_MODE_MODULE else False\n            config = ConfigTemplate(self, require, dep, find_module_mode)\n            configs.append(config)\n\n        template = textwrap.dedent(\"\"\"\\\n            message(STATUS \"Conan: Using CMakeDeps conandeps_legacy.cmake aggregator via include()\")\n            message(STATUS \"Conan: It is recommended to use explicit find_package() per dependency instead\")\n\n            {% for config in configs %}\n            find_package({{config.file_name}})\n            {% endfor %}\n\n            set(CONANDEPS_LEGACY {% for t in configs %} {{t.root_target_name}} {% endfor %})\n            \"\"\")\n\n        template = Template(template, trim_blocks=True, lstrip_blocks=True,\n                            undefined=jinja2.StrictUndefined)\n        conandeps = template.render({\"configs\": configs})\n        save(self._conanfile, \"conandeps_legacy.cmake\", conandeps)\n\n    def get_transitive_requires(self, conanfile):\n        # Prepared to filter transitive tool-requires with visible=True\n        return get_transitive_requires(self._conanfile, conanfile)\n"
  },
  {
    "path": "conan/tools/cmake/cmakedeps/templates/__init__.py",
    "content": "import jinja2\nfrom jinja2 import Template\n\nfrom conan.errors import ConanException\n\n\nclass CMakeDepsFileTemplate:\n\n    def __init__(self, cmakedeps, require, conanfile, generating_module=False):\n        self.cmakedeps = cmakedeps\n        self.require = require\n        self.conanfile = conanfile\n        self.generating_module = generating_module\n\n    @property\n    def pkg_name(self):\n        return self.conanfile.ref.name + self.suffix\n\n    @property\n    def root_target_name(self):\n        return self.get_root_target_name(self.conanfile, self.suffix)\n\n    @property\n    def file_name(self):\n        return self.cmakedeps.get_cmake_package_name(self.conanfile, module_mode=self.generating_module) + self.suffix\n\n    @property\n    def suffix(self):\n        if not self.require.build:\n            return \"\"\n        return self.cmakedeps.build_context_suffix.get(self.conanfile.ref.name, \"\")\n\n    def render(self):\n        try:\n            context = self.context\n        except Exception as e:\n            raise ConanException(\"error generating context for '{}': {}\".format(self.conanfile, e))\n\n        # Cache the template instance as a class attribute to greatly speed up the rendering\n        # NOTE: this assumes that self.template always returns the same string\n        template_instance = getattr(type(self), \"template_instance\", None)\n        if template_instance is None:\n            template_instance = Template(self.template, trim_blocks=True, lstrip_blocks=True,\n                                         undefined=jinja2.StrictUndefined)\n            setattr(type(self), \"template_instance\", template_instance)\n        return template_instance.render(context)\n\n    def context(self):\n        raise NotImplementedError()\n\n    @property\n    def template(self):\n        raise NotImplementedError()\n\n    @property\n    def filename(self):\n        raise NotImplementedError()\n\n    @property\n    def configuration(self):\n        return self.cmakedeps.configuration\n\n    @property\n    def arch(self):\n        return self.cmakedeps.arch\n\n    @property\n    def config_suffix(self):\n        return \"_{}\".format(self.configuration.upper()) if self.configuration else \"\"\n\n    @staticmethod\n    def _get_target_default_name(req, component_name=\"\", suffix=\"\"):\n        return \"{name}{suffix}::{cname}{suffix}\".format(cname=component_name or req.ref.name,\n                                                        name=req.ref.name, suffix=suffix)\n\n    def get_root_target_name(self, req, suffix=\"\"):\n        if self.generating_module:\n            ret = self.cmakedeps.get_property(\"cmake_module_target_name\", req)\n            if ret:\n                return ret\n        ret = self.cmakedeps.get_property(\"cmake_target_name\", req)\n        return ret or self._get_target_default_name(req, suffix=suffix)\n\n    def get_component_alias(self, req, comp_name):\n        if comp_name not in req.cpp_info.components:\n            # foo::foo might be referencing the root cppinfo\n            if req.ref.name == comp_name:\n                return self.get_root_target_name(req)\n            raise ConanException(\"Component '{name}::{cname}' not found in '{name}' \"\n                                 \"package requirement\".format(name=req.ref.name, cname=comp_name))\n        if self.generating_module:\n            ret = self.cmakedeps.get_property(\"cmake_module_target_name\", req, comp_name=comp_name)\n            if ret:\n                return ret\n        ret = self.cmakedeps.get_property(\"cmake_target_name\", req, comp_name=comp_name)\n\n        # If we don't specify the `cmake_target_name` property for the component it will\n        # fallback to the pkg_name::comp_name, it wont use the root cpp_info cmake_target_name\n        # property because that is also an absolute name (Greetings::Greetings), it is not a namespace\n        # and we don't want to split and do tricks.\n        return ret or self._get_target_default_name(req, component_name=comp_name)\n"
  },
  {
    "path": "conan/tools/cmake/cmakedeps/templates/config.py",
    "content": "import textwrap\n\nfrom conan.tools.cmake.cmakedeps.templates import CMakeDepsFileTemplate\n\n\"\"\"\n\nFooConfig.cmake\nfoo-config.cmake\n\n\"\"\"\n\n\nclass ConfigTemplate(CMakeDepsFileTemplate):\n\n    @property\n    def filename(self):\n        if self.generating_module:\n            return \"Find{}.cmake\".format(self.file_name)\n        else:\n            if self.file_name == self.file_name.lower():\n                return \"{}-config.cmake\".format(self.file_name)\n            else:\n                return \"{}Config.cmake\".format(self.file_name)\n\n    @property\n    def additional_variables_prefixes(self):\n        prefix_list = (\n            self.cmakedeps.get_property(\"cmake_additional_variables_prefixes\", self.conanfile, check_type=list) or [])\n        return list(set([self.file_name] + prefix_list))\n\n    @property\n    def parsed_extra_variables(self):\n        # Reading configuration from \"cmake_extra_variables\" property\n        from conan.tools.cmake.utils import parse_extra_variable\n        conf_extra_variables = self.conanfile.conf.get(\"tools.cmake.cmaketoolchain:extra_variables\",\n                                                       default={}, check_type=dict)\n        dep_extra_variables = self.cmakedeps.get_property(\"cmake_extra_variables\", self.conanfile,\n                                                          check_type=dict) or {}\n        # The configuration variables have precedence over the dependency ones\n        extra_variables = {dep: value for dep, value in dep_extra_variables.items()\n                           if dep not in conf_extra_variables}\n        parsed_extra_variables = {}\n        for key, value in extra_variables.items():\n            parsed_extra_variables[key] = parse_extra_variable(\"cmake_extra_variables\",\n                                                               key, value)\n        return parsed_extra_variables\n\n    @property\n    def context(self):\n        targets_include = \"\" if not self.generating_module else \"module-\"\n        targets_include += \"{}Targets.cmake\".format(self.file_name)\n        return {\"is_module\": self.generating_module,\n                \"version\": self.conanfile.ref.version,\n                \"file_name\":  self.file_name,\n                \"additional_variables_prefixes\": self.additional_variables_prefixes,\n                \"extra_variables\": self.parsed_extra_variables,\n                \"pkg_name\": self.pkg_name,\n                \"config_suffix\": self.config_suffix,\n                \"check_components_exist\": self.cmakedeps.check_components_exist,\n                \"targets_include_file\": targets_include}\n\n    @property\n    def template(self):\n        return textwrap.dedent(\"\"\"\\\n        {%- macro pkg_var(pkg_name, var, config_suffix) -%}\n             {{'${'+pkg_name+'_'+var+config_suffix+'}'}}\n        {%- endmacro -%}\n        ########## MACROS ###########################################################################\n        #############################################################################################\n\n        # Requires CMake > 3.15\n        if(${CMAKE_VERSION} VERSION_LESS \"3.15\")\n            message(FATAL_ERROR \"The 'CMakeDeps' generator only works with CMake >= 3.15\")\n        endif()\n\n        if({{ file_name }}_FIND_QUIETLY)\n            set({{ file_name }}_MESSAGE_MODE VERBOSE)\n        else()\n            set({{ file_name }}_MESSAGE_MODE STATUS)\n        endif()\n\n        include(${CMAKE_CURRENT_LIST_DIR}/cmakedeps_macros.cmake)\n        include(${CMAKE_CURRENT_LIST_DIR}/{{ targets_include_file }})\n        include(CMakeFindDependencyMacro)\n\n        check_build_type_defined()\n\n        foreach(_DEPENDENCY {{ pkg_var(pkg_name, 'FIND_DEPENDENCY_NAMES', '') }} )\n            # Check that we have not already called a find_package with the transitive dependency\n            if(NOT {{ '${_DEPENDENCY}' }}_FOUND)\n                find_dependency({{ '${_DEPENDENCY}' }} REQUIRED ${${_DEPENDENCY}_FIND_MODE})\n            endif()\n        endforeach()\n\n        {% for prefix in additional_variables_prefixes %}\n        set({{ prefix }}_VERSION_STRING \"{{ version }}\")\n        set({{ prefix }}_INCLUDE_DIRS {{ pkg_var(pkg_name, 'INCLUDE_DIRS', config_suffix) }} )\n        set({{ prefix }}_INCLUDE_DIR {{ pkg_var(pkg_name, 'INCLUDE_DIRS', config_suffix) }} )\n        set({{ prefix }}_LIBRARIES {{ pkg_var(pkg_name, 'LIBRARIES', config_suffix) }} )\n        set({{ prefix }}_DEFINITIONS {{ pkg_var(pkg_name, 'DEFINITIONS', config_suffix) }} )\n\n        {% endfor %}\n\n        # Definition of extra CMake variables from cmake_extra_variables\n\n        {% for key, value in extra_variables.items() %}\n        set({{ key }} {{ value }})\n        {% endfor %}\n\n        # Only the last installed configuration BUILD_MODULES are included to avoid the collision\n        foreach(_BUILD_MODULE {{ pkg_var(pkg_name, 'BUILD_MODULES_PATHS', config_suffix) }} )\n            message({% raw %}${{% endraw %}{{ file_name }}_MESSAGE_MODE} \"Conan: Including build module from '${_BUILD_MODULE}'\")\n            include({{ '${_BUILD_MODULE}' }})\n        endforeach()\n\n        {% if check_components_exist %}\n        # Check that the specified components in the find_package(Foo COMPONENTS x y z) are there\n        # This is the variable filled by CMake with the requested components in find_package\n        if({{ file_name }}_FIND_COMPONENTS)\n            foreach(_FIND_COMPONENT {{ pkg_var(file_name, 'FIND_COMPONENTS', '') }})\n                if (TARGET ${_FIND_COMPONENT})\n                    message({% raw %}${{% endraw %}{{ file_name }}_MESSAGE_MODE} \"Conan: Component '${_FIND_COMPONENT}' found in package '{{ pkg_name }}'\")\n                else()\n                    message(FATAL_ERROR \"Conan: Component '${_FIND_COMPONENT}' NOT found in package '{{ pkg_name }}'\")\n                endif()\n            endforeach()\n        endif()\n        {% endif %}\n\n        {% if is_module %}\n        include(FindPackageHandleStandardArgs)\n        set({{ file_name }}_FOUND 1)\n        set({{ file_name }}_VERSION \"{{ version }}\")\n\n        find_package_handle_standard_args({{ file_name }}\n                                          REQUIRED_VARS {{ file_name }}_VERSION\n                                          VERSION_VAR {{ file_name }}_VERSION)\n        mark_as_advanced({{ file_name }}_FOUND {{ file_name }}_VERSION)\n\n        {% for prefix in additional_variables_prefixes %}\n        set({{ prefix }}_FOUND 1)\n        set({{ prefix }}_VERSION \"{{ version }}\")\n        mark_as_advanced({{ prefix }}_FOUND {{ prefix }}_VERSION)\n        {% endfor %}\n\n        {% endif %}\n        \"\"\")\n"
  },
  {
    "path": "conan/tools/cmake/cmakedeps/templates/config_version.py",
    "content": "import textwrap\n\nfrom conan.tools.cmake.cmakedeps.templates import CMakeDepsFileTemplate\nfrom conan.errors import ConanException\n\n\"\"\"\n    foo-config-version.cmake\n\n\"\"\"\n\n\nclass ConfigVersionTemplate(CMakeDepsFileTemplate):\n\n    @property\n    def filename(self):\n        if self.file_name == self.file_name.lower():\n            return \"{}-config-version.cmake\".format(self.file_name)\n        else:\n            return \"{}ConfigVersion.cmake\".format(self.file_name)\n\n    @property\n    def context(self):\n        policy = self.cmakedeps.get_property(\"cmake_config_version_compat\", self.conanfile)\n        if policy is None:\n            policy = \"SameMajorVersion\"\n        if policy not in (\"AnyNewerVersion\", \"SameMajorVersion\", \"SameMinorVersion\", \"ExactVersion\"):\n            raise ConanException(f\"Unknown cmake_config_version_compat={policy} in {self.conanfile}\")\n        version = self.cmakedeps.get_property(\"system_package_version\", self.conanfile)\n        version = version or self.conanfile.ref.version\n        return {\"version\": version,\n                \"policy\": policy}\n\n    @property\n    def template(self):\n        # https://gitlab.kitware.com/cmake/cmake/blob/master/Modules/BasicConfigVersion-SameMajorVersion.cmake.in\n        # This will be at XXX-config-version.cmake\n        # AnyNewerVersion|SameMajorVersion|SameMinorVersion|ExactVersion\n        ret = textwrap.dedent(\"\"\"\\\n            set(PACKAGE_VERSION \"{{ version }}\")\n\n            if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION)\n                set(PACKAGE_VERSION_COMPATIBLE FALSE)\n            else()\n                {% if policy == \"AnyNewerVersion\" %}\n                set(PACKAGE_VERSION_COMPATIBLE TRUE)\n                {% elif policy == \"SameMajorVersion\" %}\n                if(\"{{ version }}\" MATCHES \"^([0-9]+)\\\\\\\\.\")\n                    set(CVF_VERSION_MAJOR {{ '${CMAKE_MATCH_1}' }})\n                else()\n                    set(CVF_VERSION_MAJOR \"{{ version }}\")\n                endif()\n\n                if(PACKAGE_FIND_VERSION_MAJOR STREQUAL CVF_VERSION_MAJOR)\n                    set(PACKAGE_VERSION_COMPATIBLE TRUE)\n                else()\n                    set(PACKAGE_VERSION_COMPATIBLE FALSE)\n                endif()\n                {% elif policy == \"SameMinorVersion\" %}\n                if(\"{{ version }}\" MATCHES \"^([0-9]+)\\\\.([0-9]+)\")\n                    set(CVF_VERSION_MAJOR \"${CMAKE_MATCH_1}\")\n                    set(CVF_VERSION_MINOR \"${CMAKE_MATCH_2}\")\n                else()\n                    set(CVF_VERSION_MAJOR \"{{ version }}\")\n                    set(CVF_VERSION_MINOR \"\")\n                endif()\n                if((PACKAGE_FIND_VERSION_MAJOR STREQUAL CVF_VERSION_MAJOR) AND\n                    (PACKAGE_FIND_VERSION_MINOR STREQUAL CVF_VERSION_MINOR))\n                  set(PACKAGE_VERSION_COMPATIBLE TRUE)\n                else()\n                  set(PACKAGE_VERSION_COMPATIBLE FALSE)\n                endif()\n                {% elif policy == \"ExactVersion\" %}\n                if(\"{{ version }}\" MATCHES \"^([0-9]+)\\\\.([0-9]+)\\\\.([0-9]+)\")\n                    set(CVF_VERSION_MAJOR \"${CMAKE_MATCH_1}\")\n                    set(CVF_VERSION_MINOR \"${CMAKE_MATCH_2}\")\n                    set(CVF_VERSION_MINOR \"${CMAKE_MATCH_3}\")\n                else()\n                    set(CVF_VERSION_MAJOR \"{{ version }}\")\n                    set(CVF_VERSION_MINOR \"\")\n                    set(CVF_VERSION_PATCH \"\")\n                endif()\n                if((PACKAGE_FIND_VERSION_MAJOR STREQUAL CVF_VERSION_MAJOR) AND\n                    (PACKAGE_FIND_VERSION_MINOR STREQUAL CVF_VERSION_MINOR) AND\n                    (PACKAGE_FIND_VERSION_PATCH STREQUAL CVF_VERSION_PATCH))\n                  set(PACKAGE_VERSION_COMPATIBLE TRUE)\n                else()\n                  set(PACKAGE_VERSION_COMPATIBLE FALSE)\n                endif()\n                {% endif %}\n\n                if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION)\n                    set(PACKAGE_VERSION_EXACT TRUE)\n                endif()\n            endif()\n            \"\"\")\n        return ret\n"
  },
  {
    "path": "conan/tools/cmake/cmakedeps/templates/macros.py",
    "content": "import textwrap\n\nfrom conan.tools.cmake.cmakedeps.templates import CMakeDepsFileTemplate\n\n\"\"\"\n\ncmakedeps_macros.cmake\n\n\"\"\"\n\n\nclass MacrosTemplate(CMakeDepsFileTemplate):\n    \"\"\"cmakedeps_macros.cmake\"\"\"\n\n    def __init__(self):\n        super(MacrosTemplate, self).__init__(cmakedeps=None, require=None, conanfile=None)\n\n    @property\n    def filename(self):\n        return \"cmakedeps_macros.cmake\"\n\n    @property\n    def context(self):\n        return {}\n\n    @property\n    def template(self):\n        return textwrap.dedent(\"\"\"\n       macro(conan_find_apple_frameworks FRAMEWORKS_FOUND FRAMEWORKS FRAMEWORKS_DIRS)\n           if(APPLE)\n               foreach(_FRAMEWORK ${FRAMEWORKS})\n                   # https://cmake.org/pipermail/cmake-developers/2017-August/030199.html\n                   find_library(CONAN_FRAMEWORK_${_FRAMEWORK}_FOUND NAMES ${_FRAMEWORK} PATHS ${FRAMEWORKS_DIRS} CMAKE_FIND_ROOT_PATH_BOTH)\n                   if(CONAN_FRAMEWORK_${_FRAMEWORK}_FOUND)\n                       list(APPEND ${FRAMEWORKS_FOUND} ${CONAN_FRAMEWORK_${_FRAMEWORK}_FOUND})\n                       message(VERBOSE \"Framework found! ${FRAMEWORKS_FOUND}\")\n                   else()\n                       message(FATAL_ERROR \"Framework library ${_FRAMEWORK} not found in paths: ${FRAMEWORKS_DIRS}\")\n                   endif()\n               endforeach()\n           endif()\n       endmacro()\n\n       function(conan_package_library_targets libraries package_libdir package_bindir library_type\n                is_host_windows deps_target out_libraries_target config_suffix package_name no_soname_mode)\n           set(_out_libraries_target \"\")\n\n           foreach(_LIBRARY_NAME ${libraries})\n               if(CMAKE_SYSTEM_NAME MATCHES \"Windows\" AND NOT DEFINED MINGW AND CMAKE_VERSION VERSION_LESS \"3.29\")\n                   # Backport logic from https://github.com/Kitware/CMake/commit/c6efbd78d86798573654d1a791f76de0e71bd93f\n                   # which is only needed on versions older than 3.29\n                   # this allows finding static library files created by meson\n                   # We are not affected by PATH-derived folders, because we call find_library with NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH\n                   set(_original_find_library_suffixes \"${CMAKE_FIND_LIBRARY_SUFFIXES}\")\n                   set(_original_find_library_prefixes \"${CMAKE_FIND_LIBRARY_PREFIXES}\")\n                   set(CMAKE_FIND_LIBRARY_PREFIXES \"\" \"lib\")\n                   set(CMAKE_FIND_LIBRARY_SUFFIXES \".dll.lib\" \".lib\" \".a\")\n               endif()\n               find_library(CONAN_FOUND_LIBRARY NAMES ${_LIBRARY_NAME} PATHS ${package_libdir}\n                           NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)\n               if(DEFINED _original_find_library_suffixes)\n                   set(CMAKE_FIND_LIBRARY_SUFFIXES \"${_original_find_library_suffixes}\")\n                   set(CMAKE_FIND_LIBRARY_PREFIXES \"${_original_find_library_prefixes}\")\n                   unset(_original_find_library_suffixes)\n                   unset(_original_find_library_prefixes)\n               endif()\n               if(CONAN_FOUND_LIBRARY)\n                   message(VERBOSE \"Conan: Library ${_LIBRARY_NAME} found ${CONAN_FOUND_LIBRARY}\")\n\n                   # Create a micro-target for each lib/a found\n                   # Allow only some characters for the target name\n                   string(REGEX REPLACE \"[^A-Za-z0-9.+_-]\" \"_\" _LIBRARY_NAME ${_LIBRARY_NAME})\n                   set(_LIB_NAME CONAN_LIB::${package_name}_${_LIBRARY_NAME}${config_suffix})\n\n                   if(is_host_windows AND library_type STREQUAL \"SHARED\")\n                     # Store and reset the variable, so it doesn't leak\n                     set(_OLD_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})\n                     set(CMAKE_FIND_LIBRARY_SUFFIXES .dll ${CMAKE_FIND_LIBRARY_SUFFIXES})\n                     find_library(CONAN_SHARED_FOUND_LIBRARY NAMES ${_LIBRARY_NAME} PATHS ${package_bindir}\n                                  NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)\n                     set(CMAKE_FIND_LIBRARY_SUFFIXES ${_OLD_CMAKE_FIND_LIBRARY_SUFFIXES})\n                     if(NOT CONAN_SHARED_FOUND_LIBRARY)\n                       message(DEBUG \"DLL library not found, creating UNKNOWN IMPORTED target, searched for: ${_LIBRARY_NAME}\")\n                       if(NOT TARGET ${_LIB_NAME})\n                          add_library(${_LIB_NAME} UNKNOWN IMPORTED)\n                       endif()\n                       set_target_properties(${_LIB_NAME} PROPERTIES IMPORTED_LOCATION${config_suffix} ${CONAN_FOUND_LIBRARY})\n                     else()\n                        if(NOT TARGET ${_LIB_NAME})\n                          add_library(${_LIB_NAME} SHARED IMPORTED)\n                        endif()\n                        set_target_properties(${_LIB_NAME} PROPERTIES IMPORTED_LOCATION${config_suffix} ${CONAN_SHARED_FOUND_LIBRARY})\n                        set_target_properties(${_LIB_NAME} PROPERTIES IMPORTED_IMPLIB${config_suffix} ${CONAN_FOUND_LIBRARY})\n                        message(DEBUG \"Found DLL and STATIC at ${CONAN_SHARED_FOUND_LIBRARY}, ${CONAN_FOUND_LIBRARY}\")\n                     endif()\n                     unset(CONAN_SHARED_FOUND_LIBRARY CACHE)\n                   else()\n                     if(NOT TARGET ${_LIB_NAME})\n                         # library_type can be STATIC, still UNKNOWN (if no package type available in the recipe) or SHARED (but no windows)\n                         add_library(${_LIB_NAME} ${library_type} IMPORTED)\n                     endif()\n                     message(DEBUG \"Created target ${_LIB_NAME} ${library_type} IMPORTED\")\n                     set_target_properties(${_LIB_NAME} PROPERTIES IMPORTED_LOCATION${config_suffix} ${CONAN_FOUND_LIBRARY} IMPORTED_NO_SONAME ${no_soname_mode})\n                   endif()\n                   list(APPEND _out_libraries_target ${_LIB_NAME})\n                   message(VERBOSE \"Conan: Found: ${CONAN_FOUND_LIBRARY}\")\n               else()\n                   message(FATAL_ERROR \"Library '${_LIBRARY_NAME}' not found in package. If '${_LIBRARY_NAME}' is a system library, declare it with 'cpp_info.system_libs' property\")\n               endif()\n               unset(CONAN_FOUND_LIBRARY CACHE)\n           endforeach()\n\n           # Add the dependencies target for all the imported libraries\n           foreach(_T ${_out_libraries_target})\n               set_property(TARGET ${_T} APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${deps_target})\n           endforeach()\n\n           set(${out_libraries_target} ${_out_libraries_target} PARENT_SCOPE)\n       endfunction()\n\n       macro(check_build_type_defined)\n           # Check that the -DCMAKE_BUILD_TYPE argument is always present\n           get_property(isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)\n           if(NOT isMultiConfig AND NOT CMAKE_BUILD_TYPE)\n               message(FATAL_ERROR \"Please, set the CMAKE_BUILD_TYPE variable when calling to CMake \"\n                                   \"adding the '-DCMAKE_BUILD_TYPE=<build_type>' argument.\")\n           endif()\n       endmacro()\n\n        \"\"\")\n"
  },
  {
    "path": "conan/tools/cmake/cmakedeps/templates/target_configuration.py",
    "content": "import textwrap\n\nfrom conan.tools.cmake.cmakedeps.templates import CMakeDepsFileTemplate\n\n\"\"\"\n\nFooTarget-release.cmake\n\n\"\"\"\n\n\nclass TargetConfigurationTemplate(CMakeDepsFileTemplate):\n\n    @property\n    def filename(self):\n        name = \"\" if not self.generating_module else \"module-\"\n        name += \"{}-Target-{}.cmake\".format(self.file_name, self.cmakedeps.configuration.lower())\n        return name\n\n    @property\n    def context(self):\n        deps_targets_names = self.get_deps_targets_names() \\\n            if not self.require.build else []\n\n        components_targets_names = self.get_declared_components_targets_names()\n        components_names = [(components_target_name.replace(\"::\", \"_\"), components_target_name)\n                            for components_target_name in components_targets_names]\n\n        is_win = self.conanfile.settings.get_safe(\"os\") == \"Windows\"\n        auto_link = self.cmakedeps.get_property(\"cmake_set_interface_link_directories\",\n                                                self.conanfile, check_type=bool)\n        if auto_link:\n            out = self.cmakedeps._conanfile.output # noqa\n            out.warning(\"CMakeDeps: cmake_set_interface_link_directories is legacy, not necessary\",\n                        warn_tag=\"deprecated\")\n\n        return {\"pkg_name\": self.pkg_name,\n                \"root_target_name\": self.root_target_name,\n                \"config_suffix\": self.config_suffix,\n                \"config\": self.configuration.upper(),\n                \"deps_targets_names\": \";\".join(deps_targets_names),\n                \"components_names\": components_names,\n                \"configuration\": self.cmakedeps.configuration,\n                \"set_interface_link_directories\": auto_link and is_win}\n\n    @property\n    def template(self):\n        return textwrap.dedent(\"\"\"\\\n        # Avoid multiple calls to find_package to append duplicated properties to the targets\n        include_guard()\n\n        {%- macro comp_var(pkg_name, comp_name, var, config_suffix) -%}\n            {{'${'+pkg_name+'_'+comp_name+'_'+var+config_suffix+'}'}}\n        {%- endmacro -%}\n        {%- macro pkg_var(pkg_name, var, config_suffix) -%}\n            {{'${'+pkg_name+'_'+var+config_suffix+'}'}}\n        {%- endmacro -%}\n\n        ########### VARIABLES #######################################################################\n        #############################################################################################\n        set({{ pkg_name }}_FRAMEWORKS_FOUND{{ config_suffix }} \"\") # Will be filled later\n        conan_find_apple_frameworks({{ pkg_name }}_FRAMEWORKS_FOUND{{ config_suffix }} \"{{ pkg_var(pkg_name, 'FRAMEWORKS', config_suffix) }}\" \"{{ pkg_var(pkg_name, 'FRAMEWORK_DIRS', config_suffix) }}\")\n\n        set({{ pkg_name }}_LIBRARIES_TARGETS \"\") # Will be filled later\n\n\n        ######## Create an interface target to contain all the dependencies (frameworks, system and conan deps)\n        if(NOT TARGET {{ pkg_name+'_DEPS_TARGET'}})\n            add_library({{ pkg_name+'_DEPS_TARGET'}} INTERFACE IMPORTED)\n        endif()\n\n        set_property(TARGET {{ pkg_name + '_DEPS_TARGET'}}\n                     APPEND PROPERTY INTERFACE_LINK_LIBRARIES\n                     $<$<CONFIG:{{configuration}}>:{{ pkg_var(pkg_name, 'FRAMEWORKS_FOUND', config_suffix) }}>\n                     $<$<CONFIG:{{configuration}}>:{{ pkg_var(pkg_name, 'SYSTEM_LIBS', config_suffix) }}>\n                     $<$<CONFIG:{{configuration}}>:{{ deps_targets_names }}>)\n\n        ####### Find the libraries declared in cpp_info.libs, create an IMPORTED target for each one and link the\n        ####### {{pkg_name}}_DEPS_TARGET to all of them\n        conan_package_library_targets(\"{{ pkg_var(pkg_name, 'LIBS', config_suffix) }}\"    # libraries\n                                      \"{{ pkg_var(pkg_name, 'LIB_DIRS', config_suffix) }}\" # package_libdir\n                                      \"{{ pkg_var(pkg_name, 'BIN_DIRS', config_suffix) }}\" # package_bindir\n                                      \"{{ pkg_var(pkg_name, 'LIBRARY_TYPE', config_suffix) }}\"\n                                      \"{{ pkg_var(pkg_name, 'IS_HOST_WINDOWS', config_suffix) }}\"\n                                      {{ pkg_name + '_DEPS_TARGET'}}\n                                      {{ pkg_name }}_LIBRARIES_TARGETS  # out_libraries_targets\n                                      \"{{ config_suffix }}\"\n                                      \"{{ pkg_name }}\"    # package_name\n                                      \"{{ pkg_var(pkg_name, 'NO_SONAME_MODE', config_suffix) }}\")  # soname\n\n        # FIXME: What is the result of this for multi-config? All configs adding themselves to path?\n        set(CMAKE_MODULE_PATH {{ pkg_var(pkg_name, 'BUILD_DIRS', config_suffix) }} {{ '${' }}CMAKE_MODULE_PATH})\n        {% if not components_names %}\n\n        ########## GLOBAL TARGET PROPERTIES {{ configuration }} ########################################\n            set_property(TARGET {{root_target_name}}\n                         APPEND PROPERTY INTERFACE_LINK_LIBRARIES\n                         $<$<CONFIG:{{configuration}}>:{{ pkg_var(pkg_name, 'OBJECTS', config_suffix) }}>\n                         $<$<CONFIG:{{configuration}}>:{{ pkg_var(pkg_name, 'LIBRARIES_TARGETS', '') }}>\n                         )\n\n            if(\"{{ pkg_var(pkg_name, 'LIBS', config_suffix) }}\" STREQUAL \"\")\n                # If the package is not declaring any \"cpp_info.libs\" the package deps, system libs,\n                # frameworks etc are not linked to the imported targets and we need to do it to the\n                # global target\n                set_property(TARGET {{root_target_name}}\n                             APPEND PROPERTY INTERFACE_LINK_LIBRARIES\n                             {{pkg_name}}_DEPS_TARGET)\n            endif()\n\n            set_property(TARGET {{root_target_name}}\n                         APPEND PROPERTY INTERFACE_LINK_OPTIONS\n                         $<$<CONFIG:{{configuration}}>:{{ pkg_var(pkg_name, 'LINKER_FLAGS', config_suffix) }}>)\n            set_property(TARGET {{root_target_name}}\n                         APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES\n                         $<$<CONFIG:{{configuration}}>:{{ pkg_var(pkg_name, 'INCLUDE_DIRS', config_suffix) }}>)\n            # Necessary to find LINK shared libraries in Linux\n            set_property(TARGET {{root_target_name}}\n                         APPEND PROPERTY INTERFACE_LINK_DIRECTORIES\n                         $<$<CONFIG:{{configuration}}>:{{ pkg_var(pkg_name, 'LIB_DIRS', config_suffix) }}>)\n            set_property(TARGET {{root_target_name}}\n                         APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS\n                         $<$<CONFIG:{{configuration}}>:{{ pkg_var(pkg_name, 'COMPILE_DEFINITIONS', config_suffix) }}>)\n            set_property(TARGET {{root_target_name}}\n                         APPEND PROPERTY INTERFACE_COMPILE_OPTIONS\n                         $<$<CONFIG:{{configuration}}>:{{ pkg_var(pkg_name, 'COMPILE_OPTIONS', config_suffix) }}>)\n        {%- else %}\n\n        ########## COMPONENTS TARGET PROPERTIES {{ configuration }} ########################################\n\n            {%- for comp_variable_name, comp_target_name in components_names %}\n\n\n            ########## COMPONENT {{ comp_target_name }} #############\n\n                set({{ pkg_name }}_{{ comp_variable_name }}_FRAMEWORKS_FOUND{{ config_suffix }} \"\")\n                conan_find_apple_frameworks({{ pkg_name }}_{{ comp_variable_name }}_FRAMEWORKS_FOUND{{ config_suffix }} \"{{ comp_var(pkg_name, comp_variable_name, 'FRAMEWORKS', config_suffix) }}\" \"{{ comp_var(pkg_name, comp_variable_name, 'FRAMEWORK_DIRS', config_suffix) }}\")\n\n                set({{ pkg_name }}_{{ comp_variable_name }}_LIBRARIES_TARGETS \"\")\n\n                ######## Create an interface target to contain all the dependencies (frameworks, system and conan deps)\n                if(NOT TARGET {{ pkg_name + '_' + comp_variable_name + '_DEPS_TARGET'}})\n                    add_library({{ pkg_name + '_' + comp_variable_name + '_DEPS_TARGET'}} INTERFACE IMPORTED)\n                endif()\n\n                set_property(TARGET {{ pkg_name + '_' + comp_variable_name + '_DEPS_TARGET'}}\n                             APPEND PROPERTY INTERFACE_LINK_LIBRARIES\n                             $<$<CONFIG:{{configuration}}>:{{ comp_var(pkg_name, comp_variable_name, 'FRAMEWORKS_FOUND', config_suffix) }}>\n                             $<$<CONFIG:{{configuration}}>:{{ comp_var(pkg_name, comp_variable_name, 'SYSTEM_LIBS', config_suffix) }}>\n                             $<$<CONFIG:{{configuration}}>:{{ comp_var(pkg_name, comp_variable_name, 'DEPENDENCIES', config_suffix) }}>\n                             )\n\n                ####### Find the libraries declared in cpp_info.component[\"xxx\"].libs,\n                ####### create an IMPORTED target for each one and link the '{{pkg_name}}_{{comp_variable_name}}_DEPS_TARGET' to all of them\n                conan_package_library_targets(\"{{ comp_var(pkg_name, comp_variable_name, 'LIBS', config_suffix) }}\"\n                                      \"{{ comp_var(pkg_name, comp_variable_name, 'LIB_DIRS', config_suffix) }}\"\n                                      \"{{ comp_var(pkg_name, comp_variable_name, 'BIN_DIRS', config_suffix) }}\" # package_bindir\n                                      \"{{ comp_var(pkg_name, comp_variable_name, 'LIBRARY_TYPE', config_suffix) }}\"\n                                      \"{{ comp_var(pkg_name, comp_variable_name, 'IS_HOST_WINDOWS', config_suffix) }}\"\n                                      {{ pkg_name + '_' + comp_variable_name + '_DEPS_TARGET'}}\n                                      {{ pkg_name + '_' + comp_variable_name + '_LIBRARIES_TARGETS'}}\n                                      \"{{ config_suffix }}\"\n                                      \"{{ pkg_name }}_{{ comp_variable_name }}\"\n                                      \"{{ comp_var(pkg_name, comp_variable_name, 'NO_SONAME_MODE', config_suffix) }}\")\n\n\n                ########## TARGET PROPERTIES #####################################\n                set_property(TARGET {{comp_target_name}}\n                             APPEND PROPERTY INTERFACE_LINK_LIBRARIES\n                             $<$<CONFIG:{{configuration}}>:{{ comp_var(pkg_name, comp_variable_name, 'OBJECTS', config_suffix) }}>\n                             $<$<CONFIG:{{configuration}}>:{{ comp_var(pkg_name, comp_variable_name, 'LIBRARIES_TARGETS', '') }}>\n                             )\n\n                if(\"{{ comp_var(pkg_name, comp_variable_name, 'LIBS', config_suffix) }}\" STREQUAL \"\")\n                    # If the component is not declaring any \"cpp_info.components['foo'].libs\" the system, frameworks etc are not\n                    # linked to the imported targets and we need to do it to the global target\n                    set_property(TARGET {{comp_target_name}}\n                                 APPEND PROPERTY INTERFACE_LINK_LIBRARIES\n                                 {{pkg_name}}_{{comp_variable_name}}_DEPS_TARGET)\n                endif()\n\n                set_property(TARGET {{ comp_target_name }} APPEND PROPERTY INTERFACE_LINK_OPTIONS\n                             $<$<CONFIG:{{ configuration }}>:{{ comp_var(pkg_name, comp_variable_name, 'LINKER_FLAGS', config_suffix) }}>)\n                set_property(TARGET {{ comp_target_name }} APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES\n                             $<$<CONFIG:{{ configuration }}>:{{ comp_var(pkg_name, comp_variable_name, 'INCLUDE_DIRS', config_suffix) }}>)\n                set_property(TARGET {{ comp_target_name }} APPEND PROPERTY INTERFACE_LINK_DIRECTORIES\n                             $<$<CONFIG:{{ configuration }}>:{{ comp_var(pkg_name, comp_variable_name, 'LIB_DIRS', config_suffix) }}>)\n                set_property(TARGET {{ comp_target_name }} APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS\n                             $<$<CONFIG:{{ configuration }}>:{{ comp_var(pkg_name, comp_variable_name, 'COMPILE_DEFINITIONS', config_suffix) }}>)\n                set_property(TARGET {{ comp_target_name }} APPEND PROPERTY INTERFACE_COMPILE_OPTIONS\n                             $<$<CONFIG:{{ configuration }}>:{{ comp_var(pkg_name, comp_variable_name, 'COMPILE_OPTIONS', config_suffix) }}>)\n            {%endfor %}\n\n\n            ########## AGGREGATED GLOBAL TARGET WITH THE COMPONENTS #####################\n            {%- for comp_variable_name, comp_target_name in components_names %}\n\n            set_property(TARGET {{root_target_name}} APPEND PROPERTY INTERFACE_LINK_LIBRARIES {{ comp_target_name }})\n\n            {%- endfor %}\n\n\n        {%- endif %}\n\n\n        ########## For the modules (FindXXX)\n        set({{ pkg_name }}_LIBRARIES{{ config_suffix }} {{root_target_name}})\n\n        \"\"\")\n\n    def get_declared_components_targets_names(self):\n        \"\"\"Returns a list of component_name\"\"\"\n        ret = []\n        sorted_comps = self.conanfile.cpp_info.get_sorted_components()\n        for comp_name, comp in sorted_comps.items():\n            ret.append(self.get_component_alias(self.conanfile, comp_name))\n        ret.reverse()\n        return ret\n\n    def get_deps_targets_names(self):\n        \"\"\"\n          - [{foo}::{bar}, ] of the required\n        \"\"\"\n        ret = []\n\n        # Get a list of dependencies target names\n        # Declared cppinfo.requires or .components[].requires\n        transitive_reqs = self.cmakedeps.get_transitive_requires(self.conanfile)\n        if self.conanfile.cpp_info.required_components:\n            for dep_name, component_name in self.conanfile.cpp_info.required_components:\n                try:\n                    # if not dep_name, it is internal, from current self.conanfile\n                    req = transitive_reqs[dep_name] if dep_name is not None else self.conanfile\n                except KeyError:\n                    # if it raises it means the required component is not in the direct_host\n                    # dependencies, maybe it has been filtered out by traits => Skip\n                    pass\n                else:\n                    component_name = self.get_component_alias(req, component_name)\n                    ret.append(component_name)\n        elif transitive_reqs:\n            # Regular external \"conanfile.requires\" declared, not cpp_info requires\n            ret = [self.get_root_target_name(r) for r in transitive_reqs.values()]\n        return ret\n"
  },
  {
    "path": "conan/tools/cmake/cmakedeps/templates/target_data.py",
    "content": "import os\nimport textwrap\n\nfrom conan.tools.cmake.cmakedeps import FIND_MODE_NONE, FIND_MODE_CONFIG, FIND_MODE_MODULE, \\\n    FIND_MODE_BOTH\nfrom conan.tools.cmake.cmakedeps.templates import CMakeDepsFileTemplate\nfrom conan.errors import ConanException\nfrom conan.internal.api.install.generators import relativize_path\nfrom conan.tools.cmake.utils import cmake_escape_value\n\n\"\"\"\n\nfoo-release-x86_64-data.cmake\n\n\"\"\"\n\n\nclass ConfigDataTemplate(CMakeDepsFileTemplate):\n\n    @property\n    def filename(self):\n        data_fname = \"\" if not self.generating_module else \"module-\"\n        data_fname += \"{}-{}\".format(self.file_name, self.configuration.lower())\n        if self.arch:\n            data_fname += \"-{}\".format(self.arch)\n        data_fname += \"-data.cmake\"\n        # https://github.com/conan-io/conan/issues/17009\n        return data_fname.replace(\"|\", \"_\")\n\n    @property\n    def _build_modules_activated(self):\n        if self.require.build:\n            return self.conanfile.ref.name in self.cmakedeps.build_context_build_modules\n        else:\n            return self.conanfile.ref.name not in self.cmakedeps.build_context_build_modules\n\n    @property\n    def context(self):\n        global_cpp = self._get_global_cpp_cmake()\n        if not self._build_modules_activated:\n            global_cpp.build_modules_paths = \"\"\n\n        components = self._get_required_components_cpp()\n        # using the target names to name components, may change in the future?\n        components_names = \" \".join([components_target_name for components_target_name, _ in\n                                    reversed(components)])\n\n        components_cpp = [(cmake_target_name.replace(\"::\", \"_\"), cmake_target_name, cpp)\n                          for cmake_target_name, cpp in components]\n\n        # For the build requires, we don't care about the transitive (only runtime for the br)\n        # so as the xxx-conf.cmake files won't be generated, don't include them as find_dependency\n        # This is because in Conan 2.0 model, only the pure tools like CMake will be build_requires\n        # for example a framework test won't be a build require but a \"test/not public\" require.\n        dependency_filenames = self._get_dependency_filenames()\n        # Get the nodes that have the property cmake_find_mode=None (no files to generate)\n        dependency_find_modes = self._get_dependencies_find_modes()\n\n        # Make the root_folder relative to the generated xxx-data.cmake file\n        root_folder = self._root_folder\n        root_folder = root_folder.replace('\\\\', '/').replace('$', '\\\\$').replace('\"', '\\\\\"')\n        # it is the relative path of the caller, not the dependency\n        root_folder = relativize_path(root_folder, self.cmakedeps._conanfile,\n                                      \"${CMAKE_CURRENT_LIST_DIR}\")\n\n        return {\"global_cpp\": global_cpp,\n                \"has_components\": self.conanfile.cpp_info.has_components,\n                \"pkg_name\": self.pkg_name,\n                \"file_name\": self.file_name,\n                \"package_folder\": root_folder,\n                \"config_suffix\": self.config_suffix,\n                \"components_names\": components_names,\n                \"components_cpp\": components_cpp,\n                \"dependency_filenames\": \" \".join(dependency_filenames),\n                \"dependency_find_modes\": dependency_find_modes}\n\n    @property\n    def cmake_package_type(self):\n        return {\"shared-library\": \"SHARED\",\n                \"static-library\": \"STATIC\"}.get(str(self.conanfile.package_type), \"UNKNOWN\")\n\n    @property\n    def is_host_windows(self):\n        # to account for all WindowsStore, WindowsCE and Windows OS in settings\n        return \"Windows\" in self.conanfile.settings.get_safe(\"os\", \"\")\n\n    @property\n    def template(self):\n        # This will be at: XXX-release-data.cmake\n        ret = textwrap.dedent(\"\"\"\\\n              {%- macro comp_var(pkg_name, comp_name, var, config_suffix) -%}\n                 {{'${'+pkg_name+'_'+comp_name+'_'+var+config_suffix+'}'}}\n              {%- endmacro -%}\n              {%- macro pkg_var(pkg_name, var, config_suffix) -%}\n                 {{'${'+pkg_name+'_'+var+config_suffix+'}'}}\n              {%- endmacro -%}\n              ########### AGGREGATED COMPONENTS AND DEPENDENCIES FOR THE MULTI CONFIG #####################\n              #############################################################################################\n\n              {% if components_names %}\n              list(APPEND {{ pkg_name }}_COMPONENT_NAMES {{ components_names }})\n              list(REMOVE_DUPLICATES {{ pkg_name }}_COMPONENT_NAMES)\n              {% else %}\n              set({{ pkg_name }}_COMPONENT_NAMES \"\")\n              {% endif %}\n              if(DEFINED {{ pkg_name }}_FIND_DEPENDENCY_NAMES)\n                list(APPEND {{ pkg_name }}_FIND_DEPENDENCY_NAMES {{ dependency_filenames }})\n                list(REMOVE_DUPLICATES {{ pkg_name }}_FIND_DEPENDENCY_NAMES)\n              else()\n                set({{ pkg_name }}_FIND_DEPENDENCY_NAMES {{ dependency_filenames }})\n              endif()\n              {% for dep_name, mode in dependency_find_modes.items() %}\n              set({{ dep_name }}_FIND_MODE \"{{ mode }}\")\n              {% endfor %}\n\n              ########### VARIABLES #######################################################################\n              #############################################################################################\n              set({{ pkg_name }}_PACKAGE_FOLDER{{ config_suffix }} \"{{ package_folder }}\")\n              set({{ pkg_name }}_BUILD_MODULES_PATHS{{ config_suffix }} {{ global_cpp.build_modules_paths }})\n\n\n              set({{ pkg_name }}_INCLUDE_DIRS{{ config_suffix }} {{ global_cpp.include_paths }})\n              set({{ pkg_name }}_RES_DIRS{{ config_suffix }} {{ global_cpp.res_paths }})\n              set({{ pkg_name }}_DEFINITIONS{{ config_suffix }} {{ global_cpp.defines }})\n              set({{ pkg_name }}_SHARED_LINK_FLAGS{{ config_suffix }} {{ global_cpp.sharedlinkflags_list }})\n              set({{ pkg_name }}_EXE_LINK_FLAGS{{ config_suffix }} {{ global_cpp.exelinkflags_list }})\n              set({{ pkg_name }}_OBJECTS{{ config_suffix }} {{ global_cpp.objects_list }})\n              set({{ pkg_name }}_COMPILE_DEFINITIONS{{ config_suffix }} {{ global_cpp.compile_definitions }})\n              set({{ pkg_name }}_COMPILE_OPTIONS_C{{ config_suffix }} {{ global_cpp.cflags_list }})\n              set({{ pkg_name }}_COMPILE_OPTIONS_CXX{{ config_suffix }} {{ global_cpp.cxxflags_list}})\n              set({{ pkg_name }}_LIB_DIRS{{ config_suffix }} {{ global_cpp.lib_paths }})\n              set({{ pkg_name }}_BIN_DIRS{{ config_suffix }} {{ global_cpp.bin_paths }})\n              set({{ pkg_name }}_LIBRARY_TYPE{{ config_suffix }} {{ global_cpp.library_type }})\n              set({{ pkg_name }}_IS_HOST_WINDOWS{{ config_suffix }} {{ global_cpp.is_host_windows }})\n              set({{ pkg_name }}_LIBS{{ config_suffix }} {{ global_cpp.libs }})\n              set({{ pkg_name }}_SYSTEM_LIBS{{ config_suffix }} {{ global_cpp.system_libs }})\n              set({{ pkg_name }}_FRAMEWORK_DIRS{{ config_suffix }} {{ global_cpp.framework_paths }})\n              set({{ pkg_name }}_FRAMEWORKS{{ config_suffix }} {{ global_cpp.frameworks }})\n              set({{ pkg_name }}_BUILD_DIRS{{ config_suffix }} {{ global_cpp.build_paths }})\n              set({{ pkg_name }}_NO_SONAME_MODE{{ config_suffix }} {{ global_cpp.no_soname }})\n\n\n              # COMPOUND VARIABLES\n              set({{ pkg_name }}_COMPILE_OPTIONS{{ config_suffix }}\n                  \"$<$<COMPILE_LANGUAGE:CXX>:{{ pkg_var(pkg_name, 'COMPILE_OPTIONS_CXX', config_suffix) }}>\"\n                  \"$<$<COMPILE_LANGUAGE:C>:{{ pkg_var(pkg_name, 'COMPILE_OPTIONS_C', config_suffix) }}>\")\n              set({{ pkg_name }}_LINKER_FLAGS{{ config_suffix }}\n                  \"$<$<STREQUAL{{ ':$' }}<TARGET_PROPERTY:TYPE>,SHARED_LIBRARY>:{{ pkg_var(pkg_name, 'SHARED_LINK_FLAGS', config_suffix) }}>\"\n                  \"$<$<STREQUAL{{ ':$' }}<TARGET_PROPERTY:TYPE>,MODULE_LIBRARY>:{{ pkg_var(pkg_name, 'SHARED_LINK_FLAGS', config_suffix) }}>\"\n                  \"$<$<STREQUAL{{ ':$' }}<TARGET_PROPERTY:TYPE>,EXECUTABLE>:{{ pkg_var(pkg_name, 'EXE_LINK_FLAGS', config_suffix) }}>\")\n\n\n              set({{ pkg_name }}_COMPONENTS{{ config_suffix }} {{ components_names }})\n              {%- for comp_variable_name, comp_target_name, cpp in components_cpp %}\n\n              ########### COMPONENT {{ comp_target_name }} VARIABLES ############################################\n\n              set({{ pkg_name }}_{{ comp_variable_name }}_INCLUDE_DIRS{{ config_suffix }} {{ cpp.include_paths }})\n              set({{ pkg_name }}_{{ comp_variable_name }}_LIB_DIRS{{ config_suffix }} {{ cpp.lib_paths }})\n              set({{ pkg_name }}_{{ comp_variable_name }}_BIN_DIRS{{ config_suffix }} {{ cpp.bin_paths }})\n              set({{ pkg_name }}_{{ comp_variable_name }}_LIBRARY_TYPE{{ config_suffix }} {{ cpp.library_type }})\n              set({{ pkg_name }}_{{ comp_variable_name }}_IS_HOST_WINDOWS{{ config_suffix }} {{ cpp.is_host_windows }})\n              set({{ pkg_name }}_{{ comp_variable_name }}_RES_DIRS{{ config_suffix }} {{ cpp.res_paths }})\n              set({{ pkg_name }}_{{ comp_variable_name }}_DEFINITIONS{{ config_suffix }} {{ cpp.defines }})\n              set({{ pkg_name }}_{{ comp_variable_name }}_OBJECTS{{ config_suffix }} {{ cpp.objects_list }})\n              set({{ pkg_name }}_{{ comp_variable_name }}_COMPILE_DEFINITIONS{{ config_suffix }} {{ cpp.compile_definitions }})\n              set({{ pkg_name }}_{{ comp_variable_name }}_COMPILE_OPTIONS_C{{ config_suffix }} \"{{ cpp.cflags_list }}\")\n              set({{ pkg_name }}_{{ comp_variable_name }}_COMPILE_OPTIONS_CXX{{ config_suffix }} \"{{ cpp.cxxflags_list }}\")\n              set({{ pkg_name }}_{{ comp_variable_name }}_LIBS{{ config_suffix }} {{ cpp.libs }})\n              set({{ pkg_name }}_{{ comp_variable_name }}_SYSTEM_LIBS{{ config_suffix }} {{ cpp.system_libs }})\n              set({{ pkg_name }}_{{ comp_variable_name }}_FRAMEWORK_DIRS{{ config_suffix }} {{ cpp.framework_paths }})\n              set({{ pkg_name }}_{{ comp_variable_name }}_FRAMEWORKS{{ config_suffix }} {{ cpp.frameworks }})\n              set({{ pkg_name }}_{{ comp_variable_name }}_DEPENDENCIES{{ config_suffix }} {{ cpp.public_deps }})\n              set({{ pkg_name }}_{{ comp_variable_name }}_SHARED_LINK_FLAGS{{ config_suffix }} {{ cpp.sharedlinkflags_list }})\n              set({{ pkg_name }}_{{ comp_variable_name }}_EXE_LINK_FLAGS{{ config_suffix }} {{ cpp.exelinkflags_list }})\n              set({{ pkg_name }}_{{ comp_variable_name }}_NO_SONAME_MODE{{ config_suffix }} {{ cpp.no_soname }})\n\n              # COMPOUND VARIABLES\n              set({{ pkg_name }}_{{ comp_variable_name }}_LINKER_FLAGS{{ config_suffix }}\n                      $<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,SHARED_LIBRARY>:{{ comp_var(pkg_name, comp_variable_name, 'SHARED_LINK_FLAGS', config_suffix) }}>\n                      $<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,MODULE_LIBRARY>:{{ comp_var(pkg_name, comp_variable_name, 'SHARED_LINK_FLAGS', config_suffix) }}>\n                      $<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:{{ comp_var(pkg_name, comp_variable_name, 'EXE_LINK_FLAGS', config_suffix) }}>\n              )\n              set({{ pkg_name }}_{{ comp_variable_name }}_COMPILE_OPTIONS{{ config_suffix }}\n                  \"$<$<COMPILE_LANGUAGE:CXX>:{{ comp_var(pkg_name, comp_variable_name, 'COMPILE_OPTIONS_CXX', config_suffix) }}>\"\n                  \"$<$<COMPILE_LANGUAGE:C>:{{ comp_var(pkg_name, comp_variable_name, 'COMPILE_OPTIONS_C', config_suffix) }}>\")\n\n              {%- endfor %}\n          \"\"\")\n        return ret\n\n    def _get_global_cpp_cmake(self):\n        global_cppinfo = self.conanfile.cpp_info.aggregated_components()\n        pfolder_var_name = \"{}_PACKAGE_FOLDER{}\".format(self.pkg_name, self.config_suffix)\n        return _TargetDataContext(global_cppinfo, pfolder_var_name, self._root_folder,\n                                  self.require, self.cmake_package_type, self.is_host_windows,\n                                  self.conanfile, self.cmakedeps)\n\n    @property\n    def _root_folder(self):\n        return self.conanfile.recipe_folder if self.conanfile.package_folder is None \\\n            else self.conanfile.package_folder\n\n    def _get_required_components_cpp(self):\n        \"\"\"Returns a list of (component_name, DepsCppCMake)\"\"\"\n        ret = []\n        sorted_comps = self.conanfile.cpp_info.get_sorted_components()\n        pfolder_var_name = \"{}_PACKAGE_FOLDER{}\".format(self.pkg_name, self.config_suffix)\n        transitive_requires = self.cmakedeps.get_transitive_requires(self.conanfile)\n        for comp_name, comp in sorted_comps.items():\n            deps_cpp_cmake = _TargetDataContext(comp, pfolder_var_name, self._root_folder,\n                                                self.require, self.cmake_package_type,\n                                                self.is_host_windows, self.conanfile, self.cmakedeps,\n                                                comp_name)\n\n            public_comp_deps = []\n            for required_pkg, required_comp in comp.parsed_requires():\n                if required_pkg is not None:  # Points to a component of a different package\n                    try:  # Make sure the declared dependency is at least in the recipe requires\n                        self.conanfile.dependencies[required_pkg]\n                    except KeyError:\n                        raise ConanException(f\"{self.conanfile}: component '{comp_name}' required \"\n                                             f\"'{required_pkg}::{required_comp}', \"\n                                             f\"but '{required_pkg}' is not a direct dependency\")\n                    try:\n                        req = transitive_requires[required_pkg]\n                    except KeyError:  # The transitive dep might have been skipped\n                        pass\n                    else:\n                        public_comp_deps.append(self.get_component_alias(req, required_comp))\n                else:  # Points to a component of same package\n                    public_comp_deps.append(self.get_component_alias(self.conanfile, required_comp))\n            deps_cpp_cmake.public_deps = \" \".join(public_comp_deps)\n            component_target_name = self.get_component_alias(self.conanfile, comp_name)\n            ret.append((component_target_name, deps_cpp_cmake))\n        ret.reverse()\n        return ret\n\n    def _get_dependency_filenames(self):\n        if self.require.build:\n            return []\n\n        transitive_reqs = self.cmakedeps.get_transitive_requires(self.conanfile)\n        # Previously it was filtering here components, but not clear why the file dependency\n        # should be skipped if components are not being required, why would it declare a\n        # dependency to it?\n        ret = [self.cmakedeps.get_cmake_package_name(r, self.generating_module)\n               for r in transitive_reqs.values()]\n        return ret\n\n    def _get_dependencies_find_modes(self):\n        ret = {}\n        if self.require.build:\n            return ret\n        deps = self.cmakedeps.get_transitive_requires(self.conanfile)\n        for dep in deps.values():\n            dep_file_name = self.cmakedeps.get_cmake_package_name(dep, self.generating_module)\n            find_mode = self.cmakedeps.get_find_mode(dep)\n            default_value = \"NO_MODULE\" if not self.generating_module else \"MODULE\"\n            values = {\n                FIND_MODE_NONE: \"\",\n                FIND_MODE_CONFIG: \"NO_MODULE\",\n                FIND_MODE_MODULE: \"MODULE\",\n                # When the dependency is \"both\" or not defined, we use the one is forced\n                # by self.find_module_mode (creating modules files-> modules, config -> config)\n                FIND_MODE_BOTH: default_value,\n                None: default_value}\n            ret[dep_file_name] = values[find_mode]\n        return ret\n\n\nclass _TargetDataContext:\n\n    def __init__(self, cpp_info, pfolder_var_name, package_folder, require, library_type,\n                 is_host_windows, conanfile, cmakedeps, comp_name=None):\n\n        def join_paths(paths):\n            \"\"\"\n            Paths are doubled quoted, and escaped (but spaces)\n            e.g: set(LIBFOO_INCLUDE_DIRS \"/path/to/included/dir\" \"/path/to/included/dir2\")\n            \"\"\"\n            ret = []\n            for p in paths:\n                assert os.path.isabs(p), \"{} is not absolute\".format(p)\n\n                # Trying to use a ${mypkg_PACKAGE_FOLDER}/include path instead of full\n                if p.startswith(package_folder):\n                    # Prepend the {{ pkg_name }}_PACKAGE_FOLDER{{ config_suffix }}\n                    rel = p[len(package_folder):]\n                    rel = rel.replace('\\\\', '/').replace('$', '\\\\$').replace('\"', '\\\\\"').lstrip(\"/\")\n                    norm_path = (\"${%s}/%s\" % (pfolder_var_name, rel))\n                else:\n                    norm_path = p.replace('\\\\', '/').replace('$', '\\\\$').replace('\"', '\\\\\"')\n                ret.append('\"{}\"'.format(norm_path))\n\n            return \"\\n\\t\\t\\t\".join(ret)\n\n        def join_flags(separator, values):\n            # Flags have to be escaped\n            ret = separator.join(cmake_escape_value(v) for v in values)\n            return ret\n\n        def join_defines(values, prefix=\"\"):\n            # Defines have to be escaped, included spaces\n            return \"\\n\\t\\t\\t\".join('\"%s%s\"' % (prefix, cmake_escape_value(v)) for v in values)\n\n        self.include_paths = join_paths(cpp_info.includedirs)\n        self.lib_paths = join_paths(cpp_info.libdirs)\n        self.res_paths = join_paths(cpp_info.resdirs)\n        self.bin_paths = join_paths(cpp_info.bindirs)\n        self.build_paths = join_paths(cpp_info.builddirs)\n        self.framework_paths = join_paths(cpp_info.frameworkdirs)\n        self.libs = join_flags(\" \", cpp_info.libs)\n        self.system_libs = join_flags(\" \", cpp_info.system_libs)\n        self.frameworks = join_flags(\" \", cpp_info.frameworks)\n        self.defines = join_defines(cpp_info.defines, \"-D\")\n        self.compile_definitions = join_defines(cpp_info.defines)\n        self.library_type = library_type\n        self.is_host_windows = \"1\" if is_host_windows else \"0\"\n\n        # For modern CMake targets we need to prepare a list to not\n        # loose the elements in the list by replacing \" \" with \";\". Example \"-framework Foundation\"\n        # Issue: #1251\n        self.cxxflags_list = join_flags(\";\", cpp_info.cxxflags)\n        self.cflags_list = join_flags(\";\", cpp_info.cflags)\n\n        # linker flags without magic: trying to mess with - and / =>\n        # https://github.com/conan-io/conan/issues/8811\n        # frameworks should be declared with cppinfo.frameworks not \"-framework Foundation\"\n        self.sharedlinkflags_list = '\"{}\"'.format(join_flags(\";\", cpp_info.sharedlinkflags)) \\\n            if cpp_info.sharedlinkflags else ''\n        self.exelinkflags_list = '\"{}\"'.format(join_flags(\";\", cpp_info.exelinkflags)) \\\n            if cpp_info.exelinkflags else ''\n\n        self.objects_list = join_paths(cpp_info.objects)\n\n        # traits logic\n        if require and not require.headers:\n            self.include_paths = \"\"\n        if require and not require.libs:\n            # self.lib_paths = \"\"  IMPORTANT! LINKERS IN LINUX FOR SHARED MIGHT NEED IT EVEN IF\n            #                      NOT REALLY LINKING LIB\n            self.libs = \"\"\n            if cpp_info.frameworkdirs:  # Only invalidate for in-package frameworks\n                # FIXME: The mix of in-package frameworks + system ones is broken\n                self.frameworks = \"\"\n        if require and not require.libs and not require.headers:\n            self.defines = \"\"\n            self.compile_definitions = \"\"\n            self.cxxflags_list = \"\"\n            self.cflags_list = \"\"\n            self.sharedlinkflags_list = \"\"\n            self.exelinkflags_list = \"\"\n            self.objects_list = \"\"\n        if require and not require.run:\n            self.bin_paths = \"\"\n\n        build_modules = cmakedeps.get_property(\"cmake_build_modules\", conanfile, check_type=list) or []\n        self.build_modules_paths = join_paths(build_modules)\n        # SONAME flag only makes sense for SHARED libraries\n        nosoname = cmakedeps.get_property(\"nosoname\", conanfile, comp_name, check_type=bool)\n        self.no_soname = str((nosoname if self.library_type == \"SHARED\" else False) or False).upper()\n"
  },
  {
    "path": "conan/tools/cmake/cmakedeps/templates/targets.py",
    "content": "import textwrap\n\nfrom conan.tools.cmake.cmakedeps.templates import CMakeDepsFileTemplate\n\n\"\"\"\n\nFooTargets.cmake\n\n\"\"\"\n\n\nclass TargetsTemplate(CMakeDepsFileTemplate):\n\n    @property\n    def filename(self):\n        name = \"\" if not self.generating_module else \"module-\"\n        name += self.file_name + \"Targets.cmake\"\n        return name\n\n    @property\n    def context(self):\n        data_pattern = \"${CMAKE_CURRENT_LIST_DIR}/\" if not self.generating_module else \"${CMAKE_CURRENT_LIST_DIR}/module-\"\n        data_pattern += \"{}-*-data.cmake\".format(self.file_name)\n\n        target_pattern = \"\" if not self.generating_module else \"module-\"\n        target_pattern += \"{}-Target-*.cmake\".format(self.file_name)\n\n        cmake_target_aliases = self.cmakedeps.get_property(\"cmake_target_aliases\",\n                                                           self.conanfile,\n                                                           check_type=list) or dict()\n\n        target = self.root_target_name\n        cmake_target_aliases = {alias: target for alias in cmake_target_aliases}\n\n        cmake_component_target_aliases = dict()\n        for comp_name in self.conanfile.cpp_info.components:\n            if comp_name is not None:\n                aliases = self.cmakedeps.get_property(\"cmake_target_aliases\",\n                                                      self.conanfile,\n                                                      comp_name=comp_name,\n                                                      check_type=list) or dict()\n                target = self.get_component_alias(self.conanfile, comp_name)\n                cmake_component_target_aliases[comp_name] = {alias: target for alias in aliases}\n\n        ret = {\"pkg_name\": self.pkg_name,\n               \"root_target_name\": self.root_target_name,\n               \"file_name\": self.file_name,\n               \"data_pattern\": data_pattern,\n               \"target_pattern\": target_pattern,\n               \"cmake_target_aliases\": cmake_target_aliases,\n               \"cmake_component_target_aliases\": cmake_component_target_aliases}\n\n        return ret\n\n    @property\n    def template(self):\n        return textwrap.dedent(\"\"\"\\\n        # Load the debug and release variables\n        file(GLOB DATA_FILES \"{{data_pattern}}\")\n\n        foreach(f ${DATA_FILES})\n            include(${f})\n        endforeach()\n\n        # Create the targets for all the components\n        foreach(_COMPONENT {{ '${' + pkg_name + '_COMPONENT_NAMES' + '}' }} )\n            if(NOT TARGET ${_COMPONENT})\n                add_library(${_COMPONENT} INTERFACE IMPORTED)\n                message({% raw %}${{% endraw %}{{ file_name }}_MESSAGE_MODE} \"Conan: Component target declared '${_COMPONENT}'\")\n            endif()\n        endforeach()\n\n        if(NOT TARGET {{ root_target_name }})\n            add_library({{ root_target_name }} INTERFACE IMPORTED)\n            message({% raw %}${{% endraw %}{{ file_name }}_MESSAGE_MODE} \"Conan: Target declared '{{ root_target_name }}'\")\n        endif()\n\n        {%- for alias, target in cmake_target_aliases.items() %}\n\n        if(NOT TARGET {{alias}})\n            add_library({{alias}} INTERFACE IMPORTED)\n            set_property(TARGET {{ alias }} PROPERTY INTERFACE_LINK_LIBRARIES {{target}})\n        endif()\n\n        {%- endfor %}\n\n        {%- for comp_name, component_aliases in cmake_component_target_aliases.items() %}\n\n            {%- for alias, target in component_aliases.items() %}\n\n        if(NOT TARGET {{alias}})\n            add_library({{alias}} INTERFACE IMPORTED)\n            set_property(TARGET {{ alias }} PROPERTY INTERFACE_LINK_LIBRARIES {{target}})\n        endif()\n\n            {%- endfor %}\n\n        {%- endfor %}\n\n        # Load the debug and release library finders\n        file(GLOB CONFIG_FILES \"${CMAKE_CURRENT_LIST_DIR}/{{ target_pattern }}\")\n\n        foreach(f ${CONFIG_FILES})\n            include(${f})\n        endforeach()\n        \"\"\")\n"
  },
  {
    "path": "conan/tools/cmake/layout.py",
    "content": "import os\nimport tempfile\n\nfrom conan.internal.graph.graph import RECIPE_CONSUMER, RECIPE_EDITABLE\nfrom conan.errors import ConanException\n\n\ndef cmake_layout(conanfile, generator=None, src_folder=\".\", build_folder=\"build\"):\n    \"\"\"\n    :param conanfile: The current recipe object. Always use ``self``.\n    :param generator: Allow defining the CMake generator. In most cases it doesn't need to be passed,\n                      as it will get the value from the configuration\n                      ``tools.cmake.cmaketoolchain:generator``, or it will automatically deduce\n                      the generator from the ``settings``\n    :param src_folder: Value for ``conanfile.folders.source``, change it if your source code\n                       (and CMakeLists.txt) is in a subfolder.\n    :param build_folder: Specify the name of the \"base\" build folder. The default is \"build\", but\n                        if that folder name is used by the project, a different one can be defined\n    \"\"\"\n    gen = conanfile.conf.get(\"tools.cmake.cmaketoolchain:generator\", default=generator)\n    if gen:\n        multi = \"Visual\" in gen or \"Xcode\" in gen or \"Multi-Config\" in gen\n    else:\n        compiler = conanfile.settings.get_safe(\"compiler\")\n        if compiler == \"msvc\":\n            multi = True\n        else:\n            multi = False\n\n    subproject = conanfile.folders.subproject\n    conanfile.folders.source = src_folder if not subproject else os.path.join(subproject, src_folder)\n    try:\n        build_type = str(conanfile.settings.build_type)\n    except ConanException:\n        raise ConanException(\"'build_type' setting not defined, it is necessary for cmake_layout()\")\n\n    try:  # TODO: Refactor this repeated pattern to deduce \"is-consumer\"\n        if conanfile._conan_node.recipe in (RECIPE_CONSUMER, RECIPE_EDITABLE):\n            folder = \"test_folder\" if conanfile.tested_reference_str else \"build_folder\"\n            build_folder = conanfile.conf.get(f\"tools.cmake.cmake_layout:{folder}\") or build_folder\n            if build_folder == \"$TMP\" and folder == \"test_folder\":\n                build_folder = tempfile.mkdtemp()\n    except AttributeError:\n        pass\n\n    build_folder = build_folder if not subproject else os.path.join(subproject, build_folder)\n    config_build_folder, user_defined_build = get_build_folder_custom_vars(conanfile)\n    if config_build_folder:\n        build_folder = os.path.join(build_folder, config_build_folder)\n    if not multi and not user_defined_build:\n        build_folder = os.path.join(build_folder, build_type)\n    conanfile.folders.build = build_folder\n\n    conanfile.folders.generators = os.path.join(conanfile.folders.build, \"generators\")\n\n    conanfile.cpp.source.includedirs = [\"include\"]\n\n    if multi:\n        conanfile.cpp.build.libdirs = [\"{}\".format(build_type)]\n        conanfile.cpp.build.bindirs = [\"{}\".format(build_type)]\n    else:\n        conanfile.cpp.build.libdirs = [\".\"]\n        conanfile.cpp.build.bindirs = [\".\"]\n\n\ndef get_build_folder_custom_vars(conanfile):\n    conanfile_vars = conanfile.folders.build_folder_vars\n    build_vars = conanfile.conf.get(\"tools.cmake.cmake_layout:build_folder_vars\", check_type=list)\n    if conanfile.tested_reference_str:\n        if build_vars is None:  # The user can define conf build_folder_vars = [] for no vars\n            build_vars = conanfile_vars or \\\n                     [\"settings.compiler\", \"settings.compiler.version\", \"settings.arch\",\n                      \"settings.compiler.cppstd\", \"settings.build_type\", \"options.shared\"]\n    else:\n        try:\n            is_consumer = conanfile._conan_node.recipe in (RECIPE_CONSUMER, RECIPE_EDITABLE)\n        except AttributeError:\n            is_consumer = False\n        if is_consumer:\n            if build_vars is None:\n                build_vars = conanfile_vars or []\n        else:\n            build_vars = conanfile_vars or []\n\n    ret = []\n    for s in build_vars:\n        group, var = s.split(\".\", 1)\n        tmp = None\n        if group == \"settings\":\n            tmp = conanfile.settings.get_safe(var)\n            if tmp and var == \"arch\":  # handle Apple multi-arch/universal binaries\n                tmp = tmp.replace(\"|\", \"_\")\n        elif group == \"options\":\n            value = conanfile.options.get_safe(var)\n            if value is not None:\n                if var == \"shared\":\n                    tmp = \"shared\" if value else \"static\"\n                else:\n                    tmp = \"{}_{}\".format(var, value)\n        elif group == \"self\":\n            tmp = getattr(conanfile, var, None)\n        elif group == \"const\":\n            tmp = var\n        else:\n            raise ConanException(\"Invalid 'tools.cmake.cmake_layout:build_folder_vars' value, it has\"\n                                 f\" to start with 'settings.', 'options.', 'self.' or 'const.': {s}\")\n        if tmp:\n            ret.append(tmp.lower())\n\n    user_defined_build = \"settings.build_type\" in build_vars\n    return \"-\".join(ret), user_defined_build\n"
  },
  {
    "path": "conan/tools/cmake/presets.py",
    "content": "import json\nimport os\nimport platform\nimport textwrap\n\nfrom conan.api.output import ConanOutput, Color\nfrom conan.tools.cmake.layout import get_build_folder_custom_vars\nfrom conan.tools.cmake.toolchain.blocks import GenericSystemBlock\nfrom conan.tools.cmake.utils import is_multi_configuration\nfrom conan.tools.build import build_jobs\nfrom conan.tools.microsoft import is_msvc\nfrom conan.internal.graph.graph import RECIPE_CONSUMER\nfrom conan.errors import ConanException\nfrom conan.internal.util.files import save, load\n\n\ndef write_cmake_presets(conanfile, toolchain_file, generator, cache_variables,\n                        user_presets_path=None, preset_prefix=None, buildenv=None, runenv=None,\n                        cmake_executable=None, absolute_paths=None):\n    preset_path, preset_data = _CMakePresets.generate(conanfile, toolchain_file, generator,\n                                                      cache_variables, preset_prefix, buildenv,\n                                                      runenv, cmake_executable, absolute_paths)\n    _IncludingPresets.generate(conanfile, preset_path, user_presets_path, preset_prefix, preset_data,\n                               absolute_paths)\n\n\nclass _CMakePresets:\n    \"\"\" Conan generated main CMakePresets.json inside the generators_folder\n    \"\"\"\n    @staticmethod\n    def generate(conanfile, toolchain_file, generator, cache_variables, preset_prefix, buildenv,\n                 runenv, cmake_executable, absolute_paths):\n        toolchain_file = os.path.abspath(os.path.join(conanfile.generators_folder, toolchain_file))\n        if not absolute_paths:\n            try:  # Make it relative to the build dir if possible\n                toolchain_file = os.path.relpath(toolchain_file, conanfile.build_folder)\n            except ValueError:\n                pass\n        cache_variables = cache_variables or {}\n        if platform.system() == \"Windows\" and generator == \"MinGW Makefiles\":\n            if \"CMAKE_SH\" not in cache_variables:\n                cache_variables[\"CMAKE_SH\"] = \"CMAKE_SH-NOTFOUND\"\n\n        cmake_make_program = conanfile.conf.get(\"tools.gnu:make_program\",\n                                                default=cache_variables.get(\"CMAKE_MAKE_PROGRAM\"))\n        if cmake_make_program:\n            cmake_make_program = cmake_make_program.replace(\"\\\\\", \"/\")\n            cache_variables[\"CMAKE_MAKE_PROGRAM\"] = cmake_make_program\n\n        if \"CMAKE_POLICY_DEFAULT_CMP0091\" not in cache_variables:\n            cache_variables[\"CMAKE_POLICY_DEFAULT_CMP0091\"] = \"NEW\"\n\n        if \"BUILD_TESTING\" not in cache_variables:\n            if conanfile.conf.get(\"tools.build:skip_test\", check_type=bool):\n                cache_variables[\"BUILD_TESTING\"] = \"OFF\"\n\n        preset_path = os.path.join(conanfile.generators_folder, \"CMakePresets.json\")\n        multiconfig = is_multi_configuration(generator)\n        if os.path.exists(preset_path):\n            data = json.loads(load(preset_path))\n            if \"conan\" not in data.get(\"vendor\", {}):\n                # The file is not ours, we cannot overwrite it\n                raise ConanException(\"Existing CMakePresets.json not generated by Conan cannot be \"\n                                     \"overwritten.\\nUse --output-folder or define a 'layout' to \"\n                                     \"avoid collision with your CMakePresets.json\")\n        if os.path.exists(preset_path) and multiconfig:\n            data = json.loads(load(preset_path))\n            build_preset = _CMakePresets._build_preset_fields(conanfile, multiconfig, preset_prefix)\n            test_preset = _CMakePresets._test_preset_fields(conanfile, multiconfig, preset_prefix,\n                                                            runenv)\n            _CMakePresets._insert_preset(data, \"buildPresets\", build_preset)\n            _CMakePresets._insert_preset(data, \"testPresets\", test_preset)\n            configure_preset = _CMakePresets._configure_preset(conanfile, generator, cache_variables,\n                                                               toolchain_file, multiconfig,\n                                                               preset_prefix, buildenv,\n                                                               cmake_executable)\n            # Conan generated presets should have only 1 configurePreset, no more, overwrite it\n            data[\"configurePresets\"] = [configure_preset]\n        else:\n            data = _CMakePresets._contents(conanfile, toolchain_file, cache_variables, generator,\n                                           preset_prefix, buildenv, runenv, cmake_executable)\n\n        preset_content = json.dumps(data, indent=4)\n        save(preset_path, preset_content)\n        ConanOutput(str(conanfile)).info(f\"CMakeToolchain generated: {preset_path}\")\n        return preset_path, data\n\n    @staticmethod\n    def _insert_preset(data, preset_type, preset):\n        presets = data.setdefault(preset_type, [])\n        preset_name = preset[\"name\"]\n        positions = [index for index, p in enumerate(presets) if p[\"name\"] == preset_name]\n        if positions:\n            data[preset_type][positions[0]] = preset\n        else:\n            data[preset_type].append(preset)\n\n    @staticmethod\n    def _contents(conanfile, toolchain_file, cache_variables, generator, preset_prefix, buildenv,\n                  runenv, cmake_executable):\n        \"\"\"\n        Contents for the CMakePresets.json\n        It uses schema version 3 unless it is forced to 2\n        \"\"\"\n        multiconfig = is_multi_configuration(generator)\n        conf = _CMakePresets._configure_preset(conanfile, generator, cache_variables, toolchain_file,\n                                               multiconfig, preset_prefix, buildenv,\n                                               cmake_executable)\n        build = _CMakePresets._build_preset_fields(conanfile, multiconfig, preset_prefix)\n        test = _CMakePresets._test_preset_fields(conanfile, multiconfig, preset_prefix, runenv)\n        ret = {\"version\": 3,\n               \"vendor\": {\"conan\": {}},\n               \"cmakeMinimumRequired\": {\"major\": 3, \"minor\": 15, \"patch\": 0},\n               \"configurePresets\": [conf],\n               \"buildPresets\": [build],\n               \"testPresets\": [test]\n               }\n        return ret\n\n    @staticmethod\n    def _configure_preset(conanfile, generator, cache_variables, toolchain_file, multiconfig,\n                          preset_prefix, buildenv, cmake_executable):\n        build_type = conanfile.settings.get_safe(\"build_type\")\n        name = _CMakePresets._configure_preset_name(conanfile, multiconfig)\n        if preset_prefix:\n            name = f\"{preset_prefix}-{name}\"\n        if not multiconfig and build_type:\n            cache_variables[\"CMAKE_BUILD_TYPE\"] = build_type\n        ret = {\n            \"name\": name,\n            \"displayName\": \"'{}' config\".format(name),\n            \"description\": \"'{}' configure using '{}' generator\".format(name, generator),\n            \"generator\": generator,\n            \"cacheVariables\": cache_variables,\n        }\n\n        if buildenv:\n            ret[\"environment\"] = buildenv\n\n        if cmake_executable:\n            ret[\"cmakeExecutable\"] = cmake_executable\n\n        if is_msvc(conanfile):\n            # We can force the generator Visual even if it is Ninja, to define the toolset\n            toolset = GenericSystemBlock.get_toolset(\"Visual\", conanfile)\n            # It seems \"external\" strategy is enough, as it is defined by toolchain\n            if toolset:\n                ret[\"toolset\"] = {\n                    \"value\": toolset,\n                    \"strategy\": \"external\"\n                }\n            arch = GenericSystemBlock.get_generator_platform(\"Visual\", conanfile)\n            # https://learn.microsoft.com/en-us/cpp/build/cmake-presets-vs\n            if generator and \"Ninja\" in generator and arch == \"Win32\":\n                arch = \"x86\"  # for command line, it is not Win32, it is x86\n            if arch:\n                ret[\"architecture\"] = {\n                    \"value\": arch,\n                    \"strategy\": \"external\"\n                }\n\n        # Second attempt at https://github.com/conan-io/conan/issues/13136\n        # for cmake-tools to activate environment. Similar to CompilersBlock\n        # Only for cl/clang-cl, other compilers such clang can be breaking (Android)\n        compilers_by_conf = conanfile.conf.get(\"tools.build:compiler_executables\", default={})\n        compiler = conanfile.settings.get_safe(\"compiler\")\n        default_cl = \"cl\" if compiler == \"msvc\" and \"Ninja\" in str(generator) else None\n        for lang in (\"c\", \"cpp\"):\n            comp = compilers_by_conf.get(lang, default_cl)\n            if comp and os.path.basename(comp) in (\"cl\", \"cl.exe\", \"clang-cl\", \"clang-cl.exe\"):\n                lang = {\"c\": \"C\", \"cpp\": \"CXX\"}[lang]\n                ret[\"cacheVariables\"][f\"CMAKE_{lang}_COMPILER\"] = comp.replace(\"\\\\\", \"/\")\n\n        ret[\"toolchainFile\"] = toolchain_file\n        if conanfile.build_folder:\n            # If we are installing a ref: \"conan install <ref>\", we don't have build_folder, because\n            # we don't even have a conanfile with a `layout()` to determine the build folder.\n            # If we install a local conanfile \"conan install .\" with a layout(), it will be available\n            ret[\"binaryDir\"] = conanfile.build_folder\n\n        def _format_val(val):\n            return f'\"{val}\"' if type(val) is str and \" \" in val else f\"{val}\"\n\n        try:\n            is_consumer = conanfile._conan_node.recipe == RECIPE_CONSUMER and \\\n                          conanfile.tested_reference_str is None\n        except:\n            is_consumer = False\n        if is_consumer:\n            # https://github.com/conan-io/conan/pull/12034#issuecomment-1253776285\n            vars_tip = \" \".join([f\"-D{k}={_format_val(v)}\" for k, v in cache_variables.items()])\n            tc_tip = f\"-DCMAKE_TOOLCHAIN_FILE=<output_folder>/{toolchain_file} \" \\\n                if \"CMAKE_TOOLCHAIN_FILE\" not in vars_tip else \"\"\n\n            msg = textwrap.dedent(f\"\"\"\\\n                CMakeToolchain: Preset '{name}' added to CMakePresets.json.\n                    (cmake>=3.23) cmake --preset {name}\n                    (cmake<3.23) cmake <path> -G {_format_val(generator)} {tc_tip} {vars_tip}\"\"\")\n            conanfile.output.info(msg, fg=Color.CYAN)\n        return ret\n\n    @staticmethod\n    def _common_preset_fields(conanfile, multiconfig, preset_prefix):\n        build_type = conanfile.settings.get_safe(\"build_type\")\n        configure_preset_name = _CMakePresets._configure_preset_name(conanfile, multiconfig)\n        build_preset_name = _CMakePresets._build_and_test_preset_name(conanfile)\n        if preset_prefix:\n            configure_preset_name = f\"{preset_prefix}-{configure_preset_name}\"\n            build_preset_name = f\"{preset_prefix}-{build_preset_name}\"\n        ret = {\"name\": build_preset_name, \"configurePreset\": configure_preset_name}\n        if multiconfig:\n            ret[\"configuration\"] = build_type\n        return ret\n\n    @staticmethod\n    def _build_preset_fields(conanfile, multiconfig, preset_prefix):\n        ret = _CMakePresets._common_preset_fields(conanfile, multiconfig, preset_prefix)\n        build_preset_jobs = build_jobs(conanfile)\n        if build_preset_jobs:\n            ret[\"jobs\"] = build_preset_jobs\n        return ret\n\n    @staticmethod\n    def _test_preset_fields(conanfile, multiconfig, preset_prefix, runenv):\n        ret = _CMakePresets._common_preset_fields(conanfile, multiconfig, preset_prefix)\n        build_preset_jobs = build_jobs(conanfile)\n        if build_preset_jobs:\n            ret.setdefault(\"execution\", {})[\"jobs\"] = build_preset_jobs\n        if runenv:\n            ret[\"environment\"] = runenv\n        return ret\n\n    @staticmethod\n    def _build_and_test_preset_name(conanfile):\n        build_type = conanfile.settings.get_safe(\"build_type\")\n        custom_conf, user_defined_build = get_build_folder_custom_vars(conanfile)\n        if user_defined_build:\n            return custom_conf\n\n        if custom_conf:\n            if build_type:\n                return \"{}-{}\".format(custom_conf, build_type.lower())\n            else:\n                return custom_conf\n        return build_type.lower() if build_type else \"default\"\n\n    @staticmethod\n    def _configure_preset_name(conanfile, multiconfig):\n        build_type = conanfile.settings.get_safe(\"build_type\")\n        custom_conf, user_defined_build = get_build_folder_custom_vars(conanfile)\n\n        if user_defined_build:\n            return custom_conf\n\n        if multiconfig or not build_type:\n            return \"default\" if not custom_conf else custom_conf\n\n        if custom_conf:\n            return \"{}-{}\".format(custom_conf, str(build_type).lower())\n        else:\n            return str(build_type).lower()\n\n\nclass _IncludingPresets:\n    \"\"\"\n    CMakeUserPresets or ConanPresets.json that include the main generated CMakePresets\n    \"\"\"\n\n    @staticmethod\n    def generate(conanfile, preset_path, user_presets_path, preset_prefix, preset_data,\n                 absolute_paths):\n        if not user_presets_path:\n            return\n\n        # If generators folder is the same as source folder, do not create the user presets\n        # we already have the CMakePresets.json right there\n        if not (conanfile.source_folder and conanfile.source_folder != conanfile.generators_folder):\n            return\n\n        is_default = user_presets_path == \"CMakeUserPresets.json\"\n        user_presets_path = os.path.join(conanfile.source_folder, user_presets_path)\n        if os.path.isdir(user_presets_path):  # Allows user to specify only the folder\n            output_dir = user_presets_path\n            user_presets_path = os.path.join(user_presets_path, \"CMakeUserPresets.json\")\n        else:\n            output_dir = os.path.dirname(user_presets_path)\n\n        if is_default and not os.path.exists(os.path.join(output_dir, \"CMakeLists.txt\")):\n            return\n\n        # It uses schema version 4 unless it is forced to 2\n        inherited_user = {}\n        if os.path.basename(user_presets_path) != \"CMakeUserPresets.json\":\n            inherited_user = _IncludingPresets._collect_user_inherits(output_dir, preset_prefix)\n\n        if not os.path.exists(user_presets_path):\n            data = {\"version\": 4,\n                    \"vendor\": {\"conan\": dict()}}\n        else:\n            data = json.loads(load(user_presets_path))\n            if \"conan\" not in data.get(\"vendor\", {}):\n                # The file is not ours, we cannot overwrite it\n                return\n\n        if not absolute_paths:\n            try:  # Make it relative to the CMakeUserPresets.json if possible\n                preset_path = os.path.relpath(preset_path, output_dir)\n                # If we don't normalize, path will be removed in Linux shared folders\n                # https://github.com/conan-io/conan/issues/18434\n                preset_path = preset_path.replace(\"\\\\\", \"/\")\n            except ValueError:\n                pass\n        data = _IncludingPresets._append_user_preset_path(data, preset_path, output_dir)\n\n        if inherited_user:\n            data = _IncludingPresets._update_stubs(data, inherited_user, output_dir, absolute_paths)\n\n        data = json.dumps(data, indent=4)\n        ConanOutput(str(conanfile)).info(f\"CMakeToolchain generated: {user_presets_path}\")\n        save(user_presets_path, data)\n\n    @staticmethod\n    def _update_stubs(data, inherited_user, output_dir, absolute_paths):\n        \"\"\"\n        Set configurePresets/buildPresets/testPresets to stubs for conan-* presets\n        that the user inherits but that don't have a real preset of the same type in the includes.\n        \"\"\"\n        real_preset_names_by_type = {\n            \"configurePresets\": set(),\n            \"buildPresets\": set(),\n            \"testPresets\": set(),\n        }\n        for inc in data.get(\"include\", []):\n            inc_path = os.path.join(output_dir, inc) if not absolute_paths else inc\n            assert os.path.exists(inc_path), f\"Presets include must point to an existing file: '{inc_path}'\"\n            try:\n                inc_json = json.loads(load(inc_path))\n            except Exception:\n                continue\n            for preset_type in (\"configurePresets\", \"buildPresets\", \"testPresets\"):\n                for p in inc_json.get(preset_type, []):\n                    name = p.get(\"name\")\n                    if name:\n                        real_preset_names_by_type[preset_type].add(name)\n\n        for preset_type in (\"configurePresets\", \"buildPresets\", \"testPresets\"):\n            real_names = real_preset_names_by_type[preset_type]\n            stubs = []\n            for name in inherited_user.get(preset_type, []):\n                if name not in real_names:\n                    stub = {\"name\": name}\n                    if preset_type in (\"buildPresets\", \"testPresets\"):\n                        stub[\"configurePreset\"] = name\n                    stubs.append(stub)\n            data[preset_type] = stubs\n\n        return data\n\n    @staticmethod\n    def _collect_user_inherits(output_dir, preset_prefix):\n        # Collect all the existing targets in the user files, to create empty conan- presets\n        # so things doesn't break for multi-platform, when inherits don't exist\n        collected_targets = {}\n        types = \"configurePresets\", \"buildPresets\", \"testPresets\"\n        for file in (\"CMakePresets.json\", \"CMakeUserPresets.json\"):\n            user_file = os.path.join(output_dir, file)\n            if os.path.exists(user_file):\n                user_json = json.loads(load(user_file))\n                for preset_type in types:\n                    for preset in user_json.get(preset_type, []):\n                        inherits = preset.get(\"inherits\", [])\n                        if isinstance(inherits, str):\n                            inherits = [inherits]\n                        inherits = [i for i in inherits if i.startswith(preset_prefix)]\n                        if inherits:\n                            existing = collected_targets.setdefault(preset_type, [])\n                            for i in inherits:\n                                if i not in existing:\n                                    existing.append(i)\n\n        return collected_targets\n\n    @staticmethod\n    def _append_user_preset_path(data, preset_path, output_dir):\n        \"\"\" - Appends a 'include' to preset_path if the schema supports it.\n            - Otherwise it merges to \"data\" all the configurePresets, buildPresets etc from the\n              read preset_path.\n        \"\"\"\n        if \"include\" not in data:\n            data[\"include\"] = []\n        # Clear the folders that have been deleted\n        data[\"include\"] = [i for i in data.get(\"include\", [])\n                           if os.path.exists(os.path.join(output_dir, i))]\n        if preset_path not in data[\"include\"]:\n            data[\"include\"].append(preset_path)\n        return data\n\n\ndef load_cmake_presets(folder):\n    try:\n        tmp = load(os.path.join(folder, \"CMakePresets.json\"))\n    except FileNotFoundError:\n        # Issue: https://github.com/conan-io/conan/issues/12896\n        raise ConanException(f\"CMakePresets.json was not found in {folder} folder. Check that you \"\n                             f\"are using CMakeToolchain as generator to ensure its correct \"\n                             f\"initialization.\")\n    return json.loads(tmp)\n"
  },
  {
    "path": "conan/tools/cmake/toolchain/__init__.py",
    "content": "CONAN_TOOLCHAIN_FILENAME = \"conan_toolchain.cmake\"\n\n"
  },
  {
    "path": "conan/tools/cmake/toolchain/blocks.py",
    "content": "import os\nimport re\nimport textwrap\nfrom collections import OrderedDict\n\nfrom jinja2 import Template\n\nfrom conan.internal.internal_tools import universal_arch_separator, is_universal_arch\nfrom conan.tools.apple.apple import get_apple_sdk_fullname, _to_apple_arch\nfrom conan.tools.android.utils import android_abi\nfrom conan.tools.apple.apple import is_apple_os, to_apple_arch\nfrom conan.tools.build import build_jobs\nfrom conan.tools.build.flags import architecture_flag, architecture_link_flag, libcxx_flags, threads_flags\nfrom conan.tools.build.cross_building import cross_building\nfrom conan.tools.cmake.toolchain import CONAN_TOOLCHAIN_FILENAME\nfrom conan.tools.cmake.utils import is_multi_configuration, cmake_escape_value\nfrom conan.tools.intel import IntelCC\nfrom conan.tools.microsoft.visual import msvc_version_to_toolset_version, msvc_platform_from_arch\nfrom conan.internal.api.install.generators import relativize_path\nfrom conan.internal.subsystems import deduce_subsystem, WINDOWS\nfrom conan.errors import ConanException\nfrom conan.internal.model.version import Version\nfrom conan.internal.util.files import load\n\n\nclass Block:\n    def __init__(self, conanfile, toolchain, name):\n        self._conanfile = conanfile\n        self._toolchain = toolchain\n        self._context_values = None\n        self._name = name\n\n    @property\n    def values(self):\n        if self._context_values is None:\n            self._context_values = self.context()\n        return self._context_values\n\n    @values.setter\n    def values(self, context_values):\n        self._context_values = context_values\n\n    def get_rendered_content(self):\n        context = self.values\n        if context is None:\n            return\n\n        template = f\"########## '{self._name}' block #############\\n\" + self.template + \"\\n\\n\"\n        template = Template(template, trim_blocks=True, lstrip_blocks=True)\n        return template.render(**context)\n\n    def context(self):\n        return {}\n\n    @property\n    def template(self):\n        raise NotImplementedError()\n\n\nclass VSRuntimeBlock(Block):\n    template = textwrap.dedent(\"\"\"\\\n        # Definition of VS runtime CMAKE_MSVC_RUNTIME_LIBRARY, from settings build_type,\n        # compiler.runtime, compiler.runtime_type\n\n        {% set genexpr = namespace(str='') %}\n        {% for config, value in vs_runtimes.items() %}\n            {% set genexpr.str = genexpr.str +\n                                  '$<$<CONFIG:' + config + '>:' + value|string + '>' %}\n        {% endfor %}\n        cmake_policy(GET CMP0091 POLICY_CMP0091)\n        if(NOT \"${POLICY_CMP0091}\" STREQUAL NEW)\n            message(FATAL_ERROR \"The CMake policy CMP0091 must be NEW, but is '${POLICY_CMP0091}'\")\n        endif()\n        message(STATUS \"Conan toolchain: Setting CMAKE_MSVC_RUNTIME_LIBRARY={{ genexpr.str  }}\")\n        set(CMAKE_MSVC_RUNTIME_LIBRARY \"{{ genexpr.str }}\")\n        \"\"\")\n\n    def context(self):\n        # Parsing existing toolchain file to get existing configured runtimes\n        settings = self._conanfile.settings\n        if settings.get_safe(\"os\") != \"Windows\":\n            return\n\n        compiler = settings.get_safe(\"compiler\")\n        if compiler not in (\"msvc\", \"clang\", \"intel-cc\"):\n            return\n\n        runtime = settings.get_safe(\"compiler.runtime\")\n        if runtime is None:\n            return\n\n        config_dict = {}\n        if os.path.exists(CONAN_TOOLCHAIN_FILENAME):\n            existing_include = load(CONAN_TOOLCHAIN_FILENAME)\n            msvc_runtime_value = re.search(r\"set\\(CMAKE_MSVC_RUNTIME_LIBRARY \\\"([^)]*)\\\"\\)\",\n                                           existing_include)\n            if msvc_runtime_value:\n                capture = msvc_runtime_value.group(1)\n                matches = re.findall(r\"\\$<\\$<CONFIG:([A-Za-z]*)>:([A-Za-z]*)>\", capture)\n                config_dict = dict(matches)\n\n        build_type = settings.get_safe(\"build_type\")  # FIXME: change for configuration\n        if build_type is None:\n            return None\n\n        if compiler == \"msvc\" or compiler == \"intel-cc\" or compiler == \"clang\":\n            runtime_type = settings.get_safe(\"compiler.runtime_type\")\n            rt = \"MultiThreadedDebug\" if runtime_type == \"Debug\" else \"MultiThreaded\"\n            if runtime != \"static\":\n                rt += \"DLL\"\n            config_dict[build_type] = rt\n\n            # If clang is being used the CMake check of compiler will try to create a simple\n            # test application, and will fail because the Debug runtime is not there\n            if compiler == \"clang\":\n                if config_dict.get(\"Debug\") is None:\n                    clang_rt = \"MultiThreadedDebug\" + (\"DLL\" if runtime != \"static\" else \"\")\n                    config_dict[\"Debug\"] = clang_rt\n\n        return {\"vs_runtimes\": config_dict}\n\n\nclass VSDebuggerEnvironment(Block):\n    template = textwrap.dedent(\"\"\"\\\n        # Definition of CMAKE_VS_DEBUGGER_ENVIRONMENT from \"bindirs\" folders of dependencies\n        # for execution of applications with shared libraries within the VS IDE\n\n        {% if vs_debugger_path %}\n        # if the file exists it will be loaded by FindFiles block and the variable defined there\n        if(NOT EXISTS \"${CMAKE_CURRENT_LIST_DIR}/conan_cmakedeps_paths.cmake\")\n        # This variable requires CMake>=3.27 to work\n        set(CMAKE_VS_DEBUGGER_ENVIRONMENT \"{{ vs_debugger_path }}\")\n        endif()\n        {% endif %}\n        \"\"\")\n\n    def context(self):\n        os_ = self._conanfile.settings.get_safe(\"os\")\n        build_type = self._conanfile.settings.get_safe(\"build_type\")\n\n        if (os_ and \"Windows\" not in os_) or not build_type:\n            return None\n\n        if \"Visual\" not in self._toolchain.generator:\n            return None\n\n        config_dict = {}\n        if os.path.exists(CONAN_TOOLCHAIN_FILENAME):\n            existing_include = load(CONAN_TOOLCHAIN_FILENAME)\n            pattern = r\"set\\(CMAKE_VS_DEBUGGER_ENVIRONMENT \\\"PATH=([^)]*);%PATH%\\\"\\)\"\n            vs_debugger_environment = re.search(pattern, existing_include)\n            if vs_debugger_environment:\n                capture = vs_debugger_environment.group(1)\n                matches = re.findall(r\"\\$<\\$<CONFIG:([A-Za-z]*)>:([^>]*)>\", capture)\n                config_dict = dict(matches)\n\n        host_deps = self._conanfile.dependencies.host.values()\n        test_deps = self._conanfile.dependencies.test.values()\n        bin_dirs = [p for dep in host_deps for p in dep.cpp_info.aggregated_components().bindirs]\n        test_bindirs = [p for dep in test_deps for p in dep.cpp_info.aggregated_components().bindirs]\n        bin_dirs.extend(test_bindirs)\n        bin_dirs = [relativize_path(p, self._conanfile, \"${CMAKE_CURRENT_LIST_DIR}\")\n                    for p in bin_dirs]\n        bin_dirs = [p.replace(\"\\\\\", \"/\") for p in bin_dirs]\n        bin_dirs = \";\".join(bin_dirs) if bin_dirs else None\n        if bin_dirs:\n            config_dict[build_type] = bin_dirs\n\n        if not config_dict:\n            return None\n\n        vs_debugger_path = \"\"\n        for config, value in config_dict.items():\n            vs_debugger_path += f\"$<$<CONFIG:{config}>:{value}>\"\n        vs_debugger_path = f\"PATH={vs_debugger_path};%PATH%\"\n        return {\"vs_debugger_path\": vs_debugger_path}\n\n\nclass FPicBlock(Block):\n    template = textwrap.dedent(\"\"\"\\\n        # Defining CMAKE_POSITION_INDEPENDENT_CODE for static libraries when necessary\n\n        {% if fpic %}\n        message(STATUS \"Conan toolchain: Setting CMAKE_POSITION_INDEPENDENT_CODE={{ fpic }} (options.fPIC)\")\n        set(CMAKE_POSITION_INDEPENDENT_CODE {{ fpic }} CACHE BOOL \"Position independent code\")\n        {% endif %}\n        \"\"\")\n\n    def context(self):\n        fpic = self._conanfile.options.get_safe(\"fPIC\")\n        if fpic is None:\n            return None\n        os_ = self._conanfile.settings.get_safe(\"os\")\n        if os_ and \"Windows\" in os_:\n            self._conanfile.output.warning(\"Toolchain: Ignoring fPIC option defined for Windows\")\n            return None\n        return {\"fpic\": \"ON\" if fpic else \"OFF\"}\n\n\nclass GLibCXXBlock(Block):\n    template = textwrap.dedent(\"\"\"\\\n        # Definition of libcxx from 'compiler.libcxx' setting, defining the\n        # right CXX_FLAGS for that libcxx\n\n        {% if set_libcxx %}\n        message(STATUS \"Conan toolchain: Defining libcxx as C++ flags: {{ set_libcxx }}\")\n        string(APPEND CONAN_CXX_FLAGS \" {{ set_libcxx }}\")\n        {% endif %}\n        {% if glibcxx %}\n        message(STATUS \"Conan toolchain: Adding glibcxx compile definition: {{ glibcxx }}\")\n        add_compile_definitions({{ glibcxx }})\n        {% endif %}\n        \"\"\")\n\n    def context(self):\n        libcxx, stdlib11 = libcxx_flags(self._conanfile)\n        return {\"set_libcxx\": libcxx, \"glibcxx\": stdlib11}\n\n\nclass SkipRPath(Block):\n    template = textwrap.dedent(\"\"\"\\\n        # Defining CMAKE_SKIP_RPATH\n\n        {% if skip_rpath %}\n        set(CMAKE_SKIP_RPATH 1 CACHE BOOL \"rpaths\" FORCE)\n        # Policy CMP0068\n        # We want the old behavior, in CMake >= 3.9 CMAKE_SKIP_RPATH won't affect install_name in OSX\n        set(CMAKE_INSTALL_NAME_DIR \"\")\n        {% endif %}\n        \"\"\")\n\n    skip_rpath = False\n\n    def context(self):\n        return {\"skip_rpath\": self.skip_rpath}\n\n\nclass ArchitectureBlock(Block):\n    template = textwrap.dedent(\"\"\"\\\n        {% if arch_flag %}\n        # Define C++ flags, C flags and linker flags from 'settings.arch'\n        message(STATUS \"Conan toolchain: Defining architecture flag: {{ arch_flag }}\")\n        string(APPEND CONAN_CXX_FLAGS \" {{ arch_flag }}\")\n        string(APPEND CONAN_C_FLAGS \" {{ arch_flag }}\")\n        string(APPEND CONAN_SHARED_LINKER_FLAGS \" {{ arch_flag }}\")\n        string(APPEND CONAN_EXE_LINKER_FLAGS \" {{ arch_flag }}\")\n        {% endif %}\n        {% if arch_link_flag %}\n        message(STATUS \"Conan toolchain: Defining architecture linker flag: {{ arch_link_flag }}\")\n        string(APPEND CONAN_SHARED_LINKER_FLAGS \" {{ arch_link_flag }}\")\n        string(APPEND CONAN_EXE_LINKER_FLAGS \" {{ arch_link_flag }}\")\n        {% endif %}\n        {% if thread_flags_list %}\n        # Define C++ flags, C flags and linker flags from 'compiler.threads'\n        message(STATUS \"Conan toolchain: Defining thread flags: {{ thread_flags_list }}\")\n        string(APPEND CONAN_CXX_FLAGS \" {{ thread_flags_list }}\")\n        string(APPEND CONAN_C_FLAGS \" {{ thread_flags_list }}\")\n        string(APPEND CONAN_SHARED_LINKER_FLAGS \" {{ thread_flags_list }}\")\n        string(APPEND CONAN_EXE_LINKER_FLAGS \" {{ thread_flags_list }}\")\n        {% endif %}\n        \"\"\")\n\n    def context(self):\n        arch_flag = architecture_flag(self._conanfile)\n        arch_link_flag = architecture_link_flag(self._conanfile)\n        thread_flags_list = \" \".join(threads_flags(self._conanfile))\n        if not arch_flag and not arch_link_flag and not thread_flags_list:\n            return\n        return {\"arch_flag\": arch_flag, \"arch_link_flag\": arch_link_flag,\n                \"thread_flags_list\": thread_flags_list}\n\nclass RpathLinkFlagsBlock(Block):\n    template = textwrap.dedent(\"\"\"\\\n        # Pass -rpath-link pointing to all directories with runtime libraries\n        {% if rpath_link_flags %}\n        string(APPEND CONAN_EXE_LINKER_FLAGS \" {{ rpath_link_flags }}\")\n        string(APPEND CONAN_SHARED_LINKER_FLAGS \" {{ rpath_link_flags }}\")\n        {% endif %}\n        \"\"\")\n\n    def context(self):\n        add_rpath_link = self._toolchain.add_rpath_link or self._conanfile.conf.get(\"tools.build:add_rpath_link\", check_type=bool)\n        if add_rpath_link:\n            runtime_dirs = []\n            host_req = self._conanfile.dependencies.filter({\"build\": False}).values()\n            for req in host_req:\n                cppinfo = req.cpp_info.aggregated_components()\n                runtime_dirs.extend(cppinfo.libdirs)\n\n            # surround each dir with escaped quotes, to avoid problems with spaces in paths\n            rpath_link_flags = \" \".join([f'-Wl,-rpath-link=\\\\\"{d}\\\\\"' for d in runtime_dirs]) if runtime_dirs else None\n        else:\n            rpath_link_flags = None\n        return {\"rpath_link_flags\": rpath_link_flags}\n\nclass LinkerScriptsBlock(Block):\n    template = textwrap.dedent(\"\"\"\\\n        # Add linker flags from tools.build:linker_scripts conf\n\n        message(STATUS \"Conan toolchain: Defining linker script flag: {{ linker_script_flags }}\")\n        string(APPEND CONAN_EXE_LINKER_FLAGS \" {{ linker_script_flags }}\")\n        \"\"\")\n\n    def context(self):\n        linker_scripts = self._conanfile.conf.get(\n            \"tools.build:linker_scripts\", check_type=list, default=[])\n        if not linker_scripts:\n            return\n        linker_scripts = [linker_script.replace('\\\\', '/') for linker_script in linker_scripts]\n        linker_scripts = [relativize_path(p, self._conanfile, \"${CMAKE_CURRENT_LIST_DIR}\")\n                          for p in linker_scripts]\n        linker_script_flags = [r'-T\\\"' + linker_script + r'\\\"' for linker_script in linker_scripts]\n        return {\"linker_script_flags\": \" \".join(linker_script_flags)}\n\n\nclass CppStdBlock(Block):\n    template = textwrap.dedent(\"\"\"\\\n        # Define the C++ and C standards from 'compiler.cppstd' and 'compiler.cstd'\n\n        function(conan_modify_std_watch variable access value current_list_file stack)\n            set(conan_watched_std_variable \"{{ cppstd }}\")\n            if (${variable} STREQUAL \"CMAKE_C_STANDARD\")\n                set(conan_watched_std_variable \"{{ cstd }}\")\n            endif()\n            if (\"${access}\" STREQUAL \"MODIFIED_ACCESS\" AND NOT \"${value}\" STREQUAL \"${conan_watched_std_variable}\")\n                message(STATUS \"Warning: Standard ${variable} value defined in conan_toolchain.cmake to ${conan_watched_std_variable} has been modified to ${value} by ${current_list_file}\")\n            endif()\n            unset(conan_watched_std_variable)\n        endfunction()\n\n        {% if cppstd %}\n        message(STATUS \"Conan toolchain: C++ Standard {{ cppstd }} with extensions {{ cppstd_extensions }}\")\n        set(CMAKE_CXX_STANDARD {{ cppstd }})\n        set(CMAKE_CXX_EXTENSIONS {{ cppstd_extensions }})\n        set(CMAKE_CXX_STANDARD_REQUIRED ON)\n        variable_watch(CMAKE_CXX_STANDARD conan_modify_std_watch)\n        {% endif %}\n        {% if cstd %}\n        message(STATUS \"Conan toolchain: C Standard {{ cstd }} with extensions {{ cstd_extensions }}\")\n        set(CMAKE_C_STANDARD {{ cstd }})\n        set(CMAKE_C_EXTENSIONS {{ cstd_extensions }})\n        set(CMAKE_C_STANDARD_REQUIRED ON)\n        variable_watch(CMAKE_C_STANDARD conan_modify_std_watch)\n        {% endif %}\n        \"\"\")\n\n    def context(self):\n        compiler_cppstd = self._conanfile.settings.get_safe(\"compiler.cppstd\")\n        compiler_cstd = self._conanfile.settings.get_safe(\"compiler.cstd\")\n        result = {}\n        if compiler_cppstd is not None:\n            if compiler_cppstd.startswith(\"gnu\"):\n                result[\"cppstd\"] = compiler_cppstd[3:]\n                result[\"cppstd_extensions\"] = \"ON\"\n            else:\n                result[\"cppstd\"] = compiler_cppstd\n                result[\"cppstd_extensions\"] = \"OFF\"\n        if compiler_cstd is not None:\n            if compiler_cstd.startswith(\"gnu\"):\n                result[\"cstd\"] = compiler_cstd[3:]\n                result[\"cstd_extensions\"] = \"ON\"\n            else:\n                result[\"cstd\"] = compiler_cstd\n                result[\"cstd_extensions\"] = \"OFF\"\n        return result or None\n\n\nclass SharedLibBock(Block):\n    template = textwrap.dedent(\"\"\"\\\n        # Define BUILD_SHARED_LIBS for shared libraries\n\n        message(STATUS \"Conan toolchain: Setting BUILD_SHARED_LIBS = {{ shared_libs }}\")\n        set(BUILD_SHARED_LIBS {{ shared_libs }} CACHE BOOL \"Build shared libraries\")\n        \"\"\")\n\n    def context(self):\n        try:\n            shared_libs = \"ON\" if self._conanfile.options.shared else \"OFF\"\n            return {\"shared_libs\": shared_libs}\n        except ConanException:\n            return None\n\n\nclass ParallelBlock(Block):\n    template = textwrap.dedent(\"\"\"\\\n        # Define VS paralell build /MP flags\n\n        string(APPEND CONAN_CXX_FLAGS \" /MP{{ parallel }}\")\n        string(APPEND CONAN_C_FLAGS \" /MP{{ parallel }}\")\n        \"\"\")\n\n    def context(self):\n        # TODO: Check this conf\n\n        compiler = self._conanfile.settings.get_safe(\"compiler\")\n        if compiler != \"msvc\" or \"Visual\" not in self._toolchain.generator:\n            return\n\n        jobs = build_jobs(self._conanfile)\n        if jobs:\n            return {\"parallel\": jobs}\n\n\nclass AndroidSystemBlock(Block):\n\n    template = textwrap.dedent(\"\"\"\\\n        # Define Android variables ANDROID_PLATFORM, ANDROID_STL, ANDROID_ABI, etc\n        # and include(.../android.toolchain.cmake) from NDK toolchain file\n\n        # New Android toolchain definitions\n        message(STATUS \"Conan toolchain: Setting Android platform: {{ android_platform }}\")\n        set(ANDROID_PLATFORM {{ android_platform }})\n        {% if android_stl %}\n        message(STATUS \"Conan toolchain: Setting Android stl: {{ android_stl }}\")\n        set(ANDROID_STL {{ android_stl }})\n        {% endif %}\n        message(STATUS \"Conan toolchain: Setting Android abi: {{ android_abi }}\")\n        set(ANDROID_ABI {{ android_abi }})\n        {% if android_use_legacy_toolchain_file %}\n        set(ANDROID_USE_LEGACY_TOOLCHAIN_FILE {{ android_use_legacy_toolchain_file }})\n        {% endif %}\n        include(\"{{ android_ndk_path }}/build/cmake/android.toolchain.cmake\")\n        \"\"\")\n\n    def context(self):\n        os_ = self._conanfile.settings.get_safe(\"os\")\n        if os_ != \"Android\":\n            return\n\n        # TODO: only 'c++_shared' y 'c++_static' supported?\n        #  https://developer.android.com/ndk/guides/cpp-support\n        libcxx_str = self._conanfile.settings.get_safe(\"compiler.libcxx\")\n\n        android_ndk_path = self._conanfile.conf.get(\"tools.android:ndk_path\")\n        if not android_ndk_path:\n            raise ConanException('CMakeToolchain needs tools.android:ndk_path configuration defined')\n        android_ndk_path = android_ndk_path.replace(\"\\\\\", \"/\")\n        android_ndk_path = relativize_path(android_ndk_path, self._conanfile,\n                                           \"${CMAKE_CURRENT_LIST_DIR}\")\n\n        use_cmake_legacy_toolchain = self._conanfile.conf.get(\"tools.android:cmake_legacy_toolchain\",\n                                                              check_type=bool)\n        if use_cmake_legacy_toolchain is not None:\n            use_cmake_legacy_toolchain = \"ON\" if use_cmake_legacy_toolchain else \"OFF\"\n\n        ctxt_toolchain = {\n            'android_platform': 'android-' + str(self._conanfile.settings.os.api_level),\n            'android_abi': android_abi(self._conanfile),\n            'android_stl': libcxx_str,\n            'android_ndk_path': android_ndk_path,\n            'android_use_legacy_toolchain_file': use_cmake_legacy_toolchain,\n        }\n        return ctxt_toolchain\n\n\nclass AppleSystemBlock(Block):\n    template = textwrap.dedent(\"\"\"\\\n        # Define Apple architectures, sysroot, deployment target, bitcode, etc\n\n        # Set the architectures for which to build.\n        set(CMAKE_OSX_ARCHITECTURES {{ cmake_osx_architectures }} CACHE STRING \"\" FORCE)\n        # Setting CMAKE_OSX_SYSROOT SDK, when using Xcode generator the name is enough\n        # but full path is necessary for others\n        set(CMAKE_OSX_SYSROOT {{ cmake_osx_sysroot }} CACHE STRING \"\" FORCE)\n        {% if cmake_osx_deployment_target is defined %}\n        # Setting CMAKE_OSX_DEPLOYMENT_TARGET if \"os.version\" is defined by the used conan profile\n        set(CMAKE_OSX_DEPLOYMENT_TARGET \"{{ cmake_osx_deployment_target }}\" CACHE STRING \"\")\n        {% endif %}\n        set(BITCODE \"\")\n        set(FOBJC_ARC \"\")\n        set(VISIBILITY \"\")\n        {% if enable_bitcode %}\n        # Bitcode ON\n        set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE \"YES\")\n        set(CMAKE_XCODE_ATTRIBUTE_BITCODE_GENERATION_MODE \"bitcode\")\n        {% if enable_bitcode_marker %}\n        set(BITCODE \"-fembed-bitcode-marker\")\n        {% else %}\n        set(BITCODE \"-fembed-bitcode\")\n        {% endif %}\n        {% elif enable_bitcode is not none %}\n        # Bitcode OFF\n        set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE \"NO\")\n        {% endif %}\n        {% if enable_arc %}\n        # ARC ON\n        set(FOBJC_ARC \"-fobjc-arc\")\n        set(CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC \"YES\")\n        {% elif enable_arc is not none %}\n        # ARC OFF\n        set(FOBJC_ARC \"-fno-objc-arc\")\n        set(CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC \"NO\")\n        {% endif %}\n        {% if enable_visibility %}\n        # Visibility ON\n        set(CMAKE_XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN \"NO\")\n        set(VISIBILITY \"-fvisibility=default\")\n        {% elif enable_visibility is not none %}\n        # Visibility OFF\n        set(VISIBILITY \"-fvisibility=hidden -fvisibility-inlines-hidden\")\n        set(CMAKE_XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN \"YES\")\n        {% endif %}\n        #Check if Xcode generator is used, since that will handle these flags automagically\n        if(CMAKE_GENERATOR MATCHES \"Xcode\")\n          message(DEBUG \"Not setting any manual command-line buildflags, since Xcode is selected as generator.\")\n        else()\n            string(APPEND CONAN_C_FLAGS \" ${BITCODE} ${VISIBILITY}\")\n            string(APPEND CONAN_CXX_FLAGS \" ${BITCODE} ${VISIBILITY}\")\n            # Objective-C/C++ specific flags\n            string(APPEND CONAN_OBJC_FLAGS \" ${BITCODE} ${VISIBILITY} ${FOBJC_ARC}\")\n            string(APPEND CONAN_OBJCXX_FLAGS \" ${BITCODE} ${VISIBILITY} ${FOBJC_ARC}\")\n        endif()\n        \"\"\")\n\n    def context(self):\n        if not is_apple_os(self._conanfile):\n            return None\n\n        def to_apple_archs(conanfile):\n            f\"\"\"converts conan-style architectures into Apple-style archs\n            to be used by CMake also supports multiple architectures\n            separated by '{universal_arch_separator}'\"\"\"\n            arch_ = conanfile.settings.get_safe(\"arch\") if conanfile else None\n            if arch_ is not None:\n                return \";\".join([_to_apple_arch(arch, default=arch) for arch in\n                                 arch_.split(universal_arch_separator)])\n\n        # check valid combinations of architecture - os ?\n        # for iOS a FAT library valid for simulator and device can be generated\n        # if multiple archs are specified \"-DCMAKE_OSX_ARCHITECTURES=armv7;armv7s;arm64;i386;x86_64\"\n        host_architecture = to_apple_archs(self._conanfile)\n\n        host_os_version = self._conanfile.settings.get_safe(\"os.version\")\n        host_sdk_name = self._conanfile.conf.get(\"tools.apple:sdk_path\") or get_apple_sdk_fullname(self._conanfile)\n        is_debug = self._conanfile.settings.get_safe('build_type') == \"Debug\"\n\n        # Reading some configurations to enable or disable some Xcode toolchain flags and variables\n        # Issue related: https://github.com/conan-io/conan/issues/9448\n        # Based on https://github.com/leetal/ios-cmake repository\n        enable_bitcode = self._conanfile.conf.get(\"tools.apple:enable_bitcode\", check_type=bool)\n        enable_arc = self._conanfile.conf.get(\"tools.apple:enable_arc\", check_type=bool)\n        enable_visibility = self._conanfile.conf.get(\"tools.apple:enable_visibility\", check_type=bool)\n\n        ctxt_toolchain = {\n            \"enable_bitcode\": enable_bitcode,\n            \"enable_bitcode_marker\": all([enable_bitcode, is_debug]),\n            \"enable_arc\": enable_arc,\n            \"enable_visibility\": enable_visibility\n        }\n        if host_sdk_name:\n            host_sdk_name = relativize_path(host_sdk_name, self._conanfile,\n                                            \"${CMAKE_CURRENT_LIST_DIR}\")\n            ctxt_toolchain[\"cmake_osx_sysroot\"] = host_sdk_name\n        # this is used to initialize the OSX_ARCHITECTURES property on each target as it is created\n        if host_architecture:\n            ctxt_toolchain[\"cmake_osx_architectures\"] = host_architecture\n\n        if host_os_version:\n            # https://cmake.org/cmake/help/latest/variable/CMAKE_OSX_DEPLOYMENT_TARGET.html\n            # Despite the OSX part in the variable name(s) they apply also to other SDKs than\n            # macOS like iOS, tvOS, watchOS or visionOS.\n            ctxt_toolchain[\"cmake_osx_deployment_target\"] = host_os_version\n\n        return ctxt_toolchain\n\n\nclass FindFiles(Block):\n    template = textwrap.dedent(\"\"\"\\\n        # Define paths to find packages, programs, libraries, etc.\n        if(EXISTS \"${CMAKE_CURRENT_LIST_DIR}/conan_cmakedeps_paths.cmake\")\n          message(STATUS \"Conan toolchain: Including CMakeDeps generated conan_cmakedeps_paths.cmake\")\n          include(\"${CMAKE_CURRENT_LIST_DIR}/conan_cmakedeps_paths.cmake\")\n        else()\n\n        {% if find_package_prefer_config %}\n        set(CMAKE_FIND_PACKAGE_PREFER_CONFIG {{ find_package_prefer_config }})\n        {% endif %}\n\n        # Definition of CMAKE_MODULE_PATH\n        {% if build_paths %}\n        list(PREPEND CMAKE_MODULE_PATH {{ build_paths }})\n        {% endif %}\n        {% if generators_folder %}\n        # the generators folder (where conan generates files, like this toolchain)\n        list(PREPEND CMAKE_MODULE_PATH {{ generators_folder }})\n        {% endif %}\n\n        # Definition of CMAKE_PREFIX_PATH, CMAKE_XXXXX_PATH\n        {% if build_paths %}\n        # The explicitly defined \"builddirs\" of \"host\" context dependencies must be in PREFIX_PATH\n        list(PREPEND CMAKE_PREFIX_PATH {{ build_paths }})\n        {% endif %}\n        {% if generators_folder %}\n        # The Conan local \"generators\" folder, where this toolchain is saved.\n        list(PREPEND CMAKE_PREFIX_PATH {{ generators_folder }} )\n        {% endif %}\n        {% if cmake_program_path %}\n        list(PREPEND CMAKE_PROGRAM_PATH {{ cmake_program_path }})\n        {% endif %}\n        {% if cmake_library_path %}\n        list(PREPEND CMAKE_LIBRARY_PATH {{ cmake_library_path }})\n        {% endif %}\n        {% if is_apple and cmake_framework_path %}\n        list(PREPEND CMAKE_FRAMEWORK_PATH {{ cmake_framework_path }})\n        {% endif %}\n        {% if cmake_include_path %}\n        list(PREPEND CMAKE_INCLUDE_PATH {{ cmake_include_path }})\n        {% endif %}\n        {% if host_runtime_dirs %}\n        set(CONAN_RUNTIME_LIB_DIRS {{ host_runtime_dirs }} )\n        {% endif %}\n\n        {% if cross_building %}\n        if(NOT DEFINED CMAKE_FIND_ROOT_PATH_MODE_PACKAGE OR CMAKE_FIND_ROOT_PATH_MODE_PACKAGE STREQUAL \"ONLY\")\n            set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE \"BOTH\")\n        endif()\n        if(NOT DEFINED CMAKE_FIND_ROOT_PATH_MODE_PROGRAM OR CMAKE_FIND_ROOT_PATH_MODE_PROGRAM STREQUAL \"ONLY\")\n            set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM \"BOTH\")\n        endif()\n        if(NOT DEFINED CMAKE_FIND_ROOT_PATH_MODE_LIBRARY OR CMAKE_FIND_ROOT_PATH_MODE_LIBRARY STREQUAL \"ONLY\")\n            set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY \"BOTH\")\n        endif()\n        {% if is_apple %}\n        if(NOT DEFINED CMAKE_FIND_ROOT_PATH_MODE_FRAMEWORK OR CMAKE_FIND_ROOT_PATH_MODE_FRAMEWORK STREQUAL \"ONLY\")\n            set(CMAKE_FIND_ROOT_PATH_MODE_FRAMEWORK \"BOTH\")\n        endif()\n        {% endif %}\n        if(NOT DEFINED CMAKE_FIND_ROOT_PATH_MODE_INCLUDE OR CMAKE_FIND_ROOT_PATH_MODE_INCLUDE STREQUAL \"ONLY\")\n            set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE \"BOTH\")\n        endif()\n        {% endif %}\n        endif()\n    \"\"\")\n\n    def _runtime_dirs_value(self, dirs):\n        if is_multi_configuration(self._toolchain.generator):\n            return ' '.join(f'\"$<$<CONFIG:{c}>:{i}>\"' for c, v in dirs.items() for i in v)\n        else:\n            return ' '.join(f'\"{item}\"' for _, items in dirs.items() for item in items)\n\n    def _get_host_runtime_dirs(self, host_req):\n        settings = self._conanfile.settings\n        host_runtime_dirs = {}\n        is_win = self._conanfile.settings.get_safe(\"os\") == \"Windows\"\n\n        # Get the previous configuration\n        if is_multi_configuration(self._toolchain.generator) and os.path.exists(CONAN_TOOLCHAIN_FILENAME):\n            existing_toolchain = load(CONAN_TOOLCHAIN_FILENAME)\n            pattern_lib_dirs = r\"set\\(CONAN_RUNTIME_LIB_DIRS ([^)]*)\\)\"\n            variable_match = re.search(pattern_lib_dirs, existing_toolchain)\n            if variable_match:\n                capture = variable_match.group(1)\n                matches = re.findall(r'\"\\$<\\$<CONFIG:([A-Za-z]*)>:([^>]*)>\"', capture)\n                host_runtime_dirs = {}\n                for k, v in matches:\n                    host_runtime_dirs.setdefault(k, []).append(v)\n\n        # Calculate the dirs for the current build_type\n        runtime_dirs = []\n        for req in host_req:\n            cppinfo = req.cpp_info.aggregated_components()\n            runtime_dirs.extend(cppinfo.bindirs if is_win else cppinfo.libdirs)\n\n        build_type = settings.get_safe(\"build_type\")\n        host_runtime_dirs[build_type] = [s.replace(\"\\\\\", \"/\") for s in runtime_dirs]\n\n        return host_runtime_dirs\n\n    def _join_paths(self, paths):\n        paths = [p.replace('\\\\', '/').replace('$', '\\\\$').replace('\"', '\\\\\"') for p in paths]\n        paths = [relativize_path(p, self._conanfile, \"${CMAKE_CURRENT_LIST_DIR}\") for p in paths]\n        return \" \".join([f'\"{p}\"' for p in paths])\n\n    def context(self):\n        # To find the generated cmake_find_package finders\n        # TODO: Change this for parameterized output location of CMakeDeps\n        find_package_prefer_config = \"ON\"  # assume ON by default if not specified in conf\n        prefer_config = self._conanfile.conf.get(\"tools.cmake.cmaketoolchain:find_package_prefer_config\",\n                                                 check_type=bool)\n        if prefer_config is False:\n            find_package_prefer_config = \"OFF\"\n\n        is_apple_ = is_apple_os(self._conanfile)\n\n        # Read information from host context\n        # TODO: Add here in 2.0 the \"skip\": False trait\n        host_req = self._conanfile.dependencies.filter({\"build\": False}).values()\n        build_paths = []\n        host_lib_paths = []\n        host_runtime_dirs = self._get_host_runtime_dirs(host_req)\n        host_framework_paths = []\n        host_include_paths = []\n        for req in host_req:\n            cppinfo = req.cpp_info.aggregated_components()\n            build_paths.extend(cppinfo.builddirs)\n            host_lib_paths.extend(cppinfo.libdirs)\n            if is_apple_:\n                host_framework_paths.extend(cppinfo.frameworkdirs)\n            host_include_paths.extend(cppinfo.includedirs)\n\n        # Read information from build context\n        build_req = self._conanfile.dependencies.build.values()\n        build_bin_paths = []\n        for req in build_req:\n            cppinfo = req.cpp_info.aggregated_components()\n            build_paths.extend(cppinfo.builddirs)\n            build_bin_paths.extend(cppinfo.bindirs)\n\n        return {\n            \"find_package_prefer_config\": find_package_prefer_config,\n            \"generators_folder\": \"${CMAKE_CURRENT_LIST_DIR}\",\n            \"build_paths\": self._join_paths(build_paths),\n            \"cmake_program_path\": self._join_paths(build_bin_paths),\n            \"cmake_library_path\": self._join_paths(host_lib_paths),\n            \"cmake_framework_path\": self._join_paths(host_framework_paths),\n            \"cmake_include_path\": self._join_paths(host_include_paths),\n            \"is_apple\": is_apple_,\n            \"cross_building\": cross_building(self._conanfile),\n            \"host_runtime_dirs\": self._runtime_dirs_value(host_runtime_dirs)\n        }\n\n\nclass PkgConfigBlock(Block):\n    template = textwrap.dedent(\"\"\"\\\n        # Define pkg-config from 'tools.gnu:pkg_config' executable and paths\n\n        {% if pkg_config %}\n        set(PKG_CONFIG_EXECUTABLE {{ pkg_config }} CACHE FILEPATH \"pkg-config executable\")\n        {% endif %}\n        {% if pkg_config_path %}\n        if (DEFINED ENV{PKG_CONFIG_PATH})\n        set(ENV{PKG_CONFIG_PATH} \"{{ pkg_config_path }}$ENV{PKG_CONFIG_PATH}\")\n        else()\n        set(ENV{PKG_CONFIG_PATH} \"{{ pkg_config_path }}\")\n        endif()\n        {% endif %}\n        \"\"\")\n\n    def context(self):\n        pkg_config = self._conanfile.conf.get(\"tools.gnu:pkg_config\", check_type=str)\n        if pkg_config:\n            pkg_config = pkg_config.replace(\"\\\\\", \"/\")\n        subsystem = deduce_subsystem(self._conanfile, \"build\")\n        pathsep = \":\" if subsystem != WINDOWS else \";\"\n        pkg_config_path = \"${CMAKE_CURRENT_LIST_DIR}\" + pathsep\n        return {\"pkg_config\": pkg_config,\n                \"pkg_config_path\": pkg_config_path}\n\n\nclass UserToolchain(Block):\n    template = textwrap.dedent(\"\"\"\\\n        # Include one or more CMake user toolchain from tools.cmake.cmaketoolchain:user_toolchain\n\n        {% for user_toolchain in paths %}\n        message(STATUS \"Conan toolchain: Including user_toolchain: {{user_toolchain}}\")\n        include(\"{{user_toolchain}}\")\n        {% endfor %}\n        \"\"\")\n\n    def context(self):\n        # This is global [conf] injection of extra toolchain files\n        user_toolchain = self._conanfile.conf.get(\"tools.cmake.cmaketoolchain:user_toolchain\",\n                                                  default=[], check_type=list)\n        paths = [relativize_path(p, self._conanfile, \"${CMAKE_CURRENT_LIST_DIR}\")\n                 for p in user_toolchain]\n        paths = [p.replace(\"\\\\\", \"/\") for p in paths]\n        return {\"paths\": paths}\n\n\nclass ExtraFlagsBlock(Block):\n    \"\"\"This block is adding flags directly from user [conf] section\"\"\"\n\n    _template = textwrap.dedent(\"\"\"\\\n        # Include extra C++, C and linker flags from configuration tools.build:<type>flags\n        # and from CMakeToolchain.extra_<type>_flags\n\n        # Conan conf flags start: {{config}}\n        {% if cxxflags %}\n        string(APPEND CONAN_CXX_FLAGS{{suffix}} \"{% for cxxflag in cxxflags %} {{ cxxflag }}{% endfor %}\")\n        {% endif %}\n        {% if cflags %}\n        string(APPEND CONAN_C_FLAGS{{suffix}} \"{% for cflag in cflags %} {{ cflag }}{% endfor %}\")\n        {% endif %}\n        {% if sharedlinkflags %}\n        string(APPEND CONAN_SHARED_LINKER_FLAGS{{suffix}} \"{% for sharedlinkflag in sharedlinkflags %} {{ sharedlinkflag }}{% endfor %}\")\n        {% endif %}\n        {% if exelinkflags %}\n        string(APPEND CONAN_EXE_LINKER_FLAGS{{suffix}} \"{% for exelinkflag in exelinkflags %} {{ exelinkflag }}{% endfor %}\")\n        {% endif %}\n        {% if rcflags %}\n        string(APPEND CONAN_RC_FLAGS{{suffix}} \"{% for rcflag in rcflags %} {{ rcflag }}{% endfor %}\")\n        {% endif %}\n        {% if defines %}\n        {% if config %}\n        {% for define in defines %}\n        add_compile_definitions(\"$<$<CONFIG:{{config}}>:{{ define }}>\")\n        {% endfor %}\n        {% else %}\n        add_compile_definitions({% for define in defines %} \"{{ define }}\"{% endfor %})\n        {% endif %}\n        {% endif %}\n        # Conan conf flags end\n    \"\"\")\n\n    @property\n    def template(self):\n        if not is_multi_configuration(self._toolchain.generator):\n            return self._template\n\n        sections = {}\n        if os.path.exists(CONAN_TOOLCHAIN_FILENAME):\n            existing_toolchain = load(CONAN_TOOLCHAIN_FILENAME)\n            lines = existing_toolchain.splitlines()\n            current_section = None\n            for line in lines:\n                if line.startswith(\"# Conan conf flags start: \"):\n                    section_name = line.split(\":\", 1)[1].strip()\n                    current_section = [line]\n                    sections[section_name] = current_section\n                elif line == \"# Conan conf flags end\":\n                    current_section.append(line)\n                    current_section = None\n                elif current_section is not None:\n                    current_section.append(line)\n            sections.pop(\"\", None)  # Just in case it had a single config before\n\n        config = self._conanfile.settings.get_safe(\"build_type\")\n        for k, v in sections.items():\n            if k != config:\n                v.insert(0, \"{% raw %}\")\n                v.append(\"{% endraw %}\")\n        sections[config] = [self._template]\n        sections = [\"\\n\".join(lines) for lines in sections.values()]\n        sections = \"\\n\".join(sections)\n        return sections\n\n    def context(self):\n        # Now, it's time to get all the flags defined by the user\n        cxxflags = self._toolchain.extra_cxxflags + self._conanfile.conf.get(\"tools.build:cxxflags\", default=[], check_type=list)\n        cflags = self._toolchain.extra_cflags + self._conanfile.conf.get(\"tools.build:cflags\", default=[], check_type=list)\n        sharedlinkflags = self._toolchain.extra_sharedlinkflags + self._conanfile.conf.get(\"tools.build:sharedlinkflags\", default=[], check_type=list)\n        exelinkflags = self._toolchain.extra_exelinkflags + self._conanfile.conf.get(\"tools.build:exelinkflags\", default=[], check_type=list)\n        rcflags = self._conanfile.conf.get(\"tools.build:rcflags\", default=[], check_type=list)\n        defines = self._conanfile.conf.get(\"tools.build:defines\", default=[], check_type=list)\n\n        # See https://github.com/conan-io/conan/issues/13374\n        android_ndk_path = self._conanfile.conf.get(\"tools.android:ndk_path\")\n        android_legacy_toolchain = self._conanfile.conf.get(\"tools.android:cmake_legacy_toolchain\",\n                                                            check_type=bool)\n        if android_ndk_path and (cxxflags or cflags) and android_legacy_toolchain is not False:\n            self._conanfile.output.warning(\"tools.build:cxxflags or cflags are defined, but Android NDK toolchain may be overriding \"\n                                           \"the values. Consider setting tools.android:cmake_legacy_toolchain to False.\")\n\n        config = \"\"\n        suffix = \"\"\n        if is_multi_configuration(self._toolchain.generator):\n            config = self._conanfile.settings.get_safe(\"build_type\")\n            suffix = f\"_{config.upper()}\" if config else \"\"\n        return {\n            \"config\": config,\n            \"suffix\": suffix,\n            \"cxxflags\": cxxflags,\n            \"cflags\": cflags,\n            \"sharedlinkflags\": sharedlinkflags,\n            \"exelinkflags\": exelinkflags,\n            \"rcflags\": rcflags,\n            \"defines\": [define.replace('\"', '\\\\\"') for define in defines],\n        }\n\n\nclass CMakeFlagsInitBlock(Block):\n    template = textwrap.dedent(\"\"\"\\\n        # Define CMAKE_<XXX>_FLAGS from CONAN_<XXX>_FLAGS\n\n        foreach(config IN LISTS CMAKE_CONFIGURATION_TYPES)\n            string(TOUPPER ${config} config)\n            if(DEFINED CONAN_CXX_FLAGS_${config})\n              string(APPEND CMAKE_CXX_FLAGS_${config}_INIT \" ${CONAN_CXX_FLAGS_${config}}\")\n            endif()\n            if(DEFINED CONAN_C_FLAGS_${config})\n              string(APPEND CMAKE_C_FLAGS_${config}_INIT \" ${CONAN_C_FLAGS_${config}}\")\n            endif()\n            if(DEFINED CONAN_SHARED_LINKER_FLAGS_${config})\n              string(APPEND CMAKE_SHARED_LINKER_FLAGS_${config}_INIT \" ${CONAN_SHARED_LINKER_FLAGS_${config}}\")\n            endif()\n            if(DEFINED CONAN_EXE_LINKER_FLAGS_${config})\n              string(APPEND CMAKE_EXE_LINKER_FLAGS_${config}_INIT \" ${CONAN_EXE_LINKER_FLAGS_${config}}\")\n            endif()\n            if(DEFINED CONAN_RC_FLAGS_${config})\n              string(APPEND CMAKE_RC_FLAGS_${config}_INIT \" ${CONAN_RC_FLAGS_${config}}\")\n            endif()\n        endforeach()\n\n        if(DEFINED CONAN_CXX_FLAGS)\n          string(APPEND CMAKE_CXX_FLAGS_INIT \" ${CONAN_CXX_FLAGS}\")\n        endif()\n        if(DEFINED CONAN_C_FLAGS)\n          string(APPEND CMAKE_C_FLAGS_INIT \" ${CONAN_C_FLAGS}\")\n        endif()\n        if(DEFINED CONAN_SHARED_LINKER_FLAGS)\n          string(APPEND CMAKE_SHARED_LINKER_FLAGS_INIT \" ${CONAN_SHARED_LINKER_FLAGS}\")\n        endif()\n        if(DEFINED CONAN_EXE_LINKER_FLAGS)\n          string(APPEND CMAKE_EXE_LINKER_FLAGS_INIT \" ${CONAN_EXE_LINKER_FLAGS}\")\n        endif()\n        if(DEFINED CONAN_RC_FLAGS)\n          string(APPEND CMAKE_RC_FLAGS_INIT \" ${CONAN_RC_FLAGS}\")\n        endif()\n        if(DEFINED CONAN_OBJCXX_FLAGS)\n          string(APPEND CMAKE_OBJCXX_FLAGS_INIT \" ${CONAN_OBJCXX_FLAGS}\")\n        endif()\n        if(DEFINED CONAN_OBJC_FLAGS)\n          string(APPEND CMAKE_OBJC_FLAGS_INIT \" ${CONAN_OBJC_FLAGS}\")\n        endif()\n        \"\"\")\n\n\nclass TryCompileBlock(Block):\n    template = textwrap.dedent(\"\"\"\\\n        # Blocks after this one will not be added when running CMake try/checks\n        {% if config %}\n        if(NOT DEFINED CMAKE_TRY_COMPILE_CONFIGURATION)  # to allow user command line override\n            set(CMAKE_TRY_COMPILE_CONFIGURATION {{config}})\n        endif()\n        {% endif %}\n        get_property( _CMAKE_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE )\n        if(_CMAKE_IN_TRY_COMPILE)\n            message(STATUS \"Running toolchain IN_TRY_COMPILE\")\n            return()\n        endif()\n        \"\"\")\n\n    def context(self):\n        # Only for well known CMake configurations, but not for custom ones\n        # Revert of https://github.com/conan-io/conan/pull/18559, even if it was correct, there are\n        # legacy code using check_function_exists that breaks in CMake with MSVC, see\n        # https://github.com/conan-io/conan/issues/18689\n        # TODO: Resume this effort when other try_compile things are sorted out\n        # bt = self._conanfile.settings.get_safe(\"build_type\")\n        # config = bt if bt in [\"Debug\", \"Release\", \"RelWithDebInfo\", \"MinSizeRel\"] else None\n        config = None  # Keep it defined but as `None` in case some user already customized it\n        return {\"config\": config}\n\n\nclass CompilersBlock(Block):\n    template = textwrap.dedent(r\"\"\"\n        {% for lang, compiler_path in compilers.items() %}\n        set(CMAKE_{{ lang }}_COMPILER \"{{ compiler_path|replace('\\\\', '/') }}\")\n        {% endfor %}\n    \"\"\")\n\n    def context(self):\n        # Reading configuration from \"tools.build:compiler_executables\" -> {\"C\": \"/usr/bin/gcc\"}\n        compilers_by_conf = self._conanfile.conf.get(\"tools.build:compiler_executables\", default={},\n                                                     check_type=dict)\n        # Map the possible languages\n        compilers = {}\n        # Allowed <LANG> variables (and <LANG>_LAUNCHER)\n        compilers_mapping = {\"c\": \"C\", \"cuda\": \"CUDA\", \"cpp\": \"CXX\", \"objc\": \"OBJC\",\n                             \"objcpp\": \"OBJCXX\", \"rc\": \"RC\", 'fortran': \"Fortran\", 'asm': \"ASM\",\n                             \"hip\": \"HIP\", \"ispc\": \"ISPC\"}\n        for comp, lang in compilers_mapping.items():\n            # To set CMAKE_<LANG>_COMPILER\n            if comp in compilers_by_conf:\n                compilers[lang] = compilers_by_conf[comp]\n        compiler = self._conanfile.settings.get_safe(\"compiler\")\n        if compiler == \"msvc\" and \"Ninja\" in str(self._toolchain.generator):\n            # None of them defined, if one is defined by user, user should define the other too\n            if \"c\" not in compilers_by_conf and \"cpp\" not in compilers_by_conf:\n                compilers[\"C\"] = \"cl\"\n                compilers[\"CXX\"] = \"cl\"\n        return {\"compilers\": compilers}\n\n\nclass GenericSystemBlock(Block):\n    template = textwrap.dedent(\"\"\"\\\n        # Definition of system, platform and toolset\n\n        {% if cmake_sysroot %}\n        set(CMAKE_SYSROOT {{ cmake_sysroot }})\n        {% endif %}\n        {% if cmake_system_name %}\n        # Cross building\n        if(NOT DEFINED CMAKE_SYSTEM_NAME) # It might have been defined by a user toolchain\n        set(CMAKE_SYSTEM_NAME {{ cmake_system_name }})\n        endif()\n        {% endif %}\n        {% if cmake_system_version %}\n        if(NOT DEFINED CMAKE_SYSTEM_VERSION) # It might have been defined by a user toolchain\n        set(CMAKE_SYSTEM_VERSION {{ cmake_system_version }})\n        endif()\n        {% endif %}\n        {% if cmake_system_processor %}\n        if(NOT DEFINED CMAKE_SYSTEM_PROCESSOR) # It might have been defined by a user toolchain\n        set(CMAKE_SYSTEM_PROCESSOR {{ cmake_system_processor }})\n        endif()\n        {% endif %}\n\n        {% if generator_platform and not winsdk_version %}\n        set(CMAKE_GENERATOR_PLATFORM \"{{ generator_platform }}\" CACHE STRING \"\" FORCE)\n        {% elif winsdk_version %}\n        if(POLICY CMP0149)\n            cmake_policy(GET CMP0149 _POLICY_WINSDK_VERSION)\n        endif()\n        if(_POLICY_WINSDK_VERSION STREQUAL \"NEW\")\n            message(STATUS \"Conan toolchain: CMAKE_GENERATOR_PLATFORM={{gen_platform_sdk_version}}\")\n            set(CMAKE_GENERATOR_PLATFORM \"{{ gen_platform_sdk_version }}\" CACHE STRING \"\" FORCE)\n        else()\n            # winsdk_version will be taken from above CMAKE_SYSTEM_VERSION\n            message(STATUS \"Conan toolchain: CMAKE_GENERATOR_PLATFORM={{generator_platform}}\")\n            set(CMAKE_GENERATOR_PLATFORM \"{{ generator_platform }}\" CACHE STRING \"\" FORCE)\n        endif()\n        {% endif %}\n\n        {% if toolset %}\n        message(STATUS \"Conan toolchain: CMAKE_GENERATOR_TOOLSET={{ toolset }}\")\n        set(CMAKE_GENERATOR_TOOLSET \"{{ toolset }}\" CACHE STRING \"\" FORCE)\n        {% endif %}\n        \"\"\")\n\n    @staticmethod\n    def get_toolset(generator, conanfile):\n        toolset = None\n        if generator is None or (\"Visual\" not in generator and \"Xcode\" not in generator):\n            return None\n        settings = conanfile.settings\n        compiler = settings.get_safe(\"compiler\")\n        if compiler == \"intel-cc\":\n            return IntelCC(conanfile).ms_toolset\n        elif compiler == \"msvc\":\n            toolset = settings.get_safe(\"compiler.toolset\")\n            if toolset is None:\n                compiler_version = str(settings.compiler.version)\n                msvc_update = conanfile.conf.get(\"tools.microsoft:msvc_update\")\n                compiler_update = msvc_update or settings.get_safe(\"compiler.update\")\n                toolset = msvc_version_to_toolset_version(compiler_version)\n                if compiler_update is not None:  # It is full one(19.28), not generic 19.2X\n                    # The equivalent of compiler 19.26 is toolset 14.26\n                    toolset += \",version=14.{}{}\".format(compiler_version[-1], compiler_update)\n        elif compiler == \"clang\":\n            if generator and \"Visual\" in generator:\n                if any(f\"Visual Studio {v}\" in generator for v in (\"16\", \"17\", \"18\")):\n                    toolset = \"ClangCL\"\n                else:\n                    raise ConanException(\"CMakeToolchain with compiler=clang and a CMake \"\n                                         \"'Visual Studio' generator requires VS16, VS17 or VS18\")\n        toolset_arch = conanfile.conf.get(\"tools.cmake.cmaketoolchain:toolset_arch\")\n        if toolset_arch is not None:\n            toolset_arch = \"host={}\".format(toolset_arch)\n            toolset = toolset_arch if toolset is None else \"{},{}\".format(toolset, toolset_arch)\n        toolset_cuda = conanfile.conf.get(\"tools.cmake.cmaketoolchain:toolset_cuda\")\n        if toolset_cuda is not None:\n            toolset_cuda = relativize_path(toolset_cuda, conanfile, \"${CMAKE_CURRENT_LIST_DIR}\")\n            toolset_cuda = f\"cuda={toolset_cuda}\"\n            toolset = toolset_cuda if toolset is None else f\"{toolset},{toolset_cuda}\"\n        return toolset\n\n    @staticmethod\n    def get_generator_platform(generator, conanfile):\n        settings = conanfile.settings\n        # Returns the generator platform to be used by CMake\n        compiler = settings.get_safe(\"compiler\")\n        arch = settings.get_safe(\"arch\")\n\n        if settings.get_safe(\"os\") == \"WindowsCE\":\n            return settings.get_safe(\"os.platform\")\n\n        if compiler in (\"msvc\", \"clang\") and generator and \"Visual\" in generator:\n            return msvc_platform_from_arch(arch)\n        return None\n\n    def _get_generic_system_name(self):\n        os_host = self._conanfile.settings.get_safe(\"os\")\n        os_build = self._conanfile.settings_build.get_safe(\"os\")\n        arch_host = self._conanfile.settings.get_safe(\"arch\")\n        arch_build = self._conanfile.settings_build.get_safe(\"arch\")\n        cmake_system_name_map = {\"Neutrino\": \"QNX\",\n                                 \"\": \"Generic\",\n                                 \"baremetal\": \"Generic\",\n                                 None: \"Generic\"}\n        if os_host != os_build:\n            # os_host would be 'baremetal' for tricore, but it's ideal to use the Generic-ELF\n            # system name instead of just \"Generic\" because it matches how Aurix Dev Studio\n            # generated makefiles behave by generating binaries with the '.elf' extension.\n            if arch_host in ['tc131', 'tc16', 'tc161', 'tc162', 'tc18']:\n                return \"Generic-ELF\"\n            return cmake_system_name_map.get(os_host, os_host)\n        elif arch_host is not None and arch_host != arch_build:\n            if not ((arch_build == \"x86_64\") and (arch_host == \"x86\") or\n                    (arch_build == \"sparcv9\") and (arch_host == \"sparc\") or\n                    (arch_build == \"ppc64\") and (arch_host == \"ppc32\")):\n                return cmake_system_name_map.get(os_host, os_host)\n\n    def _is_apple_cross_building(self):\n\n        if is_universal_arch(self._conanfile.settings.get_safe(\"arch\"),\n                             self._conanfile.settings.possible_values().get(\"arch\")):\n            return False\n\n        os_host = self._conanfile.settings.get_safe(\"os\")\n        arch_host = self._conanfile.settings.get_safe(\"arch\")\n        arch_build = self._conanfile.settings_build.get_safe(\"arch\")\n        os_build = self._conanfile.settings_build.get_safe(\"os\")\n        return os_host in ('iOS', 'watchOS', 'tvOS', 'visionOS') or (\n                os_host == 'Macos' and (arch_host != arch_build or os_build != os_host))\n\n    @staticmethod\n    def _get_darwin_version(os_name, os_version):\n        # version mapping from https://en.wikipedia.org/wiki/Darwin_(operating_system)\n        # but a more detailed version can be found in https://theapplewiki.com/wiki/Kernel\n        version_mapping = {\n            \"Macos\": {\n                \"10.6\": \"10\", \"10.7\": \"11\", \"10.8\": \"12\", \"10.9\": \"13\", \"10.10\": \"14\", \"10.11\": \"15\",\n                \"10.12\": \"16\", \"10.13\": \"17\", \"10.14\": \"18\", \"10.15\": \"19\", \"11\": \"20\", \"12\": \"21\",\n                \"13\": \"22\", \"14\": \"23\", \"15\": \"24\"\n            },\n            \"iOS\": {\n                \"7\": \"14\", \"8\": \"14\", \"9\": \"15\", \"10\": \"16\", \"11\": \"17\", \"12\": \"18\", \"13\": \"19\",\n                \"14\": \"20\", \"15\": \"21\", \"16\": \"22\", \"17\": \"23\", \"18\": \"24\"\n            },\n            \"watchOS\": {\n                \"4\": \"17\", \"5\": \"18\", \"6\": \"19\", \"7\": \"20\",\n                \"8\": \"21\", \"9\": \"22\", \"10\": \"23\", \"11\": \"24\"\n            },\n            \"tvOS\": {\n                \"11\": \"17\", \"12\": \"18\", \"13\": \"19\", \"14\": \"20\",\n                \"15\": \"21\", \"16\": \"22\", \"17\": \"23\", \"18\": \"24\"\n            },\n            \"visionOS\": {\n                \"1\": \"23\", \"2\": \"24\"\n            }\n        }\n        os_version = Version(os_version).major if os_name != \"Macos\" or (os_name == \"Macos\" and Version(\n            os_version) >= Version(\"11\")) else os_version\n        return version_mapping.get(os_name, {}).get(str(os_version))\n\n    def _get_cross_build(self):\n        system_name = self._conanfile.conf.get(\"tools.cmake.cmaketoolchain:system_name\")\n        system_version = self._conanfile.conf.get(\"tools.cmake.cmaketoolchain:system_version\")\n        system_processor = self._conanfile.conf.get(\"tools.cmake.cmaketoolchain:system_processor\")\n\n        # try to detect automatically\n        if not is_universal_arch(self._conanfile.settings.get_safe(\"arch\"),\n                                 self._conanfile.settings.possible_values().get(\"arch\")):\n            os_host = self._conanfile.settings.get_safe(\"os\")\n            os_host_version = self._conanfile.settings.get_safe(\"os.version\")\n            arch_host = self._conanfile.settings.get_safe(\"arch\")\n            if arch_host == \"armv8\":\n                arch_host = {\"Windows\": \"ARM64\", \"Macos\": \"arm64\"}.get(os_host, \"aarch64\")\n\n            if system_name is None:  # Try to deduce\n                _system_version = None\n                _system_processor = None\n                if self._is_apple_cross_building():\n                    # cross-build in Macos also for M1\n                    system_name = {'Macos': 'Darwin'}.get(os_host, os_host)\n                    #  CMAKE_SYSTEM_VERSION for Apple sets the Darwin version, not the os version\n                    _system_version = self._get_darwin_version(os_host, os_host_version)\n                    _system_processor = to_apple_arch(self._conanfile)\n                elif os_host != 'Android':\n                    system_name = self._get_generic_system_name()\n                    if arch_host in ['tc131', 'tc16', 'tc161', 'tc162', 'tc18']:\n                        _system_processor = \"tricore\"\n                    else:\n                        _system_processor = arch_host\n                    _system_version = os_host_version\n\n                if system_name is not None and system_version is None:\n                    system_version = _system_version\n                if system_name is not None and system_processor is None:\n                    system_processor = _system_processor\n\n        return system_name, system_version, system_processor\n\n    def _get_winsdk_version(self, system_version, generator_platform):\n        compiler = self._conanfile.settings.get_safe(\"compiler\")\n        if compiler not in (\"msvc\", \"clang\") or \"Visual\" not in str(self._toolchain.generator):\n            # Ninja will get it from VCVars, not from toolchain\n            return system_version, None, None\n\n        winsdk_version = self._conanfile.conf.get(\"tools.microsoft:winsdk_version\", check_type=str)\n        if winsdk_version:\n            if system_version:\n                self._conanfile.output.warning(\"Both cmake_system_version and winsdk_version confs\"\n                                               \" defined, prioritizing winsdk_version\")\n            system_version = winsdk_version\n        elif \"Windows\" in self._conanfile.settings.get_safe(\"os\", \"\"):\n            winsdk_version = self._conanfile.settings.get_safe(\"os.version\")\n            if system_version:\n                if winsdk_version:\n                    self._conanfile.output.warning(\"Both cmake_system_version conf and os.version\"\n                                                   \" defined, prioritizing cmake_system_version\")\n                winsdk_version = system_version\n\n        gen_platform_sdk_version = [generator_platform,\n                                    f\"version={winsdk_version}\" if winsdk_version else None]\n        gen_platform_sdk_version = \",\".join(d for d in gen_platform_sdk_version if d)\n\n        return system_version, winsdk_version, gen_platform_sdk_version\n\n    def context(self):\n        generator = self._toolchain.generator\n        generator_platform = self.get_generator_platform(generator, self._conanfile)\n        toolset = self.get_toolset(generator, self._conanfile)\n        system_name, system_version, system_processor = self._get_cross_build()\n\n        # This is handled by the tools.apple:sdk_path and CMAKE_OSX_SYSROOT in Apple\n        cmake_sysroot = self._conanfile.conf.get(\"tools.build:sysroot\")\n        cmake_sysroot = cmake_sysroot.replace(\"\\\\\", \"/\") if cmake_sysroot is not None else None\n        if cmake_sysroot is not None:\n            cmake_sysroot = relativize_path(cmake_sysroot, self._conanfile,\n                                            \"${CMAKE_CURRENT_LIST_DIR}\")\n\n        result = self._get_winsdk_version(system_version, generator_platform)\n        system_version, winsdk_version, gen_platform_sdk_version = result\n\n        return {\"toolset\": toolset,\n                \"generator_platform\": generator_platform,\n                \"cmake_system_name\": system_name,\n                \"cmake_system_version\": system_version,\n                \"cmake_system_processor\": system_processor,\n                \"cmake_sysroot\": cmake_sysroot,\n                \"winsdk_version\": winsdk_version,\n                \"gen_platform_sdk_version\": gen_platform_sdk_version}\n\n\nclass ExtraVariablesBlock(Block):\n    template = textwrap.dedent(\"\"\"\\\n        # Definition of extra CMake variables from tools.cmake.cmaketoolchain:extra_variables\n\n        {% if extra_variables %}\n        {% for key, value in extra_variables.items() %}\n        set({{ key }} {{ value }})\n        {% endfor %}\n        {% endif %}\n    \"\"\")\n\n    def context(self):\n        from conan.tools.cmake.utils import parse_extra_variable\n        # Reading configuration from \"tools.cmake.cmaketoolchain:extra_variables\"\n        extra_variables = self._conanfile.conf.get(\"tools.cmake.cmaketoolchain:extra_variables\",\n                                                   default={}, check_type=dict)\n        compilation_verbosity = self._conanfile.conf.get(\"tools.compilation:verbosity\",\n                                                         choices=(\"quiet\", \"verbose\"))\n        build_verbosity = self._conanfile.conf.get(\"tools.build:verbosity\",\n                                                   choices=(\"quiet\", \"verbose\"))\n        if build_verbosity == \"quiet\":\n            build_verbosity = \"error\"\n\n        if compilation_verbosity == \"verbose\":\n            extra_variables.setdefault(\"CMAKE_VERBOSE_MAKEFILE\",\n                                       {\"cache\": True, \"type\": \"BOOL\",\n                                        \"value\": \"ON\"})\n\n        if build_verbosity:\n            extra_variables.setdefault(\"CMAKE_MESSAGE_LOG_LEVEL\",\n                                       {\"cache\": True, \"type\": \"STRING\",\n                                        \"value\": build_verbosity.upper()})\n\n        parsed_extra_variables = {}\n        for key, value in extra_variables.items():\n            parsed_extra_variables[key] = parse_extra_variable(\"tools.cmake.cmaketoolchain:extra_variables\",\n                                                               key, value)\n        return {\"extra_variables\": parsed_extra_variables}\n\n\nclass OutputDirsBlock(Block):\n\n    @property\n    def template(self):\n        return textwrap.dedent(\"\"\"\\\n           # Definition of CMAKE_INSTALL_XXX folders\n\n           # Ensure export(PACKAGE) honors CMAKE_EXPORT_PACKAGE_REGISTRY even if the\n           # project sets cmake_minimum_required() lower than 3.15.\n           cmake_policy(SET CMP0090 NEW)\n           if(NOT DEFINED CMAKE_EXPORT_PACKAGE_REGISTRY)\n               set(CMAKE_EXPORT_PACKAGE_REGISTRY OFF)\n           endif()\n\n           {% if package_folder %}\n           set(CMAKE_INSTALL_PREFIX \"{{package_folder}}\")\n           {% endif %}\n           {% if default_bin %}\n           set(CMAKE_INSTALL_BINDIR \"{{default_bin}}\")\n           set(CMAKE_INSTALL_SBINDIR \"{{default_bin}}\")\n           set(CMAKE_INSTALL_LIBEXECDIR \"{{default_bin}}\")\n           {% endif %}\n           {% if default_lib %}\n           set(CMAKE_INSTALL_LIBDIR \"{{default_lib}}\")\n           {% endif %}\n           {% if default_include %}\n           set(CMAKE_INSTALL_INCLUDEDIR \"{{default_include}}\")\n           set(CMAKE_INSTALL_OLDINCLUDEDIR \"{{default_include}}\")\n           {% endif %}\n           {% if default_res %}\n           set(CMAKE_INSTALL_DATAROOTDIR \"{{default_res}}\")\n           {% endif %}\n        \"\"\")\n\n    def _get_cpp_info_value(self, name):\n        # Why not taking cpp.build? because this variables are used by the \"cmake install\"\n        # that correspond to the package folder (even if the root is the build directory)\n        elements = getattr(self._conanfile.cpp.package, name)\n        return elements[0] if elements else None\n\n    def context(self):\n        pf = self._conanfile.package_folder\n        return {\"package_folder\": pf.replace(\"\\\\\", \"/\") if pf else None,\n                \"default_bin\": self._get_cpp_info_value(\"bindirs\"),\n                \"default_lib\": self._get_cpp_info_value(\"libdirs\"),\n                \"default_include\": self._get_cpp_info_value(\"includedirs\"),\n                \"default_res\": self._get_cpp_info_value(\"resdirs\")}\n\n\nclass VariablesBlock(Block):\n    @property\n    def template(self):\n        return textwrap.dedent(\"\"\"\\\n            # Definition of CMake variables from CMakeToolchain.variables values\n\n            {% macro iterate_configs(var_config, action) %}\n            {% for it, values in var_config.items() %}\n                {% set genexpr = namespace(str='') %}\n                {% for conf, value in values -%}\n                set(CONAN_DEF_{{ conf }}{{ it }} \"{{ value }}\")\n                {% endfor %}\n                {% for conf, value in values -%}\n                    {% set genexpr.str = genexpr.str +\n                                          '$<IF:$<CONFIG:' + conf + '>,${CONAN_DEF_' + conf|string + it|string + '},' %}\n                    {% if loop.last %}{% set genexpr.str = genexpr.str + '\"\"' -%}{%- endif -%}\n                {% endfor %}\n                {% for i in range(values|count) %}{% set genexpr.str = genexpr.str + '>' %}\n                {% endfor %}\n            set({{ it }} {{ genexpr.str }} CACHE STRING\n                \"Variable {{ it }} conan-toolchain defined\")\n            {% endfor %}\n            {% endmacro %}\n            # Variables\n            {% for it, value in variables.items() %}\n            {% if value is boolean %}\n            set({{ it }} {{ \"ON\" if value else \"OFF\"}} CACHE BOOL \"Variable {{ it }} conan-toolchain defined\")\n            {% else %}\n            set({{ it }} \"{{ value }}\" CACHE STRING \"Variable {{ it }} conan-toolchain defined\")\n            {% endif %}\n            {% endfor %}\n            # Variables  per configuration\n            {{ iterate_configs(variables_config, action='set') }}\n            \"\"\")\n\n    def context(self):\n        return {\"variables\": self._toolchain.variables,\n                \"variables_config\": self._toolchain.variables.configuration_types}\n\n\nclass PreprocessorBlock(Block):\n    @property\n    def template(self):\n        return textwrap.dedent(\"\"\"\\\n        # Preprocessor definitions from CMakeToolchain.preprocessor_definitions values\n\n        {% for it, value in preprocessor_definitions.items() %}\n        {% if value is none %}\n        add_compile_definitions(\"{{ it }}\")\n        {% else %}\n        add_compile_definitions(\"{{ it }}={{ value }}\")\n        {% endif %}\n        {% endfor %}\n        # Preprocessor definitions per configuration\n        {% for name, values in preprocessor_definitions_config.items() %}\n        {%- for (conf, value) in values %}\n        {% if value is none %}\n        set(CONAN_DEF_{{conf}}_{{name}} \"{{name}}\")\n        {% else %}\n        set(CONAN_DEF_{{conf}}_{{name}} \"{{name}}={{value}}\")\n        {% endif %}\n        {% endfor %}\n        add_compile_definitions(\n        {%- for (conf, value) in values %}\n        $<$<CONFIG:{{conf}}>:${CONAN_DEF_{{conf}}_{{name}}}>\n        {%- endfor -%})\n        {% endfor %}\n        \"\"\")\n\n    def context(self):\n        return {\"preprocessor_definitions\": self._toolchain.preprocessor_definitions,\n                \"preprocessor_definitions_config\":\n                    self._toolchain.preprocessor_definitions.configuration_types}\n\n\nclass ToolchainBlocks:\n    def __init__(self, conanfile, toolchain, items=None):\n        self._blocks = OrderedDict()\n        self._conanfile = conanfile\n        self._toolchain = toolchain\n        if items:\n            for name, block in items:\n                self._blocks[name] = block(conanfile, toolchain, name)\n\n    def keys(self):\n        return self._blocks.keys()\n\n    def items(self):\n        return self._blocks.items()\n\n    def remove(self, name, *args):\n        del self._blocks[name]\n        for arg in args:\n            del self._blocks[arg]\n\n    def select(self, name, *args):\n        \"\"\"\n        keep the blocks provided as arguments, remove the others, except pre-existing \"variables\"\n        and \"preprocessor\", to not break behavior\n        \"\"\"\n        self._conanfile.output.warning(\"CMakeToolchain.select is deprecated. Use blocks.enabled()\"\n                                       \" instead\", warn_tag=\"deprecated\")\n        to_keep = [name] + list(args) + [\"variables\", \"preprocessor\"]\n        self._blocks = OrderedDict((k, v) for k, v in self._blocks.items() if k in to_keep)\n\n    def enabled(self, name, *args):\n        \"\"\"\n        keep the blocks provided as arguments, remove the others\n        \"\"\"\n        to_keep = [name] + list(args)\n        self._blocks = OrderedDict((k, v) for k, v in self._blocks.items() if k in to_keep)\n\n    def __setitem__(self, name, block_type):\n        # Create a new class inheriting Block with the elements of the provided one\n        block_type = type('proxyUserBlock', (Block,), dict(block_type.__dict__))\n        self._blocks[name] = block_type(self._conanfile, self._toolchain, name)\n\n    def __getitem__(self, name):\n        return self._blocks[name]\n\n    def process_blocks(self):\n        blocks = self._conanfile.conf.get(\"tools.cmake.cmaketoolchain:enabled_blocks\",\n                                          check_type=list)\n        if blocks is not None:\n            try:\n                new_blocks = OrderedDict((b, self._blocks[b]) for b in blocks)\n            except KeyError as e:\n                raise ConanException(f\"Block {e} defined in tools.cmake.cmaketoolchain\"\n                                     f\":enabled_blocks doesn't exist in {list(self._blocks.keys())}\")\n            self._blocks = new_blocks\n        result = []\n        for b in self._blocks.values():\n            content = b.get_rendered_content()\n            if content:\n                result.append(content)\n        return result\n"
  },
  {
    "path": "conan/tools/cmake/toolchain/toolchain.py",
    "content": "import os\nimport textwrap\nfrom collections import OrderedDict\n\nfrom jinja2 import Template\n\nfrom conan.api.output import ConanOutput\nfrom conan.internal import check_duplicated_generator\nfrom conan.tools.build import use_win_mingw\nfrom conan.tools.cmake.presets import write_cmake_presets\nfrom conan.tools.cmake.toolchain import CONAN_TOOLCHAIN_FILENAME\nfrom conan.tools.cmake.toolchain.blocks import (ExtraVariablesBlock, ToolchainBlocks,\n                                                UserToolchain, GenericSystemBlock,\n                                                AndroidSystemBlock, AppleSystemBlock, FPicBlock,\n                                                ArchitectureBlock, GLibCXXBlock, VSRuntimeBlock,\n                                                CppStdBlock, ParallelBlock, CMakeFlagsInitBlock,\n                                                TryCompileBlock, FindFiles, PkgConfigBlock,\n                                                SkipRPath, SharedLibBock, OutputDirsBlock,\n                                                ExtraFlagsBlock, CompilersBlock, LinkerScriptsBlock,\n                                                VSDebuggerEnvironment, VariablesBlock,\n                                                PreprocessorBlock, RpathLinkFlagsBlock)\nfrom conan.tools.cmake.utils import is_multi_configuration\nfrom conan.tools.env import VirtualBuildEnv, VirtualRunEnv\nfrom conan.tools.intel import IntelCC\nfrom conan.tools.microsoft import VCVars\nfrom conan.tools.microsoft.visual import vs_ide_version\nfrom conan.errors import ConanException\nfrom conan.internal.model.options import _PackageOption\nfrom conan.internal.graph.graph import RECIPE_CONSUMER, RECIPE_EDITABLE\nfrom conan.internal.util.files import save\n\n\nclass Variables(OrderedDict):\n    _configuration_types = None  # Needed for py27 to avoid infinite recursion\n\n    def __init__(self):\n        super(Variables, self).__init__()\n        self._configuration_types = {}\n\n    def __getattribute__(self, config):\n        try:\n            return super(Variables, self).__getattribute__(config)\n        except AttributeError:\n            return self._configuration_types.setdefault(config, OrderedDict())\n\n    @property\n    def configuration_types(self):\n        # Reverse index for the configuration_types variables\n        ret = OrderedDict()\n        for conf, definitions in self._configuration_types.items():\n            for k, v in definitions.items():\n                ret.setdefault(k, []).append((conf, v))\n        return ret\n\n    def quote_preprocessor_strings(self):\n        for key, var in self.items():\n            if isinstance(var, str):\n                self[key] = str(var).replace('\"', '\\\\\"')\n        for config, data in self._configuration_types.items():\n            for key, var in data.items():\n                if isinstance(var, str):\n                    data[key] = str(var).replace('\"', '\\\\\"')\n\n\nclass CMakeToolchain:\n\n    filename = CONAN_TOOLCHAIN_FILENAME\n\n    _template = textwrap.dedent(\"\"\"\\\n        # Conan automatically generated toolchain file\n        # DO NOT EDIT MANUALLY, it will be overwritten\n\n        # Avoid including toolchain file several times (bad if appending to variables like\n        #   CMAKE_CXX_FLAGS. See https://github.com/android/ndk/issues/323\n        include_guard()\n        message(STATUS \"Using Conan toolchain: ${CMAKE_CURRENT_LIST_FILE}\")\n        if(${CMAKE_VERSION} VERSION_LESS \"3.15\")\n            message(FATAL_ERROR \"The 'CMakeToolchain' generator only works with CMake >= 3.15\")\n        endif()\n\n        {% for conan_block in conan_blocks %}\n        {{ conan_block }}\n        {% endfor %}\n\n        if(CMAKE_POLICY_DEFAULT_CMP0091)  # Avoid unused and not-initialized warnings\n        endif()\n        \"\"\")\n\n    def __init__(self, conanfile, generator=None):\n        self._conanfile = conanfile\n        self.generator = self._get_generator(generator)\n        self.variables = Variables()\n        # This doesn't support multi-config, they go to the same configPreset common in multi-config\n        self.cache_variables = {}\n        self.preprocessor_definitions = Variables()\n\n        self.extra_cxxflags = []\n        self.extra_cflags = []\n        self.extra_sharedlinkflags = []\n        self.extra_exelinkflags = []\n        self.add_rpath_link = False\n\n        self.blocks = ToolchainBlocks(self._conanfile, self,\n                                      [(\"user_toolchain\", UserToolchain),\n                                       (\"generic_system\", GenericSystemBlock),\n                                       (\"compilers\", CompilersBlock),\n                                       (\"android_system\", AndroidSystemBlock),\n                                       (\"apple_system\", AppleSystemBlock),\n                                       (\"fpic\", FPicBlock),\n                                       (\"arch_flags\", ArchitectureBlock),\n                                       (\"linker_scripts\", LinkerScriptsBlock),\n                                       (\"rpath_link_flags\", RpathLinkFlagsBlock),\n                                       (\"libcxx\", GLibCXXBlock),\n                                       (\"vs_runtime\", VSRuntimeBlock),\n                                       (\"vs_debugger_environment\", VSDebuggerEnvironment),\n                                       (\"cppstd\", CppStdBlock),\n                                       (\"parallel\", ParallelBlock),\n                                       (\"extra_flags\", ExtraFlagsBlock),\n                                       (\"cmake_flags_init\", CMakeFlagsInitBlock),\n                                       (\"extra_variables\", ExtraVariablesBlock),\n                                       (\"try_compile\", TryCompileBlock),\n                                       (\"find_paths\", FindFiles),\n                                       (\"pkg_config\", PkgConfigBlock),\n                                       (\"rpath\", SkipRPath),\n                                       (\"shared\", SharedLibBock),\n                                       (\"output_dirs\", OutputDirsBlock),\n                                       (\"variables\", VariablesBlock),\n                                       (\"preprocessor\", PreprocessorBlock)])\n\n        # Set the CMAKE_MODULE_PATH and CMAKE_PREFIX_PATH to the deps .builddirs\n        self.find_builddirs = True\n        self.user_presets_path = \"CMakeUserPresets.json\"\n        self.presets_prefix = \"conan\"\n        self.presets_build_environment = None\n        self.presets_run_environment = None\n        self.absolute_paths = False  # By default use relative paths to toolchain and presets\n\n    def _context(self):\n        \"\"\" Returns dict, the context for the template\n        \"\"\"\n        self.preprocessor_definitions.quote_preprocessor_strings()\n\n        blocks = self.blocks.process_blocks()\n        ctxt_toolchain = {\n\n            \"conan_blocks\": blocks\n        }\n\n        return ctxt_toolchain\n\n    @property\n    def content(self):\n        context = self._context()\n        content = Template(self._template, trim_blocks=True, lstrip_blocks=True,\n                           keep_trailing_newline=True).render(**context)\n        return content\n\n    @property\n    def is_multi_configuration(self):\n        return is_multi_configuration(self.generator)\n\n    def _find_cmake_exe(self):\n        for req in self._conanfile.dependencies.direct_build.values():\n            if req.ref.name == \"cmake\":\n                for bindir in req.cpp_info.bindirs:\n                    cmake_path = os.path.join(bindir, \"cmake\")\n                    cmake_exe_path = os.path.join(bindir, \"cmake.exe\")\n\n                    if os.path.exists(cmake_path):\n                        return cmake_path\n                    elif os.path.exists(cmake_exe_path):\n                        return cmake_exe_path\n\n    def generate(self):\n        \"\"\"\n          This method will save the generated files to the conanfile.generators_folder\n        \"\"\"\n        check_duplicated_generator(self, self._conanfile)\n        toolchain_file = self._conanfile.conf.get(\"tools.cmake.cmaketoolchain:toolchain_file\")\n        if toolchain_file is None:  # The main toolchain file generated only if user dont define\n            toolchain_file = self.filename\n            save(os.path.join(self._conanfile.generators_folder, toolchain_file), self.content)\n            ConanOutput(str(self._conanfile)).info(f\"CMakeToolchain generated: {toolchain_file}\")\n        # If we're using Intel oneAPI, we need to generate the environment file and run it\n        if self._conanfile.settings.get_safe(\"compiler\") == \"intel-cc\":\n            IntelCC(self._conanfile).generate()\n        # Generators like Ninja or NMake requires an active vcvars\n        elif self.generator is not None and \"Visual\" not in self.generator:\n            VCVars(self._conanfile).generate()\n\n        cache_variables = {}\n        for name, value in self.cache_variables.items():\n            if isinstance(value, bool):\n                cache_variables[name] = \"ON\" if value else \"OFF\"\n            elif isinstance(value, _PackageOption):\n                if str(value).lower() in [\"true\", \"false\", \"none\"]:\n                    cache_variables[name] = \"ON\" if bool(value) else \"OFF\"\n                elif str(value).isdigit():\n                    cache_variables[name] = int(value)\n                else:\n                    cache_variables[name] = str(value)\n            else:\n                cache_variables[name] = value\n\n        buildenv, runenv, cmake_executable = None, None, None\n\n        if self._conanfile.conf.get(\"tools.cmake.cmaketoolchain:presets_environment\", default=\"\",\n                                    check_type=str, choices=(\"disabled\", \"\")) != \"disabled\":\n\n            build_env = self.presets_build_environment.vars(self._conanfile) \\\n                if self.presets_build_environment \\\n                else VirtualBuildEnv(self._conanfile, auto_generate=True).vars()\n            run_env = self.presets_run_environment.vars(self._conanfile) \\\n                if self.presets_run_environment \\\n                else VirtualRunEnv(self._conanfile, auto_generate=True).vars()\n\n            buildenv = {name: value for name, value in\n                        build_env.items(variable_reference=\"$penv{{{name}}}\")}\n            runenv = {name: value for name, value in\n                      run_env.items(variable_reference=\"$penv{{{name}}}\")}\n\n            cmake_executable = self._conanfile.conf.get(\"tools.cmake:cmake_program\", None)\n            cmake_executable = cmake_executable or self._find_cmake_exe()\n\n        user_presets = self.user_presets_path\n        try:  # TODO: Refactor this repeated pattern to deduce \"is-consumer\"\n            # The user conf user_presets ONLY applies to dev space, not in the cache\n            if self._conanfile._conan_node.recipe in (RECIPE_CONSUMER, RECIPE_EDITABLE):\n                user_presets = self._conanfile.conf.get(\"tools.cmake.cmaketoolchain:user_presets\",\n                                                        default=self.user_presets_path)\n        except AttributeError:\n            pass\n\n        write_cmake_presets(self._conanfile, toolchain_file, self.generator, cache_variables,\n                            user_presets, self.presets_prefix, buildenv, runenv,\n                            cmake_executable, self.absolute_paths)\n\n    def _get_generator(self, recipe_generator):\n        # Returns the name of the generator to be used by CMake\n        conanfile = self._conanfile\n\n        # Downstream consumer always higher priority\n        generator_conf = conanfile.conf.get(\"tools.cmake.cmaketoolchain:generator\")\n        if generator_conf:\n            return generator_conf\n\n        # second priority: the recipe one:\n        if recipe_generator:\n            return recipe_generator\n\n        # if not defined, deduce automatically the default one\n        compiler = conanfile.settings.get_safe(\"compiler\")\n        compiler_version = conanfile.settings.get_safe(\"compiler.version\")\n\n        cmake_years = {'8': '8 2005',\n                       '9': '9 2008',\n                       '10': '10 2010',\n                       '11': '11 2012',\n                       '12': '12 2013',\n                       '14': '14 2015',\n                       '15': '15 2017',\n                       '16': '16 2019',\n                       '17': '17 2022',\n                       '18': '18 2026'}\n\n        if compiler == \"msvc\":\n            if compiler_version is None:\n                raise ConanException(\"compiler.version must be defined\")\n            vs_version = vs_ide_version(self._conanfile)\n            return \"Visual Studio %s\" % cmake_years[vs_version]\n\n        if use_win_mingw(conanfile):\n            return \"MinGW Makefiles\"\n\n        return \"Unix Makefiles\"\n"
  },
  {
    "path": "conan/tools/cmake/utils.py",
    "content": "from conan.errors import ConanException\n\n\ndef is_multi_configuration(generator):\n    if not generator:\n        return False\n    return \"Visual\" in generator or \"Xcode\" in generator or \"Multi-Config\" in generator\n\n\ndef parse_extra_variable(source, key, value):\n    CMAKE_CACHE_TYPES = [\"BOOL\", \"FILEPATH\", \"PATH\", \"STRING\", \"INTERNAL\"]\n    if isinstance(value, str):\n        return f\"\\\"{value}\\\"\"\n    elif isinstance(value, (int, float)):\n        return value\n    elif isinstance(value, dict):\n        var_value = parse_extra_variable(source, key, value.get(\"value\"))\n        is_force = value.get(\"force\")\n        if is_force:\n            if not isinstance(is_force, bool):\n                raise ConanException(f'{source} \"{key}\" \"force\" must be a boolean')\n        is_cache = value.get(\"cache\")\n        if is_cache:\n            if not isinstance(is_cache, bool):\n                raise ConanException(f'{source} \"{key}\" \"cache\" must be a boolean')\n            var_type = value.get(\"type\")\n            if not var_type:\n                raise ConanException(f'{source} \"{key}\" needs \"type\" defined for cache variable')\n            if var_type not in CMAKE_CACHE_TYPES:\n                raise ConanException(f'{source} \"{key}\" invalid type \"{var_type}\" for cache variable.'\n                                     f' Possible types: {\", \".join(CMAKE_CACHE_TYPES)}')\n            # Set docstring as variable name if not defined\n            docstring = value.get(\"docstring\") or key\n            force_str = \" FORCE\" if is_force else \"\"  # Support python < 3.11\n            return f\"{var_value} CACHE {var_type} \\\"{docstring}\\\"{force_str}\"\n        else:\n            if is_force:\n                raise ConanException(f'{source} \"{key}\" \"force\" is only allowed for cache variables')\n            return var_value\n    raise ConanException(f'{source} \"{key}\" has invalid type. Allowed types: str, int, float, dict,'\n                         f' got {type(value)}')\n\n\ndef cmake_escape_value(v):\n    return v.replace('\\\\', '\\\\\\\\').replace('$', '\\\\$').replace('\"', '\\\\\"')\n"
  },
  {
    "path": "conan/tools/cps/__init__.py",
    "content": "from conan.tools.cps.cps_deps import CPSDeps\n"
  },
  {
    "path": "conan/tools/cps/cps_deps.py",
    "content": "from conan.cps.cps import CPS\nfrom conan.tools.files import save\n\nimport json\nimport os\n\n\nclass CPSDeps:\n    def __init__(self, conanfile):\n        self._conanfile = conanfile\n\n    def _config_name(self):\n        build_vars = [\"settings.compiler\", \"settings.compiler.version\", \"settings.arch\",\n                      \"settings.compiler.cppstd\", \"settings.build_type\", \"options.shared\"]\n        ret = []\n        for s in build_vars:\n            group, var = s.split(\".\", 1)\n            tmp = None\n            if group == \"settings\":\n                tmp = self._conanfile.settings.get_safe(var)\n            elif group == \"options\":\n                value = self._conanfile.options.get_safe(var)\n                if value is not None:\n                    if var == \"shared\":\n                        tmp = \"shared\" if value else \"static\"\n                    else:\n                        tmp = \"{}_{}\".format(var, value)\n            if tmp:\n                ret.append(tmp.lower())\n        return \"-\".join(ret)\n\n    def generate(self):\n        cps_folder = os.path.join(self._conanfile.folders.base_build, \"build\", \"cps\")\n        config_name = self._config_name()\n        folder = os.path.join(cps_folder, config_name, \"cps\")  # CMake wants a \"/cps/\" folder\n        self._conanfile.output.info(f\"[CPSDeps] folder {cps_folder}\")\n        deps = self._conanfile.dependencies.host.items()\n        mapping = {}\n        for _, dep in deps:\n            self._conanfile.output.info(f\"[CPSDeps]: dep {dep.ref.name}\")\n\n            cps_in_package = os.path.join(dep.package_folder, f\"{dep.ref.name}.cps\")\n            if os.path.exists(cps_in_package):\n                mapping[dep.ref.name] = cps_in_package\n                continue\n\n            cps = CPS.from_conan(dep)\n            output_file = cps.save(folder)\n            mapping[dep.ref.name] = output_file\n\n        name = f\"cpsmap-{config_name}.json\"\n        self._conanfile.output.info(f\"Generating CPS mapping file: {name}\")\n        save(self._conanfile, os.path.join(cps_folder, name), json.dumps(mapping, indent=2))\n"
  },
  {
    "path": "conan/tools/env/__init__.py",
    "content": "from conan.tools.env.environment import Environment, create_env_script, register_env_script\nfrom conan.tools.env.virtualbuildenv import VirtualBuildEnv\nfrom conan.tools.env.virtualrunenv import VirtualRunEnv\n"
  },
  {
    "path": "conan/tools/env/environment.py",
    "content": "import os\nimport textwrap\nfrom shlex import quote\nfrom collections import OrderedDict\nfrom contextlib import contextmanager\n\nfrom conan.api.output import ConanOutput\nfrom conan.internal.subsystems import deduce_subsystem, WINDOWS, subsystem_path\nfrom conan.errors import ConanException\nfrom conan.internal.model.recipe_ref import ref_matches\nfrom conan.internal.util.files import save\n\n\nclass _EnvVarPlaceHolder:\n    pass\n\n\ndef environment_wrap_command(conanfile, env_filenames, env_folder, cmd, subsystem=None,\n                             accepted_extensions=None):\n    if not env_filenames:\n        return cmd\n    filenames = [env_filenames] if not isinstance(env_filenames, list) else env_filenames\n    bats, shs, ps1s = [], [], []\n\n    accept = accepted_extensions or (\"ps1\", \"bat\", \"sh\")\n    # TODO: This implemantation is dirty, improve it\n    for f in filenames:\n        f = f if os.path.isabs(f) else os.path.join(env_folder, f)\n        if f.lower().endswith(\".sh\"):\n            if os.path.isfile(f) and \"sh\" in accept:\n                f = subsystem_path(subsystem, f)\n                shs.append(f)\n        elif f.lower().endswith(\".bat\"):\n            if os.path.isfile(f) and \"bat\" in accept:\n                bats.append(f)\n        elif f.lower().endswith(\".ps1\") and \"ps1\" in accept:\n            if os.path.isfile(f):\n                ps1s.append(f)\n        else:  # Simple name like \"conanrunenv\"\n            path_bat = \"{}.bat\".format(f)\n            path_sh = \"{}.sh\".format(f)\n            path_ps1 = \"{}.ps1\".format(f)\n            if os.path.isfile(path_bat) and \"bat\" in accept:\n                bats.append(path_bat)\n            if os.path.isfile(path_ps1) and \"ps1\" in accept:\n                ps1s.append(path_ps1)\n            if os.path.isfile(path_sh) and \"sh\" in accept:\n                path_sh = subsystem_path(subsystem, path_sh)\n                shs.append(path_sh)\n\n    if bool(bats + ps1s) + bool(shs) > 1:\n        raise ConanException(\"Cannot wrap command with different envs,\"\n                             \"{} - {}\".format(bats+ps1s, shs))\n\n    powershell = conanfile.conf.get(\"tools.env.virtualenv:powershell\") or \"powershell.exe\"\n    powershell = \"powershell.exe\" if powershell is True else powershell\n\n    if bats:\n        launchers = \" && \".join('\"{}\"'.format(b) for b in bats)\n        if ps1s:\n            ps1_launchers = f'{powershell} -Command \"' + \" ; \".join('&\\'{}\\''.format(f) for f in ps1s) + '\"'\n            cmd = cmd.replace('\"', r'\\\"')\n            return '{} && {} ; cmd /c \"{}\"'.format(launchers, ps1_launchers, cmd)\n        else:\n            return '{} && {}'.format(launchers, cmd)\n    elif shs:\n        launchers = \" && \".join('. \"{}\"'.format(f) for f in shs)\n        return '{} && {}'.format(launchers, cmd)\n    elif ps1s:\n        ps1_launchers = f'{powershell} -Command \"' + \" ; \".join('&\\'{}\\''.format(f) for f in ps1s) + '\"'\n        cmd = cmd.replace('\"', r'\\\"')\n        return '{} ; cmd /c \"{}\"'.format(ps1_launchers, cmd)\n    else:\n        return cmd\n\n\nclass _EnvValue:\n    def __init__(self, name, value=None, separator=\" \", path=False):\n        self._name = name\n        self._values = [] if value is None else value if isinstance(value, list) else [value]\n        self._path = path\n        self._sep = separator\n\n    def __bool__(self):\n        return bool(self._values)  # Empty means unset\n\n    def dumps(self):\n        result = []\n        path = \"(path)\" if self._path else \"\"\n        sep = f\"(sep={self._sep})\" if self._sep != \" \" and not self._path else \"\"\n        if not self._values:  # Empty means unset\n            result.append(\"{}=!\".format(self._name))\n        elif _EnvVarPlaceHolder in self._values:\n            index = self._values.index(_EnvVarPlaceHolder)\n            for v in reversed(self._values[:index]):  # Reverse to prepend\n                result.append(\"{}=+{}{}{}\".format(self._name, path, sep, v))\n            for v in self._values[index+1:]:\n                result.append(\"{}+={}{}{}\".format(self._name, path, sep, v))\n        else:\n            append = \"\"\n            for v in self._values:\n                result.append(\"{}{}={}{}{}\".format(self._name, append, path, sep, v))\n                append = \"+\"\n        return \"\\n\".join(result)\n\n    def copy(self):\n        return _EnvValue(self._name, self._values, self._sep, self._path)\n\n    @property\n    def is_path(self):\n        return self._path\n\n    def remove(self, value):\n        self._values.remove(value)\n\n    def append(self, value, separator=None):\n        if separator is not None:\n            self._sep = separator\n        if isinstance(value, list):\n            self._values.extend(value)\n        else:\n            self._values.append(value)\n\n    def prepend(self, value, separator=None):\n        if separator is not None:\n            self._sep = separator\n        if isinstance(value, list):\n            self._values = value + self._values\n        else:\n            self._values.insert(0, value)\n\n    def compose_env_value(self, other):\n        \"\"\"\n        :type other: _EnvValue\n        \"\"\"\n        try:\n            index = self._values.index(_EnvVarPlaceHolder)\n        except ValueError:  # It doesn't have placeholder\n            pass\n        else:\n            new_value = self._values[:]  # do a copy\n            new_value[index:index + 1] = other._values  # replace the placeholder\n            self._values = new_value\n\n    def get_str(self, placeholder, subsystem, pathsep, root_path=None, script_path=None):\n        \"\"\"\n        :param subsystem:\n        :param placeholder: a OS dependant string pattern of the previous env-var value like\n        $PATH, %PATH%, et\n        :param pathsep: The path separator, typically ; or :\n        :param root_path: To do a relativize of paths, the base root path to be replaced\n        :param script_path: the replacement instead of the script path\n        :return: a string representation of the env-var value, including the $NAME-like placeholder\n        \"\"\"\n        values = []\n        for v in self._values:\n            if v is _EnvVarPlaceHolder:\n                if placeholder:\n                    values.append(placeholder.format(name=self._name))\n            else:\n                if self._path:\n                    v = subsystem_path(subsystem, v)\n                    if root_path is not None:\n                        if v.startswith(root_path):  # relativize\n                            v = v.replace(root_path, script_path, 1)\n                        elif os.sep == \"\\\\\":  # Just in case user specified C:/path/to/somewhere\n                            r = root_path.replace(\"\\\\\", \"/\")\n                            if v.startswith(r):\n                                v = v.replace(r, script_path.replace(\"\\\\\", \"/\"))\n                values.append(v)\n        if self._path:\n            return pathsep.join(values)\n\n        return self._sep.join(values)\n\n    def get_value(self, subsystem, pathsep):\n        previous_value = os.getenv(self._name)\n        return self.get_str(previous_value, subsystem, pathsep)\n\n    def deploy_base_folder(self, package_folder, deploy_folder):\n        \"\"\"Make the path relative to the deploy_folder\"\"\"\n        if not self._path:\n            return\n        for i, v in enumerate(self._values):\n            if v is _EnvVarPlaceHolder:\n                continue\n            rel_path = os.path.relpath(v, package_folder)\n            if rel_path.startswith(\"..\"):\n                # If it is pointing to a folder outside of the package, then do not relocate\n                continue\n            self._values[i] = os.path.join(deploy_folder, rel_path)\n\n    def set_relative_base_folder(self, folder):\n        if not self._path:\n            return\n        self._values = [os.path.join(folder, v) if v != _EnvVarPlaceHolder else v\n                        for v in self._values]\n\n\nclass Environment:\n    \"\"\"\n    Generic class that helps to define modifications to the environment variables.\n    \"\"\"\n\n    def __init__(self):\n        # It being ordered allows for Windows case-insensitive composition\n        self._values = OrderedDict()  # {var_name: [] of values, including separators}\n\n    def __bool__(self):\n        return bool(self._values)\n\n    def copy(self):\n        e = Environment()\n        for k, v in self._values.items():\n            e._values[k] = v.copy()\n        return e\n\n    def __repr__(self):\n        return repr(self._values)\n\n    def dumps(self):\n\n        \"\"\"\n        :return: A string with a profile-like original definition, not the full environment\n                 values\n        \"\"\"\n        return \"\\n\".join([v.dumps() for v in reversed(self._values.values())])\n\n    def define(self, name, value, separator=\" \"):\n        \"\"\"\n        Define `name` environment variable with value `value`\n\n        :param name: Name of the variable\n        :param value: Value that the environment variable will take\n        :param separator: The character to separate appended or prepended values\n        \"\"\"\n        self._values[name] = _EnvValue(name, value, separator, path=False)\n\n    def define_path(self, name, value):\n        self._values[name] = _EnvValue(name, value, path=True)\n\n    def unset(self, name):\n        \"\"\"\n        clears the variable, equivalent to a unset or set XXX=\n\n        :param name: Name of the variable to unset\n        \"\"\"\n        self._values[name] = _EnvValue(name, None)\n\n    def append(self, name, value, separator=None):\n        \"\"\"\n        Append the `value` to an environment variable `name`\n\n        :param name: Name of the variable to append a new value\n        :param value: New value\n        :param separator: The character to separate the appended value with the previous value. By default it will use a blank space.\n        \"\"\"\n        self._values.setdefault(name, _EnvValue(name, _EnvVarPlaceHolder)).append(value, separator)\n\n    def append_path(self, name, value):\n        \"\"\"\n        Similar to \"append\" method but indicating that the variable is a filesystem path. It will automatically handle the path separators depending on the operating system.\n\n        :param name: Name of the variable to append a new value\n        :param value: New value\n        \"\"\"\n        self._values.setdefault(name, _EnvValue(name, _EnvVarPlaceHolder, path=True)).append(value)\n\n    def prepend(self, name, value, separator=None):\n        \"\"\"\n        Prepend the `value` to an environment variable `name`\n\n        :param name: Name of the variable to prepend a new value\n        :param value: New value\n        :param separator: The character to separate the prepended value with the previous value\n        \"\"\"\n        self._values.setdefault(name, _EnvValue(name, _EnvVarPlaceHolder)).prepend(value, separator)\n\n    def prepend_path(self, name, value):\n        \"\"\"\n        Similar to \"prepend\" method but indicating that the variable is a filesystem path. It will automatically handle the path separators depending on the operating system.\n\n        :param name: Name of the variable to prepend a new value\n        :param value: New value\n        \"\"\"\n        self._values.setdefault(name, _EnvValue(name, _EnvVarPlaceHolder, path=True)).prepend(value)\n\n    def remove(self, name, value):\n        \"\"\"\n        Removes the `value` from the variable `name`.\n\n        :param name: Name of the variable\n        :param value: Value to be removed.\n        \"\"\"\n        self._values[name].remove(value)\n\n    def compose_env(self, other):\n        \"\"\"\n        Compose an Environment object with another one.\n        ``self`` has precedence, the \"other\" will add/append if possible and not\n        conflicting, but ``self`` mandates what to do. If ``self`` has ``define()``, without\n        placeholder, that will remain.\n\n        :param other: the \"other\" Environment\n        :type other: class:`Environment`\n        \"\"\"\n        for k, v in other._values.items():\n            existing = self._values.get(k)\n            if existing is None:\n                self._values[k] = v.copy()\n            else:\n                existing.compose_env_value(v)\n\n        return self\n\n    def __eq__(self, other):\n        \"\"\"\n        :param other: the \"other\" environment\n        :type other: class:`Environment`\n        \"\"\"\n        return other._values == self._values\n\n    def vars(self, conanfile, scope=\"build\"):\n        \"\"\"\n        :param conanfile: Instance of a conanfile, usually ``self`` in a recipe\n        :param scope: Determine the scope of the declared variables.\n        :return: An EnvVars object from the current Environment object\n        \"\"\"\n        return EnvVars(conanfile, self._values, scope)\n\n    def deploy_base_folder(self, package_folder, deploy_folder):\n        \"\"\"Make the paths relative to the deploy_folder\"\"\"\n        for varvalues in self._values.values():\n            varvalues.deploy_base_folder(package_folder, deploy_folder)\n\n    def set_relative_base_folder(self, folder):\n        for v in self._values.values():\n            v.set_relative_base_folder(folder)\n\n\nclass EnvVars:\n    \"\"\"\n    Represents an instance of environment variables for a given system. It is obtained from the generic Environment class.\n\n    \"\"\"\n    def __init__(self, conanfile, values, scope):\n        self._values = values  # {var_name: _EnvValue}, just a reference to the Environment\n        self._conanfile = conanfile\n        self._scope = scope\n        self._subsystem = deduce_subsystem(conanfile, scope)\n        self._deactivation_mode = conanfile.conf.get(\"tools.env:deactivation_mode\", default=None, check_type=str)\n\n    @property\n    def _pathsep(self):\n        return \":\" if self._subsystem != WINDOWS else \";\"\n\n    def __getitem__(self, name):\n        return self._values[name].get_value(self._subsystem, self._pathsep)\n\n    def keys(self):\n        return self._values.keys()\n\n    def get(self, name, default=None, variable_reference=None):\n        \"\"\" get the value of a env-var\n\n        :param name: The name of the environment variable.\n        :param default: The returned value if the variable doesn't exist, by default None.\n        :param variable_reference: if specified, use a variable reference instead of the\n                                   pre-existing value of environment variable, where {name}\n                                   can be used to refer to the name of the variable.\n        \"\"\"\n        v = self._values.get(name)\n        if v is None:\n            return default\n        if variable_reference:\n            return v.get_str(variable_reference, self._subsystem, self._pathsep)\n        else:\n            return v.get_value(self._subsystem, self._pathsep)\n\n    def items(self, variable_reference=None):\n        \"\"\"returns {str: str} (varname: value)\n\n        :param variable_reference: if specified, use a variable reference instead of the\n                                   pre-existing value of environment variable, where {name}\n                                   can be used to refer to the name of the variable.\n        \"\"\"\n        if variable_reference:\n            return {k: v.get_str(variable_reference, self._subsystem, self._pathsep)\n                    for k, v in self._values.items()}.items()\n        else:\n            return {k: v.get_value(self._subsystem, self._pathsep)\n                    for k, v in self._values.items()}.items()\n\n    @contextmanager\n    def apply(self):\n        \"\"\"\n        Context manager to apply the declared variables to the current ``os.environ`` restoring\n        the original environment when the context ends.\n\n        \"\"\"\n        apply_vars = self.items()\n        old_env = dict(os.environ)\n        os.environ.update(apply_vars)\n        try:\n            yield\n        finally:\n            os.environ.clear()\n            os.environ.update(old_env)\n\n    def save_dotenv(self, file_location):\n        result = []\n        for varname, varvalues in self._values.items():\n            value = varvalues.get_value(subsystem=self._subsystem, pathsep=self._pathsep)\n            result.append('{}=\"{}\"'.format(varname, value))\n        content = \"\\n\".join(result)\n        save(file_location, content)\n\n    def save_bat(self, file_location, generate_deactivate=True):\n        _, filename = os.path.split(file_location)\n        deactivate_file = \"deactivate_{}\".format(filename)\n        is_function = self._deactivation_mode == \"function\"\n        deactivates_variable = f\"_CONAN_{self._scope}_DEACTIVATES_DIR\"\n        dest_variable = f\"%{deactivates_variable}%\" if is_function else \"%~dp0\"\n\n        function_preamble = textwrap.dedent(f\"\"\"\n            set \"local_defined=0\"\n            if defined {deactivates_variable} goto skip_deactivate_variable\n\n            set \"local_defined=1\"\n            set \"{deactivates_variable}=%TEMP%\\\\conan_{self._scope}_%RANDOM%\"\n            mkdir \"%{deactivates_variable}%\"\n            set \"PATH=%{deactivates_variable}%;%PATH%\"\n\n            :skip_deactivate_variable\n        \"\"\") if is_function else \"\"\n\n        function_epilogue = textwrap.dedent(f\"\"\"\n            if %local_defined% == 0 goto end\n            echo set \"PATH=%%PATH:%{deactivates_variable}%;=%%\" >> \"{dest_variable}/{deactivate_file}\"\n            echo set \"{deactivates_variable}=\">> \"{dest_variable}/{deactivate_file}\"\n            :end\n        \"\"\") if is_function else \"\"\n\n        variables = \" \".join(self._values.keys())\n\n        deactivate = textwrap.dedent(f\"\"\"\\\n            @echo off\n            {function_preamble}\n\n            setlocal\n            echo @echo off > \"{dest_variable}/{deactivate_file}\"\n            echo echo Restoring environment for {filename} >> \"{dest_variable}/{deactivate_file}\"\n            for %%v in ({variables}) do (\n                set foundenvvar=\n                for /f \"delims== tokens=1,2\" %%a in ('set') do (\n                    if /I \"%%a\" == \"%%v\" (\n                        echo set \"%%a=%%b\">> \"{dest_variable}/{deactivate_file}\"\n                        set foundenvvar=1\n                    )\n                )\n                if not defined foundenvvar (\n                    echo set %%v=>> \"{dest_variable}/{deactivate_file}\"\n                )\n            )\n            endlocal\n\n            {function_epilogue}\n            \"\"\")\n        capture = textwrap.dedent(\"\"\"\\\n            @echo off\n            chcp 65001 > nul\n            {deactivate}\n            \"\"\").format(deactivate=deactivate if generate_deactivate else \"\")\n        result = [capture]\n        abs_base_path, new_path = _relativize_paths(self._conanfile, \"%~dp0\")\n        for varname, varvalues in self._values.items():\n            value = varvalues.get_str(\"%{name}%\", subsystem=self._subsystem, pathsep=self._pathsep,\n                                      root_path=abs_base_path, script_path=new_path)\n            no_value = varvalues.get_str(\"\", subsystem=self._subsystem, pathsep=self._pathsep,\n                                         root_path=abs_base_path, script_path=new_path)\n            if value != no_value:\n                set_value = textwrap.dedent(f\"\"\"\\\n                    if defined {varname} (\n                        set \"{varname}={value}\"\n                    ) else (\n                        set \"{varname}={no_value}\"\n                    )\"\"\")\n            else:\n                set_value = f'set \"{varname}={value}\"'\n            result.append(set_value)\n\n        content = \"\\n\".join(result)\n        # It is very important to save it correctly with utf-8, the Conan util save() is broken\n        os.makedirs(os.path.dirname(os.path.abspath(file_location)), exist_ok=True)\n        with open(file_location, \"w\", encoding=\"utf-8\") as f:\n            f.write(content)\n\n    def save_ps1(self, file_location, generate_deactivate=True):\n        _, filename = os.path.split(file_location)\n\n        result = []\n        if generate_deactivate:\n            result.append(_ps1_deactivate_contents(self._deactivation_mode, self._values, filename))\n        abs_base_path, new_path = _relativize_paths(self._conanfile, \"$PSScriptRoot\")\n        for varname, varvalues in self._values.items():\n            value = varvalues.get_str(\"$env:{name}\", subsystem=self._subsystem, pathsep=self._pathsep,\n                                      root_path=abs_base_path, script_path=new_path)\n            no_value = varvalues.get_str(\"\", subsystem=self._subsystem, pathsep=self._pathsep,\n                                         root_path=abs_base_path, script_path=new_path)\n            if generate_deactivate and self._deactivation_mode == \"function\":\n                # Check environment variable existence before saving value\n                result.append(\n                    f'if ($env:{varname}) {{ $env:{_old_env_prefix(filename)}_{varname} = $env:{varname} }}'\n                )\n            if varvalues:\n                value = value.replace('\"', '`\"')  # escape quotes\n                no_value = no_value.replace('\"', '`\"')  # escape quotes\n\n                if value != no_value:\n                    set_value = textwrap.dedent(f\"\"\"\\\n                       if ($env:{varname}) {{\n                           $env:{varname}=\"{value}\"\n                       }} else {{\n                           $env:{varname}=\"{no_value}\"\n                       }}\n                       \"\"\")\n                else:\n                    set_value = f'$env:{varname}=\"{value}\"'\n                result.append(set_value)\n            else:\n                result.append('if (Test-Path env:{0}) {{ Remove-Item env:{0} }}'.format(varname))\n\n        content = \"\\n\".join(result)\n        # It is very important to save it correctly with utf-16, the Conan util save() is broken\n        # and powershell uses utf-16 files!!!\n        os.makedirs(os.path.dirname(os.path.abspath(file_location)), exist_ok=True)\n        with open(file_location, \"w\", encoding=\"utf-16\") as f:\n            f.write(content)\n\n    def save_sh(self, file_location, generate_deactivate=True):\n        filepath, filename = os.path.split(file_location)\n        result = []\n        if generate_deactivate:\n            result.append(_sh_deactivate_contents(self._deactivation_mode, self._values, filename))\n        abs_base_path, new_path = _relativize_paths(self._conanfile, \"$script_folder\")\n        for varname, varvalues in self._values.items():\n            value = varvalues.get_str(\"${name}\", self._subsystem, pathsep=self._pathsep,\n                                      root_path=abs_base_path, script_path=new_path)\n            placeholder = f\"${varname}\"\n            sep = self._pathsep if varvalues._path else varvalues._sep  # noqa\n            if value.endswith(sep + placeholder):\n                value = value.replace(sep + placeholder, f\"${{{varname}:+{sep}${varname}}}\", 1)\n            elif (placeholder + sep) in value:\n                value = value.replace(placeholder + sep, f\"${{{varname}:-}}${{{varname}:+{sep}}}\", 1)\n            value = value.replace('\"', '\\\\\"')\n            if generate_deactivate and self._deactivation_mode == \"function\":\n                # Check environment variable existence before saving value\n                result.append(\n                    f'if [ -n \"${{{varname}+x}}\" ]; then '\n                    f'export {_old_env_prefix(filename)}_{varname}=\"${{{varname}}}\"; '\n                    f'fi;'\n                )\n            if varvalues:\n                result.append(f'export {varname}=\"{value}\"')\n            else:\n                result.append(f'unset {varname}')\n\n        content = \"\\n\".join(result)\n        content = f'script_folder=\"{os.path.abspath(filepath)}\"\\n' + content\n        save(file_location, content)\n\n    def save_script(self, filename):\n        \"\"\"\n        Saves a script file (bat, sh, ps1) with a launcher to set the environment.\n        If the conf \"tools.env.virtualenv:powershell\" is not an empty string\n        it will generate powershell\n        launchers if Windows.\n\n        :param filename: Name of the file to generate. If the extension is provided, it will generate\n                         the launcher script for that extension, otherwise the format will be deduced\n                         checking if we are running inside Windows (checking also the subsystem) or not.\n        \"\"\"\n        name, ext = os.path.splitext(filename)\n        if ext:\n            is_bat = ext == \".bat\"\n            is_ps1 = ext == \".ps1\"\n        else:  # Need to deduce it automatically\n            is_bat = self._subsystem == WINDOWS\n            try:\n                is_ps1 = self._conanfile.conf.get(\"tools.env.virtualenv:powershell\", check_type=bool)\n                if is_ps1 is not None:\n                    ConanOutput().warning(\n                        \"Boolean values for 'tools.env.virtualenv:powershell' are deprecated. \"\n                        \"Please specify 'powershell.exe' or 'pwsh' instead, appending arguments if needed \"\n                        \"(for example: 'powershell.exe -argument'). \"\n                        \"To unset this configuration, use `tools.env.virtualenv:powershell=!`, which matches \"\n                        \"the previous 'False' behavior.\",\n                        warn_tag=\"deprecated\"\n                    )\n            except ConanException:\n                is_ps1 = self._conanfile.conf.get(\"tools.env.virtualenv:powershell\", check_type=str)\n            if is_ps1:\n                filename = filename + \".ps1\"\n                is_bat = False\n            else:\n                filename = filename + (\".bat\" if is_bat else \".sh\")\n\n        path = os.path.join(self._conanfile.generators_folder, filename)\n        if is_bat:\n            self.save_bat(path)\n        elif is_ps1:\n            self.save_ps1(path)\n        else:\n            self.save_sh(path)\n\n        if self._conanfile.conf.get(\"tools.env:dotenv\", check_type=bool):\n            bt = self._conanfile.settings.get_safe(\"build_type\")\n            arch = self._conanfile.settings.get_safe(\"arch\")\n            name = name.replace(bt.lower(), bt) if bt else name\n            name = name.replace(arch.lower(), arch) if arch else name\n            ConanOutput().warning(f\"Creating dotenv file: {name}.env\\n\"\n                                  \"Files generated with absolute paths, not interpolated.\\n\"\n                                  \"When https://github.com/microsoft/vscode-cpptools/issues/13781 \"\n                                  \"solved, it will get interpolation\", warn_tag=\"experimental\")\n            self.save_dotenv(f\"{name}.env\")\n\n        if self._scope:\n            register_env_script(self._conanfile, path, self._scope)\n\n\ndef _deactivate_func_name(filename):\n    return os.path.splitext(os.path.basename(filename))[0].replace(\"-\", \"_\")\n\n\ndef _old_env_prefix(filename):\n    return f\"_CONAN_OLD_{_deactivate_func_name(filename).upper()}\"\n\n\ndef _ps1_deactivate_contents(deactivation_mode, values, filename):\n    vars_list = \", \".join(f'\"{v}\"' for v in values.keys())\n    if deactivation_mode == \"function\":\n        var_prefix = _old_env_prefix(filename)\n        func_name = _deactivate_func_name(filename)\n        return textwrap.dedent(f\"\"\"\\\n            function global:deactivate_{func_name} {{\n                Write-Host \"Restoring environment\"\n                foreach ($v in @({vars_list})) {{\n                    $oldVarName = \"{var_prefix}_$v\"\n                    $oldValue = Get-Item -Path \"Env:$oldVarName\" -ErrorAction SilentlyContinue\n                    if (Test-Path env:$oldValue) {{\n                        Remove-Item -Path \"Env:$v\" -ErrorAction SilentlyContinue\n                    }} else {{\n                        Set-Item -Path \"Env:$v\" -Value $oldValue.Value\n                    }}\n                    Remove-Item -Path \"Env:$oldVarName\" -ErrorAction SilentlyContinue\n                }}\n                Remove-Item -Path function:deactivate_{func_name} -ErrorAction SilentlyContinue\n            }}\n        \"\"\")\n\n    deactivate_file = \"deactivate_{}\".format(filename)\n    return textwrap.dedent(f\"\"\"\\\n        Push-Location $PSScriptRoot\n        \"echo `\"Restoring environment`\"\" | Out-File -FilePath \"{deactivate_file}\"\n        $vars = (Get-ChildItem env:*).name\n        $updated_vars = @({vars_list})\n\n        foreach ($var in $updated_vars)\n        {{\n            if ($var -in $vars)\n            {{\n                $var_value = (Get-ChildItem env:$var).value\n                Add-Content \"{deactivate_file}\" \"`n`$env:$var = `\"$var_value`\"\"\n            }}\n            else\n            {{\n                Add-Content \"{deactivate_file}\" \"`nif (Test-Path env:$var) {{ Remove-Item env:$var }}\"\n            }}\n        }}\n        Pop-Location\n    \"\"\")\n\n\ndef _sh_deactivate_contents(deactivation_mode, values, filename):\n    vars_list = \" \".join(quote(v) for v in values.keys())\n    if deactivation_mode == \"function\":\n        func_name = _deactivate_func_name(filename)\n        return textwrap.dedent(f\"\"\"\\\n            # sh-like function to restore environment\n            deactivate_{func_name} () {{\n                echo \"Restoring environment\"\n                for v in {vars_list}; do\n                    old_var=\"{_old_env_prefix(filename)}_${{v}}\"\n                    # Use eval for indirect expansion (POSIX safe)\n                    eval \"is_set=\\\\${{${{old_var}}+x}}\"\n                    if [ -n \"${{is_set}}\" ]; then\n                        eval \"old_value=\\\\${{${{old_var}}}}\"\n                        eval \"export ${{v}}=\\\\${{old_value}}\"\n                    else\n                        unset \"${{v}}\"\n                    fi\n                    unset \"${{old_var}}\"\n                done\n                unset -f deactivate_{func_name}\n            }}\n        \"\"\")\n    deactivate_file = os.path.join(\"$script_folder\", \"deactivate_{}\".format(filename))\n    return textwrap.dedent(f\"\"\"\\\n        echo \"echo Restoring environment\" > \"{deactivate_file}\"\n        for v in {vars_list}\n        do\n           is_defined=\"true\"\n           value=$(printenv $v) || is_defined=\"\" || true\n           if [ -n \"$value\" ] || [ -n \"$is_defined\" ]\n           then\n               echo export \"$v='$value'\" >> \"{deactivate_file}\"\n           else\n               echo unset $v >> \"{deactivate_file}\"\n           fi\n        done\n    \"\"\")\n\n\nclass ProfileEnvironment:\n    def __init__(self):\n        self._environments = OrderedDict()\n\n    def __repr__(self):\n        return repr(self._environments)\n\n    def __bool__(self):\n        return bool(self._environments)\n\n    def get_profile_env(self, ref, is_consumer=False):\n        \"\"\" computes package-specific Environment\n        it is only called when conanfile.buildenv is called\n        the last one found in the profile file has top priority\n        \"\"\"\n        result = Environment()\n        for pattern, env in self._environments.items():\n            if pattern is None or ref_matches(ref, pattern, is_consumer):\n                # Latest declared has priority, copy() necessary to not destroy data\n                result = env.copy().compose_env(result)\n        return result\n\n    def update_profile_env(self, other):\n        \"\"\"\n        :type other: ProfileEnvironment\n        :param other: The argument profile has priority/precedence over the current one.\n        \"\"\"\n        for pattern, environment in other._environments.items():\n            existing = self._environments.get(pattern)\n            if existing is not None:\n                self._environments[pattern] = environment.compose_env(existing)\n            else:\n                self._environments[pattern] = environment\n\n    def dumps(self):\n        result = []\n        for pattern, env in self._environments.items():\n            if pattern is None:\n                result.append(env.dumps())\n            else:\n                result.append(\"\\n\".join(\"{}:{}\".format(pattern, line) if line else \"\"\n                                        for line in env.dumps().splitlines()))\n        if result:\n            result.append(\"\")\n        return \"\\n\".join(result)\n\n    @staticmethod\n    def loads(text):\n        result = ProfileEnvironment()\n        for line in text.splitlines():\n            line = line.strip()\n            if not line or line.startswith(\"#\"):\n                continue\n            for op, method in ((\"+=\", \"append\"), (\"=+\", \"prepend\"),\n                               (\"=!\", \"unset\"), (\"=\", \"define\")):\n                tokens = line.split(op, 1)\n                if len(tokens) != 2:\n                    continue\n                pattern_name, value = tokens\n                pattern_name = pattern_name.split(\":\", 1)\n                if len(pattern_name) == 2:\n                    pattern, name = pattern_name\n                else:\n                    pattern, name = None, pattern_name[0]\n\n                # strip whitespaces before/after =\n                # values are not strip() unless they are a path, to preserve potential whitespaces\n                name = name.strip()\n\n                # When loading from profile file, latest line has priority\n                env = Environment()\n                if method == \"unset\":\n                    env.unset(name)\n                elif value.strip().startswith(\"(sep=\"):\n                    value = value.strip()\n                    sep = value[5]\n                    value = value[7:]\n                    if value.strip().startswith(\"(path)\"):\n                        msg = f\"Cannot use (sep) and (path) qualifiers simultaneously: {line}\"\n                        raise ConanException(msg)\n                    getattr(env, method)(name, value, separator=sep)\n                else:\n                    if value.strip().startswith(\"(path)\"):\n                        value = value.strip()\n                        value = value[6:]\n                        method = method + \"_path\"\n                    getattr(env, method)(name, value)\n\n                existing = result._environments.get(pattern)\n                if existing is None:\n                    result._environments[pattern] = env\n                else:\n                    result._environments[pattern] = env.compose_env(existing)\n                break\n            else:\n                raise ConanException(\"Bad env definition: {}\".format(line))\n        return result\n\n\ndef create_env_script(conanfile, content, filename, scope=\"build\"):\n    \"\"\"\n    Create a file with any content which will be registered as a new script for the defined \"scope\".\n\n    Args:\n        conanfile: The Conanfile instance.\n        content (str): The content of the script to write into the file.\n        filename (str): The name of the file to be created in the generators folder.\n        scope (str): The scope or environment group for which the script will be registered.\n    \"\"\"\n    path = os.path.join(conanfile.generators_folder, filename)\n    save(path, content)\n\n    if scope:\n        register_env_script(conanfile, path, scope)\n\n\ndef register_env_script(conanfile, env_script_path, scope=\"build\"):\n    \"\"\"\n    Add the \"env_script_path\" to the current list of registered scripts for defined \"scope\"\n    These will be mapped to files:\n    - conan{group}.bat|sh = calls env_script_path1,... env_script_pathN\n\n    Args:\n        conanfile: The Conanfile instance.\n        env_script_path (str): The full path of the script to register.\n        scope (str): The scope ('build' or 'host') for which the script will be registered.\n    \"\"\"\n    existing = conanfile.env_scripts.setdefault(scope, [])\n    if env_script_path not in existing:\n        existing.append(env_script_path)\n\n\ndef generate_aggregated_env(conanfile):\n\n    def deactivates(filenames):\n        # FIXME: Probably the order needs to be reversed\n        result = []\n        for s in reversed(filenames):\n            folder, f = os.path.split(s)\n            result.append(os.path.join(folder, \"deactivate_{}\".format(f)))\n        return result\n\n    def deactivate_function_names(filenames):\n        return [os.path.splitext(os.path.basename(s))[0].replace(\"-\", \"_\")\n                for s in reversed(filenames)]\n\n    deactivation_mode = conanfile.conf.get(\"tools.env:deactivation_mode\", default=None, check_type=str)\n    generated = []\n    for group, env_scripts in conanfile.env_scripts.items():\n        subsystem = deduce_subsystem(conanfile, group)\n        bats = []\n        shs = []\n        ps1s = []\n        for env_script in env_scripts:\n            path = os.path.join(conanfile.generators_folder, env_script)\n            # Only the .bat and .ps1 are made relative to current script\n            if env_script.endswith(\".bat\"):\n                path = os.path.relpath(path, conanfile.generators_folder)\n                bats.append(\"%~dp0/\"+path)\n            elif env_script.endswith(\".sh\"):\n                shs.append(subsystem_path(subsystem, path))\n            elif env_script.endswith(\".ps1\"):\n                path = os.path.relpath(path, conanfile.generators_folder)\n                # This $PSScriptRoot uses the current script directory\n                ps1s.append(\"$PSScriptRoot/\"+path)\n        if shs:\n            def sh_content(files):\n                content = \". \" + \" && . \".join('\"{}\"'.format(s) for s in files)\n                if deactivation_mode == \"function\":\n                    content += f\"\\n\\ndeactivate_conan{group}() {{\\n\"\n                    for deactivate_name in deactivate_function_names(shs):\n                        content += f\"    deactivate_{deactivate_name}\\n\"\n                    content += f\"    unset -f deactivate_conan{group}\\n}}\\n\"\n                return content\n            filename = \"conan{}.sh\".format(group)\n            generated.append(filename)\n            save(os.path.join(conanfile.generators_folder, filename), sh_content(shs))\n            if not deactivation_mode:\n                save(os.path.join(conanfile.generators_folder, \"deactivate_{}\".format(filename)),\n                     sh_content(deactivates(shs)))\n        if bats:\n            filename = f\"conan{group}.bat\"\n            deactivate_filename = f\"deactivate_{filename}\"\n\n            def bat_content(files):\n                content = [\"@echo off\"]\n\n                if deactivation_mode == \"function\":\n                    from conan.tools.microsoft.visual import CONAN_VCVARS\n                    deactivates_var = f\"_CONAN_{group}_DEACTIVATES_DIR\"\n                    content += [\n                        f'set \"{deactivates_var}=%TEMP%\\\\conan_{group}_%RANDOM%\"',\n                        f'mkdir \"%{deactivates_var}%\"'\n                    ]\n                    # TODO: Find a better way to get rid of vcvars deactivation\n                    f = [f for f in files if f != f\"%~dp0/{CONAN_VCVARS}.bat\"]\n                    deactivate_filenames = [f.replace(\"%~dp0\\\\\", \"\")\n                                            for f in deactivates(f)]\n\n                    content += [f'set PATH=%{deactivates_var}%;%PATH%']\n                    content += [f'echo @echo off > \"%{deactivates_var}%\\\\{deactivate_filename}\"']\n                    content += [f'echo call \"{b}\" >> \"%{deactivates_var}%\\\\{deactivate_filename}\"'\n                                for b in deactivate_filenames]\n                    # See https://ss64.com/nt/syntax-replace.html for the syntax below to remove\n                    # the deactivation path from PATH when the deactivation script is called\n                    content += [f'echo set \"PATH=%%PATH:%{deactivates_var}%;=%%\" >> '\n                                f'\"%{deactivates_var}%\\\\{deactivate_filename}\"']\n                    content += [f'echo set \"{deactivates_var}=\" >> '\n                                f'\"%{deactivates_var}%\\\\{deactivate_filename}\"']\n\n                content += [f'call \"{b}\"' for b in files]\n\n                return \"\\r\\n\".join(content)\n\n            generated.append(filename)\n            save(os.path.join(conanfile.generators_folder, filename), bat_content(bats))\n            if not deactivation_mode:\n                save(os.path.join(conanfile.generators_folder, deactivate_filename),\n                     bat_content(deactivates(bats)))\n\n        if ps1s:\n            def ps1_content(files):\n                content = \"\\r\\n\".join(['& \"{}\"'.format(b) for b in files])\n                if deactivation_mode == \"function\":\n                    content += f\"\\n\\nfunction global:deactivate_conan{group} {{\\n\"\n                    for deactivate_name in deactivate_function_names(ps1s):\n                        content += f\"    deactivate_{deactivate_name}\\n\"\n                    content += (f\"    Remove-Item -Path function:deactivate_conan{group} \"\n                                \"-ErrorAction SilentlyContinue\"\n                                \"\\n}\\n\")\n                return content\n            filename = \"conan{}.ps1\".format(group)\n            generated.append(filename)\n            save(os.path.join(conanfile.generators_folder, filename), ps1_content(ps1s))\n            if not deactivation_mode:\n                save(os.path.join(conanfile.generators_folder, \"deactivate_{}\".format(filename)),\n                     ps1_content(deactivates(ps1s)))\n    if generated:\n        conanfile.output.highlight(\"Generating aggregated env files\")\n        conanfile.output.info(f\"Generated aggregated env files: {generated}\")\n\n\ndef _relativize_paths(conanfile, placeholder):\n    abs_base_path = conanfile.folders._base_generators  # noqa\n    if not abs_base_path or not os.path.isabs(abs_base_path):\n        return None, None\n    abs_base_path = os.path.join(abs_base_path, \"\")  # For the trailing / to dissambiguate matches\n    generators_folder = conanfile.generators_folder\n    try:\n        rel_path = os.path.relpath(abs_base_path, generators_folder)\n    except ValueError:  # In case the unit in Windows is different, path cannot be made relative\n        return None, None\n    new_path = placeholder if rel_path == \".\" else os.path.join(placeholder, rel_path)\n    new_path = os.path.join(new_path, \"\")  # For the trailing / to dissambiguate matches\n    return abs_base_path, new_path\n"
  },
  {
    "path": "conan/tools/env/virtualbuildenv.py",
    "content": "from conan.internal import check_duplicated_generator\nfrom conan.tools.env import Environment\nfrom conan.tools.env.virtualrunenv import runenv_from_cpp_info\n\n\nclass VirtualBuildEnv:\n    \"\"\" Calculates the environment variables of the build time context and produces a conanbuildenv\n        .bat or .sh script\n    \"\"\"\n\n    def __init__(self, conanfile, auto_generate=False):\n        self._buildenv = None\n        self._conanfile = conanfile\n        if not auto_generate:\n            self._conanfile.virtualbuildenv = False\n        self.basename = \"conanbuildenv\"\n        self.configuration = None\n        self.arch = None\n\n    @property\n    def _filename(self):\n        if not self.configuration:\n            # TODO: Make this use the settings_build\n            configuration = self._conanfile.settings.get_safe(\"build_type\")\n            configuration = configuration.lower() if configuration else None\n        else:\n            configuration = self.configuration\n        if not self.arch:\n            arch = self._conanfile.settings.get_safe(\"arch\")\n            arch = arch.lower() if arch else None\n        else:\n            arch = self.arch\n        f = self.basename\n        if configuration:\n            f += \"-\" + configuration.replace(\".\", \"_\")\n        if arch:\n            f += \"-\" + arch.replace(\".\", \"_\").replace(\"|\", \"_\")\n        return f\n\n    def environment(self):\n        \"\"\"\n        Returns an ``Environment`` object containing the environment variables of the build context.\n\n        :return: an ``Environment`` object instance containing the obtained variables.\n        \"\"\"\n\n        if self._buildenv is None:\n            self._buildenv = Environment()\n        else:\n            return self._buildenv\n\n        # Top priority: profile\n        profile_env = self._conanfile.buildenv\n        self._buildenv.compose_env(profile_env)\n\n        build_requires = self._conanfile.dependencies.build.topological_sort\n        for require, build_require in reversed(build_requires.items()):\n            if require.direct:  # Only buildenv_info from direct deps is propagated\n                # higher priority, explicit buildenv_info\n                if build_require.buildenv_info:\n                    self._buildenv.compose_env(build_require.buildenv_info)\n            # Lower priority, the runenv of all transitive \"requires\" of the build requires\n            if build_require.runenv_info:\n                self._buildenv.compose_env(build_require.runenv_info)\n            # Then the implicit\n            os_name = self._conanfile.settings_build.get_safe(\"os\")\n            self._buildenv.compose_env(runenv_from_cpp_info(build_require, os_name))\n\n        # Requires in host context can also bring some direct buildenv_info\n        host_requires = self._conanfile.dependencies.host.topological_sort\n        for require in reversed(host_requires.values()):\n            if require.buildenv_info:\n                self._buildenv.compose_env(require.buildenv_info)\n\n        return self._buildenv\n\n    def vars(self, scope=\"build\"):\n        \"\"\"\n        :param scope: Scope to be used.\n        :return: An ``EnvVars`` instance containing the computed environment variables.\n        \"\"\"\n        return self.environment().vars(self._conanfile, scope=scope)\n\n    def generate(self, scope=\"build\"):\n        \"\"\"\n        Produces the launcher scripts activating the variables for the build context.\n\n        :param scope: Scope to be used.\n        \"\"\"\n        check_duplicated_generator(self, self._conanfile)\n        build_env = self.environment()\n        build_env.vars(self._conanfile, scope=scope).save_script(self._filename)\n"
  },
  {
    "path": "conan/tools/env/virtualrunenv.py",
    "content": "import os\n\nfrom conan.internal import check_duplicated_generator\nfrom conan.tools.env import Environment\n\n\ndef runenv_from_cpp_info(dep, os_name):\n    \"\"\" return an Environment deducing the runtime information from a cpp_info\n    \"\"\"\n    dyn_runenv = Environment()\n    cpp_info = dep.cpp_info.aggregated_components()\n\n    def _prepend_path(envvar, paths):\n        existing = [p for p in paths if os.path.exists(p)] if paths else None\n        if existing:\n            dyn_runenv.prepend_path(envvar, existing)\n\n    _prepend_path(\"PATH\", cpp_info.bindirs)\n    # If it is a build_require this will be the build-os, otherwise it will be the host-os\n    if os_name and not os_name.startswith(\"Windows\"):\n        _prepend_path(\"LD_LIBRARY_PATH\", cpp_info.libdirs)\n        _prepend_path(\"DYLD_LIBRARY_PATH\", cpp_info.libdirs)\n        _prepend_path(\"DYLD_FRAMEWORK_PATH\", cpp_info.frameworkdirs)\n    return dyn_runenv\n\n\nclass VirtualRunEnv:\n    \"\"\" Calculates the environment variables of the runtime context and produces a conanrunenv\n        .bat or .sh script\n    \"\"\"\n\n    def __init__(self, conanfile, auto_generate=False):\n        \"\"\"\n\n        :param conanfile:  The current recipe object. Always use ``self``.\n        \"\"\"\n        self._runenv = None\n        self._conanfile = conanfile\n        if not auto_generate:\n            self._conanfile.virtualrunenv = False\n        self.basename = \"conanrunenv\"\n        self.configuration = conanfile.settings.get_safe(\"build_type\")\n        if self.configuration:\n            self.configuration = self.configuration.lower()\n        self.arch = conanfile.settings.get_safe(\"arch\")\n        if self.arch:\n            self.arch = self.arch.lower()\n\n    @property\n    def _filename(self):\n        f = self.basename\n        if self.configuration:\n            f += \"-\" + self.configuration.replace(\".\", \"_\")\n        if self.arch:\n            f += \"-\" + self.arch.replace(\".\", \"_\").replace(\"|\", \"_\")\n        return f\n\n    def environment(self):\n        \"\"\"\n        Returns an ``Environment`` object containing the environment variables of the run context.\n\n        :return: an ``Environment`` object instance containing the obtained variables.\n        \"\"\"\n\n        if self._runenv is None:\n            self._runenv = Environment()\n        else:\n            return self._runenv\n\n        # Top priority: profile\n        profile_env = self._conanfile.runenv\n        self._runenv.compose_env(profile_env)\n\n        host_req = self._conanfile.dependencies.host\n        test_req = self._conanfile.dependencies.test\n        for require, dep in list(host_req.items()) + list(test_req.items()):\n            if dep.runenv_info:\n                self._runenv.compose_env(dep.runenv_info)\n            if require.run:  # Only if the require is run (shared or application to be run)\n                _os = self._conanfile.settings.get_safe(\"os\")\n                self._runenv.compose_env(runenv_from_cpp_info(dep, _os))\n\n        return self._runenv\n\n    def vars(self, scope=\"run\"):\n        \"\"\"\n        :param scope: Scope to be used.\n        :return: An ``EnvVars`` instance containing the computed environment variables.\n        \"\"\"\n        return self.environment().vars(self._conanfile, scope=scope)\n\n    def generate(self, scope=\"run\"):\n        \"\"\"\n        Produces the launcher scripts activating the variables for the run context.\n\n        :param scope: Scope to be used.\n        \"\"\"\n        check_duplicated_generator(self, self._conanfile)\n        run_env = self.environment()\n        run_env.vars(self._conanfile, scope=scope).save_script(self._filename)\n"
  },
  {
    "path": "conan/tools/files/__init__.py",
    "content": "from conan.tools.files.files import load, save, mkdir, rmdir, rm, ftp_download, download, get, \\\n    rename, chdir, unzip, replace_in_file, collect_libs, check_md5, check_sha1, check_sha256, \\\n    move_folder_contents, chmod\n\nfrom conan.tools.files.patches import patch, apply_conandata_patches, export_conandata_patches\nfrom conan.tools.files.symlinks import symlinks\nfrom conan.tools.files.copy_pattern import copy\nfrom conan.tools.files.conandata import update_conandata, trim_conandata\n"
  },
  {
    "path": "conan/tools/files/conandata.py",
    "content": "import os\n\nimport yaml\n\nfrom conan.errors import ConanException\nfrom conan.internal.util.files import load, save\n\n\ndef update_conandata(conanfile, data):\n    \"\"\"\n    Tool to modify the ``conandata.yml`` once it is exported. It can be used, for example:\n\n       - To add additional data like the \"commit\" and \"url\" for the scm.\n       - To modify the contents cleaning the data that belong to other versions (different\n         from the exported) to avoid changing the recipe revision when the changed data doesn't\n         belong to the current version.\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :param data: (Required) A dictionary (can be nested), of values to update\n    \"\"\"\n\n    if not hasattr(conanfile, \"export_folder\") or conanfile.export_folder is None:\n        raise ConanException(\"The 'update_conandata()' can only be used in the 'export()' method\")\n    path = os.path.join(conanfile.export_folder, \"conandata.yml\")\n    if os.path.exists(path):\n        conandata = load(path)\n        conandata = yaml.safe_load(conandata)\n    else:  # File doesn't exist, create it\n        conandata = {}\n\n    def recursive_dict_update(d, u):\n        for k, v in u.items():\n            if isinstance(v, dict):\n                d[k] = recursive_dict_update(d.get(k, {}), v)\n            else:\n                d[k] = v\n        return d\n\n    recursive_dict_update(conandata, data)\n    new_content = yaml.safe_dump(conandata)\n    save(path, new_content)\n\n\ndef trim_conandata(conanfile, raise_if_missing=True):\n    \"\"\"\n    Tool to modify the ``conandata.yml`` once it is exported, to limit it to the current version\n    only\n    \"\"\"\n    if not hasattr(conanfile, \"export_folder\") or conanfile.export_folder is None:\n        raise ConanException(\"The 'trim_conandata()' tool can only be used in \"\n                             \"the 'export()' method or 'post_export()' hook\")\n    path = os.path.join(conanfile.export_folder, \"conandata.yml\")\n    if not os.path.exists(path):\n        if raise_if_missing:\n            raise ConanException(\"conandata.yml file doesn't exist\")\n        else:\n            conanfile.output.warning(\"conandata.yml file doesn't exist\")\n            return\n\n    conandata = load(path)\n    conandata = yaml.safe_load(conandata)\n\n    version = str(conanfile.version)\n    result = {}\n    for k, v in conandata.items():\n        if k == \"scm\" or not isinstance(v, dict):\n            result[k] = v\n            continue  # to allow user extra conandata, common to all versions\n        version_data = v.get(version)\n        if version_data is not None:\n            result[k] = {version: version_data}\n\n    # Update the internal conanfile data too\n    conanfile.conan_data = result\n\n    new_conandata_yml = yaml.safe_dump(result, default_flow_style=False)\n    save(path, new_conandata_yml)\n"
  },
  {
    "path": "conan/tools/files/copy_pattern.py",
    "content": "import filecmp\nimport fnmatch\nimport os\nimport shutil\n\nfrom conan.errors import ConanException\nfrom conan.internal.util.files import mkdir\n\n\ndef copy(conanfile, pattern, src, dst, keep_path=True, excludes=None,\n         ignore_case=True, overwrite_equal=False):\n    \"\"\"\n    Copy the files matching the pattern (fnmatch) at the src folder to a dst folder.\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :param pattern: (Required) An fnmatch file pattern of the files that should be copied.\n           It must not start with ``..`` relative path or an exception will be raised.\n    :param src: (Required) Source folder in which those files will be searched. This folder\n           will be stripped from the dst parameter. E.g., lib/Debug/x86.\n    :param dst: (Required) Destination local folder. It must be different from src value or an\n           exception will be raised.\n    :param keep_path: (Optional, defaulted to ``True``) Means if you want to keep the relative\n           path when you copy the files from the src folder to the dst one.\n    :param excludes: (Optional, defaulted to ``None``) A tuple/list of fnmatch patterns or even a\n           single one to be excluded from the copy.\n    :param ignore_case: (Optional, defaulted to ``True``) If enabled, it will do a\n           case-insensitive pattern matching. will do a case-insensitive pattern matching when\n           ``True``\n    :param overwrite_equal: (Optional, default ``False``). If the file to be copied already exists\n           in the destination folder, only really copy it if it seems different (different size,\n           different modification time)\n    :return: list of copied files\n    \"\"\"\n    if src == dst:\n        raise ConanException(\"copy() 'src' and 'dst' arguments must have different values\")\n    if pattern.startswith(\"..\"):\n        raise ConanException(\"copy() it is not possible to use relative patterns starting with '..'\")\n    if src is None:\n        raise ConanException(\"copy() received 'src=None' argument\")\n\n    # This is necessary to add the trailing / so it is not reported as symlink\n    src = os.path.join(src, \"\")\n    excluded_folder = dst\n    files_to_copy, files_symlinked_to_folders = _filter_files(src, pattern, excludes, ignore_case,\n                                                              excluded_folder)\n\n    copied_files = _copy_files(files_to_copy, src, dst, keep_path, overwrite_equal)\n    copied_files.extend(_copy_files_symlinked_to_folders(files_symlinked_to_folders, src, dst))\n    if conanfile:  # Some usages still pass None\n        copied = '\\n    '.join(files_to_copy)\n        conanfile.output.debug(f\"copy(pattern={pattern}) copied {len(copied_files)} files\\n\"\n                               f\"  from {src}\\n\"\n                               f\"  to {dst}\\n\"\n                               f\"  Files:\\n    {copied}\")\n    return copied_files\n\n\ndef _filter_files(src, pattern, excludes, ignore_case, excluded_folder):\n    \"\"\" return a list of the files matching the patterns\n    The list will be relative path names wrt to the root src folder\n    \"\"\"\n    filenames = []\n    files_symlinked_to_folders = []\n\n    pattern = pattern.lower() if ignore_case else pattern\n    if excludes:\n        if not isinstance(excludes, (tuple, list)):\n            excludes = (excludes, )\n        if ignore_case:\n            excludes = [e.lower() for e in excludes]\n    else:\n        excludes = []\n\n    for root, subfolders, files in os.walk(src):\n        if root == excluded_folder:\n            subfolders[:] = []\n            continue\n\n        # Check if any of the subfolders is a symlink\n        for subfolder in subfolders:\n            if os.path.islink(os.path.join(root, subfolder)):\n                relative_path = os.path.relpath(os.path.join(root, subfolder), src)\n                compare_relative_path = relative_path.lower() if ignore_case else relative_path\n                if fnmatch.fnmatch(os.path.normpath(compare_relative_path), pattern):\n                    files_symlinked_to_folders.append(relative_path)\n\n        relative_path = os.path.relpath(root, src)\n        compare_relative_path = relative_path.lower() if ignore_case else relative_path\n        # Don't try to exclude the start folder, it conflicts with excluding names starting with dots\n        if not compare_relative_path == \".\":\n            for exclude in excludes:\n                if fnmatch.fnmatch(compare_relative_path, exclude):\n                    subfolders[:] = []\n                    files = []\n                    break\n        for f in files:\n            relative_name = os.path.normpath(os.path.join(relative_path, f))\n            filenames.append(relative_name)\n\n    if ignore_case:\n        files_to_copy = [n for n in filenames if fnmatch.fnmatch(os.path.normpath(n.lower()),\n                                                                 pattern)]\n    else:\n        files_to_copy = [n for n in filenames if fnmatch.fnmatchcase(os.path.normpath(n),\n                                                                     pattern)]\n\n    for exclude in excludes:\n        if ignore_case:\n            files_to_copy = [f for f in files_to_copy if not fnmatch.fnmatch(f.lower(), exclude)]\n            files_symlinked_to_folders =\\\n                [f for f in files_symlinked_to_folders if not fnmatch.fnmatch(f.lower(), exclude)]\n        else:\n            files_to_copy = [f for f in files_to_copy if not fnmatch.fnmatchcase(f, exclude)]\n            files_symlinked_to_folders =\\\n                [f for f in files_symlinked_to_folders if not fnmatch.fnmatchcase(f, exclude)]\n\n    return files_to_copy, files_symlinked_to_folders\n\n\ndef _copy_files(files, src, dst, keep_path, overwrite_equal):\n    \"\"\" executes a multiple file copy from [(src_file, dst_file), (..)]\n    managing symlinks if necessary\n    \"\"\"\n    copied_files = []\n    for filename in files:\n        abs_src_name = os.path.join(src, filename)\n        filename = filename if keep_path else os.path.basename(filename)\n        abs_dst_name = os.path.normpath(os.path.join(dst, filename))\n        parent_folder = os.path.dirname(abs_dst_name)\n        if parent_folder:  # There are cases where this folder will be empty for relative paths\n            os.makedirs(parent_folder, exist_ok=True)\n\n        if os.path.islink(abs_src_name):\n            linkto = os.readlink(abs_src_name)\n            try:\n                os.remove(abs_dst_name)\n            except OSError:\n                pass\n            os.symlink(linkto, abs_dst_name)\n        else:\n            # Avoid the copy if the file exists and has the exact same signature (size + mod time)\n            if overwrite_equal or not os.path.exists(abs_dst_name) \\\n                    or not filecmp.cmp(abs_src_name, abs_dst_name):\n                shutil.copy2(abs_src_name, abs_dst_name)\n        copied_files.append(abs_dst_name)\n    return copied_files\n\n\ndef _copy_files_symlinked_to_folders(files_symlinked_to_folders, src, dst):\n    \"\"\"Copy the files that are symlinks to folders from src to dst.\n       The files are already filtered with the specified pattern\"\"\"\n    copied_files = []\n    for relative_path in files_symlinked_to_folders:\n        abs_path = os.path.join(src, relative_path)\n        symlink_path = os.path.join(dst, relative_path)\n        # We create the same symlink in dst, no matter if it is absolute or relative\n        link_dst = os.readlink(abs_path)  # This could be perfectly broken\n\n        # Create the parent directory that will contain the symlink file\n        mkdir(os.path.dirname(symlink_path))\n        # If the symlink is already there, remove it (multiple copy(*.h) copy(*.dll))\n        if os.path.islink(symlink_path):\n            os.unlink(symlink_path)\n        os.symlink(link_dst, symlink_path)\n        copied_files.append(symlink_path)\n    return copied_files\n"
  },
  {
    "path": "conan/tools/files/files.py",
    "content": "import gzip\nimport os\nimport stat\nimport platform\nimport shutil\nimport subprocess\nfrom typing import Optional\nfrom contextlib import contextmanager\nfrom fnmatch import fnmatch\nfrom shutil import which\n\n\nfrom conan.internal.rest.caching_file_downloader import SourcesCachingDownloader\nfrom conan.errors import ConanException\nfrom conan.internal.rest.file_uploader import FileProgress\nfrom conan.internal.util.files import rmdir as _internal_rmdir, human_size, check_with_algorithm_sum\n\n\ndef load(conanfile, path, encoding=\"utf-8\"):\n    \"\"\"\n    Utility function to load files in one line. It will manage the open and close of the file,\n    and load binary encodings. Returns the content of the file.\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :param path: Path to the file to read\n    :param encoding: (Optional, Defaulted to ``utf-8``): Specifies the input file text encoding.\n    :return: The contents of the file\n    \"\"\"\n    with open(path, \"r\", encoding=encoding, newline=\"\") as handle:\n        tmp = handle.read()\n        return tmp\n\n\ndef save(conanfile, path, content, append=False, encoding=\"utf-8\"):\n    \"\"\"\n    Utility function to save files in one line. It will manage the open and close of the file\n    and creating directories if necessary.\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :param path: Path of the file to be created.\n    :param content: Content (str or bytes) to be write to the file.\n    :param append: (Optional, Defaulted to False): If ``True`` the contents will be appended to the\n           existing one.\n    :param encoding: (Optional, Defaulted to utf-8): Specifies the output file text encoding.\n    \"\"\"\n    dir_path = os.path.dirname(path)\n    if dir_path:\n        os.makedirs(dir_path, exist_ok=True)\n    with open(path, \"a\" if append else \"w\", encoding=encoding, newline=\"\") as handle:\n        handle.write(content)\n\n\ndef mkdir(conanfile, path):\n    \"\"\"\n    Utility functions to create a directory. The existence of the specified directory is checked,\n    so mkdir() will do nothing if the directory already exists.\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :param path: Path to the folder to be created.\n    \"\"\"\n    if os.path.exists(path):\n        return\n    os.makedirs(path)\n\n\ndef rmdir(conanfile, path):\n    _internal_rmdir(path)\n\n\ndef rm(conanfile, pattern, folder, recursive=False, excludes=None):\n    \"\"\"\n    Utility functions to remove files matching a ``pattern`` in a ``folder``.\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :param pattern: Pattern that the files to be removed have to match (fnmatch).\n    :param folder: Folder to search/remove the files.\n    :param recursive: If ``recursive`` is specified it will search in the subfolders.\n    :param excludes: (Optional, defaulted to None) A tuple/list of fnmatch patterns or even a\n                     single one to be excluded from the remove pattern.\n    \"\"\"\n    if excludes and not isinstance(excludes, (tuple, list)):\n        excludes = (excludes,)\n    elif not excludes:\n        excludes = []\n\n    for root, _, filenames in os.walk(folder):\n        for filename in filenames:\n            if fnmatch(filename, pattern) and not any(fnmatch(filename, it) for it in excludes):\n                fullname = os.path.join(root, filename)\n                os.unlink(fullname)\n        if not recursive:\n            break\n\n\ndef get(conanfile, url, md5=None, sha1=None, sha256=None, destination=\".\", filename=\"\",\n        keep_permissions=False, pattern=None, verify=True, retry=None, retry_wait=None,\n        auth=None, headers=None, strip_root=False, extract_filter=None, excludes=None):\n    \"\"\"\n    High level download and decompressing of a tgz, zip or other compressed format file.\n    Just a high level wrapper for download, unzip, and remove the temporary zip file once unzipped.\n    You can pass hash checking parameters: ``md5``, ``sha1``, ``sha256``. All the specified\n    algorithms will be checked. If any of them doesn't match, it will raise a ``ConanException``.\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :param destination: (Optional defaulted to ``.``) Destination folder\n    :param filename: (Optional defaulted to '') If provided, the saved file will have the specified name,\n           otherwise it is deduced from the URL\n    :param url: forwarded to ``tools.file.download()``.\n    :param md5: forwarded to ``tools.file.download()``.\n    :param sha1:  forwarded to ``tools.file.download()``.\n    :param sha256:  forwarded to ``tools.file.download()``.\n    :param keep_permissions:  forwarded to ``tools.file.unzip()``.\n    :param pattern: forwarded to ``tools.file.unzip()``.\n    :param verify:  forwarded to ``tools.file.download()``.\n    :param retry:  forwarded to ``tools.file.download()``.\n    :param retry_wait: S forwarded to ``tools.file.download()``.\n    :param auth:  forwarded to ``tools.file.download()``.\n    :param headers:  forwarded to ``tools.file.download()``.\n    :param strip_root: forwarded to ``tools.file.unzip()``.\n    :param extract_filter: forwarded to ``tools.file.unzip()``.\n    :param excludes: forwarded to ``tools.file.unzip()``.\n    \"\"\"\n\n    if not filename:  # deduce filename from the URL\n        url_base = url[0] if isinstance(url, (list, tuple)) else url\n        if \"?\" in url_base or \"=\" in url_base:\n            raise ConanException(\"Cannot deduce file name from the url: '{}'. Use 'filename' \"\n                                 \"parameter.\".format(url_base))\n        filename = os.path.basename(url_base)\n\n    download(conanfile, url, filename, verify=verify,\n             retry=retry, retry_wait=retry_wait, auth=auth, headers=headers,\n             md5=md5, sha1=sha1, sha256=sha256)\n    unzip(conanfile, filename, destination=destination, keep_permissions=keep_permissions,\n          pattern=pattern, strip_root=strip_root, extract_filter=extract_filter,\n          excludes=excludes)\n    os.unlink(filename)\n\n\ndef ftp_download(conanfile, host, filename, login='', password='', secure=False):\n    \"\"\"\n    Ftp download of a file. Retrieves a file from an FTP server.\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :param host: IP or host of the FTP server.\n    :param filename: Path to the file to be downloaded.\n    :param login: Authentication login.\n    :param password: Authentication password.\n    :param secure: Set to True to use FTP over TLS/SSL (FTPS). Defaults to False for regular FTP.\n    \"\"\"\n    # TODO: Check if we want to join this method with download() one, based on ftp:// protocol\n    # this has been requested by some users, but the hash is a bit divergent\n    import ftplib\n    ftp = None\n    try:\n        if secure:\n            ftp = ftplib.FTP_TLS(host)\n            ftp.prot_p()\n        else:\n            ftp = ftplib.FTP(host)\n        ftp.login(login, password)\n        filepath, filename = os.path.split(filename)\n        if filepath:\n            ftp.cwd(filepath)\n        with open(filename, 'wb') as f:\n            ftp.retrbinary('RETR ' + filename, f.write)\n    except Exception as e:\n        try:\n            os.unlink(filename)\n        except OSError:\n            pass\n        raise ConanException(\"Error in FTP download from %s\\n%s\" % (host, str(e)))\n    finally:\n        if ftp:\n            ftp.quit()\n\n\ndef download(conanfile, url, filename, verify=True, retry=None, retry_wait=None,\n             auth=None, headers=None, md5=None, sha1=None, sha256=None):\n    \"\"\"\n    Retrieves a file from a given URL into a file with a given filename. It uses certificates from\n    a list of known verifiers for https downloads, but this can be optionally disabled.\n\n    You can pass hash checking parameters: ``md5``, ``sha1``, ``sha256``. All the specified\n    algorithms will be checked. If any of them doesn’t match, the downloaded file will be removed\n    and it will raise a ``ConanException``.\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :param url: URL to download. It can be a list, which only the first one will be downloaded, and\n                the follow URLs will be used as mirror in case of download error.  Files accessible\n                in the local filesystem can be referenced with a URL starting with ``file:///``\n                followed by an absolute path to a file (where the third ``/`` implies ``localhost``).\n    :param filename: Name of the file to be created in the local storage\n    :param verify: When False, disables https certificate validation\n    :param retry: Number of retries in case of failure. Default is overridden by\n           \"tools.files.download:retry\" conf\n    :param retry_wait: Seconds to wait between download attempts. Default is overriden by\n           \"tools.files.download:retry_wait\" conf.\n    :param auth: A tuple of user and password to use HTTPBasic authentication\n    :param headers: A dictionary with additional headers\n    :param md5: MD5 hash code to check the downloaded file\n    :param sha1: SHA-1 hash code to check the downloaded file\n    :param sha256: SHA-256 hash code to check the downloaded file\n    \"\"\"\n    config = conanfile.conf\n\n    retry = retry if retry is not None else 2\n    retry = config.get(\"tools.files.download:retry\", check_type=int, default=retry)\n    retry_wait = retry_wait if retry_wait is not None else 5\n    retry_wait = config.get(\"tools.files.download:retry_wait\", check_type=int, default=retry_wait)\n    verify = config.get(\"tools.files.download:verify\", check_type=bool, default=verify)\n\n    filename = os.path.abspath(filename)\n    downloader = SourcesCachingDownloader(conanfile)\n    downloader.download(url, filename, retry, retry_wait, verify, auth, headers, md5, sha1, sha256)\n\n\ndef rename(conanfile, src, dst):\n    \"\"\"\n    Utility functions to rename a file or folder src to dst with retrying. ``os.rename()``\n    frequently raises “Access is denied” exception on Windows.\n    This function renames file or folder using robocopy to avoid the exception on Windows.\n\n\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :param src: Path to be renamed.\n    :param dst: Path to be renamed to.\n    \"\"\"\n\n    # FIXME: This function has been copied from legacy. Needs to fix: which()\n    # call and wrap subprocess call.\n    if os.path.exists(dst):\n        raise ConanException(\"rename {} to {} failed, dst exists.\".format(src, dst))\n\n    if platform.system() == \"Windows\" and which(\"robocopy\") and os.path.isdir(src):\n        # /move Moves files and directories, and deletes them from the source after they are copied.\n        # /e Copies subdirectories. Note that this option includes empty directories.\n        # /ndl Specifies that directory names are not to be logged.\n        # /nfl Specifies that file names are not to be logged.\n        process = subprocess.Popen([\"robocopy\", \"/move\", \"/e\", \"/ndl\", \"/nfl\", src, dst],\n                                   stdout=subprocess.PIPE)\n        process.communicate()\n        if process.returncode > 7:  # https://ss64.com/nt/robocopy-exit.html\n            raise ConanException(\"rename {} to {} failed.\".format(src, dst))\n    else:\n        try:\n            os.rename(src, dst)\n        except Exception as err:\n            raise ConanException(\"rename {} to {} failed: {}\".format(src, dst, err))\n\n\n@contextmanager\ndef chdir(conanfile, newdir):\n    \"\"\"\n    This is a context manager that allows to temporary change the current directory in your conanfile\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :param newdir: Directory path name to change the current directory.\n\n    \"\"\"\n    old_path = os.getcwd()\n    os.chdir(newdir)\n    try:\n        yield\n    finally:\n        os.chdir(old_path)\n\n\ndef chmod(conanfile, path: str, read: Optional[bool] = None, write: Optional[bool] = None,\n          execute: Optional[bool] = None, recursive: bool = False):\n    \"\"\"Change file or directory permissions cross-platform.\n\n    .. versionadded:: 2.15\n\n    This function is a simple wrapper around the chmod Unix command, but it is cross-platform supported.\n    It is indicated to use it instead of os.stat + os.chmod, as it only changes the permissions of the\n    directory or file for the owner and avoids issues with the umask.\n    On Windows is limited to changing write permission only.\n\n    Parameters\n    ----------\n    conanfile : object\n        The current recipe object. Always use ``self``.\n    path : str\n        Path to the file or directory whose permissions will be changed.\n    read : bool, optional\n        If ``True``, the file or directory will be given read permissions for owner user.\n        If ``False``, the read permission will be removed.\n        If ``None``, the read permission will be left unchanged.\n        Defaults to None.\n    write : bool, optional\n        If ``True``, the file or directory will be given write permissions for owner user.\n        If ``False``, the write permission will be removed.\n        If ``None``, the file or directory will not be changed.\n        Defaults to None.\n    execute : bool, optional\n        If ``True``, the file or directory will be given execute permissions for owner user.\n        If ``False``, the execution permission will be removed.\n        If ``None``, the file or directory will not be changed.\n        Defaults to None.\n    recursive : bool\n        If ``True``, the permissions will be applied recursively to all files and directories\n        inside the specified directory. If ``False``, only the specified file or directory will\n        be changed. Defaults to False.\n\n    Returns\n    -------\n    None\n\n    Examples\n    --------\n    .. code-block:: python\n        :caption: Add execution permission to a packaged bash script\n\n        from conan.tools.files import chmod\n        chmod(self, os.path.join(self.package_folder, \"bin\", \"script.sh\"), execute=True)\n    \"\"\"\n    if read is None and write is None and execute is None:\n        raise ConanException(\"Could not change permission: At least one of the permissions should be set.\")\n\n    if not os.path.exists(path):\n        raise ConanException(f\"Could not change permission: Path \\\"{path}\\\" does not exist.\")\n\n    def _change_permission(it_path:str):\n        mode = os.stat(it_path).st_mode\n        permissions = [\n            (read, stat.S_IRUSR),\n            (write, stat.S_IWUSR),\n            (execute, stat.S_IXUSR)\n        ]\n        for enabled, mask in permissions:\n            if enabled is None:\n                continue\n            elif enabled:\n                mode |= mask\n            else:\n                mode &= ~mask\n        os.chmod(it_path, mode)\n\n    if recursive:\n        for root, _, files in os.walk(path):\n            for file in files:\n                _change_permission(os.path.join(root, file))\n    else:\n        _change_permission(path)\n\n\ndef unzip(conanfile, filename, destination=\".\", keep_permissions=False, pattern=None,\n          strip_root=False, extract_filter=None, excludes=None):\n    \"\"\"\n    Extract different compressed formats\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :param filename: Path to the compressed file.\n    :param destination: (Optional, Defaulted to ``.``) Destination folder (or file for .gz files)\n    :param keep_permissions: (Optional, Defaulted to ``False``) Keep the zip permissions.\n           WARNING: Can be dangerous if the zip was not created in a NIX system, the bits could\n           produce undefined permission schema. Use this option only if you are sure that the zip\n           was created correctly.\n    :param pattern: (Optional, Defaulted to ``None``) Extract only paths matching the pattern.\n           This should be a Unix shell-style wildcard, see fnmatch documentation for more details.\n    :param strip_root: (Optional, Defaulted to False) If True, and all the unzipped contents are\n           in a single folder it will flat the folder moving all the contents to the parent folder.\n    :param extract_filter: (Optional, defaulted to None). When extracting a tar file,\n           use the tar extracting filters define by Python in\n           https://docs.python.org/3/library/tarfile.html\n    :param excludes: (Optional, defaulted to None). When extracting a file,\n           exclude paths matching any of the patterns. This should be a Unix shell-style wildcard,\n           see fnmatch documentation for more details.\n    \"\"\"\n\n    output = conanfile.output\n    extract_filter = conanfile.conf.get(\"tools.files.unzip:filter\") or extract_filter\n    output.info(f\"Uncompressing {filename} to {destination}\")\n    if (filename.endswith(\".tar.gz\") or filename.endswith(\".tgz\") or\n            filename.endswith(\".tbz2\") or filename.endswith(\".tar.bz2\") or\n            filename.endswith(\".tar\")):\n        return untargz(filename, destination, pattern, strip_root, extract_filter,\n                       excludes=excludes)\n    if filename.endswith(\".gz\"):\n        target_name = filename[:-3] if destination == \".\" else destination\n        target_dir = os.path.dirname(target_name)\n        if target_dir:\n            os.makedirs(target_dir, exist_ok=True)\n        with gzip.open(filename, 'rb') as fin:\n            with open(target_name, \"wb\") as fout:\n                shutil.copyfileobj(fin, fout)\n        return\n    if filename.endswith(\".tar.xz\") or filename.endswith(\".txz\"):\n        return untargz(filename, destination, pattern, strip_root, extract_filter,\n                       excludes=excludes)\n\n    import zipfile\n    full_path = os.path.normpath(os.path.join(os.getcwd(), destination))\n\n    with FileProgress(filename, msg=\"Unzipping\", mode=\"r\") as file, zipfile.ZipFile(file) as z:\n        zip_info = z.infolist()\n        if pattern:\n            zip_info = [zi for zi in zip_info if fnmatch(zi.filename, pattern)]\n        if excludes:\n            zip_info = [zi for zi in zip_info\n                        if not any(fnmatch(zi.filename, pat) for pat in excludes)]\n        if strip_root:\n            names = [zi.filename.replace(\"\\\\\", \"/\") for zi in zip_info]\n            common_folder = os.path.commonprefix(names).split(\"/\", 1)[0]\n            if not common_folder and len(names) > 1:\n                raise ConanException(\"The zip file contains more than 1 folder in the root\")\n            if len(names) == 1 and len(names[0].split(\"/\", 1)) == 1:\n                raise ConanException(\"The zip file contains a file in the root\")\n            # Remove the directory entry if present\n            # Note: The \"zip\" format contains the \"/\" at the end if it is a directory\n            zip_info = [m for m in zip_info if m.filename != (common_folder + \"/\")]\n            for member in zip_info:\n                name = member.filename.replace(\"\\\\\", \"/\")\n                member.filename = name.split(\"/\", 1)[1]\n\n        uncompress_size = sum((file_.file_size for file_ in zip_info))\n        if uncompress_size > 100000:\n            output.info(\"Unzipping %s, this can take a while\" % human_size(uncompress_size))\n        else:\n            output.info(\"Unzipping %s\" % human_size(uncompress_size))\n        extracted_size = 0\n\n        if platform.system() == \"Windows\":\n            for file_ in zip_info:\n                extracted_size += file_.file_size\n                try:\n                    z.extract(file_, full_path)\n                except Exception as e:\n                    output.error(f\"Error extract {file_.filename}\\n{str(e)}\", error_type=\"exception\")\n        else:  # duplicated for, to avoid a platform check for each zipped file\n            for file_ in zip_info:\n                extracted_size += file_.file_size\n                try:\n                    z.extract(file_, full_path)\n                    if keep_permissions:\n                        # Could be dangerous if the ZIP has been created in a non nix system\n                        # https://bugs.python.org/issue15795\n                        perm = file_.external_attr >> 16 & 0xFFF\n                        os.chmod(os.path.join(full_path, file_.filename), perm)\n                except Exception as e:\n                    output.error(f\"Error extract {file_.filename}\\n{str(e)}\", error_type=\"exception\")\n        output.writeln(\"\")\n\n\ndef untargz(filename, destination=\".\", pattern=None, strip_root=False, extract_filter=None,\n            excludes=None):\n    # NOT EXPOSED at `conan.tools.files` but used in tests\n    import tarfile\n    with tarfile.TarFile.open(filename, mode='r:*') as tarredgzippedFile:\n        f = getattr(tarfile, f\"{extract_filter}_filter\", None) if extract_filter else None\n        tarredgzippedFile.extraction_filter = f or (lambda member_, _: member_)\n        # https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=registry\n        # File I/O functions in the Windows API convert \"/\" to \"\\\" as part of converting\n        # the name to an NT-style name, except when using the \"\\\\?\\\" prefix\n        using_long_path_prefix = destination.startswith(\"\\\\\\\\?\\\\\")\n        if not pattern and not excludes and not strip_root and not using_long_path_prefix:\n            tarredgzippedFile.extractall(destination)\n        else:\n            common_folder = None\n            members = []\n            for member in tarredgzippedFile:\n                if pattern and not fnmatch(member.name, pattern):\n                    continue  # Skip files that don’t match the pattern\n                if excludes and any(fnmatch(member.name, pat) for pat in excludes):\n                    continue  # Skip files that match the excludes\n\n                if strip_root:\n                    name = member.name.replace(\"\\\\\", \"/\")\n                    if not common_folder:\n                        splits = name.split(\"/\", 1)\n                        # First case for a plain folder in the root\n                        if member.isdir() or len(splits) > 1:\n                            common_folder = splits[0]  # Find the root folder\n                        else:\n                            raise ConanException(\"Can't untar a tgz containing files in the root with strip_root enabled\")\n                    if not name.startswith(common_folder):\n                        raise ConanException(\"The tgz file contains more than 1 folder in the root\")\n                    # Adjust the member's name for extraction\n                    member.name = name[len(common_folder) + 1:]\n                    member.path = member.name\n                    if member.linkpath and member.linkpath.startswith(common_folder):\n                        # https://github.com/conan-io/conan/issues/11065\n                        member.linkpath = member.linkpath[len(common_folder) + 1:].replace(\"\\\\\", \"/\")\n                        member.linkname = member.linkpath\n                if using_long_path_prefix:\n                    member.name = member.name.replace(\"/\", \"\\\\\")\n                # Let's gather each member\n                members.append(member)\n            tarredgzippedFile.extractall(destination, members=members)\n\n\ndef check_sha1(conanfile, file_path, signature):\n    \"\"\"\n    Check that the specified ``SHA-1`` hash of the ``file_path`` matches the actual hash.\n    If doesn’t match it will raise a ``ConanException``.\n\n    :param conanfile: Conanfile object.\n    :param file_path: Path of the file to check.\n    :param signature: Expected SHA-1 hash.\n    \"\"\"\n    check_with_algorithm_sum(\"sha1\", file_path, signature)\n\n\ndef check_md5(conanfile, file_path, signature):\n    \"\"\"\n    Check that the specified ``MD5`` hash of the ``file_path`` matches the actual hash.\n    If doesn’t match it will raise a ``ConanException``.\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :param file_path: Path of the file to check.\n    :param signature: Expected MD5 hash.\n    \"\"\"\n    check_with_algorithm_sum(\"md5\", file_path, signature)\n\n\ndef check_sha256(conanfile, file_path, signature):\n    \"\"\"\n    Check that the specified ``SHA-256`` hash of the ``file_path`` matches the actual hash.\n    If doesn’t match it will raise a ``ConanException``.\n\n    :param conanfile: Conanfile object.\n    :param file_path: Path of the file to check.\n    :param signature: Expected SHA-256 hash.\n    \"\"\"\n    check_with_algorithm_sum(\"sha256\", file_path, signature)\n\n\ndef replace_in_file(conanfile, file_path, search, replace, strict=True, encoding=\"utf-8\"):\n    \"\"\"\n    Replace a string ``search`` in the contents of the file ``file_path`` with the string replace.\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :param file_path: File path of the file to perform the replacing.\n    :param search: String you want to be replaced.\n    :param replace: String to replace the searched string.\n    :param strict: (Optional, Defaulted to ``True``) If ``True``, it raises an error if the searched\n           string is not found, so nothing is actually replaced.\n    :param encoding: (Optional, Defaulted to utf-8): Specifies the input and output files text\n           encoding.\n    :return: ``True`` if the pattern was found, ``False`` otherwise if `strict` is ``False``.\n    \"\"\"\n    output = conanfile.output\n    content = load(conanfile, file_path, encoding=encoding)\n    if -1 == content.find(search):\n        message = \"replace_in_file didn't find pattern '%s' in '%s' file.\" % (search, file_path)\n        if strict:\n            raise ConanException(message)\n        else:\n            output.warning(message)\n            return False\n    content = content.replace(search, replace)\n    save(conanfile, file_path, content, encoding=encoding)\n    return True\n\n\ndef collect_libs(conanfile, folder=None):\n    \"\"\"\n    Returns a sorted list of library names from the libraries (files with extensions *.so*, *.lib*,\n    *.a* and *.dylib*) located inside the ``conanfile.cpp_info.libdirs`` (by default) or the\n    **folder** directory relative to the package folder. Useful to collect not inter-dependent\n    libraries or with complex names like ``libmylib-x86-debug-en.lib``.\n\n    For UNIX libraries staring with **lib**, like *libmath.a*, this tool will collect the library\n    name **math**.\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :param folder: (Optional, Defaulted to ``None``): String indicating the subfolder name inside\n           ``conanfile.package_folder`` where the library files are.\n    :return: A list with the library names\n    \"\"\"\n    if not conanfile.package_folder:\n        return []\n    if folder:\n        lib_folders = [os.path.join(conanfile.package_folder, folder)]\n    else:\n        lib_folders = [os.path.join(conanfile.package_folder, folder)\n                       for folder in conanfile.cpp_info.libdirs]\n\n    ref_libs = {}\n    for lib_folder in lib_folders:\n        if not os.path.exists(lib_folder):\n            conanfile.output.warning(\"Lib folder doesn't exist, can't collect libraries: \"\n                                     \"{0}\".format(lib_folder))\n            continue\n        # In case of symlinks, only keep shortest file name in the same \"group\"\n        files = os.listdir(lib_folder)\n        for f in files:\n            name, ext = os.path.splitext(f)\n            if ext in (\".so\", \".lib\", \".a\", \".dylib\", \".bc\"):\n                real_lib = os.path.basename(os.path.realpath(os.path.join(lib_folder, f)))\n                if real_lib not in ref_libs or len(f) < len(ref_libs[real_lib]):\n                    ref_libs[real_lib] = f\n\n    result = []\n    for f in ref_libs.values():\n        name, ext = os.path.splitext(f)\n        if ext != \".lib\" and name.startswith(\"lib\"):\n            name = name[3:]\n        result.append(name)\n    result.sort()\n    return result\n\n\ndef move_folder_contents(conanfile, src_folder, dst_folder):\n    \"\"\" replaces the dst_folder contents with the contents of the src_folder, which can be a\n    child folder of dst_folder. This is used in the SCM monorepo flow, when it is necessary\n    to use one subproject subfolder to replace the whole cloned git repo\n    /base-folder                       /base-folder\n        /pkg  (src folder)                 /other/<otherfiles>\n          /other/<otherfiles>              /pkg/<pkgfiles>\n          /pkg/<pkgfiles>                  <files>\n          <files>\n        /siblings\n        <siblingsfiles>\n    \"\"\"\n    # Remove potential \"siblings\" folders not wanted\n    src_folder_name = os.path.basename(src_folder)\n    for f in os.listdir(dst_folder):\n        if f != src_folder_name:  # FIXME: Only works for 1st level subfolder\n            dst = os.path.join(dst_folder, f)\n            if os.path.isfile(dst):\n                os.remove(dst)\n            else:\n                _internal_rmdir(dst)\n\n    # Move all the contents\n    for f in os.listdir(src_folder):\n        src = os.path.join(src_folder, f)\n        dst = os.path.join(dst_folder, f)\n        if not os.path.exists(dst):\n            shutil.move(src, dst_folder)\n        else:\n            for sub_src in os.listdir(src):\n                shutil.move(os.path.join(src, sub_src), dst)\n            _internal_rmdir(src)\n    try:\n        os.rmdir(src_folder)\n    except OSError:\n        pass\n"
  },
  {
    "path": "conan/tools/files/patches.py",
    "content": "import logging\nimport os\nimport shutil\n\nimport patch_ng\nimport yaml\n\nfrom conan.errors import ConanException\nfrom conan.internal.paths import DATA_YML\nfrom conan.internal.util.files import mkdir, load, save\n\n\nclass PatchLogHandler(logging.Handler):\n    def __init__(self, scoped_output, patch_file):\n        logging.Handler.__init__(self, logging.DEBUG)\n        self._scoped_output = scoped_output\n        self.patchname = patch_file or \"patch_ng\"\n\n    def emit(self, record):\n        logstr = self.format(record)\n        if record.levelno == logging.WARN:\n            self._scoped_output.warning(\"%s: %s\" % (self.patchname, logstr))\n        else:\n            self._scoped_output.info(\"%s: %s\" % (self.patchname, logstr))\n\n\ndef patch(conanfile, base_path=None, patch_file=None, patch_string=None, strip=0, fuzz=False, **kwargs):\n    \"\"\"\n    Applies a diff from file (patch_file) or string (patch_string) in the conanfile.source_folder\n    directory. The folder containing the sources can be customized with the self.folders attribute\n    in the layout(self) method.\n\n    :param conanfile: the current recipe, always pass 'self'\n    :param base_path: The path is a relative path to conanfile.export_sources_folder unless an\n           absolute path is provided.\n    :param patch_file: Patch file that should be applied. The path is relative to the\n           conanfile.source_folder unless an absolute path is provided.\n    :param patch_string: Patch string that should be applied.\n    :param strip: Number of folders to be stripped from the path.\n    :param fuzz: Should accept fuzzy patches.\n    :param kwargs: Extra parameters that can be added and will contribute to output information\n    \"\"\"\n\n    patch_type = kwargs.get('patch_type') or (\"file\" if patch_file else \"string\")\n    patch_description = kwargs.get('patch_description')\n\n    if patch_type or patch_description:\n        patch_type_str = ' ({})'.format(patch_type) if patch_type else ''\n        patch_description_str = ': {}'.format(patch_description) if patch_description else ''\n        conanfile.output.info('Apply patch{}{}'.format(patch_type_str, patch_description_str))\n\n    patchlog = logging.getLogger(\"patch_ng\")\n    patchlog.handlers = []\n    patchlog.addHandler(PatchLogHandler(conanfile.output, patch_file))\n\n    if patch_file:\n        # trick *1: patch_file path could be absolute (e.g. conanfile.build_folder), in that case\n        # the join does nothing and works.\n        patch_path = os.path.join(conanfile.export_sources_folder, patch_file)\n        patchset = patch_ng.fromfile(patch_path)\n    else:\n        patchset = patch_ng.fromstring(patch_string.encode())\n\n    if not patchset:\n        raise ConanException(\"Failed to parse patch: %s\" % (patch_file if patch_file else \"string\"))\n\n    # trick *1\n    root = os.path.join(conanfile.source_folder, base_path) if base_path else conanfile.source_folder\n    if not patchset.apply(strip=strip, root=root, fuzz=fuzz):\n        raise ConanException(\"Failed to apply patch: %s\" % patch_file)\n\n\ndef apply_conandata_patches(conanfile):\n    \"\"\"\n    Applies patches stored in ``conanfile.conan_data`` (read from ``conandata.yml`` file).\n    It will apply all the patches under ``patches`` entry that matches the given\n    ``conanfile.version``. If versions are not defined in ``conandata.yml`` it will apply all the\n    patches directly under ``patches`` keyword.\n\n    The key entries will be passed as kwargs to the ``patch`` function.\n    \"\"\"\n    if conanfile.conan_data is None:\n        raise ConanException(\"conandata.yml not defined\")\n\n    patches = conanfile.conan_data.get('patches')\n    if patches is None:\n        conanfile.output.info(\"apply_conandata_patches(): No patches defined in conandata\")\n        return\n\n    if isinstance(patches, dict):\n        assert conanfile.version, \"Can only be applied if conanfile.version is already defined\"\n        entries = patches.get(str(conanfile.version), [])\n        if entries is None:\n            conanfile.output.warning(f\"apply_conandata_patches(): No patches defined for version {conanfile.version} in conandata.yml\")\n            return\n    elif isinstance(patches, list):\n        entries = patches\n    else:\n        raise ConanException(\"conandata.yml 'patches' should be a list or a dict {version: list}\")\n    for it in entries:\n        if \"patch_file\" in it:\n            # The patch files are located in the root src\n            entry = it.copy()\n            patch_file = entry.pop(\"patch_file\")\n            patch_file_path = os.path.join(conanfile.export_sources_folder, patch_file)\n            if \"patch_description\" not in entry:\n                entry[\"patch_description\"] = patch_file\n            patch(conanfile, patch_file=patch_file_path, **entry)\n        elif \"patch_string\" in it:\n            patch(conanfile, **it)\n        elif \"patch_user\" in it:\n            pass  # This will be managed directly by users, can be a command or a script execution\n        else:\n            raise ConanException(\"The 'conandata.yml' file needs a 'patch_file' or 'patch_string'\"\n                                 \" entry for every patch to be applied\")\n\n\ndef export_conandata_patches(conanfile):\n    \"\"\"\n    Exports patches stored in 'conanfile.conan_data' (read from 'conandata.yml' file). It will export\n    all the patches under 'patches' entry that matches the given 'conanfile.version'. If versions are\n    not defined in 'conandata.yml' it will export all the patches directly under 'patches' keyword.\n    \"\"\"\n    if conanfile.conan_data is None:\n        raise ConanException(\"conandata.yml not defined\")\n\n    conanfile_patches = conanfile.conan_data.get('patches')\n\n    def _handle_patches(patches, patches_folder):\n        if patches is None:\n            conanfile.output.info(\"export_conandata_patches(): No patches defined in conandata\")\n            return\n\n        if isinstance(patches, dict):\n            assert conanfile.version, \"Can only be exported if conanfile.version is already defined\"\n            entries = patches.get(conanfile.version, [])\n            if entries is None:\n                conanfile.output.warning(\"export_conandata_patches(): No patches defined for \"\n                                         f\"version {conanfile.version} in conandata.yml\")\n                return\n        elif isinstance(patches, list):\n            entries = patches\n        else:\n            raise ConanException(\"conandata.yml 'patches' should be a list or a dict \"\n                                 \"{version: list}\")\n        for it in entries:\n            patch_file = it.get(\"patch_file\")\n            if patch_file:\n                src = os.path.join(patches_folder, patch_file)\n                dst = os.path.join(conanfile.export_sources_folder, patch_file)\n                if not os.path.exists(src):\n                    raise ConanException(f\"Patch file does not exist: '{src}'\")\n                mkdir(os.path.dirname(dst))\n                shutil.copy2(src, dst)\n        return entries\n\n    _handle_patches(conanfile_patches, conanfile.recipe_folder)\n\n    extra_path = conanfile.conf.get(\"core.sources.patch:extra_path\")\n    if extra_path:\n        if not os.path.isdir(extra_path):\n            raise ConanException(f\"Patches extra path '{extra_path}' does not exist\")\n        pkg_path = os.path.join(extra_path, conanfile.name)\n        if not os.path.isdir(pkg_path):\n            return\n        data_path = os.path.join(pkg_path, DATA_YML)\n        try:\n            data = yaml.safe_load(load(data_path))\n        except Exception as e:\n            raise ConanException(\"Invalid yml format at {}: {}\".format(data_path, e))\n        data = data or {}\n        conanfile.output.info(f\"Applying extra patches 'core.sources.patch:extra_path': {data_path}\")\n        new_patches = _handle_patches(data.get('patches'), pkg_path)\n\n        # Update the CONANDATA.YML\n        conanfile_patches = conanfile_patches or {}\n        conanfile_patches.setdefault(conanfile.version, []).extend(new_patches)\n\n        conanfile.conan_data['patches'] = conanfile_patches\n        # Saving in the EXPORT folder\n        conanfile_data_path = os.path.join(conanfile.export_folder, DATA_YML)\n        new_conandata_yml = yaml.safe_dump(conanfile.conan_data, default_flow_style=False)\n        save(conanfile_data_path, new_conandata_yml)\n"
  },
  {
    "path": "conan/tools/files/symlinks/__init__.py",
    "content": "from conan.tools.files.symlinks.symlinks import absolute_to_relative_symlinks, \\\n    remove_external_symlinks, remove_broken_symlinks, get_symlinks\n"
  },
  {
    "path": "conan/tools/files/symlinks/symlinks.py",
    "content": "import os\n\n\ndef get_symlinks(base_folder):\n    \"\"\"Return the absolute path to the symlink files in base_folder\"\"\"\n    for (root, dirnames, filenames) in os.walk(base_folder):\n        for el in filenames + dirnames:\n            fullpath = os.path.join(root, el)\n            if os.path.islink(fullpath):\n                yield fullpath\n\n\ndef _path_inside(base, folder):\n    base = os.path.abspath(base)\n    folder = os.path.abspath(folder)\n    return os.path.commonprefix([base, folder]) == base\n\n\ndef absolute_to_relative_symlinks(conanfile, base_folder):\n    \"\"\"\n    Convert the symlinks with absolute paths into relative ones if they are pointing to a file or\n    directory inside the ``base_folder``. Any absolute symlink pointing outside the ``base_folder``    will be ignored.\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :param base_folder: Folder to be scanned.\n    \"\"\"\n    for fullpath in get_symlinks(base_folder):\n        link_target = os.readlink(fullpath)\n        if not os.path.isabs(link_target):\n            continue\n        folder_of_symlink = os.path.dirname(fullpath)\n        if _path_inside(base_folder, link_target):\n            os.unlink(fullpath)\n            new_link = os.path.relpath(link_target, folder_of_symlink)\n            os.symlink(new_link, fullpath)\n\n\ndef remove_external_symlinks(conanfile, base_folder):\n    \"\"\"\n    Remove the symlinks to files that point outside the ``base_folder``, no matter if relative or absolute.\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :param base_folder: Folder to be scanned.\n    \"\"\"\n    for fullpath in get_symlinks(base_folder):\n        link_target = os.readlink(fullpath)\n        if not os.path.isabs(link_target):\n            link_target = os.path.join(os.path.dirname(fullpath), link_target)\n        if not _path_inside(base_folder, link_target):\n            os.unlink(fullpath)\n\n\ndef remove_broken_symlinks(conanfile, base_folder=None):\n    \"\"\"\n    Remove the broken symlinks, no matter if relative or absolute.\n\n    :param conanfile: The current recipe object. Always use ``self``.\n    :param base_folder: Folder to be scanned.\n    \"\"\"\n    for fullpath in get_symlinks(base_folder):\n        link_target = os.readlink(fullpath)\n        if not os.path.isabs(link_target):\n            link_target = os.path.join(os.path.dirname(fullpath), link_target)\n        if not os.path.exists(link_target):\n            os.unlink(fullpath)\n"
  },
  {
    "path": "conan/tools/gnu/__init__.py",
    "content": "from conan.tools.gnu.autotools import Autotools\nfrom conan.tools.gnu.autotoolstoolchain import AutotoolsToolchain\nfrom conan.tools.gnu.gnutoolchain import GnuToolchain\nfrom conan.tools.gnu.autotoolsdeps import AutotoolsDeps\nfrom conan.tools.gnu.pkgconfig import PkgConfig\nfrom conan.tools.gnu.pkgconfigdeps import PkgConfigDeps\nfrom conan.tools.gnu.makedeps import MakeDeps\n"
  },
  {
    "path": "conan/tools/gnu/autotools.py",
    "content": "import os\nimport re\n\nfrom conan.tools.build import build_jobs, cmd_args_to_string, load_toolchain_args\nfrom conan.internal.subsystems import subsystem_path, deduce_subsystem\nfrom conan.tools.files import chdir\nfrom conan.tools.microsoft import unix_path\n\n\ndef join_arguments(args):\n    return \" \".join(filter(None, args))\n\n\nclass Autotools:\n\n    def __init__(self, conanfile, namespace=None):\n        \"\"\"\n        :param conanfile: The current recipe object. Always use ``self``.\n        :param namespace: this argument avoids collisions when you have multiple toolchain calls in\n                          the same recipe. By setting this argument, the *conanbuild.conf* file used\n                          to pass information to the toolchain will be named as:\n                          *<namespace>_conanbuild.conf*. The default value is ``None`` meaning that\n                          the name of the generated file is *conanbuild.conf*. This namespace must\n                          be also set with the same value in the constructor of the AutotoolsToolchain\n                          so that it reads the information from the proper file.\n        \"\"\"\n        self._conanfile = conanfile\n\n        toolchain_file_content = load_toolchain_args(self._conanfile.generators_folder,\n                                                     namespace=namespace)\n\n        self._configure_args = toolchain_file_content.get(\"configure_args\")\n        self._make_args = toolchain_file_content.get(\"make_args\")\n        self._autoreconf_args = toolchain_file_content.get(\"autoreconf_args\")\n\n    def configure(self, build_script_folder=None, args=None):\n        \"\"\"\n        Call the configure script.\n\n        :param args: List of arguments to use for the ``configure`` call.\n        :param build_script_folder: Subfolder where the `configure` script is located. If not specified\n                                    conanfile.source_folder is used.\n        \"\"\"\n        # http://jingfenghanmax.blogspot.com.es/2010/09/configure-with-host-target-and-build.html\n        # https://gcc.gnu.org/onlinedocs/gccint/Configure-Terms.html\n        script_folder = os.path.join(self._conanfile.source_folder, build_script_folder) \\\n            if build_script_folder else self._conanfile.source_folder\n\n        configure_args = []\n        configure_args.extend(args or [])\n\n        self._configure_args = \"{} {}\".format(self._configure_args, cmd_args_to_string(configure_args))\n\n        configure_cmd = \"{}/configure\".format(script_folder)\n        subsystem = deduce_subsystem(self._conanfile, scope=\"build\")\n        configure_cmd = subsystem_path(subsystem, configure_cmd)\n        cmd = '\"{}\" {}'.format(configure_cmd, self._configure_args)\n        self._conanfile.run(cmd)\n\n    def make(self, target=None, args=None, makefile=None):\n        \"\"\"\n        Call the make program.\n\n        :param target: (Optional, Defaulted to ``None``): Choose which target to build. This allows\n                       building of e.g., docs, shared libraries or install for some AutoTools\n                       projects\n        :param args: (Optional, Defaulted to ``None``): List of arguments to use for the\n                     ``make`` call.\n        :param makefile: (Optional, Defaulted to ``None``): Allow specifying a custom makefile to use instead of default \"Makefile\"\n        \"\"\"\n        make_program = self._conanfile.conf.get(\"tools.gnu:make_program\",\n                                                default=\"mingw32-make\" if self._use_win_mingw()\n                                                else \"make\")\n        subsystem = deduce_subsystem(self._conanfile, scope=\"build\")\n        make_program = subsystem_path(subsystem, make_program)\n        str_args = self._make_args\n        str_extra_args = \" \".join(args) if args is not None else \"\"\n        jobs = \"\"\n        jobs_already_passed = re.search(r\"(^-j\\d+)|(\\W-j\\d+\\s*)\", join_arguments([str_args, str_extra_args]))\n        if not jobs_already_passed and \"nmake\" not in make_program.lower():\n            njobs = build_jobs(self._conanfile)\n            if njobs:\n                jobs = \"-j{}\".format(njobs)\n        str_makefile = f\"--file={makefile}\" if makefile else None\n\n        command = join_arguments([make_program, str_makefile, target, str_args, str_extra_args, jobs])\n        self._conanfile.run(command)\n\n    def install(self, args=None, target=None, makefile=None):\n        \"\"\"\n        This is just an \"alias\" of ``self.make(target=\"install\")`` or ``self.make(target=\"install-strip\")``\n\n        :param args: (Optional, Defaulted to ``None``): List of arguments to use for the\n                     ``make`` call. By default an argument ``DESTDIR=unix_path(self.package_folder)``\n                     is added to the call if the passed value is ``None``. See more information about\n                     :ref:`tools.microsoft.unix_path() function<conan_tools_microsoft_unix_path>`\n        :param target: (Optional, Defaulted to ``None``): Choose which target to install.\n        :param makefile: (Optional, Defaulted to ``None``): Allow specifying a custom makefile to use instead of default \"Makefile\"\n        \"\"\"\n        if target is None:\n            target = \"install\"\n            do_strip = self._conanfile.conf.get(\"tools.build:install_strip\", check_type=bool)\n            if do_strip:\n                target += \"-strip\"\n        args = args if args else []\n        str_args = \" \".join(args)\n        if \"DESTDIR=\" not in str_args:\n            args.insert(0, \"DESTDIR={}\".format(unix_path(self._conanfile, self._conanfile.package_folder)))\n        self.make(target=target, args=args, makefile=makefile)\n\n    def autoreconf(self, build_script_folder=None, args=None):\n        \"\"\"\n        Call ``autoreconf``\n\n        :param args: (Optional, Defaulted to ``None``): List of arguments to use for the\n                     ``autoreconf`` call.\n        :param build_script_folder: Subfolder where the `configure` script is located. If not specified\n                                    conanfile.source_folder is used.\n        \"\"\"\n        script_folder = os.path.join(self._conanfile.source_folder, build_script_folder) \\\n            if build_script_folder else self._conanfile.source_folder\n        args = args or []\n        command = join_arguments([\"autoreconf\", self._autoreconf_args, cmd_args_to_string(args)])\n        with chdir(self, script_folder):\n            self._conanfile.run(command)\n\n    def _use_win_mingw(self):\n        os_build = self._conanfile.settings_build.get_safe('os')\n\n        if os_build == \"Windows\":\n            compiler = self._conanfile.settings.get_safe(\"compiler\")\n            sub = self._conanfile.settings.get_safe(\"os.subsystem\")\n            if sub in (\"cygwin\", \"msys2\", \"msys\") or compiler == \"qcc\":\n                return False\n            else:\n                if self._conanfile.win_bash:\n                    return False\n                return True\n        return False\n"
  },
  {
    "path": "conan/tools/gnu/autotoolsdeps.py",
    "content": "from conan.internal import check_duplicated_generator\nfrom conan.tools import CppInfo\nfrom conan.tools.env import Environment\nfrom conan.tools.gnu.gnudeps_flags import GnuDepsFlags\n\n\nclass AutotoolsDeps:\n    def __init__(self, conanfile):\n        self._conanfile = conanfile\n        self._environment = None\n        self._ordered_deps = None\n\n    @property\n    def ordered_deps(self):\n        if self._ordered_deps is None:\n            deps = self._conanfile.dependencies.host.topological_sort\n            self._ordered_deps = [dep for dep in reversed(deps.values())]\n        return self._ordered_deps\n\n    def _get_cpp_info(self):\n        ret = CppInfo(self._conanfile)\n        for dep in self.ordered_deps:\n            dep_cppinfo = dep.cpp_info.aggregated_components()\n            # In case we have components, aggregate them, we do not support isolated\n            # \"targets\" with autotools\n            ret.merge(dep_cppinfo)\n        return ret\n\n    def _rpaths_flags(self):\n        flags = []\n        for dep in self.ordered_deps:\n            flags.extend([\"-Wl,-rpath -Wl,{}\".format(libdir) for libdir in dep.cpp_info.libdirs\n                          if dep.options.get_safe(\"shared\", False)])\n        return flags\n\n    @property\n    def environment(self):\n        \"\"\"\n\n        :return: An ``Environment`` object containing the computed variables. If you need\n                 to modify some of the computed values you can access to the ``environment`` object.\n        \"\"\"\n        if self._environment is None:\n            flags = GnuDepsFlags(self._conanfile, self._get_cpp_info())\n\n            # cpp_flags\n            cpp_flags = []\n            cpp_flags.extend(flags.include_paths)\n            cpp_flags.extend(flags.defines)\n\n            # Ldflags\n            ldflags = flags.sharedlinkflags\n            ldflags.extend(flags.exelinkflags)\n            ldflags.extend(flags.frameworks)\n            ldflags.extend(flags.framework_paths)\n            ldflags.extend(flags.lib_paths)\n\n            # set the rpath in Macos so that the library are found in the configure step\n            if self._conanfile.settings.get_safe(\"os\") == \"Macos\":\n                ldflags.extend(self._rpaths_flags())\n\n            # libs\n            libs = flags.libs\n            libs.extend(flags.system_libs)\n\n            # cflags\n            cflags = flags.cflags\n            cxxflags = flags.cxxflags\n\n            env = Environment()\n            env.append(\"CPPFLAGS\", cpp_flags)\n            env.append(\"LIBS\", libs)\n            env.append(\"LDFLAGS\", ldflags)\n            env.append(\"CXXFLAGS\", cxxflags)\n            env.append(\"CFLAGS\", cflags)\n            self._environment = env\n        return self._environment\n\n    def vars(self, scope=\"build\"):\n        return self.environment.vars(self._conanfile, scope=scope)\n\n    def generate(self,  scope=\"build\"):\n        check_duplicated_generator(self, self._conanfile)\n        self.vars(scope).save_script(\"conanautotoolsdeps\")\n"
  },
  {
    "path": "conan/tools/gnu/autotoolstoolchain.py",
    "content": "import os\n\nfrom conan.errors import ConanException\nfrom conan.internal import check_duplicated_generator\nfrom conan.internal.internal_tools import is_universal_arch\nfrom conan.tools.apple.apple import is_apple_os, resolve_apple_flags, apple_extra_flags\nfrom conan.tools.build import cmd_args_to_string, save_toolchain_args\nfrom conan.tools.build.cross_building import cross_building\nfrom conan.tools.build.flags import architecture_flag, architecture_link_flag, build_type_flags, cppstd_flag, \\\n    build_type_link_flags, libcxx_flags, cstd_flag, llvm_clang_front, threads_flags\nfrom conan.tools.env import Environment, VirtualBuildEnv\nfrom conan.tools.gnu.get_gnu_triplet import _get_gnu_triplet\nfrom conan.tools.microsoft import VCVars, msvc_runtime_flag, unix_path, check_min_vs, is_msvc\nfrom conan.internal.model.pkg_type import PackageType\n\n\nclass AutotoolsToolchain:\n\n    def __init__(self, conanfile, namespace=None, prefix=\"/\"):\n        \"\"\"\n        :param conanfile: The current recipe object. Always use ``self``.\n        :param namespace: This argument avoids collisions when you have multiple toolchain calls in\n               the same recipe. By setting this argument, the *conanbuild.conf* file used to pass\n               information to the build helper will be named as *<namespace>_conanbuild.conf*. The default\n               value is ``None`` meaning that the name of the generated file is *conanbuild.conf*. This\n               namespace must be also set with the same value in the constructor of the Autotools build\n               helper so that it reads the information from the proper file.\n        :param prefix: Folder to use for ``--prefix`` argument (\"/\" by default).\n        \"\"\"\n\n        self._conanfile = conanfile\n        self._namespace = namespace\n        self._prefix = prefix\n\n        # Flags\n        self.extra_cxxflags = []\n        self.extra_cflags = []\n        self.extra_ldflags = []\n        self.extra_defines = []\n\n        # Defines\n        self.ndebug = None\n        build_type = self._conanfile.settings.get_safe(\"build_type\")\n        if build_type in ['Release', 'RelWithDebInfo', 'MinSizeRel']:\n            self.ndebug = \"NDEBUG\"\n\n        # TODO: This is also covering compilers like Visual Studio, necessary to test it (&remove?)\n        self.build_type_flags = build_type_flags(self._conanfile)\n        self.build_type_link_flags = build_type_link_flags(self._conanfile.settings)\n\n        self.cppstd = cppstd_flag(self._conanfile)\n        self.cstd = cstd_flag(self._conanfile)\n        self.arch_flag = architecture_flag(self._conanfile)\n        self.arch_ld_flag = architecture_link_flag(self._conanfile)\n        self.threads_flags = threads_flags(self._conanfile)\n        self.libcxx, self.gcc_cxx11_abi = libcxx_flags(self._conanfile)\n        self.fpic = self._conanfile.options.get_safe(\"fPIC\")\n        self.msvc_runtime_flag = self._get_msvc_runtime_flag()\n        self.msvc_extra_flags = self._msvc_extra_flags()\n        self.msvc_runtime_link_flags = []\n        if llvm_clang_front(self._conanfile) == \"clang\":\n            self.msvc_runtime_link_flags = [\"-fuse-ld=lld-link\"]\n\n        self._is_universal_arch = is_universal_arch(conanfile.settings.get_safe(\"arch\"),\n                                                    conanfile.settings.possible_values().get(\"arch\"))\n        if self._is_universal_arch and not is_apple_os(self._conanfile):\n            arch_str = conanfile.settings.get_safe('arch')\n            raise ConanException(f\"Universal arch '{arch_str}' is only supported in Apple OSes\")\n\n        # Cross build triplets\n        self._host = self._conanfile.conf.get(\"tools.gnu:host_triplet\")\n        self._build = self._conanfile.conf.get(\"tools.gnu:build_triplet\")\n        self._target = None\n\n        self.android_cross_flags = {}\n        self._is_cross_building = not self._is_universal_arch and cross_building(self._conanfile)\n        if self._is_cross_building:\n            compiler = self._conanfile.settings.get_safe(\"compiler\")\n            # If cross-building and tools.android:ndk_path is defined, let's try to guess the Android\n            # cross-building flags\n            self.android_cross_flags = self._resolve_android_cross_compilation()\n            # If it's not defined the triplet\n            if not self._host:\n                os_host = conanfile.settings.get_safe(\"os\")\n                arch_host = conanfile.settings.get_safe(\"arch\")\n                self._host = _get_gnu_triplet(os_host, arch_host, compiler=compiler)[\"triplet\"]\n            # Build triplet\n            if not self._build:\n                os_build = conanfile.settings_build.get_safe('os')\n                arch_build = conanfile.settings_build.get_safe('arch')\n                self._build = _get_gnu_triplet(os_build, arch_build, compiler=compiler)[\"triplet\"]\n\n        sysroot = self._conanfile.conf.get(\"tools.build:sysroot\")\n        if sysroot:\n            root = sysroot.replace(\"\\\\\", \"/\")\n            compiler = self._conanfile.settings.get_safe(\"compiler\")\n            self.sysroot_flag = f\"--sysroot {root}\" if compiler != \"qcc\" else f\"-Wc,-isysroot,{root}\"\n        else:\n            self.sysroot_flag = None\n\n        extra_configure_args = self._conanfile.conf.get(\"tools.gnu:extra_configure_args\",\n                                                        check_type=list,\n                                                        default=[])\n\n        self.configure_args = (self._default_configure_shared_flags() +\n                               self._default_configure_install_flags() +\n                               self._get_triplets() +\n                               extra_configure_args)\n        self.autoreconf_args = self._default_autoreconf_flags()\n        self.make_args = []\n        # Apple stuff\n        is_cross_building_osx = (self._is_cross_building\n                                 and conanfile.settings_build.get_safe('os') == \"Macos\"\n                                 and is_apple_os(conanfile)\n                                 and not self._is_universal_arch)\n\n        min_flag, arch_flags, isysroot_flag = (\n            resolve_apple_flags(conanfile, is_cross_building=is_cross_building_osx,\n                                is_universal=self._is_universal_arch)\n        )\n        # https://man.archlinux.org/man/clang.1.en#Target_Selection_Options\n        self.apple_arch_flag = arch_flags\n        # -isysroot makes all includes for your library relative to the build directory\n        self.apple_isysroot_flag = isysroot_flag\n        self.apple_min_version_flag = min_flag\n        self.apple_extra_flags = apple_extra_flags(self._conanfile)\n\n    def _resolve_android_cross_compilation(self):\n        # Issue related: https://github.com/conan-io/conan/issues/13443\n        ret = {}\n        if not self._is_cross_building or not self._conanfile.settings.get_safe(\"os\") == \"Android\":\n            return ret\n        # Setting host if it was not already defined yet\n        arch = self._conanfile.settings.get_safe(\"arch\")\n        android_target = {'armv7': 'armv7a-linux-androideabi',\n                          'armv8': 'aarch64-linux-android',\n                          'x86': 'i686-linux-android',\n                          'x86_64': 'x86_64-linux-android'}.get(arch)\n        self._host = self._host or android_target\n        # Automatic guessing made by Conan (need the NDK path variable defined)\n        conan_vars = {}\n        ndk_path = self._conanfile.conf.get(\"tools.android:ndk_path\", check_type=str)\n        if ndk_path:\n            if self._conanfile.conf.get(\"tools.build:compiler_executables\"):\n                self._conanfile.output.warning(\"tools.build:compiler_executables conf has no effect\"\n                                               \" when tools.android:ndk_path is defined too.\")\n            os_build = self._conanfile.settings_build.get_safe(\"os\")\n            ndk_os_folder = {\n                'Macos': 'darwin',\n                'iOS': 'darwin',\n                'watchOS': 'darwin',\n                'tvOS': 'darwin',\n                'visionOS': 'darwin',\n                'FreeBSD': 'linux',\n                'Linux': 'linux',\n                'Windows': 'windows',\n                'WindowsCE': 'windows',\n                'WindowsStore': 'windows'\n            }.get(os_build, \"linux\")\n            ext = \".cmd\" if os_build == \"Windows\" else \"\"\n            ndk_bin = os.path.join(ndk_path, \"toolchains\", \"llvm\", \"prebuilt\",\n                                   f\"{ndk_os_folder}-x86_64\", \"bin\")\n            android_api_level = self._conanfile.settings.get_safe(\"os.api_level\")\n            conan_vars = {\n                \"CC\": os.path.join(ndk_bin, f\"{android_target}{android_api_level}-clang{ext}\"),\n                \"CXX\": os.path.join(ndk_bin, f\"{android_target}{android_api_level}-clang++{ext}\"),\n                \"LD\": os.path.join(ndk_bin, \"ld\"),\n                \"STRIP\": os.path.join(ndk_bin, \"llvm-strip\"),\n                \"RANLIB\": os.path.join(ndk_bin, \"llvm-ranlib\"),\n                \"AS\": os.path.join(ndk_bin, f\"{android_target}{android_api_level}-clang{ext}\"),\n                \"AR\": os.path.join(ndk_bin, \"llvm-ar\"),\n                \"ADDR2LINE\": os.path.join(ndk_bin, \"llvm-addr2line\"),\n                \"NM\": os.path.join(ndk_bin, \"llvm-nm\"),\n                \"OBJCOPY\": os.path.join(ndk_bin, \"llvm-objcopy\"),\n                \"OBJDUMP\": os.path.join(ndk_bin, \"llvm-objdump\"),\n                \"READELF\": os.path.join(ndk_bin, \"llvm-readelf\"),\n                \"ELFEDIT\": os.path.join(ndk_bin, \"llvm-elfedit\")\n            }\n        build_env = VirtualBuildEnv(self._conanfile, auto_generate=True).vars()\n        for var_name, var_path in conan_vars.items():\n            # User variables have more priority than Conan ones, so if it was defined within\n            # the build env then do nothing\n            if build_env.get(var_name) is None:\n                ret[var_name] = var_path\n        return ret\n\n    def _get_msvc_runtime_flag(self):\n        if llvm_clang_front(self._conanfile) == \"clang\":\n            if self._conanfile.settings.compiler.runtime == \"dynamic\":\n                runtime_type = self._conanfile.settings.get_safe(\"compiler.runtime_type\")\n                library = \"msvcrtd\" if runtime_type == \"Debug\" else \"msvcrt\"\n                # The -D_DEBUG is important to link with the Debug MSVCP140D.dll\n                debug = \"-D_DEBUG \" if runtime_type == \"Debug\" else \"\"\n                return f\"{debug}-D_DLL -D_MT -Xclang --dependent-lib={library}\"\n            return \"\"  # By default it already link statically\n\n        flag = msvc_runtime_flag(self._conanfile)\n        if flag:\n            flag = \"-{}\".format(flag)\n        return flag\n\n    def _msvc_extra_flags(self):\n        if is_msvc(self._conanfile) and check_min_vs(self._conanfile, \"180\",\n                                                     raise_invalid=False):\n            return [\"-FS\"]\n        return []\n\n    def _add_msvc_flags(self, flags):\n        # This is to avoid potential duplicate with users recipes -FS (already some in ConanCenter)\n        return [f for f in self.msvc_extra_flags if f not in flags]\n\n    @staticmethod\n    def _filter_list_empty_fields(v):\n        return list(filter(bool, v))\n\n    @property\n    def cxxflags(self):\n        fpic = \"-fPIC\" if self.fpic else None\n        ret = [self.libcxx, self.cppstd, self.arch_flag, fpic, self.msvc_runtime_flag,\n               self.sysroot_flag] + self.threads_flags\n        apple_flags = [self.apple_isysroot_flag, self.apple_arch_flag, self.apple_min_version_flag]\n        apple_flags += self.apple_extra_flags\n        conf_flags = self._conanfile.conf.get(\"tools.build:cxxflags\", default=[], check_type=list)\n        vs_flag = self._add_msvc_flags(self.extra_cxxflags)\n        ret = ret + self.build_type_flags + apple_flags + self.extra_cxxflags + vs_flag + conf_flags\n        return self._filter_list_empty_fields(ret)\n\n    @property\n    def cflags(self):\n        fpic = \"-fPIC\" if self.fpic else None\n        ret = [self.cstd, self.arch_flag, fpic, self.msvc_runtime_flag, self.sysroot_flag] + self.threads_flags\n        apple_flags = [self.apple_isysroot_flag, self.apple_arch_flag, self.apple_min_version_flag]\n        apple_flags += self.apple_extra_flags\n        conf_flags = self._conanfile.conf.get(\"tools.build:cflags\", default=[], check_type=list)\n        vs_flag = self._add_msvc_flags(self.extra_cflags)\n        ret = ret + self.build_type_flags + apple_flags + self.extra_cflags + vs_flag + conf_flags\n        return self._filter_list_empty_fields(ret)\n\n    @property\n    def ldflags(self):\n        ret = [self.arch_flag, self.sysroot_flag, self.arch_ld_flag] + self.threads_flags\n        apple_flags = [self.apple_isysroot_flag, self.apple_arch_flag, self.apple_min_version_flag]\n        apple_flags += self.apple_extra_flags\n        conf_flags = self._conanfile.conf.get(\"tools.build:sharedlinkflags\", default=[],\n                                              check_type=list)\n        conf_flags.extend(self._conanfile.conf.get(\"tools.build:exelinkflags\", default=[],\n                                                   check_type=list))\n        linker_scripts = self._conanfile.conf.get(\"tools.build:linker_scripts\", default=[],\n                                                  check_type=list)\n        conf_flags.extend([\"-T'\" + linker_script + \"'\" for linker_script in linker_scripts])\n        ret = ret + self.build_type_link_flags + apple_flags + self.extra_ldflags + conf_flags\n        ret = ret + self.msvc_runtime_link_flags\n        return self._filter_list_empty_fields(ret)\n\n    @property\n    def defines(self):\n        conf_flags = self._conanfile.conf.get(\"tools.build:defines\", default=[], check_type=list)\n        ret = [self.ndebug, self.gcc_cxx11_abi] + self.extra_defines + conf_flags\n        return self._filter_list_empty_fields(ret)\n\n    @property\n    def rcflags(self):\n        conf_flags = self._conanfile.conf.get(\"tools.build:rcflags\", default=[], check_type=list)\n        return self._filter_list_empty_fields(conf_flags)\n\n    def _include_obj_arc_flags(self, env):\n        enable_arc = self._conanfile.conf.get(\"tools.apple:enable_arc\", check_type=bool)\n        fobj_arc = \"\"\n        if enable_arc:\n            fobj_arc = \"-fobjc-arc\"\n        if enable_arc is False:\n            fobj_arc = \"-fno-objc-arc\"\n        if fobj_arc:\n            env.append('OBJCFLAGS', [fobj_arc])\n            env.append('OBJCXXFLAGS', [fobj_arc])\n\n    def environment(self):\n        env = Environment()\n        # Setting Android cross-compilation flags (if exist)\n        if self.android_cross_flags:\n            for env_var, env_value in self.android_cross_flags.items():\n                unix_env_value = unix_path(self._conanfile, env_value)\n                env.define(env_var, unix_env_value)\n        else:\n            # Setting user custom compiler executables flags\n            compilers_by_conf = self._conanfile.conf.get(\"tools.build:compiler_executables\",\n                                                         default={},\n                                                         check_type=dict)\n            if compilers_by_conf:\n                compilers_mapping = {\"c\": \"CC\", \"cpp\": \"CXX\", \"cuda\": \"NVCC\", \"fortran\": \"FC\",\n                                     \"rc\": \"RC\"}\n                for comp, env_var in compilers_mapping.items():\n                    if comp in compilers_by_conf:\n                        compiler = compilers_by_conf[comp]\n                        # https://github.com/conan-io/conan/issues/13780\n                        compiler = unix_path(self._conanfile, compiler)\n                        env.define(env_var, compiler)\n            compiler_setting = self._conanfile.settings.get_safe(\"compiler\")\n            if compiler_setting == \"msvc\":\n                # None of them defined, if one is defined by user, user should define the other too\n                if \"c\" not in compilers_by_conf and \"cpp\" not in compilers_by_conf:\n                    env.define(\"CC\", \"cl\")\n                    env.define(\"CXX\", \"cl\")\n\n        env.append(\"CPPFLAGS\", [\"-D{}\".format(d) for d in self.defines])\n        env.append(\"CXXFLAGS\", self.cxxflags)\n        env.append(\"CFLAGS\", self.cflags)\n        env.append(\"LDFLAGS\", self.ldflags)\n        if self.rcflags:\n            env.append(\"RCFLAGS\", self.rcflags)\n        env.prepend_path(\"PKG_CONFIG_PATH\", self._conanfile.generators_folder)\n        # Objective C/C++\n        self._include_obj_arc_flags(env)\n        # Issue related: https://github.com/conan-io/conan/issues/15486\n        if self._is_cross_building and self._conanfile.conf_build:\n            compilers_build_mapping = (\n                self._conanfile.conf_build.get(\"tools.build:compiler_executables\", default={},\n                                               check_type=dict)\n            )\n            if \"c\" in compilers_build_mapping:\n                env.define(\"CC_FOR_BUILD\", compilers_build_mapping[\"c\"])\n            if \"cpp\" in compilers_build_mapping:\n                env.define(\"CXX_FOR_BUILD\", compilers_build_mapping[\"cpp\"])\n        return env\n\n    def vars(self):\n        return self.environment().vars(self._conanfile, scope=\"build\")\n\n    def generate(self, env=None, scope=\"build\"):\n        check_duplicated_generator(self, self._conanfile)\n        env = env or self.environment()\n        env = env.vars(self._conanfile, scope=scope)\n        env.save_script(\"conanautotoolstoolchain\")\n        self.generate_args()\n        VCVars(self._conanfile).generate(scope=scope)\n\n    def _default_configure_shared_flags(self):\n        args = []\n        # Just add these flags if there's a shared option defined (never add to exe's)\n        try:\n            if self._conanfile.package_type is PackageType.SHARED:\n                args.extend([\"--enable-shared\", \"--disable-static\"])\n            elif self._conanfile.package_type is PackageType.STATIC:\n                args.extend([\"--disable-shared\", \"--enable-static\"])\n        except ConanException:\n            pass\n\n        return args\n\n    def _default_configure_install_flags(self):\n        configure_install_flags = []\n\n        def _get_argument(argument_name, cppinfo_name):\n            elements = getattr(self._conanfile.cpp.package, cppinfo_name)\n            return \"--{}=${{prefix}}/{}\".format(argument_name, elements[0]) if elements else \"\"\n\n        # If someone want arguments but not the defaults can pass them in args manually\n        configure_install_flags.extend([f\"--prefix={self._prefix}\",\n                                       _get_argument(\"bindir\", \"bindirs\"),\n                                       _get_argument(\"sbindir\", \"bindirs\"),\n                                       _get_argument(\"libdir\", \"libdirs\"),\n                                       _get_argument(\"includedir\", \"includedirs\"),\n                                       _get_argument(\"oldincludedir\", \"includedirs\"),\n                                       _get_argument(\"datarootdir\", \"resdirs\")])\n        return [el for el in configure_install_flags if el]\n\n    @staticmethod\n    def _default_autoreconf_flags():\n        return [\"--force\", \"--install\"]\n\n    def _get_triplets(self):\n        triplets = []\n        for flag, value in ((\"--host=\", self._host), (\"--build=\", self._build),\n                            (\"--target=\", self._target)):\n            if value:\n                triplets.append(f'{flag}{value}')\n        return triplets\n\n    def update_configure_args(self, updated_flags):\n        \"\"\"\n        Helper to update/prune flags from ``self.configure_args``.\n\n        :param updated_flags: ``dict`` with arguments as keys and their argument values.\n                              Notice that if argument value is ``None``, this one will be pruned.\n        \"\"\"\n        self._update_flags(\"configure_args\", updated_flags)\n\n    def update_make_args(self, updated_flags):\n        \"\"\"\n        Helper to update/prune arguments from ``self.make_args``.\n\n        :param updated_flags: ``dict`` with arguments as keys and their argument values.\n                              Notice that if argument value is ``None``, this one will be pruned.\n        \"\"\"\n        self._update_flags(\"make_args\", updated_flags)\n\n    def update_autoreconf_args(self, updated_flags):\n        \"\"\"\n        Helper to update/prune arguments from ``self.autoreconf_args``.\n\n        :param updated_flags: ``dict`` with arguments as keys and their argument values.\n                              Notice that if argument value is ``None``, this one will be pruned.\n        \"\"\"\n        self._update_flags(\"autoreconf_args\", updated_flags)\n\n    # FIXME: Remove all these update_xxxx whenever xxxx_args are dicts or new ones replace them\n    def _update_flags(self, attr_name, updated_flags):\n\n        def _list_to_dict(flags):\n            ret = {}\n            for flag in flags:\n                # Only splitting if \"=\" is there\n                option = flag.split(\"=\", 1)\n                if len(option) == 2:\n                    ret[option[0]] = option[1]\n                else:\n                    ret[option[0]] = \"\"\n            return ret\n\n        def _dict_to_list(flags):\n            return [f\"{k}={v}\" if v else k for k, v in flags.items() if v is not None]\n\n        self_args = getattr(self, attr_name)\n        # FIXME: if xxxxx_args -> dict-type at some point, all these lines could be removed\n        options = _list_to_dict(self_args)\n        # Add/update/remove the current xxxxx_args with the new flags given\n        options.update(updated_flags)\n        # Update the current ones\n        setattr(self, attr_name, _dict_to_list(options))\n\n    def generate_args(self):\n        args = {\"configure_args\": cmd_args_to_string(self.configure_args),\n                \"make_args\":  cmd_args_to_string(self.make_args),\n                \"autoreconf_args\": cmd_args_to_string(self.autoreconf_args)}\n        save_toolchain_args(args, namespace=self._namespace)\n"
  },
  {
    "path": "conan/tools/gnu/get_gnu_triplet.py",
    "content": "from conan.errors import ConanException\n\n\ndef _get_gnu_arch(os_, arch):\n    # Calculate the arch\n    machine = {\"x86\": \"i686\",\n               \"x86_64\": \"x86_64\",\n               \"armv8\": \"aarch64\",\n               \"armv8_32\": \"aarch64\",  # https://wiki.linaro.org/Platform/arm64-ilp32\n               \"armv8.3\": \"aarch64\",\n               \"asm.js\": \"asmjs\",\n               \"wasm\": \"wasm32\",\n               \"wasm64\": \"wasm64\",\n               }.get(arch, None)\n\n    if not machine:\n        # https://wiki.debian.org/Multiarch/Tuples\n        if os_ == \"AIX\":\n            if \"ppc32\" in arch:\n                machine = \"rs6000\"\n            elif \"ppc64\" in arch:\n                machine = \"powerpc\"\n        elif \"arm\" in arch:\n            machine = \"arm\"\n        elif \"ppc32be\" in arch:\n            machine = \"powerpcbe\"\n        elif \"ppc64le\" in arch:\n            machine = \"powerpc64le\"\n        elif \"ppc64\" in arch:\n            machine = \"powerpc64\"\n        elif \"ppc32\" in arch:\n            machine = \"powerpc\"\n        elif \"mips64\" in arch:\n            machine = \"mips64\"\n        elif \"mips\" in arch:\n            machine = \"mips\"\n        elif \"sparcv9\" in arch:\n            machine = \"sparc64\"\n        elif \"sparc\" in arch:\n            machine = \"sparc\"\n        elif \"s390x\" in arch:\n            machine = \"s390x-ibm\"\n        elif \"s390\" in arch:\n            machine = \"s390-ibm\"\n        elif \"sh4\" in arch:\n            machine = \"sh4\"\n        elif \"e2k\" in arch:\n            # https://lists.gnu.org/archive/html/config-patches/2015-03/msg00000.html\n            machine = \"e2k-unknown\"\n        elif \"riscv64\" in arch:\n            machine = 'riscv64'\n        elif 'riscv32' in arch:\n            machine = \"riscv32\"\n\n    if machine is None:\n        raise ConanException(\"Unknown '%s' machine, Conan doesn't know how to \"\n                             \"translate it to the GNU triplet, please report at \"\n                             \" https://github.com/conan-io/conan/issues\" % arch)\n    return machine\n\n\ndef _get_gnu_os(os_, arch, compiler=None):\n    # Calculate the OS\n    if compiler == \"gcc\":\n        windows_op = \"w64-mingw32\"\n    else:\n        windows_op = \"unknown-windows\"\n\n    op_system = {\"Windows\": windows_op,\n                 \"Linux\": \"linux-gnu\",\n                 \"Darwin\": \"apple-darwin\",\n                 \"Android\": \"linux-android\",\n                 \"Macos\": \"apple-darwin\",\n                 \"iOS\": \"apple-ios\",\n                 \"watchOS\": \"apple-watchos\",\n                 \"tvOS\": \"apple-tvos\",\n                 \"visionOS\": \"apple-xros\",\n                 # NOTE: it technically must be \"asmjs-unknown-emscripten\" or\n                 # \"wasm32-unknown-emscripten\", but it's not recognized by old config.sub versions\n                 \"Emscripten\": \"local-emscripten\",\n                 \"AIX\": \"ibm-aix\",\n                 \"Neutrino\": \"nto-qnx\"}.get(os_, os_.lower())\n\n    if os_ in (\"Linux\", \"Android\"):\n        if \"arm\" in arch and \"armv8\" not in arch:\n            op_system += \"eabi\"\n\n        if (arch == \"armv5hf\" or arch == \"armv7hf\") and os_ == \"Linux\":\n            op_system += \"hf\"\n\n        if arch == \"armv8_32\" and os_ == \"Linux\":\n            op_system += \"_ilp32\"  # https://wiki.linaro.org/Platform/arm64-ilp32\n    return op_system\n\n\ndef _get_gnu_triplet(os_, arch, compiler=None):\n    \"\"\"\n    Returns string with <machine>-<vendor>-<op_system> triplet (<vendor> can be omitted in practice)\n\n    :param os_: os to be used to create the triplet\n    :param arch: arch to be used to create the triplet\n    :param compiler: compiler used to create the triplet (only needed fo windows)\n    \"\"\"\n    if os_ == \"Windows\" and compiler is None:\n        raise ConanException(\"'compiler' parameter for 'get_gnu_triplet()' is not specified and \"\n                             \"needed for os=Windows\")\n    machine = _get_gnu_arch(os_, arch)\n    op_system = _get_gnu_os(os_, arch, compiler=compiler)\n    return {\n        'machine': machine,\n        'system': op_system,\n        'triplet': f\"{machine}-{op_system}\"\n    }\n"
  },
  {
    "path": "conan/tools/gnu/gnudeps_flags.py",
    "content": "\"\"\"\n    This is a helper class which offers a lot of useful methods and attributes\n\"\"\"\n# FIXME: only for tools.gnu? perhaps it should be a global module\n\nfrom conan.tools.apple.apple import is_apple_os\nfrom conan.tools.microsoft import is_msvc\nfrom conan.internal.subsystems import subsystem_path, deduce_subsystem\n\n\nclass GnuDepsFlags:\n\n    def __init__(self, conanfile, cpp_info):\n        self._conanfile = conanfile\n        self._subsystem = deduce_subsystem(conanfile, scope=\"build\")\n\n        # From cppinfo, calculated flags\n        self.include_paths = self._format_include_paths(cpp_info.includedirs)\n        self.lib_paths = self._format_library_paths(cpp_info.libdirs)\n        self.defines = self._format_defines(cpp_info.defines)\n        self.libs = self._format_libraries(cpp_info.libs)\n        self.frameworks = self._format_frameworks(cpp_info.frameworks)\n        self.framework_paths = self._format_frameworks(cpp_info.frameworkdirs, is_path=True)\n\n        # Direct flags\n        self.cxxflags = cpp_info.cxxflags or []\n        self.cflags = cpp_info.cflags or []\n        self.sharedlinkflags = cpp_info.sharedlinkflags or []\n        self.exelinkflags = cpp_info.exelinkflags or []\n        self.system_libs = self._format_libraries(cpp_info.system_libs)\n\n        # Not used?\n        # self.bin_paths\n        # self.build_paths\n        # self.src_paths\n\n    _GCC_LIKE = ['clang', 'apple-clang', 'gcc']\n\n    @staticmethod\n    def _format_defines(defines):\n        return [\"-D%s\" % define for define in defines] if defines else []\n\n    def _format_frameworks(self, frameworks, is_path=False):\n        \"\"\"\n        returns an appropriate compiler flags to link with Apple Frameworks\n        or an empty array, if Apple Frameworks aren't supported by the given compiler\n        \"\"\"\n        os_ = self._conanfile.settings.get_safe(\"os\")\n        if not frameworks or not is_apple_os(self._conanfile):\n            return []\n        compiler = self._conanfile.settings.get_safe(\"compiler\")\n        if str(compiler) not in self._GCC_LIKE:\n            return []\n        if is_path:\n            return [\"-F\\\"%s\\\"\" % self._adjust_path(framework_path) for framework_path in frameworks]\n        else:\n            return [\"-framework %s\" % framework for framework in frameworks]\n\n    def _format_include_paths(self, include_paths):\n        if not include_paths:\n            return []\n        pattern = \"/I%s\" if is_msvc(self._conanfile) else \"-I%s\"\n        return [pattern % (self._adjust_path(include_path))\n                for include_path in include_paths if include_path]\n\n    def _format_library_paths(self, library_paths):\n        if not library_paths:\n            return []\n        pattern = \"/LIBPATH:%s\" if is_msvc(self._conanfile) else \"-L%s\"\n        return [pattern % self._adjust_path(library_path)\n                for library_path in library_paths if library_path]\n\n    def _format_libraries(self, libraries):\n        if not libraries:\n            return []\n\n        result = []\n\n        is_visual = is_msvc(self._conanfile)\n        for library in libraries:\n            if is_visual:\n                if not library.endswith(\".lib\"):\n                    library += \".lib\"\n                result.append(library)\n            else:\n                result.append(\"-l%s\" % library)\n        return result\n\n    def _adjust_path(self, path):\n        if is_msvc(self._conanfile):\n            path = path.replace('/', '\\\\')\n        else:\n            path = path.replace('\\\\', '/')\n\n        path = subsystem_path(self._subsystem, path)\n        return '\"%s\"' % path if ' ' in path else path\n"
  },
  {
    "path": "conan/tools/gnu/gnutoolchain.py",
    "content": "import os\n\nfrom conan.errors import ConanException\nfrom conan.internal import check_duplicated_generator\nfrom conan.internal.internal_tools import is_universal_arch\nfrom conan.tools.apple.apple import is_apple_os, resolve_apple_flags, apple_extra_flags\nfrom conan.tools.build import cmd_args_to_string, save_toolchain_args\nfrom conan.tools.build.cross_building import cross_building\nfrom conan.tools.build.flags import architecture_flag, architecture_link_flag, build_type_flags, cppstd_flag, \\\n    build_type_link_flags, \\\n    libcxx_flags, llvm_clang_front, threads_flags\nfrom conan.tools.env import Environment, VirtualBuildEnv\nfrom conan.tools.gnu.get_gnu_triplet import _get_gnu_triplet\nfrom conan.tools.microsoft import VCVars, msvc_runtime_flag, unix_path, check_min_vs, is_msvc\nfrom conan.internal.model.pkg_type import PackageType\n\n\nclass GnuToolchain:\n    \"\"\"\n    GnuToolchain generator.\n\n    Note: it's based on legacy AutotoolsToolchain but with a more modern and usable UX\n    \"\"\"\n    script_name = \"conangnutoolchain\"\n\n    def __init__(self, conanfile, namespace=None, prefix=\"/\"):\n        \"\"\"\n        :param conanfile: The current recipe object. Always use ``self``.\n        :param namespace: This argument avoids collisions when you have multiple toolchain calls in\n               the same recipe. By setting this argument, the *conanbuild.conf* file used to pass\n               information to the build helper will be named as *<namespace>_conanbuild.conf*. The default\n               value is ``None`` meaning that the name of the generated file is *conanbuild.conf*. This\n               namespace must be also set with the same value in the constructor of the Autotools build\n               helper so that it reads the information from the proper file.\n        :param prefix: Folder to use for ``--prefix`` argument (\"/\" by default).\n        \"\"\"\n        self._conanfile = conanfile\n        self._namespace = namespace\n        self._is_apple_system = is_apple_os(self._conanfile)\n        self._prefix = prefix\n        # Extra flags\n        self.extra_cxxflags = []\n        self.extra_cflags = []\n        self.extra_ldflags = []\n        self.extra_defines = []\n        # Extra environment definitions\n        self.extra_env = Environment()\n        # Defines\n        self.ndebug = None\n        build_type = self._conanfile.settings.get_safe(\"build_type\")\n        if build_type in ['Release', 'RelWithDebInfo', 'MinSizeRel']:\n            self.ndebug = \"NDEBUG\"\n\n        # TODO: This is also covering compilers like Visual Studio, necessary to test it (&remove?)\n        self.build_type_flags = build_type_flags(self._conanfile)\n        self.build_type_link_flags = build_type_link_flags(self._conanfile.settings)\n\n        self.cppstd = cppstd_flag(self._conanfile)\n        self.arch_flag = architecture_flag(self._conanfile)\n        self.arch_ld_flag = architecture_link_flag(self._conanfile)\n        self.threads_flags = threads_flags(self._conanfile)\n        self.libcxx, self.gcc_cxx11_abi = libcxx_flags(self._conanfile)\n        self.fpic = self._conanfile.options.get_safe(\"fPIC\")\n        self.msvc_runtime_flag = self._get_msvc_runtime_flag()\n        self.msvc_extra_flags = self._msvc_extra_flags()\n        self.msvc_runtime_link_flags = []\n        if llvm_clang_front(self._conanfile) == \"clang\":\n            self.msvc_runtime_link_flags = [\"-fuse-ld=lld-link\"]\n\n        self._is_universal_arch = is_universal_arch(conanfile.settings.get_safe(\"arch\"),\n                                                    conanfile.settings.possible_values().get(\"arch\"))\n        if self._is_universal_arch and not is_apple_os(self._conanfile):\n            arch_str = conanfile.settings.get_safe('arch')\n            raise ConanException(f\"Universal arch '{arch_str}' is only supported in Apple OSes\")\n\n        extra_configure_args = self._conanfile.conf.get(\"tools.gnu:extra_configure_args\",\n                                                        check_type=list,\n                                                        default=[])\n        extra_configure_args = {it: None for it in extra_configure_args}\n\n        # Host/Build triplets\n        self.triplets_info = {\n            \"host\": {\"triplet\": self._conanfile.conf.get(\"tools.gnu:host_triplet\")},\n            \"build\": {\"triplet\": self._conanfile.conf.get(\"tools.gnu:build_triplet\")}\n        }\n        self._is_cross_building = not self._is_universal_arch and cross_building(self._conanfile)\n        if self._is_cross_building:\n            compiler = self._conanfile.settings.get_safe(\"compiler\")\n            # Host triplet\n            if not self.triplets_info[\"host\"][\"triplet\"]:\n                os_host = conanfile.settings.get_safe(\"os\")\n                arch_host = conanfile.settings.get_safe(\"arch\")\n                self.triplets_info[\"host\"] = _get_gnu_triplet(os_host, arch_host, compiler=compiler)\n            # Build triplet\n            if not self.triplets_info[\"build\"][\"triplet\"]:\n                os_build = conanfile.settings_build.get_safe('os')\n                arch_build = conanfile.settings_build.get_safe('arch')\n                self.triplets_info[\"build\"] = _get_gnu_triplet(os_build, arch_build, compiler=compiler)\n\n        sysroot = self._conanfile.conf.get(\"tools.build:sysroot\")\n        if sysroot:\n            root = sysroot.replace(\"\\\\\", \"/\")\n            compiler = self._conanfile.settings.get_safe(\"compiler\")\n            self.sysroot_flag = f\"--sysroot {root}\" if compiler != \"qcc\" else f\"-Wc,-isysroot,{root}\"\n        else:\n            self.sysroot_flag = None\n\n        self.configure_args = {}\n        self.autoreconf_args = {\"--force\": None, \"--install\": None}\n        self.make_args = {}\n        # Initializing configure arguments: triplets, shared flags, dirs flags, etc.\n        self.configure_args.update(self._get_default_configure_shared_flags())\n        self.configure_args.update(self._get_default_configure_install_flags())\n        self.configure_args.update(self._get_default_triplets())\n        self.configure_args.update(extra_configure_args)\n        # Apple stuff\n        is_cross_building_osx = (self._is_cross_building\n                                 and conanfile.settings_build.get_safe('os') == \"Macos\"\n                                 and is_apple_os(conanfile)\n                                 and not self._is_universal_arch)\n\n        min_flag, arch_flags, isysroot_flag = (\n            resolve_apple_flags(conanfile, is_cross_building=is_cross_building_osx,\n                                is_universal=self._is_universal_arch)\n        )\n        # https://man.archlinux.org/man/clang.1.en#Target_Selection_Options\n        self.apple_arch_flag = arch_flags\n        # -isysroot makes all includes for your library relative to the build directory\n        self.apple_isysroot_flag = isysroot_flag\n        self.apple_min_version_flag = min_flag\n        self.apple_extra_flags = apple_extra_flags(conanfile)\n        # Default initial environment flags\n        self._initialize_default_extra_env()\n\n    def yes_no(self, option_name, default=None, negated=False):\n        \"\"\"\n        Simple wrapper to return \"yes\" or \"no\" depending on whether option_name is\n        evaluated as True or False.\n\n        :param option_name: option name.\n        :param default: Default value to return.\n        :param negated: Negates the option value if True.\n        :return: \"yes\" or \"no\" depending on whether option_name is True or False.\n        \"\"\"\n        option_value = bool(self._conanfile.options.get_safe(option_name, default=default))\n        option_value = not option_value if negated else option_value\n        return \"yes\" if option_value else \"no\"\n\n    def _resolve_android_cross_compilation(self):\n        # Issue related: https://github.com/conan-io/conan/issues/13443\n        ret = {}\n        if not self._is_cross_building or not self._conanfile.settings.get_safe(\"os\") == \"Android\":\n            return ret\n        # Setting host if it was not already defined yet\n        arch = self._conanfile.settings.get_safe(\"arch\")\n        android_target = {'armv7': 'armv7a-linux-androideabi',\n                          'armv8': 'aarch64-linux-android',\n                          'x86': 'i686-linux-android',\n                          'x86_64': 'x86_64-linux-android'}.get(arch)\n        if self.triplets_info[\"host\"][\"triplet\"] is None:\n            self.triplets_info[\"host\"][\"triplet\"] = android_target\n        # Automatic guessing made by Conan (need the NDK path variable defined)\n        conan_vars = {}\n        ndk_path = self._conanfile.conf.get(\"tools.android:ndk_path\", check_type=str)\n        if ndk_path:\n            os_build = self._conanfile.settings_build.get_safe(\"os\")\n            ndk_os_folder = {\n                'Macos': 'darwin',\n                'iOS': 'darwin',\n                'watchOS': 'darwin',\n                'tvOS': 'darwin',\n                'visionOS': 'darwin',\n                'FreeBSD': 'linux',\n                'Linux': 'linux',\n                'Windows': 'windows',\n                'WindowsCE': 'windows',\n                'WindowsStore': 'windows'\n            }.get(os_build, \"linux\")\n            ext = \".cmd\" if os_build == \"Windows\" else \"\"\n            ndk_bin = os.path.join(ndk_path, \"toolchains\", \"llvm\", \"prebuilt\",\n                                   f\"{ndk_os_folder}-x86_64\", \"bin\")\n            android_api_level = self._conanfile.settings.get_safe(\"os.api_level\")\n            conan_vars = {\n                \"CC\": os.path.join(ndk_bin, f\"{android_target}{android_api_level}-clang{ext}\"),\n                \"CXX\": os.path.join(ndk_bin, f\"{android_target}{android_api_level}-clang++{ext}\"),\n                \"LD\": os.path.join(ndk_bin, \"ld\"),\n                \"STRIP\": os.path.join(ndk_bin, \"llvm-strip\"),\n                \"RANLIB\": os.path.join(ndk_bin, \"llvm-ranlib\"),\n                \"AS\": os.path.join(ndk_bin, f\"{android_target}{android_api_level}-clang{ext}\"),\n                \"AR\": os.path.join(ndk_bin, \"llvm-ar\"),\n                \"ADDR2LINE\": os.path.join(ndk_bin, \"llvm-addr2line\"),\n                \"NM\": os.path.join(ndk_bin, \"llvm-nm\"),\n                \"OBJCOPY\": os.path.join(ndk_bin, \"llvm-objcopy\"),\n                \"OBJDUMP\": os.path.join(ndk_bin, \"llvm-objdump\"),\n                \"READELF\": os.path.join(ndk_bin, \"llvm-readelf\"),\n                \"ELFEDIT\": os.path.join(ndk_bin, \"llvm-elfedit\")\n            }\n        build_env = VirtualBuildEnv(self._conanfile, auto_generate=True).vars()\n        for var_name, var_path in conan_vars.items():\n            # User variables have more priority than Conan ones, so if it was defined within\n            # the build env then do nothing\n            if build_env.get(var_name) is None:\n                ret[var_name] = var_path\n        return ret\n\n    def _resolve_compilers_mapping_variables(self):\n        ret = {}\n        # Configuration map\n        compilers_mapping = {\"c\": \"CC\", \"cpp\": \"CXX\", \"cuda\": \"NVCC\", \"fortran\": \"FC\",\n                             \"rc\": \"RC\", \"nm\": \"NM\", \"ranlib\": \"RANLIB\",\n                             \"objdump\": \"OBJDUMP\", \"strip\": \"STRIP\"}\n        # Compiler definitions by conf\n        compilers_by_conf = self._conanfile.conf.get(\"tools.build:compiler_executables\",\n                                                     default={}, check_type=dict)\n        if compilers_by_conf:\n            for comp, env_var in compilers_mapping.items():\n                if comp in compilers_by_conf:\n                    compiler = compilers_by_conf[comp]\n                    # https://github.com/conan-io/conan/issues/13780\n                    compiler = unix_path(self._conanfile, compiler)\n                    ret[env_var] = compiler  # User/tools ones have precedence\n        return ret\n\n    def _initialize_default_extra_env(self):\n        \"\"\"Initialize the default environment variables.\"\"\"\n        # If it's an Android cross-compilation\n        extra_env_vars = self._resolve_android_cross_compilation()\n        if not extra_env_vars:\n            # Normally, these are the most common default flags used by MSVC in Windows\n            if is_msvc(self._conanfile):\n                extra_env_vars = {\"CC\": \"cl -nologo\",\n                                  \"CXX\": \"cl -nologo\",\n                                  \"LD\": \"link -nologo\",\n                                  \"AR\": \"lib\",\n                                  \"NM\": \"dumpbin -symbols\",\n                                  \"OBJDUMP\": \":\",\n                                  \"RANLIB\": \":\",\n                                  \"STRIP\": \":\"}\n            extra_env_vars.update(self._resolve_compilers_mapping_variables())\n        # Issue related: https://github.com/conan-io/conan/issues/15486\n        if self._is_cross_building and self._conanfile.conf_build:\n            compilers_build_mapping = (\n                self._conanfile.conf_build.get(\"tools.build:compiler_executables\", default={},\n                                               check_type=dict)\n            )\n            if \"c\" in compilers_build_mapping:\n                extra_env_vars[\"CC_FOR_BUILD\"] = compilers_build_mapping[\"c\"]\n            if \"cpp\" in compilers_build_mapping:\n                extra_env_vars[\"CXX_FOR_BUILD\"] = compilers_build_mapping[\"cpp\"]\n        # Update the extra_env attribute with all the compiler values\n        for env_var, env_value in extra_env_vars.items():\n            self.extra_env.define(env_var, env_value)\n\n    def _get_msvc_runtime_flag(self):\n        if llvm_clang_front(self._conanfile) == \"clang\":\n            if self._conanfile.settings.compiler.runtime == \"dynamic\":\n                runtime_type = self._conanfile.settings.get_safe(\"compiler.runtime_type\")\n                library = \"msvcrtd\" if runtime_type == \"Debug\" else \"msvcrt\"\n                debug = \"-D_DEBUG \" if runtime_type == \"Debug\" else \"\"\n                return f\"{debug}-D_DLL -D_MT -Xclang --dependent-lib={library}\"\n            return \"\"  # By default it already link statically\n\n        flag = msvc_runtime_flag(self._conanfile)\n        return f\"-{flag}\" if flag else \"\"\n\n    def _msvc_extra_flags(self):\n        if is_msvc(self._conanfile) and check_min_vs(self._conanfile, \"180\", raise_invalid=False):\n            return [\"-FS\"]\n        return []\n\n    def _add_msvc_flags(self, flags):\n        # This is to avoid potential duplicate with users recipes -FS (alreday some in ConanCenter)\n        return [f for f in self.msvc_extra_flags if f not in flags]\n\n    @staticmethod\n    def _filter_list_empty_fields(v):\n        return list(filter(bool, v))\n\n    @staticmethod\n    def _dict_to_list(flags):\n        return [f\"{k}={v}\" if v is not None else k for k, v in flags.items()]\n\n    @property\n    def cxxflags(self):\n        fpic = \"-fPIC\" if self.fpic else None\n        ret = [self.libcxx, self.cppstd, self.arch_flag, fpic, self.msvc_runtime_flag,\n               self.sysroot_flag] + self.threads_flags\n        apple_flags = [self.apple_isysroot_flag, self.apple_arch_flag, self.apple_min_version_flag]\n        apple_flags += self.apple_extra_flags\n        conf_flags = self._conanfile.conf.get(\"tools.build:cxxflags\", default=[], check_type=list)\n        vs_flag = self._add_msvc_flags(self.extra_cxxflags)\n        ret = ret + self.build_type_flags + apple_flags + self.extra_cxxflags + vs_flag + conf_flags\n        return self._filter_list_empty_fields(ret)\n\n    @property\n    def cflags(self):\n        fpic = \"-fPIC\" if self.fpic else None\n        ret = [self.arch_flag, fpic, self.msvc_runtime_flag, self.sysroot_flag] + self.threads_flags\n        apple_flags = [self.apple_isysroot_flag, self.apple_arch_flag, self.apple_min_version_flag]\n        apple_flags += self.apple_extra_flags\n        conf_flags = self._conanfile.conf.get(\"tools.build:cflags\", default=[], check_type=list)\n        vs_flag = self._add_msvc_flags(self.extra_cflags)\n        ret = ret + self.build_type_flags + apple_flags + self.extra_cflags + vs_flag + conf_flags\n        return self._filter_list_empty_fields(ret)\n\n    @property\n    def ldflags(self):\n        ret = [self.arch_flag, self.sysroot_flag, self.arch_ld_flag] + self.threads_flags\n        apple_flags = [self.apple_isysroot_flag, self.apple_arch_flag, self.apple_min_version_flag]\n        apple_flags += self.apple_extra_flags\n        conf_flags = self._conanfile.conf.get(\"tools.build:sharedlinkflags\", default=[],\n                                              check_type=list)\n        conf_flags.extend(self._conanfile.conf.get(\"tools.build:exelinkflags\", default=[],\n                                                   check_type=list))\n        linker_scripts = self._conanfile.conf.get(\"tools.build:linker_scripts\", default=[],\n                                                  check_type=list)\n        conf_flags.extend([\"-T'\" + linker_script + \"'\" for linker_script in linker_scripts])\n        ret = ret + self.build_type_link_flags + apple_flags + self.extra_ldflags + conf_flags\n        ret = ret + self.msvc_runtime_link_flags\n        return self._filter_list_empty_fields(ret)\n\n    @property\n    def defines(self):\n        conf_flags = self._conanfile.conf.get(\"tools.build:defines\", default=[], check_type=list)\n        ret = [self.ndebug, self.gcc_cxx11_abi] + self.extra_defines + conf_flags\n        return self._filter_list_empty_fields(ret)\n\n    @property\n    def rcflags(self):\n        conf_flags = self._conanfile.conf.get(\"tools.build:rcflags\", default=[], check_type=list)\n        return self._filter_list_empty_fields(conf_flags)\n\n    def _get_default_configure_shared_flags(self):\n        args = {}\n        # Just add these flags if there's a shared option defined (never add to exe's)\n        if self._conanfile.package_type is PackageType.SHARED:\n            args = {\"--enable-shared\": None, \"--disable-static\": None}\n        elif self._conanfile.package_type is PackageType.STATIC:\n            args = {\"--disable-shared\": None, \"--enable-static\": None}\n        return args\n\n    def _get_default_configure_install_flags(self):\n        configure_install_flags = {\"--prefix\": self._prefix}\n        # If someone want arguments but not the defaults can pass them in args manually\n        for flag_name, cppinfo_name in [(\"bindir\", \"bindirs\"), (\"sbindir\", \"bindirs\"),\n                                        (\"libdir\", \"libdirs\"), (\"includedir\", \"includedirs\"),\n                                        (\"oldincludedir\", \"includedirs\"),\n                                        (\"datarootdir\", \"resdirs\")]:\n            elements = getattr(self._conanfile.cpp.package, cppinfo_name)\n            cppinfo_value = f\"${{prefix}}/{elements[0]}\" if elements else None\n            if cppinfo_value:\n                configure_install_flags[f\"--{flag_name}\"] = cppinfo_value\n        return configure_install_flags\n\n    def _get_default_triplets(self):\n        triplets = {}\n        for context, info in self.triplets_info.items():\n            if info.get(\"triplet\") is not None:\n                triplets[f\"--{context}\"] = info[\"triplet\"]\n        return triplets\n\n    def _include_obj_arc_flags(self, env):\n        enable_arc = self._conanfile.conf.get(\"tools.apple:enable_arc\", check_type=bool)\n        fobj_arc = \"\"\n        if enable_arc:\n            fobj_arc = \"-fobjc-arc\"\n        if enable_arc is False:\n            fobj_arc = \"-fno-objc-arc\"\n        if fobj_arc:\n            env.append('OBJCFLAGS', [fobj_arc])\n            env.append('OBJCXXFLAGS', [fobj_arc])\n\n    @property\n    def _environment(self):\n        env = Environment()\n        # Flags and defines\n        env.append(\"CPPFLAGS\", [\"-D{}\".format(d) for d in self.defines])\n        env.append(\"CXXFLAGS\", self.cxxflags)\n        env.append(\"CFLAGS\", self.cflags)\n        env.append(\"LDFLAGS\", self.ldflags)\n        if self.rcflags:\n            env.append(\"RCFLAGS\", self.rcflags)\n        env.prepend_path(\"PKG_CONFIG_PATH\", self._conanfile.generators_folder)\n        # Objective C/C++\n        self._include_obj_arc_flags(env)\n        # Let's compose with user extra env variables defined (user ones have precedence)\n        return self.extra_env.compose_env(env)\n\n    def generate(self):\n        check_duplicated_generator(self, self._conanfile)\n        # Composing both environments. User extra_env definitions has precedence\n        env_vars = self._environment.vars(self._conanfile)\n        env_vars.save_script(GnuToolchain.script_name)\n        # Converts all the arguments into strings\n        args = {\n            \"configure_args\": cmd_args_to_string(self._dict_to_list(self.configure_args)),\n            \"make_args\": cmd_args_to_string(self._dict_to_list(self.make_args)),\n            \"autoreconf_args\": cmd_args_to_string(self._dict_to_list(self.autoreconf_args))\n        }\n        save_toolchain_args(args, namespace=self._namespace)\n        VCVars(self._conanfile).generate()\n"
  },
  {
    "path": "conan/tools/gnu/makedeps.py",
    "content": "\"\"\"Makefile generator for Conan dependencies\n\nThis generator creates a Makefile (conandeps.mk) with variables for each dependency and consider their components.\nTo simplify its usage, it also creates global variables with aggregated values from all dependencies.\nThis generator does not work like a toolchain, it does not include settings.\n\nFor better customization, it allows appending prefixes as flags variables:\n\n- CONAN_LIB_FLAG: Add a prefix to all libs variables, e.g. -l\n- CONAN_DEFINE_FLAG: Add a prefix to all defines variables, e.g. -D\n- CONAN_SYSTEM_LIB_FLAG: Add a prefix to all system_libs variables, e.g. -l\n- CONAN_INCLUDE_DIR_FLAG: Add a prefix to all include dirs variables, e.g. -I\n- CONAN_LIB_DIR_FLAG: Add a prefix to all lib dirs variables, e.g. -L\n- CONAN_BIN_DIR_FLAG: Add a prefix to all bin dirs variables, e.g. -L\n\n\nThe conandeps.mk file layout is as follows:\n\n- CONAN_DEPS: list all transitive and direct dependencies names without version (e.g. zlib)\n- Iterate over each dependency and its components:\n    - Prints name, version, root folder, regular folders, libs and flags\n    - Components are rootified to avoid repeating same prefix twice for the root folder\n    - Components libs, folder and flags are solved as variables to avoid repeating same name twice\n- Aggregated global variables for simplification, sum all dependencies to common variables (e.g. CONAN_INCLUDE_DIRS)\n\n\"\"\"\n\nimport os\nimport re\nimport textwrap\n\nfrom jinja2 import Template, StrictUndefined\nfrom typing import Optional\n\nfrom conan.api.output import ConanOutput\nfrom conan.internal import check_duplicated_generator\nfrom conan.tools.files import save\n\n\nCONAN_MAKEFILE_FILENAME = \"conandeps.mk\"\n\n\ndef _get_formatted_dirs(folders: list, prefix_path_: str, name: str) -> list:\n    \"\"\" Format the directories to be used in the makefile, adding the prefix path if needed\n    :param folders: list of directories\n    :param prefix_path_: prefix path\n    :param name: component name\n    :return: list of formatted directories\n    \"\"\"\n    ret = []\n    for directory in folders:\n        if directory.startswith(\"$(CONAN\"):  # already a variable\n            ret.append(directory)\n            continue\n        directory = os.path.normpath(directory).replace(\"\\\\\", \"/\")\n        prefix = \"\"\n        if not os.path.isabs(directory):\n            prefix = f\"$(CONAN_ROOT_{name})/\"\n        elif directory.startswith(prefix_path_):\n            prefix = f\"$(CONAN_ROOT_{name})/\"\n            directory = os.path.relpath(directory, prefix_path_).replace(\"\\\\\", \"/\")\n        ret.append(f\"{prefix}{directory}\")\n    return ret\n\n\ndef _makefy(name: str) -> str:\n    \"\"\"\n    Convert a name to Make-variable-friendly syntax\n    :param name: The name to be converted\n    :return: Safe makefile variable, not including bad characters that are not parsed correctly\n    \"\"\"\n    return re.sub(r'[^0-9A-Z_]', '_', name.upper())\n\n\ndef _makefy_properties(properties: Optional[dict]) -> dict:\n    \"\"\"\n    Convert property dictionary keys to Make-variable-friendly syntax\n    :param properties: The property dictionary to be converted (None is also accepted)\n    :return: Modified property dictionary with keys not including bad characters that are not parsed correctly\n    \"\"\"\n    return {_makefy(name): value for name, value in properties.items()} if properties else {}\n\n\ndef _check_property_value(name, value, output):\n    if \"\\n\" in value:\n        output.warning(f\"Skipping propery '{name}' because it contains newline\")\n        return False\n    else:\n        return True\n\n\ndef _filter_properties(properties: Optional[dict], output) -> dict:\n    \"\"\"\n    Filter out properties whose values contain newlines, because they would break the generated makefile\n    :param properties: A property dictionary (None is also accepted)\n    :return: A property dictionary without the properties containing newlines\n    \"\"\"\n    return {name: value for name, value in properties.items() if _check_property_value(name, value, output)} if properties else {}\n\n\ndef _conan_prefix_flag(variable: str) -> str:\n    \"\"\"\n    Return a global flag to be used as prefix to any value in the makefile\n    \"\"\"\n    return f\"$(CONAN_{variable.upper()}_FLAG)\" if variable else \"\"\n\n\ndef _common_cppinfo_variables() -> dict:\n    \"\"\"\n    Regular cppinfo variables exported by any Conanfile and their Makefile prefixes\n    \"\"\"\n    return {\n        \"objects\": None,\n        \"libs\": \"lib\",\n        \"defines\": \"define\",\n        \"cflags\": None,\n        \"cxxflags\": None,\n        \"sharedlinkflags\": None,\n        \"exelinkflags\": None,\n        \"frameworks\": None,\n        \"requires\": None,\n        \"system_libs\": \"system_lib\",\n    }\n\n\ndef _common_cppinfo_dirs() -> dict:\n    \"\"\"\n    Regular cppinfo folders exported by any Conanfile and their Makefile prefixes\n    \"\"\"\n    return {\n        \"includedirs\": \"include_dir\",\n        \"libdirs\": \"lib_dir\",\n        \"bindirs\": \"bin_dir\",\n        \"srcdirs\": None,\n        \"builddirs\": None,\n        \"resdirs\": None,\n        \"frameworkdirs\": None,\n    }\n\n\ndef _jinja_format_list_values() -> str:\n    \"\"\"\n    Template method to format a list of values in a Makefile,\n    - Empty variables are not exposed in the Makefile\n    - Single value variables are exposed in a single line\n    - Multiple value variables are exposed in multiple lines with a tabulation\n    e.g.\n    define_variable_value(\"FOO\", [\"single_value\"])\n    output:\n    FOO = single_value\n\n    define_variable_value(\"BAR\", [\"value1\", \"value2\"])\n    output:\n    BAR = \\\n        value1 \\\n        value2\n    \"\"\"\n    return textwrap.dedent(\"\"\"\\\n            {%- macro define_variable_value_safe(var, object, attribute) -%}\n            {%- if attribute in object -%}\n            {{ define_variable_value(\"{}\".format(var), object[attribute]) }}\n            {%- endif -%}\n            {%- endmacro %}\n\n            {%- macro define_multiple_variable_value(var, values) -%}\n            {% for property_name, value in values.items() %}\n            {{ var }}_{{ property_name }} = {{ value }}\n            {% endfor %}\n            {%- endmacro %}\n\n            {%- macro define_variable_value(var, values) -%}\n            {%- if values is not none -%}\n            {%- if values|length > 0 -%}\n            {{ var }} = {{ format_list_values(values) }}\n            {%- endif -%}\n            {%- endif -%}\n            {%- endmacro %}\n\n            {%- macro format_list_values(values) -%}\n            {% if values|length == 1 %}\n            {{ values[0] }}\n\n            {% elif values|length > 1 %}\n            \\\\\n            {% for value in values[:-1] %}\n            \\t{{ value }} \\\\\n            {% endfor %}\n            \\t{{ values|last }}\n\n            {% endif %}\n            {%- endmacro %}\n            \"\"\")\n\n\nclass MakeInfo:\n    \"\"\"\n    Store temporary information about each dependency\n    \"\"\"\n\n    def __init__(self, name: str, dirs: list, flags: list):\n        \"\"\"\n        :param name: Dependency or component raw name\n        :param dirs: cpp_info folders supported by the dependency\n        :param flags: cpp_info variables supported by the dependency\n        \"\"\"\n        self._name = name\n        self._dirs = dirs\n        self._flags = flags\n\n    @property\n    def name(self) -> str:\n        return self._name\n\n    @property\n    def dirs(self) -> list:\n        \"\"\"\n        :return: List of cpp_info folders supported by the dependency without duplicates\n        \"\"\"\n        return list(set(self._dirs))\n\n    @property\n    def flags(self) -> list:\n        \"\"\"\n        :return: List of cpp_info variables supported by the dependency without duplicates\n        \"\"\"\n        return list(set(self._flags))\n\n    def dirs_append(self, directory: str):\n        \"\"\"\n        Add a new cpp_info folder to the dependency\n        \"\"\"\n        self._dirs.append(directory)\n\n    def flags_append(self, flag: str):\n        \"\"\"\n        Add a new cpp_info variable to the dependency\n        \"\"\"\n        self._flags.append(flag)\n\n\nclass GlobalContentGenerator:\n    \"\"\"\n    Generates the formatted content for global variables (e.g. CONAN_DEPS, CONAN_LIBS)\n    \"\"\"\n\n    template = textwrap.dedent(\"\"\"\\\n\n            # Aggregated global variables\n\n            {{ define_variable_value(\"CONAN_INCLUDE_DIRS\", deps_cpp_info_dirs.include_dirs) -}}\n            {{- define_variable_value(\"CONAN_LIB_DIRS\", deps_cpp_info_dirs.lib_dirs) -}}\n            {{- define_variable_value(\"CONAN_BIN_DIRS\", deps_cpp_info_dirs.bin_dirs) -}}\n            {{- define_variable_value(\"CONAN_SRC_DIRS\", deps_cpp_info_dirs.src_dirs) -}}\n            {{- define_variable_value(\"CONAN_BUILD_DIRS\", deps_cpp_info_dirs.build_dirs) -}}\n            {{- define_variable_value(\"CONAN_RES_DIRS\", deps_cpp_info_dirs.res_dirs) -}}\n            {{- define_variable_value(\"CONAN_FRAMEWORK_DIRS\", deps_cpp_info_dirs.framework_dirs) -}}\n            {{- define_variable_value(\"CONAN_OBJECTS\", deps_cpp_info_flags.objects) -}}\n            {{- define_variable_value(\"CONAN_LIBS\", deps_cpp_info_flags.libs) -}}\n            {{- define_variable_value(\"CONAN_DEFINES\", deps_cpp_info_flags.defines) -}}\n            {{- define_variable_value(\"CONAN_CFLAGS\", deps_cpp_info_flags.cflags) -}}\n            {{- define_variable_value(\"CONAN_CXXFLAGS\", deps_cpp_info_flags.cxxflags) -}}\n            {{- define_variable_value(\"CONAN_SHAREDLINKFLAGS\", deps_cpp_info_flags.sharedlinkflags) -}}\n            {{- define_variable_value(\"CONAN_EXELINKFLAGS\", deps_cpp_info_flags.exelinkflags) -}}\n            {{- define_variable_value(\"CONAN_FRAMEWORKS\", deps_cpp_info_flags.frameworks) -}}\n            {{- define_variable_value(\"CONAN_REQUIRES\", deps_cpp_info_flags.requires) -}}\n            {{- define_variable_value(\"CONAN_SYSTEM_LIBS\", deps_cpp_info_flags.system_libs) -}}\n            \"\"\")\n\n    template_deps = textwrap.dedent(\"\"\"\\\n            {{ define_variable_value(\"CONAN_DEPS\", deps) }}\n            \"\"\")\n\n    def content(self, deps_cpp_info_dirs: dict, deps_cpp_info_flags: dict) -> str:\n        \"\"\"\n        Generate content for Cppinfo variables (e.g. CONAN_LIBS, CONAN_INCLUDE_DIRS)\n        :param deps_cpp_info_dirs: Formatted dependencies folders\n        :param deps_cpp_info_flags: Formatted dependencies variables\n        \"\"\"\n        context = {\"deps_cpp_info_dirs\": deps_cpp_info_dirs,\n                   \"deps_cpp_info_flags\": deps_cpp_info_flags}\n        template = Template(_jinja_format_list_values() + self.template, trim_blocks=True,\n                            lstrip_blocks=True, undefined=StrictUndefined)\n        return template.render(context)\n\n    def deps_content(self, dependencies_names: list) -> str:\n        \"\"\"\n        Generate content for CONAN_DEPS (e.g. CONAN_DEPS = zlib, openssl)\n        :param dependencies_names: Non-formatted dependencies names\n        \"\"\"\n        context = {\"deps\": dependencies_names}\n        template = Template(_jinja_format_list_values() + self.template_deps, trim_blocks=True,\n                            lstrip_blocks=True, undefined=StrictUndefined)\n        return template.render(context)\n\n\nclass GlobalGenerator:\n    \"\"\"\n    Process all collected dependencies and parse to generate global content\n    \"\"\"\n\n    def __init__(self, conanfile, make_infos):\n        self._conanfile = conanfile\n        self._make_infos = make_infos\n\n    def _get_dependency_dirs(self) -> dict:\n        \"\"\"\n        List regular directories from cpp_info and format them to be used in the makefile\n        \"\"\"\n        dirs = {}\n        for var in _common_cppinfo_dirs():\n            key = var.replace(\"dirs\", \"_dirs\")\n            dirs[key] = [f\"$(CONAN_{key.upper()}_{_makefy(makeinfo.name)})\"\n                         for makeinfo in self._make_infos if var in makeinfo.dirs]\n        return dirs\n\n    def _get_dependency_flags(self) -> dict:\n        \"\"\"\n        List common variables from cpp_info and format them to be used in the makefile\n        \"\"\"\n        flags = {}\n        for var in _common_cppinfo_variables():\n            key = var.replace(\"dirs\", \"_dirs\")\n            flags[key] = [f\"$(CONAN_{key.upper()}_{_makefy(makeinfo.name)})\"\n                          for makeinfo in self._make_infos if var in makeinfo.flags]\n        return flags\n\n    def generate(self) -> str:\n        \"\"\"\n        Process folder and variables for a dependency and generates its Makefile content\n        \"\"\"\n        glob_content_gen = GlobalContentGenerator()\n        dirs = self._get_dependency_dirs()\n        flags = self._get_dependency_flags()\n        return glob_content_gen.content(dirs, flags)\n\n    def deps_generate(self) -> str:\n        \"\"\"\n        Process dependencies names and generates its Makefile content.\n        It should be added as first variable in the Makefile.\n        \"\"\"\n        dependencies = [makeinfo.name for makeinfo in self._make_infos\n                        if makeinfo.name != self._conanfile.name]\n        glob_content_gen = GlobalContentGenerator()\n        return glob_content_gen.deps_content(dependencies)\n\n\nclass DepComponentContentGenerator:\n    \"\"\"\n    Generates Makefile content for each dependency component\n    \"\"\"\n\n    template = textwrap.dedent(\"\"\"\\\n        # {{ dep.ref.name }}::{{ comp_name }}\n\n        {{  define_variable_value_safe(\"CONAN_INCLUDE_DIRS_{}_{}\".format(dep_name, name), cpp_info_dirs, 'include_dirs') -}}\n        {{- define_variable_value_safe(\"CONAN_LIB_DIRS_{}_{}\".format(dep_name, name), cpp_info_dirs, 'lib_dirs') -}}\n        {{- define_variable_value_safe(\"CONAN_BIN_DIRS_{}_{}\".format(dep_name, name), cpp_info_dirs, 'bin_dirs') -}}\n        {{- define_variable_value_safe(\"CONAN_SRC_DIRS_{}_{}\".format(dep_name, name), cpp_info_dirs, 'src_dirs') -}}\n        {{- define_variable_value_safe(\"CONAN_BUILD_DIRS_{}_{}\".format(dep_name, name), cpp_info_dirs, 'build_dirs') -}}\n        {{- define_variable_value_safe(\"CONAN_RES_DIRS_{}_{}\".format(dep_name, name), cpp_info_dirs, 'res_dirs') -}}\n        {{- define_variable_value_safe(\"CONAN_FRAMEWORK_DIRS_{}_{}\".format(dep_name, name), cpp_info_dirs, 'framework_dirs') -}}\n        {{- define_variable_value_safe(\"CONAN_OBJECTS_{}_{}\".format(dep_name, name), cpp_info_flags, 'objects') -}}\n        {{- define_variable_value_safe(\"CONAN_LIBS_{}_{}\".format(dep_name, name), cpp_info_flags, 'libs') -}}\n        {{- define_variable_value_safe(\"CONAN_DEFINES_{}_{}\".format(dep_name, name), cpp_info_flags, 'defines') -}}\n        {{- define_variable_value_safe(\"CONAN_CFLAGS_{}_{}\".format(dep_name, name), cpp_info_flags, 'cflags') -}}\n        {{- define_variable_value_safe(\"CONAN_CXXFLAGS_{}_{}\".format(dep_name, name), cpp_info_flags, 'cxxflags') -}}\n        {{- define_variable_value_safe(\"CONAN_SHAREDLINKFLAGS_{}_{}\".format(dep_name, name), cpp_info_flags, 'sharedlinkflags') -}}\n        {{- define_variable_value_safe(\"CONAN_EXELINKFLAGS_{}_{}\".format(dep_name, name), cpp_info_flags, 'exelinkflags') -}}\n        {{- define_variable_value_safe(\"CONAN_FRAMEWORKS_{}_{}\".format(dep_name, name), cpp_info_flags, 'frameworks') -}}\n        {{- define_variable_value_safe(\"CONAN_REQUIRES_{}_{}\".format(dep_name, name), cpp_info_flags, 'requires') -}}\n        {{- define_variable_value_safe(\"CONAN_SYSTEM_LIBS_{}_{}\".format(dep_name, name), cpp_info_flags, 'system_libs') -}}\n        {{- define_multiple_variable_value(\"CONAN_PROPERTY_{}_{}\".format(dep_name, name), properties) -}}\n        \"\"\")\n\n    def __init__(self, dependency, component_name: str, dirs: dict, flags: dict, output):\n        \"\"\"\n        :param dependency: The dependency object that owns the component\n        :param component_name: component raw name e.g. poco::poco_json\n        :param dirs: The component cpp_info folders\n        :param flags: The component cpp_info variables\n        \"\"\"\n        self._dep = dependency\n        self._name = component_name\n        self._dirs = dirs or {}\n        self._flags = flags or {}\n        self._output = output\n\n    def content(self) -> str:\n        \"\"\"\n        Format template and generate Makefile component\n        \"\"\"\n        context = {\n            \"dep\": self._dep,\n            \"comp_name\": self._name,\n            \"dep_name\": _makefy(self._dep.ref.name),\n            \"name\": _makefy(self._name),\n            \"cpp_info_dirs\": self._dirs,\n            \"cpp_info_flags\": self._flags,\n            \"properties\": _makefy_properties(_filter_properties(self._dep.cpp_info.components[self._name]._properties, self._output)),\n        }\n        template = Template(_jinja_format_list_values() + self.template, trim_blocks=True,\n                            lstrip_blocks=True, undefined=StrictUndefined)\n        return template.render(context)\n\n\nclass DepContentGenerator:\n    \"\"\"\n    Generates Makefile content for a dependency\n    \"\"\"\n\n    template = textwrap.dedent(\"\"\"\\\n\n        # {{ dep.ref }}{% if not req.direct %} (indirect dependency){% endif +%}\n\n        CONAN_NAME_{{ name }} = {{ dep.ref.name }}\n        CONAN_VERSION_{{ name }} = {{ dep.ref.version }}\n        CONAN_REFERENCE_{{ name }} = {{ dep.ref }}\n\n        CONAN_ROOT_{{ name }} = {{ root }}\n\n        {{  define_variable_value(\"CONAN_SYSROOT_{}\".format(name), sysroot) -}}\n        {{- define_variable_value_safe(\"CONAN_INCLUDE_DIRS_{}\".format(name), cpp_info_dirs, 'include_dirs') -}}\n        {{- define_variable_value_safe(\"CONAN_LIB_DIRS_{}\".format(name), cpp_info_dirs, 'lib_dirs') -}}\n        {{- define_variable_value_safe(\"CONAN_BIN_DIRS_{}\".format(name), cpp_info_dirs, 'bin_dirs') -}}\n        {{- define_variable_value_safe(\"CONAN_SRC_DIRS_{}\".format(name), cpp_info_dirs, 'src_dirs') -}}\n        {{- define_variable_value_safe(\"CONAN_BUILD_DIRS_{}\".format(name), cpp_info_dirs, 'build_dirs') -}}\n        {{- define_variable_value_safe(\"CONAN_RES_DIRS_{}\".format(name), cpp_info_dirs, 'res_dirs') -}}\n        {{- define_variable_value_safe(\"CONAN_FRAMEWORK_DIRS_{}\".format(name), cpp_info_dirs, 'framework_dirs') -}}\n        {{- define_variable_value_safe(\"CONAN_OBJECTS_{}\".format(name), cpp_info_flags, 'objects') -}}\n        {{- define_variable_value_safe(\"CONAN_LIBS_{}\".format(name), cpp_info_flags, 'libs') -}}\n        {{- define_variable_value_safe(\"CONAN_DEFINES_{}\".format(name), cpp_info_flags, 'defines') -}}\n        {{- define_variable_value_safe(\"CONAN_CFLAGS_{}\".format(name), cpp_info_flags, 'cflags') -}}\n        {{- define_variable_value_safe(\"CONAN_CXXFLAGS_{}\".format(name), cpp_info_flags, 'cxxflags') -}}\n        {{- define_variable_value_safe(\"CONAN_SHAREDLINKFLAGS_{}\".format(name), cpp_info_flags, 'sharedlinkflags') -}}\n        {{- define_variable_value_safe(\"CONAN_EXELINKFLAGS_{}\".format(name), cpp_info_flags, 'exelinkflags') -}}\n        {{- define_variable_value_safe(\"CONAN_FRAMEWORKS_{}\".format(name), cpp_info_flags, 'frameworks') -}}\n        {{- define_variable_value_safe(\"CONAN_REQUIRES_{}\".format(name), cpp_info_flags, 'requires') -}}\n        {{- define_variable_value_safe(\"CONAN_SYSTEM_LIBS_{}\".format(name), cpp_info_flags, 'system_libs') -}}\n        {{- define_variable_value(\"CONAN_COMPONENTS_{}\".format(name), components) -}}\n        {{- define_multiple_variable_value(\"CONAN_PROPERTY_{}\".format(name), properties) -}}\n        \"\"\")\n\n    def __init__(self, dependency, require, root: str, sysroot, dirs: dict, flags: dict, output):\n        self._dep = dependency\n        self._req = require\n        self._root = root\n        self._sysroot = sysroot\n        self._dirs = dirs or {}\n        self._flags = flags or {}\n        self._output = output\n\n    def content(self) -> str:\n        \"\"\"\n        Parse dependency variables and generate its Makefile content\n        \"\"\"\n        context = {\n            \"dep\": self._dep,\n            \"req\": self._req,\n            \"name\": _makefy(self._dep.ref.name),\n            \"root\": self._root,\n            \"sysroot\": self._sysroot,\n            \"components\": list(self._dep.cpp_info.get_sorted_components().keys()),\n            \"cpp_info_dirs\": self._dirs,\n            \"cpp_info_flags\": self._flags,\n            \"properties\": _makefy_properties(_filter_properties(self._dep.cpp_info._properties, self._output)),\n        }\n        template = Template(_jinja_format_list_values() + self.template, trim_blocks=True,\n                            lstrip_blocks=True, undefined=StrictUndefined)\n        return template.render(context)\n\n\nclass DepComponentGenerator:\n    \"\"\"\n    Generates Makefile content for a dependency component\n    \"\"\"\n\n    def __init__(self, dependency, makeinfo: MakeInfo, component_name: str, component, root: str, output):\n        \"\"\"\n        :param dependency: The dependency object that owns the component\n        :param makeinfo: Makeinfo to store component variables\n        :param component_name: The component raw name e.g. poco::poco_json\n        :param component: The component object to obtain cpp_info variables\n        :param root: The dependency root folder\n        \"\"\"\n        self._dep = dependency\n        self._name = component_name\n        self._comp = component\n        self._root = root\n        self._makeinfo = makeinfo\n        self._output = output\n\n    def _get_component_dirs(self) -> dict:\n        \"\"\"\n        List regular directories from cpp_info and format them to be used in the makefile\n        :return: A dictionary with regular folder name and its formatted path\n        \"\"\"\n        dirs = {}\n        for var, flag in _common_cppinfo_dirs().items():\n            cppinfo_value = getattr(self._comp, var)\n            formatted_dirs = _get_formatted_dirs(cppinfo_value, self._root, _makefy(self._name))\n            if formatted_dirs:\n                self._makeinfo.dirs_append(var)\n                var = var.replace(\"dirs\", \"_dirs\")\n                formatted_dirs = self._rootify(self._root, self._dep.ref.name, cppinfo_value)\n                dirs[var] = [_conan_prefix_flag(flag) + it for it in formatted_dirs]\n        return dirs\n\n    @staticmethod\n    def _rootify(root: str, root_id: str, path_list: list) -> list:\n        \"\"\"\n        Replaces component folder path by its root node folder path in case they match\n        :param root: root folder path for component's father\n        :param root_id: component's dependency name\n        :param path_list: folder list available in the component\n        :return: A formatted folder list, solving root folder path as prefix\n        \"\"\"\n        root_len = len(root)\n        root_with_sep = root + os.sep\n        root_var_ref = f\"$(CONAN_ROOT_{_makefy(root_id)})\"\n        return [root_var_ref + path[root_len:].replace(\"\\\\\", \"/\") if path.startswith(root_with_sep)\n                else path for path in path_list]\n\n    def _get_component_flags(self) -> dict:\n        \"\"\"\n        List common variables from cpp_info and format them to be used in the makefile\n        :return: A dictionary with regular flag/variable name and its formatted value with prefix\n        \"\"\"\n        flags = {}\n        for var, prefix_var in _common_cppinfo_variables().items():\n            cppinfo_value = getattr(self._comp, var)\n            if not cppinfo_value:\n                continue\n            if \"flags\" in var:\n                cppinfo_value = [var.replace('\"', '\\\\\"') for var in cppinfo_value]\n            if cppinfo_value:\n                flags[var] = [_conan_prefix_flag(prefix_var) + it for it in cppinfo_value]\n                self._makeinfo.flags_append(var)\n        return flags\n\n    def generate(self) -> str:\n        \"\"\"\n        Process component cpp_info variables and generate its Makefile content\n        :return: Component Makefile content\n        \"\"\"\n        dirs = self._get_component_dirs()\n        flags = self._get_component_flags()\n        comp_content_gen = DepComponentContentGenerator(self._dep, self._name, dirs, flags, self._output)\n        comp_content = comp_content_gen.content()\n        return comp_content\n\n\nclass DepGenerator:\n    \"\"\"\n    Process a dependency cpp_info variables and generate its Makefile content\n    \"\"\"\n\n    def __init__(self, dependency, require, output):\n        self._dep = dependency\n        self._req = require\n        self._info = MakeInfo(self._dep.ref.name, [], [])\n        self._output = output\n\n    @property\n    def makeinfo(self) -> MakeInfo:\n        \"\"\"\n        :return: Dependency folder and flags\n        \"\"\"\n        return self._info\n\n    def _get_dependency_dirs(self, root: str, dependency) -> dict:\n        \"\"\"\n        List regular directories from cpp_info and format them to be used in the makefile\n        :param root: Package root folder\n        :param dependency: Dependency object\n        :return: A dictionary with regular folder name and its formatted path\n        \"\"\"\n        dirs = {}\n        for var, prefix in _common_cppinfo_dirs().items():\n            cppinfo_value = getattr(dependency.cpp_info, var)\n            if not cppinfo_value:  # The root value is not defined, there might be components\n                cppinfo_value = [f\"$(CONAN_{var.replace('dirs', '_dirs').upper()}_{_makefy(dependency.ref.name)}_{_makefy(name)})\"\n                                 for name, obj in dependency.cpp_info.components.items() if getattr(obj, var.lower())]\n                prefix = \"\"\n            formatted_dirs = _get_formatted_dirs(cppinfo_value, root, _makefy(dependency.ref.name))\n            if formatted_dirs:\n                self._info.dirs_append(var)\n                var = var.replace(\"dirs\", \"_dirs\")\n                dirs[var] = [_conan_prefix_flag(prefix) + it for it in formatted_dirs]\n        return dirs\n\n    def _get_dependency_flags(self, dependency) -> dict:\n        \"\"\"\n        List common variables from cpp_info and format them to be used in the makefile\n        :param dependency: Dependency object\n        \"\"\"\n        flags = {}\n        for var, prefix_var in _common_cppinfo_variables().items():\n            cppinfo_value = getattr(dependency.cpp_info, var)\n            # Use component cpp_info info when does not provide any value\n            if not cppinfo_value:\n                cppinfo_value = [f\"$(CONAN_{var.upper()}_{_makefy(dependency.ref.name)}_{_makefy(name)})\" for name, obj in dependency.cpp_info.components.items() if getattr(obj, var.lower())]\n                # avoid repeating same prefix twice\n                prefix_var = \"\"\n            if \"flags\" in var:\n                cppinfo_value = [var.replace('\"', '\\\\\"') for var in cppinfo_value]\n            if cppinfo_value:\n                self._info.flags_append(var)\n                flags[var] = [_conan_prefix_flag(prefix_var) + it for it in cppinfo_value]\n        return flags\n\n    def _get_sysroot(self, root: str) -> list:\n        \"\"\"\n        Get the sysroot of the dependency. Sysroot is a list of directories, or a single directory\n        \"\"\"\n        sysroot = self._dep.cpp_info.sysroot if isinstance(self._dep.cpp_info.sysroot, list) else [self._dep.cpp_info.sysroot]\n        # sysroot may return ['']\n        if not sysroot or not sysroot[0]:\n            return []\n        return _get_formatted_dirs(sysroot, root, _makefy(self._dep.ref.name)) if sysroot and sysroot[0] else None\n\n    def _get_root_folder(self):\n        \"\"\"\n        Get the root folder of the dependency\n        \"\"\"\n        root = self._dep.recipe_folder if self._dep.package_folder is None else self._dep.package_folder\n        return root.replace(\"\\\\\", \"/\")\n\n    def generate(self) -> str:\n        \"\"\"\n        Process dependency folders and flags to generate its Makefile content. Plus, execute same\n        steps for each component\n        \"\"\"\n        root = self._get_root_folder()\n        sysroot = self._get_sysroot(root)\n        dirs = self._get_dependency_dirs(root, self._dep)\n        flags = self._get_dependency_flags(self._dep)\n        dep_content_gen = DepContentGenerator(self._dep, self._req, root, sysroot, dirs, flags, self._output)\n        content = dep_content_gen.content()\n\n        for comp_name, comp in self._dep.cpp_info.get_sorted_components().items():\n            component_gen = DepComponentGenerator(self._dep, self._info, comp_name, comp, root, self._output)\n            content += component_gen.generate()\n\n        return content\n\n\nclass MakeDeps:\n    \"\"\"\n    Generates a Makefile with the variables needed to build a project with the specified.\n    \"\"\"\n\n    _title = \"# This Makefile has been generated by Conan. DO NOT EDIT!\\n\"\n\n    def __init__(self, conanfile):\n        \"\"\"\n        :param conanfile: ``< ConanFile object >`` The current recipe object. Always use ``self``.\n        \"\"\"\n        self._conanfile = conanfile\n\n    def generate(self) -> None:\n        \"\"\"\n        Collects all dependencies and components, then, generating a Makefile\n        \"\"\"\n        check_duplicated_generator(self, self._conanfile)\n\n        host_req = self._conanfile.dependencies.host\n        test_req = self._conanfile.dependencies.test\n\n        content_buffer = f\"{self._title}\\n\"\n        deps_buffer = \"\"\n\n        # Filter the build_requires not activated for any requirement\n        dependencies = list(host_req.items()) + list(test_req.items())\n\n        make_infos = []\n\n        for require, dep in dependencies:\n            output = ConanOutput(scope=f\"{self._conanfile} MakeDeps: {dep}:\")\n            dep_gen = DepGenerator(dep, require, output)\n            make_infos.append(dep_gen.makeinfo)\n            deps_buffer += dep_gen.generate()\n\n        glob_gen = GlobalGenerator(self._conanfile, make_infos)\n        content_buffer += glob_gen.deps_generate() + deps_buffer + glob_gen.generate()\n\n        save(self._conanfile, CONAN_MAKEFILE_FILENAME, content_buffer)\n        self._conanfile.output.info(f\"Generated {CONAN_MAKEFILE_FILENAME}\")\n"
  },
  {
    "path": "conan/tools/gnu/pkgconfig.py",
    "content": "import textwrap\nfrom io import StringIO\n\nfrom conan.tools.build import cmd_args_to_string\nfrom conan.tools.env import Environment\nfrom conan.errors import ConanException\n\n\nclass PkgConfig:\n\n    def __init__(self, conanfile, library, pkg_config_path=None):\n        \"\"\"\n\n        :param conanfile: The current recipe object. Always use ``self``.\n        :param library: The library which ``.pc`` file is to be parsed. It must exist in the pkg_config path.\n        :param pkg_config_path:  If defined it will be prepended to ``PKG_CONFIG_PATH`` environment\n               variable, so the execution finds the required files.\n        \"\"\"\n        self._conanfile = conanfile\n        self._library = library\n        self._info = {}\n        self._pkg_config_path = pkg_config_path\n        self._variables = None\n\n    def _parse_output(self, option):\n        executable = self._conanfile.conf.get(\"tools.gnu:pkg_config\", default=\"pkg-config\")\n        command = cmd_args_to_string([executable, '--' + option, self._library, '--print-errors'])\n\n        env = Environment()\n        if self._pkg_config_path:\n            env.prepend_path(\"PKG_CONFIG_PATH\", self._pkg_config_path)\n        with env.vars(self._conanfile).apply():\n            # This way we get the environment from ConanFile, from profile (default buildenv)\n            output, err = StringIO(), StringIO()\n            ret = self._conanfile.run(command, stdout=output, stderr=err, quiet=True,\n                                      ignore_errors=True)\n            if ret != 0:\n                raise ConanException(f\"PkgConfig failed. Command: {command}\\n\"\n                                     f\"    stdout:\\n{textwrap.indent(output.getvalue(), '    ')}\\n\"\n                                     f\"    stderr:\\n{textwrap.indent(err.getvalue(), '    ')}\\n\")\n        value = output.getvalue().strip()\n        return value\n\n    def _get_option(self, option):\n        if option not in self._info:\n            self._info[option] = self._parse_output(option)\n        return self._info[option]\n\n    @property\n    def includedirs(self):\n        return [include[2:] for include in self._get_option('cflags-only-I').split()]\n\n    @property\n    def cflags(self):\n        return [flag for flag in self._get_option('cflags-only-other').split()\n                if not flag.startswith(\"-D\")]\n\n    @property\n    def defines(self):\n        return [flag[2:] for flag in self._get_option('cflags-only-other').split()\n                if flag.startswith(\"-D\")]\n\n    @property\n    def libdirs(self):\n        return [lib[2:] for lib in self._get_option('libs-only-L').split()]\n\n    @property\n    def libs(self):\n        return [lib[2:] for lib in self._get_option('libs-only-l').split()]\n\n    @property\n    def linkflags(self):\n        return self._get_option('libs-only-other').split()\n\n    @property\n    def provides(self):\n        return self._get_option('print-provides')\n\n    @property\n    def version(self):\n        return self._get_option('modversion')\n\n    @property\n    def variables(self):\n        if self._variables is None:\n            variable_names = self._parse_output('print-variables').split()\n            self._variables = {}\n            for name in variable_names:\n                self._variables[name] = self._parse_output('variable=%s' % name)\n        return self._variables\n\n    def fill_cpp_info(self, cpp_info, is_system=True, system_libs=None):\n        \"\"\"\n        Method to fill a cpp_info object from the PkgConfig configuration\n\n        :param cpp_info: Can be the global one (self.cpp_info) or a component one (self.components[\"foo\"].cpp_info).\n        :param is_system: If ``True``, all detected libraries will be assigned to ``cpp_info.system_libs``, and none to ``cpp_info.libs``.\n        :param system_libs: If ``True``, all detected libraries will be assigned to ``cpp_info.system_libs``, and none to ``cpp_info.libs``.\n\n        \"\"\"\n        if not self.provides:\n            raise ConanException(\"PkgConfig error, '{}' files not available\".format(self._library))\n        self._conanfile.output.verbose(f\"PkgConfig fill cpp_info for {self._library}\")\n        if is_system:\n            cpp_info.system_libs = self.libs\n        else:\n            system_libs = system_libs or []\n            cpp_info.libs = [lib for lib in self.libs if lib not in system_libs]\n            cpp_info.system_libs = [lib for lib in self.libs if lib in system_libs]\n        cpp_info.libdirs = self.libdirs\n        cpp_info.sharedlinkflags = self.linkflags\n        cpp_info.exelinkflags = self.linkflags\n        cpp_info.defines = self.defines\n        cpp_info.includedirs = self.includedirs\n        cpp_info.cflags = self.cflags\n        cpp_info.cxxflags = self.cflags\n"
  },
  {
    "path": "conan/tools/gnu/pkgconfigdeps.py",
    "content": "import os\nimport re\nimport textwrap\n\nfrom jinja2 import Template, StrictUndefined\n\nfrom conan.errors import ConanException\nfrom conan.internal import check_duplicated_generator\nfrom conan.internal.model.dependencies import get_transitive_requires\nfrom conan.internal.util.files import save\n\n\nclass _PCFilesDeps:\n\n    template = textwrap.dedent(\"\"\"\\\n        {% for k, v in pc_variables.items() %}\n        {{ \"{}={}\".format(k, v) }}\n        {% endfor %}\n\n        Name: {{ name }}\n        Description: {{ description }}\n        Version: {{ version }}\n        {% if libflags %}\n        Libs: {{ libflags }}\n        {% endif %}\n        {% if cflags %}\n        Cflags: {{ cflags }}\n        {% endif %}\n        {% if requires|length %}\n        Requires: {{ requires|join(' ') }}\n        {% endif %}\n    \"\"\")\n\n    alias_template = textwrap.dedent(\"\"\"\\\n        Name: {{name}}\n        Description: Alias {{name}} for {{aliased}}\n        Version: {{version}}\n        Requires: {{aliased}}\n    \"\"\")\n\n    def __init__(self, pkgconfigdeps, dep, suffix=\"\"):\n        self._conanfile = pkgconfigdeps._conanfile  # noqa\n        self._properties = pkgconfigdeps._properties  # noqa\n        self._transitive_reqs = get_transitive_requires(self._conanfile, dep)\n        self._dep = dep\n        self._suffix = suffix\n\n    def _get_aliases(self, dep, pkg_name=None, comp_ref_name=None):\n        def _get_dep_aliases():\n            pkg_aliases = self._get_property(\"pkg_config_aliases\", dep, check_type=list)\n            return pkg_aliases or []\n\n        # TODO: LET'S DEPRECATE ALL THE ALIASES MECHANISM!!\n        if pkg_name is None and comp_ref_name is None:\n            return _get_dep_aliases()\n        if comp_ref_name not in dep.cpp_info.components:\n            # Either foo::foo might be referencing the root cpp_info\n            if (dep.ref.name == comp_ref_name or\n                # Or a \"replace_require\" is used and cpp_info.requires is the root one, e.g.,\n                # zlib/*: zlib-ng/*, and self.cpp_info.requires = [\"zlib::zlib\"]\n                (dep.ref.name != pkg_name and pkg_name == comp_ref_name)):\n                return _get_dep_aliases()\n            raise ConanException(\"Component '{name}::{cname}' not found in '{name}' \"\n                                 \"package requirement\".format(name=dep.ref.name,\n                                                              cname=comp_ref_name))\n        comp_aliases = self._get_property(\"pkg_config_aliases\", dep, comp_ref_name, check_type=list)\n        return comp_aliases or []\n\n    def _get_name(self, dep, pkg_name=None, comp_ref_name=None):\n        def _get_dep_name():\n            dep_name = self._get_property(\"pkg_config_name\", dep) or dep.ref.name\n            return f\"{dep_name}{self._suffix}\"\n\n        if pkg_name is None and comp_ref_name is None:\n            return _get_dep_name()\n        if comp_ref_name not in dep.cpp_info.components:\n            # Either foo::foo might be referencing the root cpp_info\n            if (dep.ref.name == comp_ref_name or\n                # Or a \"replace_require\" is used and cpp_info.requires is the root one, e.g.,\n                # zlib/*: zlib-ng/*, and self.cpp_info.requires = [\"zlib::zlib\"]\n                (dep.ref.name != pkg_name and pkg_name == comp_ref_name)):\n                return _get_dep_name()\n            raise ConanException(\"Component '{name}::{cname}' not found in '{name}' \"\n                                 \"package requirement\".format(name=dep.ref.name,\n                                                              cname=comp_ref_name))\n        comp_name = self._get_property(\"pkg_config_name\", dep, comp_ref_name)\n        if comp_name:\n            return f\"{comp_name}{self._suffix}\"\n        else:\n            dep_name = _get_dep_name()\n            # Creating a component name with namespace, e.g., dep-comp1\n            return f\"{dep_name}-{comp_ref_name}\"\n\n    def _get_property(self, prop, dep, comp_name=None, check_type=None):\n        dep_name = dep.ref.name\n        dep_comp = f\"{str(dep_name)}::{comp_name}\" if comp_name else f\"{str(dep_name)}\"\n        try:\n            value = self._properties[f\"{dep_comp}{self._suffix}\"][prop]\n            if check_type is not None and not isinstance(value, check_type):\n                raise ConanException(\n                    f'The expected type for {prop} is \"{check_type.__name__}\", but \"{type(value).__name__}\" was found')\n            return value\n        except KeyError:\n            return dep.cpp_info.get_property(prop, check_type=check_type) if not comp_name \\\n                else dep.cpp_info.components[comp_name].get_property(prop, check_type=check_type)\n\n    def _get_pc_variables(self, dep, cpp_info, custom_content=None):\n        \"\"\"\n        Get all the freeform variables defined by Conan and\n        users (through ``pkg_config_custom_content``). This last ones will override the\n        Conan defined variables.\n        \"\"\"\n        def apply_custom_content():\n            if isinstance(custom_content, dict):\n                pc_variables.update(custom_content)\n            elif custom_content:  # Legacy: custom content is string\n                pc_variable_pattern = re.compile(\"^(.*)=(.*)\")\n                for line in custom_content.splitlines():\n                    match = pc_variable_pattern.match(line)\n                    if match:\n                        key, value = match.group(1).strip(), match.group(2).strip()\n                        pc_variables[key] = value\n\n        # If editable, package_folder can be None\n        prefix_path = (dep.recipe_folder if dep.package_folder is None\n                                   else dep.package_folder).replace(\"\\\\\", \"/\")\n        pc_variables = {\"prefix\": prefix_path}\n        # Already formatted directories\n        pc_variables.update(self._get_formatted_dirs(\"libdir\", cpp_info.libdirs, prefix_path))\n        pc_variables.update(self._get_formatted_dirs(\"includedir\", cpp_info.includedirs, prefix_path))\n        pc_variables.update(self._get_formatted_dirs(\"bindir\", cpp_info.bindirs, prefix_path))\n        # Get the custom content introduced by user and sanitize it\n        apply_custom_content()\n        return pc_variables\n\n    @staticmethod\n    def _get_formatted_dirs(folder_name, folders, prefix_path_):\n        ret = {}\n        for i, directory in enumerate(folders):\n            directory = os.path.normpath(directory).replace(\"\\\\\", \"/\")\n            if directory.startswith(prefix_path_):\n                prefix = \"${prefix}/\"\n                directory = os.path.relpath(directory, prefix_path_).replace(\"\\\\\", \"/\")\n            else:\n                prefix = \"\" if os.path.isabs(directory) else \"${prefix}/\"\n            suffix = str(i) if i else \"\"\n            var_name = f\"{folder_name}{suffix}\"\n            ret[var_name] = f\"{prefix}{directory}\"\n        return ret\n\n    def _get_framework_flags(self, cpp_info):\n        # FIXME: GnuDepsFlags used only here. Let's adapt the code and remove this dependency.\n        #        self._conanfile is also used only here.\n        from conan.tools.gnu.gnudeps_flags import GnuDepsFlags\n        gnudeps_flags = GnuDepsFlags(self._conanfile, cpp_info)\n        return gnudeps_flags.frameworks + gnudeps_flags.framework_paths\n\n    def _get_lib_flags(self, libdirvars, cpp_info):\n        framework_flags = self._get_framework_flags(cpp_info)\n        libdirsflags = ['-L\"${%s}\"' % d for d in libdirvars]\n        system_libs = [\"-l%s\" % li for li in (cpp_info.libs + cpp_info.system_libs)]\n        shared_flags = cpp_info.sharedlinkflags + cpp_info.exelinkflags\n        return \" \".join(libdirsflags + system_libs + shared_flags + framework_flags)\n\n    def _get_cflags(self, includedirvars, cpp_info):\n        includedirsflags = ['-I\"${%s}\"' % d for d in includedirvars]\n        cxxflags = [var.replace('\"', '\\\\\"') for var in cpp_info.cxxflags]\n        cflags = [var.replace('\"', '\\\\\"') for var in cpp_info.cflags]\n        defines = [\"-D%s\" % var.replace('\"', '\\\\\"') for var in cpp_info.defines]\n        return \" \".join(includedirsflags + cxxflags + cflags + defines)\n\n    def _get_component_requirement_names(self, cpp_info):\n        \"\"\"\n        Get all the pkg-config valid names from the requirements ones given a CppInfo object.\n\n        For instance, those requirements could be coming from:\n\n        ```python\n        from conan import ConanFile\n        class PkgConfigConan(ConanFile):\n            requires = \"other/1.0\"\n\n            def package_info(self):\n                self.cpp_info.requires = [\"other::cmp1\"]\n\n            # Or:\n\n            def package_info(self):\n                self.cpp_info.components[\"cmp\"].requires = [\"other::cmp1\"]\n        ```\n        \"\"\"\n        dep_ref_name = self._dep.ref.name\n        ret = []\n        for req in cpp_info.requires:\n            pkg_ref_name, comp_ref_name = req.split(\"::\") if \"::\" in req else (dep_ref_name, req)\n            # For instance, dep == \"hello/1.0\" and req == \"other::cmp1\" -> hello != other\n            if dep_ref_name != pkg_ref_name:\n                try:\n                    req_conanfile = self._transitive_reqs[pkg_ref_name]\n                except KeyError:\n                    continue  # If the dependency is not in the transitive, might be skipped\n            else:  # For instance, dep == \"hello/1.0\" and req == \"hello::cmp1\" -> hello == hello\n                req_conanfile = self._dep\n            comp_name = self._get_name(req_conanfile, pkg_ref_name, comp_ref_name)\n            if comp_name not in ret:\n                ret.append(comp_name)\n        return ret\n\n    def items(self):\n        \"\"\"\n        Get all the PC files and contents for any dependency:\n\n        * If the given dependency does not have components:\n            The PC file will be the dependency one.\n\n        * If the given dependency has components:\n            The PC files will be saved in this order:\n                1- Package components.\n                2- Root component.\n\n            Note: If the root-package PC name matches with any other of the components one, the first one\n            is not going to be created. Components have more priority than root package.\n\n        * Apart from those PC files, if there are any aliases declared, they will be created too.\n        \"\"\"\n        pc_files = {}\n        pc_alias_files = {}\n        pkg_name = self._get_name(self._dep)\n        # First, let's load all the components PC files\n        # Loop through all the package's components\n        for comp_ref_name, comp_cpp_info in self._dep.cpp_info.get_sorted_components().items():\n            # At first, let's check if we have defined some components requires, e.g., \"dep::cmp1\"\n            comp_requires = self._get_component_requirement_names(comp_cpp_info)\n            comp_name = self._get_name(self._dep, pkg_name, comp_ref_name)\n            version = (self._get_property(\"component_version\", self._dep, comp_ref_name) or\n                       self._get_property(\"system_package_version\", self._dep, comp_ref_name) or\n                       self._dep.ref.version)\n            custom_content = self._get_property(\"pkg_config_custom_content\", self._dep, comp_ref_name)\n            pc_variables = self._get_pc_variables(self._dep, comp_cpp_info, custom_content)\n            pc_context = {\n                \"name\": comp_name,\n                \"description\": f\"Conan component: {comp_name}\",\n                \"version\": version,\n                \"requires\": comp_requires,\n                \"pc_variables\": pc_variables,\n                \"cflags\": self._get_cflags([d for d in pc_variables if d.startswith(\"includedir\")],\n                                           comp_cpp_info),\n                \"libflags\": self._get_lib_flags([d for d in pc_variables if d.startswith(\"libdir\")],\n                                                comp_cpp_info)\n            }\n            pc_files[comp_name] = self._get_pc_content(pc_context)\n            # Aliases\n            for alias in self._get_aliases(self._dep, pkg_name, comp_ref_name):\n                pc_alias_files[alias] = self._get_alias_pc_content({\n                    \"name\": alias,\n                    \"version\": version,\n                    \"aliased\": comp_name\n                })\n        # Second, let's load the root package's PC file ONLY\n        # if it does not already exist in components one\n        # Issue related: https://github.com/conan-io/conan/issues/10341\n        should_skip_main = self._get_property(\"pkg_config_name\", self._dep) == \"none\"\n        if pkg_name not in pc_files and not should_skip_main:\n            cpp_info = self._dep.cpp_info\n            # At first, let's check if we have defined some global requires, e.g., \"other::cmp1\"\n            # Note: If DEP has components, they'll be the requirements == pc_files.keys()\n            requires = list(pc_files.keys()) or self._get_component_requirement_names(cpp_info)\n            # If we have found some component requirements it would be enough\n            if not requires:\n                # If no requires were found, let's try to get all the direct visible dependencies,\n                # e.g., requires = \"other_pkg/1.0\"\n                requires = [self._get_name(req) for req in self._transitive_reqs.values()]\n            version = (self._get_property(\"system_package_version\", self._dep)\n                       or self._dep.ref.version)\n            custom_content = self._get_property(\"pkg_config_custom_content\", self._dep)\n            pc_variables = self._get_pc_variables(self._dep, cpp_info, custom_content)\n            pc_context = {\n                \"name\": pkg_name,\n                \"description\": f\"Conan package: {pkg_name}\",\n                \"version\": version,\n                \"requires\": requires,\n                \"pc_variables\": pc_variables,\n                \"cflags\": self._get_cflags([d for d in pc_variables if d.startswith(\"includedir\")],\n                                           cpp_info),\n                \"libflags\": self._get_lib_flags([d for d in pc_variables if d.startswith(\"libdir\")],\n                                                cpp_info)\n            }\n            pc_files[pkg_name] = self._get_pc_content(pc_context)\n            # Aliases\n            for alias in self._get_aliases(self._dep):\n                pc_alias_files[alias] = self._get_alias_pc_content({\n                    \"name\": alias,\n                    \"version\": version,\n                    \"aliased\": pkg_name\n                })\n        # Adding the aliases\n        pc_files.update(pc_alias_files)\n        return pc_files.items()\n\n    def _get_pc_content(self, context):\n        template = Template(self.template, trim_blocks=True, lstrip_blocks=True,\n                            undefined=StrictUndefined)\n        return template.render(context)\n\n    def _get_alias_pc_content(self, context):\n        template = Template(self.alias_template, trim_blocks=True, lstrip_blocks=True,\n                            undefined=StrictUndefined, keep_trailing_newline=True)\n        return template.render(context)\n\n\nclass PkgConfigDeps:\n\n    def __init__(self, conanfile):\n        self._conanfile = conanfile\n        # Activate the build *.pc files for the specified libraries\n        self.build_context_activated = []\n        # If specified, the files/requires/names for the build context will be renamed appending\n        # a suffix. It is necessary in case of same require and build_require and will cause an error\n        # DEPRECATED: consumers should use build_context_folder instead\n        # FIXME: Conan 3.x: Remove build_context_suffix attribute\n        self.build_context_suffix = {}\n        # By default, the \"[generators_folder]/build\" folder will save all the *.pc files activated\n        # in the build_context_activated list.\n        # Notice that if the `build_context_suffix` attr is defined, the `build_context_folder` one\n        # will have no effect.\n        # Issue: https://github.com/conan-io/conan/issues/12342\n        # Issue: https://github.com/conan-io/conan/issues/14935\n        # FIXME: Conan 3.x: build_context_folder should be \"build\" by default\n        self.build_context_folder = None  # Keeping backward-compatibility\n        self._properties = {}\n\n    def _get_dependencies(self):\n        # Get all the dependencies\n        host_req = self._conanfile.dependencies.host\n        build_req = self._conanfile.dependencies.build  # tool_requires\n        test_req = self._conanfile.dependencies.test\n        # If self.build_context_suffix is not defined, the build requires will be saved\n        # in the self.build_context_folder\n        # FIXME: Conan 3.x: Remove build_context_suffix attribute and the validation function\n        if self.build_context_folder is None:  # Legacy flow\n            if self.build_context_suffix:\n                # deprecation warning\n                self._conanfile.output.warning(\n                    \"PkgConfigDeps.build_context_suffix attribute has been \"\n                    \"deprecated. Use PkgConfigDeps.build_context_folder instead.\"\n                )\n            # Check if it exists both as require and as build require without a suffix\n            activated_br = {r.ref.name for r in build_req.values()\n                            if r.ref.name in self.build_context_activated}\n            common_names = {r.ref.name for r in host_req.values()}.intersection(activated_br)\n            without_suffixes = [common_name for common_name in common_names\n                                if not self.build_context_suffix.get(common_name)]\n            if without_suffixes:\n                raise ConanException(\n                    f\"The packages {without_suffixes} exist both as 'require' and as\"\n                    f\" 'build require'. You need to specify a suffix using the \"\n                    f\"'build_context_suffix' attribute at the PkgConfigDeps generator.\")\n        elif self.build_context_folder is not None and self.build_context_suffix:\n            raise ConanException(\n                \"It's not allowed to define both PkgConfigDeps.build_context_folder \"\n                \"and PkgConfigDeps.build_context_suffix (deprecated).\")\n\n        for require, dep in list(host_req.items()) + list(build_req.items()) + list(test_req.items()):\n            # Filter the build_requires not activated with PkgConfigDeps.build_context_activated\n            if require.build and dep.ref.name not in self.build_context_activated:\n                continue\n            yield require, dep\n\n    def generate(self):\n        \"\"\"\n        Save all the `*.pc` files\n        \"\"\"\n        def _pc_file_name(name_, is_build_context=False, has_suffix=False):\n            # If no suffix is defined, we can save the *.pc file in the build_context_folder\n            build = is_build_context and self.build_context_folder and not has_suffix\n            # Issue: https://github.com/conan-io/conan/issues/12342\n            # Issue: https://github.com/conan-io/conan/issues/14935\n            return f\"{self.build_context_folder}/{name_}.pc\" if build else f\"{name_}.pc\"\n\n        check_duplicated_generator(self, self._conanfile)\n        for require, dep in self._get_dependencies():\n            suffix = self.build_context_suffix.get(require.ref.name, \"\") if require.build else \"\"\n            # Save all the *.pc files and their contents\n            for name, content in _PCFilesDeps(self, dep, suffix=suffix).items():\n                pc_name = _pc_file_name(name, is_build_context=require.build,\n                                        has_suffix=bool(suffix))\n                save(pc_name, content)\n\n    def set_property(self, dep, prop, value):\n        \"\"\"\n        Using this method you can overwrite the :ref:`property<PkgConfigDeps Properties>` values set by\n        the Conan recipes from the consumer. This can be done for `pkg_config_name`,\n        `pkg_config_aliases` and `pkg_config_custom_content` properties.\n\n        :param dep: Name of the dependency to set the :ref:`property<PkgConfigDeps Properties>`. For\n         components use the syntax: ``dep_name::component_name``.\n        :param prop: Name of the :ref:`property<PkgConfigDeps Properties>`.\n        :param value: Value of the property. Use ``None`` to invalidate any value set by the\n         upstream recipe.\n        \"\"\"\n        self._properties.setdefault(dep, {}).update({prop: value})\n"
  },
  {
    "path": "conan/tools/google/__init__.py",
    "content": "from conan.tools.google.toolchain import BazelToolchain\nfrom conan.tools.google.bazeldeps import BazelDeps\nfrom conan.tools.google.bazel import Bazel\nfrom conan.tools.google.layout import bazel_layout\n"
  },
  {
    "path": "conan/tools/google/bazel.py",
    "content": "import os\nimport platform\n\nfrom conan.tools.google import BazelToolchain\n\n\nclass Bazel:\n\n    def __init__(self, conanfile):\n        \"\"\"\n        :param conanfile: ``< ConanFile object >`` The current recipe object. Always use ``self``.\n        \"\"\"\n        self._conanfile = conanfile\n        # Use BazelToolchain generated file if exists\n        self._conan_bazelrc = os.path.join(self._conanfile.generators_folder, BazelToolchain.bazelrc_name)\n        self._use_conan_config = os.path.exists(self._conan_bazelrc)\n        self._startup_opts = self._get_startup_command_options()\n\n    def _safe_run_command(self, command):\n        \"\"\"\n        Windows is having problems stopping bazel processes, so it ends up locking\n        some files if something goes wrong. Better to shut down the Bazel server after running\n        each command.\n        \"\"\"\n        try:\n            self._conanfile.run(command)\n        finally:\n            if platform.system() == \"Windows\":\n                self._conanfile.run(\"bazel\" + self._startup_opts + \" shutdown\")\n\n    def _get_startup_command_options(self):\n        bazelrc_paths = []\n        if self._use_conan_config:\n            bazelrc_paths.append(self._conan_bazelrc)\n        # User bazelrc paths have more prio than Conan one\n        # See more info in https://bazel.build/run/bazelrc\n        bazelrc_paths.extend(self._conanfile.conf.get(\"tools.google.bazel:bazelrc_path\", default=[],\n                                                      check_type=list))\n        opts = \" \".join([\"--bazelrc=\" + rc.replace(\"\\\\\", \"/\") for rc in bazelrc_paths])\n        return f\" {opts}\" if opts else \"\"\n\n    def build(self, args=None, target=\"//...\", clean=True):\n        \"\"\"\n        Runs \"bazel <rcpaths> build <configs> <args> <targets>\" command where:\n\n        * ``rcpaths``: adds ``--bazelrc=xxxx`` per rc-file path. It listens to ``BazelToolchain``\n          (``--bazelrc=conan_bzl.rc``), and ``tools.google.bazel:bazelrc_path`` conf.\n        * ``configs``: adds ``--config=xxxx`` per bazel-build configuration.\n          It listens to ``BazelToolchain`` (``--config=conan-config``), and\n          ``tools.google.bazel:configs`` conf.\n        * ``args``: they are any extra arguments to add to the ``bazel build`` execution.\n        * ``targets``: all the target labels.\n\n        :param target: It is the target label. By default, it's \"//...\" which runs all the targets.\n        :param args: list of extra arguments to pass to the CLI.\n        :param clean: boolean that indicates to run a \"bazel clean\" before running the \"bazel build\".\n                      Notice that this is important to ensure a fresh bazel cache every\n        \"\"\"\n        # Note: In case of error like this: ... https://bcr.bazel.build/: PKIX path building failed\n        # Check this comment: https://github.com/bazelbuild/bazel/issues/3915#issuecomment-1120894057\n        bazelrc_build_configs = []\n        if self._use_conan_config:\n            bazelrc_build_configs.append(BazelToolchain.bazelrc_config)\n        command = \"bazel\" + self._startup_opts + \" build\"\n        bazelrc_build_configs.extend(self._conanfile.conf.get(\"tools.google.bazel:configs\", default=[],\n                                                        check_type=list))\n        for config in bazelrc_build_configs:\n            command += f\" --config={config}\"\n        if args:\n            command += \" \".join(f\" {arg}\" for arg in args)\n        command += f\" {target}\"\n        if clean:\n            self._safe_run_command(\"bazel\" + self._startup_opts + \" clean\")\n        self._safe_run_command(command)\n\n    def test(self, target=None):\n        \"\"\"\n        Runs \"bazel test <targets>\" command.\n        \"\"\"\n        if self._conanfile.conf.get(\"tools.build:skip_test\", check_type=bool) or target is None:\n            return\n        self._safe_run_command(\"bazel\" + self._startup_opts + f\" test {target}\")\n"
  },
  {
    "path": "conan/tools/google/bazeldeps.py",
    "content": "import os\nimport re\nimport textwrap\n\nfrom jinja2 import Template, StrictUndefined\n\nfrom conan.internal import check_duplicated_generator\nfrom conan.internal.model.dependencies import get_transitive_requires\nfrom conan.internal.model.pkg_type import PackageType\nfrom conan.internal.util.files import save\n\n\ndef _relativize_path(path, start_folder):\n    \"\"\"\n    Returns a relative path with regard to the given folder.\n\n    :param path: absolute or relative path.\n    :param start_folder: folder to start relative to.\n    :return: Unix-like path relative if matches to the given pattern.\n             Otherwise, it returns the original path.\n    \"\"\"\n    if not path or not start_folder:\n        return path\n    path_ = path.replace(\"\\\\\", \"/\").replace(\"/./\", \"/\")\n    pattern_ = start_folder.replace(\"\\\\\", \"/\").replace(\"/./\", \"/\")\n    match = re.match(pattern_, path_)\n    if match:\n        matching = match[0]\n        if path_.startswith(matching):\n            path_ = path_.replace(matching, \"\").strip(\"/\")\n            return path_.strip(\"./\") or \"./\"\n    return path\n\n\nclass _BazelDepBuildGenerator:\n    \"\"\"\n    This class creates the BUILD.bazel for each dependency where it's declared all the\n    necessary information to load the libraries\n    \"\"\"\n    # If both files exist, BUILD.bazel takes precedence over BUILD\n    # https://bazel.build/concepts/build-files\n    dep_build_filename = \"BUILD.bazel\"\n    dep_build_template = textwrap.dedent(\"\"\"\\\n    {% macro cc_import_macro(libs) %}\n    {% for lib_info in libs %}\n    cc_import(\n        name = \"{{ lib_info['name'] }}_precompiled\",\n        {% if lib_info['is_shared'] %}\n        shared_library = \"{{ lib_info['lib_path'] }}\",\n        {% else %}\n        static_library = \"{{ lib_info['lib_path'] }}\",\n        {% endif %}\n        {% if lib_info['import_lib_path'] %}\n        interface_library = \"{{ lib_info['import_lib_path'] }}\",\n        {% endif %}\n        {% if lib_info[\"linkopts\"] %}\n        linkopts = [\n            {% for linkopt in lib_info[\"linkopts\"] %}\n            {{ linkopt }},\n            {% endfor %}\n        ],\n        {% endif %}\n    )\n    {% endfor %}\n    {% endmacro %}\n    {% macro cc_library_macro(obj) %}\n    cc_library(\n        name = \"{{ obj[\"name\"] }}\",\n        {% if obj[\"headers\"] %}\n        hdrs = glob([\n            {% for header in obj[\"headers\"] %}\n            {{ header }},\n            {% endfor %}\n        ],\n        allow_empty = True\n        ),\n        {% endif %}\n        {% if obj[\"includes\"] %}\n        includes = [\n            {% for include in obj[\"includes\"] %}\n            {{ include }},\n            {% endfor %}\n        ],\n        {% endif %}\n        {% if obj[\"defines\"] %}\n        defines = [\n            {% for define in obj[\"defines\"] %}\n            {{ define }},\n            {% endfor %}\n        ],\n        {% endif %}\n        {% if obj[\"linkopts\"] %}\n        linkopts = [\n            {% for linkopt in obj[\"linkopts\"] %}\n            {{ linkopt }},\n            {% endfor %}\n        ],\n        {% endif %}\n        {% if obj[\"copts\"] %}\n        copts = [\n            {% for copt in obj[\"copts\"] %}\n            {{ copt }},\n            {% endfor %}\n        ],\n        {% endif %}\n        visibility = [\"//visibility:public\"],\n        {% if obj[\"libs\"] or obj[\"dependencies\"] or obj.get(\"component_names\", []) %}\n        deps = [\n            # do not sort\n            {% for lib in obj[\"libs\"] %}\n            \":{{ lib.name }}_precompiled\",\n            {% endfor %}\n            {% for name in obj.get(\"component_names\", []) %}\n            \":{{ name }}\",\n            {% endfor %}\n            {% for dep in obj[\"dependencies\"] %}\n            \"{{ dep }}\",\n            {% endfor %}\n        ],\n        {% endif %}\n    )\n    {% endmacro %}\n    {% macro filegroup_bindirs_macro(obj) %}\n    {% if obj[\"bindirs\"] %}\n    filegroup(\n        name = \"{{ obj[\"name\"] }}_binaries\",\n        srcs = glob([\n            {% for bindir in obj[\"bindirs\"] %}\n            \"{{ bindir }}/**\",\n            {% endfor %}\n        ],\n        allow_empty = True\n        ),\n        visibility = [\"//visibility:public\"],\n    )\n    {% endif %}\n    {% endmacro %}\n    # Components precompiled libs\n    {% for component in components %}\n    {{ cc_import_macro(component[\"libs\"]) }}\n    {% endfor %}\n    # Root package precompiled libs\n    {{ cc_import_macro(root[\"libs\"]) }}\n    # Components libraries declaration\n    {% for component in components %}\n    {{ cc_library_macro(component) }}\n    {% endfor %}\n    # Package library declaration\n    {{ cc_library_macro(root) }}\n    # Filegroup library declaration\n    {{ filegroup_bindirs_macro(root) }}\n    \"\"\")\n\n    def __init__(self, conanfile, dep, require):\n        self._conanfile = conanfile\n        self._dep = dep\n        self._is_build_require = require.build\n        self._transitive_reqs = get_transitive_requires(self._conanfile, dep)\n\n    @property\n    def _build_file_path(self):\n        \"\"\"\n        Returns the absolute path to the BUILD file created by Conan\n        \"\"\"\n        folder = os.path.join(self._get_repository_name(self._dep), self.dep_build_filename)\n        return folder.replace(\"\\\\\", \"/\")\n\n    @property\n    def _absolute_build_file_path(self):\n        \"\"\"\n        Returns the absolute path to the BUILD file created by Conan\n        \"\"\"\n        folder = os.path.join(self._conanfile.generators_folder, self._build_file_path)\n        return folder.replace(\"\\\\\", \"/\")\n\n    @property\n    def _package_folder(self):\n        \"\"\"\n        Returns the package folder path\n        \"\"\"\n        # If editable, package_folder can be None\n        root_folder = self._dep.recipe_folder if self._dep.package_folder is None \\\n            else self._dep.package_folder\n        return root_folder.replace(\"\\\\\", \"/\")\n\n    def _get_repository_name(self, dep):\n        pkg_name = dep.cpp_info.get_property(\"bazel_repository_name\") or dep.ref.name\n        return f\"build-{pkg_name}\" if self._is_build_require else pkg_name\n\n    def _get_target_name(self, dep):\n        pkg_name = dep.cpp_info.get_property(\"bazel_target_name\") or dep.ref.name\n        return pkg_name\n\n    def _get_component_name(self, dep, comp_ref_name):\n        pkg_name = self._get_target_name(dep)\n        if comp_ref_name not in dep.cpp_info.components:\n            # foo::foo might be referencing the root cppinfo\n            if dep.ref.name == comp_ref_name:\n                return pkg_name\n            return f\"{pkg_name}-{comp_ref_name}\"\n        comp_name = dep.cpp_info.components[comp_ref_name].get_property(\"bazel_target_name\")\n        # If user did not set bazel_target_name, let's create a component name\n        # with a namespace, e.g., dep-comp1\n        return comp_name or f\"{pkg_name}-{comp_ref_name}\"\n\n    def _get_headers(self, cpp_info):\n        return ['\"{}/**\"'.format(_relativize_path(path, self._package_folder))\n                for path in cpp_info.includedirs]\n\n    def _get_bindirs(self, cpp_info):\n        return [_relativize_path(bindir, self._package_folder) for bindir in cpp_info.bindirs]\n\n    def _get_includes(self, cpp_info):\n        return ['\"{}\"'.format(_relativize_path(path, self._package_folder))\n                for path in cpp_info.includedirs]\n\n    def _get_defines(self, cpp_info):\n        return ['\"{}\"'.format(define.replace('\"', '\\\\' * 3 + '\"'))\n                for define in cpp_info.defines]\n\n    def _get_linkopts(self, cpp_info):\n        os_build = self._dep.settings_build.get_safe(\"os\")\n        link_opt = '/DEFAULTLIB:{}' if os_build == \"Windows\" else '-l{}'\n        system_libs = [link_opt.format(lib) for lib in cpp_info.system_libs]\n        shared_flags = cpp_info.sharedlinkflags + cpp_info.exelinkflags\n        frameworkdirs_flags = []\n        framework_flags = []\n        for frw in cpp_info.frameworks:\n            framework_flags.extend([\"-framework\", frw])\n        for frw_dir in cpp_info.frameworkdirs:\n            frameworkdirs_flags.extend([\"-F\", frw_dir.replace(\"\\\\\", \"/\")])\n        return [f'\"{flag}\"' for flag in (system_libs + shared_flags + framework_flags + frameworkdirs_flags)]\n\n    def _get_copts(self, cpp_info):\n        # FIXME: long discussions between copts (-Iflag) vs includes in Bazel. Not sure yet\n        # includedirsflags = ['\"-I{}\"'.format(_relativize_path(d, package_folder_path))\n        #                     for d in cpp_info.includedirs]\n        cxxflags = [var.replace('\"', '\\\\\"') for var in cpp_info.cxxflags]\n        cflags = [var.replace('\"', '\\\\\"') for var in cpp_info.cflags]\n        return [f'\"{flag}\"' for flag in (cxxflags + cflags)]\n\n    def _get_component_requirement_names(self, cpp_info):\n        \"\"\"\n        Get all the valid names from the requirements ones given a CppInfo object.\n\n        For instance, those requirements could be coming from:\n\n        ```python\n        from conan import ConanFile\n        class PkgConan(ConanFile):\n            requires = \"other/1.0\"\n\n            def package_info(self):\n                self.cpp_info.requires = [\"other::cmp1\"]\n\n            # Or:\n\n            def package_info(self):\n                self.cpp_info.components[\"cmp\"].requires = [\"other::cmp1\"]\n        ```\n        \"\"\"\n        dep_ref_name = self._dep.ref.name\n        ret = []\n        for req in cpp_info.requires:\n            pkg_ref_name, comp_ref_name = req.split(\"::\") if \"::\" in req else (dep_ref_name, req)\n            prefix = \":\"  # Requirements declared in the same BUILD file\n            # For instance, dep == \"hello/1.0\" and req == \"other::cmp1\" -> hello != other\n            if dep_ref_name != pkg_ref_name:\n                try:\n                    req_conanfile = self._transitive_reqs[pkg_ref_name]\n                    # Requirements declared in another dependency BUILD file\n                    prefix = f\"@{self._get_repository_name(req_conanfile)}//:\"\n                except KeyError:\n                    continue  # If the dependency is not in the transitive, might be skipped\n            else:  # For instance, dep == \"hello/1.0\" and req == \"hello::cmp1\" -> hello == hello\n                req_conanfile = self._dep\n            comp_name = self._get_component_name(req_conanfile, comp_ref_name)\n            dep_name = f\"{prefix}{comp_name}\"\n            if dep_name not in ret:\n                ret.append(dep_name)\n        return ret\n\n    def _get_lib_info(self, cpp_info, deduced_cpp_info, component_name=None):\n\n        def _lib_info(lib_name, virtual_cpp_info):\n            info = {\n                \"name\": lib_name,\n                \"is_shared\": virtual_cpp_info.type == PackageType.SHARED,\n                \"lib_path\": _relativize_path(virtual_cpp_info.location, self._package_folder),\n                \"import_lib_path\": _relativize_path(virtual_cpp_info.link_location, self._package_folder),\n                \"linkopts\": []\n            }\n            if info['is_shared'] and info[\"lib_path\"] and not info[\"lib_path\"].endswith(\".dll\"):\n                # Issue: https://github.com/conan-io/conan/issues/19190\n                # Issue: https://github.com/conan-io/conan/issues/19135\n                # (UNIX) Adding the rpath flag as any application could link through the library\n                # which points out a symlink, but that name does not appear in the library location\n                info[\"linkopts\"] = [f'\"-Wl,-rpath,{libdir}\"' for libdir in cpp_info.libdirs]\n            return info\n\n        libs = cpp_info.libs\n        libs_info = []\n        if libs:\n            if len(libs) > 1:\n                for lib_name in libs:\n                    name = f'_{component_name}_{lib_name}' if component_name else f'_{lib_name}'\n                    virtual_cpp_info = deduced_cpp_info.components[name]\n                    libs_info.append(_lib_info(lib_name, virtual_cpp_info))\n            else:\n                lib_name = libs[0]\n                virtual_cpp_info = deduced_cpp_info.components[component_name] if component_name else deduced_cpp_info\n                libs_info.append(_lib_info(lib_name, virtual_cpp_info))\n        return libs_info\n\n    def _get_build_file_context(self):\n        \"\"\"\n        Get the whole package information\n\n        :return: `_BazelTargetInfo` object with the package information\n        \"\"\"\n        build_content = {\"components\": [], \"root\": {}}\n        component_names = []\n        deduced_cpp_info = self._dep.cpp_info.deduce_full_cpp_info(self._dep)\n\n        if self._dep.cpp_info.has_components:\n            # Loop through all the package's components\n            for comp_ref_name, cmp_cpp_info in self._dep.cpp_info.get_sorted_components().items():\n                # At first, let's check if we have defined some components requires, e.g., \"dep::cmp1\"\n                comp_requires_names = self._get_component_requirement_names(cmp_cpp_info)\n                comp_name = self._get_component_name(self._dep, comp_ref_name)\n                component_names.append(comp_name)\n                build_content[\"components\"].append({\n                    \"name\": comp_name,\n                    \"libs\": self._get_lib_info(cmp_cpp_info, deduced_cpp_info, component_name=comp_ref_name),\n                    \"bindirs\": self._get_bindirs(cmp_cpp_info),\n                    \"headers\": self._get_headers(cmp_cpp_info),\n                    \"includes\": self._get_includes(cmp_cpp_info),\n                    \"defines\": self._get_defines(cmp_cpp_info),\n                    \"linkopts\": self._get_linkopts(cmp_cpp_info),\n                    \"copts\": self._get_copts(cmp_cpp_info),\n                    \"dependencies\": comp_requires_names,\n                })\n\n        pkg_name = self._get_target_name(self._dep)\n        # At first, let's check if we have defined some global requires, e.g., \"other::cmp1\"\n        requires = self._get_component_requirement_names(self._dep.cpp_info)\n        # If we have found some component requires it would be enough\n        if not requires:\n            # If no requires were found, let's try to get all the direct dependencies,\n            # e.g., requires = \"other_pkg/1.0\"\n            requires = [\n                f\"@{self._get_repository_name(req)}//:{self._get_target_name(req)}\"\n                for req in self._transitive_reqs.values()\n            ]\n        cpp_info = self._dep.cpp_info\n        build_content[\"root\"] = {\n            \"name\": pkg_name,\n            \"libs\": self._get_lib_info(cpp_info, deduced_cpp_info),\n            \"bindirs\": self._get_bindirs(cpp_info),\n            \"headers\": self._get_headers(cpp_info),\n            \"includes\": self._get_includes(cpp_info),\n            \"defines\": self._get_defines(cpp_info),\n            \"linkopts\": self._get_linkopts(cpp_info),\n            \"copts\": self._get_copts(cpp_info),\n            \"dependencies\": requires,\n            \"component_names\": component_names\n        }\n        return build_content\n\n    @property\n    def dep_context(self):\n        \"\"\"\n        Return the dependency context to fill later the conan_deps_module_extension.bzl and so on.\n        \"\"\"\n        return {\n            'repository_name': self._get_repository_name(self._dep),\n            'package_folder': self._package_folder,\n            'package_build_file_path': self._absolute_build_file_path,\n        }\n\n    def items(self):\n        template = Template(self.dep_build_template, trim_blocks=True, lstrip_blocks=True,\n                            undefined=StrictUndefined)\n        content = template.render(self._get_build_file_context())\n        return {self._build_file_path: content}.items()\n\n\nclass _BazelPathsGenerator:\n    \"\"\"\n    Bazel 6.0 needs to know all the dependencies for its current project. So, the only way\n    to do that is to tell the WORKSPACE file how to load all the Conan ones. This is the goal\n    of the function created by this class, the ``load_conan_dependencies`` one.\n\n    More information:\n        * https://bazel.build/reference/be/workspace#new_local_repository\n\n    Bazel >= 7.1 needs to know all the dependencies as well, but provided via the MODULE.bazel file.\n    Therefor we provide a static repository rule to load the dependencies. This rule is used by a\n    module extension, passing the package path and the BUILD file path to the repository rule.\n    \"\"\"\n    repository_filename = \"dependencies.bzl\"\n    modules_filename = \"conan_deps_module_extension.bzl\"\n    repository_rules_filename = \"conan_deps_repo_rules.bzl\"\n    repository_template = textwrap.dedent(\"\"\"\\\n        # This Bazel module should be loaded by your WORKSPACE file.\n        # Add these lines to your WORKSPACE one (assuming that you're using the \"bazel_layout\"):\n        # load(\"@//conan:dependencies.bzl\", \"load_conan_dependencies\")\n        # load_conan_dependencies()\n\n        def load_conan_dependencies():\n        {% for dep_info in dependencies %}\n            native.new_local_repository(\n                name=\"{{dep_info['repository_name']}}\",\n                path=\"{{dep_info['package_folder']}}\",\n                build_file=\"{{dep_info['package_build_file_path']}}\",\n            )\n        {% endfor %}\n        \"\"\")\n    module_template = textwrap.dedent(\"\"\"\\\n        # This module provides a repo for each requires-dependency in your conanfile.\n        # It's generated by the BazelDeps, and should be used in your Module.bazel file.\n        load(\":conan_deps_repo_rules.bzl\", \"conan_dependency_repo\")\n\n        def _load_dependencies_impl(mctx):\n        {% for dep_info in dependencies %}\n            conan_dependency_repo(\n                name = \"{{dep_info['repository_name']}}\",\n                package_path = \"{{dep_info['package_folder']}}\",\n                build_file_path = \"{{dep_info['package_build_file_path']}}\",\n            )\n        {% endfor %}\n\n            return mctx.extension_metadata(\n                # It will only warn you if any direct\n                # dependency is not imported by the 'use_repo' or even it is imported\n                # but not created. Notice that root_module_direct_dev_deps can not be None as we\n                # are giving 'all' value to root_module_direct_deps.\n                # Fix the 'use_repo' calls by running 'bazel mod tidy'\n                root_module_direct_deps = 'all',\n                root_module_direct_dev_deps = [],\n\n                # Prevent writing function content to lockfiles:\n                # - https://bazel.build/rules/lib/builtins/module_ctx#extension_metadata\n                # Important for remote build. Actually it's not reproducible, as local paths will\n                # be different on different machines. But we assume that conan works correctly here.\n                # IMPORTANT: Not compatible with bazel < 7.1\n                reproducible = True,\n            )\n\n        conan_extension = module_extension(\n            implementation = _load_dependencies_impl,\n            os_dependent = True,\n            arch_dependent = True,\n        )\n        \"\"\")\n    repository_rules_content = textwrap.dedent(\"\"\"\\\n        # This bazel repository rule is used to load Conan dependencies into the Bazel workspace.\n        # It's used by a generated module file that provides information about the conan packages.\n        # Each conan package is loaded into a bazel repository rule, with having the name of the\n        # package. The whole method is based on symlinks to not copy the whole package into the\n        # Bazel workspace, which is expensive.\n        def _conan_dependency_repo(rctx):\n            package_path = rctx.workspace_root.get_child(rctx.attr.package_path)\n\n            child_packages = package_path.readdir()\n            for child in child_packages:\n                rctx.symlink(child, child.basename)\n\n            rctx.symlink(rctx.attr.build_file_path, \"BUILD.bazel\")\n\n        conan_dependency_repo = repository_rule(\n            implementation = _conan_dependency_repo,\n            attrs = {\n                \"package_path\": attr.string(\n                    mandatory = True,\n                    doc = \"The path to the Conan package in conan cache.\",\n                ),\n                \"build_file_path\": attr.string(\n                    mandatory = True,\n                    doc = \"The path to the BUILD file.\",\n                ),\n            },\n        )\n        \"\"\")\n\n    @classmethod\n    def items(cls, dependencies_context):\n        if not dependencies_context:\n            return {}\n        # Bazel 6.x, but it'll likely be dropped soon\n        repository_template = Template(cls.repository_template, trim_blocks=True,\n                                       lstrip_blocks=True,\n                                       undefined=StrictUndefined)\n        content_6x = repository_template.render(dependencies=dependencies_context)\n        # Bazel 7.x files\n        module_template = Template(cls.module_template, trim_blocks=True, lstrip_blocks=True,\n                                   undefined=StrictUndefined)\n        content = module_template.render(dependencies=dependencies_context)\n        return {\n            cls.repository_filename: content_6x,  # bazel 6.x compatible\n            cls.modules_filename: content,\n            cls.repository_rules_filename: cls.repository_rules_content,\n            \"BUILD.bazel\": \"# This is an empty BUILD file.\"  # Bazel needs this file in each subfolder\n        }.items()\n\n\nclass BazelDeps:\n\n    def __init__(self, conanfile):\n        \"\"\"\n        :param conanfile: ``< ConanFile object >`` The current recipe object. Always use ``self``.\n        \"\"\"\n        self._conanfile = conanfile\n        #: Activates the build context for the specified Conan package names.\n        self.build_context_activated = []\n\n    def _get_requirements(self, build_context_activated):\n        \"\"\"\n        Simply save the activated requirements (host + build + test), and the deactivated ones\n        \"\"\"\n        # All the requirements\n        host_req = self._conanfile.dependencies.host\n        build_req = self._conanfile.dependencies.direct_build  # tool_requires\n        test_req = self._conanfile.dependencies.test\n\n        for require, dep in list(host_req.items()) + list(build_req.items()) + list(\n            test_req.items()):\n            # Require is not used at the moment, but its information could be used,\n            # and will be used in Conan 2.0\n            # Filter the build_requires not activated with self.build_context_activated\n            if require.build and dep.ref.name not in build_context_activated:\n                continue\n            yield require, dep\n\n    def generate(self):\n        \"\"\"\n        Generates all the targets <DEP>/BUILD.bazel files, a dependencies.bzl (for bazel<7), a\n        conan_deps_repo_rules.bzl and a conan_deps_module_extension.bzl file (for bazel>=7.1) one in the\n        build folder.\n\n        In case of bazel < 7, it's important to highlight that the ``dependencies.bzl`` file should\n        be loaded by your WORKSPACE Bazel file:\n\n        .. code-block:: python\n\n            load(\"@//[BUILD_FOLDER]:dependencies.bzl\", \"load_conan_dependencies\")\n            load_conan_dependencies()\n\n        In case of bazel >= 7.1, the ``conan_deps_module_extension.bzl`` file should be loaded by your\n        Module.bazel file, e.g. like this:\n\n        .. code-block:: python\n\n            load_conan_dependencies = use_extension(\n                \"//build:conan_deps_module_extension.bzl\",\n                \"conan_extension\"\n            )\n            use_repo(load_conan_dependencies, \"dep-1\", \"dep-2\", ...)\n        \"\"\"\n        check_duplicated_generator(self, self._conanfile)\n        dependencies_context = []\n        for require, dep in self._get_requirements(self.build_context_activated):\n            # Bazel info generator\n            dep_build_generator = _BazelDepBuildGenerator(self._conanfile, dep, require)\n            dependencies_context.append(dep_build_generator.dep_context)\n            for name, content in dep_build_generator.items():\n                save(name, content)\n\n        for name, content in _BazelPathsGenerator.items(dependencies_context):\n            save(name, content)\n"
  },
  {
    "path": "conan/tools/google/layout.py",
    "content": "import os\n\n\ndef bazel_layout(conanfile, src_folder=\".\", build_folder=\".\", target_folder=None):\n    \"\"\"Bazel layout is so limited. It does not allow to create its special symlinks in other\n    folder. See more information in https://bazel.build/remote/output-directories\"\"\"\n    subproject = conanfile.folders.subproject\n    conanfile.folders.source = src_folder if not subproject else os.path.join(subproject, src_folder)\n    # Bazel always builds the whole project in the root folder, but consumer can put another one\n    conanfile.folders.build = build_folder if not subproject else os.path.join(subproject, build_folder)\n    generators_folder = conanfile.folders.generators or \"conan\"\n    conanfile.folders.generators = os.path.join(conanfile.folders.build, generators_folder)\n    bindirs = os.path.join(conanfile.folders.build, \"bazel-bin\")\n    libdirs = os.path.join(conanfile.folders.build, \"bazel-bin\")\n    # Target folder is useful for working on editable mode\n    if target_folder:\n        bindirs = os.path.join(bindirs, target_folder)\n        libdirs = os.path.join(libdirs, target_folder)\n    conanfile.cpp.build.bindirs = [bindirs]\n    conanfile.cpp.build.libdirs = [libdirs]\n"
  },
  {
    "path": "conan/tools/google/toolchain.py",
    "content": "\"\"\"\nCreates a simple conan_bzl.rc file which defines a conan-config configuration with all the\nattributes defined by the consumer. Bear in mind that this is not a complete toolchain, it\nonly fills some common CLI attributes and save them in a ``*.rc`` file.\n\nImportant: Maybe, this toolchain should create a new Conan platform with the user\nconstraints, but it's not the goal for now as Bazel has tons of platforms and toolchains\nalready available in its bazel_tools repo. For now, it only admits a list of platforms defined\nby the user.\n\nMore information related:\n    * Toolchains: https://bazel.build/extending/toolchains (deprecated)\n    * Platforms: https://bazel.build/concepts/platforms (new default since Bazel 7.x)\n    * Migrating to platforms: https://bazel.build/concepts/platforms\n    * Issue related: https://github.com/bazelbuild/bazel/issues/6516\n\nOthers:\n    * CROOSTOOL: https://github.com/bazelbuild/bazel/blob/cb0fb033bad2a73e0457f206afb87e195be93df2/tools/cpp/CROSSTOOL\n    * Cross-compiling with Bazel: https://ltekieli.com/cross-compiling-with-bazel/\n    * bazelrc files: https://bazel.build/run/bazelrc\n    * CLI options: https://bazel.build/reference/command-line-reference\n    * User manual: https://bazel.build/docs/user-manual\n\"\"\"\nimport textwrap\n\nfrom jinja2 import Template\n\nfrom conan.internal import check_duplicated_generator\nfrom conan.internal.internal_tools import raise_on_universal_arch\nfrom conan.tools.apple import to_apple_arch, is_apple_os\nfrom conan.tools.build.cross_building import cross_building\nfrom conan.tools.build.flags import cppstd_flag\nfrom conan.tools.files import save\n\n\ndef _get_cpu_name(conanfile):\n    host_os = conanfile.settings.get_safe('os').lower()\n    host_arch = conanfile.settings.get_safe('arch')\n    if is_apple_os(conanfile):\n        host_os = \"darwin\" if host_os == \"macos\" else host_os\n        host_arch = to_apple_arch(conanfile)\n    # FIXME: Probably it's going to fail, but let's try it because it normally follows this syntax\n    return f\"{host_os}_{host_arch}\"\n\n\n# FIXME: In the future, it could be BazelPlatform instead? Check https://bazel.build/concepts/platforms\nclass BazelToolchain:\n    bazelrc_name = \"conan_bzl.rc\"\n    bazelrc_config = \"conan-config\"\n    bazelrc_template = textwrap.dedent(\"\"\"\\\n    # Automatic bazelrc file created by Conan\n    {% if copt %}build:conan-config {{copt}}{% endif %}\n    {% if conlyopt %}build:conan-config {{conlyopt}}{% endif %}\n    {% if cxxopt %}build:conan-config {{cxxopt}}{% endif %}\n    {% if linkopt %}build:conan-config {{linkopt}}{% endif %}\n    {% if force_pic %}build:conan-config --force_pic={{force_pic}}{% endif %}\n    {% if dynamic_mode %}build:conan-config --dynamic_mode={{dynamic_mode}}{% endif %}\n    {% if compilation_mode %}build:conan-config --compilation_mode={{compilation_mode}}{% endif %}\n    {% if compiler %}build:conan-config --compiler={{compiler}}{% endif %}\n    {% if cpu %}build:conan-config --cpu={{cpu}}{% endif %}\n    {% if crosstool_top %}build:conan-config --crosstool_top={{crosstool_top}}{% endif %}\"\"\")\n\n    def __init__(self, conanfile):\n        \"\"\"\n        :param conanfile: ``< ConanFile object >`` The current recipe object. Always use ``self``.\n        \"\"\"\n        raise_on_universal_arch(conanfile)\n\n        self._conanfile = conanfile\n\n        # Bazel build parameters\n        shared = self._conanfile.options.get_safe(\"shared\")\n        fpic = self._conanfile.options.get_safe(\"fPIC\")\n        #: Boolean used to add --force_pic=True. Depends on self.options.shared and\n        #: self.options.fPIC values\n        self.force_pic = fpic if (not shared and fpic is not None) else None\n        # FIXME: Keeping this option but it's not working as expected. It's not creating the shared\n        #        libraries at all.\n        #: String used to add --dynamic_mode=[\"fully\"|\"off\"]. Depends on self.options.shared value.\n        self.dynamic_mode = \"fully\" if shared else \"off\"\n        #: String used to add --cppstd=[FLAG]. Depends on your settings.\n        self.cppstd = cppstd_flag(self._conanfile)\n        #: List of flags used to add --copt=flag1 ... --copt=flagN\n        self.copt = []\n        #: List of flags used to add --conlyopt=flag1 ... --conlyopt=flagN\n        self.conlyopt = []\n        #: List of flags used to add --cxxopt=flag1 ... --cxxopt=flagN\n        self.cxxopt = []\n        #: List of flags used to add --linkopt=flag1 ... --linkopt=flagN\n        self.linkopt = []\n        #: String used to add --compilation_mode=[\"opt\"|\"dbg\"]. Depends on self.settings.build_type\n        self.compilation_mode = {'Release': 'opt', 'Debug': 'dbg'}.get(\n            self._conanfile.settings.get_safe(\"build_type\")\n        )\n        # Be aware that this parameter does not admit a compiler absolute path\n        # If you want to add it, you will have to use a specific Bazel toolchain\n        #: String used to add --compiler=xxxx.\n        self.compiler = None\n        # cpu is the target architecture, and it's a bit tricky. If it's not a cross-compilation,\n        # let Bazel guess it.\n        #: String used to add --cpu=xxxxx. At the moment, it's only added if cross-building.\n        self.cpu = None\n        # TODO: cross-compilation process is so powerless. Needs to use the new platforms.\n        if cross_building(self._conanfile):\n            # Bazel is using those toolchains/platforms by default.\n            # It's better to let it configure the project in that case\n            self.cpu = _get_cpu_name(conanfile)\n        # This is itself a toolchain but just in case\n        #: String used to add --crosstool_top.\n        self.crosstool_top = None\n        # TODO: Have a look at https://bazel.build/reference/be/make-variables\n        # FIXME: Missing host_xxxx options. When are they needed? Cross-compilation?\n\n    @staticmethod\n    def _filter_list_empty_fields(v):\n        return list(filter(bool, v))\n\n    @property\n    def cxxflags(self):\n        ret = [self.cppstd]\n        conf_flags = self._conanfile.conf.get(\"tools.build:cxxflags\", default=[], check_type=list)\n        ret = ret  + self.cxxopt + conf_flags\n        return self._filter_list_empty_fields(ret)\n\n    @property\n    def cflags(self):\n        conf_flags = self._conanfile.conf.get(\"tools.build:cflags\", default=[], check_type=list)\n        ret = self.conlyopt + conf_flags\n        return self._filter_list_empty_fields(ret)\n\n    @property\n    def ldflags(self):\n        conf_flags = self._conanfile.conf.get(\"tools.build:sharedlinkflags\", default=[],\n                                              check_type=list)\n        conf_flags.extend(self._conanfile.conf.get(\"tools.build:exelinkflags\", default=[],\n                                                   check_type=list))\n        linker_scripts = self._conanfile.conf.get(\"tools.build:linker_scripts\", default=[], check_type=list)\n        conf_flags.extend([\"-T'\" + linker_script + \"'\" for linker_script in linker_scripts])\n        ret = self.linkopt + conf_flags\n        return self._filter_list_empty_fields(ret)\n\n    def _context(self):\n        return {\n            \"copt\": \" \".join(f\"--copt={flag}\" for flag in self.copt),\n            \"conlyopt\": \" \".join(f\"--conlyopt={flag}\" for flag in self.cflags),\n            \"cxxopt\": \" \".join(f\"--cxxopt={flag}\" for flag in self.cxxflags),\n            \"linkopt\": \" \".join(f\"--linkopt={flag}\" for flag in self.ldflags),\n            \"force_pic\": self.force_pic,\n            \"dynamic_mode\": self.dynamic_mode,\n            \"compilation_mode\": self.compilation_mode,\n            \"compiler\": self.compiler,\n            \"cpu\": self.cpu,\n            \"crosstool_top\": self.crosstool_top,\n        }\n\n    @property\n    def _content(self):\n        context = self._context()\n        content = Template(self.bazelrc_template).render(context)\n        return content\n\n    def generate(self):\n        \"\"\"\n        Creates a ``conan_bzl.rc`` file with some bazel-build configuration. This last mentioned\n        is put as ``conan-config``.\n        \"\"\"\n        check_duplicated_generator(self, self._conanfile)\n        save(self._conanfile, BazelToolchain.bazelrc_name, self._content)\n"
  },
  {
    "path": "conan/tools/intel/__init__.py",
    "content": "from conan.tools.intel.intel_cc import IntelCC\n"
  },
  {
    "path": "conan/tools/intel/intel_cc.py",
    "content": "\"\"\"\n    Intel generator module for oneAPI Toolkits.\n\n    For simplicity and clarity, Intel informally refers to some of the terms in this document,\n    as listed below:\n\n        - ICX - Intel oneAPI DPC++/C++ Compiler\n        - ICC Classic - Intel C++ Compiler Classic\n        - DPCPP - Intel oneAPI DPC++/C++ Compiler\n\n    DPCPP is built upon ICX as the underlying C++ Compiler, therefore most of this information\n    also applies to DPCPP.\n\n    Intel oneAPI Toolkit (DPC++/C++ Compiler)\n        - Versioning: https://software.intel.com/content/www/us/en/develop/articles/oneapi-toolkit-version-to-compiler-version-mapping.html\n        - Compiler: https://software.intel.com/content/www/us/en/develop/documentation/oneapi-dpcpp-cpp-compiler-dev-guide-and-reference/top.html\n\"\"\"\nimport os\nimport platform\nimport textwrap\n\nfrom conan.internal import check_duplicated_generator\nfrom conan.errors import ConanException\n\n\ndef _is_using_intel_oneapi(compiler_version):\n    \"\"\"Check if the Intel compiler to be used belongs to Intel oneAPI\n\n    Note: Intel oneAPI Toolkit first version is 2021.1\n    \"\"\"\n    return int(compiler_version.split(\".\")[0]) >= 2021\n\n\nclass IntelCC:\n    \"\"\"Class that manages Intel oneAPI DPC++/C++/Classic Compilers vars generation\"\"\"\n\n    filename = \"conanintelsetvars\"\n\n    def __init__(self, conanfile):\n        # Let's check the compatibility\n        compiler_version = conanfile.settings.get_safe(\"compiler.version\")\n        mode = conanfile.settings.get_safe(\"compiler.mode\")\n        if _is_using_intel_oneapi(compiler_version):\n            if mode != \"classic\" and conanfile.settings.get_safe(\"os\") == \"Darwin\":\n                raise ConanException(\n                    'macOS* is not supported for the icx/icpx or dpcpp compilers. '\n                    'Use the \"classic\" mode (icc compiler) instead.')\n        else:\n            # Do not support legacy versions\n            raise ConanException(\"You have to use 'intel' compiler which is meant for legacy \"\n                                 \"versions like Intel Parallel Studio XE.\")\n        # Private properties\n        self._conanfile = conanfile\n        self._settings = conanfile.settings\n        self._compiler_version = compiler_version\n        self._mode = mode\n        self._out = conanfile.output\n        # Public properties\n        #: arch setting\n        self.arch = conanfile.settings.get_safe(\"arch\")\n\n    @property\n    def ms_toolset(self):\n        \"\"\"Get Microsoft Visual Studio Toolset depending on the mode selected\"\"\"\n        if self._mode == \"classic\":\n            # TODO: Get automatically the classic compiler version\n            return \"Intel C++ Compiler 19.2\"\n        elif self._mode == \"icx\":\n            return \"Intel C++ Compiler %s\" % (self._compiler_version.split('.')[0])\n        else:  # DPC++ compiler\n            return \"Intel(R) oneAPI DPC++ Compiler\"\n\n    def generate(self, scope=\"build\"):\n        \"\"\"Generate the Conan Intel file to be loaded in build environment by default\"\"\"\n        check_duplicated_generator(self, self._conanfile)\n        intel_cc_path = self._conanfile.conf.get(\"tools.intel:installation_path\")\n        if intel_cc_path == \"\":\n            return\n\n        if platform.system() == \"Windows\" and not self._conanfile.win_bash:\n            content = textwrap.dedent(\"\"\"\\\n                @echo off\n                {}\n                \"\"\".format(self.command))\n            filename = self.filename + '.bat'\n        else:\n            filename = self.filename + '.sh'\n            content = self.command\n        from conan.tools.env.environment import create_env_script\n        create_env_script(self._conanfile, content, filename, scope)\n\n    @property\n    def installation_path(self):\n        \"\"\"Get the Intel oneAPI installation root path\"\"\"\n        installation_path = self._conanfile.conf.get(\"tools.intel:installation_path\")\n        if not installation_path:\n            raise ConanException(\"To use Intel oneAPI, specify a [conf] entry \"\n                                 \"'tools.intel:installation_path' containing the path to the \"\n                                 \"installation folder.\")\n        self._out.info(\"Got Intel oneAPI installation folder: %s\" % installation_path)\n        return installation_path\n\n    @property\n    def command(self):\n        \"\"\"\n        The Intel oneAPI DPC++/C++ Compiler includes environment configuration scripts to\n        configure your build and development environment variables:\n\n        - On Linux, the file is a shell script called setvars.sh.\n        - On Windows, the file is a batch file called setvars.bat.\n\n        - Linux -> ``>> . /<install-dir>/setvars.sh <arg1> <arg2> … <argn><arg1> <arg2> … <argn>``\n          The compiler environment script file accepts an optional target architecture\n          argument <arg>:\n          - intel64: Generate code and use libraries for Intel 64 architecture-based targets.\n          - ia32: Generate code and use libraries for IA-32 architecture-based targets.\n\n        - Windows -> ``>> call <install-dir>\\\\setvars.bat [<arg1>] [<arg2>]``\n          Where <arg1> is optional and can be one of the following:\n          - intel64: Generate code and use libraries for Intel 64 architecture (host and target).\n          - ia32: Generate code and use libraries for IA-32 architecture (host and target).\n\n          With the dpcpp compiler, <arg1> is intel64 by default.\n\n          The <arg2> is optional. If specified, it is one of the following:\n          - vs2019: Microsoft Visual Studio* 2019\n          - vs2017: Microsoft Visual Studio 2017\n\n        :return: `str` setvars.sh|bat command to be run\n        \"\"\"\n        # Let's check if user wants to use some custom arguments to run the setvars script\n        command_args = self._conanfile.conf.get(\"tools.intel:setvars_args\", default=\"\")\n        system = platform.system()\n        svars = \"setvars.bat\" if system == \"Windows\" else \"setvars.sh\"\n        command = '\"%s\"' % os.path.join(self.installation_path, svars)\n        if system == \"Windows\":\n            command = \"call \" + command\n        else:\n            command = \". \" + command  # dot is more portable than source\n        # If user has passed custom arguments\n        if command_args:\n            command += \" %s\" % command_args\n            return command\n        # Add architecture argument\n        if self.arch == \"x86_64\":\n            command += \" intel64\"\n        elif self.arch == \"x86\":\n            command += \" ia32\"\n        else:\n            raise ConanException(\"don't know how to call %s for %s\" % (svars, self.arch))\n\n        return command\n"
  },
  {
    "path": "conan/tools/layout/__init__.py",
    "content": "import os\n\n\ndef basic_layout(conanfile, src_folder=\".\", build_folder=None):\n    subproject = conanfile.folders.subproject\n\n    conanfile.folders.source = src_folder if not subproject else os.path.join(subproject, src_folder)\n    if build_folder:\n        conanfile.folders.build = build_folder if not subproject else os.path.join(subproject, build_folder)\n    else:\n        conanfile.folders.build = \"build\" if not subproject else os.path.join(subproject, \"build\")\n        if conanfile.settings.get_safe(\"build_type\"):\n            conanfile.folders.build += \"-{}\".format(str(conanfile.settings.build_type).lower())\n    conanfile.folders.generators = os.path.join(conanfile.folders.build, \"conan\")\n    conanfile.cpp.build.bindirs = [\".\"]\n    conanfile.cpp.build.libdirs = [\".\"]\n\n    if not conanfile.cpp.source.includedirs:\n        conanfile.cpp.source.includedirs = [\"include\"]\n"
  },
  {
    "path": "conan/tools/meson/__init__.py",
    "content": "from conan.tools.meson.meson import Meson\nfrom conan.tools.meson.toolchain import MesonToolchain\n\n"
  },
  {
    "path": "conan/tools/meson/helpers.py",
    "content": "from conan.api.output import ConanOutput\nfrom conan.tools.build.flags import cppstd_msvc_flag, disable_flag\nfrom conan.internal.model.options import _PackageOption\n\n# https://mesonbuild.com/Reference-tables.html#operating-system-names\n_meson_system_map = {\n    'Android': 'android',\n    'Macos': 'darwin',\n    'iOS': 'darwin',\n    'watchOS': 'darwin',\n    'tvOS': 'darwin',\n    'visionOS': 'darwin',\n    'FreeBSD': 'freebsd',\n    'Emscripten': 'emscripten',\n    'Linux': 'linux',\n    'SunOS': 'sunos',\n    'Windows': 'windows',\n    'WindowsCE': 'windows',\n    'WindowsStore': 'windows',\n}\n\n# https://mesonbuild.com/Reference-tables.html#cpu-families\n_meson_cpu_family_map = {\n    'armv4': ('arm', 'armv4', 'little'),\n    'armv4i': ('arm', 'armv4i', 'little'),\n    'armv5el': ('arm', 'armv5el', 'little'),\n    'armv5hf': ('arm', 'armv5hf', 'little'),\n    'armv6': ('arm', 'armv6', 'little'),\n    'armv7': ('arm', 'armv7', 'little'),\n    'armv7hf': ('arm', 'armv7hf', 'little'),\n    'armv7s': ('arm', 'armv7s', 'little'),\n    'armv7k': ('arm', 'armv7k', 'little'),\n    'armv8': ('aarch64', 'armv8', 'little'),\n    'armv8_32': ('aarch64', 'armv8_32', 'little'),\n    'armv8.3': ('aarch64', 'armv8.3', 'little'),\n    'arm64ec': ('aarch64', 'arm64ec', 'little'),\n    'avr': ('avr', 'avr', 'little'),\n    'mips': ('mips', 'mips', 'big'),\n    'mips64': ('mips64', 'mips64', 'big'),\n    'ppc32be': ('ppc', 'ppc', 'big'),\n    'ppc32': ('ppc', 'ppc', 'little'),\n    'ppc64le': ('ppc64', 'ppc64', 'little'),\n    'ppc64': ('ppc64', 'ppc64', 'big'),\n    's390': ('s390', 's390', 'big'),\n    's390x': ('s390x', 's390x', 'big'),\n    'sh4le': ('sh4', 'sh4', 'little'),\n    'sparc': ('sparc', 'sparc', 'big'),\n    'sparcv9': ('sparc64', 'sparc64', 'big'),\n    'wasm': ('wasm32', 'wasm32', 'little'),\n    'wasm64': ('wasm64', 'wasm64', 'little'),\n    'x86': ('x86', 'x86', 'little'),\n    'x86_64': ('x86_64', 'x86_64', 'little'),\n    'riscv32': ('riscv32', 'riscv32', 'little'),\n    'riscv64': ('riscv64', 'riscv64', 'little')\n}\n\n\ndef get_apple_subsystem(apple_sdk):\n    return {\n        \"iphoneos\": \"ios\",\n        \"iphonesimulator\": \"ios-simulator\",\n        \"appletvos\": \"tvos\",\n        \"appletvsimulator\": \"tvos-simulator\",\n        \"watchos\": \"watchos\",\n        \"watchsimulator\": \"watchos-simulator\",\n    }.get(apple_sdk, \"macos\")\n\n\ndef to_meson_machine(machine_os, machine_arch):\n    \"\"\"Gets the OS system info as the Meson machine context.\n\n    :param machine_os: ``str`` OS name.\n    :param machine_arch: ``str`` OS arch.\n    :return: ``dict`` Meson machine context.\n    \"\"\"\n    system = _meson_system_map.get(machine_os, machine_os.lower())\n    default_cpu_tuple = (machine_arch.lower(), machine_arch.lower(), 'little')\n    cpu_tuple = _meson_cpu_family_map.get(machine_arch, default_cpu_tuple)\n    cpu_family, cpu, endian = cpu_tuple[0], cpu_tuple[1], cpu_tuple[2]\n    context = {\n        'system': system,\n        'cpu_family': cpu_family,\n        'cpu': cpu,\n        'endian': endian,\n    }\n    return context\n\n\ndef to_meson_value(value):\n    \"\"\"Puts any value with a valid str-like Meson format.\n\n    :param value: ``str``, ``bool``, or ``list``, otherwise, it will do nothing.\n    :return: formatted value as a ``str``.\n    \"\"\"\n    # https://mesonbuild.com/Machine-files.html#data-types\n    # we don't need to transform the integer values\n    if isinstance(value, str):\n        return f\"'{value}'\"\n    elif isinstance(value, bool):\n        return 'true' if value else 'false'\n    elif isinstance(value, list):\n        return '[{}]'.format(', '.join([str(to_meson_value(val)) for val in value]))\n    elif isinstance(value, _PackageOption):\n        ConanOutput().warning(f\"Please, do not use a Conan option value directly. \"\n                              f\"Convert 'options.{value.name}' into a valid Python\"\n                              f\"data type, e.g, bool(self.options.shared)\", warn_tag=\"deprecated\")\n    return value\n\n\ndef to_cppstd_flag(conanfile, compiler, compiler_version, cppstd):\n    \"\"\"Gets a valid cppstd flag.\n    :param conanfile: ``ConanFile`` instance.\n    :param compiler: ``str`` compiler name.\n    :param compiler_version: ``str`` compiler version.\n    :param cppstd: ``str`` cppstd version.\n    :return: ``str`` cppstd flag.\n    \"\"\"\n    if cppstd is None:\n        return None\n    if disable_flag(conanfile, \"cppstd\"):\n        return None\n    if compiler == \"msvc\":\n        # Meson's logic with 'vc++X' vs 'c++X' is possibly a little outdated.\n        # Presumably the intent is 'vc++X' is permissive and 'c++X' is not,\n        # but '/permissive-' is the default since 16.8.\n        flag = cppstd_msvc_flag(compiler_version, cppstd)\n        return 'v%s' % flag if flag else None\n    else:\n        return f\"gnu++{cppstd[3:]}\" if cppstd.startswith(\"gnu\") else f\"c++{cppstd}\"\n\n\ndef to_cstd_flag(conanfile, cstd):\n    \"\"\"Gets a valid cstd flag.\n    \"\"\"\n    if cstd is None:\n        return None\n    if disable_flag(conanfile, \"cppstd\"):\n        return None\n    return cstd if cstd.startswith(\"gnu\") else f\"c{cstd}\"\n"
  },
  {
    "path": "conan/tools/meson/meson.py",
    "content": "import os\n\nfrom conan.tools.build import build_jobs\nfrom conan.tools.meson.toolchain import MesonToolchain\n\n\nclass Meson:\n    \"\"\"\n    This class calls Meson commands when a package is being built. Notice that\n    this one should be used together with the ``MesonToolchain`` generator.\n    \"\"\"\n\n    def __init__(self, conanfile):\n        \"\"\"\n        :param conanfile: ``< ConanFile object >`` The current recipe object. Always use ``self``.\n        \"\"\"\n        self._conanfile = conanfile\n\n    def configure(self, reconfigure=False):\n        \"\"\"\n        Runs ``meson setup [FILE] \"BUILD_FOLDER\" \"SOURCE_FOLDER\" [-Dprefix=/]``\n        command, where ``FILE`` could be ``--native-file conan_meson_native.ini``\n        (if native builds) or ``--cross-file conan_meson_cross.ini`` (if cross builds).\n\n        :param reconfigure: ``bool`` value that adds ``--reconfigure`` param to the final command.\n        \"\"\"\n        if reconfigure:\n            self._conanfile.output.warning(\"reconfigure param has been deprecated.\"\n                                           \" Removing in Conan 2.x.\", warn_tag=\"deprecated\")\n        source_folder = self._conanfile.source_folder\n        build_folder = self._conanfile.build_folder\n        generators_folder = self._conanfile.generators_folder\n        cross = os.path.join(generators_folder, MesonToolchain.cross_filename)\n        native = os.path.join(generators_folder, MesonToolchain.native_filename)\n        is_cross_build = os.path.exists(cross)\n        machine_files = self._conanfile.conf.get(\"tools.meson.mesontoolchain:extra_machine_files\",\n                                                 default=[], check_type=list)\n        cmd = \"meson setup \"\n        if is_cross_build:\n            machine_files.insert(0, cross)\n            cmd += \" \".join([f'--cross-file \"{file}\"' for file in machine_files])\n        if os.path.exists(native):\n            if not is_cross_build:  # machine files are only appended to the cross or the native one\n                machine_files.insert(0, native)\n                cmd += \" \".join([f'--native-file \"{file}\"' for file in machine_files])\n            else:  # extra native file for cross-building scenarios\n                cmd += f' --native-file \"{native}\"'\n        cmd += ' \"{}\" \"{}\"'.format(build_folder, source_folder)\n        cmd += f\" --prefix={self._prefix}\"\n        self._conanfile.output.info(\"Meson configure cmd: {}\".format(cmd))\n        self._conanfile.run(cmd)\n\n    def build(self, target=None):\n        \"\"\"\n        Runs ``meson compile -C . -j[N_JOBS] [TARGET]`` in the build folder.\n        You can specify ``N_JOBS`` through the configuration line ``tools.build:jobs=N_JOBS``\n        in your profile ``[conf]`` section.\n\n        :param target: ``str`` Specifies the target to be executed.\n        \"\"\"\n        meson_build_folder = self._conanfile.build_folder\n        cmd = 'meson compile -C \"{}\"'.format(meson_build_folder)\n        njobs = build_jobs(self._conanfile)\n        if njobs:\n            cmd += \" -j{}\".format(njobs)\n        if target:\n            cmd += \" {}\".format(target)\n        verbosity = self._build_verbosity\n        if verbosity:\n            cmd += \" \" + verbosity\n        self._conanfile.output.info(\"Meson build cmd: {}\".format(cmd))\n        self._conanfile.run(cmd)\n\n    def install(self, cli_args=None):\n        \"\"\"\n        Runs ``meson install -C \".\" --destdir ..`` in the build folder.\n\n        :param cli_args: List of arguments to be added to the command:\n                    ``meson install -C \".\" --destdir ... arg1 arg2``\n        \"\"\"\n        meson_build_folder = self._conanfile.build_folder.replace(\"\\\\\", \"/\")\n        meson_package_folder = self._conanfile.package_folder.replace(\"\\\\\", \"/\")\n        # Assuming meson >= 0.57.0\n        cmd = f'meson install -C \"{meson_build_folder}\" --destdir \"{meson_package_folder}\"'\n        verbosity = self._install_verbosity\n        if verbosity:\n            cmd += \" \" + verbosity\n        if self._conanfile.conf.get(\"tools.build:install_strip\", check_type=bool):\n            cmd += \" --strip\"\n        if cli_args:\n            cmd += \" \" + \" \".join(cli_args)\n        self._conanfile.run(cmd)\n\n    def test(self):\n        \"\"\"\n        Runs ``meson test -v -C \".\"`` in the build folder.\n        \"\"\"\n        if self._conanfile.conf.get(\"tools.build:skip_test\", check_type=bool):\n            return\n        meson_build_folder = self._conanfile.build_folder\n        cmd = 'meson test -v -C \"{}\"'.format(meson_build_folder)\n        # TODO: Do we need vcvars for test?\n        # TODO: This should use conanrunenv, but what if meson itself is a build-require?\n        self._conanfile.run(cmd)\n\n    @property\n    def _build_verbosity(self):\n        # verbosity of build tools. This passes -v to ninja, for example.\n        # See https://github.com/mesonbuild/meson/blob/master/mesonbuild/mcompile.py#L156\n        verbosity = self._conanfile.conf.get(\"tools.compilation:verbosity\",\n                                             choices=(\"quiet\", \"verbose\"))\n        return \"--verbose\" if verbosity == \"verbose\" else \"\"\n\n    @property\n    def _install_verbosity(self):\n        # https://github.com/mesonbuild/meson/blob/master/mesonbuild/minstall.py#L81\n        # Errors are always logged, and status about installed files is controlled by this flag,\n        # so it's a bit backwards\n        verbosity = self._conanfile.conf.get(\"tools.build:verbosity\", choices=(\"quiet\", \"verbose\"))\n        return \"--quiet\" if verbosity else \"\"\n\n    @property\n    def _prefix(self):\n        \"\"\"Generate a valid ``--prefix`` argument value for meson.\n        For conan, the prefix must be similar to the Unix root directory ``/``.\n\n        The result of this function should be passed to\n        ``meson setup --prefix={self._prefix} ...``\n\n        Python 3.13 changed the semantics of ``/`` on the Windows ntpath module,\n        it is now special-cased as a relative directory.\n        Thus, ``os.path.isabs(\"/\")`` is true on Linux but false on Windows.\n        So for Windows, an equivalent path is ``C:\\\\``. However, this can be\n        parsed wrongly in meson in specific circumstances due to the trailing\n        backslash. Hence, we also use forward slashes for Windows, leaving us\n        with ``C:/`` or similar paths.\n\n        See also\n        --------\n        * The meson issue discussing the need to set ``--prefix`` to ``/``:\n            `mesonbuild/meson#12880 <https://github.com/mesonbuild/meson/issues/12880>`_\n        * The cpython PR introducing the ``/`` behavior change:\n            `python/cpython#113829 <https://github.com/python/cpython/pull/113829>`_\n        * The issue detailing the erroneous parsing of ``\\\\``:\n            `conan-io/conan#14213 <https://github.com/conan-io/conan/issues/14213>`_\n        \"\"\"\n        return os.path.abspath(\"/\").replace(\"\\\\\", \"/\")\n"
  },
  {
    "path": "conan/tools/meson/toolchain.py",
    "content": "import os\nimport textwrap\n\nfrom jinja2 import Template, StrictUndefined\n\nfrom conan.errors import ConanException\nfrom conan.internal import check_duplicated_generator\nfrom conan.internal.internal_tools import raise_on_universal_arch\nfrom conan.tools.apple.apple import is_apple_os, apple_min_version_flag, \\\n    resolve_apple_flags, apple_extra_flags\nfrom conan.tools.build.cross_building import cross_building, can_run\nfrom conan.tools.build.flags import (architecture_link_flag, libcxx_flags, architecture_flag,\n                                     threads_flags)\nfrom conan.tools.env import VirtualBuildEnv\nfrom conan.tools.meson.helpers import get_apple_subsystem, to_cppstd_flag, to_cstd_flag, \\\n    to_meson_machine, to_meson_value\nfrom conan.tools.microsoft import VCVars, msvc_runtime_flag\nfrom conan.internal.util.files import save\n\n\nclass MesonToolchain:\n    \"\"\"\n    MesonToolchain generator\n    \"\"\"\n    native_filename = \"conan_meson_native.ini\"\n    cross_filename = \"conan_meson_cross.ini\"\n\n    _meson_file_template = textwrap.dedent(\"\"\"\\\n    [properties]\n    {% for it, value in properties.items() -%}\n    {{it}} = {{value}}\n    {% endfor %}\n\n    [constants]\n    preprocessor_definitions = [{% for it, value in preprocessor_definitions.items() -%}\n    '-D{{ it }}=\"{{ value}}\"'{%- if not loop.last %}, {% endif %}{% endfor %}]\n\n    [project options]\n    {% for it, value in project_options.items() -%}\n    {{it}} = {{value}}\n    {% endfor %}\n\n    {% for subproject, listkeypair in subproject_options -%}\n    [{{subproject}}:project options]\n    {% for keypair in listkeypair -%}\n    {% for it, value in keypair.items() -%}\n    {{it}} = {{value}}\n    {% endfor %}\n    {% endfor %}\n    {% endfor %}\n\n    [binaries]\n    {% if c %}\n    c = {{c}}\n    {% endif %}\n    {% if cpp %}\n    cpp = {{cpp}}\n    {% endif %}\n    {% if ld %}\n    ld = {{ld}}\n    {% endif %}\n    {% if is_apple_system %}\n    {% if objc %}\n    objc = '{{objc}}'\n    {% endif %}\n    {% if objcpp %}\n    objcpp = '{{objcpp}}'\n    {% endif %}\n    {% endif %}\n    {% if c_ld %}\n    c_ld = '{{c_ld}}'\n    {% endif %}\n    {% if cpp_ld %}\n    cpp_ld = '{{cpp_ld}}'\n    {% endif %}\n    {% if ar %}\n    ar = '{{ar}}'\n    {% endif %}\n    {% if strip %}\n    strip = '{{strip}}'\n    {% endif %}\n    {% if as %}\n    as = '{{as}}'\n    {% endif %}\n    {% if windres %}\n    windres = '{{windres}}'\n    {% endif %}\n    {% if pkgconfig %}\n    pkgconfig = '{{pkgconfig}}'\n    {% endif %}\n    {% if pkgconfig %}\n    pkg-config = '{{pkgconfig}}'\n    {% endif %}\n\n    [built-in options]\n    {% if buildtype %}\n    buildtype = '{{buildtype}}'\n    {% endif %}\n    {% if default_library %}\n    default_library = '{{default_library}}'\n    {% endif %}\n    {% if b_vscrt %}\n    b_vscrt = '{{b_vscrt}}'\n    {% endif %}\n    {% if b_ndebug %}\n    b_ndebug = {{b_ndebug}}\n    {% endif %}\n    {% if b_staticpic %}\n    b_staticpic = {{b_staticpic}}\n    {% endif %}\n    {% if cpp_std %}\n    cpp_std = '{{cpp_std}}'\n    {% endif %}\n    {% if c_std %}\n    c_std = '{{c_std}}'\n    {% endif %}\n    {% if backend %}\n    backend = '{{backend}}'\n    {% endif %}\n    {% if pkg_config_path %}\n    pkg_config_path = '{{pkg_config_path}}'\n    {% endif %}\n    {% if build_pkg_config_path %}\n    build.pkg_config_path = '{{build_pkg_config_path}}'\n    {% endif %}\n    # C/C++ arguments\n    c_args = {{c_args}} + preprocessor_definitions\n    c_link_args = {{c_link_args}}\n    cpp_args = {{cpp_args}} + preprocessor_definitions\n    cpp_link_args = {{cpp_link_args}}\n    {% if is_apple_system %}\n    # Objective-C/C++ arguments\n    objc_args = {{objc_args}} + preprocessor_definitions\n    objc_link_args = {{objc_link_args}}\n    objcpp_args = {{objcpp_args}} + preprocessor_definitions\n    objcpp_link_args = {{objcpp_link_args}}\n    {% endif %}\n\n    {% for context, values in cross_build.items() %}\n    [{{context}}_machine]\n    system = '{{values[\"system\"]}}'\n    {% if values.get(\"subsystem\") %}\n    subsystem = '{{values[\"subsystem\"]}}'\n    {% endif %}\n    cpu_family = '{{values[\"cpu_family\"]}}'\n    cpu = '{{values[\"cpu\"]}}'\n    endian = '{{values[\"endian\"]}}'\n    {% endfor %}\n    \"\"\")\n\n    def __init__(self, conanfile, backend=None, native=False):\n        \"\"\"\n        :param conanfile: ``< ConanFile object >`` The current recipe object. Always use ``self``.\n        :param backend: (**DEPRECATED**, use ``self.backend`` instead) ``str`` ``backend`` Meson variable\n                        value. By default, ``ninja``.\n        :param native: ``bool`` Indicates whether you want Conan to create the\n                       ``conan_meson_native.ini`` in a cross-building context. Notice that it only\n                       makes sense if your project's ``meson.build`` uses the ``native=true``\n                       (see also https://mesonbuild.com/Cross-compilation.html#mixing-host-and-build-targets).\n        \"\"\"\n        raise_on_universal_arch(conanfile)\n        self._conanfile = conanfile\n        self._native = native\n        self._is_apple_system = is_apple_os(self._conanfile)\n        is_cross_building = cross_building(conanfile)  # x86_64->x86 is considered cross-building\n        if not is_cross_building and native:\n            raise ConanException(\"You can only pass native=True if you're cross-building, \"\n                                 \"otherwise, it could cause unexpected results.\")\n        self._conanfile_conf = self._conanfile.conf_build if native else self._conanfile.conf\n        # Values are kept as Python built-ins so users can modify them more easily, and they are\n        # only converted to Meson file syntax for rendering\n        # priority: first user conf, then recipe, last one is default \"ninja\"\n        #: Backend to use. Defined by the conf ``tools.meson.mesontoolchain:backend``. By default, ``ninja``.\n        self.backend = backend or 'ninja'\n        build_type = self._conanfile.settings.get_safe(\"build_type\")\n        #: Build type to use.\n        self.buildtype = {\"Debug\": \"debug\",  # Note, it is not \"'debug'\"\n                          \"Release\": \"release\",\n                          \"MinSizeRel\": \"minsize\",\n                          \"RelWithDebInfo\": \"debugoptimized\"}.get(build_type, build_type)\n        #: Disable asserts.\n        self.b_ndebug = \"true\" if self.buildtype != \"debug\" else \"false\"\n\n        # https://mesonbuild.com/Builtin-options.html#base-options\n        fpic = self._conanfile.options.get_safe(\"fPIC\")\n        shared = self._conanfile.options.get_safe(\"shared\")\n        #: Build static libraries as position independent. By default, ``self.options.get_safe(\"fPIC\")``\n        self.b_staticpic = fpic if (shared is False and fpic is not None) else None\n        # https://mesonbuild.com/Builtin-options.html#core-options\n        # Do not adjust \"debug\" if already adjusted \"buildtype\"\n        #: Default library type, e.g., \"shared.\n        self.default_library = (\"shared\" if shared else \"static\") if shared is not None else None\n\n        compiler = self._conanfile.settings.get_safe(\"compiler\")\n        if compiler is None:\n            raise ConanException(\"MesonToolchain needs 'settings.compiler', but it is not defined\")\n        compiler_version = self._conanfile.settings.get_safe(\"compiler.version\")\n        if compiler_version is None:\n            raise ConanException(\"MesonToolchain needs 'settings.compiler.version', but it is not defined\")\n\n        cppstd = self._conanfile.settings.get_safe(\"compiler.cppstd\")\n        cstd = self._conanfile.settings.get_safe(\"compiler.cstd\")\n        #: C++ language standard to use. Defined by ``to_cppstd_flag()`` by default.\n        self.cpp_std = to_cppstd_flag(self._conanfile, compiler, compiler_version, cppstd)\n        #: C language standard to use. Defined by ``to_cstd_flag()`` by default.\n        self.c_std = to_cstd_flag(self._conanfile, cstd)\n        #: VS runtime library to use. Defined by ``msvc_runtime_flag()`` by default.\n        self.b_vscrt = None\n        if compiler in (\"msvc\", \"clang\"):\n            vscrt = msvc_runtime_flag(self._conanfile)\n            if vscrt:\n                self.b_vscrt = str(vscrt).lower()\n\n        # Extra flags\n        #: List of extra ``CXX`` flags. Added to ``cpp_args``\n        self.extra_cxxflags = []\n        #: List of extra ``C`` flags. Added to ``c_args``\n        self.extra_cflags = []\n        #: List of extra linker flags. Added to ``c_link_args`` and ``cpp_link_args``\n        self.extra_ldflags = []\n        #: List of extra preprocessor definitions. Added to ``c_args`` and ``cpp_args`` with the\n        #: format ``-D[FLAG_N]``.\n        self.extra_defines = []\n        #: Architecture flag deduced by Conan and added to ``c_args``, ``cpp_args``, ``c_link_args`` and ``cpp_link_args``\n        self.arch_flag = architecture_flag(self._conanfile)  # https://github.com/conan-io/conan/issues/17624\n        #: Architecture link flag deduced by Conan and added to ``c_link_args`` and ``cpp_link_args``\n        self.arch_link_flag = architecture_link_flag(self._conanfile)\n        #: Threads flags deduced by Conan and added to ``c_args``, ``cpp_args``, ``c_link_args`` and ``cpp_link_args``\n        self.threads_flags = threads_flags(self._conanfile)\n        #: Dict-like object that defines Meson ``properties`` with ``key=value`` format\n        self.properties = {}\n        #: Dict-like object that defines Meson ``project options`` with ``key=value`` format\n        self.project_options = {\n            \"wrap_mode\": \"nofallback\"  # https://github.com/conan-io/conan/issues/10671\n        }\n        #: Dict-like object that defines Meson ``preprocessor definitions``\n        self.preprocessor_definitions = {}\n        # Add all the default dirs\n        self.project_options.update(self._get_default_dirs())\n        #: Dict-like object that defines Meson ``subproject options``.\n        self.subproject_options = {}\n        #: Defines the Meson ``pkg_config_path`` variable\n        self.pkg_config_path = self._conanfile.generators_folder\n        #: Defines the Meson ``build.pkg_config_path`` variable (build context)\n        # Issue: https://github.com/conan-io/conan/issues/12342\n        # Issue: https://github.com/conan-io/conan/issues/14935\n        self.build_pkg_config_path = None\n        self.libcxx, self.gcc_cxx11_abi = libcxx_flags(self._conanfile)\n        #: Dict-like object with the build, host, and target as the Meson machine context\n        self.cross_build = {}\n        default_comp = \"\"\n        default_comp_cpp = \"\"\n        if native is False and is_cross_building:\n            os_host = conanfile.settings.get_safe(\"os\")\n            arch_host = conanfile.settings.get_safe(\"arch\")\n            os_build = conanfile.settings_build.get_safe('os')\n            arch_build = conanfile.settings_build.get_safe('arch')\n            self.cross_build[\"build\"] = to_meson_machine(os_build, arch_build)\n            self.cross_build[\"host\"] = to_meson_machine(os_host, arch_host)\n            # Check subsystem if it's Apple cross-building only. It requires Meson >= 1.2.0,\n            # but it does not break lower versions.\n            # See https://mesonbuild.com/Reference-tables.html#subsystem-names-since-120\n            # Issue: https://github.com/conan-io/conan/issues/17873\n            if self._is_apple_system and is_apple_os(conanfile, build_context=True):\n                sdk_build = conanfile.settings_build.get_safe(\"os.sdk\")\n                sdk_host = conanfile.settings.get_safe(\"os.sdk\")\n                self.cross_build[\"host\"][\"subsystem\"] = get_apple_subsystem(sdk_host)\n                self.cross_build[\"build\"][\"subsystem\"] = get_apple_subsystem(sdk_build)\n            # Issue: https://github.com/conan-io/conan/issues/19217\n            self.properties[\"needs_exe_wrapper\"] = not can_run(self._conanfile)\n            if hasattr(conanfile, 'settings_target') and conanfile.settings_target:\n                settings_target = conanfile.settings_target\n                os_target = settings_target.get_safe(\"os\")\n                arch_target = settings_target.get_safe(\"arch\")\n                self.cross_build[\"target\"] = to_meson_machine(os_target, arch_target)\n            if is_apple_os(self._conanfile):  # default cross-compiler in Apple is common\n                default_comp = \"clang\"\n                default_comp_cpp = \"clang++\"\n        else:\n            if \"clang\" in compiler:\n                default_comp = \"clang\"\n                default_comp_cpp = \"clang++\"\n            elif compiler == \"gcc\":\n                default_comp = \"gcc\"\n                default_comp_cpp = \"g++\"\n\n        if \"Visual\" in compiler or compiler == \"msvc\":\n            default_comp = \"cl\"\n            default_comp_cpp = \"cl\"\n\n        # Read configuration for sys_root property (honoring existing conf)\n        self._sys_root = self._conanfile_conf.get(\"tools.build:sysroot\", check_type=str)\n\n        # Read configuration for compilers\n        compilers_by_conf = self._conanfile_conf.get(\"tools.build:compiler_executables\", default={},\n                                                     check_type=dict)\n        # Read the VirtualBuildEnv to update the variables\n        build_env = self._conanfile.buildenv_build.vars(self._conanfile) if native else (\n            VirtualBuildEnv(self._conanfile, auto_generate=True).vars())\n        #: Sets the Meson ``c`` variable, defaulting to the ``CC`` build environment value.\n        #: If provided as a blank-separated string, it will be transformed into a list.\n        #: Otherwise, it remains a single string.\n        self.c = compilers_by_conf.get(\"c\") or self._sanitize_env_format(build_env.get(\"CC\")) or default_comp\n        #: Sets the Meson ``cpp`` variable, defaulting to the ``CXX`` build environment value.\n        #: If provided as a blank-separated string, it will be transformed into a list.\n        #: Otherwise, it remains a single string.\n        self.cpp = compilers_by_conf.get(\"cpp\") or self._sanitize_env_format(build_env.get(\"CXX\")) or default_comp_cpp\n        #: Sets the Meson ``ld`` variable, defaulting to the ``LD`` build environment value.\n        #: If provided as a blank-separated string, it will be transformed into a list.\n        #: Otherwise, it remains a single string.\n        self.ld = self._sanitize_env_format(build_env.get(\"LD\"))\n        # FIXME: Should we use the new tools.build:compiler_executables and avoid buildenv?\n        # Issue related: https://github.com/mesonbuild/meson/issues/6442\n        # PR related: https://github.com/mesonbuild/meson/pull/6457\n        #: Defines the Meson ``c_ld`` variable. Defaulted to ``CC_LD``\n        #: environment value\n        self.c_ld = build_env.get(\"CC_LD\")\n        #: Defines the Meson ``cpp_ld`` variable. Defaulted to ``CXX_LD``\n        #: environment value\n        self.cpp_ld = build_env.get(\"CXX_LD\")\n        #: Defines the Meson ``ar`` variable. Defaulted to ``AR`` build environment value\n        self.ar = build_env.get(\"AR\")\n        #: Defines the Meson ``strip`` variable. Defaulted to ``STRIP`` build environment value\n        self.strip = build_env.get(\"STRIP\")\n        #: Defines the Meson ``as`` variable. Defaulted to ``AS`` build environment value\n        self.as_ = build_env.get(\"AS\")\n        #: Defines the Meson ``windres`` variable. Defaulted to ``WINDRES`` build environment value\n        self.windres = build_env.get(\"WINDRES\")\n        #: Defines the Meson ``pkgconfig`` variable. Defaulted to ``PKG_CONFIG``\n        #: build environment value\n        self.pkgconfig = (self._conanfile_conf.get(\"tools.gnu:pkg_config\", check_type=str) or\n                          build_env.get(\"PKG_CONFIG\"))\n        #: Defines the Meson ``c_args`` variable. Defaulted to ``CFLAGS`` build environment value\n        self.c_args = self._get_env_list(build_env.get(\"CFLAGS\", []))\n        #: Defines the Meson ``c_link_args`` variable. Defaulted to ``LDFLAGS`` build\n        #: environment value\n        self.c_link_args = self._get_env_list(build_env.get(\"LDFLAGS\", []))\n        #: Defines the Meson ``cpp_args`` variable. Defaulted to ``CXXFLAGS`` build environment value\n        self.cpp_args = self._get_env_list(build_env.get(\"CXXFLAGS\", []))\n        #: Defines the Meson ``cpp_link_args`` variable. Defaulted to ``LDFLAGS`` build\n        #: environment value\n        self.cpp_link_args = self._get_env_list(build_env.get(\"LDFLAGS\", []))\n\n        # Apple flags and variables\n        #: Apple arch flag as a list, e.g., ``[\"-arch\", \"i386\"]``\n        self.apple_arch_flag = []\n        #: Apple sysroot flag as a list, e.g., ``[\"-isysroot\", \"./Platforms/MacOSX.platform\"]``\n        self.apple_isysroot_flag = []\n        #: Apple minimum binary version flag as a list, e.g., ``[\"-mios-version-min\", \"10.8\"]``\n        self.apple_min_version_flag = []\n        #: Apple bitcode, visibility and arc flags\n        self.apple_extra_flags = apple_extra_flags(self._conanfile)\n        #: Defines the Meson ``objc`` variable. Defaulted to ``None``, if if any Apple OS ``clang``\n        self.objc = None\n        #: Defines the Meson ``objcpp`` variable. Defaulted to ``None``, if if any Apple OS ``clang++``\n        self.objcpp = None\n        #: Defines the Meson ``objc_args`` variable. Defaulted to ``OBJCFLAGS`` build environment value\n        self.objc_args = []\n        #: Defines the Meson ``objc_link_args`` variable. Defaulted to ``LDFLAGS`` build environment value\n        self.objc_link_args = []\n        #: Defines the Meson ``objcpp_args`` variable. Defaulted to ``OBJCXXFLAGS`` build environment value\n        self.objcpp_args = []\n        #: Defines the Meson ``objcpp_link_args`` variable. Defaulted to ``LDFLAGS`` build environment value\n        self.objcpp_link_args = []\n\n        self._resolve_apple_flags_and_variables(build_env, compilers_by_conf)\n        if native is False:\n            self._resolve_android_cross_compilation()\n\n    def _get_default_dirs(self):\n        \"\"\"\n        Get all the default directories from cpp.package.\n\n        Issues related:\n            - https://github.com/conan-io/conan/issues/9713\n            - https://github.com/conan-io/conan/issues/11596\n        \"\"\"\n        def _get_cpp_info_value(name):\n            elements = getattr(self._conanfile.cpp.package, name)\n            return elements[0] if elements else None\n\n        ret = {}\n        bindir = _get_cpp_info_value(\"bindirs\")\n        datadir = _get_cpp_info_value(\"resdirs\")\n        libdir = _get_cpp_info_value(\"libdirs\")\n        includedir = _get_cpp_info_value(\"includedirs\")\n        if bindir:\n            ret.update({\n                'bindir': bindir,\n                'sbindir': bindir,\n                'libexecdir': bindir\n            })\n        if datadir:\n            ret.update({\n                'datadir': datadir,\n                'localedir': datadir,\n                'mandir': datadir,\n                'infodir': datadir\n            })\n        if includedir:\n            ret[\"includedir\"] = includedir\n        if libdir:\n            ret[\"libdir\"] = libdir\n        return ret\n\n    def _resolve_apple_flags_and_variables(self, build_env, compilers_by_conf):\n        if not self._is_apple_system:\n            return\n        # Calculating the main Apple flags\n        min_flag, arch_flag, isysroot_flag = (\n            resolve_apple_flags(self._conanfile, is_cross_building=self.cross_build))\n        self.apple_arch_flag = arch_flag.split() if arch_flag else []\n        self.apple_isysroot_flag = isysroot_flag.split() if isysroot_flag else []\n        self.apple_min_version_flag = [apple_min_version_flag(self._conanfile)]\n        # Objective C/C++ ones\n        self.objc = compilers_by_conf.get(\"objc\", \"clang\")\n        self.objcpp = compilers_by_conf.get(\"objcpp\", \"clang++\")\n        enable_arc = self._conanfile.conf.get(\"tools.apple:enable_arc\", check_type=bool)\n        fobj_arc = \"\"\n        if enable_arc:\n            fobj_arc = \"-fobjc-arc\"\n        if enable_arc is False:\n            fobj_arc = \"-fno-objc-arc\"\n        self.objc_args = self._get_env_list(build_env.get('OBJCFLAGS', [])) + [fobj_arc]\n        self.objc_link_args = self._get_env_list(build_env.get('LDFLAGS', []))\n        self.objcpp_args = self._get_env_list(build_env.get('OBJCXXFLAGS', [])) + [fobj_arc]\n        self.objcpp_link_args = self._get_env_list(build_env.get('LDFLAGS', []))\n\n    def _resolve_android_cross_compilation(self):\n        if not self.cross_build or not self.cross_build[\"host\"][\"system\"] == \"android\":\n            return\n\n        ndk_path = self._conanfile_conf.get(\"tools.android:ndk_path\")\n        if not ndk_path:\n            raise ConanException(\"You must provide a NDK path. Use 'tools.android:ndk_path' \"\n                                 \"configuration field.\")\n\n        arch = self._conanfile.settings.get_safe(\"arch\")\n        os_build = self.cross_build[\"build\"][\"system\"]\n        ndk_bin = os.path.join(ndk_path, \"toolchains\",\n                               \"llvm\", \"prebuilt\", \"{}-x86_64\".format(os_build), \"bin\")\n        android_api_level = self._conanfile.settings.get_safe(\"os.api_level\")\n        android_target = {'armv7': 'armv7a-linux-androideabi',\n                          'armv8': 'aarch64-linux-android',\n                          'x86': 'i686-linux-android',\n                          'x86_64': 'x86_64-linux-android'}.get(arch)\n        os_build = self._conanfile.settings_build.get_safe('os')\n        compile_ext = \".cmd\" if os_build == \"Windows\" else \"\"\n        # User has more prio than Conan\n        self.c = os.path.join(ndk_bin, f\"{android_target}{android_api_level}-clang{compile_ext}\")\n        self.cpp = os.path.join(ndk_bin, f\"{android_target}{android_api_level}-clang++{compile_ext}\")\n        self.ar = os.path.join(ndk_bin, \"llvm-ar\")\n    \n    @property\n    def _rpath_link_flag(self):\n        add_rpath_link = self._conanfile.conf.get(\"tools.build:add_rpath_link\", check_type=bool)\n        if not add_rpath_link:\n            return []\n        runtime_dirs = []\n        host_req = self._conanfile.dependencies.filter({\"build\": False}).values()\n        for req in host_req:\n            cppinfo = req.cpp_info.aggregated_components()\n            runtime_dirs.extend(cppinfo.libdirs)\n        return [\"-Wl,-rpath-link=\" + \":\".join(runtime_dirs)] if runtime_dirs else []\n    \n    def _get_extra_flags(self):\n        # Now, it's time to get all the flags defined by the user\n        cxxflags = self._conanfile_conf.get(\"tools.build:cxxflags\", default=[], check_type=list)\n        cflags = self._conanfile_conf.get(\"tools.build:cflags\", default=[], check_type=list)\n        sharedlinkflags = self._conanfile_conf.get(\"tools.build:sharedlinkflags\", default=[],\n                                                   check_type=list)\n        exelinkflags = self._conanfile_conf.get(\"tools.build:exelinkflags\", default=[],\n                                                check_type=list)\n        linker_scripts = self._conanfile_conf.get(\"tools.build:linker_scripts\", default=[],\n                                                  check_type=list)\n        linker_script_flags = ['-T' + linker_script for linker_script in linker_scripts]\n        defines = self._conanfile_conf.get(\"tools.build:defines\", default=[], check_type=list)\n        sys_root = [f\"--sysroot={self._sys_root}\"] if self._sys_root else [\"\"]\n        ld = (sharedlinkflags + exelinkflags + linker_script_flags + sys_root + self.extra_ldflags\n              + self.threads_flags)\n        # Apple extra flags from confs (visibilty, bitcode, arc)\n        cxxflags += self.apple_extra_flags\n        cflags += self.apple_extra_flags\n        ld += self.apple_extra_flags\n        return {\n            \"cxxflags\": [self.arch_flag] + cxxflags + sys_root + self.extra_cxxflags\n                        + self.threads_flags,\n            \"cflags\": [self.arch_flag] + cflags + sys_root + self.extra_cflags + self.threads_flags,\n            \"ldflags\": [self.arch_flag] + [self.arch_link_flag] + ld + self._rpath_link_flag,\n            \"defines\": [f\"-D{d}\" for d in (defines + self.extra_defines)]\n        }\n\n    @staticmethod\n    def _get_env_list(v):\n        # FIXME: Should Environment have the \"check_type=None\" keyword as Conf?\n        return v.strip().split() if not isinstance(v, list) else v\n\n    @staticmethod\n    def _filter_list_empty_fields(v):\n        return list(filter(bool, v))\n\n    @staticmethod\n    def _sanitize_env_format(value):\n        if value is None or isinstance(value, list):\n            return value\n        if not isinstance(value, str):\n            raise ConanException(f\"MesonToolchain: Value '{value}' should be a string\")\n        ret = [x.strip() for x in value.split() if x]\n        return ret[0] if len(ret) == 1 else ret\n\n    @property\n    def _context(self):\n        apple_flags = self.apple_isysroot_flag + self.apple_arch_flag + self.apple_min_version_flag\n        extra_flags = self._get_extra_flags()\n\n        self.c_args.extend(apple_flags + extra_flags[\"cflags\"] + extra_flags[\"defines\"])\n        self.cpp_args.extend(apple_flags + extra_flags[\"cxxflags\"] + extra_flags[\"defines\"])\n        self.c_link_args.extend(apple_flags + extra_flags[\"ldflags\"])\n        self.cpp_link_args.extend(apple_flags + extra_flags[\"ldflags\"])\n        # Objective C/C++\n        self.objc_args.extend(self.c_args)\n        self.objcpp_args.extend(self.cpp_args)\n        # These link_args have already the LDFLAGS env value so let's add only the new possible ones\n        self.objc_link_args.extend(self.c_link_args)\n        self.objcpp_link_args.extend(self.cpp_link_args)\n\n        if self.preprocessor_definitions:\n            self._conanfile.output.warning(\n                \"Use 'extra_defines' attribute for compiler preprocessor definitions instead \" +\n                \"of 'preprocessor_definitions'\", warn_tag=\"deprecated\")\n\n        if self.libcxx:\n            self.cpp_args.append(self.libcxx)\n            self.cpp_link_args.append(self.libcxx)\n        if self.gcc_cxx11_abi:\n            self.cpp_args.append(\"-D{}\".format(self.gcc_cxx11_abi))\n\n        subproject_options = {}\n        for subproject, listkeypair in self.subproject_options.items():\n            if listkeypair:\n                if not isinstance(listkeypair, list):\n                    raise ConanException(\"MesonToolchain.subproject_options must be a list of dicts\")\n                subproject_options[subproject] = [{k: to_meson_value(v) for k, v in keypair.items()}\n                                                  for keypair in listkeypair]\n        return {\n            # https://mesonbuild.com/Machine-files.html#properties\n            \"properties\": {k: to_meson_value(v) for k, v in self.properties.items()},\n            # https://mesonbuild.com/Machine-files.html#project-specific-options\n            \"project_options\": {k: to_meson_value(v) for k, v in self.project_options.items()},\n            # https://mesonbuild.com/Subprojects.html#build-options-in-subproject\n            \"subproject_options\": subproject_options.items(),\n            # https://mesonbuild.com/Builtin-options.html#directories\n            # https://mesonbuild.com/Machine-files.html#binaries\n            # https://mesonbuild.com/Reference-tables.html#compiler-and-linker-selection-variables\n            \"c\": to_meson_value(self.c),\n            \"cpp\": to_meson_value(self.cpp),\n            \"ld\": to_meson_value(self.ld),\n            \"objc\": self.objc,\n            \"objcpp\": self.objcpp,\n            \"c_ld\": self.c_ld,\n            \"cpp_ld\": self.cpp_ld,\n            \"ar\": self.ar,\n            \"strip\": self.strip,\n            \"as\": self.as_,\n            \"windres\": self.windres,\n            \"pkgconfig\": self.pkgconfig,\n            # https://mesonbuild.com/Builtin-options.html#core-options\n            \"buildtype\": self.buildtype,\n            \"default_library\": self.default_library,\n            \"backend\": self._conanfile_conf.get(\"tools.meson.mesontoolchain:backend\",\n                                                default=self.backend),\n            # https://mesonbuild.com/Builtin-options.html#base-options\n            \"b_vscrt\": self.b_vscrt,\n            \"b_staticpic\": to_meson_value(self.b_staticpic),  # boolean\n            \"b_ndebug\": to_meson_value(self.b_ndebug),  # boolean as string\n            # https://mesonbuild.com/Builtin-options.html#compiler-options\n            \"cpp_std\": self.cpp_std,\n            \"c_std\": self.c_std,\n            \"c_args\": to_meson_value(self._filter_list_empty_fields(self.c_args)),\n            \"c_link_args\": to_meson_value(self._filter_list_empty_fields(self.c_link_args)),\n            \"cpp_args\": to_meson_value(self._filter_list_empty_fields(self.cpp_args)),\n            \"cpp_link_args\": to_meson_value(self._filter_list_empty_fields(self.cpp_link_args)),\n            \"objc_args\": to_meson_value(self._filter_list_empty_fields(self.objc_args)),\n            \"objc_link_args\": to_meson_value(self._filter_list_empty_fields(self.objc_link_args)),\n            \"objcpp_args\": to_meson_value(self._filter_list_empty_fields(self.objcpp_args)),\n            \"objcpp_link_args\": to_meson_value(self._filter_list_empty_fields(self.objcpp_link_args)),\n            \"pkg_config_path\": self.pkg_config_path,\n            \"build_pkg_config_path\": self.build_pkg_config_path,\n            #: Deprecated: Dict-like object that defines Meson ``preprocessor definitions``. Use the extra_defines attribute instead.\n            \"preprocessor_definitions\": self.preprocessor_definitions,\n            \"cross_build\": self.cross_build,\n            \"is_apple_system\": self._is_apple_system\n        }\n\n    @property\n    def _filename(self):\n        if self.cross_build and self._native:\n            return self.native_filename\n        elif self.cross_build:\n            return self.cross_filename\n        else:\n            return self.native_filename\n\n    @property\n    def _content(self):\n        \"\"\"\n        Gets content of the file to be used by Meson as its context.\n\n        :return: ``str`` whole Meson context content.\n        \"\"\"\n        context = self._context\n        content = Template(self._meson_file_template, trim_blocks=True, lstrip_blocks=True,\n                           undefined=StrictUndefined).render(context)\n        return content\n\n    def generate(self):\n        \"\"\"\n        Creates a ``conan_meson_native.ini`` (if native builds) or a\n        ``conan_meson_cross.ini`` (if cross builds) with the proper content.\n        If Windows OS, it will be created a ``conanvcvars.bat`` as well.\n        \"\"\"\n        check_duplicated_generator(self, self._conanfile)\n        self._conanfile.output.info(f\"MesonToolchain generated: {self._filename}\")\n        save(self._filename, self._content)\n        # FIXME: Should we check the OS and compiler to call VCVars?\n        VCVars(self._conanfile).generate()\n"
  },
  {
    "path": "conan/tools/microsoft/__init__.py",
    "content": "from conan.tools.microsoft.layout import vs_layout\nfrom conan.tools.microsoft.msbuild import MSBuild\nfrom conan.tools.microsoft.msbuilddeps import MSBuildDeps\nfrom conan.tools.microsoft.subsystems import unix_path, unix_path_package_info_legacy\nfrom conan.tools.microsoft.toolchain import MSBuildToolchain\nfrom conan.tools.microsoft.nmaketoolchain import NMakeToolchain\nfrom conan.tools.microsoft.nmakedeps import NMakeDeps\nfrom conan.tools.microsoft.visual import msvc_runtime_flag, VCVars, is_msvc, \\\n    is_msvc_static_runtime, check_min_vs, msvs_toolset\n"
  },
  {
    "path": "conan/tools/microsoft/layout.py",
    "content": "import os\n\nfrom conan.errors import ConanException\nfrom conan.tools.microsoft.visual import msvc_platform_from_arch\n\n\ndef vs_layout(conanfile):\n    \"\"\"\n    Initialize a layout for a typical Visual Studio project.\n\n    :param conanfile: ``< ConanFile object >`` The current recipe object. Always use ``self``.\n    \"\"\"\n    subproject = conanfile.folders.subproject\n    conanfile.folders.source = subproject or \".\"\n    conanfile.folders.generators = os.path.join(subproject, \"conan\") if subproject else \"conan\"\n    conanfile.folders.build = subproject or \".\"\n    conanfile.cpp.source.includedirs = [\"include\"]\n\n    try:\n        build_type = str(conanfile.settings.build_type)\n    except ConanException:\n        raise ConanException(\"The 'vs_layout' requires the 'build_type' setting\")\n    try:\n        arch = str(conanfile.settings.arch)\n    except ConanException:\n        raise ConanException(\"The 'vs_layout' requires the 'arch' setting\")\n\n    if arch != \"None\" and arch != \"x86\":\n        msvc_arch = msvc_platform_from_arch(arch)\n        if not msvc_arch:\n            raise ConanException(f\"The 'vs_layout' doesn't work with the arch '{arch}'. \"\n                                 \"Accepted architectures: 'x86', 'x86_64', 'armv7', 'armv8'\")\n        bindirs = os.path.join(msvc_arch, build_type)\n    else:\n        bindirs = build_type\n\n    conanfile.cpp.build.libdirs = [bindirs]\n    conanfile.cpp.build.bindirs = [bindirs]\n"
  },
  {
    "path": "conan/tools/microsoft/msbuild.py",
    "content": "from conan.errors import ConanException\nfrom conan.tools.microsoft.visual import msvc_platform_from_arch\n\n\ndef msbuild_verbosity_cmd_line_arg(conanfile):\n    \"\"\"\n    Controls msbuild verbosity.\n    See https://learn.microsoft.com/en-us/visualstudio/msbuild/msbuild-command-line-reference\n    :return:\n    \"\"\"\n    verbosity = conanfile.conf.get(\"tools.build:verbosity\", choices=(\"quiet\", \"verbose\"))\n    if verbosity is not None:\n        verbosity = {\n            \"quiet\": \"Quiet\",\n            \"verbose\": \"Detailed\",\n        }.get(verbosity)\n        return f'-verbosity:{verbosity}'\n    return \"\"\n\n\nclass MSBuild:\n    \"\"\"\n    MSBuild build helper class\n    \"\"\"\n\n    def __init__(self, conanfile):\n        \"\"\"\n        :param conanfile: ``< ConanFile object >`` The current recipe object. Always use ``self``.\n        \"\"\"\n        self._conanfile = conanfile\n        #: Defines the build type. By default, ``settings.build_type``.\n        self.build_type = conanfile.settings.get_safe(\"build_type\")\n        # if platforms:\n        #    msvc_arch.update(platforms)\n        arch = conanfile.settings.get_safe(\"arch\")\n        # MSVC default platform for VS projects is \"x86\", not \"Win32\" (but CMake default is \"Win32\")\n        msvc_platform = msvc_platform_from_arch(arch) if arch != \"x86\" else \"x86\"\n        if conanfile.settings.get_safe(\"os\") == \"WindowsCE\":\n            msvc_platform = conanfile.settings.get_safe(\"os.platform\")\n        #: Defines the platform name, e.g., ``ARM`` if ``settings.arch == \"armv7\"``.\n        self.platform = msvc_platform\n\n    def command(self, sln, targets=None):\n        \"\"\"\n        Gets the ``msbuild`` command line. For instance,\n        :command:`msbuild.exe \"MyProject.sln\" -p:Configuration=<conf> -p:Platform=<platform>`.\n\n        :param sln: ``str`` name of Visual Studio ``*.sln`` file\n        :param targets: ``targets`` is an optional argument, defaults to ``None``, and otherwise it is a list of targets to build\n        :return: ``str`` msbuild command line.\n        \"\"\"\n        # TODO: Enable output_binary_log via config\n        cmd = ('msbuild.exe \"%s\" -p:Configuration=\"%s\" -p:Platform=\"%s\"'\n               % (sln, self.build_type, self.platform))\n\n        verbosity = msbuild_verbosity_cmd_line_arg(self._conanfile)\n        if verbosity:\n            cmd += \" {}\".format(verbosity)\n\n        maxcpucount = self._conanfile.conf.get(\"tools.microsoft.msbuild:max_cpu_count\",\n                                               check_type=int)\n        if maxcpucount is not None:\n            cmd += f' -m:\"{maxcpucount}\"' if maxcpucount > 0 else \" -m\"\n\n        if targets:\n            if not isinstance(targets, list):\n                raise ConanException(\"targets argument should be a list\")\n            cmd += ' -target:\"{}\"'.format(\";\".join(targets))\n\n        return cmd\n\n    def build(self, sln, targets=None):\n        \"\"\"\n        Runs the ``msbuild`` command line obtained from ``self.command(sln)``.\n\n        :param sln: ``str`` name of Visual Studio ``*.sln`` file\n        :param targets: ``targets`` is an optional argument, defaults to ``None``, and otherwise it is a list of targets to build\n        \"\"\"\n        cmd = self.command(sln, targets=targets)\n        self._conanfile.run(cmd)\n\n    @staticmethod\n    def get_version(_):\n        return NotImplementedError(\"get_version() method is not supported in MSBuild \"\n                                   \"toolchain helper\")\n"
  },
  {
    "path": "conan/tools/microsoft/msbuilddeps.py",
    "content": "import fnmatch\nimport os\nimport re\nimport textwrap\nfrom xml.dom import minidom\n\nfrom jinja2 import Template\n\nfrom conan.internal import check_duplicated_generator\nfrom conan.errors import ConanException\nfrom conan.internal.api.install.generators import relativize_path\nfrom conan.internal.model.dependencies import get_transitive_requires\nfrom conan.tools.microsoft.visual import msvc_platform_from_arch\nfrom conan.internal.util.files import load, save\n\nVALID_LIB_EXTENSIONS = (\".so\", \".lib\", \".a\", \".dylib\", \".bc\")\n\n\nclass MSBuildDeps:\n    \"\"\"\n    MSBuildDeps class generator\n    conandeps.props: unconditional import of all *direct* dependencies only\n    \"\"\"\n\n    _vars_props = textwrap.dedent(\"\"\"\\\n        <?xml version=\"1.0\" encoding=\"utf-8\"?>\n        <Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n          <PropertyGroup Label=\"ConanVariables\">\n            <Conan{{name}}RootFolder>{{root_folder}}</Conan{{name}}RootFolder>\n            <Conan{{name}}BinaryDirectories>{{bin_dirs}}</Conan{{name}}BinaryDirectories>\n            {% if host_context %}\n            <Conan{{name}}CompilerFlags>{{compiler_flags}}</Conan{{name}}CompilerFlags>\n            <Conan{{name}}LinkerFlags>{{linker_flags}}</Conan{{name}}LinkerFlags>\n            <Conan{{name}}PreprocessorDefinitions>{{definitions}}</Conan{{name}}PreprocessorDefinitions>\n            <Conan{{name}}IncludeDirectories>{{include_dirs}}</Conan{{name}}IncludeDirectories>\n            <Conan{{name}}ResourceDirectories>{{res_dirs}}</Conan{{name}}ResourceDirectories>\n            <Conan{{name}}LibraryDirectories>{{lib_dirs}}</Conan{{name}}LibraryDirectories>\n            <Conan{{name}}Libraries>{{libs}}</Conan{{name}}Libraries>\n            <Conan{{name}}SystemLibs>{{system_libs}}</Conan{{name}}SystemLibs>\n            {% endif %}\n          </PropertyGroup>\n        </Project>\n        \"\"\")\n\n    _conf_props = textwrap.dedent(\"\"\"\\\n        <?xml version=\"1.0\" encoding=\"utf-8\"?>\n        <Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n          <ImportGroup Label=\"PropertySheets\">\n            {% for dep in deps %}\n            <Import Condition=\"'$(conan_{{dep}}_props_imported)' != 'True'\" Project=\"conan_{{dep}}.props\"/>\n            {% endfor %}\n          </ImportGroup>\n          <ImportGroup Label=\"PropertySheets\">\n            <Import Project=\"{{vars_filename}}\"/>\n          </ImportGroup>\n          {% if host_context %}\n          <PropertyGroup>\n            <ConanDebugPath>$(Conan{{name}}BinaryDirectories);$(ConanDebugPath)</ConanDebugPath>\n            <LocalDebuggerEnvironment>PATH=$(ConanDebugPath);%PATH%</LocalDebuggerEnvironment>\n            <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>\n            {% if ca_exclude %}\n            <CAExcludePath>$(Conan{{name}}IncludeDirectories);$(CAExcludePath)</CAExcludePath>\n            {% endif %}\n          </PropertyGroup>\n          <ItemDefinitionGroup>\n            <ClCompile>\n              <AdditionalIncludeDirectories>$(Conan{{name}}IncludeDirectories)%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n              <PreprocessorDefinitions>$(Conan{{name}}PreprocessorDefinitions)%(PreprocessorDefinitions)</PreprocessorDefinitions>\n              <AdditionalOptions>$(Conan{{name}}CompilerFlags) %(AdditionalOptions)</AdditionalOptions>\n            </ClCompile>\n            <Link>\n              <AdditionalLibraryDirectories>$(Conan{{name}}LibraryDirectories)%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\n              <AdditionalDependencies>$(Conan{{name}}Libraries)%(AdditionalDependencies)</AdditionalDependencies>\n              <AdditionalDependencies>$(Conan{{name}}SystemLibs)%(AdditionalDependencies)</AdditionalDependencies>\n              <AdditionalOptions>$(Conan{{name}}LinkerFlags) %(AdditionalOptions)</AdditionalOptions>\n            </Link>\n            <Midl>\n              <AdditionalIncludeDirectories>$(Conan{{name}}IncludeDirectories)%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n            </Midl>\n            <ResourceCompile>\n              <AdditionalIncludeDirectories>$(Conan{{name}}IncludeDirectories)%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n              <PreprocessorDefinitions>$(Conan{{name}}PreprocessorDefinitions)%(PreprocessorDefinitions)</PreprocessorDefinitions>\n            </ResourceCompile>\n          </ItemDefinitionGroup>\n          {% else %}\n          <PropertyGroup>\n            <ExecutablePath>$(Conan{{name}}BinaryDirectories)$(ExecutablePath)</ExecutablePath>\n          </PropertyGroup>\n          {% endif %}\n        </Project>\n        \"\"\")\n\n    def __init__(self, conanfile):\n        \"\"\"\n        :param conanfile: ``< ConanFile object >`` The current recipe object. Always use ``self``.\n        \"\"\"\n        self._conanfile = conanfile\n        #: Defines the build type. By default, the value of ``settings.build_type``.\n        self.configuration = conanfile.settings.build_type\n        #: Defines the configuration key used to conditionally select which property sheet to\n        #: import (defaults to ``\"Configuration\"``).\n        self.configuration_key = \"Configuration\"\n        # TODO: This platform is not exactly the same as ``msbuild_arch``, because it differs\n        # in x86=>Win32\n        #: Platform name, e.g., ``Win32`` if ``settings.arch == \"x86\"``.\n        self.platform = msvc_platform_from_arch(str(conanfile.settings.arch))\n        #: Defines the platform key used to conditionally select which property sheet to\n        #: import (defaults to ``\"Platform\"``).\n        self.platform_key = \"Platform\"\n        ca_exclude = \"tools.microsoft.msbuilddeps:exclude_code_analysis\"\n        #: List of packages names patterns to add Visual Studio ``CAExcludePath`` property\n        #: to each match as part of its ``conan_[DEP]_[CONFIG].props``. By default, value given by\n        #: ``tools.microsoft.msbuilddeps:exclude_code_analysis`` configuration.\n        self.exclude_code_analysis = self._conanfile.conf.get(ca_exclude, check_type=list)\n\n    def generate(self):\n        \"\"\"\n        Generates ``conan_<pkg>_<config>_vars.props``, ``conan_<pkg>_<config>.props``,\n        and ``conan_<pkg>.props`` files into the ``conanfile.generators_folder``.\n        \"\"\"\n        check_duplicated_generator(self, self._conanfile)\n        if self.configuration is None:\n            raise ConanException(\"MSBuildDeps.configuration is None, it should have a value\")\n        if self.platform is None:\n            raise ConanException(\"MSBuildDeps.platform is None, it should have a value\")\n        generator_files = self._content()\n        for generator_file, content in generator_files.items():\n            save(generator_file, content)\n\n    def _config_filename(self):\n        props = [self.configuration,\n                 self.platform]\n        name = \"\".join(\"_%s\" % v for v in props)\n        return name.lower()\n\n    def _condition(self):\n        props = [(self.configuration_key, self.configuration),\n                 (self.platform_key, self.platform)]\n        condition = \" And \".join(\"'$(%s)' == '%s'\" % (k, v) for k, v in props)\n        return condition\n\n    @staticmethod\n    def _dep_name(dep, build):\n        dep_name = dep.ref.name\n        if build:  # dep.context == CONTEXT_BUILD:\n            dep_name += \"_build\"\n        return MSBuildDeps._get_valid_xml_format(dep_name)\n\n    @staticmethod\n    def _get_valid_xml_format(name):\n        return re.compile(r\"[.+]\").sub(\"_\", name)\n\n    def _vars_props_file(self, require, dep, name, cpp_info, build):\n        \"\"\"\n        content for conan_vars_poco_x86_release.props, containing the variables for 1 config\n        This will be for 1 package or for one component of a package\n        :return: varfile content\n        \"\"\"\n\n        def add_valid_ext(libname, libdirs=None):\n            ext = os.path.splitext(libname)[1]\n            if ext in VALID_LIB_EXTENSIONS:\n                return f\"{libname};\"\n\n            lib_name = f\"{libname}.lib\"\n            if libdirs and not any(lib_name in os.listdir(d) for d in libdirs if os.path.isdir(d)):\n                meson_name = f\"lib{libname}.a\"\n                if any(meson_name in os.listdir(d) for d in libdirs if os.path.isdir(d)):\n                    lib_name = meson_name\n            return f\"{lib_name};\"\n\n        pkg_placeholder = \"$(Conan{}RootFolder)\".format(name)\n\n        def escape_path(path):\n            # https://docs.microsoft.com/en-us/visualstudio/msbuild/\n            #                          how-to-escape-special-characters-in-msbuild\n            # https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild-special-characters\n            return path.lstrip(\"/\")\n\n        def join_paths(paths):\n            # TODO: ALmost copied from CMakeDeps TargetDataContext\n            ret = []\n            for p in paths:\n                assert os.path.isabs(p), \"{} is not absolute\".format(p)\n                full_path = escape_path(p)\n                if full_path.startswith(root_folder):\n                    rel = full_path[len(root_folder)+1:]\n                    full_path = (\"%s/%s\" % (pkg_placeholder, rel))\n                ret.append(full_path)\n            return \"\".join(\"{};\".format(e) for e in ret)\n\n        root_folder = dep.recipe_folder if dep.package_folder is None else dep.package_folder\n        root_folder = escape_path(root_folder)\n        # Make the root_folder relative to the generated conan_vars_xxx.props file\n        relative_root_folder = relativize_path(root_folder, self._conanfile,\n                                               \"$(MSBuildThisFileDirectory)\", normalize=False)\n\n        bin_dirs = join_paths(cpp_info.bindirs)\n        res_dirs = join_paths(cpp_info.resdirs)\n        include_dirs = join_paths(cpp_info.includedirs)\n        lib_dirs = join_paths(cpp_info.libdirs)\n        libs = \"\".join([add_valid_ext(lib, cpp_info.libdirs) for lib in cpp_info.libs])\n        # TODO: Missing objects\n        system_libs = \"\".join([add_valid_ext(sys_dep) for sys_dep in cpp_info.system_libs])\n        definitions = \"\".join(\"%s;\" % d for d in cpp_info.defines)\n        compiler_flags = \" \".join(cpp_info.cxxflags + cpp_info.cflags)\n        linker_flags = \" \".join(cpp_info.sharedlinkflags + cpp_info.exelinkflags)\n\n        # traits logic\n        if require and not require.headers:\n            include_dirs = \"\"\n        if require and not require.libs:\n            lib_dirs = \"\"\n            libs = \"\"\n        if require and not require.libs and not require.headers:\n            definitions = \"\"\n            compiler_flags = \"\"\n            linker_flags = \"\"\n        if require and not require.run:\n            bin_dirs = \"\"\n\n        fields = {\n            'name': name,\n            'root_folder': relative_root_folder,\n            'bin_dirs': bin_dirs,\n            'res_dirs': res_dirs,\n            'include_dirs': include_dirs,\n            'lib_dirs': lib_dirs,\n            'libs': libs,\n            # TODO: Missing objects\n            'system_libs': system_libs,\n            'definitions': definitions,\n            'compiler_flags': compiler_flags,\n            'linker_flags': linker_flags,\n            'host_context': not build\n        }\n        formatted_template = Template(self._vars_props, trim_blocks=True,\n                                      lstrip_blocks=True).render(**fields)\n        return formatted_template\n\n    def _activate_props_file(self, dep_name, vars_filename, deps, build):\n        \"\"\"\n        Actual activation of the VS variables, per configuration\n            - conan_pkgname_x86_release.props / conan_pkgname_compname_x86_release.props\n        :param dep_name: pkgname / pkgname_compname\n        :param deps: the name of other things to be included: [dep1, dep2:compA, ...]\n        :param build: if it is a build require or not\n        \"\"\"\n\n        # TODO: This must include somehow the user/channel, most likely pattern to exclude/include\n        # Probably also the negation pattern, exclude all not @mycompany/*\n        ca_exclude = any(fnmatch.fnmatch(dep_name, p) for p in self.exclude_code_analysis or ())\n        template = Template(self._conf_props, trim_blocks=True, lstrip_blocks=True)\n        content_multi = template.render(host_context=not build, name=dep_name, ca_exclude=ca_exclude,\n                                        vars_filename=vars_filename, deps=deps)\n        return content_multi\n\n    @staticmethod\n    def _dep_props_file(dep_name, filename, aggregated_filename, condition, content=None):\n        \"\"\"\n        The file aggregating all configurations for a given pkg / component\n            - conan_pkgname.props\n        \"\"\"\n        # Current directory is the generators_folder\n        if content:\n            content_multi = content  # Useful for aggregating multiple components in one pass\n        elif os.path.isfile(filename):\n            content_multi = load(filename)\n        else:\n            content_multi = textwrap.dedent(\"\"\"\\\n            <?xml version=\"1.0\" encoding=\"utf-8\"?>\n            <Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n              <ImportGroup Label=\"PropertySheets\">\n              </ImportGroup>\n              <PropertyGroup>\n                <conan_{{name}}_props_imported>True</conan_{{name}}_props_imported>\n              </PropertyGroup>\n            </Project>\n            \"\"\")\n            content_multi = Template(content_multi).render({\"name\": dep_name})\n        # parse the multi_file and add new import statement if needed\n        dom = minidom.parseString(content_multi)\n        import_vars = dom.getElementsByTagName('ImportGroup')[0]\n\n        # Current vars\n        children = import_vars.getElementsByTagName(\"Import\")\n        for node in children:\n            if aggregated_filename == node.getAttribute(\"Project\") \\\n                    and condition == node.getAttribute(\"Condition\"):\n                break\n        else:  # create a new import statement\n            import_node = dom.createElement('Import')\n            import_node.setAttribute('Condition', condition)\n            import_node.setAttribute('Project', aggregated_filename)\n            import_vars.appendChild(import_node)\n\n        content_multi = dom.toprettyxml()\n        content_multi = \"\\n\".join(line for line in content_multi.splitlines() if line.strip())\n        return content_multi\n\n    def _conandeps(self):\n        \"\"\" this is a .props file including direct declared dependencies\n        \"\"\"\n        # Current directory is the generators_folder\n        conandeps_filename = \"conandeps.props\"\n        direct_deps = self._conanfile.dependencies.filter({\"direct\": True})\n        pkg_aggregated_content = textwrap.dedent(\"\"\"\\\n            <?xml version=\"1.0\" encoding=\"utf-8\"?>\n            <Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n              <ImportGroup Label=\"PropertySheets\">\n              </ImportGroup>\n            </Project>\n            \"\"\")\n        for req, dep in direct_deps.items():\n            dep_name = self._dep_name(dep, req.build)\n            filename = \"conan_%s.props\" % dep_name\n            comp_condition = \"'$(conan_%s_props_imported)' != 'True'\" % dep_name\n            pkg_aggregated_content = self._dep_props_file(\"\", conandeps_filename, filename,\n                                                          condition=comp_condition,\n                                                          content=pkg_aggregated_content)\n        return {conandeps_filename: pkg_aggregated_content}\n\n    def _package_props_files(self, require, dep, build=False):\n        \"\"\" all the files for a given package:\n        - conan_pkgname_vars_config.props: definition of variables, one per config\n        - conan_pkgname_config.props: The one using those variables. This is very different for\n                                      Host and build, build only activate <ExecutablePath>\n        - conan_pkgname.props: Conditional aggregate xxx_config.props based on active config\n        \"\"\"\n        conf_name = self._config_filename()\n        condition = self._condition()\n        dep_name = self._dep_name(dep, build)\n        result = {}\n        pkg_deps = get_transitive_requires(self._conanfile, dep)  # only non-skipped dependencies\n        if dep.cpp_info.has_components:\n            pkg_aggregated_content = None\n            for comp_name, comp_info in dep.cpp_info.components.items():\n                full_comp_name = \"{}_{}\".format(dep_name, self._get_valid_xml_format(comp_name))\n                vars_filename = \"conan_%s_vars%s.props\" % (full_comp_name, conf_name)\n                activate_filename = \"conan_%s%s.props\" % (full_comp_name, conf_name)\n                comp_filename = \"conan_%s.props\" % full_comp_name\n                pkg_filename = \"conan_%s.props\" % dep_name\n\n                public_deps = []  # To store the xml dependencies/file names\n                for required_pkg, required_comp in comp_info.parsed_requires():\n                    if required_pkg is not None:  # Points to a component of a different package\n                        try:\n                            required = pkg_deps[required_pkg]\n                        except KeyError:  # The transitive dep might have been skipped\n                            required = None\n                        if required:  # The transitive dep might have been skipped\n                            required_name = self._dep_name(required, build)\n                            public_deps.append(required_name if required_pkg == required_comp\n                                               else \"{}_{}\".format(required_name, required_comp))\n                    else:  # Points to a component of same package\n                        public_deps.append(\"{}_{}\".format(dep_name, required_comp))\n                public_deps = [self._get_valid_xml_format(d) for d in public_deps]\n                result[vars_filename] = self._vars_props_file(require, dep, full_comp_name,\n                                                              comp_info, build=build)\n                result[activate_filename] = self._activate_props_file(full_comp_name, vars_filename,\n                                                                      public_deps, build=build)\n                result[comp_filename] = self._dep_props_file(full_comp_name, comp_filename,\n                                                             activate_filename, condition)\n                comp_condition = \"'$(conan_%s_props_imported)' != 'True'\" % full_comp_name\n                pkg_aggregated_content = self._dep_props_file(dep_name, pkg_filename, comp_filename,\n                                                              condition=comp_condition,\n                                                              content=pkg_aggregated_content)\n                result[pkg_filename] = pkg_aggregated_content\n        else:\n            cpp_info = dep.cpp_info\n            vars_filename = \"conan_%s_vars%s.props\" % (dep_name, conf_name)\n            activate_filename = \"conan_%s%s.props\" % (dep_name, conf_name)\n            pkg_filename = \"conan_%s.props\" % dep_name\n            public_deps = [self._dep_name(d, build) for d in pkg_deps.values()]\n\n            result[vars_filename] = self._vars_props_file(require, dep, dep_name, cpp_info,\n                                                          build=build)\n            result[activate_filename] = self._activate_props_file(dep_name, vars_filename,\n                                                                  public_deps, build=build)\n            result[pkg_filename] = self._dep_props_file(dep_name, pkg_filename, activate_filename,\n                                                        condition=condition)\n        return result\n\n    def _content(self):\n        if not self._conanfile.settings.get_safe(\"build_type\"):\n            raise ConanException(\"The 'msbuild' generator requires a 'build_type' setting value\")\n        result = {}\n\n        for req, dep in self._conanfile.dependencies.host.items():\n            result.update(self._package_props_files(req, dep, build=False))\n        for req, dep in self._conanfile.dependencies.test.items():\n            result.update(self._package_props_files(req, dep, build=False))\n        for req, dep in self._conanfile.dependencies.build.items():\n            result.update(self._package_props_files(req, dep, build=True))\n\n        # Include all direct build_requires for host context. This might change\n        result.update(self._conandeps())\n\n        return result\n"
  },
  {
    "path": "conan/tools/microsoft/nmakedeps.py",
    "content": "import os\n\nfrom conan.internal import check_duplicated_generator\nfrom conan.tools import CppInfo\nfrom conan.tools.env import Environment\n\n\nclass NMakeDeps:\n\n    def __init__(self, conanfile):\n        \"\"\"\n        :param conanfile: ``< ConanFile object >`` The current recipe object. Always use ``self``.\n        \"\"\"\n        self._conanfile = conanfile\n        self._environment = None\n\n    # TODO: This is similar from AutotoolsDeps: Refactor and make common\n    def _get_cpp_info(self):\n        ret = CppInfo(self._conanfile)\n        deps = self._conanfile.dependencies.host.topological_sort\n        deps = [dep for dep in reversed(deps.values())]\n        for dep in deps:\n            dep_cppinfo = dep.cpp_info.aggregated_components()\n            # In case we have components, aggregate them, we do not support isolated\n            # \"targets\" with autotools\n            ret.merge(dep_cppinfo)\n        return ret\n\n    @property\n    def environment(self):\n        # TODO: Seems we want to make this uniform, equal to other generators\n        if self._environment is None:\n            cpp_info = self._get_cpp_info()\n\n            lib_paths = \";\".join(cpp_info.libdirs or [])\n\n            def format_lib(lib):\n                ext = os.path.splitext(lib)[1]\n                return lib if ext in (\".so\", \".lib\", \".a\", \".dylib\", \".bc\") else '%s.lib' % lib\n\n            ret = []\n            ret.extend(cpp_info.exelinkflags or [])\n            ret.extend(cpp_info.sharedlinkflags or [])\n            ret.extend([format_lib(lib) for lib in cpp_info.libs or []])\n            ret.extend([format_lib(lib) for lib in cpp_info.system_libs or []])\n            link_args = \" \".join(ret)\n\n            def format_define(define):\n                if \"=\" in define:\n                    # CL env-var can't accept '=' sign in /D option, it can be replaced by '#' sign:\n                    # https://learn.microsoft.com/en-us/cpp/build/reference/cl-environment-variables\n                    macro, value = define.split(\"=\", 1)\n                    if value and not value.isnumeric():\n                        value = f'\\\"{value}\\\"'\n                    define = f\"{macro}#{value}\"\n                return f\"/D\\\"{define}\\\"\"\n\n            cl_flags = [f'-I\"{p}\"' for p in cpp_info.includedirs or []]\n            cl_flags.extend(cpp_info.cflags or [])\n            cl_flags.extend(cpp_info.cxxflags or [])\n            cl_flags.extend([format_define(define) for define in cpp_info.defines or []])\n\n            env = Environment()\n            env.append(\"CL\", \" \".join(cl_flags))\n            env.append_path(\"LIB\", lib_paths)\n            env.append(\"_LINK_\", link_args)\n            self._environment = env\n        return self._environment\n\n    def vars(self, scope=\"build\"):\n        return self.environment.vars(self._conanfile, scope=scope)\n\n    def generate(self, scope=\"build\"):\n        check_duplicated_generator(self, self._conanfile)\n        self.vars(scope).save_script(\"conannmakedeps\")\n"
  },
  {
    "path": "conan/tools/microsoft/nmaketoolchain.py",
    "content": "\nfrom conan.internal import check_duplicated_generator\nfrom conan.tools.build.flags import build_type_flags, cppstd_flag, build_type_link_flags\nfrom conan.tools.env import Environment\nfrom conan.tools.microsoft.visual import msvc_runtime_flag, VCVars\n\n\nclass NMakeToolchain:\n    \"\"\"\n    https://learn.microsoft.com/en-us/cpp/build/reference/running-nmake?view=msvc-170#toolsini-and-nmake\n    We have also explored the usage of Tools.ini:\n    https://learn.microsoft.com/en-us/cpp/build/reference/running-nmake?view=msvc-170\n    but not possible, because it cannot include other files, it will also potentially collide with\n    a user Tool.ini, without easy resolution. At least the environment is additive.\n    \"\"\"\n    def __init__(self, conanfile):\n        \"\"\"\n        :param conanfile: ``< ConanFile object >`` The current recipe object. Always use ``self``.\n        \"\"\"\n        self._conanfile = conanfile\n\n        # Flags\n        self.extra_cflags = []\n        self.extra_cxxflags = []\n        self.extra_ldflags = []\n        self.extra_defines = []\n\n    @staticmethod\n    def _format_options(options):\n        return [f\"{opt[0].replace('-', '/')}{opt[1:]}\" for opt in options if len(opt) > 1]\n\n    @staticmethod\n    def _format_defines(defines):\n        formated_defines = []\n        for define in defines:\n            if \"=\" in define:\n                # CL env-var can't accept '=' sign in /D option, it can be replaced by '#' sign:\n                # https://learn.microsoft.com/en-us/cpp/build/reference/cl-environment-variables\n                macro, value = define.split(\"=\", 1)\n                if value and not value.isnumeric():\n                    value = f'\\\\\"{value}\\\\\"'\n                define = f\"{macro}#{value}\"\n            formated_defines.append(f\"/D\\\"{define}\\\"\")\n        return formated_defines\n\n    @property\n    def _cl(self):\n        bt_flags = build_type_flags(self._conanfile)\n        bt_flags = bt_flags if bt_flags else []\n\n        rt_flags = msvc_runtime_flag(self._conanfile)\n        rt_flags = [f\"/{rt_flags}\"] if rt_flags else []\n\n        cflags = []\n        cflags.extend(self._conanfile.conf.get(\"tools.build:cflags\", default=[], check_type=list))\n        cflags.extend(self.extra_cflags)\n\n        cxxflags = []\n        cppstd = cppstd_flag(self._conanfile)\n        if cppstd:\n            cxxflags.append(cppstd)\n        cxxflags.extend(self._conanfile.conf.get(\"tools.build:cxxflags\", default=[],\n                                                 check_type=list))\n        cxxflags.extend(self.extra_cxxflags)\n\n        defines = []\n        build_type = self._conanfile.settings.get_safe(\"build_type\")\n        if build_type in [\"Release\", \"RelWithDebInfo\", \"MinSizeRel\"]:\n            defines.append(\"NDEBUG\")\n        defines.extend(self._conanfile.conf.get(\"tools.build:defines\", default=[], check_type=list))\n        defines.extend(self.extra_defines)\n\n        return ([\"/nologo\"] + self._format_options(bt_flags + rt_flags + cflags + cxxflags) +\n                self._format_defines(defines))\n\n    @property\n    def _link(self):\n        bt_ldflags = build_type_link_flags(self._conanfile.settings)\n        bt_ldflags = bt_ldflags if bt_ldflags else []\n\n        ldflags = []\n        ldflags.extend(bt_ldflags)\n        ldflags.extend(self._conanfile.conf.get(\"tools.build:sharedlinkflags\", default=[],\n                                                check_type=list))\n        ldflags.extend(self._conanfile.conf.get(\"tools.build:exelinkflags\", default=[],\n                                                check_type=list))\n        ldflags.extend(self.extra_ldflags)\n\n        return [\"/nologo\"] + self._format_options(ldflags)\n\n    @property\n    def _rcflags(self):\n        rcflags = self._conanfile.conf.get(\"tools.build:rcflags\", default=[], check_type=list)\n        return self._format_options(rcflags) if rcflags else []\n\n    def environment(self):\n        env = Environment()\n        # Injection of compile flags in CL env-var:\n        # https://learn.microsoft.com/en-us/cpp/build/reference/cl-environment-variables\n        env.append(\"CL\", self._cl)\n        # Injection of link flags in _LINK_ env-var:\n        # https://learn.microsoft.com/en-us/cpp/build/reference/linking\n        env.append(\"_LINK_\", self._link)\n        if self._rcflags:\n            env.append(\"RCFLAGS\", self._rcflags)\n        # Also define some special env-vars which can override special NMake macros:\n        # https://learn.microsoft.com/en-us/cpp/build/reference/special-nmake-macros\n        conf_compilers = self._conanfile.conf.get(\"tools.build:compiler_executables\", default={},\n                                                  check_type=dict)\n        if conf_compilers:\n            compilers_mapping = {\n                \"AS\": \"asm\",\n                \"CC\": \"c\",\n                \"CPP\": \"cpp\",\n                \"CXX\": \"cpp\",\n                \"RC\": \"rc\",\n            }\n            for env_var, comp in compilers_mapping.items():\n                if comp in conf_compilers:\n                    env.define(env_var, conf_compilers[comp])\n        return env\n\n    def vars(self):\n        return self.environment().vars(self._conanfile, scope=\"build\")\n\n    def generate(self, env=None, scope=\"build\"):\n        check_duplicated_generator(self, self._conanfile)\n        env = env or self.environment()\n        env.vars(self._conanfile, scope=scope).save_script(\"conannmaketoolchain\")\n        VCVars(self._conanfile).generate(scope=scope)\n"
  },
  {
    "path": "conan/tools/microsoft/subsystems.py",
    "content": "from conan.internal.subsystems import deduce_subsystem, subsystem_path\n\n\ndef unix_path(conanfile, path, scope=\"build\"):\n    subsystem = deduce_subsystem(conanfile, scope=scope)\n    return subsystem_path(subsystem, path)\n\n\ndef unix_path_package_info_legacy(conanfile, path, path_flavor=None):\n    message = \"The use of 'unix_path_legacy_compat' is deprecated in Conan 2.0 and does not \" \\\n              \"perform path conversions. This is retained for compatibility with Conan 1.x \" \\\n              \"and will be removed in a future version.\"\n    conanfile.output.warning(message, warn_tag=\"deprecated\")\n    return path\n"
  },
  {
    "path": "conan/tools/microsoft/toolchain.py",
    "content": "import os\nimport textwrap\nfrom xml.dom import minidom\n\nfrom jinja2 import Template\n\nfrom conan.internal import check_duplicated_generator\nfrom conan.internal.api.detect.detect_vs import vs_installation_path\nfrom conan.tools.build import build_jobs\nfrom conan.tools.intel.intel_cc import IntelCC\nfrom conan.tools.microsoft.visual import VCVars, msvs_toolset, msvc_runtime_flag, \\\n    msvc_platform_from_arch, vs_ide_version\nfrom conan.errors import ConanException\nfrom conan.internal.util.files import save, load\n\n\nclass MSBuildToolchain:\n    \"\"\"\n    MSBuildToolchain class generator\n    \"\"\"\n\n    filename = \"conantoolchain.props\"\n\n    _config_toolchain_props = textwrap.dedent(\"\"\"\\\n        <?xml version=\"1.0\" encoding=\"utf-8\"?>\n        <Project xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n          {% if toolset_version_full_path %}\n          <Import Project=\"{{toolset_version_full_path}}\" />\n          {% endif %}\n          <ItemDefinitionGroup>\n            <ClCompile>\n              <PreprocessorDefinitions>{{ defines }}%(PreprocessorDefinitions)</PreprocessorDefinitions>\n              <AdditionalOptions>{{ compiler_flags }} %(AdditionalOptions)</AdditionalOptions>\n              <RuntimeLibrary>{{ runtime_library }}</RuntimeLibrary>\n              {% if cstd %}<LanguageStandard_C>{{ cstd }}</LanguageStandard_C>{% endif %}\n              <LanguageStandard>{{ cppstd }}</LanguageStandard>{{ parallel }}{{ compile_options }}\n            </ClCompile>\n            <Link>\n              <AdditionalOptions>{{ linker_flags }} %(AdditionalOptions)</AdditionalOptions>\n            </Link>\n            <ResourceCompile>\n              <PreprocessorDefinitions>{{ defines }}%(PreprocessorDefinitions)</PreprocessorDefinitions>\n              {% if rc_flags %}<AdditionalOptions>{{ rc_flags }} %(AdditionalOptions)</AdditionalOptions>{% endif %}\n            </ResourceCompile>\n          </ItemDefinitionGroup>\n          <PropertyGroup Label=\"Configuration\">\n            {% if winsdk_version %}\n            <WindowsTargetPlatformVersion>{{ winsdk_version}}</WindowsTargetPlatformVersion>\n            {% endif %}\n            <PlatformToolset>{{ toolset }}</PlatformToolset>\n            {% for k, v in properties.items() %}\n            <{{k}}>{{ v }}</{{k}}>\n            {% endfor %}\n          </PropertyGroup>\n        </Project>\n    \"\"\")\n\n    def __init__(self, conanfile):\n        \"\"\"\n        :param conanfile: ``< ConanFile object >`` The current recipe object. Always use ``self``.\n        \"\"\"\n        self._conanfile = conanfile\n        #: Dict-like that defines the preprocessor definitions\n        self.preprocessor_definitions = {}\n        #: Dict with compile options that will be added as <key>value</key> in the ClCompile section\n        self.compile_options = {}\n        #: List of all the CXX flags\n        self.cxxflags = []\n        #: List of all the C flags\n        self.cflags = []\n        #: List of all the LD linker flags\n        self.ldflags = []\n        #: List of all the RC (resource compiler) flags\n        self.rcflags = []\n        #: The build type. By default, the ``conanfile.settings.build_type`` value\n        self.configuration = conanfile.settings.build_type\n        #: The runtime flag. By default, it'll be based on the `compiler.runtime` setting.\n        self.runtime_library = self._runtime_library()\n        #: cppstd value. By default, ``compiler.cppstd`` one.\n        self.cppstd = conanfile.settings.get_safe(\"compiler.cppstd\")\n        self.cstd = conanfile.settings.get_safe(\"compiler.cstd\")\n        #: VS IDE Toolset, e.g., ``\"v140\"``. If ``compiler=msvc``, you can use ``compiler.toolset``\n        #: setting, else, it'll be based on ``msvc`` version.\n        self.toolset = msvs_toolset(conanfile)\n        self.properties = {}\n        self.toolset_version_full_path = _get_toolset_props(conanfile)\n\n    def _name_condition(self, settings):\n        platform = msvc_platform_from_arch(settings.get_safe(\"arch\"))\n        props = [(\"Configuration\", self.configuration),\n                 (\"Platform\", platform)]\n\n        name = \"\".join(\"_%s\" % v for _, v in props if v is not None)\n        condition = \" And \".join(\"'$(%s)' == '%s'\" % (k, v) for k, v in props if v is not None)\n        return name.lower(), condition\n\n    def generate(self):\n        \"\"\"\n        Generates a ``conantoolchain.props``, a ``conantoolchain_<config>.props``, and,\n        if ``compiler=msvc``, a ``conanvcvars.bat`` files. In the first two cases, they'll have the\n        valid XML format with all the good settings like any other VS project ``*.props`` file. The\n        last one emulates the ``vcvarsall.bat`` env script. See also :class:`VCVars`.\n        \"\"\"\n        check_duplicated_generator(self, self._conanfile)\n        name, condition = self._name_condition(self._conanfile.settings)\n        config_filename = \"conantoolchain{}.props\".format(name)\n        # Writing the props files\n        self._write_config_toolchain(config_filename)\n        self._write_main_toolchain(config_filename, condition)\n        if self._conanfile.settings.get_safe(\"compiler\") == \"intel-cc\":\n            IntelCC(self._conanfile).generate()\n        else:\n            VCVars(self._conanfile).generate()\n\n    def _runtime_library(self):\n        return {\n            \"MT\": \"MultiThreaded\",\n            \"MTd\": \"MultiThreadedDebug\",\n            \"MD\": \"MultiThreadedDLL\",\n            \"MDd\": \"MultiThreadedDebugDLL\",\n        }.get(msvc_runtime_flag(self._conanfile), \"\")\n\n    @property\n    def context_config_toolchain(self):\n\n        def format_macro(key, value):\n            return '%s=%s' % (key, value) if value is not None else key\n\n        cxxflags, cflags, defines, sharedlinkflags, exelinkflags, rcflags = self._get_extra_flags()\n        preprocessor_definitions = \"\".join([\"%s;\" % format_macro(k, v)\n                                            for k, v in self.preprocessor_definitions.items()])\n        defines = preprocessor_definitions + \"\".join(\"%s;\" % d for d in defines)\n        self.cxxflags.extend(cxxflags)\n        self.cflags.extend(cflags)\n        self.ldflags.extend(sharedlinkflags + exelinkflags)\n        self.rcflags.extend(rcflags)\n\n        cppstd = \"stdcpp%s\" % self.cppstd if self.cppstd else \"\"\n        cstd = f\"stdc{self.cstd}\" if self.cstd else \"\"\n        runtime_library = self.runtime_library\n        toolset = self.toolset or \"\"\n        conf_options = self._conanfile.conf.get(\"tools.microsoft.msbuildtoolchain:compile_options\",\n                                                default={}, check_type=dict)\n        self.compile_options.update(conf_options)\n        parallel = \"\"\n        njobs = build_jobs(self._conanfile)\n        if njobs:\n            parallel = \"\".join(\n                [\"\\n      <MultiProcessorCompilation>True</MultiProcessorCompilation>\",\n                 \"\\n      <ProcessorNumber>{}</ProcessorNumber>\".format(njobs)])\n        compile_options = \"\".join(\"\\n      <{k}>{v}</{k}>\".format(k=k, v=v)\n                                  for k, v in self.compile_options.items())\n\n        winsdk_version = self._conanfile.conf.get(\"tools.microsoft:winsdk_version\", check_type=str)\n        winsdk_version = winsdk_version or self._conanfile.settings.get_safe(\"os.version\")\n\n        return {\n            'defines': defines,\n            'compiler_flags': \" \".join(self.cxxflags + self.cflags),\n            'linker_flags': \" \".join(self.ldflags),\n            'rc_flags': \" \".join(self.rcflags),\n            \"cppstd\": cppstd,\n            \"cstd\": cstd,\n            \"runtime_library\": runtime_library,\n            \"toolset\": toolset,\n            \"compile_options\": compile_options,\n            \"parallel\": parallel,\n            \"properties\": self.properties,\n            \"winsdk_version\": winsdk_version,\n            \"toolset_version_full_path\": self.toolset_version_full_path\n        }\n\n    def _write_config_toolchain(self, config_filename):\n        config_filepath = os.path.join(self._conanfile.generators_folder, config_filename)\n        config_props = Template(self._config_toolchain_props, trim_blocks=True,\n                                lstrip_blocks=True).render(**self.context_config_toolchain)\n        self._conanfile.output.info(\"MSBuildToolchain created %s\" % config_filename)\n        save(config_filepath, config_props)\n\n    def _write_main_toolchain(self, config_filename, condition):\n        main_toolchain_path = os.path.join(self._conanfile.generators_folder, self.filename)\n        if os.path.isfile(main_toolchain_path):\n            content = load(main_toolchain_path)\n        else:\n            content = textwrap.dedent(\"\"\"\\\n                <?xml version=\"1.0\" encoding=\"utf-8\"?>\n                <Project ToolsVersion=\"4.0\"\n                        xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n                    <ImportGroup Label=\"PropertySheets\" >\n                    </ImportGroup>\n                    <PropertyGroup Label=\"ConanPackageInfo\">\n                        <ConanPackageName>{}</ConanPackageName>\n                        <ConanPackageVersion>{}</ConanPackageVersion>\n                    </PropertyGroup>\n                </Project>\n                \"\"\")\n\n            conan_package_name = self._conanfile.name if self._conanfile.name else \"\"\n            conan_package_version = self._conanfile.version if self._conanfile.version else \"\"\n            content = content.format(conan_package_name, conan_package_version)\n\n        dom = minidom.parseString(content)\n        try:\n            import_group = dom.getElementsByTagName('ImportGroup')[0]\n        except Exception:\n            raise ConanException(\"Broken {}. Remove the file and try again\".format(self.filename))\n        children = import_group.getElementsByTagName(\"Import\")\n        for node in children:\n            if (config_filename == node.getAttribute(\"Project\") and\n                    condition == node.getAttribute(\"Condition\")):\n                break  # the import statement already exists\n        else:  # create a new import statement\n            import_node = dom.createElement('Import')\n            import_node.setAttribute('Condition', condition)\n            import_node.setAttribute('Project', config_filename)\n            import_group.appendChild(import_node)\n\n        conan_toolchain = dom.toprettyxml()\n        conan_toolchain = \"\\n\".join(line for line in conan_toolchain.splitlines() if line.strip())\n        self._conanfile.output.info(\"MSBuildToolchain writing {}\".format(self.filename))\n        save(main_toolchain_path, conan_toolchain)\n\n    def _get_extra_flags(self):\n        # Now, it's time to get all the flags defined by the user\n        cxxflags = self._conanfile.conf.get(\"tools.build:cxxflags\", default=[], check_type=list)\n        cflags = self._conanfile.conf.get(\"tools.build:cflags\", default=[], check_type=list)\n        sharedlinkflags = self._conanfile.conf.get(\"tools.build:sharedlinkflags\", default=[],\n                                                   check_type=list)\n        exelinkflags = self._conanfile.conf.get(\"tools.build:exelinkflags\", default=[],\n                                                check_type=list)\n        rcflags = self._conanfile.conf.get(\"tools.build:rcflags\", default=[], check_type=list)\n        defines = self._conanfile.conf.get(\"tools.build:defines\", default=[], check_type=list)\n        return cxxflags, cflags, defines, sharedlinkflags, exelinkflags, rcflags\n\n\ndef _get_toolset_props(conanfile):\n    msvc_update = conanfile.conf.get(\"tools.microsoft:msvc_update\")\n    compiler_update = msvc_update or conanfile.settings.get_safe(\"compiler.update\")\n    if compiler_update is None:\n        return\n\n    vs_version = vs_ide_version(conanfile)\n    if int(vs_version) <= 14:\n        return\n    vs_install_path = conanfile.conf.get(\"tools.microsoft.msbuild:installation_path\")\n    vs_path = vs_install_path or vs_installation_path(vs_version)\n    if not vs_path or not os.path.isdir(vs_path):\n        return\n\n    basebuild = os.path.normpath(os.path.join(vs_path, \"VC/Auxiliary/Build\"))\n    # The equivalent of compiler 19.26 is toolset 14.26\n    compiler_version = str(conanfile.settings.compiler.version)\n    vcvars_ver = \"14.{}{}\".format(compiler_version[-1], compiler_update)\n    for folder in os.listdir(basebuild):\n        if not os.path.isdir(os.path.join(basebuild, folder)):\n            continue\n        if folder.startswith(vcvars_ver):\n            result = folder\n            return os.path.join(basebuild, result, f\"Microsoft.VCToolsVersion.{result}.props\")\n"
  },
  {
    "path": "conan/tools/microsoft/visual.py",
    "content": "import os\nimport textwrap\n\nfrom conan.api.output import ConanOutput\nfrom conan.internal import check_duplicated_generator\nfrom conan.internal.api.detect.detect_vs import vs_installation_path\nfrom conan.errors import ConanException, ConanInvalidConfiguration\nfrom conan.tools.scm import Version\nfrom conan.tools.intel.intel_cc import IntelCC\nfrom conan.internal.util.files import save\n\nCONAN_VCVARS = \"conanvcvars\"\n\n\ndef msvc_platform_from_arch(arch):\n    return {\"x86\": \"Win32\",\n            \"x86_64\": \"x64\",\n            \"armv7\": \"ARM\",\n            \"armv8\": \"ARM64\",\n            \"arm64ec\": \"ARM64EC\"}.get(arch)\n\n\ndef check_min_vs(conanfile, version, raise_invalid=True):\n    \"\"\"\n    This is a helper method to allow the migration of 1.X -> 2.0 and VisualStudio -> msvc settings\n    without breaking recipes.\n    The legacy \"Visual Studio\" with different toolset is not managed, not worth the complexity.\n\n    :param raise_invalid: ``bool`` Whether to raise or return False if the version check fails\n    :param conanfile: ``< ConanFile object >`` The current recipe object. Always use ``self``.\n    :param version: ``str`` Visual Studio or msvc version number.\n    \"\"\"\n    compiler = conanfile.settings.get_safe(\"compiler\")\n    compiler_version = None\n    if compiler == \"Visual Studio\":\n        compiler_version = conanfile.settings.get_safe(\"compiler.version\")\n        compiler_version = {\"17\": \"193\",\n                            \"16\": \"192\",\n                            \"15\": \"191\",\n                            \"14\": \"190\",\n                            \"12\": \"180\",\n                            \"11\": \"170\"}.get(compiler_version)\n    elif compiler == \"msvc\":\n        compiler_version = conanfile.settings.get_safe(\"compiler.version\")\n        msvc_update = conanfile.conf.get(\"tools.microsoft:msvc_update\")\n        compiler_update = msvc_update or conanfile.settings.get_safe(\"compiler.update\")\n        if compiler_version and compiler_update is not None:\n            compiler_version += \".{}\".format(compiler_update)\n\n    if compiler_version and Version(compiler_version) < version:\n        if raise_invalid:\n            msg = f\"This package doesn't work with VS compiler version '{compiler_version}'\" \\\n                  f\", it requires at least '{version}'\"\n            raise ConanInvalidConfiguration(msg)\n        else:\n            return False\n    return True\n\n\ndef msvc_version_to_vs_ide_version(version):\n    \"\"\"\n    Gets the Visual Studio IDE version given the ``msvc`` compiler one.\n\n    :param version: ``str`` or ``int`` msvc version\n    :return: VS IDE version\n    \"\"\"\n    _visuals = {'170': '11',\n                '180': '12',\n                '190': '14',\n                '191': '15',\n                '192': '16',\n                '193': '17',\n                '194': '17',  # Note both 193 and 194 belong to VS 17 2022\n                '195': '18'}\n    return _visuals[str(version)]\n\n\ndef msvc_version_to_toolset_version(version):\n    \"\"\"\n    Gets the Visual Studio IDE toolset version given the ``msvc`` compiler one.\n\n    :param version: ``str`` or ``int`` msvc version\n    :return: VS IDE toolset version\n    \"\"\"\n    toolsets = {'170': 'v110',\n                '180': 'v120',\n                '190': 'v140',\n                '191': 'v141',\n                '192': 'v142',\n                \"193\": 'v143',\n                \"194\": 'v143',\n                \"195\": 'v145'}\n    return toolsets.get(str(version))\n\n\nclass VCVars:\n    \"\"\"\n    VCVars class generator to generate a ``conanvcvars.bat`` script that activates the correct\n    Visual Studio prompt.\n\n    This generator will be automatically called by other generators such as ``CMakeToolchain``\n    when considered necessary, for example if building with Visual Studio compiler using the\n    CMake ``Ninja`` generator, which needs an active Visual Studio prompt.\n    Then, it is not necessary to explicitly instantiate this generator in most cases.\n    \"\"\"\n\n    def __init__(self, conanfile):\n        \"\"\"\n        :param conanfile: ``ConanFile object`` The current recipe object. Always use ``self``.\n        \"\"\"\n        self._conanfile = conanfile\n\n    def generate(self, scope=\"build\"):\n        \"\"\"\n        Creates a ``conanvcvars.bat`` file that calls Visual ``vcvars`` with the necessary\n        args to activate the correct Visual Studio prompt matching the Conan settings.\n\n        :param scope: ``str`` activation scope, by default \"build\". It means it will add a\n                      call to this ``conanvcvars.bat`` from the aggregating general\n                      ``conanbuild.bat``, which is the script that will be called by default\n                      in ``self.run()`` calls and build helpers such as ``cmake.configure()``\n                      and ``cmake.build()``.\n        \"\"\"\n        check_duplicated_generator(self, self._conanfile)\n        conanfile = self._conanfile\n\n        os_ = conanfile.settings.get_safe(\"os\")\n        build_os_ = conanfile.settings_build.get_safe(\"os\")\n\n        if (os_ != \"Windows\" and os_ != \"WindowsStore\") or build_os_ != \"Windows\":\n            return\n\n        compiler = conanfile.settings.get_safe(\"compiler\")\n        if compiler not in (\"msvc\", \"clang\"):\n            return\n\n        vs_install_path = conanfile.conf.get(\"tools.microsoft.msbuild:installation_path\")\n        if vs_install_path == \"\":  # Empty string means \"disable\"\n            return\n\n        vs_version, vcvars_ver = _vcvars_versions(conanfile)\n        if vs_version is None:\n            return\n\n        vcvarsarch = _vcvars_arch(conanfile)\n\n        winsdk_version = conanfile.conf.get(\"tools.microsoft:winsdk_version\", check_type=str)\n        winsdk_version = winsdk_version or conanfile.settings.get_safe(\"os.version\")\n        # The vs_install_path is like\n        # C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\n        # C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community\n        # C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\n        vcvars = vcvars_command(vs_version, architecture=vcvarsarch, platform_type=None,\n                                winsdk_version=winsdk_version, vcvars_ver=vcvars_ver,\n                                vs_install_path=vs_install_path)\n\n        content = textwrap.dedent(f\"\"\"\\\n            @echo off\n            set __VSCMD_ARG_NO_LOGO=1\n            set VSCMD_SKIP_SENDTELEMETRY=1\n            echo conanvcvars.bat: Activating environment Visual Studio {vs_version} - {vcvarsarch} - winsdk_version={winsdk_version} - vcvars_ver={vcvars_ver}\n            {vcvars}\n            \"\"\")\n        from conan.tools.env.environment import create_env_script\n        conan_vcvars_bat = f\"{CONAN_VCVARS}.bat\"\n        create_env_script(conanfile, content, conan_vcvars_bat, scope)\n        _create_deactivate_vcvars_file(conanfile, conan_vcvars_bat)\n\n        try:\n            is_ps1 = self._conanfile.conf.get(\"tools.env.virtualenv:powershell\", check_type=bool)\n            if is_ps1 is not None:\n                ConanOutput().warning(\n                    \"Boolean values for 'tools.env.virtualenv:powershell' are deprecated. \"\n                    \"Please specify 'powershell.exe' or 'pwsh' instead, appending arguments \"\n                    \"if needed (for example: 'powershell.exe -argument'). \"\n                    \"To unset this configuration, use `tools.env.virtualenv:powershell=!`, \"\n                    \"which matches the previous 'False' behavior.\",\n                    warn_tag=\"deprecated\"\n                )\n        except ConanException:\n            is_ps1 = self._conanfile.conf.get(\"tools.env.virtualenv:powershell\", check_type=str)\n        if is_ps1:\n            content_ps1 = textwrap.dedent(rf\"\"\"\n            if (-not $env:VSCMD_ARG_VCVARS_VER){{\n                Push-Location \"$PSScriptRoot\"\n                cmd /c \"conanvcvars.bat&set\" |\n                foreach {{\n                  if ($_ -match \"=\") {{\n                    $v = $_.split(\"=\", 2); set-item -force -path \"ENV:\\$($v[0])\"  -value \"$($v[1])\"\n                  }}\n                }}\n                Pop-Location\n                write-host conanvcvars.ps1: Activated environment}}\n            \"\"\").strip()\n            conan_vcvars_ps1 = f\"{CONAN_VCVARS}.ps1\"\n            create_env_script(conanfile, content_ps1, conan_vcvars_ps1, scope)\n            _create_deactivate_vcvars_file(conanfile, conan_vcvars_ps1)\n\n\ndef _create_deactivate_vcvars_file(conanfile, filename):\n    if conanfile.conf.get(\"tools.env:deactivation_mode\") == \"function\":\n        return\n    deactivate_filename = f\"deactivate_{filename}\"\n    message = f\"[{deactivate_filename}]: *** vcvars env cannot be deactivated ***\\n\"\n    is_ps1 = filename.endswith(\".ps1\")\n    if is_ps1:\n        content = f\"Write-Host {message}\"\n    else:\n        content = f\"echo {message}\"\n    path = os.path.join(conanfile.generators_folder, deactivate_filename)\n    save(path, content)\n\n\ndef vs_ide_version(conanfile):\n    \"\"\"\n    Gets the VS IDE version as string. It'll use the ``compiler.version`` (if exists) and/or the\n    ``tools.microsoft.msbuild:vs_version`` if ``compiler`` is ``msvc``.\n\n    :param conanfile: ``< ConanFile object >`` The current recipe object. Always use ``self``.\n    :return: ``str`` Visual IDE version number.\n    \"\"\"\n    compiler = conanfile.settings.get_safe(\"compiler\")\n    compiler_version = conanfile.settings.get_safe(\"compiler.version\")\n    if compiler == \"msvc\":\n        toolset_override = conanfile.conf.get(\"tools.microsoft.msbuild:vs_version\", check_type=str)\n        if toolset_override:\n            visual_version = toolset_override\n        else:\n            visual_version = msvc_version_to_vs_ide_version(compiler_version)\n    else:\n        visual_version = compiler_version\n    return visual_version\n\n\ndef msvc_runtime_flag(conanfile):\n    \"\"\"\n    Gets the MSVC runtime flag given the ``compiler.runtime`` value from the settings.\n\n    :param conanfile: ``< ConanFile object >`` The current recipe object. Always use ``self``.\n    :return: ``str`` runtime flag.\n    \"\"\"\n    settings = conanfile.settings\n    runtime = settings.get_safe(\"compiler.runtime\")\n    if runtime is not None:\n        if runtime == \"static\":\n            runtime = \"MT\"\n        elif runtime == \"dynamic\":\n            runtime = \"MD\"\n        else:\n            raise ConanException(\"compiler.runtime should be 'static' or 'dynamic'\")\n        runtime_type = settings.get_safe(\"compiler.runtime_type\")\n        if runtime_type == \"Debug\":\n            runtime = \"{}d\".format(runtime)\n        return runtime\n    return \"\"\n\n\ndef vcvars_command(version, architecture=None, platform_type=None, winsdk_version=None,\n                   vcvars_ver=None, start_dir_cd=True, vs_install_path=None):\n    \"\"\"\n    Conan-agnostic construction of vcvars command\n    https://docs.microsoft.com/en-us/cpp/build/building-on-the-command-line\n\n    :param version: ``str`` Visual Studio version.\n    :param architecture: ``str`` Specifies the host and target architecture to use.\n    :param platform_type: ``str`` Allows you to specify ``store`` or ``uwp`` as the platform type.\n    :param winsdk_version: ``str`` Specifies the version of the Windows SDK to use.\n    :param vcvars_ver: ``str`` Specifies the Visual Studio compiler toolset to use.\n    :param start_dir_cd: ``bool`` If ``True``, the command will execute\n                         ``set \"VSCMD_START_DIR=%CD%`` at first.\n    :param vs_install_path: ``str`` Visual Studio installation path.\n    :return: ``str`` complete _vcvarsall_ command.\n    \"\"\"\n    cmd = []\n    if start_dir_cd:\n        cmd.append('set \"VSCMD_START_DIR=%CD%\" &&')\n\n    # The \"call\" is useful in case it is called from another .bat script\n    cmd.append('call \"%s\" ' % _vcvars_path(version, vs_install_path))\n    if architecture:\n        cmd.append(architecture)\n    if platform_type:\n        cmd.append(platform_type)\n    if winsdk_version:\n        cmd.append(winsdk_version)\n    if vcvars_ver:\n        cmd.append(\"-vcvars_ver=%s\" % vcvars_ver)\n    return \" \".join(cmd)\n\n\ndef _vcvars_path(version, vs_install_path):\n    # TODO: This comes from conans/client/tools/win.py vcvars_command()\n    vs_path = vs_install_path or vs_installation_path(version)\n    if not vs_path or not os.path.isdir(vs_path):\n        raise ConanException(f\"VS non-existing installation: Visual Studio {version}. \"\n                             \"If using a non-default toolset from a VS IDE version consider \"\n                             \"specifying it with the 'tools.microsoft.msbuild:vs_version' conf\")\n\n    if int(version) > 14:\n        vcpath = os.path.join(vs_path, \"VC/Auxiliary/Build/vcvarsall.bat\")\n    else:\n        vcpath = os.path.join(vs_path, \"VC/vcvarsall.bat\")\n    vcpath = os.path.normpath(vcpath)\n    return vcpath\n\n\ndef _vcvars_versions(conanfile):\n    compiler = conanfile.settings.get_safe(\"compiler\")\n    msvc_update = conanfile.conf.get(\"tools.microsoft:msvc_update\")\n    if compiler == \"clang\":\n        # The vcvars only needed for LLVM/Clang and VS ClangCL, who define runtime\n        if not conanfile.settings.get_safe(\"compiler.runtime\"):\n            # NMake Makefiles will need vcvars activated, for VS target, defined with runtime\n            return None, None\n        toolset_version = conanfile.settings.get_safe(\"compiler.runtime_version\")\n        vs_version = {\"v140\": \"14\",\n                      \"v141\": \"15\",\n                      \"v142\": \"16\",\n                      \"v143\": \"17\",\n                      \"v144\": \"17\",\n                      \"v145\": \"18\"}.get(toolset_version)\n        if vs_version is None:\n            raise ConanException(\"Visual Studio Runtime version (v140-v145) not defined. Please, \"\n                                 \"add the compiler.runtime_version=[v140-v145] setting to your \"\n                                 \"profile.\")\n        vcvars_ver = {\"v140\": \"14.0\",\n                      \"v141\": \"14.1\",\n                      \"v142\": \"14.2\",\n                      \"v143\": \"14.3\",\n                      \"v144\": \"14.4\",\n                      \"v145\": \"14.5\"}.get(toolset_version)\n        if vcvars_ver and msvc_update is not None:\n            vcvars_ver += f\"{msvc_update}\"\n    else:\n        vs_version = vs_ide_version(conanfile)\n        if int(vs_version) <= 14:\n            vcvars_ver = None\n        else:\n            compiler_version = str(conanfile.settings.compiler.version)\n            compiler_update = msvc_update or conanfile.settings.get_safe(\"compiler.update\", \"\")\n            # The equivalent of compiler 19.26 is toolset 14.26\n            vcvars_ver = \"14.{}{}\".format(compiler_version[-1], compiler_update)\n    return vs_version, vcvars_ver\n\n\ndef _vcvars_arch(conanfile):\n    \"\"\"\n    Computes the vcvars command line architecture based on conanfile settings (host) and\n    settings_build.\n    \"\"\"\n    settings_host = conanfile.settings\n    settings_build = conanfile.settings_build\n\n    arch_host = str(settings_host.arch)\n    arch_build = str(settings_build.arch)\n\n    arch = None\n    if arch_build == 'x86_64':\n        arch = {'x86': \"amd64_x86\",\n                'x86_64': 'amd64',\n                'armv7': 'amd64_arm',\n                'armv8': 'amd64_arm64',\n                'arm64ec': 'amd64_arm64'}.get(arch_host)\n    elif arch_build == 'x86':\n        arch = {'x86': 'x86',\n                'x86_64': 'x86_amd64',\n                'armv7': 'x86_arm',\n                'armv8': 'x86_arm64'}.get(arch_host)\n    elif arch_build == 'armv8':\n        arch = {'x86': 'arm64_x86',\n                'x86_64': 'arm64_x64',\n                'armv7': 'arm64_arm',\n                'armv8': 'arm64'}.get(arch_host)\n\n    if not arch:\n        raise ConanException('vcvars unsupported architectures %s-%s' % (arch_build, arch_host))\n\n    return arch\n\n\ndef is_msvc(conanfile, build_context=False):\n    \"\"\"\n    Validates if the current compiler is ``msvc``.\n\n    :param conanfile: ``< ConanFile object >`` The current recipe object. Always use ``self``.\n    :param build_context: If True, will use the settings from the build context, not host ones\n    :return: ``bool`` True, if the host compiler is ``msvc``, otherwise, False.\n    \"\"\"\n    if not build_context:\n        settings = conanfile.settings\n    else:\n        settings = conanfile.settings_build\n    return settings.get_safe(\"compiler\") == \"msvc\"\n\n\ndef is_msvc_static_runtime(conanfile):\n    \"\"\"\n    Validates when building with Visual Studio or msvc and MT on runtime.\n\n    :param conanfile: ``< ConanFile object >`` The current recipe object. Always use ``self``.\n    :return: ``bool`` True, if ``msvc + runtime MT``. Otherwise, False.\n    \"\"\"\n    return is_msvc(conanfile) and \"MT\" in msvc_runtime_flag(conanfile)\n\n\ndef msvs_toolset(conanfile):\n    \"\"\"\n    Returns the corresponding platform toolset based on the compiler setting.\n    In case no toolset is configured in the profile, it will return a toolset based on the\n    compiler version, otherwise, it will return the toolset from the profile.\n    When there is no compiler version neither toolset configured, it will return None\n    It supports msvc, intel-cc and clang compilers. For clang, is assumes the ClangCl toolset,\n    as provided by the Visual Studio installer.\n\n    :param conanfile: Conanfile instance to access settings.compiler\n    :return: A toolset when compiler.version is valid or compiler.toolset is configured. Otherwise, None.\n    \"\"\"\n    settings = conanfile.settings\n    compiler = settings.get_safe(\"compiler\")\n    compiler_version = settings.get_safe(\"compiler.version\")\n    if compiler == \"msvc\":\n        subs_toolset = settings.get_safe(\"compiler.toolset\")\n        if subs_toolset:\n            return subs_toolset\n        return msvc_version_to_toolset_version(compiler_version)\n    if compiler == \"clang\":\n        return \"ClangCl\"\n    if compiler == \"intel-cc\":\n        return IntelCC(conanfile).ms_toolset\n"
  },
  {
    "path": "conan/tools/premake/__init__.py",
    "content": "from conan.tools.premake.premake import Premake\nfrom conan.tools.premake.premakedeps import PremakeDeps\nfrom conan.tools.premake.toolchain import PremakeToolchain\n"
  },
  {
    "path": "conan/tools/premake/constants.py",
    "content": "# Source: https://premake.github.io/docs/architecture/\nCONAN_TO_PREMAKE_ARCH = {\n    \"x86\": \"x86\",\n    \"x86_64\": \"x86_64\",\n\n    \"armv4\": \"arm\",\n    \"armv4i\": \"arm\",\n    \"armv5el\": \"arm\",\n    \"armv5hf\": \"arm\",\n    \"armv6\": \"arm\",\n    \"armv7\": \"arm\",\n    \"armv7hf\": \"arm\",\n    \"armv7s\": \"arm\",\n    \"armv7k\": \"arm\",\n\n    \"armv8\": \"arm64\",\n    \"armv8_32\": \"arm64\",\n    \"armv8.3\": \"arm64\",\n    \"arm64ec\": \"arm64\",\n\n    \"e2k-v2\": \"e2k\",\n    \"e2k-v3\": \"e2k\",\n    \"e2k-v4\": \"e2k\",\n    \"e2k-v5\": \"e2k\",\n    \"e2k-v6\": \"e2k\",\n    \"e2k-v7\": \"e2k\",\n\n    \"riscv64\": \"riscv64\",\n\n    \"wasm\": \"wasm32\",\n    \"wasm64\": \"wasm64\",\n    \"asm.js\": \"wasm32\",\n}\n"
  },
  {
    "path": "conan/tools/premake/premake.py",
    "content": "import textwrap\nfrom pathlib import Path\n\nfrom conan.tools.build.cpu import build_jobs\nfrom jinja2 import Template\n\nfrom conan.errors import ConanException\nfrom conan.tools.files import save\nfrom conan.tools.microsoft.msbuild import MSBuild\nfrom conan.tools.premake.toolchain import PremakeToolchain\nfrom conan.tools.premake.constants import CONAN_TO_PREMAKE_ARCH\n\n# Source: https://learn.microsoft.com/en-us/cpp/overview/compiler-versions?view=msvc-170\nPREMAKE_VS_VERSION = {\n    '190': '2015',\n    '191': '2017',\n    '192': '2019',\n    '193': '2022',\n    '194': '2022',  # still 2022\n    '195': '2026'\n}\n\n\nclass Premake:\n    \"\"\"\n    This class calls Premake commands when a package is being built. Notice that\n    this one should be used together with the ``PremakeToolchain`` generator.\n\n    This premake generator is only compatible with ``premake5``.\n    \"\"\"\n\n    filename = \"conanfile.premake5.lua\"\n\n    # Conan premake file which will preconfigure toolchain and then will call the user's premake file\n    _premake_file_template = textwrap.dedent(\n        \"\"\"\\\n    #!lua\n    include(\"{{luafile}}\")\n    include(\"{{premake_conan_toolchain}}\")\n    \"\"\"\n    )\n\n    def __init__(self, conanfile):\n        \"\"\"\n        :param conanfile: ``< ConanFile object >`` The current recipe object. Always use ``self``.\n        \"\"\"\n        self._conanfile = conanfile\n        #: Path to the root premake5 lua file (default is ``premake5.lua``)\n        self.luafile = (Path(self._conanfile.source_folder) / \"premake5.lua\").as_posix()\n        #: Key value pairs. Will translate to \"--{key}={value}\"\n        self.arguments = {}  # https://premake.github.io/docs/Command-Line-Arguments/\n\n        if \"msvc\" in self._conanfile.settings.compiler:\n            msvc_version = PREMAKE_VS_VERSION.get(str(self._conanfile.settings.compiler.version))\n            self.action = f'vs{msvc_version}'\n        else:\n            self.action = \"gmake\"  # New generator (old gmakelegacy is deprecated)\n\n        self._premake_conan_toolchain = Path(self._conanfile.generators_folder) / PremakeToolchain.filename\n\n    @staticmethod\n    def _expand_args(args):\n        return ' '.join([f'--{key}={value}' for key, value in args.items()])\n\n    def configure(self):\n        \"\"\"\n        Runs ``premake5 <action> [FILE]`` which will generate respective build scripts depending on the ``action``.\n        \"\"\"\n        if self._premake_conan_toolchain.exists():\n            content = Template(self._premake_file_template).render(\n                premake_conan_toolchain=self._premake_conan_toolchain.as_posix(), luafile=self.luafile\n            )\n            conan_luafile = Path(self._conanfile.build_folder) / self.filename\n            save(self._conanfile, conan_luafile, content)\n            arch = str(self._conanfile.settings.arch)\n            if arch not in CONAN_TO_PREMAKE_ARCH:\n                raise ConanException(f\"Premake does not support {arch} architecture.\")\n            self.arguments[\"arch\"] = CONAN_TO_PREMAKE_ARCH[arch]\n        else:\n            # Old behavior, for backward compatibility\n            conan_luafile = self.luafile\n\n        premake_options = dict()\n        premake_options[\"file\"] = f'\"{conan_luafile}\"'\n\n        premake_command = (\n            f\"premake5 {self._expand_args(premake_options)} {self.action} \"\n            f\"{self._expand_args(self.arguments)}{self._premake_verbosity}\"\n        )\n        self._conanfile.run(premake_command)\n\n    @property\n    def _premake_verbosity(self):\n        verbosity = self._conanfile.conf.get(\"tools.build:verbosity\", choices=(\"quiet\", \"verbose\"))\n        return \" --verbose\" if verbosity == \"verbose\" else \"\"\n\n    @property\n    def _compilation_verbosity(self):\n        verbosity = self._conanfile.conf.get(\"tools.compilation:verbosity\", choices=(\"quiet\", \"verbose\"))\n        # --verbose does not print compilation commands but internal Makefile progress logic\n        return \" verbose=1\" if verbosity == \"verbose\" else \"\"\n\n    def build(self, workspace, targets=None, configuration=None, msbuild_platform=None):\n        \"\"\"\n        Depending on the action, this method will run either ``msbuild`` or ``make`` with ``N_JOBS``.\n        You can specify ``N_JOBS`` through the configuration line ``tools.build:jobs=N_JOBS``\n        in your profile ``[conf]`` section.\n\n        :param workspace: ``str`` Specifies the solution to be compiled (only used by ``MSBuild``).\n        :param targets: ``List[str]`` Declare the projects to be built (None to build all projects).\n        :param configuration: ``str`` Specify the configuration build type, default to build_type (\"Release\" or \"Debug\"),\n            but this allow setting custom configuration type.\n        :param msbuild_platform: ``str`` Specify the platform for the internal MSBuild generator (only used by ``MSBuild``).\n        \"\"\"\n        if not self._premake_conan_toolchain.exists():\n            raise ConanException(\"Premake.build() method requires PremakeToolchain to work properly\")\n\n        build_type = configuration or str(self._conanfile.settings.build_type)\n        if self.action.startswith(\"vs\"):\n            msbuild = MSBuild(self._conanfile)\n            if msbuild_platform:\n                msbuild.platform = msbuild_platform\n            msbuild.build_type = build_type\n            msbuild.build(sln=f\"{workspace}.sln\", targets=targets)\n        else:\n            targets = \"all\" if targets is None else \" \".join(targets)\n            njobs = build_jobs(self._conanfile)\n            self._conanfile.run(f\"make config={build_type.lower()} {targets} -j{njobs}{self._compilation_verbosity}\")\n"
  },
  {
    "path": "conan/tools/premake/premakedeps.py",
    "content": "import itertools\nimport glob\nimport re\n\nfrom conan.internal import check_duplicated_generator\nfrom conan.internal.util.files import save\nfrom conan.tools.premake.constants import CONAN_TO_PREMAKE_ARCH\n\n# Filename format strings\nPREMAKE_VAR_FILE = \"conan_{pkgname}_vars_{config}.premake5.lua\"\nPREMAKE_PKG_FILE = \"conan_{pkgname}.premake5.lua\"\nPREMAKE_ROOT_FILE = \"conandeps.premake5.lua\"\n\nPREMAKE_CONFIG_FILE = \"conanconfig_{config}.premake5.lua\"\nPREMAKE_CONFIG_ROOT_FILE = \"conanconfig.premake5.lua\"\n\n# File template format strings\nPREMAKE_TEMPLATE_CONFIG = \"\"\"\ninclude \"conanutils.premake5.lua\"\n\nt_conan_deps_order = {{}}\nt_conan_deps_order[\"{config}\"] = {{{order}}}\n\nif conan_deps_order == nil then conan_deps_order = {{}} end\nconan_premake_tmerge(conan_deps_order, t_conan_deps_order)\n\"\"\"\nPREMAKE_TEMPLATE_UTILS = \"\"\"\nfunction conan_premake_tmerge(dst, src)\n    for k, v in pairs(src) do\n        if type(v) == \"table\" then\n            if type(dst[k] or 0) == \"table\" then\n                conan_premake_tmerge(dst[k] or {}, src[k] or {})\n            else\n                dst[k] = v\n            end\n        else\n            dst[k] = v\n        end\n    end\n    return dst\nend\n\"\"\"\nPREMAKE_TEMPLATE_VAR = \"\"\"\ninclude \"conanutils.premake5.lua\"\n\nt_conandeps = {{}}\nt_conandeps[\"{config}\"] = {{}}\nt_conandeps[\"{config}\"][\"{pkgname}\"] = {{}}\nt_conandeps[\"{config}\"][\"{pkgname}\"][\"includedirs\"] = {{{deps.includedirs}}}\nt_conandeps[\"{config}\"][\"{pkgname}\"][\"libdirs\"] = {{{deps.libdirs}}}\nt_conandeps[\"{config}\"][\"{pkgname}\"][\"bindirs\"] = {{{deps.bindirs}}}\nt_conandeps[\"{config}\"][\"{pkgname}\"][\"libs\"] = {{{deps.libs}}}\nt_conandeps[\"{config}\"][\"{pkgname}\"][\"system_libs\"] = {{{deps.system_libs}}}\nt_conandeps[\"{config}\"][\"{pkgname}\"][\"defines\"] = {{{deps.defines}}}\nt_conandeps[\"{config}\"][\"{pkgname}\"][\"cxxflags\"] = {{{deps.cxxflags}}}\nt_conandeps[\"{config}\"][\"{pkgname}\"][\"cflags\"] = {{{deps.cflags}}}\nt_conandeps[\"{config}\"][\"{pkgname}\"][\"sharedlinkflags\"] = {{{deps.sharedlinkflags}}}\nt_conandeps[\"{config}\"][\"{pkgname}\"][\"exelinkflags\"] = {{{deps.exelinkflags}}}\nt_conandeps[\"{config}\"][\"{pkgname}\"][\"frameworks\"] = {{{deps.frameworks}}}\n\nif conandeps == nil then conandeps = {{}} end\nconan_premake_tmerge(conandeps, t_conandeps)\n\"\"\"\nPREMAKE_TEMPLATE_ROOT_BUILD = \"\"\"\n        includedirs(conandeps[conf][pkg][\"includedirs\"])\n        bindirs(conandeps[conf][pkg][\"bindirs\"])\n        defines(conandeps[conf][pkg][\"defines\"])\n\"\"\"\nPREMAKE_TEMPLATE_ROOT_LINK = \"\"\"\n        libdirs(conandeps[conf][pkg][\"libdirs\"])\n        links(conandeps[conf][pkg][\"libs\"])\n        links(conandeps[conf][pkg][\"system_libs\"])\n        links(conandeps[conf][pkg][\"frameworks\"])\n\"\"\"\nPREMAKE_TEMPLATE_ROOT_FUNCTION = \"\"\"\nfunction {function_name}(conf, pkg)\n    if conf == nil then\n{filter_call}\n    elseif pkg == nil then\n        local order = conan_deps_order[conf]\n        for index, lib in ipairs(order) do\n            {function_name}(conf, lib)\n        end\n    else\n{lua_content}\n    end\nend\n\"\"\"\nPREMAKE_TEMPLATE_ROOT_GLOBAL = \"\"\"\nfunction conan_setup(conf, pkg)\n    conan_setup_build(conf, pkg)\n    conan_setup_link(conf, pkg)\nend\n\"\"\"\n\n\n# Helper class that expands cpp_info meta information in lua readable string sequences\nclass _PremakeTemplate:\n    def __init__(self, req, dep_cpp_info):\n        def _format_paths(paths):\n            if not paths:\n                return \"\"\n            return \",\\n\".join(f'\"{p}\"'.replace(\"\\\\\", \"/\") for p in paths)\n\n        def _format_flags(flags):\n            if not flags:\n                return \"\"\n            return \", \".join('\"%s\"' % p.replace('\"', '\\\\\"') for p in flags)\n\n        # Headers dependant\n        with_headers = req and req.headers\n        self.includedirs = _format_paths(dep_cpp_info.includedirs if with_headers else [])\n        self.defines = _format_flags(dep_cpp_info.defines if with_headers else [])\n        self.cxxflags = _format_flags(dep_cpp_info.cxxflags if with_headers else [])\n        self.cflags = _format_flags(dep_cpp_info.cflags if with_headers else [])\n        self.sharedlinkflags = _format_flags(dep_cpp_info.sharedlinkflags if with_headers else [])\n        self.exelinkflags = _format_flags(dep_cpp_info.exelinkflags if with_headers else [])\n\n        # Libs dependant\n        with_libs = req and req.libs\n        self.libs = _format_flags(dep_cpp_info.libs if with_libs else [])\n        self.libdirs = _format_paths(dep_cpp_info.libdirs if with_libs else [])\n\n        # Run dependant\n        with_run = req and req.run\n        self.bindirs = _format_paths(dep_cpp_info.bindirs if with_run else [])\n\n        self.system_libs = _format_flags(dep_cpp_info.system_libs)\n        self.frameworks = \", \".join('\"%s.framework\"' % p.replace('\"', '\\\\\"') for p in\n                                    dep_cpp_info.frameworks) if dep_cpp_info.frameworks else \"\"\n        self.sysroot = f\"{dep_cpp_info.sysroot}\".replace(\"\\\\\", \"/\") \\\n            if dep_cpp_info.sysroot else \"\"\n\n\nclass PremakeDeps:\n    \"\"\"\n    PremakeDeps class generator\n    conandeps.premake5.lua: unconditional import of all *direct* dependencies only\n    \"\"\"\n\n    def __init__(self, conanfile):\n        \"\"\"\n        :param conanfile: ``< ConanFile object >`` The current recipe object. Always use ``self``.\n        \"\"\"\n\n        self._conanfile = conanfile\n\n        # Tab configuration\n        self.tab = \"    \"\n\n        # Return value buffer\n        self.output_files = {}\n        # Extract configuration and architecture form conanfile\n        self.configuration = conanfile.settings.build_type\n        self.architecture = conanfile.settings.arch\n\n    def generate(self):\n        \"\"\"\n        Generates ``conan_<pkg>_vars_<config>.premake5.lua``, ``conan_<pkg>_<config>.premake5.lua``,\n        and ``conan_<pkg>.premake5.lua`` files into the ``conanfile.generators_folder``.\n        \"\"\"\n\n        check_duplicated_generator(self, self._conanfile)\n        # Current directory is the generators_folder\n        generator_files = self.content\n        for generator_file, content in generator_files.items():\n            save(generator_file, content)\n\n    def _config_suffix(self):\n        return f\"{self.configuration}_{CONAN_TO_PREMAKE_ARCH[str(self.architecture)]}\".lower()\n\n    def _output_lua_file(self, filename, content):\n        self.output_files[filename] = \"\\n\".join([\"#!lua\", *content])\n\n    def _indent_string(self, string, indent=1):\n        return \"\\n\".join([\n            f\"{self.tab * indent}{line}\" for line in list(filter(None, string.splitlines()))\n        ])\n\n    def _premake_filtered(self, content, configuration, architecture, indent=0):\n        \"\"\"\n        - Surrounds the lua line(s) contained within ``content`` with a premake \"filter\" and returns the result.\n        - A \"filter\" will affect all premake function calls after it's set. It's used to limit following project\n          setup function call(s) to a certain scope. Here it is used to limit the calls in content to only apply\n          if the premake ``configuration`` and ``architecture`` matches the parameters in this function call.\n        \"\"\"\n        lines = list(itertools.chain.from_iterable([cnt.splitlines() for cnt in content]))\n        return [\n            # Set new filter\n            f'{self.tab * indent}filter {{ \"configurations:{configuration}\", \"architecture:{architecture}\" }}',\n            # Emit content\n            *[f\"{self.tab * indent}{self.tab}{line.strip()}\" for line in list(filter(None, lines))],\n            # Clear active filter\n            f\"{self.tab * indent}filter {{}}\",\n        ]\n\n    @property\n    def content(self):\n        check_duplicated_generator(self, self._conanfile)\n\n        self.output_files = {}\n        conf_name = self._config_suffix()\n\n        # Global utility file\n        self._output_lua_file(\"conanutils.premake5.lua\", [PREMAKE_TEMPLATE_UTILS])\n\n        # Extract all dependencies in topological order: some linkers like ld or gold prunes the\n        # functions which are not being used in the lookup table. If the less dependant libraries are\n        # passed first, the linker will not be able to resolve the symbols in the dependent libraries\n        # as they will have been removed\n        host_req = self._conanfile.dependencies.host.topological_sort\n        test_req = self._conanfile.dependencies.test.topological_sort\n        build_req = self._conanfile.dependencies.direct_build.topological_sort\n\n        # Merge into one list\n        full_req = list(host_req.items()) + list(test_req.items()) + list(build_req.items())\n\n        # Process dependencies and accumulate globally required data\n        pkg_files = []\n        dep_names = []\n        config_sets = []\n        for require, dep in full_req:\n            dep_name = require.ref.name\n            dep_names.append(dep_name)\n\n            # Convert and aggregate dependency's\n            dep_aggregate = dep.cpp_info.aggregated_components()\n\n            # Generate config dependent package variable and setup premake file\n            var_filename = PREMAKE_VAR_FILE.format(pkgname=dep_name, config=conf_name)\n            self._output_lua_file(var_filename, [\n                PREMAKE_TEMPLATE_VAR.format(pkgname=dep_name,\n                    config=conf_name, deps=_PremakeTemplate(require, dep_aggregate))\n            ])\n\n            # Create list of all available profiles by searching on disk\n            file_pattern = PREMAKE_VAR_FILE.format(pkgname=dep_name, config=\"*\")\n            file_regex = PREMAKE_VAR_FILE.format(pkgname=re.escape(dep_name), config=\"(([^_]*)_(.*))\")\n            available_config_files = glob.glob(file_pattern)\n            # Add filename of current generations var file if not already present\n            if var_filename not in available_config_files:\n                available_config_files.append(var_filename)\n            profiles = [\n                (regex_res[0], regex_res.group(1), regex_res.group(2), regex_res.group(3)) for regex_res in [\n                    re.search(file_regex, file_name) for file_name in available_config_files\n                ]\n            ]\n            config_sets = [profile[1] for profile in profiles]\n\n            # Emit package premake file\n            pkg_filename = PREMAKE_PKG_FILE.format(pkgname=dep_name)\n            pkg_files.append(pkg_filename)\n            self._output_lua_file(pkg_filename, [\n                # Includes\n                *['include \"{}\"'.format(profile[0]) for profile in profiles],\n            ])\n\n        # Output global premake file\n        self._output_lua_file(PREMAKE_ROOT_FILE, [\n            # Includes\n            *[f'include \"{pkg_file}\"' for pkg_file in pkg_files],\n            # Global order for each configuration\n            'include \"conanconfig.premake5.lua\"',\n            # Functions\n            PREMAKE_TEMPLATE_ROOT_FUNCTION.format(\n                function_name=\"conan_setup_build\",\n                lua_content=PREMAKE_TEMPLATE_ROOT_BUILD,\n                filter_call=\"\\n\".join(\n                    [\"\\n\".join(self._premake_filtered(\n                        [f'conan_setup_build(\"{config}\")'], config.split(\"_\", 1)[0], config.split(\"_\", 1)[1], 2)\n                    ) for config in config_sets]\n                )\n            ),\n            PREMAKE_TEMPLATE_ROOT_FUNCTION.format(\n                function_name=\"conan_setup_link\",\n                lua_content=PREMAKE_TEMPLATE_ROOT_LINK,\n                filter_call=\"\\n\".join(\n                    [\"\\n\".join(self._premake_filtered(\n                        [f'conan_setup_link(\"{config}\")'], config.split(\"_\", 1)[0], config.split(\"_\", 1)[1], 2)\n                    ) for config in config_sets]\n                )\n            ),\n            PREMAKE_TEMPLATE_ROOT_GLOBAL\n        ])\n\n        # Output configuration file for the current build configuration\n        self._output_lua_file(PREMAKE_CONFIG_FILE.format(config=conf_name), [\n            PREMAKE_TEMPLATE_CONFIG.format(\n                config=conf_name, order=\", \".join(f'\"{name}\"' for name in reversed(dep_names))\n            )\n        ])\n\n        # Output root configuration file\n        available_config_files = glob.glob(PREMAKE_CONFIG_FILE.format(config=\"*\"))\n        available_configs = [file_name.split(\"_\", 1)[1].split(\".\")[0] for file_name in available_config_files]\n        available_configs.append(conf_name)\n        self._output_lua_file(PREMAKE_CONFIG_ROOT_FILE, [\n            *['include \"{}\"'.format(PREMAKE_CONFIG_FILE.format(config=config)) for config in available_configs],\n        ])\n\n        return self.output_files\n"
  },
  {
    "path": "conan/tools/premake/toolchain.py",
    "content": "from conan.tools.build.flags import architecture_flag, architecture_link_flag, libcxx_flags, threads_flags\nimport os\nimport textwrap\nfrom pathlib import Path\n\nfrom conan.tools.env.virtualbuildenv import VirtualBuildEnv\nfrom jinja2 import Template\n\nfrom conan.tools.build.cross_building import cross_building\nfrom conan.tools.files import save\nfrom conan.tools.microsoft.visual import VCVars\nfrom conan.tools.premake.premakedeps import PREMAKE_ROOT_FILE\n\n\ndef _generate_flags(self, conanfile):\n    template = textwrap.dedent(\n        \"\"\"\\\n        {% if extra_cflags %}\n        -- C flags retrieved from CFLAGS environment, conan.conf(tools.build:cflags), extra_cflags and compiler settings\n        filter { files { \"**.c\" } }\n            buildoptions { {{ extra_cflags }} }\n        filter {}\n        {% endif %}\n        {% if extra_cxxflags %}\n        -- CXX flags retrieved from CXXFLAGS environment, conan.conf(tools.build:cxxflags), extra_cxxflags and compiler settings\n        filter { files { \"**.cpp\", \"**.cxx\", \"**.cc\" } }\n            buildoptions { {{ extra_cxxflags }} }\n        filter {}\n        {% endif %}\n        {% if extra_ldflags %}\n        -- Link flags retrieved from LDFLAGS environment, conan.conf(tools.build:sharedlinkflags), conan.conf(tools.build:exelinkflags), extra_cxxflags and compiler settings\n        linkoptions { {{ extra_ldflags }} }\n        {% endif %}\n        {% if extra_rcflags %}\n        -- RC flags retrieved from conan.conf(tools.build:rcflags)\n        filter { files { \"**.rc\" } }\n            buildoptions { {{ extra_rcflags }} }\n        filter {}\n        {% endif %}\n        {% if extra_defines %}\n        -- Defines retrieved from DEFINES environment, conan.conf(tools.build:defines) and extra_defines\n        defines { {{ extra_defines }} }\n        {% endif %}\n    \"\"\"\n    )\n\n    def format_list(items):\n        return \", \".join(f'\"{item}\"' for item in items) if items else None\n\n    def to_list(value):\n        return value if isinstance(value, list) else [value] if value else []\n\n    arch_flags = to_list(architecture_flag(self._conanfile))\n    cxx_flags, libcxx_compile_definitions = libcxx_flags(self._conanfile)\n    arch_link_flags = to_list(architecture_link_flag(self._conanfile))\n    thread_flags_list = threads_flags(self._conanfile)\n\n    extra_defines = format_list(\n        conanfile.conf.get(\"tools.build:defines\", default=[], check_type=list)\n        + self.extra_defines\n        + to_list(libcxx_compile_definitions)\n    )\n    extra_c_flags = format_list(\n        conanfile.conf.get(\"tools.build:cflags\", default=[], check_type=list)\n        + self.extra_cflags\n        + arch_flags\n        + thread_flags_list\n    )\n    extra_cxx_flags = format_list(\n        conanfile.conf.get(\"tools.build:cxxflags\", default=[], check_type=list)\n        + to_list(cxx_flags)\n        + self.extra_cxxflags\n        + arch_flags\n        + thread_flags_list\n    )\n    extra_ld_flags = format_list(\n        conanfile.conf.get(\"tools.build:sharedlinkflags\", default=[], check_type=list)\n        + conanfile.conf.get(\"tools.build:exelinkflags\", default=[], check_type=list)\n        + self.extra_ldflags\n        + arch_flags\n        + arch_link_flags\n        + thread_flags_list\n    )\n    extra_rc_flags = format_list(conanfile.conf.get(\"tools.build:rcflags\", default=[], check_type=list))\n\n    return (\n        Template(template, trim_blocks=True, lstrip_blocks=True)\n        .render(\n            extra_defines=extra_defines,\n            extra_cflags=extra_c_flags,\n            extra_cxxflags=extra_cxx_flags,\n            extra_ldflags=extra_ld_flags,\n            extra_rcflags=extra_rc_flags,\n        )\n        .strip()\n    )\n\n\nclass _PremakeProject:\n    _premake_project_template = textwrap.dedent(\n        \"\"\"\\\n    project \"{{ name }}\"\n        {% if kind %}\n        kind \"{{ kind }}\"\n        {% endif %}\n        {% if flags %}\n    {{ flags | indent(indent_level, first=True) }}\n        {% endif %}\n    \"\"\"\n    )\n\n    def __init__(self, name, conanfile) -> None:\n        self.name = name\n        self.kind = None\n        self.extra_cxxflags = []\n        self.extra_cflags = []\n        self.extra_ldflags = []\n        self.extra_defines = []\n        self.disable = False\n        self._conanfile = conanfile\n\n    def _generate(self):\n        \"\"\"Generates project block\"\"\"\n        flags_content = _generate_flags(self, self._conanfile)  # Generate flags specific to this project\n        return Template(self._premake_project_template, trim_blocks=True, lstrip_blocks=True).render(\n            name=self.name,\n            kind=\"None\" if self.disable else self.kind,\n            flags=flags_content,\n            indent_level=4,\n        )\n\n\nclass PremakeToolchain:\n    \"\"\"\n    PremakeToolchain generator\n    \"\"\"\n\n    filename = \"conantoolchain.premake5.lua\"\n    # Keep template indented correctly for Lua output\n    _premake_file_template = textwrap.dedent(\n        \"\"\"\\\n    #!lua\n    -- Conan auto-generated toolchain file\n    {% if has_conan_deps %}\n    -- Include conandeps.premake5.lua with Conan dependency setup\n    include(\"conandeps.premake5.lua\")\n    {% endif %}\n\n    -- Base build directory\n    local locationDir = path.normalize(\"{{ build_folder }}\")\n\n    -- Generate workspace configurations\n    for wks in premake.global.eachWorkspace() do\n        workspace(wks.name)\n            -- Set base location for all workspaces\n            location(locationDir)\n            targetdir(path.join(locationDir, \"bin\"))\n            objdir(path.join(locationDir, \"obj\"))\n\n            {% if cppstd %}\n            cppdialect \"{{ cppstd }}\"\n            {% endif %}\n            {% if cstd %}\n            cdialect \"{{ cstd }}\"\n            {% endif %}\n            {% if shared != None %}\n            -- IMPORTANT: this global setting will only apply `project`s which do not have `kind` set.\n            -- IMPORTANT: This will not override existing `kind` set in `project` block.\n            -- To let conan take control over `kind` of the libraries, DO NOT SET `kind` (StaticLib or\n            -- SharedLib) in `project` block.\n            kind \"{{ \"SharedLib\" if shared else \"StaticLib\" }}\"\n            {% endif %}\n            {% if fpic != None %}\n            -- Enable position independent code\n            pic \"{{ \"On\" if fpic else \"Off\" }}\"\n            {% endif %}\n            filter { \"architecture: not wasm64\" }\n                -- TODO: There is an issue with premake and \"wasm64\" when system is declared \"emscripten\"\n                system \"{{ target_build_os }}\"\n            filter {}\n            {% if macho_to_amd64 %}\n            -- TODO: this should be fixed by premake: https://github.com/premake/premake-core/issues/2136\n            buildoptions \"-arch x86_64\"\n            linkoptions \"-arch x86_64\"\n            {% endif %}\n            {% if target_build_os == \"emscripten\" %}\n            filter { \"system:emscripten\", \"kind:ConsoleApp or WindowedApp\" }\n                -- Replace built in .wasm extension to .js to generate also a JavaScript files\n                targetextension \".js\"\n            filter {}\n            {% endif %}\n            {% if flags %}\n    {{ flags | indent(indent_level, first=True) }}\n            {% endif %}\n\n            filter { \"system:macosx\" }\n                -- SHARED LIBS\n                -- In the future we could add an opt in configuration to run\n                -- fix_apple_shared_install_name on executables to have a similar behavior as CMake\n                -- generator. Premake does not allow adding absolute RCPATHS\n                -- Due to this limitation, if a consumer depends on a premake shared recipe, it will\n                -- require to run conanrun script to setup proper DYLD_LIBRARY_PATH\n                -- Reference: https://github.com/premake/premake-core/issues/2262#issuecomment-2378250385\n                linkoptions { \"-Wl,-rpath,@loader_path\" }\n            filter {}\n\n            conan_setup()\n    end\n\n        {% for project in projects.values() %}\n\n    {{ project._generate() }}\n        {% endfor %}\n    \"\"\"\n    )\n\n    def __init__(self, conanfile):\n        \"\"\"\n        :param conanfile: ``< ConanFile object >`` The current recipe object. Always use ``self``.\n        \"\"\"\n        self._conanfile = conanfile\n        self._projects = {}\n        # Extra flags\n        #: List of extra ``CXX`` flags. Added to ``buildoptions``.\n        self.extra_cxxflags = []\n        #: List of extra ``C`` flags. Added to ``buildoptions``.\n        self.extra_cflags = []\n        #: List of extra linker flags. Added to ``linkoptions``.\n        self.extra_ldflags = []\n        #: List of extra preprocessor definitions. Added to ``defines``.\n        self.extra_defines = []\n\n    def project(self, project_name):\n        \"\"\"\n        The returned object will also have the same properties as the workspace but will only affect\n        the project with the name.\n        :param project_name: The name of the project inside the workspace to be updated.\n        :return: ``<PremakeProject>`` object which allow to set project specific flags.\n        \"\"\"\n        if project_name not in self._projects:\n            self._projects[project_name] = _PremakeProject(project_name, self._conanfile)\n        return self._projects[project_name]\n\n    def generate(self):\n        \"\"\"\n        Creates a ``conantoolchain.premake5.lua`` file which will properly configure build paths,\n        binary paths, configuration settings and compiler/linker flags based on toolchain\n        configuration.\n        \"\"\"\n        premake_conan_deps = Path(self._conanfile.generators_folder) / PREMAKE_ROOT_FILE\n        cppstd = self._conanfile.settings.get_safe(\"compiler.cppstd\")\n        if cppstd:\n            # See premake possible cppstd values: https://premake.github.io/docs/cppdialect/\n            if cppstd.startswith(\"gnu\"):\n                cppstd = f\"gnu++{cppstd[3:]}\"\n            elif cppstd[0].isnumeric():\n                cppstd = f\"c++{cppstd}\"\n\n        compilers_build_mapping = self._conanfile.conf.get(\n            \"tools.build:compiler_executables\", default={}, check_type=dict\n        )\n        if compilers_build_mapping:\n            build_env = VirtualBuildEnv(self._conanfile, auto_generate=False)\n            env = build_env.environment()\n            if \"c\" in compilers_build_mapping:\n                env.define(\"CC\", compilers_build_mapping[\"c\"])\n            if \"cpp\" in compilers_build_mapping:\n                env.define(\"CXX\", compilers_build_mapping[\"cpp\"])\n            build_env.generate()\n\n        macho_to_amd64 = (\n            self._conanfile.settings.arch\n            if cross_building(self._conanfile) and self._conanfile.settings.os == \"Macos\"\n            else None\n        )\n\n        content = Template(self._premake_file_template, trim_blocks=True, lstrip_blocks=True).render(\n            # Pass posix path for better cross-platform compatibility in Lua\n            build_folder=Path(self._conanfile.build_folder).as_posix(),\n            has_conan_deps=premake_conan_deps.exists(),\n            cppstd=cppstd,\n            cstd=self._conanfile.settings.get_safe(\"compiler.cstd\"),\n            shared=self._conanfile.options.get_safe(\"shared\"),\n            fpic=self._conanfile.options.get_safe(\"fPIC\"),\n            target_build_os=self._target_build_os(),\n            macho_to_amd64=macho_to_amd64,\n            projects=self._projects,\n            flags=_generate_flags(self, self._conanfile),\n            indent_level=8,\n        )\n        save(\n            self,\n            os.path.join(self._conanfile.generators_folder, self.filename),\n            content,\n        )\n        # Generate VCVars if using MSVC\n        if \"msvc\" in self._conanfile.settings.compiler:\n            VCVars(self._conanfile).generate()\n\n    def _target_build_os(self):\n        conan_os = str(self._conanfile.settings.os)\n        if conan_os == \"Macos\":\n            return \"macosx\"\n        return conan_os.lower()\n"
  },
  {
    "path": "conan/tools/qbs/__init__.py",
    "content": "from conan.tools.qbs.qbs import Qbs\nfrom conan.tools.qbs.qbsdeps import QbsDeps\nfrom conan.tools.qbs.qbsprofile import QbsProfile\n"
  },
  {
    "path": "conan/tools/qbs/common.py",
    "content": "architecture_map = {\n    'x86': 'x86',\n    'x86_64': 'x86_64',\n    'ppc32be': 'ppc',\n    'ppc32': 'ppc',\n    'ppc64le': 'ppc64',\n    'ppc64': 'ppc64',\n    'armv4': 'arm',\n    'armv4i': 'arm',\n    'armv5el': 'arm',\n    'armv5hf': 'arm',\n    'armv6': 'arm',\n    'armv7': 'arm',\n    'armv7hf': 'arm',\n    'armv7s': 'arm',\n    'armv7k': 'arm',\n    'armv8': 'arm64',\n    'armv8_32': 'arm64',\n    'armv8.3': 'arm64',\n    'sparc': 'sparc',\n    'sparcv9': 'sparc64',\n    'mips': 'mips',\n    'mips64': 'mips64',\n    'avr': 'avr',\n    's390': 's390x',\n    's390x': 's390x',\n    'asm.js': None,\n    'wasm': None,\n    'wasm64': None,\n    'sh4le': 'sh'\n}\n\n\nbuild_variant_map = {\n    'Debug': 'debug',\n    'Release': 'release',\n    'RelWithDebInfo': 'profiling',\n    'MinSizeRel': 'release'\n}\n\n\noptimization_map = {\n    'MinSizeRel': 'small'\n}\n\n\ncxx_language_version_map = {\n    '98': 'c++98',\n    'gnu98': 'c++98',\n    '11': 'c++11',\n    'gnu11': 'c++11',\n    '14': 'c++14',\n    'gnu14': 'c++14',\n    '17': 'c++17',\n    'gnu17': 'c++17',\n    '20': 'c++20',\n    'gnu20': 'c++20'\n}\n\n\ntarget_platform_map = {\n    'Windows': 'windows',\n    'WindowsStore': 'windows',\n    'WindowsCE': 'windows',\n    'Linux': 'linux',\n    'Macos': 'macos',\n    'Android': 'android',\n    'iOS': 'ios',\n    'watchOS': 'watchos',\n    'tvOS': 'tvos',\n    'visionOS': 'xros',\n    'FreeBSD': 'freebsd',\n    'SunOS': 'solaris',\n    'AIX': 'aix',\n    'Emscripten': None,\n    'Arduino': 'none',\n    'Neutrino': 'qnx',\n}\n\n\nruntime_library_map = {\n    'static': 'static',\n    'dynamic': 'dynamic',\n    'MD': 'dynamic',\n    'MT': 'static',\n    'MDd': 'dynamic',\n    'MTd': 'static',\n}\n"
  },
  {
    "path": "conan/tools/qbs/qbs.py",
    "content": "import os\nimport shutil\n\nfrom conan.tools.build import build_jobs, cmd_args_to_string\nfrom conan.errors import ConanException\n\ndef _configuration_dict_to_commandlist(name, config_dict):\n    command_list = ['config:%s' % name]\n    for key, value in config_dict.items():\n        if type(value) is bool:\n            if value:\n                b = 'true'\n            else:\n                b = 'false'\n            command_list.append('%s:%s' % (key, b))\n        else:\n            command_list.append('%s:%s' % (key, value))\n    return command_list\n\n\nclass Qbs:\n    \"\"\"\n    Qbs helper to use together with the QbsDeps feature.\n    This class provides helper methods that wraps calls to the Qbs tool.\n    \"\"\"\n    def __init__(self, conanfile, project_file=None):\n        \"\"\"\n        :param conanfile: The current recipe object. Always use ``self``.\n        :param project_file: The name to the main project file. If not set, Qbs will try to\n            autodetect the project file.\n        \"\"\"\n        self.profile = None\n        self._conanfile = conanfile\n        self._set_project_file(project_file)\n        self.jobs = build_jobs(conanfile)\n        self._configuration = dict()\n\n    def _set_project_file(self, project_file):\n        if not project_file:\n            self._project_file = self._conanfile.source_folder\n        else:\n            self._project_file = project_file\n\n        if not os.path.exists(self._project_file):\n            raise ConanException('Qbs: could not find project file %s' % self._project_file)\n\n    def add_configuration(self, name, values):\n        \"\"\"\n        Adds a build configuration for the multi-configuration build.\n        This Qbs feature is rarely needed since each conan package can contain only one\n        configuration, however might be useful when creating multiple versions of the same product\n        that should be put in the same Conan package.\n\n        :param name: the name of the configuration. This corresponds to the ``config`` parameter\n            of ``qbs resolve``, ``qbs build`` and ``qbs install`` commands.\n        :param values: the dict containing Qbs properties and their values for this configuration.\n        \"\"\"\n        self._configuration[name] = values\n\n    def _qbs_settings_paths(self):\n        generators_folder = self._conanfile.generators_folder\n        qbs_settings_path = os.path.join(generators_folder, 'qbs_settings.txt')\n        if not os.path.exists(qbs_settings_path):\n            return None, None\n        return os.path.join(generators_folder, 'conan-qbs-settings-dir'), qbs_settings_path\n\n    def _get_common_arguments(self):\n        args = []\n        settings_dir, _ = self._qbs_settings_paths()\n        if settings_dir is not None:\n            args.extend(['--settings-dir', settings_dir])\n        args.extend([\n            '--build-directory', self._conanfile.build_folder,\n            '--file', self._project_file,\n        ])\n        return args\n\n    def resolve(self, parallel=True):\n        \"\"\"\n        Wraps the ``qbs resolve`` call.\n        If QbsDeps generator is used, this will also set the necessary properites of the Qbs\n        \"conan\" module provider automatically adding dependencies to the project.\n        :param parallel: Whether to use multi-threaded resolving. Defaults to ``True``.\n        \"\"\"\n        generators_folder = self._conanfile.generators_folder\n        settings_dir, settings_path = self._qbs_settings_paths()\n        if settings_dir is not None:\n            shutil.rmtree(settings_dir, ignore_errors=True)\n            import_args = ['--settings-dir', settings_dir, '--import', settings_path]\n            import_cmd = 'qbs config  %s' % cmd_args_to_string(import_args)\n            self._conanfile.run(import_cmd)\n\n        args = self._get_common_arguments()\n\n        if parallel:\n            args.extend(['--jobs', '%s' % self.jobs])\n        else:\n            args.extend(['--jobs', '1'])\n\n        if self.profile:\n            args.append('profile:%s' % self.profile)\n\n        if os.path.exists(os.path.join(generators_folder, 'conan-qbs-deps')):\n            args.append('moduleProviders.conan.installDirectory:' + generators_folder)\n\n        for name in self._configuration:\n            config = self._configuration[name]\n            args.extend(_configuration_dict_to_commandlist(name, config))\n\n        cmd = 'qbs resolve %s' % cmd_args_to_string(args)\n        self._conanfile.run(cmd)\n\n    def _build(self, products, all_products):\n\n        args = self._get_common_arguments()\n        args.append('--no-install')\n\n        if all_products:\n            args.append('--all-products')\n        elif products:\n            args.extend(['--products', ','.join(products or [])])\n\n        args.extend(['--jobs', '%s' % self.jobs])\n\n        for name in self._configuration:\n            args.append('config:%s' % name)\n\n        cmd = 'qbs build %s' % cmd_args_to_string(args)\n        self._conanfile.run(cmd)\n\n    def build(self, products=None):\n        \"\"\"\n        Wraps the ``qbs build`` call.\n\n        :param products: The list of product names to build. If not set, builds all products that\n            have builtByDefault set to true. This parameter corresponds to the ``--products``\n            option of the ``qbs build`` command.\n\n        The resolve() method should be called before calling this method.\n        \"\"\"\n        return self._build(products=products, all_products=False)\n\n    def build_all(self):\n        \"\"\"\n        Wraps the ``qbs build --all-products`` call.\n        This method builds all products, even if their builtByDefault property is false.\n        The resolve() method should be called before calling this method.\n        \"\"\"\n        return self._build(products=None, all_products=True)\n\n    def install(self):\n        \"\"\"\n        Wraps the ``qbs install`` call.\n        Perfoms the installation of files marked as installable in the Qbs project.\n        The build() or build_all() methods should be called before calling this method.\n        \"\"\"\n        args = self._get_common_arguments()\n        args.extend(['--no-build', '--install-root', self._conanfile.package_folder])\n\n        for name in self._configuration:\n            args.append('config:%s' % name)\n\n        cmd = 'qbs install %s' % cmd_args_to_string(args)\n        self._conanfile.run(cmd)\n"
  },
  {
    "path": "conan/tools/qbs/qbsdeps.py",
    "content": "from conan.tools.files import save\nfrom conan.errors import ConanException\nfrom conan.internal.model.dependencies import get_transitive_requires\nimport json\nimport os\n\n\nclass _QbsDepsModuleFile:\n    def __init__(self, qbsdeps, dep, component, deps, module_name):\n        self._qbsdeps = qbsdeps\n        self._dep = dep\n        self._component = component\n        self._deps = deps\n        self._module_name = module_name\n        self._build_bindirs = qbsdeps._build_bindirs\n        self._version = (component.get_property(\"component_version\") or\n                         component.get_property(\"system_package_version\") or\n                         dep.ref.version)\n\n    @property\n    def filename(self):\n        return self._module_name + '.json'\n\n    @property\n    def version(self):\n        return self._version\n\n    def get_content(self):\n        cpp_info_attrs = [\n            'includedirs', 'srcdirs', 'libdirs', 'resdirs', 'bindirs', 'builddirs',\n            'frameworkdirs', 'system_libs', 'frameworks', 'libs', 'defines', 'cflags', 'cxxflags',\n            'sharedlinkflags', 'exelinkflags', 'objects', 'sysroot'\n        ]\n        return {\n            'package_name': self._dep.ref.name,\n            'package_dir': self._get_package_dir(),\n            'version': str(self._version),\n            'cpp_info': {k : getattr(self._component, k) for k in cpp_info_attrs},\n            'build_bindirs': self._build_bindirs,\n            'dependencies': [{'name': n, \"version\": str(v)} for n, v in self._deps],\n            'settings': {k: v for k, v in self._dep.settings.items()},\n            'options': {k: v for k, v in self._dep.options.items()}\n        }\n\n    def _get_package_dir(self):\n        # If editable, package_folder can be None\n        root_folder = self._dep.recipe_folder if self._dep.package_folder is None \\\n            else self._dep.package_folder\n        return root_folder.replace(\"\\\\\", \"/\")\n\n    def render(self):\n        return json.dumps(self.get_content(), indent=4)\n\n\nclass _QbsDepGenerator:\n    \"\"\" Handles a single package, can create multiple modules in case of several components\n    \"\"\"\n    def __init__(self, conanfile, dep, build_bindirs):\n        self._conanfile = conanfile\n        self._dep = dep\n        self._build_bindirs = build_bindirs\n\n    @property\n    def content(self):\n        qbs_files = {}\n        transitive_reqs = get_transitive_requires(self._conanfile, self._dep)\n\n        def _get_package_name(dep):\n            # TODO: pkgconfig uses suffix, do we need it? see:\n            # https://github.com/conan-io/conan/blob/develop2/conan/tools/gnu/pkgconfigdeps.py#L319\n            return dep.cpp_info.get_property(\"pkg_config_name\") or dep.ref.name\n\n        def _get_component_name(dep, comp_name):\n            if comp_name not in dep.cpp_info.components:\n                if dep.ref.name == comp_name:\n                    return _get_package_name(dep)\n                raise ConanException(\"Component '{name}::{cname}' not found in '{name}' \"\n                                     \"package requirement\".format(name=dep.ref.name,\n                                                                  cname=comp_name))\n\n            # TODO: pkgconfig uses suffix, do we need it?\n            # We re-use pkg_config_name for compatiblitity with the Qbs pkg-config provider:\n            # in that case, Qbs/its users do not need to do additional mapping on their side\n            pkg_config_name = dep.cpp_info.components[comp_name].get_property(\"pkg_config_name\")\n            return pkg_config_name or comp_name\n\n        def _get_name_with_namespace(namespace, name):\n            \"\"\"\n            Build a name with a namespace, e.g., openssl-crypto\n            \"\"\"\n            return f\"{namespace}-{name}\"\n\n        def get_components(dep):\n            ret = {}\n            for comp_ref_name, info in dep.cpp_info.get_sorted_components().items():\n                comp_name = _get_component_name(dep, comp_ref_name)\n                ret[comp_name] = info\n            return ret\n\n        # copy & paste from pkgconfig deps\n        def get_cpp_info_requires_names(dep, cpp_info):\n            ret = []\n            dep_ref_name = dep.ref.name\n            for req in cpp_info.requires:\n                pkg_ref_name, comp_ref_name = (\n                    req.split(\"::\") if \"::\" in req else (dep_ref_name, req)\n                )\n\n                if dep_ref_name != pkg_ref_name:\n                    try:\n                        req_conanfile = transitive_reqs[pkg_ref_name]\n                    except KeyError:\n                        # If the dependency is not in the transitive, might be skipped\n                        continue\n                # For instance, dep == \"hello/1.0\" and req == \"hello::cmp1\" -> hello == hello\n                else:\n                    req_conanfile = dep\n\n                comp_name = _get_component_name(req_conanfile, comp_ref_name)\n                if not comp_name:\n                    pkg_name = _get_package_name(req_conanfile)\n                    # Creating a component name with namespace, e.g., dep-comp1\n                    comp_name = _get_name_with_namespace(pkg_name, comp_ref_name)\n                ret.append((comp_name, req_conanfile.ref.version))\n            return ret\n\n        if not self._dep.cpp_info.has_components:\n            module_name = _get_package_name(self._dep)\n            requires = get_cpp_info_requires_names(self._dep, self._dep.cpp_info)\n            if not requires:\n                # If no requires were found, let's try to get all the direct visible\n                # dependencies, e.g., requires = \"other_pkg/1.0\"\n                for deprequire, _ in self._dep.dependencies.direct_host.items():\n                    requires.append((deprequire.ref.name, deprequire.ref.version))\n            file = _QbsDepsModuleFile(\n                self, self._dep, self._dep.cpp_info, requires, module_name\n            )\n            qbs_files[file.filename] = file\n        else:\n            full_requires = []\n            for module_name, component in get_components(self._dep).items():\n                requires = get_cpp_info_requires_names(self._dep, component)\n                file = _QbsDepsModuleFile(self, self._dep, component, requires, module_name)\n                qbs_files[file.filename] = file\n                full_requires.append((module_name, file.version))\n            module_name = _get_package_name(self._dep)\n            file = _QbsDepsModuleFile(\n                self, self._dep, self._dep.cpp_info, full_requires, module_name)\n            # We create the root package's module file ONLY\n            # if it does not already exist in components\n            # An example is a grpc package where they have a \"grpc\" component\n            if file.filename not in qbs_files:\n                qbs_files[file.filename] = file\n\n        return qbs_files\n\n\nclass QbsDeps:\n    \"\"\"\n    This class will generate a JSON file for each dependency inside the \"conan-qbs-deps\" folder.\n    Each JSON file contains information necesary for Qbs ``\"conan\" module provider`` to be\n    able to generate Qbs module files.\n    \"\"\"\n    def __init__(self, conanfile):\n        \"\"\"\n        :param conanfile: The current recipe object. Always use ``self``.\n        \"\"\"\n        self._conanfile = conanfile\n\n    @property\n    def content(self):\n        \"\"\"\n        Returns all dependency information as a Python dict object where key is the dependency\n        name and value is a dict with dependency properties.\n        \"\"\"\n        qbs_files = {}\n\n        build_bindirs = {\n            dep.ref.name: dep.cpp_info.bindirs\n            for _, dep in self._conanfile.dependencies.build.items()}\n\n        for require, dep in self._conanfile.dependencies.items():\n\n            # skip build deps for now\n            if require.build:\n                continue\n\n            dep_build_bindirs = build_bindirs.get(dep.ref.name, [])\n            qbs_files.update(_QbsDepGenerator(self._conanfile, dep, dep_build_bindirs).content)\n        return qbs_files\n\n    def generate(self):\n        \"\"\"\n        This method will save the generated files to the \"conan-qbs-deps\" directory inside the\n        ``conanfile.generators_folder`` directory.\n        Generates a single JSON file per dependency or component.\n        \"\"\"\n        for file_name, qbs_deps_file in self.content.items():\n            save(self._conanfile, os.path.join('conan-qbs-deps', file_name), qbs_deps_file.render())\n"
  },
  {
    "path": "conan/tools/qbs/qbsprofile.py",
    "content": "import os\nimport shutil\nimport platform\nimport textwrap\n\nfrom jinja2 import Template\nfrom conan.internal import check_duplicated_generator\nfrom conan.errors import ConanException\nfrom conan.tools.env import VirtualBuildEnv\nfrom conan.tools.microsoft import msvs_toolset\nfrom conan.tools.microsoft.visual import vs_installation_path, _vcvars_path, _vcvars_versions\nfrom conan.tools.qbs import common\nfrom conan.internal.util.files import save\n\n\ndef _find_msvc(conanfile):\n    vs_install_path = conanfile.conf.get(\"tools.microsoft.msbuild:installation_path\")\n    vs_version, vcvars_ver = _vcvars_versions(conanfile)\n    vs_path = vs_install_path or vs_installation_path(vs_version)\n    if vs_path is None or vs_version is None:\n        return None\n\n    vc_install_dir = os.path.join(vs_path, 'VC', 'Tools', 'MSVC')\n    if not os.path.exists(vc_install_dir):\n        return None\n    compiler_versions = [v for v in os.listdir(vc_install_dir) if v.startswith(vcvars_ver)]\n    compiler_versions.sort(reverse=True)\n\n    build_arch_map = {\n        'x86': 'Hostx86',\n        'x86_64': 'Hostx64',\n        'armv6': 'arm',\n        'armv7': 'arm',\n        'armv8': 'arm64',\n    }\n    host_arch_map = {\n        'x86': 'x86',\n        'x86_64': 'x64',\n        'armv6': 'arm',\n        'armv7': 'arm',\n        'armv8': 'arm64',\n    }\n    build_arch = build_arch_map.get(str(conanfile.settings_build.arch))\n\n    host_arch = host_arch_map.get(str(conanfile.settings.arch))\n\n    if not host_arch or not build_arch:\n        return None\n\n    def cl_path(version):\n        return os.path.join(vc_install_dir, version, 'bin', build_arch, host_arch, 'cl.exe')\n\n    compiler_paths = [cl_path(version) for version in compiler_versions]\n    compiler_paths = [p for p in compiler_paths if os.path.exists(p)]\n\n    if len(compiler_paths) == 0:\n        return None\n\n    return compiler_paths[0]\n\n\ndef _find_clangcl(conanfile):\n    vs_install_path = conanfile.conf.get(\"tools.microsoft.msbuild:installation_path\")\n    vs_version, _ = _vcvars_versions(conanfile)\n    vs_path = vs_install_path or vs_installation_path(vs_version)\n\n    compiler_path = os.path.join(vs_path, 'VC', 'Tools', 'Llvm', 'bin', 'clang-cl.exe')\n    vcvars_path = _vcvars_path(vs_version, vs_install_path)\n    if not os.path.exists(compiler_path):\n        return None\n    return compiler_path, vcvars_path\n\n\nclass _LinkerFlagsParser:\n    def __init__(self, ld_flags):\n        self.driver_linker_flags = []\n        self.linker_flags = []\n\n        for item in ld_flags:\n            if item.startswith('-Wl'):\n                self.linker_flags.extend(item.split(',')[1:])\n            else:\n                self.driver_linker_flags.append(item)\n\n\nclass QbsProfile:\n    \"\"\"\n    Qbs profiles generator.\n\n    This class generates file with the toolchain information that can be imported by Qbs.\n    \"\"\"\n\n    def __init__(self, conanfile, profile='conan', default_profile='conan'):\n        \"\"\"\n        :param conanfile: The current recipe object. Always use ``self``.\n        :param profile: The name of the profile in settings. Defaults to ``\"conan\"``.\n        :param default_profile: The name of the default profile. Defaults to ``\"conan\"``.\n\n        \"\"\"\n        self._conanfile = conanfile\n        self._profile = profile\n        self._default_profile = default_profile\n\n        self.extra_cflags = []\n        self.extra_cxxflags = []\n        self.extra_defines = []\n        self.extra_sharedlinkflags = []\n        self.extra_exelinkflags = []\n\n        self._build_env = VirtualBuildEnv(self._conanfile, auto_generate=True).vars()\n\n    @property\n    def filename(self):\n        \"\"\"\n        The name of the generated file. Returns ``qbs_settings.txt``.\n        \"\"\"\n        return 'qbs_settings.txt'\n\n    @property\n    def content(self):\n        \"\"\"\n        Returns the content of the settings file as dict of Qbs properties.\n        \"\"\"\n        result = self._toolchain_properties()\n        result.update(self._properties_from_settings())\n        result.update(self._properties_from_conf())\n        result.update(self._properties_from_options())\n        # result.update(self._properties_from_env(self._build_env))\n        return result\n\n    def render(self):\n        \"\"\"\n        Returns the content of the settings file as string.\n        \"\"\"\n        template = textwrap.dedent('''\\\n            {%- for key, value in profile_values.items() %}\n            profiles.{{profile}}.{{ key }}:{{ value }}\n            {%- endfor %}\n            defaultProfile: {{default_profile}}\n        ''')\n        t = Template(template)\n        context = {\n            'profile_values': self.content,\n            'profile': self._profile,\n            'default_profile': self._default_profile,\n        }\n        result = t.render(**context)\n        return result\n\n    def generate(self):\n        \"\"\"\n        This method will save the generated files to the conanfile.generators_folder.\n\n        Generates the \"qbs_settings.txt\" file. This file contains Qbs settings such as toolchain\n        properties and can be imported using ``qbs config --import``.\n        \"\"\"\n        check_duplicated_generator(self, self._conanfile)\n        self._check_for_compiler()\n        save(self.filename, self.render())\n\n    def _check_for_compiler(self):\n        compiler = self._conanfile.settings.get_safe('compiler')\n        if not compiler:\n            raise ConanException('Qbs: need compiler to be set in settings')\n\n        if compiler not in ['msvc', 'gcc', 'clang', 'apple-clang']:\n            raise ConanException(f'Qbs: compiler {compiler} not supported')\n\n    def _get_qbs_toolchain(self):\n        compiler = self._conanfile.settings.get_safe('compiler')\n        the_os = self._conanfile.settings.get_safe('os')\n        if the_os == 'Windows':\n            if compiler == 'msvc':\n                if msvs_toolset(self._conanfile) == 'ClangCL':\n                    return 'clang-cl'\n                return 'msvc'\n            if compiler == 'gcc':\n                return 'mingw'\n            if compiler == 'clang':\n                return 'clang-cl'\n            raise ConanException('unknown windows compiler')\n        if compiler == 'apple-clang':\n            return 'xcode'\n        # todo: other compilers?\n        return compiler\n\n    def _default_compiler_names(self, toolchain):\n        if toolchain == 'msvc':\n            return 'cl', 'cl'\n        if toolchain == 'clang-cl':\n            return 'clang-cl', 'clang-cl'\n        if toolchain in ('gcc', 'mingw'):\n            return 'gcc', 'g++'\n        if toolchain in ('clang', 'xcode'):\n            return 'clang', 'clang++'\n\n        # what about other toolchains? IAR, Cosmic have a bunch of compilers based on arch\n        return toolchain, toolchain\n\n    def _find_exe(self, exe):\n        if platform.system() == 'Windows':\n            exe = exe + '.exe'\n        if os.path.isabs(exe):\n            return exe\n        paths = self._build_env.get(\"PATH\", \"\")\n        for p in paths.split(os.pathsep):\n            path = os.path.join(p, exe)\n            if os.path.exists(path):\n                return path\n        return shutil.which(exe)\n\n    def _toolchain_properties(self):\n        toolchain = self._get_qbs_toolchain()\n        the_os = self._conanfile.settings.get_safe('os')\n        vcvars_path = None\n        if the_os == 'Windows' and toolchain == 'msvc':\n            compiler = _find_msvc(self._conanfile)\n        elif the_os == 'Windows' and toolchain == 'clang-cl':\n            compiler, vcvars_path = _find_clangcl(self._conanfile)\n        else:\n            # TODO: use CC also for msvc?\n            c_compiler_default, cxx_compiler_default = self._default_compiler_names(toolchain)\n            compilers_by_conf = self._conanfile.conf.get(\"tools.build:compiler_executables\",\n                                                         default={}, check_type=dict)\n            c_compiler = (\n                compilers_by_conf.get(\"c\") or self._build_env.get(\"CC\") or c_compiler_default)\n            c_compiler = self._find_exe(c_compiler)\n\n            cxx_compiler = (\n                compilers_by_conf.get(\"cpp\") or self._build_env.get(\"CXX\") or cxx_compiler_default)\n            cxx_compiler = self._find_exe(cxx_compiler)\n            compiler = cxx_compiler or c_compiler\n        if compiler is None:\n            raise ConanException('cannot find compiler')\n\n        result = {\n            'qbs.toolchainType': toolchain,\n            'cpp.compilerName': os.path.basename(compiler),\n            'cpp.toolchainInstallPath': os.path.dirname(compiler).replace('\\\\', '/')\n        }\n        # GCC and friends also have separate props for compilers\n        gcc_toolchains = ['clang', 'gcc', 'llvm', 'mingw', 'qcc', 'xcode']\n        if toolchain in gcc_toolchains:\n            result['cpp.cCompilerName'] = os.path.basename(c_compiler)\n            result['cpp.cxxCompilerName'] = os.path.basename(cxx_compiler)\n        if vcvars_path:\n            result[\"cpp.vcvarsallPath\"] = vcvars_path\n        return result\n\n    def _properties_from_settings(self):\n        result = {}\n\n        def map_qbs_property(key, qbs_property, value_map, fallback=None):\n            value = value_map.get(self._conanfile.settings.get_safe(key)) or fallback\n            if value is not None:\n                result[qbs_property] = value\n\n        map_qbs_property('arch', 'qbs.architecture', common.architecture_map)\n        map_qbs_property('os', 'qbs.targetPlatform', common.target_platform_map, \"undefined\")\n        map_qbs_property('build_type', 'qbs.buildVariant', common.build_variant_map)\n        map_qbs_property(\n            'compiler.cppstd', 'cpp.cxxLanguageVersion', common.cxx_language_version_map)\n        map_qbs_property('compiler.runtime', 'cpp.runtimeLibrary', common.runtime_library_map)\n\n        return result\n\n    def _properties_from_options(self):\n        result = {}\n\n        def maybe_bool_str(b):\n            return None if b is None else str(b).lower()\n\n        fpic = maybe_bool_str(self._conanfile.options.get_safe('fPIC'))\n        if fpic:\n            result[\"cpp.positionIndependentCode\"] = fpic\n\n        return result\n\n    def _properties_from_conf(self):\n        result = {}\n\n        def map_list_property(key, qbs_property, extra):\n            value = self._conanfile.conf.get(key, default=[], check_type=list)\n            value.extend(extra)\n            if len(value) > 0:\n                result[qbs_property] = value\n\n        map_list_property(\"tools.build:cflags\", \"cpp.cFlags\", self.extra_cflags)\n        map_list_property(\"tools.build:cxxflags\", \"cpp.cxxFlags\", self.extra_cxxflags)\n        map_list_property(\"tools.build:rcflags\", \"cpp.rcFlags\", [])\n        map_list_property(\"tools.build:defines\", \"cpp.defines\", self.extra_defines)\n\n        def ldflags():\n            conf = self._conanfile.conf\n            result = conf.get(\"tools.build:sharedlinkflags\", default=[], check_type=list)\n            result.extend(self.extra_sharedlinkflags)\n            result.extend(conf.get(\"tools.build:exelinkflags\", default=[], check_type=list))\n            result.extend(self.extra_exelinkflags)\n            linker_scripts = conf.get(\"tools.build:linker_scripts\", default=[], check_type=list)\n            result.extend([\"-T'\" + linker_script + \"'\" for linker_script in linker_scripts])\n            return result\n\n        ld_flags = ldflags()\n        if len(ld_flags) > 0:\n            parser = _LinkerFlagsParser(ld_flags)\n            result['cpp.linkerFlags'] = parser.linker_flags\n            result['cpp.driverLinkerFlags'] = parser.driver_linker_flags\n\n        sysroot = self._conanfile.conf.get(\"tools.build:sysroot\")\n        if sysroot is not None:\n            sysroot = sysroot.replace(\"\\\\\", \"/\")\n            result['qbs.sysroot'] = sysroot\n\n        return result\n"
  },
  {
    "path": "conan/tools/ros/__init__.py",
    "content": "from conan.tools.ros.rosenv import ROSEnv\n"
  },
  {
    "path": "conan/tools/ros/rosenv.py",
    "content": "import os\nfrom conan.api.output import Color\nfrom conan.tools.env import Environment\nfrom conan.tools.env.environment import create_env_script\n\n\nclass ROSEnv:\n    \"\"\"\n    Generator to serve as integration for Robot Operating System 2 development workspaces.\n\n    IMPORTANT: This generator should be used together with CMakeDeps and CMakeToolchain generators.\n    \"\"\"\n\n    def __init__(self, conanfile):\n        \"\"\"\n        :param conanfile: ``< ConanFile object >`` The current recipe object. Always use ``self``.\n        \"\"\"\n        self._conanfile = conanfile\n        self.variables = {}\n        self._build_script_sh_file = \"conanrosenv-build.sh\"\n        self._build_script_bat_file = \"conanrosenv-build.bat\"\n        self._wrapper_script_sh_file = \"conanrosenv.sh\"\n        self._wrapper_script_bat_file = \"conanrosenv.bat\"\n\n    def generate(self):\n        \"\"\"\n        Creates a ``conanrosenv.sh`` with the environment variables that are needed to build and\n        execute ROS packages with Conan dependencies.\n        \"\"\"\n        cmake_toolchain_path = os.path.join(self._conanfile.generators_folder,\n                                            \"conan_toolchain.cmake\")\n        self.variables[\"CMAKE_TOOLCHAIN_FILE\"] = cmake_toolchain_path\n        build_type = self._conanfile.settings.get_safe(\"build_type\")\n        if build_type:\n            self.variables[\"CMAKE_BUILD_TYPE\"] = build_type\n\n        # Add ROS required variables to VirtualBuildEnv\n        rosbuildenv = Environment()\n        for k, v in self.variables.items():\n            rosbuildenv.define(k, v)\n        for build_script_file in [self._build_script_sh_file, self._build_script_bat_file]:\n            rosbuildenv.vars(self._conanfile, \"build\").save_script(build_script_file)\n\n        # TODO: Add powrshell support generating .ps1 files\n        self._generate_sh_files()\n        self._generate_bat_files()\n\n    def _generate_sh_files(self):\n        # Generate conanrosenv.sh script wrapper that calls conanbuild.sh and conanrun.sh\n        conanbuild_sh_path = os.path.join(self._conanfile.generators_folder, \"conanbuild.sh\")\n        conanrun_sh_path = os.path.join(self._conanfile.generators_folder, \"conanrun.sh\")\n        rosenv_sh_wrapper_content = [f\". \\\"{conanbuild_sh_path}\\\"\", f\". \\\"{conanrun_sh_path}\\\"\"]\n        create_env_script(self._conanfile, \"\\n\".join(rosenv_sh_wrapper_content),\n                          self._wrapper_script_sh_file, None)\n\n        conanrosenv_path = os.path.join(self._conanfile.generators_folder,\n                                        self._wrapper_script_sh_file)\n        msg = f\"Generated ROSEnv Conan file: {self._wrapper_script_sh_file}\\n\" + \\\n              f\"Use 'source {conanrosenv_path}' to set the ROSEnv Conan before 'colcon build'\"\n        self._conanfile.output.info(msg, fg=Color.CYAN)\n\n    def _generate_bat_files(self):\n        # Generate conanrosenv.bat script wrapper that calls conanbuild.bat and conanrun.bat\n        conanbuild_bat_path = os.path.join(self._conanfile.generators_folder, \"conanbuild.bat\")\n        conanrun_bat_path = os.path.join(self._conanfile.generators_folder, \"conanrun.bat\")\n        rosenv_bat_wrapper_content = [\n            \"@echo off\",\n            f\"CALL \\\"{conanbuild_bat_path}\\\"\",\n            f\"CALL \\\"{conanrun_bat_path}\\\"\"\n            ]\n        create_env_script(self._conanfile, \"\\n\".join(rosenv_bat_wrapper_content),\n                          self._wrapper_script_bat_file, None)\n\n        conanrosenv_path = os.path.join(self._conanfile.generators_folder,\n                                        self._wrapper_script_bat_file)\n        msg = f\"Generated ROSEnv Conan file: {self._wrapper_script_bat_file}\\n\" + \\\n              f\"Use 'call {conanrosenv_path}' to set the ROSEnv Conan before 'colcon build'\"\n        self._conanfile.output.info(msg, fg=Color.CYAN)\n"
  },
  {
    "path": "conan/tools/sbom/__init__.py",
    "content": "from conan.tools.sbom.cyclonedx import cyclonedx_1_4, cyclonedx_1_6\n"
  },
  {
    "path": "conan/tools/sbom/cyclonedx.py",
    "content": "from conan import conan_version\n\n\ndef cyclonedx_1_4(conanfile, name=None, add_build=False, add_tests=False, **kwargs):\n    \"\"\"\n    (Experimental) Generate cyclone 1.4 SBOM with JSON format\n\n    Creates a CycloneDX 1.4 Software Bill of Materials (SBOM) from a given dependency graph.\n\n\n\n    Parameters:\n        conanfile: The conanfile instance.\n        name (str, optional): Custom name for the metadata field.\n        add_build (bool, optional, default=False): Include build dependencies.\n        add_tests (bool, optional, default=False): Include test dependencies.\n\n    Returns:\n        The generated CycloneDX 1.4 document as a string.\n\n    Example usage:\n    ```\n    cyclonedx_1_4(conanfile, name=\"custom_name\", add_build=True, add_test=True, **kwargs)\n    ```\n\n    \"\"\"\n    import uuid\n    import time\n    from datetime import datetime, timezone\n    graph = conanfile.subgraph\n\n    has_special_root_node = not (getattr(graph.root.ref, \"name\", False)\n                                 and getattr(graph.root.ref, \"version\", False)\n                                 and getattr(graph.root.ref, \"revision\", False))\n    special_id = str(uuid.uuid4())\n\n    name_default = getattr(graph.root.ref, \"name\", False) or \"conan-sbom\"\n    name_default += f\"/{graph.root.ref.version}\" if getattr(graph.root.ref, \"version\", False) else \"\"\n\n    nodes = [node for node in graph.nodes if should_add_node(node, add_build, add_tests)]\n    if has_special_root_node:\n        nodes = nodes[1:]\n\n    dependencies = []\n    if has_special_root_node:\n        deps = {\"ref\": special_id,\n                \"dependsOn\": [_calculate_bomref(d.dst) for d in graph.root.edges\n                              if should_add_node(d.dst, add_build, add_tests)]}\n        dependencies.append(deps)\n    for c in nodes:\n        deps = {\"ref\": _calculate_bomref(c)}\n        dep = [d for d in c.edges if should_add_node(d.dst, add_build, add_tests)]\n\n        depends_on = [_calculate_bomref(d.dst) for d in dep\n                      if should_add_node(d.dst, add_build, add_tests)]\n        if depends_on:\n            deps[\"dependsOn\"] = depends_on\n        dependencies.append(deps)\n\n    sbom_cyclonedx_1_4 = {\n        **({\"components\": [{\n            \"author\": node.conanfile.author or \"Unknown\",\n            \"bom-ref\": _calculate_bomref(node),\n            \"description\": node.conanfile.description,\n            **({\"externalReferences\": [{\n                \"type\": \"website\",\n                \"url\": node.conanfile.homepage\n            }]} if node.conanfile.homepage else {}),\n            **({\"licenses\": _calculate_licenses(node)} if node.conanfile.license else {}),\n            \"name\": node.name,\n            \"purl\": f\"pkg:conan/{node.name}@{node.ref.version}\",\n            \"type\": \"application\" if node.conanfile.package_type == \"application\" else \"library\",\n            \"version\": str(node.ref.version),\n        } for node in nodes]} if nodes else {}),\n        **({\"dependencies\": dependencies} if dependencies else {}),\n        \"metadata\": {\n            \"component\": {\n                \"author\": conanfile.author or \"Unknown\",\n                \"bom-ref\": special_id if has_special_root_node else _calculate_bomref(conanfile),\n                \"name\": name if name else name_default,\n                \"type\": \"application\" if conanfile.package_type == \"application\" else \"library\",\n            },\n            \"timestamp\": f\"{datetime.fromtimestamp(time.time(), tz=timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ')}\",\n            \"tools\": [{\n                \"externalReferences\": [{\n                    \"type\": \"website\",\n                    \"url\": \"https://github.com/conan-io/conan\"\n                }],\n                \"name\": \"Conan-io\"\n            }],\n        },\n        \"serialNumber\": f\"urn:uuid:{uuid.uuid4()}\",\n        \"bomFormat\": \"CycloneDX\",\n        \"specVersion\": \"1.4\",\n        \"version\": 1,\n    }\n    return sbom_cyclonedx_1_4\n\n\ndef cyclonedx_1_6(conanfile, name=None, add_build=False, add_tests=False, **kwargs):\n    \"\"\"\n    (Experimental) Generate cyclone 1.6 SBOM with JSON format\n\n    Creates a CycloneDX 1.6 Software Bill of Materials (SBOM) from a given dependency graph.\n\n\n\n    Parameters:\n        conanfile: The conanfile instance.\n        name (str, optional): Custom name for the metadata field.\n        add_build (bool, optional, default=False): Include build dependencies.\n        add_tests (bool, optional, default=False): Include test dependencies.\n\n    Returns:\n        The generated CycloneDX 1.6 document as a string.\n\n    Example usage:\n    ```\n    cyclonedx_1_6(conanfile, name=\"custom_name\", add_build=True, add_test=True, **kwargs)\n    ```\n\n    \"\"\"\n    import uuid\n    import time\n    from datetime import datetime, timezone\n    graph = conanfile.subgraph\n\n    has_special_root_node = not (getattr(graph.root.ref, \"name\", False)\n                                 and getattr(graph.root.ref, \"version\", False)\n                                 and getattr(graph.root.ref, \"revision\", False))\n    special_id = str(uuid.uuid4())\n\n    name_default = getattr(graph.root.ref, \"name\", False) or \"conan-sbom\"\n    name_default += f\"/{graph.root.ref.version}\" if getattr(graph.root.ref, \"version\", False) else \"\"\n\n    nodes = [node for node in graph.nodes if should_add_node(node, add_build, add_tests)]\n    if has_special_root_node:\n        nodes = nodes[1:]\n\n    dependencies = []\n    if has_special_root_node:\n        deps = {\"ref\": special_id,\n                \"dependsOn\": [_calculate_bomref(d.dst)\n                              for d in graph.root.edges\n                              if should_add_node(d.dst, add_build, add_tests)]}\n        dependencies.append(deps)\n    for c in nodes:\n        deps = {\"ref\": _calculate_bomref(c)}\n        dep = [d for d in c.edges if should_add_node(d.dst, add_build, add_tests)]\n\n        depends_on = [_calculate_bomref(d.dst) for d in dep\n                      if should_add_node(d.dst, add_build, add_tests)]\n        if depends_on:\n            deps[\"dependsOn\"] = depends_on\n        dependencies.append(deps)\n\n    sbom_cyclonedx_1_6 = {\n        **({\"components\": [{\n            **({\"authors\": [{\"name\": node.conanfile.author}]} if node.conanfile.author else {}),\n            \"bom-ref\": _calculate_bomref(node),\n            \"description\": node.conanfile.description,\n            **({\"externalReferences\": [{\n                \"type\": \"website\",\n                \"url\": node.conanfile.homepage\n            }]} if node.conanfile.homepage else {}),\n            **({\"licenses\": _calculate_licenses(node)} if node.conanfile.license else {}),\n            \"name\": node.name,\n            \"purl\": f\"pkg:conan/{node.name}@{node.ref.version}\",\n            \"type\": \"application\" if node.conanfile.package_type == \"application\" else \"library\",\n            \"version\": str(node.ref.version),\n        } for node in nodes]} if nodes else {}),\n        **({\"dependencies\": dependencies} if dependencies else {}),\n        \"metadata\": {\n            \"component\": {\n                **({\"authors\": [{\"name\": conanfile.author}]} if conanfile.author else {}),\n                \"bom-ref\": special_id if has_special_root_node else _calculate_bomref(conanfile),\n                \"name\": name if name else name_default,\n                \"type\": \"application\" if conanfile.package_type == \"application\" else \"library\"\n            },\n            \"timestamp\": f\"{datetime.fromtimestamp(time.time(), tz=timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ')}\",\n            \"tools\": {\n                \"components\": [{\n                    \"type\": \"application\",\n                    \"name\": \"Conan-io\",\n                    \"version\": str(conan_version),\n                }]\n            },\n        },\n        \"serialNumber\": f\"urn:uuid:{uuid.uuid4()}\",\n        \"bomFormat\": \"CycloneDX\",\n        \"specVersion\": \"1.6\",\n        \"version\": 1,\n    }\n    return sbom_cyclonedx_1_6\n\n\ndef _calculate_licenses(component):\n    from conan.tools.sbom.spdx_licenses import NORMALIZED_VALID_SPDX_LICENSES\n    licenses = component.conanfile.license\n\n    if isinstance(licenses, str):  # Just one license\n        field = \"id\" if licenses.lower() in NORMALIZED_VALID_SPDX_LICENSES else \"name\"\n        return [{\"license\": {field: licenses}}]\n\n    return [\n        # More than one license\n        {\"license\": {\n            \"id\" if lic.lower() in NORMALIZED_VALID_SPDX_LICENSES else \"name\": lic\n        }}\n        for lic in licenses\n    ]\n\n\ndef _calculate_bomref(component):\n    user = f\"&user={component.ref.user}\" if component.ref.user else \"\"\n    channel = f\"&channel={component.ref.channel}\" if component.ref.channel else \"\"\n    return f\"pkg:conan/{component.name}@{component.ref.version}?rref={component.ref.revision}{user}{channel}\"\n\n\ndef should_add_node(node, add_build, add_tests):\n    return (node.context == \"host\" or add_build) and (not node.test or add_tests)\n"
  },
  {
    "path": "conan/tools/sbom/spdx_licenses.py",
    "content": "# This list comes from: https://github.com/spdx/license-list-data/blob/v3.26.0/json/licenses.json\nVALID_SPDX_LICENSES = {\n    \"0BSD\",\n    \"3D-Slicer-1.0\",\n    \"AAL\",\n    \"Abstyles\",\n    \"AdaCore-doc\",\n    \"Adobe-2006\",\n    \"Adobe-Display-PostScript\",\n    \"Adobe-Glyph\",\n    \"Adobe-Utopia\",\n    \"ADSL\",\n    \"AFL-1.1\",\n    \"AFL-1.2\",\n    \"AFL-2.0\",\n    \"AFL-2.1\",\n    \"AFL-3.0\",\n    \"Afmparse\",\n    \"AGPL-1.0\",\n    \"AGPL-1.0-only\",\n    \"AGPL-1.0-or-later\",\n    \"AGPL-3.0\",\n    \"AGPL-3.0-only\",\n    \"AGPL-3.0-or-later\",\n    \"Aladdin\",\n    \"AMD-newlib\",\n    \"AMDPLPA\",\n    \"AML\",\n    \"AML-glslang\",\n    \"AMPAS\",\n    \"ANTLR-PD\",\n    \"ANTLR-PD-fallback\",\n    \"any-OSI\",\n    \"any-OSI-perl-modules\",\n    \"Apache-1.0\",\n    \"Apache-1.1\",\n    \"Apache-2.0\",\n    \"APAFML\",\n    \"APL-1.0\",\n    \"App-s2p\",\n    \"APSL-1.0\",\n    \"APSL-1.1\",\n    \"APSL-1.2\",\n    \"APSL-2.0\",\n    \"Arphic-1999\",\n    \"Artistic-1.0\",\n    \"Artistic-1.0-cl8\",\n    \"Artistic-1.0-Perl\",\n    \"Artistic-2.0\",\n    \"ASWF-Digital-Assets-1.0\",\n    \"ASWF-Digital-Assets-1.1\",\n    \"Baekmuk\",\n    \"Bahyph\",\n    \"Barr\",\n    \"bcrypt-Solar-Designer\",\n    \"Beerware\",\n    \"Bitstream-Charter\",\n    \"Bitstream-Vera\",\n    \"BitTorrent-1.0\",\n    \"BitTorrent-1.1\",\n    \"blessing\",\n    \"BlueOak-1.0.0\",\n    \"Boehm-GC\",\n    \"Boehm-GC-without-fee\",\n    \"Borceux\",\n    \"Brian-Gladman-2-Clause\",\n    \"Brian-Gladman-3-Clause\",\n    \"BSD-1-Clause\",\n    \"BSD-2-Clause\",\n    \"BSD-2-Clause-Darwin\",\n    \"BSD-2-Clause-first-lines\",\n    \"BSD-2-Clause-FreeBSD\",\n    \"BSD-2-Clause-NetBSD\",\n    \"BSD-2-Clause-Patent\",\n    \"BSD-2-Clause-Views\",\n    \"BSD-3-Clause\",\n    \"BSD-3-Clause-acpica\",\n    \"BSD-3-Clause-Attribution\",\n    \"BSD-3-Clause-Clear\",\n    \"BSD-3-Clause-flex\",\n    \"BSD-3-Clause-HP\",\n    \"BSD-3-Clause-LBNL\",\n    \"BSD-3-Clause-Modification\",\n    \"BSD-3-Clause-No-Military-License\",\n    \"BSD-3-Clause-No-Nuclear-License\",\n    \"BSD-3-Clause-No-Nuclear-License-2014\",\n    \"BSD-3-Clause-No-Nuclear-Warranty\",\n    \"BSD-3-Clause-Open-MPI\",\n    \"BSD-3-Clause-Sun\",\n    \"BSD-4-Clause\",\n    \"BSD-4-Clause-Shortened\",\n    \"BSD-4-Clause-UC\",\n    \"BSD-4.3RENO\",\n    \"BSD-4.3TAHOE\",\n    \"BSD-Advertising-Acknowledgement\",\n    \"BSD-Attribution-HPND-disclaimer\",\n    \"BSD-Inferno-Nettverk\",\n    \"BSD-Protection\",\n    \"BSD-Source-beginning-file\",\n    \"BSD-Source-Code\",\n    \"BSD-Systemics\",\n    \"BSD-Systemics-W3Works\",\n    \"BSL-1.0\",\n    \"BUSL-1.1\",\n    \"bzip2-1.0.5\",\n    \"bzip2-1.0.6\",\n    \"C-UDA-1.0\",\n    \"CAL-1.0\",\n    \"CAL-1.0-Combined-Work-Exception\",\n    \"Caldera\",\n    \"Caldera-no-preamble\",\n    \"Catharon\",\n    \"CATOSL-1.1\",\n    \"CC-BY-1.0\",\n    \"CC-BY-2.0\",\n    \"CC-BY-2.5\",\n    \"CC-BY-2.5-AU\",\n    \"CC-BY-3.0\",\n    \"CC-BY-3.0-AT\",\n    \"CC-BY-3.0-AU\",\n    \"CC-BY-3.0-DE\",\n    \"CC-BY-3.0-IGO\",\n    \"CC-BY-3.0-NL\",\n    \"CC-BY-3.0-US\",\n    \"CC-BY-4.0\",\n    \"CC-BY-NC-1.0\",\n    \"CC-BY-NC-2.0\",\n    \"CC-BY-NC-2.5\",\n    \"CC-BY-NC-3.0\",\n    \"CC-BY-NC-3.0-DE\",\n    \"CC-BY-NC-4.0\",\n    \"CC-BY-NC-ND-1.0\",\n    \"CC-BY-NC-ND-2.0\",\n    \"CC-BY-NC-ND-2.5\",\n    \"CC-BY-NC-ND-3.0\",\n    \"CC-BY-NC-ND-3.0-DE\",\n    \"CC-BY-NC-ND-3.0-IGO\",\n    \"CC-BY-NC-ND-4.0\",\n    \"CC-BY-NC-SA-1.0\",\n    \"CC-BY-NC-SA-2.0\",\n    \"CC-BY-NC-SA-2.0-DE\",\n    \"CC-BY-NC-SA-2.0-FR\",\n    \"CC-BY-NC-SA-2.0-UK\",\n    \"CC-BY-NC-SA-2.5\",\n    \"CC-BY-NC-SA-3.0\",\n    \"CC-BY-NC-SA-3.0-DE\",\n    \"CC-BY-NC-SA-3.0-IGO\",\n    \"CC-BY-NC-SA-4.0\",\n    \"CC-BY-ND-1.0\",\n    \"CC-BY-ND-2.0\",\n    \"CC-BY-ND-2.5\",\n    \"CC-BY-ND-3.0\",\n    \"CC-BY-ND-3.0-DE\",\n    \"CC-BY-ND-4.0\",\n    \"CC-BY-SA-1.0\",\n    \"CC-BY-SA-2.0\",\n    \"CC-BY-SA-2.0-UK\",\n    \"CC-BY-SA-2.1-JP\",\n    \"CC-BY-SA-2.5\",\n    \"CC-BY-SA-3.0\",\n    \"CC-BY-SA-3.0-AT\",\n    \"CC-BY-SA-3.0-DE\",\n    \"CC-BY-SA-3.0-IGO\",\n    \"CC-BY-SA-4.0\",\n    \"CC-PDDC\",\n    \"CC-PDM-1.0\",\n    \"CC-SA-1.0\",\n    \"CC0-1.0\",\n    \"CDDL-1.0\",\n    \"CDDL-1.1\",\n    \"CDL-1.0\",\n    \"CDLA-Permissive-1.0\",\n    \"CDLA-Permissive-2.0\",\n    \"CDLA-Sharing-1.0\",\n    \"CECILL-1.0\",\n    \"CECILL-1.1\",\n    \"CECILL-2.0\",\n    \"CECILL-2.1\",\n    \"CECILL-B\",\n    \"CECILL-C\",\n    \"CERN-OHL-1.1\",\n    \"CERN-OHL-1.2\",\n    \"CERN-OHL-P-2.0\",\n    \"CERN-OHL-S-2.0\",\n    \"CERN-OHL-W-2.0\",\n    \"CFITSIO\",\n    \"check-cvs\",\n    \"checkmk\",\n    \"ClArtistic\",\n    \"Clips\",\n    \"CMU-Mach\",\n    \"CMU-Mach-nodoc\",\n    \"CNRI-Jython\",\n    \"CNRI-Python\",\n    \"CNRI-Python-GPL-Compatible\",\n    \"COIL-1.0\",\n    \"Community-Spec-1.0\",\n    \"Condor-1.1\",\n    \"copyleft-next-0.3.0\",\n    \"copyleft-next-0.3.1\",\n    \"Cornell-Lossless-JPEG\",\n    \"CPAL-1.0\",\n    \"CPL-1.0\",\n    \"CPOL-1.02\",\n    \"Cronyx\",\n    \"Crossword\",\n    \"CrystalStacker\",\n    \"CUA-OPL-1.0\",\n    \"Cube\",\n    \"curl\",\n    \"cve-tou\",\n    \"D-FSL-1.0\",\n    \"DEC-3-Clause\",\n    \"diffmark\",\n    \"DL-DE-BY-2.0\",\n    \"DL-DE-ZERO-2.0\",\n    \"DOC\",\n    \"DocBook-Schema\",\n    \"DocBook-Stylesheet\",\n    \"DocBook-XML\",\n    \"Dotseqn\",\n    \"DRL-1.0\",\n    \"DRL-1.1\",\n    \"DSDP\",\n    \"dtoa\",\n    \"dvipdfm\",\n    \"ECL-1.0\",\n    \"ECL-2.0\",\n    \"eCos-2.0\",\n    \"EFL-1.0\",\n    \"EFL-2.0\",\n    \"eGenix\",\n    \"Elastic-2.0\",\n    \"Entessa\",\n    \"EPICS\",\n    \"EPL-1.0\",\n    \"EPL-2.0\",\n    \"ErlPL-1.1\",\n    \"etalab-2.0\",\n    \"EUDatagrid\",\n    \"EUPL-1.0\",\n    \"EUPL-1.1\",\n    \"EUPL-1.2\",\n    \"Eurosym\",\n    \"Fair\",\n    \"FBM\",\n    \"FDK-AAC\",\n    \"Ferguson-Twofish\",\n    \"Frameworx-1.0\",\n    \"FreeBSD-DOC\",\n    \"FreeImage\",\n    \"FSFAP\",\n    \"FSFAP-no-warranty-disclaimer\",\n    \"FSFUL\",\n    \"FSFULLR\",\n    \"FSFULLRWD\",\n    \"FTL\",\n    \"Furuseth\",\n    \"fwlw\",\n    \"GCR-docs\",\n    \"GD\",\n    \"generic-xts\",\n    \"GFDL-1.1\",\n    \"GFDL-1.1-invariants-only\",\n    \"GFDL-1.1-invariants-or-later\",\n    \"GFDL-1.1-no-invariants-only\",\n    \"GFDL-1.1-no-invariants-or-later\",\n    \"GFDL-1.1-only\",\n    \"GFDL-1.1-or-later\",\n    \"GFDL-1.2\",\n    \"GFDL-1.2-invariants-only\",\n    \"GFDL-1.2-invariants-or-later\",\n    \"GFDL-1.2-no-invariants-only\",\n    \"GFDL-1.2-no-invariants-or-later\",\n    \"GFDL-1.2-only\",\n    \"GFDL-1.2-or-later\",\n    \"GFDL-1.3\",\n    \"GFDL-1.3-invariants-only\",\n    \"GFDL-1.3-invariants-or-later\",\n    \"GFDL-1.3-no-invariants-only\",\n    \"GFDL-1.3-no-invariants-or-later\",\n    \"GFDL-1.3-only\",\n    \"GFDL-1.3-or-later\",\n    \"Giftware\",\n    \"GL2PS\",\n    \"Glide\",\n    \"Glulxe\",\n    \"GLWTPL\",\n    \"gnuplot\",\n    \"GPL-1.0\",\n    \"GPL-1.0+\",\n    \"GPL-1.0-only\",\n    \"GPL-1.0-or-later\",\n    \"GPL-2.0\",\n    \"GPL-2.0+\",\n    \"GPL-2.0-only\",\n    \"GPL-2.0-or-later\",\n    \"GPL-2.0-with-autoconf-exception\",\n    \"GPL-2.0-with-bison-exception\",\n    \"GPL-2.0-with-classpath-exception\",\n    \"GPL-2.0-with-font-exception\",\n    \"GPL-2.0-with-GCC-exception\",\n    \"GPL-3.0\",\n    \"GPL-3.0+\",\n    \"GPL-3.0-only\",\n    \"GPL-3.0-or-later\",\n    \"GPL-3.0-with-autoconf-exception\",\n    \"GPL-3.0-with-GCC-exception\",\n    \"Graphics-Gems\",\n    \"gSOAP-1.3b\",\n    \"gtkbook\",\n    \"Gutmann\",\n    \"HaskellReport\",\n    \"hdparm\",\n    \"HIDAPI\",\n    \"Hippocratic-2.1\",\n    \"HP-1986\",\n    \"HP-1989\",\n    \"HPND\",\n    \"HPND-DEC\",\n    \"HPND-doc\",\n    \"HPND-doc-sell\",\n    \"HPND-export-US\",\n    \"HPND-export-US-acknowledgement\",\n    \"HPND-export-US-modify\",\n    \"HPND-export2-US\",\n    \"HPND-Fenneberg-Livingston\",\n    \"HPND-INRIA-IMAG\",\n    \"HPND-Intel\",\n    \"HPND-Kevlin-Henney\",\n    \"HPND-Markus-Kuhn\",\n    \"HPND-merchantability-variant\",\n    \"HPND-MIT-disclaimer\",\n    \"HPND-Netrek\",\n    \"HPND-Pbmplus\",\n    \"HPND-sell-MIT-disclaimer-xserver\",\n    \"HPND-sell-regexpr\",\n    \"HPND-sell-variant\",\n    \"HPND-sell-variant-MIT-disclaimer\",\n    \"HPND-sell-variant-MIT-disclaimer-rev\",\n    \"HPND-UC\",\n    \"HPND-UC-export-US\",\n    \"HTMLTIDY\",\n    \"IBM-pibs\",\n    \"ICU\",\n    \"IEC-Code-Components-EULA\",\n    \"IJG\",\n    \"IJG-short\",\n    \"ImageMagick\",\n    \"iMatix\",\n    \"Imlib2\",\n    \"Info-ZIP\",\n    \"Inner-Net-2.0\",\n    \"InnoSetup\",\n    \"Intel\",\n    \"Intel-ACPI\",\n    \"Interbase-1.0\",\n    \"IPA\",\n    \"IPL-1.0\",\n    \"ISC\",\n    \"ISC-Veillard\",\n    \"Jam\",\n    \"JasPer-2.0\",\n    \"JPL-image\",\n    \"JPNIC\",\n    \"JSON\",\n    \"Kastrup\",\n    \"Kazlib\",\n    \"Knuth-CTAN\",\n    \"LAL-1.2\",\n    \"LAL-1.3\",\n    \"Latex2e\",\n    \"Latex2e-translated-notice\",\n    \"Leptonica\",\n    \"LGPL-2.0\",\n    \"LGPL-2.0+\",\n    \"LGPL-2.0-only\",\n    \"LGPL-2.0-or-later\",\n    \"LGPL-2.1\",\n    \"LGPL-2.1+\",\n    \"LGPL-2.1-only\",\n    \"LGPL-2.1-or-later\",\n    \"LGPL-3.0\",\n    \"LGPL-3.0+\",\n    \"LGPL-3.0-only\",\n    \"LGPL-3.0-or-later\",\n    \"LGPLLR\",\n    \"Libpng\",\n    \"libpng-2.0\",\n    \"libselinux-1.0\",\n    \"libtiff\",\n    \"libutil-David-Nugent\",\n    \"LiLiQ-P-1.1\",\n    \"LiLiQ-R-1.1\",\n    \"LiLiQ-Rplus-1.1\",\n    \"Linux-man-pages-1-para\",\n    \"Linux-man-pages-copyleft\",\n    \"Linux-man-pages-copyleft-2-para\",\n    \"Linux-man-pages-copyleft-var\",\n    \"Linux-OpenIB\",\n    \"LOOP\",\n    \"LPD-document\",\n    \"LPL-1.0\",\n    \"LPL-1.02\",\n    \"LPPL-1.0\",\n    \"LPPL-1.1\",\n    \"LPPL-1.2\",\n    \"LPPL-1.3a\",\n    \"LPPL-1.3c\",\n    \"lsof\",\n    \"Lucida-Bitmap-Fonts\",\n    \"LZMA-SDK-9.11-to-9.20\",\n    \"LZMA-SDK-9.22\",\n    \"Mackerras-3-Clause\",\n    \"Mackerras-3-Clause-acknowledgment\",\n    \"magaz\",\n    \"mailprio\",\n    \"MakeIndex\",\n    \"Martin-Birgmeier\",\n    \"McPhee-slideshow\",\n    \"metamail\",\n    \"Minpack\",\n    \"MIPS\",\n    \"MirOS\",\n    \"MIT\",\n    \"MIT-0\",\n    \"MIT-advertising\",\n    \"MIT-Click\",\n    \"MIT-CMU\",\n    \"MIT-enna\",\n    \"MIT-feh\",\n    \"MIT-Festival\",\n    \"MIT-Khronos-old\",\n    \"MIT-Modern-Variant\",\n    \"MIT-open-group\",\n    \"MIT-testregex\",\n    \"MIT-Wu\",\n    \"MITNFA\",\n    \"MMIXware\",\n    \"Motosoto\",\n    \"MPEG-SSG\",\n    \"mpi-permissive\",\n    \"mpich2\",\n    \"MPL-1.0\",\n    \"MPL-1.1\",\n    \"MPL-2.0\",\n    \"MPL-2.0-no-copyleft-exception\",\n    \"mplus\",\n    \"MS-LPL\",\n    \"MS-PL\",\n    \"MS-RL\",\n    \"MTLL\",\n    \"MulanPSL-1.0\",\n    \"MulanPSL-2.0\",\n    \"Multics\",\n    \"Mup\",\n    \"NAIST-2003\",\n    \"NASA-1.3\",\n    \"Naumen\",\n    \"NBPL-1.0\",\n    \"NCBI-PD\",\n    \"NCGL-UK-2.0\",\n    \"NCL\",\n    \"NCSA\",\n    \"Net-SNMP\",\n    \"NetCDF\",\n    \"Newsletr\",\n    \"NGPL\",\n    \"NICTA-1.0\",\n    \"NIST-PD\",\n    \"NIST-PD-fallback\",\n    \"NIST-Software\",\n    \"NLOD-1.0\",\n    \"NLOD-2.0\",\n    \"NLPL\",\n    \"Nokia\",\n    \"NOSL\",\n    \"Noweb\",\n    \"NPL-1.0\",\n    \"NPL-1.1\",\n    \"NPOSL-3.0\",\n    \"NRL\",\n    \"NTP\",\n    \"NTP-0\",\n    \"Nunit\",\n    \"O-UDA-1.0\",\n    \"OAR\",\n    \"OCCT-PL\",\n    \"OCLC-2.0\",\n    \"ODbL-1.0\",\n    \"ODC-By-1.0\",\n    \"OFFIS\",\n    \"OFL-1.0\",\n    \"OFL-1.0-no-RFN\",\n    \"OFL-1.0-RFN\",\n    \"OFL-1.1\",\n    \"OFL-1.1-no-RFN\",\n    \"OFL-1.1-RFN\",\n    \"OGC-1.0\",\n    \"OGDL-Taiwan-1.0\",\n    \"OGL-Canada-2.0\",\n    \"OGL-UK-1.0\",\n    \"OGL-UK-2.0\",\n    \"OGL-UK-3.0\",\n    \"OGTSL\",\n    \"OLDAP-1.1\",\n    \"OLDAP-1.2\",\n    \"OLDAP-1.3\",\n    \"OLDAP-1.4\",\n    \"OLDAP-2.0\",\n    \"OLDAP-2.0.1\",\n    \"OLDAP-2.1\",\n    \"OLDAP-2.2\",\n    \"OLDAP-2.2.1\",\n    \"OLDAP-2.2.2\",\n    \"OLDAP-2.3\",\n    \"OLDAP-2.4\",\n    \"OLDAP-2.5\",\n    \"OLDAP-2.6\",\n    \"OLDAP-2.7\",\n    \"OLDAP-2.8\",\n    \"OLFL-1.3\",\n    \"OML\",\n    \"OpenPBS-2.3\",\n    \"OpenSSL\",\n    \"OpenSSL-standalone\",\n    \"OpenVision\",\n    \"OPL-1.0\",\n    \"OPL-UK-3.0\",\n    \"OPUBL-1.0\",\n    \"OSET-PL-2.1\",\n    \"OSL-1.0\",\n    \"OSL-1.1\",\n    \"OSL-2.0\",\n    \"OSL-2.1\",\n    \"OSL-3.0\",\n    \"PADL\",\n    \"Parity-6.0.0\",\n    \"Parity-7.0.0\",\n    \"PDDL-1.0\",\n    \"PHP-3.0\",\n    \"PHP-3.01\",\n    \"Pixar\",\n    \"pkgconf\",\n    \"Plexus\",\n    \"pnmstitch\",\n    \"PolyForm-Noncommercial-1.0.0\",\n    \"PolyForm-Small-Business-1.0.0\",\n    \"PostgreSQL\",\n    \"PPL\",\n    \"PSF-2.0\",\n    \"psfrag\",\n    \"psutils\",\n    \"Python-2.0\",\n    \"Python-2.0.1\",\n    \"python-ldap\",\n    \"Qhull\",\n    \"QPL-1.0\",\n    \"QPL-1.0-INRIA-2004\",\n    \"radvd\",\n    \"Rdisc\",\n    \"RHeCos-1.1\",\n    \"RPL-1.1\",\n    \"RPL-1.5\",\n    \"RPSL-1.0\",\n    \"RSA-MD\",\n    \"RSCPL\",\n    \"Ruby\",\n    \"Ruby-pty\",\n    \"SAX-PD\",\n    \"SAX-PD-2.0\",\n    \"Saxpath\",\n    \"SCEA\",\n    \"SchemeReport\",\n    \"Sendmail\",\n    \"Sendmail-8.23\",\n    \"Sendmail-Open-Source-1.1\",\n    \"SGI-B-1.0\",\n    \"SGI-B-1.1\",\n    \"SGI-B-2.0\",\n    \"SGI-OpenGL\",\n    \"SGP4\",\n    \"SHL-0.5\",\n    \"SHL-0.51\",\n    \"SimPL-2.0\",\n    \"SISSL\",\n    \"SISSL-1.2\",\n    \"SL\",\n    \"Sleepycat\",\n    \"SMAIL-GPL\",\n    \"SMLNJ\",\n    \"SMPPL\",\n    \"SNIA\",\n    \"snprintf\",\n    \"softSurfer\",\n    \"Soundex\",\n    \"Spencer-86\",\n    \"Spencer-94\",\n    \"Spencer-99\",\n    \"SPL-1.0\",\n    \"ssh-keyscan\",\n    \"SSH-OpenSSH\",\n    \"SSH-short\",\n    \"SSLeay-standalone\",\n    \"SSPL-1.0\",\n    \"StandardML-NJ\",\n    \"SugarCRM-1.1.3\",\n    \"Sun-PPP\",\n    \"Sun-PPP-2000\",\n    \"SunPro\",\n    \"SWL\",\n    \"swrule\",\n    \"Symlinks\",\n    \"TAPR-OHL-1.0\",\n    \"TCL\",\n    \"TCP-wrappers\",\n    \"TermReadKey\",\n    \"TGPPL-1.0\",\n    \"ThirdEye\",\n    \"threeparttable\",\n    \"TMate\",\n    \"TORQUE-1.1\",\n    \"TOSL\",\n    \"TPDL\",\n    \"TPL-1.0\",\n    \"TrustedQSL\",\n    \"TTWL\",\n    \"TTYP0\",\n    \"TU-Berlin-1.0\",\n    \"TU-Berlin-2.0\",\n    \"Ubuntu-font-1.0\",\n    \"UCAR\",\n    \"UCL-1.0\",\n    \"ulem\",\n    \"UMich-Merit\",\n    \"Unicode-3.0\",\n    \"Unicode-DFS-2015\",\n    \"Unicode-DFS-2016\",\n    \"Unicode-TOU\",\n    \"UnixCrypt\",\n    \"Unlicense\",\n    \"UPL-1.0\",\n    \"URT-RLE\",\n    \"Vim\",\n    \"VOSTROM\",\n    \"VSL-1.0\",\n    \"W3C\",\n    \"W3C-19980720\",\n    \"W3C-20150513\",\n    \"w3m\",\n    \"Watcom-1.0\",\n    \"Widget-Workshop\",\n    \"Wsuipa\",\n    \"WTFPL\",\n    \"wwl\",\n    \"wxWindows\",\n    \"X11\",\n    \"X11-distribute-modifications-variant\",\n    \"X11-swapped\",\n    \"Xdebug-1.03\",\n    \"Xerox\",\n    \"Xfig\",\n    \"XFree86-1.1\",\n    \"xinetd\",\n    \"xkeyboard-config-Zinoviev\",\n    \"xlock\",\n    \"Xnet\",\n    \"xpp\",\n    \"XSkat\",\n    \"xzoom\",\n    \"YPL-1.0\",\n    \"YPL-1.1\",\n    \"Zed\",\n    \"Zeeff\",\n    \"Zend-2.0\",\n    \"Zimbra-1.3\",\n    \"Zimbra-1.4\",\n    \"Zlib\",\n    \"zlib-acknowledgement\",\n    \"ZPL-1.1\",\n    \"ZPL-2.0\",\n    \"ZPL-2.1\"\n}\n\n\nNORMALIZED_VALID_SPDX_LICENSES = {\n    \"0bsd\",\n    \"3d-slicer-1.0\",\n    \"aal\",\n    \"abstyles\",\n    \"adacore-doc\",\n    \"adobe-2006\",\n    \"adobe-display-postscript\",\n    \"adobe-glyph\",\n    \"adobe-utopia\",\n    \"adsl\",\n    \"afl-1.1\",\n    \"afl-1.2\",\n    \"afl-2.0\",\n    \"afl-2.1\",\n    \"afl-3.0\",\n    \"afmparse\",\n    \"agpl-1.0\",\n    \"agpl-1.0-only\",\n    \"agpl-1.0-or-later\",\n    \"agpl-3.0\",\n    \"agpl-3.0-only\",\n    \"agpl-3.0-or-later\",\n    \"aladdin\",\n    \"amd-newlib\",\n    \"amdplpa\",\n    \"aml\",\n    \"aml-glslang\",\n    \"ampas\",\n    \"antlr-pd\",\n    \"antlr-pd-fallback\",\n    \"any-osi\",\n    \"any-osi-perl-modules\",\n    \"apache-1.0\",\n    \"apache-1.1\",\n    \"apache-2.0\",\n    \"apafml\",\n    \"apl-1.0\",\n    \"app-s2p\",\n    \"apsl-1.0\",\n    \"apsl-1.1\",\n    \"apsl-1.2\",\n    \"apsl-2.0\",\n    \"arphic-1999\",\n    \"artistic-1.0\",\n    \"artistic-1.0-cl8\",\n    \"artistic-1.0-perl\",\n    \"artistic-2.0\",\n    \"aswf-digital-assets-1.0\",\n    \"aswf-digital-assets-1.1\",\n    \"baekmuk\",\n    \"bahyph\",\n    \"barr\",\n    \"bcrypt-solar-designer\",\n    \"beerware\",\n    \"bitstream-charter\",\n    \"bitstream-vera\",\n    \"bittorrent-1.0\",\n    \"bittorrent-1.1\",\n    \"blessing\",\n    \"blueoak-1.0.0\",\n    \"boehm-gc\",\n    \"boehm-gc-without-fee\",\n    \"borceux\",\n    \"brian-gladman-2-clause\",\n    \"brian-gladman-3-clause\",\n    \"bsd-1-clause\",\n    \"bsd-2-clause\",\n    \"bsd-2-clause-darwin\",\n    \"bsd-2-clause-first-lines\",\n    \"bsd-2-clause-freebsd\",\n    \"bsd-2-clause-netbsd\",\n    \"bsd-2-clause-patent\",\n    \"bsd-2-clause-views\",\n    \"bsd-3-clause\",\n    \"bsd-3-clause-acpica\",\n    \"bsd-3-clause-attribution\",\n    \"bsd-3-clause-clear\",\n    \"bsd-3-clause-flex\",\n    \"bsd-3-clause-hp\",\n    \"bsd-3-clause-lbnl\",\n    \"bsd-3-clause-modification\",\n    \"bsd-3-clause-no-military-license\",\n    \"bsd-3-clause-no-nuclear-license\",\n    \"bsd-3-clause-no-nuclear-license-2014\",\n    \"bsd-3-clause-no-nuclear-warranty\",\n    \"bsd-3-clause-open-mpi\",\n    \"bsd-3-clause-sun\",\n    \"bsd-4-clause\",\n    \"bsd-4-clause-shortened\",\n    \"bsd-4-clause-uc\",\n    \"bsd-4.3reno\",\n    \"bsd-4.3tahoe\",\n    \"bsd-advertising-acknowledgement\",\n    \"bsd-attribution-hpnd-disclaimer\",\n    \"bsd-inferno-nettverk\",\n    \"bsd-protection\",\n    \"bsd-source-beginning-file\",\n    \"bsd-source-code\",\n    \"bsd-systemics\",\n    \"bsd-systemics-w3works\",\n    \"bsl-1.0\",\n    \"busl-1.1\",\n    \"bzip2-1.0.5\",\n    \"bzip2-1.0.6\",\n    \"c-uda-1.0\",\n    \"cal-1.0\",\n    \"cal-1.0-combined-work-exception\",\n    \"caldera\",\n    \"caldera-no-preamble\",\n    \"catharon\",\n    \"catosl-1.1\",\n    \"cc-by-1.0\",\n    \"cc-by-2.0\",\n    \"cc-by-2.5\",\n    \"cc-by-2.5-au\",\n    \"cc-by-3.0\",\n    \"cc-by-3.0-at\",\n    \"cc-by-3.0-au\",\n    \"cc-by-3.0-de\",\n    \"cc-by-3.0-igo\",\n    \"cc-by-3.0-nl\",\n    \"cc-by-3.0-us\",\n    \"cc-by-4.0\",\n    \"cc-by-nc-1.0\",\n    \"cc-by-nc-2.0\",\n    \"cc-by-nc-2.5\",\n    \"cc-by-nc-3.0\",\n    \"cc-by-nc-3.0-de\",\n    \"cc-by-nc-4.0\",\n    \"cc-by-nc-nd-1.0\",\n    \"cc-by-nc-nd-2.0\",\n    \"cc-by-nc-nd-2.5\",\n    \"cc-by-nc-nd-3.0\",\n    \"cc-by-nc-nd-3.0-de\",\n    \"cc-by-nc-nd-3.0-igo\",\n    \"cc-by-nc-nd-4.0\",\n    \"cc-by-nc-sa-1.0\",\n    \"cc-by-nc-sa-2.0\",\n    \"cc-by-nc-sa-2.0-de\",\n    \"cc-by-nc-sa-2.0-fr\",\n    \"cc-by-nc-sa-2.0-uk\",\n    \"cc-by-nc-sa-2.5\",\n    \"cc-by-nc-sa-3.0\",\n    \"cc-by-nc-sa-3.0-de\",\n    \"cc-by-nc-sa-3.0-igo\",\n    \"cc-by-nc-sa-4.0\",\n    \"cc-by-nd-1.0\",\n    \"cc-by-nd-2.0\",\n    \"cc-by-nd-2.5\",\n    \"cc-by-nd-3.0\",\n    \"cc-by-nd-3.0-de\",\n    \"cc-by-nd-4.0\",\n    \"cc-by-sa-1.0\",\n    \"cc-by-sa-2.0\",\n    \"cc-by-sa-2.0-uk\",\n    \"cc-by-sa-2.1-jp\",\n    \"cc-by-sa-2.5\",\n    \"cc-by-sa-3.0\",\n    \"cc-by-sa-3.0-at\",\n    \"cc-by-sa-3.0-de\",\n    \"cc-by-sa-3.0-igo\",\n    \"cc-by-sa-4.0\",\n    \"cc-pddc\",\n    \"cc-pdm-1.0\",\n    \"cc-sa-1.0\",\n    \"cc0-1.0\",\n    \"cddl-1.0\",\n    \"cddl-1.1\",\n    \"cdl-1.0\",\n    \"cdla-permissive-1.0\",\n    \"cdla-permissive-2.0\",\n    \"cdla-sharing-1.0\",\n    \"cecill-1.0\",\n    \"cecill-1.1\",\n    \"cecill-2.0\",\n    \"cecill-2.1\",\n    \"cecill-b\",\n    \"cecill-c\",\n    \"cern-ohl-1.1\",\n    \"cern-ohl-1.2\",\n    \"cern-ohl-p-2.0\",\n    \"cern-ohl-s-2.0\",\n    \"cern-ohl-w-2.0\",\n    \"cfitsio\",\n    \"check-cvs\",\n    \"checkmk\",\n    \"clartistic\",\n    \"clips\",\n    \"cmu-mach\",\n    \"cmu-mach-nodoc\",\n    \"cnri-jython\",\n    \"cnri-python\",\n    \"cnri-python-gpl-compatible\",\n    \"coil-1.0\",\n    \"community-spec-1.0\",\n    \"condor-1.1\",\n    \"copyleft-next-0.3.0\",\n    \"copyleft-next-0.3.1\",\n    \"cornell-lossless-jpeg\",\n    \"cpal-1.0\",\n    \"cpl-1.0\",\n    \"cpol-1.02\",\n    \"cronyx\",\n    \"crossword\",\n    \"crystalstacker\",\n    \"cua-opl-1.0\",\n    \"cube\",\n    \"curl\",\n    \"cve-tou\",\n    \"d-fsl-1.0\",\n    \"dec-3-clause\",\n    \"diffmark\",\n    \"dl-de-by-2.0\",\n    \"dl-de-zero-2.0\",\n    \"doc\",\n    \"docbook-schema\",\n    \"docbook-stylesheet\",\n    \"docbook-xml\",\n    \"dotseqn\",\n    \"drl-1.0\",\n    \"drl-1.1\",\n    \"dsdp\",\n    \"dtoa\",\n    \"dvipdfm\",\n    \"ecl-1.0\",\n    \"ecl-2.0\",\n    \"ecos-2.0\",\n    \"efl-1.0\",\n    \"efl-2.0\",\n    \"egenix\",\n    \"elastic-2.0\",\n    \"entessa\",\n    \"epics\",\n    \"epl-1.0\",\n    \"epl-2.0\",\n    \"erlpl-1.1\",\n    \"etalab-2.0\",\n    \"eudatagrid\",\n    \"eupl-1.0\",\n    \"eupl-1.1\",\n    \"eupl-1.2\",\n    \"eurosym\",\n    \"fair\",\n    \"fbm\",\n    \"fdk-aac\",\n    \"ferguson-twofish\",\n    \"frameworx-1.0\",\n    \"freebsd-doc\",\n    \"freeimage\",\n    \"fsfap\",\n    \"fsfap-no-warranty-disclaimer\",\n    \"fsful\",\n    \"fsfullr\",\n    \"fsfullrwd\",\n    \"ftl\",\n    \"furuseth\",\n    \"fwlw\",\n    \"gcr-docs\",\n    \"gd\",\n    \"generic-xts\",\n    \"gfdl-1.1\",\n    \"gfdl-1.1-invariants-only\",\n    \"gfdl-1.1-invariants-or-later\",\n    \"gfdl-1.1-no-invariants-only\",\n    \"gfdl-1.1-no-invariants-or-later\",\n    \"gfdl-1.1-only\",\n    \"gfdl-1.1-or-later\",\n    \"gfdl-1.2\",\n    \"gfdl-1.2-invariants-only\",\n    \"gfdl-1.2-invariants-or-later\",\n    \"gfdl-1.2-no-invariants-only\",\n    \"gfdl-1.2-no-invariants-or-later\",\n    \"gfdl-1.2-only\",\n    \"gfdl-1.2-or-later\",\n    \"gfdl-1.3\",\n    \"gfdl-1.3-invariants-only\",\n    \"gfdl-1.3-invariants-or-later\",\n    \"gfdl-1.3-no-invariants-only\",\n    \"gfdl-1.3-no-invariants-or-later\",\n    \"gfdl-1.3-only\",\n    \"gfdl-1.3-or-later\",\n    \"giftware\",\n    \"gl2ps\",\n    \"glide\",\n    \"glulxe\",\n    \"glwtpl\",\n    \"gnuplot\",\n    \"gpl-1.0\",\n    \"gpl-1.0+\",\n    \"gpl-1.0-only\",\n    \"gpl-1.0-or-later\",\n    \"gpl-2.0\",\n    \"gpl-2.0+\",\n    \"gpl-2.0-only\",\n    \"gpl-2.0-or-later\",\n    \"gpl-2.0-with-autoconf-exception\",\n    \"gpl-2.0-with-bison-exception\",\n    \"gpl-2.0-with-classpath-exception\",\n    \"gpl-2.0-with-font-exception\",\n    \"gpl-2.0-with-gcc-exception\",\n    \"gpl-3.0\",\n    \"gpl-3.0+\",\n    \"gpl-3.0-only\",\n    \"gpl-3.0-or-later\",\n    \"gpl-3.0-with-autoconf-exception\",\n    \"gpl-3.0-with-gcc-exception\",\n    \"graphics-gems\",\n    \"gsoap-1.3b\",\n    \"gtkbook\",\n    \"gutmann\",\n    \"haskellreport\",\n    \"hdparm\",\n    \"hidapi\",\n    \"hippocratic-2.1\",\n    \"hp-1986\",\n    \"hp-1989\",\n    \"hpnd\",\n    \"hpnd-dec\",\n    \"hpnd-doc\",\n    \"hpnd-doc-sell\",\n    \"hpnd-export-us\",\n    \"hpnd-export-us-acknowledgement\",\n    \"hpnd-export-us-modify\",\n    \"hpnd-export2-us\",\n    \"hpnd-fenneberg-livingston\",\n    \"hpnd-inria-imag\",\n    \"hpnd-intel\",\n    \"hpnd-kevlin-henney\",\n    \"hpnd-markus-kuhn\",\n    \"hpnd-merchantability-variant\",\n    \"hpnd-mit-disclaimer\",\n    \"hpnd-netrek\",\n    \"hpnd-pbmplus\",\n    \"hpnd-sell-mit-disclaimer-xserver\",\n    \"hpnd-sell-regexpr\",\n    \"hpnd-sell-variant\",\n    \"hpnd-sell-variant-mit-disclaimer\",\n    \"hpnd-sell-variant-mit-disclaimer-rev\",\n    \"hpnd-uc\",\n    \"hpnd-uc-export-us\",\n    \"htmltidy\",\n    \"ibm-pibs\",\n    \"icu\",\n    \"iec-code-components-eula\",\n    \"ijg\",\n    \"ijg-short\",\n    \"imagemagick\",\n    \"imatix\",\n    \"imlib2\",\n    \"info-zip\",\n    \"inner-net-2.0\",\n    \"innosetup\",\n    \"intel\",\n    \"intel-acpi\",\n    \"interbase-1.0\",\n    \"ipa\",\n    \"ipl-1.0\",\n    \"isc\",\n    \"isc-veillard\",\n    \"jam\",\n    \"jasper-2.0\",\n    \"jpl-image\",\n    \"jpnic\",\n    \"json\",\n    \"kastrup\",\n    \"kazlib\",\n    \"knuth-ctan\",\n    \"lal-1.2\",\n    \"lal-1.3\",\n    \"latex2e\",\n    \"latex2e-translated-notice\",\n    \"leptonica\",\n    \"lgpl-2.0\",\n    \"lgpl-2.0+\",\n    \"lgpl-2.0-only\",\n    \"lgpl-2.0-or-later\",\n    \"lgpl-2.1\",\n    \"lgpl-2.1+\",\n    \"lgpl-2.1-only\",\n    \"lgpl-2.1-or-later\",\n    \"lgpl-3.0\",\n    \"lgpl-3.0+\",\n    \"lgpl-3.0-only\",\n    \"lgpl-3.0-or-later\",\n    \"lgpllr\",\n    \"libpng\",\n    \"libpng-2.0\",\n    \"libselinux-1.0\",\n    \"libtiff\",\n    \"libutil-david-nugent\",\n    \"liliq-p-1.1\",\n    \"liliq-r-1.1\",\n    \"liliq-rplus-1.1\",\n    \"linux-man-pages-1-para\",\n    \"linux-man-pages-copyleft\",\n    \"linux-man-pages-copyleft-2-para\",\n    \"linux-man-pages-copyleft-var\",\n    \"linux-openib\",\n    \"loop\",\n    \"lpd-document\",\n    \"lpl-1.0\",\n    \"lpl-1.02\",\n    \"lppl-1.0\",\n    \"lppl-1.1\",\n    \"lppl-1.2\",\n    \"lppl-1.3a\",\n    \"lppl-1.3c\",\n    \"lsof\",\n    \"lucida-bitmap-fonts\",\n    \"lzma-sdk-9.11-to-9.20\",\n    \"lzma-sdk-9.22\",\n    \"mackerras-3-clause\",\n    \"mackerras-3-clause-acknowledgment\",\n    \"magaz\",\n    \"mailprio\",\n    \"makeindex\",\n    \"martin-birgmeier\",\n    \"mcphee-slideshow\",\n    \"metamail\",\n    \"minpack\",\n    \"mips\",\n    \"miros\",\n    \"mit\",\n    \"mit-0\",\n    \"mit-advertising\",\n    \"mit-click\",\n    \"mit-cmu\",\n    \"mit-enna\",\n    \"mit-feh\",\n    \"mit-festival\",\n    \"mit-khronos-old\",\n    \"mit-modern-variant\",\n    \"mit-open-group\",\n    \"mit-testregex\",\n    \"mit-wu\",\n    \"mitnfa\",\n    \"mmixware\",\n    \"motosoto\",\n    \"mpeg-ssg\",\n    \"mpi-permissive\",\n    \"mpich2\",\n    \"mpl-1.0\",\n    \"mpl-1.1\",\n    \"mpl-2.0\",\n    \"mpl-2.0-no-copyleft-exception\",\n    \"mplus\",\n    \"ms-lpl\",\n    \"ms-pl\",\n    \"ms-rl\",\n    \"mtll\",\n    \"mulanpsl-1.0\",\n    \"mulanpsl-2.0\",\n    \"multics\",\n    \"mup\",\n    \"naist-2003\",\n    \"nasa-1.3\",\n    \"naumen\",\n    \"nbpl-1.0\",\n    \"ncbi-pd\",\n    \"ncgl-uk-2.0\",\n    \"ncl\",\n    \"ncsa\",\n    \"net-snmp\",\n    \"netcdf\",\n    \"newsletr\",\n    \"ngpl\",\n    \"nicta-1.0\",\n    \"nist-pd\",\n    \"nist-pd-fallback\",\n    \"nist-software\",\n    \"nlod-1.0\",\n    \"nlod-2.0\",\n    \"nlpl\",\n    \"nokia\",\n    \"nosl\",\n    \"noweb\",\n    \"npl-1.0\",\n    \"npl-1.1\",\n    \"nposl-3.0\",\n    \"nrl\",\n    \"ntp\",\n    \"ntp-0\",\n    \"nunit\",\n    \"o-uda-1.0\",\n    \"oar\",\n    \"occt-pl\",\n    \"oclc-2.0\",\n    \"odbl-1.0\",\n    \"odc-by-1.0\",\n    \"offis\",\n    \"ofl-1.0\",\n    \"ofl-1.0-no-rfn\",\n    \"ofl-1.0-rfn\",\n    \"ofl-1.1\",\n    \"ofl-1.1-no-rfn\",\n    \"ofl-1.1-rfn\",\n    \"ogc-1.0\",\n    \"ogdl-taiwan-1.0\",\n    \"ogl-canada-2.0\",\n    \"ogl-uk-1.0\",\n    \"ogl-uk-2.0\",\n    \"ogl-uk-3.0\",\n    \"ogtsl\",\n    \"oldap-1.1\",\n    \"oldap-1.2\",\n    \"oldap-1.3\",\n    \"oldap-1.4\",\n    \"oldap-2.0\",\n    \"oldap-2.0.1\",\n    \"oldap-2.1\",\n    \"oldap-2.2\",\n    \"oldap-2.2.1\",\n    \"oldap-2.2.2\",\n    \"oldap-2.3\",\n    \"oldap-2.4\",\n    \"oldap-2.5\",\n    \"oldap-2.6\",\n    \"oldap-2.7\",\n    \"oldap-2.8\",\n    \"olfl-1.3\",\n    \"oml\",\n    \"openpbs-2.3\",\n    \"openssl\",\n    \"openssl-standalone\",\n    \"openvision\",\n    \"opl-1.0\",\n    \"opl-uk-3.0\",\n    \"opubl-1.0\",\n    \"oset-pl-2.1\",\n    \"osl-1.0\",\n    \"osl-1.1\",\n    \"osl-2.0\",\n    \"osl-2.1\",\n    \"osl-3.0\",\n    \"padl\",\n    \"parity-6.0.0\",\n    \"parity-7.0.0\",\n    \"pddl-1.0\",\n    \"php-3.0\",\n    \"php-3.01\",\n    \"pixar\",\n    \"pkgconf\",\n    \"plexus\",\n    \"pnmstitch\",\n    \"polyform-noncommercial-1.0.0\",\n    \"polyform-small-business-1.0.0\",\n    \"postgresql\",\n    \"ppl\",\n    \"psf-2.0\",\n    \"psfrag\",\n    \"psutils\",\n    \"python-2.0\",\n    \"python-2.0.1\",\n    \"python-ldap\",\n    \"qhull\",\n    \"qpl-1.0\",\n    \"qpl-1.0-inria-2004\",\n    \"radvd\",\n    \"rdisc\",\n    \"rhecos-1.1\",\n    \"rpl-1.1\",\n    \"rpl-1.5\",\n    \"rpsl-1.0\",\n    \"rsa-md\",\n    \"rscpl\",\n    \"ruby\",\n    \"ruby-pty\",\n    \"sax-pd\",\n    \"sax-pd-2.0\",\n    \"saxpath\",\n    \"scea\",\n    \"schemereport\",\n    \"sendmail\",\n    \"sendmail-8.23\",\n    \"sendmail-open-source-1.1\",\n    \"sgi-b-1.0\",\n    \"sgi-b-1.1\",\n    \"sgi-b-2.0\",\n    \"sgi-opengl\",\n    \"sgp4\",\n    \"shl-0.5\",\n    \"shl-0.51\",\n    \"simpl-2.0\",\n    \"sissl\",\n    \"sissl-1.2\",\n    \"sl\",\n    \"sleepycat\",\n    \"smail-gpl\",\n    \"smlnj\",\n    \"smppl\",\n    \"snia\",\n    \"snprintf\",\n    \"softsurfer\",\n    \"soundex\",\n    \"spencer-86\",\n    \"spencer-94\",\n    \"spencer-99\",\n    \"spl-1.0\",\n    \"ssh-keyscan\",\n    \"ssh-openssh\",\n    \"ssh-short\",\n    \"ssleay-standalone\",\n    \"sspl-1.0\",\n    \"standardml-nj\",\n    \"sugarcrm-1.1.3\",\n    \"sun-ppp\",\n    \"sun-ppp-2000\",\n    \"sunpro\",\n    \"swl\",\n    \"swrule\",\n    \"symlinks\",\n    \"tapr-ohl-1.0\",\n    \"tcl\",\n    \"tcp-wrappers\",\n    \"termreadkey\",\n    \"tgppl-1.0\",\n    \"thirdeye\",\n    \"threeparttable\",\n    \"tmate\",\n    \"torque-1.1\",\n    \"tosl\",\n    \"tpdl\",\n    \"tpl-1.0\",\n    \"trustedqsl\",\n    \"ttwl\",\n    \"ttyp0\",\n    \"tu-berlin-1.0\",\n    \"tu-berlin-2.0\",\n    \"ubuntu-font-1.0\",\n    \"ucar\",\n    \"ucl-1.0\",\n    \"ulem\",\n    \"umich-merit\",\n    \"unicode-3.0\",\n    \"unicode-dfs-2015\",\n    \"unicode-dfs-2016\",\n    \"unicode-tou\",\n    \"unixcrypt\",\n    \"unlicense\",\n    \"upl-1.0\",\n    \"urt-rle\",\n    \"vim\",\n    \"vostrom\",\n    \"vsl-1.0\",\n    \"w3c\",\n    \"w3c-19980720\",\n    \"w3c-20150513\",\n    \"w3m\",\n    \"watcom-1.0\",\n    \"widget-workshop\",\n    \"wsuipa\",\n    \"wtfpl\",\n    \"wwl\",\n    \"wxwindows\",\n    \"x11\",\n    \"x11-distribute-modifications-variant\",\n    \"x11-swapped\",\n    \"xdebug-1.03\",\n    \"xerox\",\n    \"xfig\",\n    \"xfree86-1.1\",\n    \"xinetd\",\n    \"xkeyboard-config-zinoviev\",\n    \"xlock\",\n    \"xnet\",\n    \"xpp\",\n    \"xskat\",\n    \"xzoom\",\n    \"ypl-1.0\",\n    \"ypl-1.1\",\n    \"zed\",\n    \"zeeff\",\n    \"zend-2.0\",\n    \"zimbra-1.3\",\n    \"zimbra-1.4\",\n    \"zlib\",\n    \"zlib-acknowledgement\",\n    \"zpl-1.1\",\n    \"zpl-2.0\",\n    \"zpl-2.1\"\n}\n"
  },
  {
    "path": "conan/tools/scm/__init__.py",
    "content": "from conan.tools.scm.git import Git\nfrom conan.internal.model.version import Version\n"
  },
  {
    "path": "conan/tools/scm/git.py",
    "content": "import fnmatch\nimport os\n\nfrom conan.api.output import Color\nfrom conan.tools.files import chdir, update_conandata\nfrom conan.errors import ConanException\nfrom conan.internal.model.conf import ConfDefinition\nfrom conan.internal.util.files import mkdir\nfrom conan.internal.util.runners import check_output_runner\n\n\nclass Git:\n    \"\"\"\n    Git is a wrapper for several common patterns used with *git* tool.\n    \"\"\"\n    def __init__(self, conanfile, folder=\".\", excluded=None):\n        \"\"\"\n        :param conanfile: Conanfile instance.\n        :param folder: Current directory, by default ``.``, the current working directory.\n        :param excluded: Files to be excluded from the \"dirty\" checks. It will compose with the\n          configuration ``core.scm:excluded`` (the configuration has higher priority).\n          It is a list of patterns to ``fnmatch``.\n        \"\"\"\n        self._conanfile = conanfile\n        self.folder = folder\n        self._excluded = excluded\n        global_conf = conanfile._conan_helpers.global_conf  # noqa _conan_helpers\n        conf_excluded = global_conf.get(\"core.scm:excluded\", check_type=list)\n        if conf_excluded:\n            if excluded:\n                c = ConfDefinition()\n                c.loads(f\"core.scm:excluded={excluded}\")\n                c.update_conf_definition(global_conf)\n                self._excluded = c.get(\"core.scm:excluded\", check_type=list)\n            else:\n                self._excluded = conf_excluded\n        self._local_url = global_conf.get(\"core.scm:local_url\", choices=[\"allow\", \"block\"])\n\n    def run(self, cmd, hidden_output=None):\n        \"\"\"\n        Executes ``git <cmd>``\n\n        :return: The console output of the command.\n        \"\"\"\n        print_cmd = cmd if hidden_output is None else cmd.replace(hidden_output, \"<hidden>\")\n        self._conanfile.output.info(f\"RUN: git {print_cmd}\", fg=Color.BRIGHT_BLUE)\n        with chdir(self._conanfile, self.folder):\n            # We tried to use self.conanfile.run(), but it didn't work:\n            #  - when using win_bash, crashing because access to .settings (forbidden in source())\n            #  - the ``conan source`` command, not passing profiles, buildenv not injected\n            return check_output_runner(\"git {}\".format(cmd)).strip()\n\n    def get_commit(self, repository=False):\n        \"\"\"\n        :param repository: By default gets the commit of the defined folder, use repo=True to get\n                     the commit of the repository instead.\n        :return: The current commit, with ``git rev-list HEAD -n 1 -- <folder>``.\n            The latest commit is returned, irrespective of local not committed changes.\n        \"\"\"\n        try:\n            # commit = self.run(\"rev-parse HEAD\") For the whole repo\n            # This rev-list knows to capture the last commit for the folder\n            # --full-history is needed to not avoid wrong commits:\n            # https://github.com/conan-io/conan/issues/10971\n            # https://git-scm.com/docs/git-rev-list#Documentation/git-rev-list.txt-Defaultmode\n            path = '' if repository else '-- \".\"'\n            commit = self.run(f'rev-list HEAD -n 1 --full-history {path}')\n            return commit\n        except Exception as e:\n            raise ConanException(\"Unable to get git commit in '%s': %s\" % (self.folder, str(e)))\n\n    def get_remote_url(self, remote=\"origin\"):\n        \"\"\"\n        Obtains the URL of the remote git remote repository, with ``git remote -v``\n\n        **Warning!**\n        Be aware that This method will get the output from ``git remote -v``.\n        If you added tokens or credentials to the remote in the URL, they will be exposed.\n        Credentials shouldn’t be added to git remotes definitions, but using a credentials manager\n        or similar mechanism. If you still want to use this approach, it is your responsibility\n        to strip the credentials from the result.\n\n        :param remote: Name of the remote git repository ('origin' by default).\n        :return: URL of the remote git remote repository.\n        \"\"\"\n        remotes = self.run(\"remote -v\")\n        for r in remotes.splitlines():\n            name, url = r.split(maxsplit=1)\n            if name == remote:\n                url, _ = url.rsplit(None, 1)\n                # if the url still has (fetch) or (push) at the end\n                if url.endswith(\"(fetch)\") or url.endswith(\"(push)\"):\n                    url, _ = url.rsplit(None, 1)\n                if os.path.exists(url):  # Windows local directory\n                    url = url.replace(\"\\\\\", \"/\")\n                return url\n\n    def commit_in_remote(self, commit, remote=\"origin\"):\n        \"\"\"\n        Checks that the given commit exists in the remote, with ``branch -r --contains <commit>``\n        and checking an occurrence of a branch in that remote exists.\n\n        :param commit: Commit to check.\n        :param remote: Name of the remote git repository ('origin' by default).\n        :return: True if the given commit exists in the remote, False otherwise.\n        \"\"\"\n        if not remote:\n            return False\n        # Potentially do two checks here.  If the clone is a shallow clone, then we won't be\n        # able to find the commit.\n        try:\n            branches = self.run(\"branch -r --contains {}\".format(commit))\n            if \"{}/\".format(remote) in branches:\n                return True\n        except Exception as e:\n            raise ConanException(\"Unable to check remote commit in '%s': %s\" % (self.folder, str(e)))\n\n        try:\n            # This will raise if commit not present.\n            self.run(f\"fetch {remote} --refetch --dry-run {commit}\")\n            return True\n        except (Exception,):\n            # For example, if using an older git<2.36, see\n            # https://github.com/conan-io/conan/issues/18470, then lets try the old approach\n            try:\n                # This will raise if commit not present.\n                self.run(\"fetch {} --dry-run --depth=1 {}\".format(remote, commit))\n                return True\n            except (Exception,):\n                # Don't raise an error because it could fail for many more reasons.\n                return False\n\n    def is_dirty(self, repository=False):\n        \"\"\"\n        Returns if the current folder is dirty, running ``git status -s``\n        The ``Git(..., excluded=[])`` argument and the ``core.scm:excluded`` configuration will\n        define file patterns to be skipped from this check.\n\n        :param repository: By default checks if the current folder is dirty. If repository=True\n                     it will check the root repository folder instead, not the current one.\n        :return: True, if the current folder is dirty. Otherwise, False.\n        \"\"\"\n        path = '' if repository else '.'\n        status = self.run(f\"status {path} --short --no-branch --untracked-files\").strip()\n        self._conanfile.output.debug(f\"Git status:\\n{status}\")\n        if not self._excluded:\n            return bool(status)\n        # Parse the status output, line by line, and match it with \"_excluded\"\n        lines = [line.strip() for line in status.splitlines()]\n        # line is of the form STATUS PATH, get the path by splitting\n        # (Taking into account that STATUS is one word, PATH might be many)\n        lines = [line.split(maxsplit=1)[1].strip('\"') for line in lines if line]\n        lines = [line for line in lines if not any(fnmatch.fnmatch(line, p) for p in self._excluded)]\n        self._conanfile.output.debug(f\"Filtered git status: {lines}\")\n        return bool(lines)\n\n    def get_url_and_commit(self, remote=\"origin\", repository=False):\n        \"\"\"\n        This is an advanced method, that returns both the current commit, and the remote repository url.\n        This method is intended to capture the current remote coordinates for a package creation,\n        so that can be used later to build again from sources from the same commit. This is the behavior:\n\n        * If the repository is dirty, it will raise an exception. Doesn’t make sense to capture coordinates\n          of something dirty, as it will not be reproducible. If there are local changes, and the\n          user wants to test a local conan create, should commit the changes first (locally, not push the changes).\n\n        * If the repository is not dirty, but the commit doesn’t exist in the given remote, the method\n          will return that commit and the URL of the local user checkout. This way, a package can be\n          conan create created locally, testing everything works, before pushing some changes to the remote.\n\n        * If the repository is not dirty, and the commit exists in the specified remote, it will\n          return that commit and the url of the remote.\n\n        **Warning!**\n        Be aware that This method will get the output from ``git remote -v``.\n        If you added tokens or credentials to the remote in the URL, they will be exposed.\n        Credentials shouldn’t be added to git remotes definitions, but using a credentials manager\n        or similar mechanism. If you still want to use this approach, it is your responsibility\n        to strip the credentials from the result.\n\n        :param remote: Name of the remote git repository ('origin' by default).\n        :param repository: By default gets the commit of the defined folder, use repo=True to get\n                     the commit of the repository instead.\n        :return: (url, commit) tuple\n        \"\"\"\n        dirty = self.is_dirty(repository=repository)\n        if dirty:\n            raise ConanException(\"Repo is dirty, cannot capture url and commit: \"\n                                 \"{}\".format(self.folder))\n        commit = self.get_commit(repository=repository)\n        url = self.get_remote_url(remote=remote)\n        in_remote = self.commit_in_remote(commit, remote=remote)\n        if in_remote:\n            return url, commit\n        if self._local_url == \"block\":\n            raise ConanException(f\"Current commit {commit} doesn't exist in remote {remote}\\n\"\n                                 \"Failing according to 'core.scm:local_url=block' conf\")\n\n        if self._local_url != \"allow\":\n            self._conanfile.output.warning(\"Current commit {} doesn't exist in remote {}\\n\"\n                                           \"This revision will not be buildable in other \"\n                                           \"computer\".format(commit, remote))\n        return self.get_repo_root(), commit\n\n    def get_repo_root(self):\n        \"\"\"\n        Get the current repository top folder with ``git rev-parse --show-toplevel``\n\n        :return: Repository top folder.\n        \"\"\"\n        folder = self.run(\"rev-parse --show-toplevel\")\n        return folder.replace(\"\\\\\", \"/\")\n\n    def clone(self, url, target=\"\", args=None, hide_url=True):\n        \"\"\"\n        Performs a ``git clone <url> <args> <target>`` operation, where target is the target directory.\n\n        :param url: URL of remote repository.\n        :param target: Target folder.\n        :param args: Extra arguments to pass to the git clone as a list.\n        :param hide_url: Hides the URL from the log output to prevent accidental\n                     credential leaks. Can be disabled by passing ``False``.\n        \"\"\"\n        args = args or []\n        if os.path.exists(url):\n            url = url.replace(\"\\\\\", \"/\")  # Windows local directory\n        mkdir(self.folder)\n        self._conanfile.output.info(\"Cloning git repo\")\n        target_path = f'\"{target}\"' if target else \"\"  # quote in case there are spaces in path\n        # Avoid printing the clone command, it can contain tokens\n        self.run('clone \"{}\" {} {}'.format(url, \" \".join(args), target_path),\n                 hidden_output=url if hide_url else None)\n\n    def fetch_commit(self, url, commit, hide_url=True):\n        \"\"\"\n        Experimental: does a single commit fetch and checkout, instead of a full clone,\n        should be faster.\n\n        :param url: URL of remote repository.\n        :param commit: The commit ref to checkout.\n        :param hide_url: Hides the URL from the log output to prevent accidental\n                     credential leaks. Can be disabled by passing ``False``.\n        \"\"\"\n        if os.path.exists(url):\n            url = url.replace(\"\\\\\", \"/\")  # Windows local directory\n        mkdir(self.folder)\n        self._conanfile.output.info(\"Shallow fetch of git repo\")\n        self.run('init')\n        self.run(f'remote add origin \"{url}\"', hidden_output=url if hide_url else None)\n        self.run(f'fetch --depth 1 origin {commit}')\n        self.run('checkout FETCH_HEAD')\n\n    def checkout(self, commit):\n        \"\"\"\n        Checkouts the given commit using ``git checkout <commit>``.\n\n        :param commit: Commit to checkout.\n        \"\"\"\n        self._conanfile.output.info(\"Checkout: {}\".format(commit))\n        self.run('checkout {}'.format(commit))\n\n    def included_files(self):\n        \"\"\"\n        Run ``git ls-files --full-name --others --cached --exclude-standard`` to the get the list\n            of files not ignored by ``.gitignore``\n\n        :return: List of files.\n        \"\"\"\n        files = self.run(\"ls-files --full-name --others --cached --exclude-standard\")\n        files = files.splitlines()\n        return files\n\n    def coordinates_to_conandata(self, repository=False):\n        \"\"\"\n        Capture the \"url\" and \"commit\" from the Git repo, calling ``get_url_and_commit()``, and then\n        store those in the ``conandata.yml`` under the \"scm\" key. This information can be\n        used later to clone and checkout the exact source point that was used to create this\n        package, and can be useful even if the recipe uses ``exports_sources`` as mechanism to\n        embed the sources.\n\n        :param repository: By default gets the commit of the defined folder, use repository=True to get\n                     the commit of the repository instead.\n        \"\"\"\n        scm_url, scm_commit = self.get_url_and_commit(repository=repository)\n        update_conandata(self._conanfile, {\"scm\": {\"commit\": scm_commit, \"url\": scm_url}})\n\n    def checkout_from_conandata_coordinates(self):\n        \"\"\"\n        Reads the \"scm\" field from the ``conandata.yml``, that must contain at least \"url\" and\n        \"commit\" and then do a ``clone(url, target=\".\")``, ``fetch <commit>``, followed by a ``checkout(commit)``.\n        \"\"\"\n        sources = self._conanfile.conan_data[\"scm\"]\n        self.clone(url=sources[\"url\"], target=\".\", args=[\"--origin=origin\"])\n        self.run(f\"fetch origin {sources['commit']}\")\n        self.checkout(commit=sources[\"commit\"])\n"
  },
  {
    "path": "conan/tools/scons/__init__.py",
    "content": "from conan.tools.scons.sconsdeps import SConsDeps\n"
  },
  {
    "path": "conan/tools/scons/sconsdeps.py",
    "content": "from jinja2 import Template\n\nfrom conan.tools import CppInfo\nfrom conan.internal.util.files import save\n\n\nclass SConsDeps:\n    def __init__(self, conanfile):\n        self._conanfile = conanfile\n        self._ordered_deps = None\n        self._generator_file = 'SConscript_conandeps'\n\n    @property\n    def ordered_deps(self):\n        if self._ordered_deps is None:\n            deps = self._conanfile.dependencies.host.topological_sort\n            self._ordered_deps = [dep for dep in reversed(deps.values())]\n        return self._ordered_deps\n\n    def _get_cpp_info(self):\n        ret = CppInfo(self._conanfile)\n        for dep in self.ordered_deps:\n            dep_cppinfo = dep.cpp_info.aggregated_components()\n            ret.merge(dep_cppinfo)\n        return ret\n\n    def generate(self):\n        save(self._generator_file, self._content)\n\n    @property\n    def _content(self):\n        template = Template(\"\"\"\n        \"{{dep_name}}\" : {\n            \"CPPPATH\"     : {{info.includedirs or []}},\n            \"LIBPATH\"     : {{info.libdirs or []}},\n            \"BINPATH\"     : {{info.bindirs or []}},\n            \"LIBS\"        : {{(info.libs or []) + (info.system_libs or [])}},\n            \"FRAMEWORKS\"  : {{info.frameworks or []}},\n            \"FRAMEWORKPATH\" : {{info.frameworkdirs or []}},\n            \"CPPDEFINES\"  : {{info.defines or []}},\n            \"CXXFLAGS\"    : {{info.cxxflags or []}},\n            \"CCFLAGS\"     : {{info.cflags or []}},\n            \"SHLINKFLAGS\" : {{info.sharedlinkflags or []}},\n            \"LINKFLAGS\"   : {{info.exelinkflags or []}},\n        },\n        {% if dep_version is not none %}\"{{dep_name}}_version\" : \"{{dep_version}}\",{% endif %}\n        \"\"\")\n        sections = [\"conandeps = {\\n\"]\n        all_flags = template.render(dep_name=\"conandeps\", dep_version=None,\n                                    info=self._get_cpp_info())\n        sections.append(all_flags)\n\n        # TODO: Add here in 2.0 the \"skip\": False trait\n        host_req = self._conanfile.dependencies.filter({\"build\": False}).values()\n        for dep in host_req:\n            dep_flags = template.render(dep_name=dep.ref.name, dep_version=dep.ref.version,\n                                        info=dep.cpp_info)\n            sections.append(dep_flags)\n        sections.append(\"}\\n\")\n        sections.append(\"Return('conandeps')\\n\")\n        return \"\\n\".join(sections)\n"
  },
  {
    "path": "conan/tools/system/__init__.py",
    "content": "from conan.tools.system.python_manager import PyEnv, PipEnv\n"
  },
  {
    "path": "conan/tools/system/package_manager.py",
    "content": "import platform\n\nfrom conan.tools.build import cross_building\nfrom conan.internal.graph.graph import CONTEXT_BUILD\nfrom conan.errors import ConanException\n\n\nclass _SystemPackageManagerTool:\n    mode_check = \"check\"  # Check if installed, fail if not\n    mode_install = \"install\"\n    mode_report = \"report\"  # Only report what would be installed, no check (can run in any system)\n    mode_report_installed = \"report-installed\"  # report installed and missing packages\n    tool_name = None\n    version_separator = \"\"\n    install_command = \"\"\n    update_command = \"\"\n    check_command = \"\"\n    check_version_command = \"\"\n    full_package_name = \"{name}{arch_separator}{arch_name}\"\n    accepted_install_codes = [0]\n    accepted_update_codes = [0]\n    accepted_check_codes = [0, 1]\n\n    def __init__(self, conanfile):\n        \"\"\"\n        :param conanfile: The current recipe object. Always use ``self``.\n        \"\"\"\n        self._conanfile = conanfile\n        self._active_tool = self._conanfile.conf.get(\"tools.system.package_manager:tool\", default=self.get_default_tool())\n        self._sudo = self._conanfile.conf.get(\"tools.system.package_manager:sudo\", default=False, check_type=bool)\n        self._sudo_askpass = self._conanfile.conf.get(\"tools.system.package_manager:sudo_askpass\", default=False, check_type=bool)\n        self._mode = self._conanfile.conf.get(\"tools.system.package_manager:mode\", default=self.mode_check)\n        self._arch = self._conanfile.settings_build.get_safe('arch') \\\n            if self._conanfile.context == CONTEXT_BUILD else self._conanfile.settings.get_safe('arch')\n        self._arch_names = {}\n        self._arch_separator = \"\"\n\n    def get_default_tool(self):\n        os_name = platform.system()\n        if os_name in [\"Linux\", \"FreeBSD\"]:\n            import distro\n            os_name = distro.id() or os_name\n        elif os_name == \"Windows\" and self._conanfile.settings.get_safe(\"os.subsystem\") == \"msys2\":\n            os_name = \"msys2\"\n        manager_mapping = {\"apt-get\": [\"Linux\", \"ubuntu\", \"debian\", \"raspbian\", \"linuxmint\",\n                                       'astra', 'elbrus', 'altlinux', 'pop'],\n                           \"apk\": [\"alpine\"],\n                           \"yum\": [\"pidora\", \"scientific\", \"xenserver\", \"amazon\", \"amzn\"],\n                           \"dnf\": [\"fedora\", \"rhel\", \"centos\", \"mageia\", \"nobara\", \"almalinux\",\n                                   \"rocky\", \"oracle\"],\n                           \"brew\": [\"Darwin\"],\n                           \"pacman\": [\"arch\", \"manjaro\", \"msys2\", \"endeavouros\"],\n                           \"choco\": [\"Windows\"],\n                           \"zypper\": [\"opensuse\", \"sles\"],\n                           \"pkg\": [\"freebsd\"],\n                           \"pkgutil\": [\"Solaris\"]}\n        # first check exact match of name\n        for tool, distros in manager_mapping.items():\n            if os_name in distros:\n                return tool\n        # in case we did not detect any exact match, check\n        # if the name is contained inside the returned distro name\n        # like for opensuse, that can have opensuse-version names\n        for tool, distros in manager_mapping.items():\n            for d in distros:\n                if d in os_name:\n                    return tool\n\n        # No default package manager was found for the system,\n        # so notify the user\n        self._conanfile.output.info(\"A default system package manager couldn't be found for {}, \"\n                                    \"system packages will not be installed.\".format(os_name))\n\n    def _split_package_name(self, package, host_package):\n\n        name, version = (package.split(\"=\")[0], package.split(\"=\")[1]) if \"=\" in package else (package, \"\")\n        arch_separator, arch_name = \"\", \"\"\n        version_separator = self.version_separator if version else \"\"\n\n        if self._arch in self._arch_names and cross_building(self._conanfile) and host_package:\n            arch_separator = self._arch_separator\n            arch_name = self._arch_names.get(self._arch)\n        return name, version, arch_separator, arch_name, version_separator\n\n    def get_package_name(self, package, host_package=True):\n        # Only if the package is for building, for example a library,\n        # we should add the host arch when cross building.\n        # If the package is a tool that should be installed on the current build\n        # machine we should not add the arch.\n\n        name, version, arch_separator, arch_name, version_separator = self._split_package_name(package, host_package)\n\n        return self.full_package_name.format(name=name,\n                                             arch_separator=arch_separator,\n                                             arch_name=arch_name,\n                                             version_separator=version_separator,\n                                             version=version)\n\n    @property\n    def sudo_str(self):\n        sudo = \"sudo \" if self._sudo else \"\"\n        askpass = \"-A \" if self._sudo and self._sudo_askpass else \"\"\n        return \"{}{}\".format(sudo, askpass)\n\n    def run(self, method, *args, **kwargs):\n        if self._active_tool == self.__class__.tool_name:\n            return method(*args, **kwargs)\n\n    def _conanfile_run(self, command, accepted_returns, quiet=True):\n        # When checking multiple packages, this is too noisy\n        ret = self._conanfile.run(command, ignore_errors=True, quiet=quiet)\n        if ret not in accepted_returns:\n            raise ConanException(\"Command '%s' failed\" % command)\n        return ret\n\n    def install_substitutes(self, *args, **kwargs):\n        \"\"\"\n        Will try to call the install() method with  several lists of packages passed as a\n        variable number of parameters. This is useful if, for example, the names of the\n        packages are different from one distro or distro version to another. For example,\n        ``libxcb`` for ``Apt`` is named ``libxcb-util-dev`` in Ubuntu >= 15.0 and ``libxcb-util0-dev``\n        for other versions. You can call to:\n\n           .. code-block:: python\n\n            # will install the first list of packages that succeeds in the installation\n            Apt.install_substitutes([\"libxcb-util-dev\"], [\"libxcb-util0-dev\"])\n\n        :param packages_alternatives: try to install the list of packages passed as a parameter.\n        :param update: try to update the package manager database before checking and installing.\n        :param check: check if the packages are already installed before installing them.\n        :return: the return code of the executed package manager command.\n        \"\"\"\n        return self.run(self._install_substitutes, *args, **kwargs)\n\n    def install(self, *args, **kwargs):\n        \"\"\"\n        Will try to install the list of packages passed as a parameter. Its\n        behaviour is affected by the value of ``tools.system.package_manager:mode``\n        :ref:`configuration<conan_tools_system_package_manager_config>`.\n\n        :param packages: try to install the list of packages passed as a parameter.\n        :param update: try to update the package manager database before checking and installing.\n        :param check: check if the packages are already installed before installing them.\n        :return: the return code of the executed package manager command.\n        \"\"\"\n        return self.run(self._install, *args, **kwargs)\n\n    def update(self, *args, **kwargs):\n        \"\"\"\n        Update the system package manager database. Its behaviour is affected by\n        the value of ``tools.system.package_manager:mode``\n        :ref:`configuration<conan_tools_system_package_manager_config>`.\n\n        :return: the return code of the executed package manager update command.\n        \"\"\"\n        return self.run(self._update, *args, **kwargs)\n\n    def check(self, *args, **kwargs):\n        \"\"\"\n        Check if the list of packages passed as parameter are already installed.\n\n        :param packages: list of packages to check.\n        :return: list of packages from the packages argument that are not installed in the system.\n        \"\"\"\n        return self.run(self._check, *args, **kwargs)\n\n    def _install_substitutes(self, *packages_substitutes, update=False, check=True, **kwargs):\n        errors = []\n        for packages in packages_substitutes:\n            try:\n                return self.install(packages, update, check, **kwargs)\n            except ConanException as e:\n                errors.append(e)\n\n        for error in errors:\n            self._conanfile.output.warning(str(error))\n        raise ConanException(\"None of the installs for the package substitutes succeeded.\")\n\n    def _install(self, packages, update=False, check=True, host_package=True, **kwargs):\n        orig_packages = packages\n        pkgs = self._conanfile.system_requires.setdefault(self._active_tool, {})\n        install_pkgs = pkgs.setdefault(\"install\", [])\n        install_pkgs.extend(p for p in packages if p not in install_pkgs)\n        if self._mode == self.mode_report:\n            return\n\n        if check or self._mode in (self.mode_check, self.mode_report_installed):\n            packages = self.check(packages, host_package=host_package)\n            missing_pkgs = pkgs.setdefault(\"missing\", [])\n            missing_pkgs.extend(p for p in packages if p not in missing_pkgs)\n        if self._mode == self.mode_report_installed:\n            return\n\n        if self._mode == self.mode_check and packages:\n            raise ConanException(\"System requirements: '{0}' are missing but can't install \"\n                                 \"because tools.system.package_manager:mode is '{1}'.\"\n                                 \"Please update packages manually or set \"\n                                 \"'tools.system.package_manager:mode' \"\n                                 \"to '{2}' in the [conf] section of the profile, \"\n                                 \"or in the command line using \"\n                                 \"'-c tools.system.package_manager:mode={2}'\".format(\", \".join(packages),\n                                                                                     self.mode_check,\n                                                                                     self.mode_install))\n        elif packages:\n            if update:\n                self.update()\n            packages_arch = [self.get_package_name(package, host_package=host_package) for package in packages]\n            if packages_arch:\n                command = self.install_command.format(sudo=self.sudo_str,\n                                                      tool=self.tool_name,\n                                                      packages=\" \".join(packages_arch),\n                                                      **kwargs)\n                return self._conanfile_run(command, self.accepted_install_codes, quiet=False)\n        else:\n            self._conanfile.output.info(f\"System requirements: {' '.join(orig_packages)} already installed\")\n\n    def _update(self):\n        # we just update the package manager database in case we are in 'install mode'\n        # in case we are in check mode just ignore\n        if self._mode == self.mode_install:\n            command = self.update_command.format(sudo=self.sudo_str, tool=self.tool_name)\n            return self._conanfile_run(command, self.accepted_update_codes, quiet=False)\n\n    def _check(self, packages, host_package=True):\n        missing = [pkg for pkg in packages if self.check_package(pkg, host_package) != 0]\n        return missing\n\n    def check_package(self, package, host_package=True):\n        name, version, arch_separator, arch_name, _ = self._split_package_name(package, host_package)\n\n        check_arch = self._arch if host_package else self._conanfile.settings_build.get_safe('arch')\n        arch_package = arch_name or self._arch_names.get(check_arch)\n        package = self.full_package_name.format(name=name,\n                                                arch_separator=arch_separator,\n                                                arch_name=arch_name,\n                                                version=\"\",\n                                                version_separator=\"\")\n        command = self.check_command.format(tool=self.tool_name, package=package, arch_package=arch_package, base_name=name)\n\n        if version:\n            if self.check_version_command:\n                command = self.check_version_command.format(tool=self.tool_name, package=package, version=version, arch_package=arch_package,\n                                                            base_name=name)\n            else:\n                self._conanfile.output.warning(f\"System requirements: \\\"{self.tool_name}\\\" doesn't support package versions,\"\n                                               f\" \\\"{package}\\\" will be installed without a specific version.\")\n        return self._conanfile_run(command, self.accepted_check_codes)\n\n\nclass Apt(_SystemPackageManagerTool):\n    # TODO: apt? apt-get?\n    tool_name = \"apt-get\"\n    version_separator = \"=\"\n    full_package_name = \"{name}{arch_separator}{arch_name}{version_separator}{version}\"\n    install_command = \"{sudo}{tool} install -y {recommends}{packages}\"\n    update_command = \"{sudo}{tool} update\"\n    check_command = r\"dpkg-query -W -f='${{Architecture}}\\n' {base_name} | grep -qEx '({arch_package}|all)'\"\n    check_version_command = r\"dpkg-query -W -f='${{Architecture}} ${{Version}}\\n' {base_name} | grep -qEx '({arch_package}|all) {version}'\"\n\n    def __init__(self, conanfile, arch_names=None):\n        \"\"\"\n        :param conanfile: The current recipe object. Always use ``self``.\n        :param arch_names: This argument maps the Conan architecture setting with the package manager\n                           tool architecture names. It is ``None`` by default, which means that it will use a\n                           default mapping for the most common architectures. For example, if you are using\n                           ``x86_64`` Conan architecture setting, it will map this value to ``amd64`` for *Apt* and\n                           try to install the ``<package_name>:amd64`` package.\n        \"\"\"\n        super(Apt, self).__init__(conanfile)\n        self._arch_names = {\"x86_64\": \"amd64\",\n                            \"x86\": \"i386\",\n                            \"ppc32\": \"powerpc\",\n                            \"ppc64le\": \"ppc64el\",\n                            \"armv7\": \"arm\",\n                            \"armv7hf\": \"armhf\",\n                            \"armv8\": \"arm64\",\n                            \"s390x\": \"s390x\",\n                            \"riscv64\": \"riscv64\"} if arch_names is None else arch_names\n\n        self._arch_separator = \":\"\n\n    def install(self, packages, update=False, check=True, recommends=False, host_package=True):\n        \"\"\"\n        Will try to install the list of packages passed as a parameter. Its\n        behaviour is affected by the value of ``tools.system.package_manager:mode``\n        :ref:`configuration<conan_tools_system_package_manager_config>`.\n\n        :param packages: try to install the list of packages passed as a parameter.\n        :param update: try to update the package manager database before checking and installing.\n        :param check: check if the packages are already installed before installing them.\n        :param host_package: install the packages for the host machine architecture (the machine\n               that will run the software), it has an effect when cross building.\n        :param recommends: if the parameter ``recommends`` is ``False`` it will add the\n               ``'--no-install-recommends'`` argument to the *apt-get* command call.\n        :return: the return code of the executed apt command.\n        \"\"\"\n        recommends_str = '' if recommends else '--no-install-recommends '\n        return super(Apt, self).install(packages, update=update, check=check,\n                                        host_package=host_package, recommends=recommends_str)\n\n\nclass Yum(_SystemPackageManagerTool):\n    tool_name = \"yum\"\n    version_separator = \"-\"\n    full_package_name = \"{name}{version_separator}{version}{arch_separator}{arch_name}\"\n    install_command = \"{sudo}{tool} install -y {packages}\"\n    update_command = \"{sudo}{tool} check-update -y\"\n    check_command = \"rpm -q {package}\"\n    check_version_command = \"rpm -q {package}-{version}\"\n    accepted_update_codes = [0, 100]\n\n    def __init__(self, conanfile, arch_names=None):\n        \"\"\"\n        :param conanfile: the current recipe object. Always use ``self``.\n        :param arch_names: this argument maps the Conan architecture setting with the package manager\n                           tool architecture names. It is ``None`` by default, which means that it will use a\n                           default mapping for the most common architectures. For example, if you are using\n                           ``x86`` Conan architecture setting, it will map this value to ``i?86`` for *Yum* and\n                           try to install the ``<package_name>.i?86`` package.\n        \"\"\"\n        super(Yum, self).__init__(conanfile)\n        self._arch_names = {\"x86_64\": \"x86_64\",\n                            \"x86\": \"i?86\",\n                            \"ppc32\": \"powerpc\",\n                            \"ppc64le\": \"ppc64le\",\n                            \"armv7\": \"armv7\",\n                            \"armv7hf\": \"armv7hl\",\n                            \"armv8\": \"aarch64\",\n                            \"s390x\": \"s390x\",\n                            \"riscv64\": \"riscv64\"} if arch_names is None else arch_names\n        self._arch_separator = \".\"\n\n\nclass Dnf(Yum):\n    tool_name = \"dnf\"\n    version_separator = \"-\"\n    full_package_name = \"{name}{version_separator}{version}{arch_separator}{arch_name}\"\n    check_version_command = \"rpm -q {package}-{version}\"\n\n\nclass Brew(_SystemPackageManagerTool):\n    tool_name = \"brew\"\n    version_separator = \"@\"\n    full_package_name = \"{name}{version_separator}{version}\"\n    install_command = \"{sudo}{tool} install {packages}\"\n    update_command = \"{sudo}{tool} update\"\n    check_command = 'test -n \"$({tool} ls --versions {package})\"'\n    check_version_command = 'brew list --versions {package} | grep \"{version}\"'\n\n\nclass Pkg(_SystemPackageManagerTool):\n    tool_name = \"pkg\"\n    version_separator = \"-\"\n    full_package_name = \"{name}{version_separator}{version}\"\n    install_command = \"{sudo}{tool} install -y {packages}\"\n    update_command = \"{sudo}{tool} update\"\n    check_command = \"{tool} info {package}\"\n    check_version_command = \"{tool} info {package} | grep \\\"Version: {version}\\\"\"\n\n\nclass PkgUtil(_SystemPackageManagerTool):\n    tool_name = \"pkgutil\"\n    version_separator = \"@\"\n    full_package_name = \"{name}{version_separator}{version}\"\n    install_command = \"{sudo}{tool} --install --yes {packages}\"\n    update_command = \"{sudo}{tool} --catalog\"\n    check_command = 'test -n \"`{tool} --list {package}`\"'\n\n\nclass Chocolatey(_SystemPackageManagerTool):\n    tool_name = \"choco\"\n    version_separator = \" --version \"\n    full_package_name = \"{name}{version_separator}{version}\"\n    install_command = \"{tool} install --yes {packages}\"\n    update_command = \"{tool} outdated\"\n    check_command = '{tool} list --exact {package} | findstr /c:\"1 packages installed.\"'\n    check_version_command = '{tool} list --local-only {package} | findstr /i \"{version}\"'\n\n\nclass PacMan(_SystemPackageManagerTool):\n    tool_name = \"pacman\"\n    install_command = \"{sudo}{tool} -S --noconfirm {packages}\"\n    update_command = \"{sudo}{tool} -Syyu --noconfirm\"\n    check_command = \"{tool} -Qi {package}\"\n\n    def __init__(self, conanfile, arch_names=None):\n        \"\"\"\n        :param conanfile: the current recipe object. Always use ``self``.\n        :param arch_names: this argument maps the Conan architecture setting with the package manager\n                           tool architecture names. It is ``None`` by default, which means that it will use a\n                           default mapping for the most common architectures. If you are using\n                           ``x86`` Conan architecture setting, it will map this value to ``lib32`` for *PacMan* and\n                           try to install the ``<package_name>-lib32`` package.\n        \"\"\"\n        super(PacMan, self).__init__(conanfile)\n        self._arch_names = {\"x86\": \"lib32\"} if arch_names is None else arch_names\n        self._arch_separator = \"-\"\n\n\nclass Apk(_SystemPackageManagerTool):\n    tool_name = \"apk\"\n    version_separator = \"=\"\n    full_package_name = \"{name}{version_separator}{version}\"\n    install_command = \"{sudo}{tool} add --no-cache {packages}\"\n    update_command = \"{sudo}{tool} update\"\n    check_command = \"{tool} info -e {package}\"\n    check_version_command = \"{tool} info {package} | grep \\\"{version}\\\"\"\n\n    def __init__(self, conanfile, _arch_names=None):\n        \"\"\"\n        Constructor method.\n        Note that *Apk* does not support architecture names since Alpine Linux does not support\n        multiarch. Therefore, the ``arch_names`` argument is ignored.\n\n        :param conanfile: the current recipe object. Always use ``self``.\n        \"\"\"\n        super(Apk, self).__init__(conanfile)\n        self._arch_names = {}\n        self._arch_separator = \"\"\n\n\nclass Zypper(_SystemPackageManagerTool):\n    tool_name = \"zypper\"\n    version_separator = \"=\"  # < or >\n    full_package_name = \"{name}{arch_separator}{arch_name}{version_separator}{version}\"\n    install_command = \"{sudo}{tool} --non-interactive in {packages}\"\n    update_command = \"{sudo}{tool} --non-interactive ref\"\n    check_command = \"rpm -q {package}\"\n    check_version_command = \"rpm -q {package}-{version}\"\n"
  },
  {
    "path": "conan/tools/system/python_manager.py",
    "content": "import platform\nimport os\nimport shutil\nimport sys\n\nfrom conan.tools.build import cmd_args_to_string\nfrom conan.tools.env.environment import Environment\nfrom conan.errors import ConanException\n\nfrom conan.api.output import (\n    ConanOutput,\n    LEVEL_QUIET,\n    LEVEL_ERROR,\n    LEVEL_WARNING,\n    LEVEL_STATUS,\n    LEVEL_VERBOSE,\n    LEVEL_DEBUG,\n    LEVEL_TRACE,\n)\n\nfrom conan.internal.util.files import rmdir\n\n\ndef _get_pip_verbosity():\n    return {\n        LEVEL_QUIET: \"-qqq\",\n        LEVEL_ERROR: \"-qq\",\n        LEVEL_WARNING: \"-q\",\n        LEVEL_VERBOSE: \"-v\",\n        LEVEL_DEBUG: \"-vv\",\n        LEVEL_TRACE: \"-vvv\",\n    }.get(ConanOutput.get_output_level(), \"\")\n\n\ndef _get_uv_verbosity():\n    return {\n        LEVEL_QUIET: \"-qq\",\n        LEVEL_ERROR: \"-qq\",\n        LEVEL_WARNING: \"-q\",\n        LEVEL_VERBOSE: \"--verbose\",\n        LEVEL_DEBUG: \"--verbose\",\n        LEVEL_TRACE: \"--verbose\",\n    }.get(ConanOutput.get_output_level(), \"\")\n\n\nclass PyEnv:\n\n    def __init__(self, conanfile, folder=None, name=\"\", py_version=None):\n        \"\"\"\n        :param conanfile: The current conanfile ``self``\n        :param folder: Optional folder, by default the ``build_folder``\n        :param name: Optional name for the virtualenv, by default ``conan_pyenv``\n        :param py_version: Optional python version to create the virtualenv using UV\n        \"\"\"\n        if sys.version_info.minor < 8 and py_version:\n            raise ConanException(\"'uv' needs Python >= 3.8. Please upgrade your Python interpreter\"\n                                 \" or use 'PyEnv' without defining the 'py_version'.\")\n\n        self._conanfile = conanfile\n        self._default_python = self._conanfile.conf.get(\"tools.system.pyenv:python_interpreter\")\n        # tools.system.pipenv deprecated warning message.\n        if not self._default_python and self._conanfile.conf.get(\"tools.system.pipenv:python_interpreter\"):\n            self._default_python = self._conanfile.conf.get(\"tools.system.pipenv:python_interpreter\")\n            ConanOutput().warning(\"'tools.system.pipenv:python_interpreter' \"\n                                  \"is deprecated, use 'tools.system.pyenv:python_interpreter'\",\n                                  warn_tag=\"deprecated\")\n\n        if not self._default_python:\n            python = \"python\" if platform.system() == \"Windows\" else \"python3\"\n            default_python = shutil.which(python)\n            self._default_python = os.path.realpath(default_python) if default_python else None\n        if not self._default_python:\n            raise ConanException(\"Conan could not find a Python executable path. Please, install \"\n                                 \"Python system-wide or set the \"\n                                 \"'tools.system.pyenv:python_interpreter' \"\n                                 \"conf to the full path of a Python executable\")\n        self._env_name = f\"conan_pyenv{f'_{name}' if name else ''}\"\n        if py_version:\n            self._env_name += f'_{py_version.replace(\".\", \"_\")}'\n        base_env_dir = os.path.abspath(folder or conanfile.build_folder)\n        self._env_dir = os.path.join(base_env_dir, self._env_name)\n        if not os.path.exists(self._env_dir):\n            if py_version:\n                self._create_uv_venv(base_env_dir, py_version)\n            else:\n                self._create_venv()\n\n    @property\n    def env_dir(self):\n        \"\"\"Root directory of the virtual environment.\"\"\"\n        return self._env_dir.replace(\"\\\\\", \"/\")\n\n    @property\n    def env_exe(self):\n        \"\"\"Path to the Python executable inside the virtual environment.\"\"\"\n        return self._get_env_python(self._env_dir).replace(\"\\\\\", \"/\")\n\n    @property\n    def bin_path(self):\n        \"\"\"Path to the bin or Scripts directory inside the virtual environment.\"\"\"\n        bins = \"Scripts\" if platform.system() == \"Windows\" else \"bin\"\n        return os.path.join(self._env_dir, bins).replace(\"\\\\\", \"/\")\n\n    @staticmethod\n    def _get_env_python(env_dir):\n        _env_bin_dir = os.path.join(env_dir, \"Scripts\" if platform.system() == \"Windows\" else \"bin\")\n        return os.path.join(_env_bin_dir, \"python.exe\" if platform.system() == \"Windows\" else \"python\")\n\n    def generate(self):\n        \"\"\"\n        Create a conan environment to use the python venv in the next steps of the conanfile.\n        \"\"\"\n        env = Environment()\n        env.prepend_path(\"PATH\", self.bin_path)\n        env.vars(self._conanfile).save_script(self._env_name)\n\n    def run(self, args):\n        return self._conanfile.run(cmd_args_to_string([self.env_exe] + list(args)))\n\n    def install(self, packages, pip_args=None):\n        \"\"\"\n        Will try to install the list of pip packages passed as a parameter.\n\n        :param packages: try to install the list of pip packages passed as a parameter.\n        :param pip_args: additional argument list to be passed to the 'pip install' command,\n                         e.g.: ['--no-cache-dir', '--index-url', 'https://my.pypi.org/simple'].\n                         Defaults to ``None``.\n        :return: the return code of the executed pip command.\n        \"\"\"\n        args = [self.env_exe, \"-m\", \"pip\", \"install\", \"--disable-pip-version-check\"]\n        pip_verbosity = _get_pip_verbosity()\n        if pip_verbosity:\n            args.append(pip_verbosity)\n        if pip_args:\n            args.extend(pip_args)\n        args += [f'\"{p}\"' for p in packages]\n        command = \" \".join(args)\n        return self._conanfile.run(command)\n\n    def _create_venv(self):\n        try:\n            self._conanfile.run(cmd_args_to_string([self._default_python, '-m', 'venv',\n                                                    self._env_dir]))\n        except ConanException as e:\n            raise ConanException(f\"PyEnv could not create a Python virtual \"\n                                 f\"environment using '{self._default_python}': {e}\")\n\n    def _create_uv_venv(self, base_env_dir, py_version):\n        uv_env_dir = None\n        try:\n            uv_path = shutil.which(\"uv\")\n            if uv_path:\n                uv_cmd = [uv_path]\n            else:\n                uv_env_dir = os.path.join(base_env_dir, f\"uv_{self._env_name}\")\n                self._conanfile.run(cmd_args_to_string(\n                    [self._default_python, '-m', 'venv', uv_env_dir])\n                )\n\n                python_exe = self._get_env_python(uv_env_dir)\n                pip_args = [python_exe, \"-m\", \"pip\", \"install\", \"--disable-pip-version-check\"]\n                pip_verbosity = _get_pip_verbosity()\n                if pip_verbosity:\n                    pip_args.append(pip_verbosity)\n                pip_args.append(\"uv\")\n                self._conanfile.run(cmd_args_to_string(pip_args))\n                uv_cmd = [python_exe, \"-m\", \"uv\"]\n\n            uv_venv_args = uv_cmd + ['venv', '--seed', '--python', py_version, self._env_dir]\n            uv_verbosity = _get_uv_verbosity()\n            if uv_verbosity:\n                uv_venv_args.append(uv_verbosity)\n            self._conanfile.run(cmd_args_to_string(uv_venv_args))\n            self._conanfile.output.info(f\"Virtual environment for Python \"\n                                        f\"{py_version} created successfully using UV.\")\n        except Exception as e:\n            raise ConanException(f\"PyEnv could not create a Python {py_version} virtual \"\n                                 f\"environment using UV and '{self._default_python}': {e}\")\n        finally:\n            if uv_env_dir:\n                rmdir(uv_env_dir)\n\n\nclass PipEnv(PyEnv):\n    def __init__(self, conanfile, folder=None, name=\"\", py_version=None):\n        super().__init__(conanfile, folder, name, py_version)\n        ConanOutput().warning(\"'PipEnv()' is deprecated, use 'PyEnv()'\", warn_tag=\"deprecated\")\n"
  },
  {
    "path": "conans/__init__.py",
    "content": ""
  },
  {
    "path": "conans/conan.py",
    "content": "import sys\nfrom conan.cli.cli import main\n\n\ndef run():\n    main(sys.argv[1:])\n\n\nif __name__ == '__main__':\n    import multiprocessing\n    multiprocessing.freeze_support()\n    run()\n"
  },
  {
    "path": "conans/conan_server.py",
    "content": "import argparse\nimport os\n\nfrom conans.server.launcher import ServerLauncher\n\n\ndef run():\n    parser = argparse.ArgumentParser(description='Launch the server')\n    parser.add_argument('--migrate', default=False, action='store_true',\n                        help='Run the pending migrations')\n    parser.add_argument('--server_dir', '-d', default=None,\n                        help='Specify where to store server config and data.')\n    args = parser.parse_args()\n    launcher = ServerLauncher(force_migration=args.migrate,\n                              server_dir=args.server_dir or os.environ.get(\"CONAN_SERVER_HOME\"))\n    launcher.launch()\n\n\nif __name__ == '__main__':\n    run()\n"
  },
  {
    "path": "conans/migrations.py",
    "content": "import os\n\nfrom conan import conan_version\nfrom conan.api.output import ConanOutput\nfrom conan.internal.loader import load_python_file\nfrom conan.errors import ConanException, ConanMigrationError\nfrom conan.internal.model.version import Version\nfrom conan.internal.util.files import load, save\n\nCONAN_VERSION = \"version.txt\"\n\n\nclass Migrator:\n\n    def __init__(self, conf_path, current_version):\n        self.conf_path = conf_path\n\n        self.current_version = current_version\n        self.file_version_path = os.path.join(self.conf_path, CONAN_VERSION)\n\n    def migrate(self):\n        try:\n            old_version = self._load_old_version()\n            if old_version is None or old_version < self.current_version:\n                self._apply_migrations(old_version)\n                self._update_version_file()\n            elif self.current_version < old_version:  # backwards migrations\n                ConanOutput().warning(f\"Downgrading cache from Conan {old_version} to \"\n                                      f\"{self.current_version}\")\n                self._apply_back_migrations()\n                self._update_version_file()\n        except Exception as e:\n            ConanOutput().error(str(e), error_type=\"exception\")\n            raise ConanMigrationError(e)\n\n    def _update_version_file(self):\n        try:\n            save(self.file_version_path, str(self.current_version))\n        except Exception as error:\n            raise ConanException(\"Can't write version file in '{}': {}\"\n                                 .format(self.file_version_path, str(error)))\n\n    def _load_old_version(self):\n        try:\n            tmp = load(self.file_version_path)\n            old_version = Version(tmp)\n        except Exception:\n            old_version = None\n        return old_version\n\n    def _apply_migrations(self, old_version):\n        \"\"\"\n        Apply any migration script.\n\n        :param old_version: ``str`` previous Conan version.\n        \"\"\"\n        pass\n\n    def _apply_back_migrations(self):\n        migrations = os.path.join(self.conf_path, \"migrations\")\n        if not os.path.exists(migrations):\n            return\n\n        # Order by versions, and filter only newer than the current version\n        migration_files = []\n        for f in os.listdir(migrations):\n            if not f.endswith(\".py\"):\n                continue\n            version, remain = f.split(\"_\", 1)\n            version = Version(version)\n            if version > conan_version:\n                migration_files.append((version, remain))\n        migration_files = [f\"{v}_{r}\" for (v, r) in reversed(sorted(migration_files))]\n\n        for migration in migration_files:\n            ConanOutput().warning(f\"Applying downgrade migration {migration}\")\n            migration = os.path.join(migrations, migration)\n            try:\n                migrate_module, _ = load_python_file(migration)\n                migrate_method = migrate_module.migrate\n                migrate_method(self.conf_path)\n            except Exception as e:\n                ConanOutput().error(f\"There was an error running downgrade migration: {e}. \"\n                                    f\"Recommended to remove the cache and start from scratch\",\n                                    error_type=\"exception\")\n            os.remove(migration)\n"
  },
  {
    "path": "conans/requirements.txt",
    "content": "requests>=2.25, <3.0.0\nurllib3>=1.26.6, <3.0\ncolorama>=0.4.3, <0.5.0\nPyYAML>=6.0, <7.0\npatch-ng>=1.18.0, <1.19\nfasteners>=0.15\ndistro>=1.4.0, <2.0.0; platform_system == 'Linux' or platform_system == 'FreeBSD'\nJinja2>=3.0, <4.0.0\npython-dateutil>=2.8.0, <3\n"
  },
  {
    "path": "conans/requirements_dev.txt",
    "content": "pytest>=7, <8.0.0\npytest-xdist  # To launch in N cores with pytest -n\nWebTest>=3.0.0, <4\nbottle\nPyJWT\npluginbase\ndocker\nsetuptools\npytest-cov\n"
  },
  {
    "path": "conans/requirements_runner.txt",
    "content": "paramiko\ndocker>=7.1.0\n"
  },
  {
    "path": "conans/requirements_server.txt",
    "content": "# Server\nbottle>=0.12.8, < 0.14\npluginbase>=0.5\nPyJWT>=2.4.0, <3.0.0\n"
  },
  {
    "path": "conans/server/__init__.py",
    "content": "from conan.internal import REVISIONS\n\nCOMPLEX_SEARCH_CAPABILITY = \"complex_search\"\n\nSERVER_CAPABILITIES = [COMPLEX_SEARCH_CAPABILITY, REVISIONS]  # Server is always with revisions\n"
  },
  {
    "path": "conans/server/conf/__init__.py",
    "content": "\"\"\"\nServer's configuration variables\n\"\"\"\n\nimport os\nimport random\nimport string\nfrom datetime import timedelta\nfrom configparser import ConfigParser, NoSectionError\n\nfrom conan.errors import ConanException\nfrom conans.server.conf.default_server_conf import default_server_conf\nfrom conans.server.store.disk_adapter import ServerDiskAdapter\nfrom conans.server.store.server_store import ServerStore\nfrom conan.internal.util.files import mkdir, save, load\n\nMIN_CLIENT_COMPATIBLE_VERSION = '0.25.0'\n\n\ndef get_env(env_key, default=None, environment=None):\n    \"\"\"Get the env variable associated with env_key\"\"\"\n    if environment is None:\n        environment = os.environ\n\n    env_var = environment.get(env_key, default)\n    if env_var != default:\n        if isinstance(default, str):\n            return env_var\n        elif isinstance(default, bool):\n            return env_var == \"1\" or env_var == \"True\"\n        elif isinstance(default, int):\n            return int(env_var)\n        elif isinstance(default, float):\n            return float(env_var)\n        elif isinstance(default, list):\n            if env_var.strip():\n                return [var.strip() for var in env_var.split(\",\")]\n            return []\n    return env_var\n\n\nclass ConanServerConfigParser(ConfigParser):\n    \"\"\" defines the configuration of the server. It can load\n    values from environment variables or from file.\n    Environment variables have PRECEDENCE over file values\n    \"\"\"\n\n    def __init__(self, base_folder, environment=None, is_custom_path=False):\n        environment = environment or os.environ\n\n        ConfigParser.__init__(self)\n        environment = environment or os.environ\n        self.optionxform = str  # This line keeps the case of the key, important for users case\n        if is_custom_path:\n            self.conan_folder = base_folder\n        else:\n            self.conan_folder = os.path.join(base_folder, '.conan_server')\n        self.config_filename = os.path.join(self.conan_folder, 'server.conf')\n        self._loaded = False\n        self.env_config = {\"updown_secret\": get_env(\"CONAN_UPDOWN_SECRET\", None, environment),\n                           \"authorize_timeout\": get_env(\"CONAN_AUTHORIZE_TIMEOUT\", None, environment),\n                           \"disk_storage_path\": get_env(\"CONAN_STORAGE_PATH\", None, environment),\n                           \"jwt_secret\": get_env(\"CONAN_JWT_SECRET\", None, environment),\n                           \"jwt_expire_minutes\": get_env(\"CONAN_JWT_EXPIRE_MINUTES\", None, environment),\n                           \"write_permissions\": [],\n                           \"read_permissions\": [],\n                           \"ssl_enabled\": get_env(\"CONAN_SSL_ENABLED\", None, environment),\n                           \"port\": get_env(\"CONAN_SERVER_PORT\", None, environment),\n                           \"public_port\": get_env(\"CONAN_SERVER_PUBLIC_PORT\", None, environment),\n                           \"host_name\": get_env(\"CONAN_HOST_NAME\", None, environment),\n                           \"custom_authenticator\": get_env(\"CONAN_CUSTOM_AUTHENTICATOR\", None, environment),\n                           \"custom_authorizer\": get_env(\"CONAN_CUSTOM_AUTHORIZER\", None, environment),\n                           # \"user:pass,user2:pass2\"\n                           \"users\": get_env(\"CONAN_SERVER_USERS\", None, environment)}\n\n    def _get_file_conf(self, section, varname=None):\n        \"\"\" Gets the section or variable from config file.\n        If the queried element is not found an exception is raised.\n        \"\"\"\n        try:\n            if not os.path.exists(self.config_filename):\n                jwt_random_secret = ''.join(random.choice(string.ascii_letters) for _ in range(32))\n                updown_random_secret = ''.join(random.choice(string.ascii_letters) for _ in range(32))\n                server_conf = default_server_conf.format(jwt_secret=jwt_random_secret,\n                                                         updown_secret=updown_random_secret)\n                save(self.config_filename, server_conf)\n\n            if not self._loaded:\n                self._loaded = True\n                # To avoid encoding problems we use our tools.load\n                self.read_string(load(self.config_filename))\n\n            if varname:\n                section = dict(self.items(section))\n                return section[varname]\n            else:\n                return self.items(section)\n        except NoSectionError:\n            raise ConanException(\"No section '%s' found\" % section)\n        except Exception as exc:\n            raise ConanException(\"Invalid configuration, \"\n                                 \"missing %s: %s\" % (section, varname))\n\n    @property\n    def ssl_enabled(self):\n        try:\n            ssl_enabled = self._get_conf_server_string(\"ssl_enabled\").lower()\n            return ssl_enabled == \"true\" or ssl_enabled == \"1\"\n        except ConanException:\n            return None\n\n    @property\n    def port(self):\n        return int(self._get_conf_server_string(\"port\"))\n\n    @property\n    def public_port(self):\n        try:\n            return int(self._get_conf_server_string(\"public_port\"))\n        except ConanException:\n            return self.port\n\n    @property\n    def host_name(self):\n        try:\n            return self._get_conf_server_string(\"host_name\")\n        except ConanException:\n            return None\n\n    @property\n    def public_url(self):\n        host_name = self.host_name\n        ssl_enabled = self.ssl_enabled\n        protocol_version = \"v2\"\n        if host_name is None and ssl_enabled is None:\n            # No hostname and ssl config means that the transfer and the\n            # logical endpoint are the same and a relative URL is sufficient\n            return protocol_version\n        elif host_name is None or ssl_enabled is None:\n            raise ConanException(\"'host_name' and 'ssl_enable' have to be defined together.\")\n        else:\n            protocol = \"https\" if ssl_enabled else \"http\"\n            port = \":%s\" % self.public_port if self.public_port != 80 else \"\"\n            return \"%s://%s%s/%s\" % (protocol, host_name, port, protocol_version)\n\n    @property\n    def disk_storage_path(self):\n        \"\"\"If adapter is disk, means the directory for storage\"\"\"\n        try:\n            disk_path = self._get_conf_server_string(\"disk_storage_path\")\n            if disk_path.startswith(\".\"):\n                disk_path = os.path.join(os.path.dirname(self.config_filename), disk_path)\n                disk_path = os.path.abspath(disk_path)\n            ret = os.path.expanduser(disk_path)\n        except ConanException:\n            # If storage_path is not defined, use the current dir\n            # So tests use test folder instead of user/.conan_server\n            ret = os.path.dirname(self.config_filename)\n        ret = os.path.normpath(ret)  # Convert to O.S paths\n        mkdir(ret)\n        return ret\n\n    @property\n    def read_permissions(self):\n        if self.env_config[\"read_permissions\"]:\n            return self.env_config[\"read_permissions\"]\n        else:\n            return self._get_file_conf(\"read_permissions\")\n\n    @property\n    def write_permissions(self):\n        if self.env_config[\"write_permissions\"]:\n            return self.env_config[\"write_permissions\"]\n        else:\n            return self._get_file_conf(\"write_permissions\")\n\n    @property\n    def custom_authenticator(self):\n        try:\n            return self._get_conf_server_string(\"custom_authenticator\")\n        except ConanException:\n            return None\n\n    @property\n    def custom_authorizer(self):\n        try:\n            return self._get_conf_server_string(\"custom_authorizer\")\n        except ConanException:\n            return None\n\n    @property\n    def users(self):\n        def validate_pass_encoding(password):\n            try:\n                password.encode('ascii')\n            except (UnicodeDecodeError, UnicodeEncodeError):\n                raise ConanException(\"Password contains invalid characters. \"\n                                     \"Only ASCII encoding is supported\")\n            return password\n\n        if self.env_config[\"users\"]:\n            pairs = self.env_config[\"users\"].split(\",\")\n            return {pair.split(\":\")[0]: validate_pass_encoding(pair.split(\":\")[1]) for pair in pairs}\n        else:\n            tmp = dict(self._get_file_conf(\"users\"))\n            tmp = {key: validate_pass_encoding(value) for key, value in tmp.items()}\n            return tmp\n\n    @property\n    def jwt_secret(self):\n        try:\n            return self._get_conf_server_string(\"jwt_secret\")\n        except ConanException:\n            raise ConanException(\"'jwt_secret' setting is needed. Please, write a value \"\n                                 \"in server.conf or set CONAN_JWT_SECRET env value.\")\n\n    @property\n    def updown_secret(self):\n        try:\n            return self._get_conf_server_string(\"updown_secret\")\n        except ConanException:\n            raise ConanException(\"'updown_secret' setting is needed. Please, write a value \"\n                                 \"in server.conf or set CONAN_UPDOWN_SECRET env value.\")\n\n    def _get_conf_server_string(self, keyname):\n        \"\"\" Gets the value of a server config value either from the environment\n        or the config file. Values from the environment have priority. If the\n        value is not defined or empty an exception is raised.\n        \"\"\"\n        if self.env_config[keyname]:\n            return self.env_config[keyname]\n\n        value = self._get_file_conf(\"server\", keyname)\n        if value == \"\":\n            raise ConanException(\"no value for 'server.%s' is defined in the config file\" % keyname)\n        return value\n\n    @property\n    def authorize_timeout(self):\n        return timedelta(seconds=int(self._get_conf_server_string(\"authorize_timeout\")))\n\n    @property\n    def jwt_expire_time(self):\n        return timedelta(minutes=float(self._get_conf_server_string(\"jwt_expire_minutes\")))\n\n\ndef get_server_store(disk_storage_path, public_url):\n    disk_controller_url = \"%s/%s\" % (public_url, \"files\")\n    adapter = ServerDiskAdapter(disk_controller_url, disk_storage_path)\n    return ServerStore(adapter)\n"
  },
  {
    "path": "conans/server/conf/default_server_conf.py",
    "content": "default_server_conf = \"\"\"[server]\n# WARNING! Change default variable of jwt_secret. You should change it periodically\n# It only affects to current authentication tokens, you can change safetely anytime\n# When it changes user are just forced to log in again\njwt_secret: {jwt_secret}\njwt_expire_minutes: 120\n\nssl_enabled: False\nport: 9300\n# Public port where files will be served. If empty will be used \"port\"\npublic_port:\nhost_name: localhost\n\n# Authorize timeout are seconds the client has to upload/download files until authorization expires\nauthorize_timeout: 1800\n\n# Just for disk storage adapter\n# updown_secret is the key used to generate the upload/download authorization token\ndisk_storage_path: ./data\ndisk_authorize_timeout: 1800\nupdown_secret: {updown_secret}\n\n\n# Check docs.conan.io to implement a different authenticator plugin for conan_server\n# if custom_authenticator is not specified, [users] section will be used to authenticate\n# the users.\n#\n# custom_authenticator: my_authenticator\n\n# Check docs.conan.io to implement a different authorizer plugin for conan_server\n# if custom_authorizer is not specified, the [read_permissions] and [write_permissions]\n# sections will be used to grant/reject access.\n#\n# custom_authorizer: my_authorizer\n\n# name/version@user/channel: user1, user2, user3\n#\n# The rules are applied in order. \n# If a rule matches your package, then the server wont look further.\n# Place your more restrictive rules first.\n#\n# Example: All versions of opencv package from lasote user in testing channel is only\n# writeable by default_user and default_user2. Rest of packages are not writtable by anything\n# except the author.\n#\n#   opencv/2.3.4@lasote/testing: default_user, default_user2\n#\n[write_permissions]\n\n# name/version@user/channel: user1, user2, user3\n# The rules are applied in order. If a rule applies to a conan, system wont look further.\n#\n# Example: \n#  All versions of opencv package from lasote user in testing channel are only\n#    readable by default_user and default_user2. \n#  All versions of internal package from any user/channel are only readable by\n#    authenticated users. \n#  Rest of packages are world readable.\n#\n#   opencv/*@lasote/testing: default_user default_user2\n#   internal/*@*/*: ?\n#   */*@*/*: *\n#\n# By default all users can read all blocks\n#\n[read_permissions]\n*/*@*/*: *\n\n[users]\n#default_user: defaultpass\ndemo: demo\n\n\"\"\"\n"
  },
  {
    "path": "conans/server/crypto/__init__.py",
    "content": ""
  },
  {
    "path": "conans/server/crypto/jwt/__init__.py",
    "content": ""
  },
  {
    "path": "conans/server/crypto/jwt/jwt_credentials_manager.py",
    "content": "from datetime import datetime, timezone\nfrom calendar import timegm\n\nimport jwt\n\n\nclass JWTCredentialsManager:\n    \"\"\"JWT for manage auth credentials\"\"\"\n\n    def __init__(self, secret, expire_time):\n        \"\"\"expire_time is a timedelta\n        secret is a string with the secret encoding key\"\"\"\n        self.secret = secret\n        self.expire_time = expire_time\n\n    def get_token_for(self, user):\n        \"\"\"Generates a token with the brl_user and additional data dict if needed\"\"\"\n        profile_fields = {\"user\": user,\n                          \"exp\": timegm((datetime.now(timezone.utc) + self.expire_time).timetuple())}\n        return jwt.encode(profile_fields, self.secret, algorithm=\"HS256\")\n\n    def get_user(self, token):\n        \"\"\"Gets the user from credentials object. None if no credentials.\n        Can raise jwt.ExpiredSignature and jwt.DecodeError\"\"\"\n        profile = jwt.decode(token, self.secret, algorithms=[\"HS256\"])\n        return profile.get(\"user\", None)\n"
  },
  {
    "path": "conans/server/launcher.py",
    "content": "#!/usr/bin/python\nimport os\nimport sys\n\nfrom conan.internal import REVISIONS\nfrom conans.server import SERVER_CAPABILITIES\nfrom conans.server.conf import get_server_store\n\nfrom conans.server.crypto.jwt.jwt_credentials_manager import JWTCredentialsManager\nfrom conans.server.migrate import migrate_and_get_server_config\nfrom conans.server.plugin_loader import load_authentication_plugin, load_authorization_plugin\nfrom conans.server.rest.server import ConanServer\n\nfrom conans.server.service.authorize import BasicAuthorizer, BasicAuthenticator\n\n\nclass ServerLauncher(object):\n    def __init__(self, force_migration=False, server_dir=None):\n        if sys.version_info.major == 2:\n            raise Exception(\"The conan_server needs Python>=3 for running\")\n        self.force_migration = force_migration\n        if server_dir:\n            user_folder = server_folder = server_dir\n        else:\n            user_folder = os.path.expanduser(\"~\")\n            server_folder = os.path.join(user_folder, '.conan_server')\n\n        server_config = migrate_and_get_server_config(\n            user_folder, self.force_migration, server_dir is not None\n        )\n        custom_authn = server_config.custom_authenticator\n        if custom_authn:\n            authenticator = load_authentication_plugin(server_folder, custom_authn)\n        else:\n            authenticator = BasicAuthenticator(dict(server_config.users))\n\n        custom_authz = server_config.custom_authorizer\n        if custom_authz:\n            authorizer = load_authorization_plugin(server_folder, custom_authz)\n        else:\n            authorizer = BasicAuthorizer(server_config.read_permissions,\n                                         server_config.write_permissions)\n\n        credentials_manager = JWTCredentialsManager(server_config.jwt_secret,\n                                                    server_config.jwt_expire_time)\n\n        server_store = get_server_store(server_config.disk_storage_path, server_config.public_url)\n\n        server_capabilities = SERVER_CAPABILITIES\n        server_capabilities.append(REVISIONS)\n\n        self.server = ConanServer(server_config.port, credentials_manager,\n                                  authorizer, authenticator, server_store,\n                                  server_capabilities)\n        if not self.force_migration:\n            print(\"***********************\")\n            print(\"Using config: %s\" % server_config.config_filename)\n            print(\"Storage: %s\" % server_config.disk_storage_path)\n            print(\"Public URL: %s\" % server_config.public_url)\n            print(\"PORT: %s\" % server_config.port)\n            print(\"***********************\")\n\n    def launch(self):\n        if not self.force_migration:\n            self.server.run(host=\"0.0.0.0\")\n"
  },
  {
    "path": "conans/server/migrate.py",
    "content": "from conan import conan_version\nfrom conans.server.conf import ConanServerConfigParser\nfrom conans.server.migrations import ServerMigrator\n\n\ndef migrate_and_get_server_config(base_folder, force_migration=False, is_custom_path=False):\n    server_config = ConanServerConfigParser(base_folder, is_custom_path=is_custom_path)\n    storage_path = server_config.disk_storage_path\n    migrator = ServerMigrator(server_config.conan_folder, storage_path,\n                              conan_version, force_migration)\n    migrator.migrate()\n\n    # Init again server_config, migrator could change something\n    server_config = ConanServerConfigParser(base_folder, is_custom_path=is_custom_path)\n    return server_config\n"
  },
  {
    "path": "conans/server/migrations.py",
    "content": "from conans.migrations import Migrator\n\n\nclass ServerMigrator(Migrator):\n\n    def __init__(self, conf_path, store_path, current_version, force_migrations):\n        self.force_migrations = force_migrations\n        self.store_path = store_path\n        super(ServerMigrator, self).__init__(conf_path, current_version)\n"
  },
  {
    "path": "conans/server/plugin_loader.py",
    "content": "import os\n\n\ndef load_plugin(server_folder, plugin_type, plugin_name):\n    try:\n        from pluginbase import PluginBase\n        plugin_base = PluginBase(package=\"plugins/%s\" % plugin_type)\n        plugins_dir = os.path.join(server_folder, \"plugins\", plugin_type)\n        plugin_source = plugin_base.make_plugin_source(\n                        searchpath=[plugins_dir])\n        plugin = plugin_source.load_plugin(plugin_name).get_class()\n        # it is necessary to keep a reference to the plugin, otherwise it is removed\n        # and some imports fail\n        plugin.plugin_source = plugin_source\n        return plugin\n    except Exception:\n        print(\"Error loading %s plugin '%s'\" % (plugin_type, plugin_name))\n        raise\n\n\ndef load_authentication_plugin(server_folder, plugin_name):\n    return load_plugin(server_folder, \"authenticator\", plugin_name)\n\n\ndef load_authorization_plugin(server_folder, plugin_name):\n    return load_plugin(server_folder, \"authorizer\", plugin_name)\n"
  },
  {
    "path": "conans/server/rest/__init__.py",
    "content": ""
  },
  {
    "path": "conans/server/rest/api_v2.py",
    "content": "from bottle import Bottle\n\nfrom conan.internal.errors import EXCEPTION_CODE_MAPPING\nfrom conans.server.rest.bottle_plugins.http_basic_authentication import HttpBasicAuthentication\nfrom conans.server.rest.bottle_plugins.jwt_authentication import JWTAuthentication\nfrom conans.server.rest.bottle_plugins.return_handler import ReturnHandlerPlugin\nfrom conans.server.rest.controller.v2.ping import PingController\nfrom conans.server.rest.controller.v2.users import UsersController\nfrom conans.server.rest.controller.v2.conan import ConanControllerV2\nfrom conans.server.rest.controller.v2.delete import DeleteControllerV2\nfrom conans.server.rest.controller.v2.revisions import RevisionsController\nfrom conans.server.rest.controller.v2.search import SearchControllerV2\n\n\nclass ApiV2(Bottle):\n\n    def __init__(self, credentials_manager, server_capabilities):\n\n        self.credentials_manager = credentials_manager\n        self.server_capabilities = server_capabilities\n        Bottle.__init__(self)\n\n    def setup(self):\n        self.install_plugins()\n\n        # Capabilities in a ping\n        PingController().attach_to(self)\n\n        SearchControllerV2().attach_to(self)\n        DeleteControllerV2().attach_to(self)\n        ConanControllerV2().attach_to(self)\n        RevisionsController().attach_to(self)\n\n        # Install users controller\n        UsersController().attach_to(self)\n\n    def install_plugins(self):\n        # Second, check Http Basic Auth\n        self.install(HttpBasicAuthentication())\n\n        # Map exceptions to http return codes\n        self.install(ReturnHandlerPlugin(EXCEPTION_CODE_MAPPING))\n\n        # Handle jwt auth\n        self.install(JWTAuthentication(self.credentials_manager))\n"
  },
  {
    "path": "conans/server/rest/bottle_plugins/__init__.py",
    "content": ""
  },
  {
    "path": "conans/server/rest/bottle_plugins/authorization_header.py",
    "content": "import inspect\nfrom abc import ABCMeta, abstractmethod\n\nfrom bottle import PluginError, request\n\n\nclass AuthorizationHeader(object, metaclass=ABCMeta):\n    \"\"\" Generic plugin to handle Authorization header. Must be extended and implement\n    some abstract methods in subclasses \"\"\"\n\n    name = 'authorizationheader'\n    api = 2\n\n    def __init__(self, keyword):\n        # Required\n        self.keyword = keyword\n\n    def setup(self, app):\n        \"\"\" Make sure that other installed plugins don't affect the same\n            keyword argument. \"\"\"\n        for other in app.plugins:\n            if not isinstance(other, self.__class__):\n                continue\n            if other.keyword == self.keyword:\n                raise PluginError(\"Found another AuthorizationHeaderBottlePlugin plugin with \"\n                                  \"conflicting settings (non-unique keyword).\")\n\n    def apply(self, callback, context):\n        \"\"\" Test if the original callback accepts a 'self.keyword' keyword. \"\"\"\n        args = inspect.getfullargspec(context.callback)[0]\n        # logger.debug(\"Call: %s\" % str(callback))\n        if self.keyword not in args:\n            return callback\n\n        def wrapper(*args, **kwargs):\n            \"\"\" Check for user credentials in http header \"\"\"\n            # Get Authorization\n            header_value = self.get_authorization_header_value()\n            new_kwargs = self.parse_authorization_value(header_value)\n            if not new_kwargs:\n                raise self.get_invalid_header_response()\n            kwargs.update(new_kwargs)\n            return callback(*args, **kwargs)  # kwargs has :xxx variables from url\n\n        # Replace the route callback with the wrapped one.\n        return wrapper\n\n    def get_authorization_header_value(self):\n        \"\"\" Get from the request the header of http basic auth:\n         http://en.wikipedia.org/wiki/Basic_access_authentication \"\"\"\n        auth_type = self.get_authorization_type()\n        if request.headers.get(\"Authorization\", None) is not None:\n            auth_line = request.headers.get(\"Authorization\", None)\n            if not auth_line.startswith(\"%s \" % auth_type):\n                raise self.get_invalid_header_response()\n            return auth_line[len(auth_type) + 1:]\n        else:\n            return None\n\n    @abstractmethod\n    def get_authorization_type(self):\n        \"\"\"Abstract. Example: Basic (for http basic auth) or Beagle for JWT\"\"\"\n        raise NotImplementedError()\n\n    @abstractmethod\n    def parse_authorization_value(self, header_value):\n        \"\"\"Abstract. Parse header_value and return kwargs to apply bottle\n        method parameters\"\"\"\n        raise NotImplementedError()\n\n    @abstractmethod\n    def get_invalid_header_response(self):\n        \"\"\"A response from a malformed header\"\"\"\n        raise NotImplementedError()\n"
  },
  {
    "path": "conans/server/rest/bottle_plugins/http_basic_authentication.py",
    "content": "import base64\nfrom collections import namedtuple\n\nfrom bottle import HTTPResponse\n\nfrom conans.server.rest.bottle_plugins.authorization_header import AuthorizationHeader\n\n\nclass UserPasswordPair(namedtuple('UserPasswordPair', ['user', 'password'])):\n    \"\"\" Simple tuple for store user and pass \"\"\"\n    pass\n\n\nclass HttpBasicAuthentication(AuthorizationHeader):\n    \"\"\" The HttpBasicAuthenticationBottlePlugin plugin requires Http Basic Authentication \"\"\"\n\n    name = 'basichttpauth'\n    api = 2\n\n    def __init__(self, keyword='http_basic_credentials'):\n        self.keyword = keyword\n        super(HttpBasicAuthentication, self).__init__(keyword)\n\n    def get_authorization_type(self):\n        \"\"\"String in Authorization header for type\"\"\"\n        return \"Basic\"\n\n    def parse_authorization_value(self, header_value):\n        \"\"\"Parse header_value and return kwargs to apply bottle\n        method parameters\"\"\"\n        if header_value is None:\n            return None\n        # HTTP protocol is utf-8\n        username, password = base64.b64decode(header_value).decode().split(\":\", 1)\n        ret = UserPasswordPair(username, password)\n        return {self.keyword: ret}\n\n    def get_invalid_header_response(self):\n        \"\"\"A response from a malformed header. Includes WWW-Authenticate for\n        ask browser to request user and password\"\"\"\n        return HTTPResponse(\"'Http Authentication not implemented'\",\n                            \"401 Unauthorized\",\n                            {\"WWW-Authenticate\": 'Basic realm=\"Login Required\"'})\n"
  },
  {
    "path": "conans/server/rest/bottle_plugins/jwt_authentication.py",
    "content": "from bottle import HTTPResponse\n\nfrom conans.server.rest.bottle_plugins.authorization_header import AuthorizationHeader\n\n\nclass JWTAuthentication(AuthorizationHeader):\n    \"\"\" The HttpBasicAuthenticationBottlePlugin plugin requires Http Basic Authentication \"\"\"\n\n    name = 'jwtauthenticationbottleplugin'\n    api = 2\n\n    def __init__(self, manager, keyword='auth_user'):\n        \"\"\" Manager should be a JWTCredentialsManager \"\"\"\n        self.manager = manager\n        self.keyword = keyword\n        super(JWTAuthentication, self).__init__(keyword)\n\n    def get_authorization_type(self):\n        \"\"\"String in Authorization header for type\"\"\"\n        return \"Bearer\"\n\n    def parse_authorization_value(self, header_value):\n        \"\"\"Parse header_value and return kwargs to apply bottle\n        method parameters\"\"\"\n        try:\n            if not header_value:\n                username = None\n            else:\n                # Check if its valid obtaining the password_timestamp\n                username = self.manager.get_user(token=header_value)\n        except Exception:\n            # Check if\n            resp = HTTPResponse(\"Wrong JWT token!\", \"401 Unauthorized\")\n            resp.set_header('Content-Type', 'text/plain')\n            raise resp\n        return {self.keyword: username}\n\n    def get_invalid_header_response(self):\n        \"\"\"A response from a malformed header. Includes WWW-Authenticate for\n        ask browser to request user and password\"\"\"\n        return HTTPResponse(\"'Http Authentication not implemented'\",\n                            \"401 Unauthorized\")\n"
  },
  {
    "path": "conans/server/rest/bottle_plugins/return_handler.py",
    "content": "from bottle import HTTPResponse\n\nfrom conan.errors import ConanException\n\n\nclass ReturnHandlerPlugin(object):\n    \"\"\" The ReturnHandlerPlugin plugin unify REST return and exception management \"\"\"\n\n    name = 'ReturnHandlerPlugin'\n    api = 2\n\n    def __init__(self, exception_mapping):\n        self.exception_mapping = exception_mapping\n\n    def setup(self, app):\n        \"\"\" Make sure that other installed plugins don't affect the same\n            keyword argument. \"\"\"\n        for other in app.plugins:\n            if not isinstance(other, ReturnHandlerPlugin):\n                continue\n\n    def apply(self, callback, _):\n        \"\"\" Apply plugin \"\"\"\n        def wrapper(*args, **kwargs):\n            \"\"\" Capture possible exceptions to manage the return \"\"\"\n            try:\n                # The encoding from browsers is utf-8, so we assume it\n                for key, value in kwargs.items():\n                    if isinstance(value, str):\n                        kwargs[key] = value\n                return callback(*args, **kwargs)  # kwargs has :xxx variables from url\n            except HTTPResponse:\n                raise\n            except ConanException as excep:\n                return get_response_from_exception(excep, self.exception_mapping)\n            except Exception as e:\n                # logger.error(e)\n                # logger.error(traceback.print_exc())\n                return get_response_from_exception(e, self.exception_mapping)\n\n        return wrapper\n\n\ndef get_response_from_exception(excep, exception_mapping):\n    status = exception_mapping.get(excep.__class__, None)\n    if status is None:\n        status = 500\n    ret = HTTPResponse(status=status, body=str(excep))\n    ret.add_header(\"Content-Type\", \"text/plain\")\n    return ret\n"
  },
  {
    "path": "conans/server/rest/bottle_routes.py",
    "content": "from conan.internal.rest.rest_routes import RestRoutes\n\n\nclass BottleRoutes(RestRoutes):\n\n    def __getattribute__(self, item):\n        tmp = super(BottleRoutes, self).__getattribute__(item)\n        tmp = tmp.replace(\"{path}\", \"<the_path:path>\").replace(\"{\", \"<\").replace(\"}\", \">\")\n        if not tmp.startswith(\"/\"):\n            return \"/{}\".format(tmp)\n        return tmp\n"
  },
  {
    "path": "conans/server/rest/controller/__init__.py",
    "content": ""
  },
  {
    "path": "conans/server/rest/controller/v2/__init__.py",
    "content": "from conan.api.model import PkgReference\nfrom conan.api.model import RecipeReference\n\n\ndef get_package_ref(name, version, username, channel, package_id, revision, p_revision):\n    ref = RecipeReference(name, version, username, channel, revision)\n    return PkgReference(ref, package_id, p_revision)\n"
  },
  {
    "path": "conans/server/rest/controller/v2/conan.py",
    "content": "from bottle import request\n\nfrom conan.internal.errors import NotFoundException\nfrom conan.api.model import RecipeReference\nfrom conans.server.rest.bottle_routes import BottleRoutes\nfrom conans.server.rest.controller.v2 import get_package_ref\nfrom conans.server.service.v2.service_v2 import ConanServiceV2\n\n\nclass ConanControllerV2(object):\n\n    @staticmethod\n    def attach_to(app):\n\n        conan_service = ConanServiceV2(app.authorizer, app.server_store)\n        r = BottleRoutes()\n\n        @app.route(r.package_revision_files, method=[\"GET\"])\n        def get_package_file_list(name, version, username, channel, package_id, auth_user,\n                                  revision, p_revision):\n            pref = get_package_ref(name, version, username, channel, package_id,\n                                   revision, p_revision)\n            ret = conan_service.get_package_file_list(pref, auth_user)\n            return ret\n\n        @app.route(r.package_revision_file, method=[\"GET\"])\n        def get_package_file(name, version, username, channel, package_id, the_path, auth_user,\n                             revision, p_revision):\n            pref = get_package_ref(name, version, username, channel, package_id,\n                                   revision, p_revision)\n            file_generator = conan_service.get_package_file(pref, the_path, auth_user)\n            return file_generator\n\n        @app.route(r.package_revision_file, method=[\"PUT\"])\n        def upload_package_file(name, version, username, channel, package_id,\n                                the_path, auth_user, revision, p_revision):\n\n            if \"X-Checksum-Deploy\" in request.headers:\n                raise NotFoundException(\"Non checksum storage\")\n            pref = get_package_ref(name, version, username, channel, package_id,\n                                   revision, p_revision)\n            conan_service.upload_package_file(request.body, request.headers, pref,\n                                              the_path, auth_user)\n\n        @app.route(r.recipe_revision_files, method=[\"GET\"])\n        def get_recipe_file_list(name, version, username, channel, auth_user, revision):\n            ref = RecipeReference(name, version, username, channel, revision)\n            ret = conan_service.get_recipe_file_list(ref, auth_user)\n            return ret\n\n        @app.route(r.recipe_revision_file, method=[\"GET\"])\n        def get_recipe_file(name, version, username, channel, the_path, auth_user, revision):\n            ref = RecipeReference(name, version, username, channel, revision)\n            file_generator = conan_service.get_recipe_file(ref, the_path, auth_user)\n            return file_generator\n\n        @app.route(r.recipe_revision_file, method=[\"PUT\"])\n        def upload_recipe_file(name, version, username, channel, the_path, auth_user, revision):\n            if \"X-Checksum-Deploy\" in request.headers:\n                raise NotFoundException(\"Not a checksum storage\")\n            ref = RecipeReference(name, version, username, channel, revision)\n            conan_service.upload_recipe_file(request.body, request.headers, ref, the_path, auth_user)\n"
  },
  {
    "path": "conans/server/rest/controller/v2/delete.py",
    "content": "from conan.api.model import RecipeReference\nfrom conans.server.rest.bottle_routes import BottleRoutes\nfrom conans.server.rest.controller.v2 import get_package_ref\nfrom conans.server.service.v2.service_v2 import ConanServiceV2\n\n\nclass DeleteControllerV2(object):\n    \"\"\"\n        Serve requests related with Conan\n    \"\"\"\n    @staticmethod\n    def attach_to(app):\n\n        r = BottleRoutes()\n\n        @app.route(r.recipe, method=\"DELETE\")\n        @app.route(r.recipe_revision, method=\"DELETE\")\n        def remove_recipe(name, version, username, channel, auth_user, revision=None):\n            \"\"\" Remove any existing conanfiles or its packages created.\n            Will remove all revisions, packages and package revisions (parent folder) if no revision\n            is passed\n            \"\"\"\n            ref = RecipeReference(name, version, username, channel, revision)\n            conan_service = ConanServiceV2(app.authorizer, app.server_store)\n            conan_service.remove_recipe(ref, auth_user)\n\n        @app.route(r.package_recipe_revision, method=[\"DELETE\"])\n        @app.route(r.package_revision, method=[\"DELETE\"])\n        def remove_package(name, version, username, channel, package_id, auth_user,\n                           revision=None, p_revision=None):\n            \"\"\" - If both RRev and PRev are specified, it will remove the specific package revision\n                  of the specific recipe revision.\n                - If PRev is NOT specified but RRev is specified (package_recipe_revision_url)\n                  it will remove all the package revisions\n             \"\"\"\n            pref = get_package_ref(name, version, username, channel, package_id,\n                                   revision, p_revision)\n            conan_service = ConanServiceV2(app.authorizer, app.server_store)\n            conan_service.remove_package(pref, auth_user)\n\n        @app.route(r.packages_revision, method=\"DELETE\")\n        def remove_all_packages(name, version, username, channel, auth_user, revision=None):\n            \"\"\" Remove all packages from a RREV\"\"\"\n            ref = RecipeReference(name, version, username, channel, revision)\n            conan_service = ConanServiceV2(app.authorizer, app.server_store)\n            conan_service.remove_all_packages(ref, auth_user)\n"
  },
  {
    "path": "conans/server/rest/controller/v2/ping.py",
    "content": "from bottle import response\n\nfrom conans.server.rest.bottle_routes import BottleRoutes\n\n\nclass PingController(object):\n\n    @staticmethod\n    def attach_to(app):\n        r = BottleRoutes()\n\n        @app.route(r.ping, method=[\"GET\"])\n        def ping():\n            \"\"\"\n            Response OK. Useful to get server capabilities\n            \"\"\"\n            response.headers['X-Conan-Server-Capabilities'] = \",\".join(app.server_capabilities)\n            return\n"
  },
  {
    "path": "conans/server/rest/controller/v2/revisions.py",
    "content": "from conan.api.model import RecipeReference\nfrom conans.server.rest.bottle_routes import BottleRoutes\nfrom conans.server.rest.controller.v2 import get_package_ref\nfrom conans.server.service.v2.service_v2 import ConanServiceV2\nfrom conan.internal.util.dates import from_timestamp_to_iso8601\n\n\nclass RevisionsController(object):\n    \"\"\"\n        Serve requests related with Conan\n    \"\"\"\n    @staticmethod\n    def attach_to(app):\n\n        r = BottleRoutes()\n\n        @app.route(r.recipe_revisions, method=\"GET\")\n        def get_recipe_revisions_references(name, version, username, channel, auth_user):\n            \"\"\" Gets a JSON with the revisions for the specified recipe\n            \"\"\"\n            conan_reference = RecipeReference(name, version, username, channel)\n            conan_service = ConanServiceV2(app.authorizer, app.server_store)\n            revs = conan_service.get_recipe_revisions_references(conan_reference, auth_user)\n            return _format_revs_return(revs)\n\n        @app.route(r.recipe_latest, method=\"GET\")\n        def get_latest_recipe_reference(name, version, username, channel, auth_user):\n            \"\"\" Gets a JSON with the revisions for the specified recipe\n            \"\"\"\n            conan_reference = RecipeReference(name, version, username, channel)\n            conan_service = ConanServiceV2(app.authorizer, app.server_store)\n            rev = conan_service.get_latest_revision(conan_reference, auth_user)\n            return _format_rev_return(rev)\n\n        @app.route(r.package_revisions, method=\"GET\")\n        def get_package_revisions_references(name, version, username, channel, package_id, auth_user,\n                                             revision):\n            \"\"\" Get a JSON with the revisions for a specified RREV \"\"\"\n            package_reference = get_package_ref(name, version, username, channel, package_id,\n                                                revision, p_revision=None)\n            conan_service = ConanServiceV2(app.authorizer, app.server_store)\n            prefs = conan_service.get_package_revisions_references(package_reference, auth_user)\n            return _format_prefs_return(prefs)\n\n        @app.route(r.package_revision_latest, method=\"GET\")\n        def get_latest_package_reference(name, version, username, channel, package_id, auth_user,\n                                         revision):\n            \"\"\" Gets a JSON with the revisions for the specified recipe\n            \"\"\"\n            package_reference = get_package_ref(name, version, username, channel, package_id,\n                                                revision, p_revision=None)\n            conan_service = ConanServiceV2(app.authorizer, app.server_store)\n            pref = conan_service.get_latest_package_reference(package_reference, auth_user)\n            return _format_pref_return(pref)\n\n\ndef _format_rev_return(rev):\n    # FIXME: fix this when RecipeReference\n    return {\"revision\": rev[0], \"time\": from_timestamp_to_iso8601(rev[1])}\n\n\ndef _format_revs_return(revs):\n    return {\"revisions\": [_format_rev_return(rev) for rev in revs]}\n\n\ndef _format_pref_return(pref):\n    return {\"revision\": pref.revision, \"time\": from_timestamp_to_iso8601(pref.timestamp)}\n\n\ndef _format_prefs_return(revs):\n    return {\"revisions\": [_format_pref_return(rev) for rev in revs]}\n"
  },
  {
    "path": "conans/server/rest/controller/v2/search.py",
    "content": "from bottle import request\n\nfrom conan.api.model import RecipeReference\nfrom conans.server.rest.bottle_routes import BottleRoutes\nfrom conans.server.service.v2.search import SearchService\n\n\nclass SearchControllerV2(object):\n    \"\"\"\n        Serve requests related with Conan\n    \"\"\"\n    @staticmethod\n    def attach_to(app):\n\n        r = BottleRoutes()\n\n        @app.route(r.common_search, method=[\"GET\"])\n        def search(auth_user):\n            pattern = request.params.get(\"q\", None)\n            ignore_case = request.params.get(\"ignorecase\", True)\n            if isinstance(ignore_case, str):\n                ignore_case = False if 'false' == ignore_case.lower() else True\n            search_service = SearchService(app.authorizer, app.server_store, auth_user)\n            references = [repr(ref) for ref in search_service.search(pattern, ignore_case)]\n            return {\"results\": references}\n\n        @app.route(r.common_search_packages, method=[\"GET\"])\n        @app.route(r.common_search_packages_revision, method=[\"GET\"])\n        def search_packages(name, version, username, channel, auth_user, revision=None):\n            # query is no longer server side\n            list_only = request.params.get(\"list_only\", False)\n            if isinstance(list_only, str):\n                list_only = False if 'false' == list_only.lower() else True\n            search_service = SearchService(app.authorizer, app.server_store, auth_user)\n            ref = RecipeReference(name, version, username, channel, revision)\n            info = search_service.search_packages(ref, list_only)\n            return info\n"
  },
  {
    "path": "conans/server/rest/controller/v2/users.py",
    "content": "from bottle import response\n\nfrom conan.internal.errors import AuthenticationException\n\nfrom conans.server.rest.bottle_routes import BottleRoutes\nfrom conans.server.service.user_service import UserService\n\n\nclass UsersController(object):\n    \"\"\"\n        Serve requests related with users\n    \"\"\"\n    def attach_to(self, app):\n\n        r = BottleRoutes()\n\n        @app.route(r.common_authenticate, method=[\"GET\"])\n        def authenticate(http_basic_credentials):\n            if not http_basic_credentials:\n                raise AuthenticationException(\"Wrong user or password\")\n\n            user_service = UserService(app.authenticator,\n                                       app.credentials_manager)\n\n            token = user_service.authenticate(http_basic_credentials.user,\n                                              http_basic_credentials.password)\n\n            response.content_type = 'text/plain'\n            return token\n\n        @app.route(r.common_check_credentials, method=[\"GET\"])\n        def check_credentials(auth_user):\n            \"\"\"Just check if valid token. It not exception\n            is raised from Bottle plugin\"\"\"\n            if not auth_user:\n                raise AuthenticationException(\"Logged user needed!\")\n            response.content_type = 'text/plain'\n            return auth_user\n"
  },
  {
    "path": "conans/server/rest/server.py",
    "content": "import bottle\nfrom bottle import Bottle\n\nfrom conans.server.rest.api_v2 import ApiV2\nfrom conans.server.rest.controller.v2.ping import PingController\n\n\nclass ConanServer(object):\n    \"\"\"\n        Server class. Instances api_v2 application and run it.\n        Receives the store.\n\n    \"\"\"\n    store = None\n    root_app = None\n\n    def __init__(self, run_port, credentials_manager, authorizer, authenticator,\n                 server_store, server_capabilities):\n\n        self.run_port = run_port\n\n        server_capabilities = server_capabilities or []\n        self.root_app = bottle.Bottle()\n\n        self.api_v2 = ApiV2(credentials_manager, server_capabilities)\n        self.api_v2.authorizer = authorizer\n        self.api_v2.authenticator = authenticator\n        self.api_v2.server_store = server_store\n        self.api_v2.setup()\n        self.root_app.mount(\"/v2/\", self.api_v2)\n\n        # FIXME: Artifactory is not returning the capabilities in V2, so the client uses v1\n        #        for that. So we need to implement the ping at V1.\n        class ApiV1Ping(Bottle):\n            def __init__(self, server_capabilities):\n                self.server_capabilities = server_capabilities\n                Bottle.__init__(self)\n\n            def setup(self):\n                # Capabilities in a ping\n                PingController().attach_to(self)\n\n        ping_v1 = ApiV1Ping(server_capabilities)\n        ping_v1.setup()\n        self.root_app.mount(\"/v1/\", ping_v1)\n\n    def run(self, **kwargs):\n        port = kwargs.pop(\"port\", self.run_port)\n        debug_set = kwargs.pop(\"debug\", False)\n        host = kwargs.pop(\"host\", \"localhost\")\n        bottle.Bottle.run(self.root_app, host=host,\n                          port=port, debug=debug_set, reloader=False)\n"
  },
  {
    "path": "conans/server/revision_list.py",
    "content": "import json\nfrom collections import namedtuple\n\nfrom conan.internal.util.dates import revision_timestamp_now\n\n_RevisionEntry = namedtuple(\"RevisionEntry\", \"revision time\")\n\n\nclass RevisionList(object):\n\n    def __init__(self):\n        self._data = []\n\n    @staticmethod\n    def loads(contents):\n        ret = RevisionList()\n        ret._data = [_RevisionEntry(e[\"revision\"], e[\"time\"])\n                     for e in json.loads(contents)[\"revisions\"]]\n        return ret\n\n    def dumps(self):\n        return json.dumps({\"revisions\": [{\"revision\": e.revision,\n                                          \"time\": e.time} for e in self._data]})\n\n    def add_revision(self, revision_id):\n        lt = self.latest_revision()\n        if lt and lt.revision == revision_id:\n            # Each uploaded file calls to update the revision\n            return\n        index = self._find_revision_index(revision_id)\n        if index:\n            self._data.pop(index)\n\n        self._data.append(_RevisionEntry(revision_id, self._now()))\n\n    @staticmethod\n    def _now():\n        return revision_timestamp_now()\n\n    def latest_revision(self):\n        if not self._data:\n            return None\n        return self._data[-1]\n\n    def get_time(self, revision):\n        tmp = self._find_revision_index(revision)\n        if tmp is None:\n            return None\n        return self._data[tmp].time\n\n    def as_list(self):\n        return list(reversed(self._data))\n\n    def remove_revision(self, revision_id):\n        index = self._find_revision_index(revision_id)\n        if index is None:\n            return\n        self._data.pop(index)\n\n    def _find_revision_index(self, revision_id):\n        for i, rev in enumerate(self._data):\n            if rev.revision == revision_id:\n                return i\n        return None\n\n    def __eq__(self, other):\n        return self.dumps() == other.dumps()\n"
  },
  {
    "path": "conans/server/server_launcher.py",
    "content": "import os\n\nfrom conans.server.launcher import ServerLauncher\n\n\nlauncher = ServerLauncher(server_dir=os.environ.get(\"CONAN_SERVER_HOME\"))\napp = launcher.server.root_app\n\n\ndef main(*args):\n    launcher.launch()\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "conans/server/service/__init__.py",
    "content": ""
  },
  {
    "path": "conans/server/service/authorize.py",
    "content": "\"\"\"\nThis module handles user authentication and permissions\nfor read or write a conans or package.\n\nThis only reads from file the users and permissions.\n\nReplace this module with other that keeps the interface or super class.\n\"\"\"\n\nfrom abc import ABCMeta, abstractmethod\n\nfrom conan.internal.errors import InternalErrorException, AuthenticationException, ForbiddenException\n\n#  ############################################\n#  ############ ABSTRACT CLASSES ##############\n#  ############################################\nfrom conan.api.model import RecipeReference\n\n\nclass Authorizer(object, metaclass=ABCMeta):\n    \"\"\"\n    Handles the access permissions to conans and packages\n    \"\"\"\n\n    @abstractmethod\n    def check_read_conan(self, username, ref):\n        \"\"\"\n        username: User that request to read the conans\n        ref: RecipeReference\n        \"\"\"\n        raise NotImplementedError()\n\n    @abstractmethod\n    def check_write_conan(self, username, ref):\n        \"\"\"\n        username: User that request to write the conans\n        ref: RecipeReference\n        \"\"\"\n        raise NotImplementedError()\n\n    @abstractmethod\n    def check_delete_conan(self, username, ref):\n        \"\"\"\n        username: User requesting a recipe's deletion\n        ref: ConanFileReference\n        \"\"\"\n        raise NotImplementedError()\n\n    @abstractmethod\n    def check_read_package(self, username, pref):\n        \"\"\"\n        username: User that request to read the package\n        pref: PackageReference\n        \"\"\"\n        raise NotImplementedError()\n\n    @abstractmethod\n    def check_write_package(self, username, pref):\n        \"\"\"\n        username: User that request to write the package\n        pref: PackageReference\n        \"\"\"\n        raise NotImplementedError()\n\n    @abstractmethod\n    def check_delete_package(self, username, pref):\n        \"\"\"\n        username: User requesting a package's deletion\n        pref: PackageReference\n        \"\"\"\n        raise NotImplementedError()\n\n\nclass Authenticator(object, metaclass=ABCMeta):\n    \"\"\"\n    Handles the user authentication\n    \"\"\"\n    @abstractmethod\n    def valid_user(self, username, plain_password):\n        \"\"\"\n        username: User that request to read the conans\n        plain_password:\n        \"\"\"\n        raise NotImplementedError()\n\n#  ########################################################\n#  ############ BASIC IMPLEMENTATION CLASSES ##############\n#  ########################################################\n\n\nclass BasicAuthenticator(Authenticator):\n    \"\"\"\n    Handles the user authentication from a dict of plain users and passwords.\n    users is {username: plain-text-passwd}\n    \"\"\"\n\n    def __init__(self, users):\n        self.users = users\n\n    def valid_user(self, username, plain_password):\n        \"\"\"\n        username: User that request to read the conans\n        plain_password:\n        return: True if match False if don't\n        \"\"\"\n        return username in self.users and self.users[username] == plain_password\n\n\nclass BasicAuthorizer(Authorizer):\n    \"\"\"\n    Reads permissions from the config file (server.cfg)\n    \"\"\"\n\n    def __init__(self, read_permissions, write_permissions):\n        \"\"\"List of tuples with refs and users:\n\n        [(ref, \"user, user, user\"),\n         (ref, \"user3, user, user\")] \"\"\"\n\n        self.read_permissions = read_permissions\n        self.write_permissions = write_permissions\n\n    def check_read_conan(self, username, ref):\n        \"\"\"\n        username: User that request to read the conans\n        ref: RecipeReference\n        \"\"\"\n        self._check_any_rule_ok(username, self.read_permissions, ref)\n\n    def check_write_conan(self, username, ref):\n        \"\"\"\n        username: User that request to write the conans\n        ref: RecipeReference\n        \"\"\"\n        self._check_any_rule_ok(username, self.write_permissions, ref)\n\n    def check_delete_conan(self, username, ref):\n        \"\"\"\n        username: User that request to write the conans\n        ref: RecipeReference\n        \"\"\"\n        self.check_write_conan(username, ref)\n\n    def check_read_package(self, username, pref):\n        \"\"\"\n        username: User that request to read the package\n        pref: PackageReference\n        \"\"\"\n        self.check_read_conan(username, pref.ref)\n\n    def check_write_package(self, username, pref):\n        \"\"\"\n        username: User that request to write the package\n        pref: PackageReference\n        \"\"\"\n        self.check_write_conan(username, pref.ref)\n\n    def check_delete_package(self, username, pref):\n        \"\"\"\n        username: User that request to write the package\n        pref: PackageReference\n        \"\"\"\n        self.check_write_package(username, pref)\n\n    def _check_any_rule_ok(self, username, rules, *args, **kwargs):\n        for rule in rules:\n            # raises if don't\n            ret = self._check_rule_ok(username, rule, *args, **kwargs)\n            if ret:  # A rule is applied ok, if not apply keep looking\n                return True\n        if username:\n            raise ForbiddenException(\"Permission denied\")\n        else:\n            raise AuthenticationException()\n\n    def _check_rule_ok(self, username, rule, ref):\n        \"\"\"Checks if a rule specified in config file applies to current conans\n        reference and current user\"\"\"\n        try:\n            rule_ref = RecipeReference.loads(rule[0])\n        except Exception:\n            # TODO: Log error\n            raise InternalErrorException(\"Invalid server configuration. \"\n                                         \"Contact the administrator.\")\n        authorized_users = [_.strip() for _ in rule[1].split(\",\")]\n        if len(authorized_users) < 1:\n            raise InternalErrorException(\"Invalid server configuration. \"\n                                         \"Contact the administrator.\")\n\n        # Check if rule apply ref\n        if self._check_ref_apply_for_rule(rule_ref, ref):\n            if authorized_users[0] == \"*\" or username in authorized_users:\n                return True  # Ok, applies and match username\n            else:\n                if username:\n                    if authorized_users[0] == \"?\":\n                        return True  # Ok, applies and match any authenticated username\n                    else:\n                        raise ForbiddenException(\"Permission denied\")\n                else:\n                    raise AuthenticationException(\"Authentication error\")\n\n        return False\n\n    def _check_ref_apply_for_rule(self, rule_ref: RecipeReference, ref: RecipeReference):\n        \"\"\"Checks if a conans reference specified in config file applies to current conans\n        reference\"\"\"\n        return not((rule_ref.name != \"*\" and rule_ref.name != ref.name) or\n                   (rule_ref.version != \"*\" and rule_ref.version != ref.version) or\n                   (rule_ref.user != \"*\" and rule_ref.user != ref.user) or\n                   (rule_ref.channel != \"*\" and rule_ref.channel != ref.channel))\n"
  },
  {
    "path": "conans/server/service/mime.py",
    "content": "def get_mime_type(filepath):\n    if filepath.endswith(\".tgz\"):\n        mimetype = \"x-gzip\"\n    elif filepath.endswith(\".txz\"):\n        mimetype = \"x-xz\"\n    else:\n        mimetype = \"auto\"\n\n    return mimetype\n"
  },
  {
    "path": "conans/server/service/user_service.py",
    "content": "from conan.internal.errors import AuthenticationException\n\n\nclass UserService(object):\n\n    def __init__(self, authenticator, credentials_manager):\n        self.authenticator = authenticator\n        self.credentials_manager = credentials_manager\n\n    def authenticate(self, username, password):\n        valid = self.authenticator.valid_user(username, password)\n\n        # If user is valid returns a token\n        if valid:\n            token = self.credentials_manager.get_token_for(username)\n            return token\n        else:\n            raise AuthenticationException(\"Wrong user or password\")\n"
  },
  {
    "path": "conans/server/service/v2/__init__.py",
    "content": ""
  },
  {
    "path": "conans/server/service/v2/search.py",
    "content": "import copy\nimport os\nimport re\nfrom fnmatch import translate\n\nfrom conan.internal.errors import ForbiddenException, RecipeNotFoundException\nfrom conan.api.model import PkgReference\nfrom conan.api.model import RecipeReference\nfrom conan.internal.paths import CONANINFO\nfrom conans.server.utils.files import list_folder_subdirs\nfrom conan.internal.util.files import load\n\n\ndef _get_local_infos_min(server_store, ref, list_only):\n    result = {}\n    new_ref = ref\n    subdirs = list_folder_subdirs(server_store.packages(new_ref), level=1)\n    # Seems that Python3.12 os.walk is retrieving a different order of folders\n    for package_id in sorted(subdirs):\n        if package_id in result:\n            continue\n        if list_only:\n            result[package_id] = {}\n            continue\n        # Read conaninfo\n        pref = PkgReference(new_ref, package_id)\n        revision_entry = server_store.get_last_package_revision(pref)\n        if not revision_entry:\n            continue  # server can store empty package-revision list files\n        pref.revision = revision_entry.revision\n        info_path = os.path.join(server_store.package(pref), CONANINFO)\n        if not os.path.exists(info_path):\n            raise Exception(f\"No conaninfo.txt file for listed {pref}\")\n        content = load(info_path)\n        # From Conan 1.48 the conaninfo.txt is sent raw.\n        result[package_id] = {\"content\": content}\n\n    return result\n\n\ndef search_packages(server_store, ref, list_only):\n    \"\"\"\n    Return a dict like this:\n\n            {package_ID: {name: \"OpenCV\",\n                           version: \"2.14\",\n                           settings: {os: Windows}}}\n    param ref: RecipeReference object\n    \"\"\"\n    if ref.revision is None:  # TODO: Verify this sometimes happen\n        latest_rev = server_store.get_last_revision(ref).revision\n        ref.revision = latest_rev\n\n    ref_norev = copy.copy(ref)\n    ref_norev.revision = None\n    if not os.path.exists(server_store.conan_revisions_root(ref_norev)):\n        raise RecipeNotFoundException(ref)\n    infos = _get_local_infos_min(server_store, ref, list_only)\n    return infos\n\n\nclass SearchService(object):\n\n    def __init__(self, authorizer, server_store, auth_user):\n        self._authorizer = authorizer\n        self._server_store = server_store\n        self._auth_user = auth_user\n\n    def search_packages(self, reference, list_only=False):\n        \"\"\"Shared between v1 and v2, v1 will iterate rrevs\"\"\"\n        self._authorizer.check_read_conan(self._auth_user, reference)\n        info = search_packages(self._server_store, reference, list_only)\n        return info\n\n    def _search_recipes(self, pattern=None, ignorecase=True):\n        subdirs = list_folder_subdirs(basedir=self._server_store.store, level=5)\n\n        def underscore_to_none(field):\n            return field if field != \"_\" else None\n\n        ret = set()\n        if not pattern:\n            for folder in subdirs:\n                fields_dir = [underscore_to_none(d) for d in folder.split(\"/\")]\n                r = RecipeReference(*fields_dir)\n                r.revision = None\n                ret.add(r)\n        else:\n            # Conan references in main storage\n            pattern = str(pattern)\n            b_pattern = translate(pattern)\n            b_pattern = re.compile(b_pattern, re.IGNORECASE) if ignorecase else re.compile(b_pattern)\n            for subdir in subdirs:\n                fields_dir = [underscore_to_none(d) for d in subdir.split(\"/\")]\n                new_ref = RecipeReference(*fields_dir)\n                new_ref.revision = None\n                if new_ref.partial_match(b_pattern):\n                    ret.add(new_ref)\n\n        return sorted(ret)\n\n    def search(self, pattern=None, ignorecase=True):\n        \"\"\" Get all the info about any package\n            Attributes:\n                pattern = wildcards like opencv/*\n        \"\"\"\n        refs = self._search_recipes(pattern, ignorecase)\n        filtered = []\n        # Filter out restricted items\n        for ref in refs:\n            try:\n                self._authorizer.check_read_conan(self._auth_user, ref)\n                filtered.append(ref)\n            except ForbiddenException:\n                pass\n        return filtered\n"
  },
  {
    "path": "conans/server/service/v2/service_v2.py",
    "content": "import copy\nimport os\n\nfrom bottle import FileUpload, static_file\n\nfrom conan.internal.errors import NotFoundException, RecipeNotFoundException, PackageNotFoundException\nfrom conan.internal.paths import CONAN_MANIFEST\nfrom conan.api.model import PkgReference\nfrom conans.server.service.mime import get_mime_type\nfrom conans.server.store.server_store import ServerStore\nfrom conan.internal.util.files import mkdir\n\n\nclass ConanServiceV2:\n\n    def __init__(self, authorizer, server_store):\n        assert(isinstance(server_store, ServerStore))\n        self._authorizer = authorizer\n        self._server_store = server_store\n\n    # RECIPE METHODS\n    def get_recipe_file_list(self, ref,  auth_user):\n        self._authorizer.check_read_conan(auth_user, ref)\n        try:\n            file_list = self._server_store.get_recipe_file_list(ref)\n        except NotFoundException:\n            raise RecipeNotFoundException(ref)\n        if not file_list:\n            raise RecipeNotFoundException(ref)\n\n        # Send speculative metadata (empty) for files (non breaking future changes)\n        return {\"files\": {key: {} for key in file_list}}\n\n    def get_recipe_file(self, reference, filename, auth_user):\n        self._authorizer.check_read_conan(auth_user, reference)\n        path = self._server_store.get_recipe_file_path(reference, filename)\n        return static_file(os.path.basename(path), root=os.path.dirname(path),\n                           mimetype=get_mime_type(path))\n\n    def upload_recipe_file(self, body, headers, reference, filename, auth_user):\n        self._authorizer.check_write_conan(auth_user, reference)\n        # FIXME: Check that reference contains revision (MANDATORY TO UPLOAD)\n        path = self._server_store.get_recipe_file_path(reference, filename)\n        self._upload_to_path(body, headers, path)\n\n        # If the upload was ok, of the manifest, update the pointer to the latest\n        if filename == CONAN_MANIFEST:\n            self._server_store.update_last_revision(reference)\n\n    def get_recipe_revisions_references(self, ref, auth_user):\n        self._authorizer.check_read_conan(auth_user, ref)\n        ref_norev = copy.copy(ref)\n        ref_norev.revision = None\n        root = self._server_store.conan_revisions_root(ref_norev)\n        if not self._server_store.path_exists(root):\n            raise RecipeNotFoundException(ref)\n        return self._server_store.get_recipe_revisions_references(ref)\n\n    def get_package_revisions_references(self, pref, auth_user):\n        self._authorizer.check_read_conan(auth_user, pref.ref)\n        ref_norev = copy.copy(pref.ref)\n        ref_norev.revision = None\n        root = self._server_store.conan_revisions_root(ref_norev)\n        if not self._server_store.path_exists(root):\n            raise RecipeNotFoundException(pref.ref)\n\n        ret = self._server_store.get_package_revisions_references(pref)\n        return ret\n\n    def get_latest_revision(self, ref, auth_user):\n        self._authorizer.check_read_conan(auth_user, ref)\n        tmp = self._server_store.get_last_revision(ref)\n        if not tmp:\n            raise RecipeNotFoundException(ref)\n        return tmp\n\n    def get_latest_package_reference(self, pref, auth_user):\n        self._authorizer.check_read_conan(auth_user, pref.ref)\n        _pref = self._server_store.get_last_package_revision(pref)\n        if not _pref:\n            raise PackageNotFoundException(pref)\n        return _pref\n\n    # PACKAGE METHODS\n    def get_package_file_list(self, pref, auth_user):\n        self._authorizer.check_read_conan(auth_user, pref.ref)\n        file_list = self._server_store.get_package_file_list(pref)\n        if not file_list:\n            raise PackageNotFoundException(pref)\n        # Send speculative metadata (empty) for files (non breaking future changes)\n        return {\"files\": {key: {} for key in file_list}}\n\n    def get_package_file(self, pref, filename, auth_user):\n        self._authorizer.check_read_conan(auth_user, pref.ref)\n        path = self._server_store.get_package_file_path(pref, filename)\n        return static_file(os.path.basename(path), root=os.path.dirname(path),\n                           mimetype=get_mime_type(path))\n\n    def upload_package_file(self, body, headers, pref, filename, auth_user):\n        self._authorizer.check_write_conan(auth_user, pref.ref)\n\n        # Check if the recipe exists\n        recipe_path = self._server_store.export(pref.ref)\n        if not os.path.exists(recipe_path):\n            raise RecipeNotFoundException(pref.ref)\n        path = self._server_store.get_package_file_path(pref, filename)\n        self._upload_to_path(body, headers, path)\n\n        # If the upload was ok, of the manifest, update the pointer to the latest\n        if filename == CONAN_MANIFEST:\n            self._server_store.update_last_package_revision(pref)\n\n    # Misc\n    @staticmethod\n    def _upload_to_path(body, headers, path):\n        file_saver = FileUpload(body, None,\n                                filename=os.path.basename(path),\n                                headers=headers)\n        if os.path.exists(path):\n            os.unlink(path)\n        if not os.path.exists(os.path.dirname(path)):\n            mkdir(os.path.dirname(path))\n        file_saver.save(os.path.dirname(path))\n\n    # REMOVE\n    def remove_recipe(self, ref, auth_user):\n        self._authorizer.check_delete_conan(auth_user, ref)\n        self._server_store.remove_recipe(ref)\n\n    def remove_package(self, pref, auth_user):\n        self._authorizer.check_delete_package(auth_user, pref)\n\n        for rrev in self._server_store.get_recipe_revisions_references(pref.ref):\n            new_ref = copy.copy(pref.ref)\n            new_ref.revision = rrev.revision\n            # FIXME: Just assign rrev when introduce RecipeReference\n            new_pref = PkgReference(new_ref, pref.package_id, pref.revision)\n            for _pref in self._server_store.get_package_revisions_references(new_pref):\n                self._server_store.remove_package(_pref)\n\n    def remove_all_packages(self, ref, auth_user):\n        self._authorizer.check_delete_conan(auth_user, ref)\n        for rrev in self._server_store.get_recipe_revisions_references(ref):\n            tmp = copy.copy(ref)\n            tmp.revision = rrev.revision\n            self._server_store.remove_all_packages(tmp)\n"
  },
  {
    "path": "conans/server/store/__init__.py",
    "content": ""
  },
  {
    "path": "conans/server/store/disk_adapter.py",
    "content": "import os\n\nimport fasteners\n\nfrom conan.internal.errors import NotFoundException\nfrom conan.internal.util.files import rmdir\nfrom conans.server.utils.files import path_exists, relative_dirs\n\n\nclass ServerDiskAdapter:\n    \"\"\"Manage access to disk files with common methods required\n    for conan operations\"\"\"\n    def __init__(self, base_url, base_storage_path):\n        \"\"\"\n        :param base_url Base url for generate urls to download and upload operations\"\"\"\n\n        self.base_url = base_url\n        # URLs are generated removing this base path\n        self._store_folder = base_storage_path\n\n    def get_file_list(self, absolute_path=\"\"):\n        if not path_exists(absolute_path, self._store_folder):\n            raise NotFoundException(\"\")\n        paths = relative_dirs(absolute_path)\n        abs_paths = [os.path.join(absolute_path, relpath) for relpath in paths]\n        return abs_paths\n\n    def delete_folder(self, path):\n        \"\"\"Delete folder from disk. Path already contains base dir\"\"\"\n        if not path_exists(path, self._store_folder):\n            raise NotFoundException(\"\")\n        rmdir(path)\n\n    def path_exists(self, path):\n        return os.path.exists(path)\n\n    def read_file(self, path, lock_file):\n        with fasteners.InterProcessLock(lock_file):\n            with open(path) as f:\n                return f.read()\n\n    def write_file(self, path, contents, lock_file):\n        with fasteners.InterProcessLock(lock_file):\n            with open(path, \"w\") as f:\n                f.write(contents)\n"
  },
  {
    "path": "conans/server/store/server_store.py",
    "content": "import os\nfrom os.path import join, normpath, relpath\n\nfrom conan.internal.errors import RecipeNotFoundException, PackageNotFoundException\nfrom conan.internal.paths import CONAN_MANIFEST\nfrom conan.api.model import PkgReference\nfrom conan.api.model import RecipeReference\nfrom conans.server.revision_list import RevisionList\n\nREVISIONS_FILE = \"revisions.txt\"\nSERVER_EXPORT_FOLDER = \"export\"\nSERVER_PACKAGES_FOLDER = \"package\"\n\n\ndef ref_dir_repr(ref):\n    return \"/\".join([ref.name, str(ref.version), ref.user or \"_\", ref.channel or \"_\"])\n\n\nclass ServerStore(object):\n\n    def __init__(self, storage_adapter):\n        self._storage_adapter = storage_adapter\n        self._store_folder = storage_adapter._store_folder\n\n    @property\n    def store(self):\n        return self._store_folder\n\n    def base_folder(self, ref):\n        assert ref.revision is not None, \"BUG: server store needs RREV to get recipe reference\"\n        tmp = normpath(join(self.store, ref_dir_repr(ref)))\n        return join(tmp, ref.revision)\n\n    def conan_revisions_root(self, ref):\n        \"\"\"Parent folder of the conan package, for all the revisions\"\"\"\n        assert not ref.revision, \"BUG: server store doesn't need RREV to conan_revisions_root\"\n        return normpath(join(self.store, ref_dir_repr(ref)))\n\n    def packages(self, ref):\n        return join(self.base_folder(ref), SERVER_PACKAGES_FOLDER)\n\n    def package(self, pref):\n        assert pref.revision is not None, \"BUG: server store needs PREV for package\"\n        tmp = join(self.packages(pref.ref), pref.package_id)\n        return join(tmp, pref.revision)\n\n    def export(self, ref):\n        return join(self.base_folder(ref), SERVER_EXPORT_FOLDER)\n\n    def get_recipe_file_path(self, ref, filename):\n        abspath = join(self.export(ref), filename)\n        return abspath\n\n    def get_package_file_path(self, pref, filename):\n        p_path = self.package(pref)\n        abspath = join(p_path, filename)\n        return abspath\n\n    def path_exists(self, path):\n        return self._storage_adapter.path_exists(path)\n\n    # ############ ONLY FILE LIST SNAPSHOTS (APIv2)\n    def get_recipe_file_list(self, ref):\n        \"\"\"Returns a  [filepath] \"\"\"\n        assert isinstance(ref, RecipeReference)\n        files = self._get_file_list(self.export(ref))\n        if CONAN_MANIFEST not in files:\n            raise RecipeNotFoundException(ref)\n        return files\n\n    def get_package_file_list(self, pref):\n        \"\"\"Returns a  [filepath] \"\"\"\n        assert isinstance(pref, PkgReference)\n        files = self._get_file_list(self.package(pref))\n        if CONAN_MANIFEST not in files:\n            raise PackageNotFoundException(pref)\n        return files\n\n    def _get_file_list(self, relative_path):\n        file_list = self._storage_adapter.get_file_list(relative_path)\n        file_list = [relpath(old_key, relative_path) for old_key in file_list]\n        return file_list\n\n    def _delete_empty_dirs(self, ref):\n        lock_files = {REVISIONS_FILE, \"%s.lock\" % REVISIONS_FILE}\n\n        ref_path = normpath(join(self.store, ref_dir_repr(ref)))\n        if ref.revision:\n            ref_path = join(ref_path, ref.revision)\n        for _ in range(4 if not ref.revision else 5):\n            if os.path.exists(ref_path):\n                if set(os.listdir(ref_path)) == lock_files:\n                    for lock_file in lock_files:\n                        os.unlink(os.path.join(ref_path, lock_file))\n                try:  # Take advantage that os.rmdir does not delete non-empty dirs\n                    os.rmdir(ref_path)\n                except OSError:\n                    break  # not empty\n            ref_path = os.path.dirname(ref_path)\n\n    # ######### DELETE (APIv1 and APIv2)\n    def remove_recipe(self, ref):\n        assert isinstance(ref, RecipeReference)\n        if not ref.revision:\n            self._storage_adapter.delete_folder(self.conan_revisions_root(ref))\n        else:\n            self._storage_adapter.delete_folder(self.base_folder(ref))\n            self._remove_revision_from_index(ref)\n        self._delete_empty_dirs(ref)\n\n    def remove_package(self, pref):\n        assert isinstance(pref, PkgReference)\n        assert pref.revision is not None, \"BUG: server store needs PREV remove_package\"\n        assert pref.ref.revision is not None, \"BUG: server store needs RREV remove_package\"\n        package_folder = self.package(pref)\n        self._storage_adapter.delete_folder(package_folder)\n        self._remove_package_revision_from_index(pref)\n\n    def remove_all_packages(self, ref):\n        assert ref.revision is not None, \"BUG: server store needs RREV remove_all_packages\"\n        assert isinstance(ref, RecipeReference)\n        packages_folder = self.packages(ref)\n        self._storage_adapter.delete_folder(packages_folder)\n\n    # Methods to manage revisions\n    def get_last_revision(self, ref):\n        assert(isinstance(ref, RecipeReference))\n        rev_file_path = self._recipe_revisions_file(ref)\n        return self._get_latest_revision(rev_file_path)\n\n    def get_recipe_revisions_references(self, ref):\n        \"\"\"Returns a RevisionList\"\"\"\n        if ref.revision:\n            tmp = RevisionList()\n            tmp.add_revision(ref.revision)\n            return tmp.as_list()\n        rev_file_path = self._recipe_revisions_file(ref)\n        revs = self._get_revisions_list(rev_file_path).as_list()\n        if not revs:\n            raise RecipeNotFoundException(ref)\n        return revs\n\n    def get_last_package_revision(self, pref):\n        assert(isinstance(pref, PkgReference))\n        rev_file_path = self._package_revisions_file(pref)\n        rev = self._get_latest_revision(rev_file_path)\n        if rev:\n            return PkgReference(pref.ref, pref.package_id, rev.revision, rev.time)\n        return None\n\n    def update_last_revision(self, ref):\n        assert(isinstance(ref, RecipeReference))\n        rev_file_path = self._recipe_revisions_file(ref)\n        self._update_last_revision(rev_file_path, ref)\n\n    def update_last_package_revision(self, pref):\n        assert(isinstance(pref, PkgReference))\n        rev_file_path = self._package_revisions_file(pref)\n        self._update_last_revision(rev_file_path, pref)\n\n    def _update_last_revision(self, rev_file_path, ref):\n        if self._storage_adapter.path_exists(rev_file_path):\n            rev_file = self._storage_adapter.read_file(rev_file_path,\n                                                       lock_file=rev_file_path + \".lock\")\n            rev_list = RevisionList.loads(rev_file)\n        else:\n            rev_list = RevisionList()\n        assert ref.revision is not None, \"Invalid revision for: %s\" % repr(ref)\n        rev_list.add_revision(ref.revision)\n        self._storage_adapter.write_file(rev_file_path, rev_list.dumps(),\n                                         lock_file=rev_file_path + \".lock\")\n\n    def get_package_revisions_references(self, pref):\n        \"\"\"Returns a RevisionList\"\"\"\n        assert pref.ref.revision is not None, \\\n            \"BUG: server store needs PREV get_package_revisions_references\"\n        if pref.revision:\n            tmp = RevisionList()\n            tmp.add_revision(pref.revision)\n            return [PkgReference(pref.ref, pref.package_id, rev.revision, rev.time)\n                    for rev in tmp.as_list()]\n\n        tmp = self._package_revisions_file(pref)\n        ret = self._get_revisions_list(tmp).as_list()\n        if not ret:\n            raise PackageNotFoundException(pref)\n        return [PkgReference(pref.ref, pref.package_id, rev.revision, rev.time) for rev in ret]\n\n    def _get_revisions_list(self, rev_file_path):\n        if self._storage_adapter.path_exists(rev_file_path):\n            rev_file = self._storage_adapter.read_file(rev_file_path,\n                                                       lock_file=rev_file_path + \".lock\")\n            rev_list = RevisionList.loads(rev_file)\n            return rev_list\n        else:\n            return RevisionList()\n\n    def _get_latest_revision(self, rev_file_path):\n        rev_list = self._get_revisions_list(rev_file_path)\n        if not rev_list:\n            return None\n        return rev_list.latest_revision()\n\n    def _recipe_revisions_file(self, ref):\n        recipe_folder = normpath(join(self._store_folder, ref_dir_repr(ref)))\n        return join(recipe_folder, REVISIONS_FILE)\n\n    def _package_revisions_file(self, pref):\n        tmp = normpath(join(self._store_folder, ref_dir_repr(pref.ref)))\n        revision = {None: \"\"}.get(pref.ref.revision, pref.ref.revision)\n        p_folder = join(tmp, revision, SERVER_PACKAGES_FOLDER, pref.package_id)\n        return join(p_folder, REVISIONS_FILE)\n\n    def get_package_revision_time(self, pref):\n        try:\n            rev_list = self._load_package_revision_list(pref)\n        except (IOError, OSError):\n            return None\n\n        return rev_list.get_time(pref.revision)\n\n    def _remove_revision_from_index(self, ref):\n        rev_list = self._load_revision_list(ref)\n        rev_list.remove_revision(ref.revision)\n        self._save_revision_list(rev_list, ref)\n\n    def _remove_package_revision_from_index(self, pref):\n        rev_list = self._load_package_revision_list(pref)\n        rev_list.remove_revision(pref.revision)\n        self._save_package_revision_list(rev_list, pref)\n\n    def _load_revision_list(self, ref):\n        path = self._recipe_revisions_file(ref)\n        rev_file = self._storage_adapter.read_file(path, lock_file=path + \".lock\")\n        return RevisionList.loads(rev_file)\n\n    def _save_revision_list(self, rev_list, ref):\n        path = self._recipe_revisions_file(ref)\n        self._storage_adapter.write_file(path, rev_list.dumps(), lock_file=path + \".lock\")\n\n    def _save_package_revision_list(self, rev_list, pref):\n        path = self._package_revisions_file(pref)\n        self._storage_adapter.write_file(path, rev_list.dumps(), lock_file=path + \".lock\")\n\n    def _load_package_revision_list(self, pref):\n        path = self._package_revisions_file(pref)\n        rev_file = self._storage_adapter.read_file(path, lock_file=path + \".lock\")\n        return RevisionList.loads(rev_file)\n"
  },
  {
    "path": "conans/server/utils/__init__.py",
    "content": ""
  },
  {
    "path": "conans/server/utils/files.py",
    "content": "import os\nimport sys\n\n\ndef list_folder_subdirs(basedir, level):\n    ret = []\n    for root, dirs, _ in os.walk(basedir):\n        rel_path = os.path.relpath(root, basedir)\n        if rel_path == \".\":\n            continue\n        dir_split = rel_path.split(os.sep)\n        if len(dir_split) == level:\n            ret.append(\"/\".join(dir_split))\n            dirs[:] = []  # Stop iterate subdirs\n    return ret\n\n\ndef path_exists(path, basedir):\n    \"\"\"Case sensitive, for windows, optional\n    basedir for skip caps check for tmp folders in testing for example (returned always\n    in lowercase for some strange reason)\"\"\"\n    exists = os.path.exists(path)\n    if not exists or sys.platform == \"linux2\":\n        return exists\n\n    path = os.path.normpath(path)\n    path = os.path.relpath(path, basedir)\n    chunks = path.split(os.sep)\n    tmp = basedir\n\n    for chunk in chunks:\n        if chunk and chunk not in os.listdir(tmp):\n            return False\n        tmp = os.path.normpath(tmp + os.sep + chunk)\n    return True\n\n\ndef relative_dirs(path):\n    \"\"\" Walks a dir and return a list with the relative paths \"\"\"\n    ret = []\n    for dirpath, _, fnames in os.walk(path):\n        for filename in fnames:\n            tmp = os.path.join(dirpath, filename)\n            tmp = tmp[len(path) + 1:]\n            ret.append(tmp)\n    return ret\n"
  },
  {
    "path": "contributors.txt",
    "content": "Contributors\n-------------\n\nThis is a very partial list of contributors to this project source code, in alphabetical order, those who\nexplicitly wanted to add details here. For the whole list (+220), refer to https://github.com/conan-io/conan/graphs/contributors\n\nMany thanks to all of them!\n\n- Bocanegra Algarra, Raul (raul.bocanegra.algarra@gmail.com)\n- Cicholewski, Adrian (et666@t-online.de)\n- Dauphin, Loïc (astralien3000@yahoo.fr, @astralien3000)\n- Díaz Más, Luis (piponazo@gmail, @pipotux)\n- Dragly, Svenn-Arne (dragly.org)\n- Ford, Andrew (andrewford55139@gmail.com)\n- Hieta, Tobias (tobias@plex.tv, @tobiashieta)\n- Hochstedler, Reid\n- Ivek, Tomislav (tomislav.ivek@gmail.com, @tomivek)\n- Koch, Marco (marco-koch@t-online.de, @MarcoKoch)\n- Kourkoulis, Dimitri (@dimi309)\n- Lee, Jeongseok (jslee02@gmail.com, @jslee02)\n- Lord, Matthew( @luckielordie )\n- Márki, Róbert (gsmiko@gmail.com, @robertmrk)\n- Ray, Chris (chris@xaltotun.com)\n- Ries, Uilian (uilianries@gmail.com, @uilianries)\n- Sechet, Olivier (osechet@gmail.com)\n- Sturm, Fabian (f@rtfs.org, @sturmf)\n- Williams, Jordan (jordan@jwillikers.com)\n"
  },
  {
    "path": "pyinstaller.py",
    "content": "\"\"\"\nThis file is able to create a self contained Conan executable that contains all it needs,\nincluding the Python interpreter, so it wouldnt be necessary to have Python installed\nin the system\nIt is important to install the dependencies and the project first with \"pip install -e .\"\nwhich configures the project as \"editable\", that is, to run from the current source folder\nAfter creating the executable, it can be pip uninstalled\n\n$ pip install -e .\n$ python pyinstaller.py\n\nThis has to run in the same platform that will be using the executable, pyinstaller does\nnot cross-build\n\nThe resulting executable can be put in the system PATH of the running machine\n\"\"\"\n\nimport argparse\nimport os\nimport platform\nimport shutil\nimport sys\n\nfrom conan import __version__\n\n\ndef _run_bin(pyinstaller_path):\n    # run the binary to test if working\n    conan_bin = os.path.join(pyinstaller_path, 'dist', 'conan', 'conan')\n    if platform.system() == 'Windows':\n        conan_bin = '\"' + conan_bin + '.exe' + '\"'\n    retcode = os.system(conan_bin)\n    if retcode != 0:\n        raise Exception(\"Binary not working\")\n\n\ndef _windows_version_file(version):\n    template = \"\"\"# UTF-8\n#\n# For more details about fixed file info 'ffi' see:\n# http://msdn.microsoft.com/en-us/library/ms646997.aspx\nVSVersionInfo(\n  ffi=FixedFileInfo(\n    # filevers and prodvers should be always a tuple with four items: (1, 2, 3, 4)\n    # Set not needed items to zero 0.\n    filevers={version_tuple},\n    prodvers={version_tuple},\n    # Contains a bitmask that specifies the valid bits 'flags'r\n    mask=0x3f,\n    # Contains a bitmask that specifies the Boolean attributes of the file.\n    flags=0x0,\n    # The operating system for which this file was designed.\n    # 0x4 - NT and there is no need to change it.\n    OS=0x4,\n    # The general type of file.\n    # 0x1 - the file is an application.\n    fileType=0x1,\n    # The function of the file.\n    # 0x0 - the function is not defined for this fileType\n    subtype=0x0,\n    # Creation date and time stamp.\n    date=(0, 0)\n    ),\n  kids=[\n    StringFileInfo(\n      [\n      StringTable(\n        u'000004b0',\n        [StringStruct(u'Comments', u'This executable was created with pyinstaller'),\n        StringStruct(u'CompanyName', u'JFrog'),\n        StringStruct(u'FileDescription', u'Conan C, C++ Open Source Package Manager'),\n        StringStruct(u'FileVersion', u'{version}'),\n        StringStruct(u'LegalCopyright', u'Copyright 2020 JFrog'),\n        StringStruct(u'ProductName', u'Conan'),\n        StringStruct(u'ProductVersion', u'{version}')])\n      ]),\n    VarFileInfo([VarStruct(u'Translation', [0, 1200])])\n  ]\n)\"\"\"\n    if \"-\" in version:\n        version, _ = version.split(\"-\")\n    version_tuple = tuple([int(v) for v in version.split(\".\")] + [0])\n    return template.format(version=version, version_tuple=version_tuple)\n\n\ndef pyinstall(source_folder, onefile=False):\n    try:\n        import PyInstaller.__main__  # noqa  Pyinstaller is not in the default requirements.txt\n    except ImportError:\n        print(f\"ERROR: PyInstaller not found. Please install it with \"\n              f\"'python -m pip install pyinstaller'\")\n        sys.exit(-1)\n\n    pyinstaller_path = os.path.join(os.getcwd(), 'pyinstaller')\n    if not os.path.exists(pyinstaller_path):\n        os.mkdir(pyinstaller_path)\n    try:\n        shutil.rmtree(os.path.join(pyinstaller_path))\n    except Exception as e:\n        print(\"Unable to remove old folder\", e)\n\n    conan_path = os.path.join(source_folder, 'conans', 'conan.py')\n    hidden_imports = []\n\n    if not os.path.exists(pyinstaller_path):\n        os.mkdir(pyinstaller_path)\n\n    if platform.system() != \"Windows\":\n        hidden_imports.append(\"setuptools.msvc\")\n        win_ver = \"\"\n    else:\n        win_ver_file = os.path.join(pyinstaller_path, 'windows-version-file')\n        content = _windows_version_file(__version__)\n        with open(win_ver_file, 'w') as file:\n            file.write(content)\n        win_ver = [\"--version-file\", win_ver_file]\n\n    if onefile:\n        distpath = os.path.join(pyinstaller_path, \"dist\", \"conan\")\n    else:\n        distpath = os.path.join(pyinstaller_path, \"dist\")\n\n    command_args = [conan_path, \"--noconfirm\", f\"--paths={source_folder}\",\n                    \"--console\", f\"--distpath={distpath}\"]\n\n    # Python standard library modules to ensure in the bundle\n    hidden_imports.append(\"glob\")\n    hidden_imports.append(\"pathlib\")\n    # inclusion of full conan package (with exclusion of irrelevant modules)\n    command_args.append(\"--collect-submodules=conan\")\n    command_args.append(\"--exclude-module=conan.test.*\")\n\n    command_args.extend(f\"--hidden-import={name}\" for name in hidden_imports)\n\n    if win_ver:\n        command_args.extend(win_ver)\n    if onefile:\n        command_args.append(\"--onefile\")\n\n    PyInstaller.__main__.run(command_args)\n\n    _run_bin(pyinstaller_path)\n\n    return os.path.abspath(os.path.join(pyinstaller_path, 'dist', 'conan'))\n\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser()\n    parser.add_argument('--onefile', action='store_true')\n    parser.set_defaults(onefile=False)\n    args = parser.parse_args()\n\n    src_folder = os.path.abspath(os.path.dirname(os.path.abspath(__file__)))\n    output_folder = pyinstall(src_folder, args.onefile)\n    print(\"\\n**************Conan binaries created!******************\\n\"\n          \"\\nAppend this folder to your system PATH: '%s'\\n\"\n          \"Feel free to move the whole folder to another location.\" % output_folder)\n"
  },
  {
    "path": "pyproject.toml",
    "content": "[build-system]\nrequires = [\"setuptools\", \"wheel\"]\nbuild-backend = \"setuptools.build_meta\"\n"
  },
  {
    "path": "pytest.ini",
    "content": "[pytest]\nnorecursedirs = '.*', 'dist', 'CVS', '_darcs', '{arch}', '*.egg', 'venv', 'assets'\ntestpaths = 'test'\nmarkers =\n   docker_runner: Mark tests that require Docker to run.\n   artifactory_ready: These tests can be run against a full Artifactory\n   slow: These tests can executed more occasionally, slow, but unlikely to fail in normal PRs\nfilterwarnings =\n    ignore:'cgi' is deprecated:DeprecationWarning\n"
  },
  {
    "path": "setup.cfg",
    "content": "[pep8]\ncount = False\nmax-line-length = 100\nstatistics = False\n\n; Coverage files are generated across different OS and machines, thus, coverage\n; reports will contain different absolute paths to reference to the same\n; project relative paths.\n; This option makes coverage to use relative paths to the project root,\n; removing the need for setting arbitrary runners paths described in here:\n; https://coverage.readthedocs.io/en/coverage-4.0.3/config.html#paths\n[coverage:run]\nrelative_files = True\n"
  },
  {
    "path": "setup.py",
    "content": "\"\"\"A setuptools based setup module.\nSee:\nhttps://packaging.python.org/en/latest/distributing.html\nhttps://github.com/pypa/sampleproject\n\"\"\"\n\n# Always prefer setuptools over distutils\nfrom setuptools import find_packages, setup\n\nimport os\nimport re\nfrom os import path\n\n\n# The tests utils are used by conan-package-tools\nhere = path.abspath(path.dirname(__file__))\nexcluded_test_packages = [\"test*\"]\n\n\ndef get_requires(filename):\n    requirements = []\n    with open(filename, \"rt\") as req_file:\n        for line in req_file.read().splitlines():\n            if not line.strip().startswith(\"#\"):\n                requirements.append(line)\n    return requirements\n\n\ndef load_version():\n    \"\"\" Loads a file content \"\"\"\n    filename = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)),\n                                            \"conan\", \"__init__.py\"))\n    with open(filename, \"rt\") as version_file:\n        conan_init = version_file.read()\n        version = re.search(r\"__version__ = '([0-9a-z.-]+)'\", conan_init).group(1)\n        return version\n\n\ndef generate_long_description_file():\n    this_directory = path.abspath(path.dirname(__file__))\n    with open(path.join(this_directory, 'README.md')) as f:\n        long_description = f.read()\n    return long_description\n\n\nproject_requirements = get_requires(\"conans/requirements.txt\")\ndev_requirements = get_requires(\"conans/requirements_dev.txt\")\nrunners_requirements = get_requires(\"conans/requirements_runner.txt\")\nexcluded_server_packages = [\"conans.server*\"]\nexclude = excluded_test_packages + excluded_server_packages\n\n\nsetup(\n    name='conan',\n    python_requires='>=3.7',\n    # Versions should comply with PEP440.  For a discussion on single-sourcing\n    # the version across setup.py and the project code, see\n    # https://packaging.python.org/en/latest/single_source_version.html\n    version=load_version(),  # + \".rc1\",\n\n    description='Conan C/C++ package manager',\n    long_description=generate_long_description_file(),\n    long_description_content_type='text/markdown',\n\n    # The project's main homepage.\n    url='https://conan.io',\n    project_urls={\n        'Documentation': 'https://docs.conan.io',\n        'Source': 'https://github.com/conan-io/conan',\n        'Tracker': 'https://github.com/conan-io/conan/issues',\n    },\n\n    # Author details\n    author='JFrog LTD',\n    author_email='luism@jfrog.com',\n\n    # Choose your license\n    license='MIT',\n\n    # See https://pypi.python.org/pypi?%3Aaction=list_classifiers\n    classifiers=[\n        'Development Status :: 5 - Production/Stable',\n        'Intended Audience :: Developers',\n        'Topic :: Software Development :: Build Tools',\n        'License :: OSI Approved :: MIT License',\n        'Programming Language :: Python :: 3',\n        'Programming Language :: Python :: 3.7',\n        'Programming Language :: Python :: 3.8',\n        'Programming Language :: Python :: 3.9',\n        'Programming Language :: Python :: 3.10',\n        'Programming Language :: Python :: 3.11',\n        'Programming Language :: Python :: 3.12',\n        'Programming Language :: Python :: 3.13'\n    ],\n\n    # What does your project relate to?\n    keywords=['C/C++', 'package', 'libraries', 'developer', 'manager',\n              'dependency', 'tool', 'c', 'c++', 'cpp'],\n\n    # You can just specify the packages manually here if your project is\n    # simple. Or you can use find_packages().\n    packages=find_packages(exclude=exclude),\n\n    # Alternatively, if you want to distribute just a my_module.py, uncomment\n    # this:\n    #   py_modules=[\"my_module\"],\n\n    # List run-time dependencies here.  These will be installed by pip when\n    # your project is installed. For an analysis of \"install_requires\" vs pip's\n    # requirements files see:\n    # https://packaging.python.org/en/latest/requirements.html\n    install_requires=project_requirements,\n\n    # List additional groups of dependencies here (e.g. development\n    # dependencies). You can install these using the following syntax,\n    # for example:\n    # $ pip install -e .[dev,test,runners]\n    extras_require={\n        'dev': dev_requirements,\n        'test': dev_requirements,\n        'runners': runners_requirements\n    },\n\n    # If there are data files included in your packages that need to be\n    # installed, specify them here.  If using Python 2.6 or less, then these\n    # have to be included in MANIFEST.in as well.\n    package_data={\n        'conans': ['*.txt'],\n    },\n\n    # Although 'package_data' is the preferred approach, in some case you may\n    # need to place data files outside of your packages. See:\n    # http://docs.python.org/3.4/distutils/setupscript.html#installing-additional-files # noqa\n    # In this case, 'data_file' will be installed into '<sys.prefix>/my_data'\n    # data_files=[('my_data', ['data/data_file'])],\n\n    # To provide executable scripts, use entry points in preference to the\n    # \"scripts\" keyword. Entry points provide cross-platform support and allow\n    # pip to create the appropriate form of executable for the target platform.\n    entry_points={\n        'console_scripts': [\n            'conan=conans.conan:run',\n        ],\n    },\n)\n"
  },
  {
    "path": "setup_server.py",
    "content": "\"\"\"A setuptools based setup module.\nSee:\nhttps://packaging.python.org/en/latest/distributing.html\nhttps://github.com/pypa/sampleproject\n\"\"\"\n\n# To use a consistent encoding\nfrom os import path\n\n# Always prefer setuptools over distutils\nfrom setuptools import find_packages, setup\n\nimport os\nimport re\n\n\n# The tests utils are used by conan-package-tools\nhere = path.abspath(path.dirname(__file__))\nexcluded_test_packages = [\"test\"]\n\n\ndef get_requires(filename):\n    requirements = []\n    with open(filename, \"rt\") as req_file:\n        for line in req_file.read().splitlines():\n            if not line.strip().startswith(\"#\"):\n                requirements.append(line)\n    return requirements\n\n\ndef load_version():\n    \"\"\" Loads a file content \"\"\"\n    filename = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)),\n                                            \"conan\", \"__init__.py\"))\n    with open(filename, \"rt\") as version_file:\n        conan_init = version_file.read()\n        version = re.search(r\"__version__ = '([0-9a-z.-]+)'\", conan_init).group(1)\n        return version\n\n\ndef generate_long_description_file():\n    this_directory = path.abspath(path.dirname(__file__))\n    with open(path.join(this_directory, 'README.md'), encoding='utf-8') as f:\n        long_description = f.read()\n    return long_description\n\n\nproject_requirements = get_requires(\"conans/requirements.txt\")\nproject_requirements.extend(get_requires(\"conans/requirements_server.txt\"))\ndev_requirements = get_requires(\"conans/requirements_dev.txt\")\n\n\nsetup(\n    name='conan_server',\n    # Versions should comply with PEP440.  For a discussion on single-sourcing\n    # the version across setup.py and the project code, see\n    # https://packaging.python.org/en/latest/single_source_version.html\n    version=load_version(),  # + \".rc1\",\n\n    description='Conan Server of Conan C/C++ package manager',\n    long_description=generate_long_description_file(),\n    long_description_content_type='text/markdown',\n\n    # The project's main homepage.\n    url='https://conan.io',\n\n    # Author details\n    author='JFrog LTD',\n    author_email='luism@jfrog.com',\n\n    # Choose your license\n    license='MIT',\n\n    # See https://pypi.python.org/pypi?%3Aaction=list_classifiers\n    classifiers=[\n        'Development Status :: 5 - Production/Stable',\n        'Intended Audience :: Developers',\n        'Topic :: Software Development :: Build Tools',\n        'License :: OSI Approved :: MIT License',\n        'Programming Language :: Python :: 3',\n        'Programming Language :: Python :: 3.7',\n        'Programming Language :: Python :: 3.8',\n        'Programming Language :: Python :: 3.9',\n        'Programming Language :: Python :: 3.10',\n        'Programming Language :: Python :: 3.11',\n        'Programming Language :: Python :: 3.12',\n        'Programming Language :: Python :: 3.13'\n    ],\n\n    # What does your project relate to?\n    keywords=['C/C++', 'package', 'libraries', 'developer', 'manager',\n              'dependency', 'tool', 'c', 'c++', 'cpp'],\n\n    # You can just specify the packages manually here if your project is\n    # simple. Or you can use find_packages().\n    packages=find_packages(exclude=excluded_test_packages + [\"./setup.py\"]),\n\n    # Alternatively, if you want to distribute just a my_module.py, uncomment\n    # this:\n    #   py_modules=[\"my_module\"],\n\n    # List run-time dependencies here.  These will be installed by pip when\n    # your project is installed. For an analysis of \"install_requires\" vs pip's\n    # requirements files see:\n    # https://packaging.python.org/en/latest/requirements.html\n    install_requires=project_requirements,\n\n    # List additional groups of dependencies here (e.g. development\n    # dependencies). You can install these using the following syntax,\n    # for example:\n    # $ pip install -e .[dev,test]\n    extras_require={\n        'dev': dev_requirements,\n        'test': dev_requirements,\n    },\n\n    # If there are data files included in your packages that need to be\n    # installed, specify them here.  If using Python 2.6 or less, then these\n    # have to be included in MANIFEST.in as well.\n    package_data={\n        'conans': ['*.txt'],\n    },\n\n    # Although 'package_data' is the preferred approach, in some case you may\n    # need to place data files outside of your packages. See:\n    # http://docs.python.org/3.4/distutils/setupscript.html#installing-additional-files # noqa\n    # In this case, 'data_file' will be installed into '<sys.prefix>/my_data'\n    # data_files=[('my_data', ['data/data_file'])],\n\n    # To provide executable scripts, use entry points in preference to the\n    # \"scripts\" keyword. Entry points provide cross-platform support and allow\n    # pip to create the appropriate form of executable for the target platform.\n    entry_points={\n        'console_scripts': [\n            'conan_server=conans.conan_server:run'\n        ],\n    },\n)\n"
  },
  {
    "path": "test/.gitignore",
    "content": "conftest_user.py\n"
  },
  {
    "path": "test/README.md",
    "content": "\n# Conan Testing\n\nConan tests fall into three categories:\n\n- **Unit tests** in `test/unittests` folder. These tests should test small pieces of code like\n  functions, methods, or properties. As long as it's possible they should not rely on anything\n  external like the file system or system configuration,  and in case they need to do it should be\n  mocked.\n\n- **Integration tests** in `test/integration` folder. We consider integration tests the ones that\n  only will need pure python to execute, but that may test the interaction between different Conan\n  modules. They could test the result of the execution of one or several Conan commands, but shouldn't\n  depend on any external tools like compilers, build systems, or version-control system\n  tools.\n\n- **Functional tests** in `test/functional` folder. Under this category, we add tests that are\n  testing the complete Conan functionality. They may call external tools (please read the section\n  below to check the tools installed on the CI). These tests should be avoided as long as\n  it's possible as they may take considerable CI time.\n\n## Writing tests\n\nWe use [Pytest](https://docs.pytest.org/en/stable/) as the testing framework. There are some\nimportant things to have in mind regarding test discovery and style.\n\n### Naming files and methods\n\nPytest follows this [convention](https://docs.pytest.org/en/stable/goodpractices.html) for test\ndiscovery:\n- Name your Python test files starting in `test_`.\n\n```\ntest\n├── README.md\n├── conftest.py\n├── unittests\n│   ├── __init__.py\n│   ├── test_mytest.py\n│   ...\n...\n```\n\n- Tests inside those Python files should follow this name convention:\n    - `test` prefixed test functions or methods outside of class.\n    - `test` prefixed test functions or methods inside `Test` prefixed test classes (without an\n      `__init__` method).\n\n```python\nclass TestSomeFunctionality:\n\n    def test_plus_name(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n        ...\n```\n\n### Marking tests\n\nPlease mark your tests if they need to. Besides the [built-in Pytest\nmarkers](https://docs.pytest.org/en/stable/mark.html#mark) we interpret some markers related to\nexternal tools: `cmake`, `gcc`, `clang`, `visual_studio`, `mingw`, `autotools`, `pkg_config`,\n`premake`, `meson`, `file`, `git`, `svn`, `compiler` and `conan`. For example:\n\n```python\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Needs windows for vcvars\")\n@pytest.mark.tool(\"visual_studio\")\ndef test_vcvars_priority(self):\n    client = TestClient()\n    ...\n```\n\nIf the test needs any of those tools to run it should be marked as using that tool and moved to the `test/functional` folder.\nNote that only tests in ``test/functional`` might need the ``@pytest.mark.tool`` annotation. Tests in ``integration`` or ``unittest`` should never require an extra tool.\n\n\n### Parametrizing tests\n\nPlease, if you need to run several combinations of the same testing code use parameterization. You can use the builtin `pytest.mark.parametrize` decorator to enable parametrization of arguments for a test function:\n\n```python\n    @pytest.mark.parametrize(\"use_components\", [False, True])\n    def test_build_modules_alias_target(self, use_components):\n        ...\n```\n\n## Running tests locally\n\nIf you want to run the Coman test suite locally, please check the [README on the front\npage](https://github.com/conan-io/conan#running-the-tests).\n\nRecall it is not expected for contributors to run the full test suite locally, only:\n\n- Run the ``unittest`` and ``integration`` tests. These shouldn't require any external tools\n- If doing modifications to some specific build-system integration, locate the relevant folder under ``functional/toolchains`` and run those tests only.\n\n\nThe reason is that the ``functional`` test suite uses too many different external tools, and installing all of them can be tedious.\nThe Conan CI system will run those tests.\n\n\n## Installation of tools\n\nWork in progress!\n\nNote the ``test/conftest.py`` file contains the upstream configuration of tools.\nThis file should not be changed, but users can create a ``test/conftest_user.py`` file containing their local definitions of tools, that will override the ``conftest.py`` definitions.\n\n### Windows msys2, mingw64 and mingw32\n\nDownload msys2 (64 bit) from msys2.org\nTo install mingw64 and mingw32 open a msys2 terminal and type:\n\n```\n$ pacman -Syuu\n$ pacman -S mingw-w64-x86_64-toolchain\n$ pacman -S mingw-w64-i686-toolchain\n$ pacman -S base-devel gcc\n$ pacman -S autoconf-wrapper\n$ pacman -S automake\n\n```\n"
  },
  {
    "path": "test/__init__.py",
    "content": ""
  },
  {
    "path": "test/conftest.py",
    "content": "import os\nimport pathlib\nimport platform\nimport uuid\nfrom shutil import which\n\nimport pytest\n\nfrom conan.internal.api.detect.detect_vs import vswhere\n\n\"\"\"\nTo override these locations with your own in your dev machine:\n1. Create a conftest_user.py just besides this conftest.py file\n2. This file is .gitignored, it will not be committed\n3. Override the tools_locations, you can completely disabled some tools, tests will be skipped\n4. Empty dicts, without specifying the path, means the tool is already in the system\n   path\n\n\ntools_locations = {\n    'svn': {\"disabled\": True},\n    'cmake': {\n        \"default\": \"3.19\",\n        \"3.15\": {},\n        \"3.16\": {\"disabled\": True},\n        \"3.17\": {\"disabled\": True},\n        \"3.19\": {\"path\": {\"Windows\": \"C:/ws/cmake/cmake-3.19.7-windows-x86_64/bin\"}},\n        # To explicitly skip one tool for one version, define the path as 'skip-tests'\n        # if you don't define the path for one platform it will run the test with the\n        # tool in the path. For example here it will skip the test with CMake in Darwin but\n        # in Linux it will run with the version found in the path if it's not specified\n        \"3.23\": {\"path\": {\"Windows\": \"C:/ws/cmake/cmake-3.19.7-windows-x86_64/bin\",\n                          \"Darwin\": \"skip-tests\"}},\n    },\n    'ninja': {\n        \"1.10.2\": {}\n    },\n    'meson': {\"disabled\": True},\n    'bazel':  {\n        \"system\": {\"path\": {'Windows': 'C:/ws/bazel/4.2.0'}},\n    }\n}\n\"\"\"\n\nMacOS_arm = all([platform.system() == \"Darwin\", platform.machine() == \"arm64\"])\nhomebrew_root = \"/opt/homebrew\" if MacOS_arm else \"/usr/local\"\nwindows_choco_root = \"C:/ProgramData/chocolatey/lib/\"\nmsys2_path = os.getenv(\"MSYS2_PATH\", \"C:/msys64\")\n\ntools_locations = {\n    \"clang\": {\n        \"exe\": \"clang\",\n        \"default\": \"20\",\n        \"20\": {\n            \"path\": {'Windows': 'C:/Program Files/LLVM/bin'}  # by choco\n        }\n    },\n    'visual_studio': {\"default\": \"15\",\n                      \"15\": {},\n                      \"16\": {\"disabled\": True},\n                      \"17\": {}},\n    'pkg_config': {\n        \"exe\": \"pkg-config\",\n        \"default\": \"0.28\",\n        \"0.28\": {\n            \"path\": {\n                # Using chocolatey in Windows -> choco install pkgconfiglite --version 0.28\n                'Windows': f\"{windows_choco_root}/pkgconfiglite/tools/pkg-config-lite-0.28-1/bin\",\n                'Darwin': f\"{homebrew_root}/bin\",\n                'Linux': \"/usr/bin\"\n            }\n        }},\n    'autotools': {\"exe\": \"autoconf\"},\n    'cmake': {\n        \"default\": \"3.15\",\n        \"3.15\": {\n            \"path\": {'Windows': 'C:/tools/cmake/3.15.7/cmake-3.15.7-win64-x64/bin',\n                     'Darwin': '/Users/runner/Applications/CMake/3.15.7/bin',\n                     'Linux': '/usr/share/cmake-3.15.7/bin'}\n        },\n        \"3.19\": {\n            \"path\": {'Windows': 'C:/tools/cmake/3.19.7/cmake-3.19.7-win64-x64/bin',\n                     'Darwin': '/Users/runner/Applications/CMake/3.19.7/bin',\n                     'Linux': '/usr/share/cmake-3.19.7/bin'}\n        },\n        \"3.23\": {\n            \"path\": {'Windows': 'C:/tools/cmake/3.23.5/cmake-3.23.5-windows-x86_64/bin',\n                     'Darwin': '/Users/runner/Applications/CMake/3.23.5/bin',\n                     'Linux': \"/usr/share/cmake-3.23.5/bin\"}\n        },\n        \"3.27\": {\n            \"path\": {'Windows': 'C:/tools/cmake/3.27.9/cmake-3.27.9-windows-x86_64/bin',\n                     'Darwin': '/Users/runner/Applications/CMake/3.27.9/bin',\n                     'Linux': \"/usr/share/cmake-3.27.9/bin\"}\n        },\n        \"4.2\": {\n            \"path\": {'Windows': 'C:/tools/cmake/4.2.1/cmake-4.2.1-windows-x86_64/bin',\n                     'Darwin': '/Users/runner/Applications/CMake/4.2.1/bin',\n                     'Linux': \"/usr/share/cmake-4.2.1/bin\"}\n        }\n    },\n    'ninja': {\n        \"default\": \"1.10.2\",\n        \"1.10.2\": {\n            \"path\": {'Windows': f'{windows_choco_root}/ninja/tools'}\n        }\n    },\n    # This is the non-msys2 mingw, which is 32 bits x86 arch\n    'mingw': {\n        \"disabled\": True,\n        \"platform\": \"Windows\",\n        \"default\": \"system\",\n        \"exe\": \"mingw32-make\",\n        \"system\": {\"path\": {'Windows': \"C:/ProgramData/mingw64/mingw64/bin\"}},\n    },\n    'mingw32': {\n        \"platform\": \"Windows\",\n        \"default\": \"system\",\n        \"exe\": \"mingw32-make\",\n        \"system\": {\"path\": {'Windows': f\"{msys2_path}/mingw32/bin\"}},\n    },\n    'ucrt64': {\n        \"platform\": \"Windows\",\n        \"default\": \"system\",\n        \"exe\": \"mingw32-make\",\n        \"system\": {\"path\": {'Windows': f\"{msys2_path}/ucrt64/bin\"}},\n    },\n    'mingw64': {\n        \"platform\": \"Windows\",\n        \"default\": \"system\",\n        \"exe\": \"mingw32-make\",\n        \"system\": {\"path\": {'Windows': f\"{msys2_path}/mingw64/bin\"}},\n    },\n    'msys2': {\n        \"platform\": \"Windows\",\n        \"default\": \"system\",\n        \"exe\": \"make\",\n        \"system\": {\"path\": {'Windows': f\"{msys2_path}/usr/bin\"}},\n    },\n    'msys2_clang64': {\n        \"platform\": \"Windows\",\n        \"default\": \"system\",\n        \"exe\": \"clang\",\n        \"system\": {\"path\": {'Windows': f\"{msys2_path}/clang64/bin\"}},\n    },\n    'msys2_mingw64_clang64': {\n        \"disabled\": True,\n        \"platform\": \"Windows\",\n        \"default\": \"system\",\n        \"exe\": \"clang\",\n        \"system\": {\"path\": {'Windows': f\"{msys2_path}/mingw64/bin\"}},\n    },\n    'cygwin': {\n        \"platform\": \"Windows\",\n        \"default\": \"system\",\n        \"exe\": \"make\",\n        \"system\": {\"path\": {'Windows': \"C:/tools/cygwin/bin\"}},\n    },\n    'bazel': {\n        \"default\": \"7.x\",\n        \"6.x\": {\"path\": {'Linux': '/usr/share/bazel-6.5.0/bin',\n                         'Windows': 'C:/tools/bazel/6.5.0',\n                         'Darwin': '/Users/runner/Applications/bazel/6.5.0'}},\n        \"7.x\": {\"path\": {'Linux': '/usr/share/bazel-7.6.2/bin',\n                         'Windows': 'C:/tools/bazel/7.6.2',\n                         'Darwin': '/Users/runner/Applications/bazel/7.6.2'}},\n        \"8.x\": {\"path\": {'Linux': '/usr/share/bazel-8.4.2/bin',\n                         'Windows': 'C:/tools/bazel/8.4.2',\n                         'Darwin': '/Users/runner/Applications/bazel/8.4.2'}},\n    },\n    'premake': {\n        \"exe\": \"premake5\",\n        \"default\": \"5.0.0\",\n        \"5.0.0\": {\n            \"path\": {'Linux': '/usr/share/premake',\n                     'Windows': 'skip-tests',\n                     'Darwin': 'skip-tests'}\n        }\n    },\n    'xcodegen': {\"platform\": \"Darwin\"},\n    'apt_get': {\"exe\": \"apt-get\"},\n    'brew': {},\n    'android_ndk': {\n        \"platform\": \"Darwin\",\n        \"exe\": \"ndk-build\",\n        \"default\": \"system\",\n        \"system\": {\n            \"path\": {'Darwin': os.getenv(\"ANDROID_NDK\")}\n            # 'Windows': os.getenv(\"ANDROID_NDK_HOME\"),\n        }\n    },\n    \"qbs\": {\n        \"exe\": \"qbs\",\n        \"default\": \"2.6.0\",\n        \"2.6.0\": {\n            \"path\": {'Linux': '/usr/share/qbs/bin'}\n        }\n    },\n    \"emcc\": {},\n    \"node\": {},\n    # TODO: Intel oneAPI is not installed in CI yet. Uncomment this line whenever it's done.\n    # \"intel_oneapi\": {\n    #     \"default\": \"2021.3\",\n    #     \"exe\": \"dpcpp\",\n    #     \"2021.3\": {\"path\": {\"Linux\": \"/opt/intel/oneapi/compiler/2021.3.0/linux/bin\"}}\n    # }\n}\n\n\n# TODO: Make this match the default tools (compilers) above automatically\n\n\ntry:\n    from test.conftest_user import tools_locations as user_tool_locations\n\n    def update(d, u):\n        for k, v in u.items():\n            if isinstance(v, dict):\n                d[k] = update(d.get(k, {}), v)\n            else:\n                d[k] = v\n        return d\n\n    update(tools_locations, user_tool_locations)\nexcept ImportError as e:\n    user_tool_locations = None\n\n\ntools_environments = {\n    'mingw32': {'Windows': {'MSYSTEM': 'MINGW32'}},\n    'mingw64': {'Windows': {'MSYSTEM': 'MINGW64'}},\n    'ucrt64': {'Windows': {'MSYSTEM': 'UCRT64'}},\n    'msys2_clang64': {\"Windows\": {\"MSYSTEM\": \"CLANG64\"}}\n}\n\n\n_cached_tools = {}\n\n\ndef _get_tool(name, version):\n    # None: not cached yet\n    # False = tool not available, legally skipped\n    # True = tool not available, test error\n    # (path, env) = tool available\n    cached = _cached_tools.setdefault(name, {}).get(version)\n    if cached is not None:\n        return cached\n    result = _get_individual_tool(name, version)\n    _cached_tools[name][version] = result\n    return result\n\n\ndef _get_individual_tool(name, version):\n    tool = tools_locations.get(name, {})\n    if tool.get(\"disabled\"):\n        return False\n\n    tool_platform = platform.system()\n    if tool.get(\"platform\", tool_platform) != tool_platform:\n        return None, None\n\n    version = version or tool.get(\"default\")\n    tool_version = tool.get(version)\n    if tool_version is not None:\n        assert isinstance(tool_version, dict)\n        if tool_version.get(\"disabled\"):\n            return False\n        if name == \"visual_studio\":\n            if vswhere():  # TODO: Missing version detection\n                return None, None\n\n        tool_path = tool_version.get(\"path\", {}).get(tool_platform)\n        tool_path = tool_path.replace(\"/\", \"\\\\\") if tool_platform == \"Windows\" and tool_path is not None else tool_path\n        # To allow to skip for a platform, we can put the path to None\n        # \"cmake\": { \"3.23\": {\n        #               \"path\": {'Windows': 'C:/cmake/cmake-3.23.1-windows-x86_64/bin',\n        #                        'Darwin': '/Users/jenkins/cmake/cmake-3.23.1/bin',\n        #                        'Linux': None}}\n        #          }\n        if tool_path == \"skip-tests\":\n            return False\n        elif tool_path is not None and not os.path.isdir(tool_path):\n            return True\n    else:\n        if version is not None:  # if the version is specified, it should be in the conf\n            return True\n        tool_path = None\n\n    try:\n        tool_env = tools_environments[name][tool_platform]\n    except KeyError:\n        tool_env = None\n\n    cached = tool_path, tool_env\n\n    # Check this particular tool is installed\n    old_environ = None\n    if tool_path is not None:\n        old_environ = dict(os.environ)\n        os.environ[\"PATH\"] = tool_path + os.pathsep + os.environ[\"PATH\"]\n    exe = tool.get(\"exe\", name)\n    exe_found = which(exe)  # TODO: This which doesn't detect version either\n    exe_path = str(pathlib.Path(exe_found).parent) if exe_found else None\n    if not exe_found:\n        cached = True\n        if tool_path is None:\n            # will fail the test, not exe found and path None\n            cached = True\n    elif tool_path is not None and tool_path not in exe_found:\n        # finds the exe in a path that is not the one set in the conf -> fail\n        cached = True\n    elif tool_path is None:\n        cached = exe_path, tool_env\n\n    if old_environ is not None:\n        os.environ.clear()\n        os.environ.update(old_environ)\n\n    return cached\n\n\ndef pytest_configure(config):\n    # register an additional marker\n    config.addinivalue_line(\n        \"markers\", \"tool(name, version): mark test to require a tool by name\"\n    )\n\n\ndef pytest_runtest_teardown(item):\n    if hasattr(item, \"old_environ\"):\n        os.environ.clear()\n        os.environ.update(item.old_environ)\n\n\ndef pytest_runtest_setup(item):\n    tools_paths = []\n    tools_env_vars = dict()\n    for mark in item.iter_markers():\n        if mark.name.startswith(\"tool_\"):\n            raise Exception(\"Invalid decorator @pytest.mark.{}\".format(mark.name))\n\n    kwargs = [mark.kwargs for mark in item.iter_markers(name=\"tool\")]\n    if any(kwargs):\n        raise Exception(\"Invalid decorator @pytest.mark Do not use kwargs: {}\".format(kwargs))\n    tools_params = [mark.args for mark in item.iter_markers(name=\"tool\")]\n    for tool_params in tools_params:\n        if len(tool_params) == 1:\n            tool_name = tool_params[0]\n            tool_version = None\n        elif len(tool_params) == 2:\n            tool_name, tool_version = tool_params\n        else:\n            raise Exception(\"Invalid arguments for mark.tool: {}\".format(tool_params))\n\n        result = _get_tool(tool_name, tool_version)\n        if result is True:\n            version_msg = \"Any\" if tool_version is None else tool_version\n            pytest.fail(\"Required '{}' tool version '{}' is not available\".format(tool_name,\n                                                                                  version_msg))\n        if result is False:\n            version_msg = \"Any\" if tool_version is None else tool_version\n            pytest.skip(\"Required '{}' tool version '{}' is not available\".format(tool_name,\n                                                                                  version_msg))\n\n        tool_path, tool_env = result\n        if tool_path:\n            tools_paths.append(tool_path)\n        if tool_env:\n            tools_env_vars.update(tool_env)\n        # Fix random failures CI because of this: https://issues.jenkins.io/browse/JENKINS-9104\n        if tool_name == \"visual_studio\":\n            tools_env_vars['_MSPDBSRV_ENDPOINT_'] = str(uuid.uuid4())\n\n    if tools_paths or tools_env_vars:\n        item.old_environ = dict(os.environ)\n        tools_env_vars['PATH'] = os.pathsep.join(tools_paths + [os.environ[\"PATH\"]])\n        os.environ.update(tools_env_vars)\n"
  },
  {
    "path": "test/functional/__init__.py",
    "content": ""
  },
  {
    "path": "test/functional/command/__init__.py",
    "content": ""
  },
  {
    "path": "test/functional/command/dockerfiles/Dockerfile",
    "content": "FROM ubuntu:22.04\nRUN apt-get update \\\n    && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \\\n        build-essential \\\n        cmake \\\n        python3 \\\n        python3-pip \\\n        python3-venv \\\n    && rm -rf /var/lib/apt/lists/*\nCOPY . /root/conan-io\nRUN cd /root/conan-io && pip install -e .\n"
  },
  {
    "path": "test/functional/command/dockerfiles/Dockerfile_args",
    "content": "ARG BASE_IMAGE\nFROM $BASE_IMAGE\nRUN apt-get update \\\n    && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \\\n        build-essential \\\n        cmake \\\n        python3 \\\n        python3-pip \\\n        python3-venv \\\n    && rm -rf /var/lib/apt/lists/*\nCOPY . /root/conan-io\nRUN cd /root/conan-io && pip install -e .\n"
  },
  {
    "path": "test/functional/command/dockerfiles/Dockerfile_ninja",
    "content": "FROM ubuntu:22.04\nRUN apt-get update \\\n    && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \\\n        build-essential \\\n        cmake \\\n        ninja-build \\\n        python3 \\\n        python3-pip \\\n        python3-venv \\\n    && rm -rf /var/lib/apt/lists/*\nCOPY . /root/conan-io\nRUN cd /root/conan-io && pip install -e ."
  },
  {
    "path": "test/functional/command/dockerfiles/Dockerfile_profile_detect",
    "content": "FROM ubuntu:22.04\nRUN apt-get update \\\n    && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \\\n        build-essential \\\n        cmake \\\n        python3 \\\n        python3-pip \\\n        python3-venv \\\n    && rm -rf /var/lib/apt/lists/*\nCOPY . /root/conan-io\nRUN cd /root/conan-io && pip install -e .\nRUN conan profile detect"
  },
  {
    "path": "test/functional/command/dockerfiles/Dockerfile_test",
    "content": "FROM ubuntu:22.04\nRUN apt-get update \\\n    && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \\\n        build-essential \\\n        cmake \\\n        python3 \\\n        python3-pip \\\n        python3-venv \\\n    && rm -rf /var/lib/apt/lists/*\nCOPY . /root/conan-io\nRUN cd /root/conan-io && pip install -e ."
  },
  {
    "path": "test/functional/command/export_test.py",
    "content": "import os\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.scm import git_add_changes_commit\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import save\n\n\n@pytest.mark.tool(\"git\")\nclass TestRevisionModeSCM:\n\n    def test_revision_mode_scm(self):\n        t = TestClient()\n        conanfile = str(GenConanfile().with_class_attribute('revision_mode = \"scm\"'))\n        commit = t.init_git_repo({'conanfile.py': conanfile})\n\n        t.run(f\"export . --name=pkg --version=0.1\")\n        assert t.exported_recipe_revision() == commit\n\n        # Now it will fail if dirty\n        t.save({\"conanfile.py\": conanfile + \"\\n#comment\"})\n        t.run(f\"export . --name=pkg --version=0.1\", assert_error=True)\n        assert \"Can't have a dirty repository using revision_mode='scm' and doing\" in t.out\n        # Commit to fix\n        commit2 = git_add_changes_commit(t.current_folder, msg=\"fix\")\n        t.run(f\"export . --name=pkg --version=0.1\")\n        assert t.exported_recipe_revision() == commit2\n\n    def test_revision_mode_scm_subfolder(self):\n        \"\"\" emulates a mono-repo with 2 subprojects, when a change is done in a subproject\n        it gets a different folder commit\n        \"\"\"\n        t = TestClient()\n        conanfile = str(GenConanfile().with_class_attribute('revision_mode = \"scm_folder\"'))\n        commit = t.init_git_repo({'pkga/conanfile.py': conanfile,\n                                  'pkgb/conanfile.py': conanfile})\n\n        t.save({\"pkgb/conanfile.py\": conanfile + \"\\n#comment\"})\n        commit_b = git_add_changes_commit(os.path.join(t.current_folder, \"pkgb\"), msg=\"fix\")\n\n        # pkga still gets the initial commit, as it didn't change its contents\n        t.run(f\"export pkga --name=pkga --version=0.1\")\n        assert t.exported_recipe_revision() == commit\n\n        # but pkgb will get the commit of the new changed folder\n        t.run(f\"export pkgb --name=pkgb --version=0.1\")\n        assert t.exported_recipe_revision() == commit_b\n\n        # if pkgb is dirty, we should still be able to correctly create pkga in 'scm_folder' mode\n        t.save({\"pkgb/conanfile.py\": conanfile + \"\\n#new comment\"})\n        t.run(f\"export pkga --name=pkga --version=0.1\")\n        assert t.exported_recipe_revision() == commit\n\n    def test_auto_revision_without_commits(self):\n        \"\"\"If we have a repo but without commits, it has to fail when the revision_mode=scm\"\"\"\n        t = TestClient()\n        t.run_command('git init .')\n        t.save({\"conanfile.py\": GenConanfile(\"lib\", \"0.1\").with_revision_mode(\"scm\")})\n        t.run(\"export .\", assert_error=True)\n        # It errors, because no commits yet\n        assert \"Cannot detect revision using 'scm' mode from repository\" in t.out\n\n    @pytest.mark.parametrize(\"conf_excluded, recipe_excluded\",\n                             [(\"\", [\"*.cpp\", \"*.txt\", \"src/*\"]),\n                              ([\"*.cpp\", \"*.txt\", \"src/*\"], \"\"),\n                              ('+[\"*.cpp\", \"*.txt\"]', [\"src/*\"]),\n                              ('+[\"*.cpp\"]', [\"*.txt\", \"src/*\"])])\n    def test_revision_mode_scm_excluded_files(self, conf_excluded, recipe_excluded):\n        t = TestClient()\n        recipe_excluded = f'revision_mode_excluded = {recipe_excluded}' if recipe_excluded else \"\"\n        conf_excluded = f'core.scm:excluded={conf_excluded}' if conf_excluded else \"\"\n        save(t.paths.global_conf_path, conf_excluded)\n        conanfile = GenConanfile(\"pkg\", \"0.1\").with_class_attribute('revision_mode = \"scm\"') \\\n                                              .with_class_attribute(recipe_excluded)\n        commit = t.init_git_repo({'conanfile.py': str(conanfile),\n                                  \"test.cpp\": \"mytest\"})\n\n        t.run(f\"export .\")\n        assert t.exported_recipe_revision() == commit\n\n        t.save({\"test.cpp\": \"mytest2\",\n                \"new.txt\": \"new\",\n                \"src/potato\": \"hello\"})\n        t.run(f\"export . -vvv\")\n        assert t.exported_recipe_revision() == commit\n\n        t.save({\"test.py\": \"\"})\n        t.run(f\"export .\", assert_error=True)\n        assert \"ERROR: Can't have a dirty repository using revision_mode='scm'\" in t.out\n"
  },
  {
    "path": "test/functional/command/profile_test.py",
    "content": "import os\nimport platform\nimport textwrap\n\nimport pytest\n\nfrom conan.internal.api.profile.detect import detect_defaults_settings\nfrom conan.test.utils.mocks import RedirectedTestOutput\nfrom conan.test.utils.tools import TestClient, redirect_output\nfrom conan.test.utils.env import environment_update\nfrom conan.internal.util.files import save\nfrom conan.internal.util.runners import detect_runner\nfrom conan.tools.microsoft.visual import vcvars_command\n\n\nclass TestProfile:\n\n    def test_list_empty(self):\n        client = TestClient()\n        client.run(\"profile list\")\n        assert \"Profiles found in the cache:\" in client.out\n\n    def test_list(self):\n        client = TestClient()\n        profiles = [\"default\", \"profile1\", \"profile2\", \"profile3\",\n                    \"nested\" + os.path.sep + \"profile4\",\n                    \"nested\" + os.path.sep + \"two\" + os.path.sep + \"profile5\",\n                    \"nested\" + os.path.sep + \"profile6\"]\n        if platform.system() != \"Windows\":\n            profiles.append(\"symlink_me\" + os.path.sep + \"profile7\")\n        for profile in profiles:\n            save(os.path.join(client.paths.profiles_path, profile), \"\")\n\n        if platform.system() != \"Windows\":\n            os.symlink(os.path.join(client.paths.profiles_path, 'symlink_me'),\n                       os.path.join(client.paths.profiles_path, 'link'))\n            # profile7 will be shown twice because it is symlinked.\n            profiles.append(\"link\" + os.path.sep + \"profile7\")\n\n        # Make sure local folder doesn't interact with profiles\n        os.mkdir(os.path.join(client.current_folder, \"profile3\"))\n        client.run(\"profile list\")\n        for p in profiles:\n            assert p in client.out\n\n        # Test profile list json file\n        # FIXME: Json cannot be captured from tests?\n        # client.run(\"profile list --format=json > profiles_list.json\")\n        # json_content = client.load(\"profiles_list.json\")\n        # json_obj = json.loads(json_content)\n        # self.assertEqual(list, type(json_obj))\n        # self.assertEqual(profiles, json_obj)\n\n    def test_show(self):\n        client = TestClient()\n        profile1 = textwrap.dedent(\"\"\"\n            [settings]\n            os=Windows\n            [options]\n            MyOption=32\n            [conf]\n            tools.build:jobs=20\n            \"\"\")\n        save(os.path.join(client.paths.profiles_path, \"profile1\"), profile1)\n\n        client.run(\"profile show -pr=profile1\")\n        assert \"[settings]\\nos=Windows\" in client.out\n        assert \"MyOption=32\" in client.out\n        # assert \"CC=/path/tomy/gcc_build\", client.out)\n        # assert \"CXX=/path/tomy/g++_build\", client.out)\n        # assert \"package:VAR=value\", client.out)\n        assert \"tools.build:jobs=20\" in client.out\n\n    def test_missing_subarguments(self):\n        client = TestClient()\n        client.run(\"profile\", assert_error=True)\n        assert \"ERROR: Exiting with code: 2\" in client.out\n\n\nclass TestDetectCompilers:\n    def test_detect_default_compilers(self):\n        platform_default_compilers = {\n            \"Linux\": \"gcc\",\n            \"Darwin\": \"apple-clang\",\n            \"Windows\": \"msvc\"\n        }\n\n        result = detect_defaults_settings()\n        # result is a list of tuples (name, value) so converting it to dict\n        result = dict(result)\n        platform_compiler = platform_default_compilers.get(platform.system(), None)\n        if platform_compiler is not None:\n            assert result.get(\"compiler\", None) == platform_compiler\n\n    @pytest.mark.tool(\"gcc\")\n    @pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"only OSX test\")\n    def test_detect_default_in_mac_os_using_gcc_as_default(self):\n        \"\"\"\n        Test if gcc in Mac OS X is using apple-clang as frontend\n        \"\"\"\n        # See: https://github.com/conan-io/conan/issues/2231\n        _, output = detect_runner(\"gcc --version\")\n\n        assert \"clang\" in output, \"Apple gcc doesn't point to clang with gcc frontend anymore!\"\n        # Not test scenario gcc should display clang in output\n        # see: https://stackoverflow.com/questions/19535422/os-x-10-9-gcc-links-to-clang\n\n        output = RedirectedTestOutput()  # Initialize each command\n        with redirect_output(output):\n            with environment_update({\"CC\": \"gcc\"}):\n                result = detect_defaults_settings()\n        # result is a list of tuples (name, value) so converting it to dict\n        result = dict(result)\n        # No compiler should be detected\n        assert result.get(\"compiler\", None) is None\n        assert \"gcc detected as a frontend using apple-clang\" in output\n\n    def test_profile_new(self):\n        c = TestClient()\n        c.run(\"profile detect --name=./MyProfile2\")\n        profile = c.load(\"MyProfile2\")\n        assert \"os=\" in profile\n        assert \"compiler.runtime_type\" not in profile  # Even in Windows\n\n        c.run(\"profile detect --name=./MyProfile2\", assert_error=True)\n        assert \"MyProfile2' already exists\" in c.out\n\n        c.run(\"profile detect --name=./MyProfile2 --force\")  # will not raise error\n        assert \"build_type=Release\" in c.load(\"MyProfile2\")\n        c.save({\"MyProfile2\": \"potato\"})\n        c.run(\"profile detect --name=./MyProfile2 --exist-ok\")  # wont raise, won't overwrite\n        assert \"Profile './MyProfile2' already exists, skipping detection\" in c.out\n        assert c.load(\"MyProfile2\") == \"potato\"\n\n    @pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows and msvc\")\n    def test_profile_new_msvc_vcvars(self):\n        c = TestClient()\n\n        # extract location of cl.exe from vcvars\n        vcvars = vcvars_command(version=\"15\", architecture=\"x64\")\n        ret = c.run_command(f\"{vcvars} && where cl.exe\")\n        assert ret == 0\n        cl_executable = c.out.splitlines()[-1]\n        assert os.path.isfile(cl_executable)\n        cl_location = os.path.dirname(cl_executable)\n\n        # Try different variations, including full path and full path with quotes\n        for var in [\"cl\", \"cl.exe\", cl_executable, f'\"{cl_executable}\"']:\n            output = RedirectedTestOutput()\n            with redirect_output(output):\n                with environment_update({\"CC\": var, \"PATH\": cl_location}):\n                    c.run(\"profile detect --name=./cl-profile --force\")\n\n            profile = c.load(\"cl-profile\")\n            assert \"compiler=msvc\" in profile\n            assert \"compiler.version=191\" in profile\n"
  },
  {
    "path": "test/functional/command/report_test.py",
    "content": "import json\nimport os\nimport textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.fixture\ndef fixture_client():\n    tc = TestClient(light=True, default_server_user=True)\n\n    patch_file = textwrap.dedent(\"\"\"\n        diff --git a/foo.txt b/foo.txt\n        new file mode 100644\n        index 0000000..e311fbb\n        --- /dev/null\n        +++ b/foo.txt\n        @@ -0,0 +1 @@\n        +{version}\n        \"\"\")\n\n    conandata_yml = textwrap.dedent(\"\"\"\n        patches:\n          \"{version}\":\n            - patch_file: \"patches/patch.patch\"\n        \"\"\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import apply_conandata_patches, export_conandata_patches, save\n\n        class TestConan(ConanFile):\n            name = \"pkg\"\n\n            exports = \"{version}.txt\"\n\n            def export_sources(self):\n                export_conandata_patches(self)\n\n            def source(self):\n                save(self, \"myfile.txt\", \"{version}\")\n                if self.version == \"2.0\":\n                    save(self, \"new-file-for-v2.txt\", \"a new file for the new version\")\n                apply_conandata_patches(self)\n        \"\"\")\n\n    tc.save({\n        \"v1/conanfile.py\": conanfile.format(version=\"v1\"),\n        \"v1/conandata.yml\": conandata_yml.format(version=\"1.0\"),\n        \"v1/v1.txt\": \"1.0\",\n        \"v1/patches/patch.patch\": patch_file.format(version=\"1.0\"),\n\n        \"v2/conanfile.py\": conanfile.format(version=\"v2\"),\n        \"v2/conandata.yml\": conandata_yml.format(version=\"2.0\"),\n        \"v2/v2.txt\": \"2.0\",\n        \"v2/patches/patch.patch\": patch_file.format(version=\"2.0\"),\n    })\n\n    tc.run(\"create v1 --version=1.0\")\n    v1_layout = tc.exported_layout()\n    tc.test_v1_path = v1_layout.export()\n\n    tc.run(\"create v2 --version=2.0\")\n    tc.test_v2_revision = tc.exported_layout().reference.revision\n\n    tc.run(\"upload * -r=default -c\")\n    tc.run(\"remove * -c\")\n\n    return tc\n\n\n@pytest.mark.parametrize(\"old_args\", [\n    \"-op=v1 -or=pkg/1.0\",\n    \"-or=pkg/1.0\"\n])\n@pytest.mark.parametrize(\"new_args\", [\n    \"-np=v2 -nr=pkg/2.0\",\n    \"-nr=pkg/2.0#{revision}\",\n])\n@pytest.mark.parametrize(\"formatter\", [\n    \"-f=json --out-file=output.json\",\n    \"-f=html --out-file=output.html\"\n])\n@pytest.mark.tool(\"git\")\ndef test_compare_paths(fixture_client, old_args, new_args, formatter):\n    tc = fixture_client\n    v2_revision = fixture_client.test_v2_revision\n    v1_path = tc.test_v1_path.replace(\"\\\\\", \"/\")\n\n    new_args = new_args.format(revision=v2_revision)\n\n    tc.run(f'report diff {old_args} {new_args} {formatter}')\n\n    if \"json\" in formatter:\n        output_json = json.loads(tc.load(\"output.json\"))\n        assert any(os.path.join(v1_path, \"conanfile.py\").replace(\"\\\\\", \"/\") in k\n                   for k in output_json.keys())\n        assert any(os.path.join(v1_path, \"conanmanifest.txt\").replace(\"\\\\\", \"/\") in k\n                   for k in output_json.keys())\n        # We have patch information\n        assert any(os.path.abspath(os.path.join(v1_path, \"..\", \"es\", \"patches\", \"patch.patch\")).replace(\"\\\\\", \"/\") in k\n                   for k in output_json.keys())\n        # We have exports information\n        assert any(os.path.abspath(os.path.join(v1_path, \"..\", \"e\", \"v1.txt\")).replace(\"\\\\\", \"/\") in k\n                   for k in output_json.keys())\n        # New files\n        assert any(\"new-file-for-v2.txt\" in k for k in output_json.keys())\n\n    elif \"html\" in formatter:\n        output_html = tc.load(\"output.html\")\n        # We have patch information\n        assert \"(old)/es/patches/patch.patch\" in output_html\n        assert \"(new)/s/new-file-for-v2.txt\" in output_html\n        # We have exports information\n        assert \"(old)/e/v1.txt\" in output_html\n"
  },
  {
    "path": "test/functional/command/runner_test.py",
    "content": "import textwrap\nimport os\nimport pytest\nimport docker\nfrom conan.test.utils.tools import TestClient\nfrom conan.test.assets.cmake import gen_cmakelists\nfrom conan.test.assets.sources import gen_function_h, gen_function_cpp\n\n\ndef docker_from_env():\n    try:\n        return docker.from_env()\n    except (Exception,):\n        rancher = f'unix://{os.path.expanduser(\"~\")}/.rd/docker.sock'\n        return docker.DockerClient(base_url=rancher, version='auto')  # Rancher\n\n\ndef docker_skip(test_image='ubuntu:22.04'):\n    try:\n        docker_client = docker_from_env()\n        if test_image:\n            docker_client.images.pull(test_image)\n    except docker.errors.DockerException:\n        return True\n    return False\n\n\ndef conan_base_path():\n    import conans\n    return os.path.dirname(os.path.dirname(conans.__file__))\n\n\ndef dockerfile_path(name=None):\n    path = os.path.join(os.path.dirname(__file__), \"dockerfiles\")\n    if name:\n        path = os.path.join(path, name)\n    return path\n\n\n@pytest.mark.docker_runner\n@pytest.mark.skipif(docker_skip(), reason=\"Only docker running\")\ndef test_create_docker_runner_cache_shared():\n    \"\"\"\n    Tests the ``conan create . ``\n    \"\"\"\n    client = TestClient()\n    profile_build = textwrap.dedent(f\"\"\"\\\n    [settings]\n    arch={{{{ detect_api.detect_arch() }}}}\n    build_type=Release\n    compiler=gcc\n    compiler.cppstd=gnu17\n    compiler.libcxx=libstdc++11\n    compiler.version=11\n    os=Linux\n    \"\"\")\n\n    profile_host = textwrap.dedent(f\"\"\"\\\n    [settings]\n    arch={{{{ detect_api.detect_arch() }}}}\n    build_type=Release\n    compiler=gcc\n    compiler.cppstd=gnu17\n    compiler.libcxx=libstdc++11\n    compiler.version=11\n    os=Linux\n    [runner]\n    type=docker\n    dockerfile={dockerfile_path()}\n    build_context={conan_base_path()}\n    image=conan-runner-default-test\n    cache=shared\n    remove=True\n    \"\"\")\n\n    client.save({\"host\": profile_host, \"build\": profile_build})\n    client.run(\"new cmake_lib -d name=pkg -d version=0.2\")\n    client.run(\"create . -pr:h host -pr:b build\")\n\n    assert \"[100%] Built target example\" in client.out\n    assert \"Removing container\" in client.out\n\n\n@pytest.mark.docker_runner\n@pytest.mark.skipif(docker_skip(), reason=\"Only docker running\")\ndef test_create_docker_runner_cache_shared_profile_from_cache():\n    \"\"\"\n    Tests the ``conan create . ``\n    \"\"\"\n    client = TestClient()\n    profile_build = textwrap.dedent(f\"\"\"\\\n    [settings]\n    arch={{{{ detect_api.detect_arch() }}}}\n    build_type=Release\n    compiler=gcc\n    compiler.cppstd=gnu17\n    compiler.libcxx=libstdc++11\n    compiler.version=11\n    os=Linux\n    \"\"\")\n\n    profile_host = textwrap.dedent(f\"\"\"\\\n    [settings]\n    arch={{{{ detect_api.detect_arch() }}}}\n    build_type=Release\n    compiler=gcc\n    compiler.cppstd=gnu17\n    compiler.libcxx=libstdc++11\n    compiler.version=11\n    os=Linux\n    [runner]\n    type=docker\n    dockerfile={dockerfile_path()}\n    build_context={conan_base_path()}\n    image=conan-runner-default-test\n    cache=shared\n    remove=True\n    \"\"\")\n\n    client.save({\"default_host\": profile_host, \"default_build\": profile_build}, path=client.paths.profiles_path)\n    client.run(\"new cmake_lib -d name=pkg -d version=0.2\")\n    client.run(\"create . -pr:h default_host -pr:b default_build\")\n\n    assert \"[100%] Built target example\" in client.out\n    assert \"Removing container\" in client.out\n\n\n@pytest.mark.docker_runner\n@pytest.mark.skipif(docker_skip(), reason=\"Only docker running\")\ndef test_create_docker_runner_cache_shared_profile_folder():\n    \"\"\"\n    Tests the ``conan create . ``\n    \"\"\"\n    client = TestClient()\n    profile_build = textwrap.dedent(f\"\"\"\\\n    [settings]\n    arch={{{{ detect_api.detect_arch() }}}}\n    build_type=Release\n    compiler=gcc\n    compiler.cppstd=gnu17\n    compiler.libcxx=libstdc++11\n    compiler.version=11\n    os=Linux\n    \"\"\")\n\n    profile_host = textwrap.dedent(f\"\"\"\\\n    [settings]\n    arch={{{{ detect_api.detect_arch() }}}}\n    build_type=Release\n    compiler=gcc\n    compiler.cppstd=gnu17\n    compiler.libcxx=libstdc++11\n    compiler.version=11\n    os=Linux\n    [runner]\n    type=docker\n    dockerfile={dockerfile_path()}\n    build_context={conan_base_path()}\n    image=conan-runner-default-test\n    cache=shared\n    remove=True\n    \"\"\")\n\n    client.save({\"build\": profile_build})\n    client.save_home({\"profiles/docker_default\": profile_host})\n    client.run(\"new cmake_lib -d name=pkg -d version=0.2\")\n    client.run(\"create . -pr:h docker_default -pr:b build\")\n\n    assert \"[100%] Built target example\" in client.out\n    assert \"Removing container\" in client.out\n\n\n@pytest.mark.docker_runner\n@pytest.mark.skipif(docker_skip(), reason=\"Only docker running\")\ndef test_create_docker_runner_dockerfile_folder_path():\n    \"\"\"\n    Tests the ``conan create . ``\n    \"\"\"\n    client = TestClient()\n    profile_build = textwrap.dedent(f\"\"\"\\\n    [settings]\n    arch={{{{ detect_api.detect_arch() }}}}\n    build_type=Release\n    compiler=gcc\n    compiler.cppstd=gnu17\n    compiler.libcxx=libstdc++11\n    compiler.version=11\n    os=Linux\n    \"\"\")\n\n    profile_host_copy = textwrap.dedent(f\"\"\"\\\n    [settings]\n    arch={{{{ detect_api.detect_arch() }}}}\n    build_type=Release\n    compiler=gcc\n    compiler.cppstd=gnu17\n    compiler.libcxx=libstdc++11\n    compiler.version=11\n    os=Linux\n    [runner]\n    type=docker\n    dockerfile={dockerfile_path()}\n    build_context={conan_base_path()}\n    image=conan-runner-default-test\n    cache=copy\n    remove=True\n    \"\"\")\n\n    profile_host_clean = textwrap.dedent(f\"\"\"\\\n    [settings]\n    arch={{{{ detect_api.detect_arch() }}}}\n    build_type=Release\n    compiler=gcc\n    compiler.cppstd=gnu17\n    compiler.libcxx=libstdc++11\n    compiler.version=11\n    os=Linux\n    [runner]\n    type=docker\n    dockerfile={dockerfile_path()}\n    build_context={conan_base_path()}\n    image=conan-runner-default-test\n    cache=clean\n    remove=True\n    \"\"\")\n\n    client.save({\"host_copy\": profile_host_copy, \"host_clean\": profile_host_clean, \"build\": profile_build})\n    client.run(\"new cmake_lib -d name=pkg -d version=0.2\")\n    client.run(\"create . -pr:h host_copy -pr:b build\")\n\n    assert \"Restore: pkg/0.2\" in client.out\n    assert \"Restore: pkg/0.2:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe\" in client.out\n    assert \"Restore: pkg/0.2:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe metadata\" in client.out\n    assert \"Removing container\" in client.out\n\n    client.run(\"create . -pr:h host_clean -pr:b build\")\n\n    assert \"Restore: pkg/0.2\" in client.out\n    assert \"Restore: pkg/0.2:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe\" in client.out\n    assert \"Restore: pkg/0.2:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe metadata\" in client.out\n    assert \"Removing container\" in client.out\n\n\n@pytest.mark.docker_runner\n@pytest.mark.skipif(docker_skip(), reason=\"Only docker running\")\ndef test_create_docker_runner_profile_default_folder():\n    \"\"\"\n    Tests the ``conan create . ``\n    \"\"\"\n    client = TestClient()\n    profile_build = textwrap.dedent(f\"\"\"\\\n    [settings]\n    arch={{{{ detect_api.detect_arch() }}}}\n    build_type=Release\n    compiler=gcc\n    compiler.cppstd=gnu17\n    compiler.libcxx=libstdc++11\n    compiler.version=11\n    os=Linux\n    \"\"\")\n    profile_host = textwrap.dedent(f\"\"\"\\\n    [settings]\n    arch={{{{ detect_api.detect_arch() }}}}\n    build_type=Release\n    compiler=gcc\n    compiler.cppstd=gnu17\n    compiler.libcxx=libstdc++11\n    compiler.version=11\n    os=Linux\n    [runner]\n    type=docker\n    dockerfile={dockerfile_path(\"Dockerfile_test\")}\n    build_context={conan_base_path()}\n    image=conan-runner-default-test\n    cache=copy\n    remove=True\n    \"\"\")\n    client.save_home({\"profiles/host_from_profile\": profile_host,\n                      \"profiles/build_from_profile\": profile_build})\n    client.run(\"new cmake_lib -d name=pkg -d version=0.2\")\n    client.run(\"create . -pr:h host_from_profile -pr:b build_from_profile\")\n\n    assert \"Container conan-runner-docker running\" in client.out\n    assert \"Restore: pkg/0.2\" in client.out\n    assert \"Restore: pkg/0.2:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe\" in client.out\n    assert \"Restore: pkg/0.2:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe metadata\" in client.out\n    assert \"Removing container\" in client.out\n\n\n@pytest.mark.docker_runner\n@pytest.mark.skipif(docker_skip(), reason=\"Only docker running\")\ndef test_create_docker_runner_dockerfile_file_path():\n    \"\"\"\n    Tests the ``conan create . ``\n    \"\"\"\n    client = TestClient()\n    profile_build = textwrap.dedent(f\"\"\"\\\n    [settings]\n    arch={{{{ detect_api.detect_arch() }}}}\n    build_type=Release\n    compiler=gcc\n    compiler.cppstd=gnu17\n    compiler.libcxx=libstdc++11\n    compiler.version=11\n    os=Linux\n    \"\"\")\n    profile_host = textwrap.dedent(f\"\"\"\\\n    [settings]\n    arch={{{{ detect_api.detect_arch() }}}}\n    build_type=Release\n    compiler=gcc\n    compiler.cppstd=gnu17\n    compiler.libcxx=libstdc++11\n    compiler.version=11\n    os=Linux\n    [runner]\n    type=docker\n    dockerfile={dockerfile_path(\"Dockerfile_test\")}\n    build_context={conan_base_path()}\n    image=conan-runner-default-test\n    cache=copy\n    remove=True\n    \"\"\")\n    client.save({\"host\": profile_host, \"build\": profile_build})\n    client.run(\"new cmake_lib -d name=pkg -d version=0.2\")\n    client.run(\"create . -pr:h host -pr:b build\")\n\n    assert \"Container conan-runner-docker running\" in client.out\n    assert \"Restore: pkg/0.2\" in client.out\n    assert \"Restore: pkg/0.2:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe\" in client.out\n    assert \"Restore: pkg/0.2:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe metadata\" in client.out\n    assert \"Removing container\" in client.out\n\n\n@pytest.mark.docker_runner\n@pytest.mark.skipif(docker_skip(), reason=\"Only docker running\")\n@pytest.mark.parametrize(\"build_type,shared\", [(\"Release\", False), (\"Debug\", True)])\ndef test_create_docker_runner_with_ninja(build_type, shared):\n    conanfile = textwrap.dedent(\"\"\"\n    import os\n    from conan import ConanFile\n    from conan.tools.cmake import CMake, CMakeToolchain\n\n    class Library(ConanFile):\n        name = \"hello\"\n        version = \"1.0\"\n        settings = 'os', 'arch', 'compiler', 'build_type'\n        exports_sources = 'hello.h', '*.cpp', 'CMakeLists.txt'\n        options = {'shared': [True, False]}\n        default_options = {'shared': False}\n\n        def generate(self):\n            tc = CMakeToolchain(self, generator=\"Ninja\")\n            tc.generate()\n\n        def build(self):\n            cmake = CMake(self)\n            cmake.configure()\n            cmake.build()\n            self.run(os.sep.join([\".\", \"myapp\"]))\n\n        def package(self):\n            cmake = CMake(self)\n            cmake.install()\n    \"\"\")\n\n    client = TestClient(path_with_spaces=False)\n    client.save({'conanfile.py': conanfile,\n                 \"CMakeLists.txt\": gen_cmakelists(libsources=[\"hello.cpp\"],\n                                                  appsources=[\"main.cpp\"],\n                                                  install=True),\n                 \"hello.h\": gen_function_h(name=\"hello\"),\n                 \"hello.cpp\": gen_function_cpp(name=\"hello\", includes=[\"hello\"]),\n                 \"main.cpp\": gen_function_cpp(name=\"main\", includes=[\"hello\"],\n                                              calls=[\"hello\"])})\n    profile = textwrap.dedent(f\"\"\"\\\n    [settings]\n    arch={{{{ detect_api.detect_arch() }}}}\n    build_type=Release\n    compiler=gcc\n    compiler.cppstd=gnu17\n    compiler.libcxx=libstdc++11\n    compiler.version=11\n    os=Linux\n    [runner]\n    type=docker\n    image=conan-runner-ninja-test\n    dockerfile={dockerfile_path(\"Dockerfile_ninja\")}\n    build_context={conan_base_path()}\n    cache=copy\n    remove=True\n    \"\"\")\n    client.save({\"profile\": profile})\n    settings = \"-s os=Linux -s build_type={} -o hello/*:shared={}\".format(build_type, shared)\n    # create should also work\n    client.run(\"create . --name=hello --version=1.0 {} -pr:h=profile -pr:b=profile\".format(settings))\n    assert 'cmake -G \"Ninja\"' in client.out\n    assert \"main: {}!\".format(build_type) in client.out\n\n\n@pytest.mark.docker_runner\n@pytest.mark.skipif(docker_skip(), reason=\"Only docker running\")\ndef test_create_docker_runner_from_configfile():\n    \"\"\"\n    Tests the ``conan create . ``\n    \"\"\"\n    client = TestClient()\n    configfile = textwrap.dedent(f\"\"\"\n        image: conan-runner-default-test\n        build:\n            dockerfile: {dockerfile_path(\"Dockerfile_test\")}\n            build_context: {conan_base_path()}\n        run:\n            name: my-custom-conan-runner-container\n        \"\"\")\n    client.save({\"configfile.yaml\": configfile})\n\n    profile_build = textwrap.dedent(f\"\"\"\\\n    [settings]\n    arch={{{{ detect_api.detect_arch() }}}}\n    build_type=Release\n    compiler=gcc\n    compiler.cppstd=gnu17\n    compiler.libcxx=libstdc++11\n    compiler.version=11\n    os=Linux\n    \"\"\")\n    profile_host = textwrap.dedent(f\"\"\"\\\n    [settings]\n    arch={{{{ detect_api.detect_arch() }}}}\n    build_type=Release\n    compiler=gcc\n    compiler.cppstd=gnu17\n    compiler.libcxx=libstdc++11\n    compiler.version=11\n    os=Linux\n    [runner]\n    type=docker\n    configfile={os.path.join(client.current_folder, 'configfile.yaml')}\n    cache=copy\n    remove=True\n    \"\"\")\n\n    client.save({\"host\": profile_host, \"build\": profile_build})\n    client.run(\"new cmake_lib -d name=pkg -d version=0.2\")\n    client.run(\"create . -pr:h 'host' -pr:b 'build'\")\n\n    assert \"Container my-custom-conan-runner-container running\" in client.out\n    assert \"Restore: pkg/0.2\" in client.out\n    assert \"Restore: pkg/0.2:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe\" in client.out\n    assert \"Restore: pkg/0.2:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe metadata\" in client.out\n    assert \"Removing container\" in client.out\n\n\n@pytest.mark.docker_runner\n@pytest.mark.skipif(docker_skip(), reason=\"Only docker running\")\ndef test_create_docker_runner_from_configfile_with_args():\n    \"\"\"\n    Tests the ``conan create . ``\n    \"\"\"\n    client = TestClient()\n\n    # Ensure the network exists\n    docker_client = docker_from_env()\n    docker_client.networks.create(\"my-network\")\n\n    configfile = textwrap.dedent(f\"\"\"\n        image: conan-runner-default-test-with-args\n        build:\n            dockerfile: {dockerfile_path(\"Dockerfile_args\")}\n            build_context: {conan_base_path()}\n            build_args:\n                BASE_IMAGE: ubuntu:22.04\n        run:\n            name: my-conan-runner-container-with-args\n            network: my-network\n        \"\"\")\n    client.save({\"configfile.yaml\": configfile})\n\n    profile_build = textwrap.dedent(f\"\"\"\\\n    [settings]\n    arch={{{{ detect_api.detect_arch() }}}}\n    build_type=Release\n    compiler=gcc\n    compiler.cppstd=gnu17\n    compiler.libcxx=libstdc++11\n    compiler.version=11\n    os=Linux\n    \"\"\")\n    profile_host = textwrap.dedent(f\"\"\"\\\n    [settings]\n    arch={{{{ detect_api.detect_arch() }}}}\n    build_type=Release\n    compiler=gcc\n    compiler.cppstd=gnu17\n    compiler.libcxx=libstdc++11\n    compiler.version=11\n    os=Linux\n    [runner]\n    type=docker\n    configfile={os.path.join(client.current_folder, 'configfile.yaml')}\n    cache=copy\n    remove=True\n    \"\"\")\n\n    client.save({\"host\": profile_host, \"build\": profile_build})\n    client.run(\"new cmake_lib -d name=pkg -d version=0.2\")\n    client.run(\"create . -pr:h 'host' -pr:b 'build'\")\n\n    assert \"command/dockerfiles/Dockerfile_args\" in client.out\n    assert \"Restore: pkg/0.2\" in client.out\n    assert \"Restore: pkg/0.2:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe\" in client.out\n    assert \"Restore: pkg/0.2:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe metadata\" in client.out\n    assert \"Removing container\" in client.out\n\n    docker_client.networks.get(\"my-network\").remove()\n\n\n@pytest.mark.docker_runner\n@pytest.mark.skipif(docker_skip(), reason=\"Only docker running\")\ndef test_create_docker_runner_default_build_profile():\n    \"\"\"\n    Tests the ``conan create . ``\n    \"\"\"\n    client = TestClient()\n\n    profile_host = textwrap.dedent(f\"\"\"\\\n    [settings]\n    arch={{{{ detect_api.detect_arch() }}}}\n    build_type=Release\n    compiler=gcc\n    compiler.cppstd=gnu17\n    compiler.libcxx=libstdc++11\n    compiler.version=11\n    os=Linux\n    [runner]\n    type=docker\n    dockerfile={dockerfile_path()}\n    build_context={conan_base_path()}\n    image=conan-runner-default-test\n    cache=clean\n    remove=True\n    \"\"\")\n\n    client.save({\"host_clean\": profile_host})\n    client.run(\"new cmake_lib -d name=pkg -d version=0.2\")\n    client.run(\"create . -pr:h host_clean -vverbose\")\n\n    assert \"Copying default profile\" in client.out\n    assert \"Restore: pkg/0.2\" in client.out\n    assert \"Restore: pkg/0.2:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe\" in client.out\n    assert \"Restore: pkg/0.2:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe metadata\" in client.out\n    assert \"Removing container\" in client.out\n\n\n@pytest.mark.docker_runner\n@pytest.mark.skipif(docker_skip('ubuntu:22.04'), reason=\"Only docker running\")\ndef test_create_docker_runner_profile_composition():\n    \"\"\"\n    Tests the ``conan create . `` with profile composition\n    \"\"\"\n    client = TestClient()\n\n    profile = textwrap.dedent(f\"\"\"\\\n    [settings]\n    arch={{{{ detect_api.detect_arch() }}}}\n    build_type=Release\n    compiler=gcc\n    compiler.cppstd=gnu17\n    compiler.libcxx=libstdc++11\n    compiler.version=11\n    os=Linux\n    [runner]\n    type=docker\n    image=conan-runner-ninja-test\n    \"\"\")\n\n    profile_extension = textwrap.dedent(f\"\"\"\\\n    [runner]\n    type=docker\n    dockerfile={dockerfile_path(\"Dockerfile_ninja\")}\n    build_context={conan_base_path()}\n    cache=copy\n    remove=True\n    \"\"\")\n    client.save({\"profile\": profile, \"profile_extension\": profile_extension})\n    client.run(\"new cmake_lib -d name=pkg -d version=2.0\")\n    client.run(\"create . -pr:h profile -pr:h profile_extension\")\n\n    assert \"[100%] Built target example\" in client.out\n    assert \"Restore: pkg/2.0 in pkgc6abef0178849\" in client.out\n    assert \"Restore: pkg/2.0:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe\" in client.out\n    assert \"Restore: pkg/2.0:8631cf963dbbb4d7a378a64a6fd1dc57558bc2fe metadata\" in client.out\n\n\n@pytest.mark.docker_runner\n@pytest.mark.skipif(docker_skip(), reason=\"Only docker running\")\ndef test_create_docker_runner_in_subfolder():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import load, copy\n        from conan.tools.cmake import CMake\n\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"1.0\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"CMakeToolchain\"\n\n            def layout(self):\n                self.folders.root = \"..\"\n                self.folders.source = \".\"\n                self.folders.build = \"build\"\n\n            def export_sources(self):\n                folder = os.path.join(self.recipe_folder, \"..\")\n                copy(self, \"*.txt\", folder, self.export_sources_folder)\n                copy(self, \"src/*.cpp\", folder, self.export_sources_folder)\n                copy(self, \"include/*.h\", folder, self.export_sources_folder)\n\n            def source(self):\n                cmake_file = load(self, \"CMakeLists.txt\")\n\n            def build(self):\n                path = os.path.join(self.source_folder, \"CMakeLists.txt\")\n                cmake_file = load(self, path)\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n\n            def package(self):\n                cmake = CMake(self)\n                cmake.install()\n            \"\"\")\n\n    header = textwrap.dedent(\"\"\"\n        #pragma once\n        void hello();\n        \"\"\")\n    source = textwrap.dedent(\"\"\"\n        #include <iostream>\n        void hello() {\n            std::cout << \"Hello!\" << std::endl;\n        }\n        \"\"\")\n\n    cmakelist = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.15)\n        project(pkg CXX)\n        add_library(pkg src/hello.cpp)\n        target_include_directories(pkg PUBLIC include)\n        set_target_properties(pkg PROPERTIES PUBLIC_HEADER \"include/hello.h\")\n        install(TARGETS pkg)\n\n        \"\"\")\n\n    profile_host = textwrap.dedent(f\"\"\"\\\n        [settings]\n        arch={{{{ detect_api.detect_arch() }}}}\n        build_type=Release\n        compiler=gcc\n        compiler.cppstd=gnu17\n        compiler.libcxx=libstdc++11\n        compiler.version=11\n        os=Linux\n        [runner]\n        type=docker\n        dockerfile={dockerfile_path()}\n        build_context={conan_base_path()}\n        image=conan-runner-default-test\n        cache=clean\n        remove=True\n        \"\"\")\n\n    client.save({\"conan/conanfile.py\": conanfile,\n                 \"conan/host\": profile_host,\n                 \"include/hello.h\": header,\n                 \"src/hello.cpp\": source,\n                 \"CMakeLists.txt\": cmakelist})\n\n    with client.chdir(\"conan\"):\n        client.run(\"create . -pr:h host -vverbose\")\n\n    assert \"Restore: pkg/1.0\" in client.out\n    assert \"Removing container\" in client.out\n"
  },
  {
    "path": "test/functional/command/test_build.py",
    "content": "import json\nimport os\nimport textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_build_different_folders():\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n\n        class AConan(ConanFile):\n\n            def build(self):\n                self.output.warning(\"Build folder=>%s\" % self.build_folder)\n                self.output.warning(\"Src folder=>%s\" % self.source_folder)\n                assert(os.path.exists(self.build_folder))\n                assert(os.path.exists(self.source_folder))\n    \"\"\")\n\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    with client.chdir(\"build1\"):\n        client.run(\"install ..\")\n    # Try relative to cwd\n    client.run(\"build . --output-folder build2\")\n    assert \"Build folder=>%s\" % os.path.join(client.current_folder, \"build2\") in client.out\n    assert \"Src folder=>%s\" % client.current_folder in client.out\n\n\ndef test_build_dots_names():\n    client = TestClient()\n    conanfile_dep = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class AConan(ConanFile):\n            pass\n    \"\"\")\n    client.save({\"conanfile.py\": conanfile_dep})\n    client.run(\"create . --name=hello.pkg --version=0.1 --user=lasote --channel=testing --format=json\",\n               redirect_stdout=\"hello.pkg.json\")\n    hellopkg_result = json.loads(client.load(\"hello.pkg.json\"))\n    client.run(\"create . --name=hello-tools --version=0.1 --user=lasote --channel=testing --format=json\",\n               redirect_stdout=\"hello-tools.json\")\n    hellotools_result = json.loads(client.load(\"hello-tools.json\"))\n    conanfile_scope_env = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class AConan(ConanFile):\n            requires = \"hello.pkg/0.1@lasote/testing\", \"hello-tools/0.1@lasote/testing\"\n\n            def generate(self):\n                self.output.info(\"HELLO ROOT PATH: %s\" %\n                    self.dependencies[\"hello.pkg\"].package_folder)\n                self.output.info(\"HELLO ROOT PATH: %s\" %\n                    self.dependencies[\"hello-tools\"].package_folder)\n\n            def build(self):\n                pass\n\n    \"\"\")\n    client.save({\"conanfile.py\": conanfile_scope_env}, clean_first=True)\n    client.run(\"build conanfile.py --build=missing\")\n\n    assert hellopkg_result[\"graph\"][\"nodes\"][\"1\"][\"package_folder\"] in client.out\n    assert hellotools_result[\"graph\"][\"nodes\"][\"1\"][\"package_folder\"] in client.out\n\n\ndef test_build_with_deps_env_info():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class AConan(ConanFile):\n            name = \"lib\"\n            version = \"1.0\"\n\n            def package_info(self):\n                self.buildenv_info.define(\"MYVAR\", \"23\")\n\n    \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"export . --user=lasote --channel=stable\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.env import VirtualBuildEnv\n        import os\n\n        class AConan(ConanFile):\n            build_requires = \"lib/1.0@lasote/stable\"\n\n            def build(self):\n                build_env = VirtualBuildEnv(self).vars()\n                assert build_env.get(\"MYVAR\") == \"23\"\n                with build_env.apply():\n                    assert(os.environ[\"MYVAR\"] == \"23\")\n    \"\"\")\n    client.save({\"conanfile.py\": conanfile}, clean_first=True)\n    client.run(\"build . --build missing\")\n\n\ndef test_build_single_full_reference():\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile(\"foo\", \"1.0\")})\n    client.run(\"create . --build='*'\")\n    assert \"foo/1.0: Forced build from source\" in client.out\n\n\ndef test_build_multiple_full_reference():\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile(\"foo\", \"1.0\")})\n    client.run(\"create .\")\n    client.save({\"conanfile.py\": GenConanfile(\"bar\", \"1.0\").with_requires(\"foo/1.0\")})\n    client.run(\"create --build foo/1.0@ --build bar/1.0@ .\")\n    assert \"foo/1.0: Forced build from source\" in client.out\n    assert \"bar/1.0: Forced build from source\" in client.out\n\n\ndef test_debug_build_release_deps():\n    # https://github.com/conan-io/conan/issues/2899\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Conan(ConanFile):\n            name = \"{name}\"\n            {requires}\n            settings = \"build_type\"\n            def build(self):\n                self.output.info(\"BUILD: %s BuildType=%s!\"\n                                 % (self.name, self.settings.build_type))\n            def package_info(self):\n                self.output.info(\"PACKAGE_INFO: %s BuildType=%s!\"\n                                 % (self.name, self.settings.build_type))\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile.format(name=\"dep\", requires=\"\")})\n    client.run(\"create . --name=dep --version=0.1 --user=user --channel=testing -s build_type=Release\")\n    client.save({\"conanfile.py\": conanfile.format(name=\"mypkg\", requires=\"requires = 'dep/0.1@user/testing'\")})\n    client.run(\"build . -s mypkg/*:build_type=Debug -s build_type=Release\")\n    assert \"dep/0.1@user/testing: PACKAGE_INFO: dep BuildType=Release!\" in client.out\n    assert \"conanfile.py (mypkg/None): BUILD: mypkg BuildType=Debug!\" in client.out\n\n"
  },
  {
    "path": "test/functional/command/test_config_install.py",
    "content": "import os\nimport shutil\nimport stat\nimport textwrap\n\nimport pytest\nfrom unittest.mock import patch\n\nfrom conan.api.model import Remote\nfrom conan.internal.api.config.config_installer import _hide_password\nfrom conan.internal.rest.file_downloader import FileDownloader\nfrom conan.internal.paths import DEFAULT_CONAN_HOME\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.file_server import TestFileServer\nfrom conan.test.utils.test_files import scan_folder, temp_folder, tgz_with_contents\nfrom conan.test.utils.tools import TestClient, zipdir\nfrom conan.internal.util.files import load, mkdir, save, save_files\n\n\ndef make_file_read_only(file_path):\n    mode = os.stat(file_path).st_mode\n    os.chmod(file_path, mode & ~ stat.S_IWRITE)\n\n\nremotes = \"\"\"{\n \"remotes\": [\n  {\n   \"name\": \"myrepo1\",\n   \"url\": \"https://myrepourl.net\",\n   \"verify_ssl\": false\n  },\n  {\n   \"name\": \"my-repo-2\",\n   \"url\": \"https://myrepo2.com\",\n   \"verify_ssl\": true\n  }\n ]\n}\n\"\"\"\n\nsettings_yml = \"\"\"os:\n    Windows:\n    Linux:\narch: [x86, x86_64]\n\"\"\"\n\n\nclass TestConfigInstall:\n\n    @staticmethod\n    def _create_profile_folder(folder=None):\n        folder = folder or temp_folder(path_with_spaces=False)\n        save_files(folder, {\"settings.yml\": settings_yml,\n                            \"remotes.json\": remotes,\n                            \"profiles/linux\": \"#linuxprofile\",\n                            \"profiles/windows\": \"#winprofile\",\n                            \"hooks/dummy\": \"#hook dummy\",\n                            \"hooks/foo.py\": \"#hook foo\",\n                            \"hooks/custom/custom.py\": \"#hook custom\",\n                            \".git/hooks/foo\": \"foo\",\n                            \"hooks/.git/hooks/before_push\": \"before_push\",\n                            \"pylintrc\": \"#Custom pylint\",\n                            \"python/myfuncs.py\": \"does not matter\",\n                            \"python/__init__.py\": \"\"\n                            })\n        return folder\n\n    def test_config_fails_no_storage(self):\n        folder = temp_folder(path_with_spaces=False)\n        save_files(folder, {\"remotes.json\": remotes})\n        client = TestClient()\n        client.save({\"conanfile.py\": GenConanfile()})\n        client.run(\"create . --name=pkg --version=1.0\")\n        client.run('config install \"%s\"' % folder)\n        client.run(\"remote list\")\n        assert \"myrepo1: https://myrepourl.net [Verify SSL: False, Enabled: True]\" in client.out\n        assert \"my-repo-2: https://myrepo2.com [Verify SSL: True, Enabled: True]\" in client.out\n\n    def _create_zip(self, zippath=None):\n        folder = self._create_profile_folder()\n        zippath = zippath or os.path.join(folder, \"myconfig.zip\")\n        zipdir(folder, zippath)\n        return zippath\n\n    @staticmethod\n    def _get_files(folder):\n        relpaths = scan_folder(folder)\n        files = {}\n        for path in relpaths:\n            with open(os.path.join(folder, path), \"r\") as file_handle:\n                files[path] = file_handle.read()\n        return files\n\n    def _create_tgz(self, tgz_path=None):\n        folder = self._create_profile_folder()\n        tgz_path = tgz_path or os.path.join(folder, \"myconfig.tar.gz\")\n        files = self._get_files(folder)\n        return tgz_with_contents(files, tgz_path)\n\n    @staticmethod\n    def _check(c):\n        settings_path = c.paths.settings_path\n        assert load(settings_path).splitlines() == settings_yml.splitlines()\n        api = c.api\n        cache_remotes = api.remotes.list()\n        assert list(cache_remotes) == [\n            Remote(\"myrepo1\", \"https://myrepourl.net\", False, False),\n            Remote(\"my-repo-2\", \"https://myrepo2.com\", True, False),\n        ]\n        assert sorted(os.listdir(c.paths.profiles_path)) == sorted([\"default\", \"linux\", \"windows\"])\n        assert c.load_home(\"profiles/linux\") == \"#linuxprofile\"\n        assert c.load_home(\"profiles/windows\") == \"#winprofile\"\n        assert \"#Custom pylint\" == c.load_home(\"pylintrc\")\n        assert \"\" == c.load_home(\"python/__init__.py\")\n        assert \"#hook dummy\" == c.load_home(\"hooks/dummy\")\n        assert \"#hook foo\" == c.load_home(\"hooks/foo.py\")\n        assert \"#hook custom\" == c.load_home(\"hooks/custom/custom.py\")\n        assert not os.path.exists(os.path.join(c.cache_folder, \"hooks\", \".git\"))\n        assert not os.path.exists(os.path.join(c.cache_folder, \".git\"))\n\n    def test_install_file(self):\n        \"\"\" should install from a file in current dir\n        \"\"\"\n        zippath = self._create_zip()\n        c = TestClient(light=True)\n        for filetype in [\"\", \"--type=file\"]:\n            c.run('config install \"%s\" %s' % (zippath, filetype))\n            self._check(c)\n            assert os.path.exists(zippath)\n\n    def test_install_config_file(self):\n        \"\"\" should install from a settings and remotes file in configuration directory\n        \"\"\"\n        import tempfile\n        profile_folder = self._create_profile_folder()\n        assert os.path.isdir(profile_folder)\n        src_setting_file = os.path.join(profile_folder, \"settings.yml\")\n        src_remote_file = os.path.join(profile_folder, \"remotes.json\")\n\n        # Install profile_folder without settings.yml remotes.json in order to install them manually\n        tmp_dir = tempfile.mkdtemp()\n        dest_setting_file = os.path.join(tmp_dir, \"settings.yml\")\n        dest_remote_file = os.path.join(tmp_dir, \"remotes.json\")\n        shutil.move(src_setting_file, dest_setting_file)\n        shutil.move(src_remote_file, dest_remote_file)\n\n        c = TestClient(light=True)\n        c.run('config install \"%s\"' % profile_folder)\n        shutil.move(dest_setting_file, src_setting_file)\n        shutil.move(dest_remote_file, src_remote_file)\n        shutil.rmtree(tmp_dir)\n\n        for cmd_option in [\"\", \"--type=file\"]:\n            c.run('config install \"%s\" %s' % (src_setting_file, cmd_option))\n            c.run('config install \"%s\" %s' % (src_remote_file, cmd_option))\n            self._check(c)\n\n    def test_install_dir(self):\n        \"\"\" should install from a dir in current dir\n        \"\"\"\n        folder = self._create_profile_folder()\n        assert os.path.isdir(folder)\n        c = TestClient(light=True)\n        for dirtype in [\"\", \"--type=dir\"]:\n            c.run('config install \"%s\" %s' % (folder, dirtype))\n            self._check(c)\n\n    def test_install_source_target_folders(self):\n        folder = temp_folder()\n        save_files(folder, {\"subf/file.txt\": \"hello\",\n                            \"subf/subf/file2.txt\": \"bye\"})\n        c = TestClient(light=True)\n        c.run('config install \"%s\" -sf=subf -tf=newsubf' % folder)\n        content = c.load_home(\"newsubf/file.txt\")\n        assert content == \"hello\"\n        content = c.load_home(\"newsubf/subf/file2.txt\")\n        assert content == \"bye\"\n\n    def test_install_remotes_json(self):\n        folder = temp_folder()\n\n        remotes_json = textwrap.dedent(\"\"\"\n            {\n                \"remotes\": [\n                    { \"name\": \"repojson1\", \"url\": \"https://repojson1.net\", \"verify_ssl\": false },\n                    { \"name\": \"repojson2\", \"url\": \"https://repojson2.com\", \"verify_ssl\": true }\n                ]\n            }\n        \"\"\")\n\n        remotes_txt = textwrap.dedent(\"\"\"\\\n            repotxt1 https://repotxt1.net False\n            repotxt2 https://repotxt2.com True\n        \"\"\")\n\n        # remotes.txt is ignored\n        save_files(folder, {\"remotes.json\": remotes_json,\n                            \"remotes.txt\": remotes_txt})\n\n        c = TestClient(light=True)\n        c.run(f'config install \"{folder}\"')\n        assert \"Defining remotes from remotes.json\" in c.out\n\n        c.run('remote list')\n\n        assert \"repojson1: https://repojson1.net [Verify SSL: False, Enabled: True]\" in c.out\n        assert \"repojson2: https://repojson2.com [Verify SSL: True, Enabled: True]\" in c.out\n\n        # We only install remotes.json\n        folder = temp_folder()\n        save_files(folder, {\"remotes.json\": remotes_json})\n\n        c.run(f'config install \"{folder}\"')\n        assert \"Defining remotes from remotes.json\" in c.out\n\n        c.run('remote list')\n\n        assert \"repojson1: https://repojson1.net [Verify SSL: False, Enabled: True]\" in c.out\n        assert \"repojson2: https://repojson2.com [Verify SSL: True, Enabled: True]\" in c.out\n\n    def test_without_profile_folder(self):\n        c = TestClient(light=True)\n        shutil.rmtree(c.paths.profiles_path)\n        zippath = self._create_zip()\n\n        c.run('config install \"%s\"' % zippath)\n        assert sorted(os.listdir(c.paths.profiles_path)) == sorted([\"linux\", \"windows\"])\n        assert c.load_home(\"profiles/linux\") == \"#linuxprofile\"\n\n    def test_install_url(self):\n        \"\"\" should install from a URL\n        \"\"\"\n        c = TestClient(light=True)\n        for origin in [\"\", \"--type=url\"]:\n            def my_download(obj, url, file_path, **kwargs):  # noqa\n                self._create_zip(file_path)\n\n            with patch.object(FileDownloader, 'download', new=my_download):\n                c.run(\"config install http://myfakeurl.com/myconf.zip %s\" % origin)\n                self._check(c)\n\n                # repeat the process to check\n                c.run(\"config install http://myfakeurl.com/myconf.zip %s\" % origin)\n                self._check(c)\n\n    def test_install_url_query(self):\n        \"\"\" should install from a URL\n        \"\"\"\n        c = TestClient(light=True)\n\n        def my_download(obj, url, file_path, **kwargs):  # noqa\n            self._create_zip(file_path)\n\n        with patch.object(FileDownloader, 'download', new=my_download):\n            # repeat the process to check it works with ?args\n            c.run(\"config install http://myfakeurl.com/myconf.zip?sha=1\")\n            self._check(c)\n\n    def test_install_change_only_verify_ssl(self):\n        def my_download(obj, url, file_path, **kwargs):  # noqa\n            self._create_zip(file_path)\n\n        c = TestClient(light=True)\n        with patch.object(FileDownloader, 'download', new=my_download):\n            c.run(\"config install http://myfakeurl.com/myconf.zip\")\n            self._check(c)\n\n            # repeat the process to check\n            c.run(\"config install http://myfakeurl.com/myconf.zip --verify-ssl=False\")\n            self._check(c)\n\n    def test_install_url_tgz(self):\n        \"\"\" should install from a URL to tar.gz\n        \"\"\"\n        c = TestClient(light=True)\n\n        def my_download(obj, url, file_path, **kwargs):  # noqa\n            self._create_tgz(file_path)\n\n        with patch.object(FileDownloader, 'download', new=my_download):\n            c.run(\"config install http://myfakeurl.com/myconf.tar.gz\")\n            self._check(c)\n\n    def test_failed_install_repo(self):\n        \"\"\" should install from a git repo\n        \"\"\"\n        c = TestClient(light=True)\n        c.run('config install notexistingrepo.git', assert_error=True)\n        assert \"ERROR: Failed conan config install: Can't clone repo\" in c.out\n\n    def test_failed_install_http(self):\n        \"\"\" should install from a http zip\n        \"\"\"\n        c = TestClient(light=True)\n        c.run('config install httpnonexisting', assert_error=True)\n        assert (\"ERROR: Failed conan config install: \"\n                \"Error while installing config from httpnonexisting\") in c.out\n\n    @pytest.mark.tool(\"git\")\n    def test_install_repo(self):\n        \"\"\" should install from a git repo\n        \"\"\"\n        c = TestClient(light=True)\n        folder = self._create_profile_folder()\n        with c.chdir(folder):\n            c.run_command('git init .')\n            c.run_command('git add .')\n            c.run_command('git config user.name myname')\n            c.run_command('git config user.email myname@mycompany.com')\n            c.run_command('git commit -m \"mymsg\"')\n\n        c.run('config install \"%s/.git\"' % folder)\n        self._check(c)\n\n    @pytest.mark.tool(\"git\")\n    def test_install_repo_relative(self):\n        c = TestClient(light=True)\n        relative_folder = \"./config\"\n        absolute_folder = os.path.join(c.current_folder, \"config\")\n        mkdir(absolute_folder)\n        folder = self._create_profile_folder(absolute_folder)\n        with c.chdir(folder):\n            c.run_command('git init .')\n            c.run_command('git add .')\n            c.run_command('git config user.name myname')\n            c.run_command('git config user.email myname@mycompany.com')\n            c.run_command('git commit -m \"mymsg\"')\n\n        c.run('config install \"%s/.git\"' % relative_folder)\n        self._check(c)\n\n    @pytest.mark.tool(\"git\")\n    def test_install_custom_args(self):\n        \"\"\" should install from a git repo\n        \"\"\"\n        c = TestClient(light=True)\n        folder = self._create_profile_folder()\n        with c.chdir(folder):\n            c.run_command('git init .')\n            c.run_command('git add .')\n            c.run_command('git config user.name myname')\n            c.run_command('git config user.email myname@mycompany.com')\n            c.run_command('git commit -m \"mymsg\"')\n\n        c.run('config install \"%s/.git\" --args=\"-c init.templateDir=value\"' % folder)\n        self._check(c)\n\n    def test_force_git_type(self):\n        client = TestClient(light=True)\n        client.run('config install httpnonexisting --type=git', assert_error=True)\n        assert \"Can't clone repo\" in client.out\n\n    def test_force_dir_type(self):\n        c = TestClient(light=True)\n        c.run('config install httpnonexisting --type=dir', assert_error=True)\n        assert \"ERROR: Failed conan config install: No such directory: 'httpnonexisting'\" in c.out\n\n    def test_force_file_type(self):\n        client = TestClient(light=True)\n        client.run('config install httpnonexisting --type=file', assert_error=True)\n        assert \"No such file or directory: 'httpnonexisting'\" in client.out\n\n    def test_force_url_type(self):\n        client = TestClient(light=True)\n        client.run('config install httpnonexisting --type=url', assert_error=True)\n        assert \"Error downloading file httpnonexisting: 'Invalid URL 'httpnonexisting'\" in client.out\n\n    def test_removed_credentials_from_url_unit(self):\n        \"\"\"\n        Unit tests to remove credentials in netloc from url when using basic auth\n        # https://github.com/conan-io/conan/issues/2324\n        \"\"\"\n        url_without_credentials = r\"https://server.com/resource.zip\"\n        url_with_credentials = r\"https://test_username:test_password_123@server.com/resource.zip\"\n        url_hidden_password = r\"https://test_username:<hidden>@server.com/resource.zip\"\n\n        # Check url is the same when not using credentials\n        assert _hide_password(url_without_credentials) == url_without_credentials\n\n        # Check password is hidden using url with credentials\n        assert _hide_password(url_with_credentials) == url_hidden_password\n\n        # Check that it works with other protocols ftp\n        ftp_with_credentials = r\"ftp://test_username_ftp:test_password_321@server.com/resurce.zip\"\n        ftp_hidden_password = r\"ftp://test_username_ftp:<hidden>@server.com/resurce.zip\"\n        assert _hide_password(ftp_with_credentials) == ftp_hidden_password\n\n        # Check function also works for file paths *unix/windows\n        unix_file_path = r\"/tmp/test\"\n        assert _hide_password(unix_file_path) == unix_file_path\n        windows_file_path = r\"c:\\windows\\test\"\n        assert _hide_password(windows_file_path) == windows_file_path\n\n        # Check works with empty string\n        assert _hide_password('') == ''\n\n    def test_remove_credentials_config_installer(self):\n        \"\"\" Functional test to check credentials are not displayed in output but are still present\n        in conan configuration\n        # https://github.com/conan-io/conan/issues/2324\n        \"\"\"\n        fake_url_with_credentials = \"http://test_user:test_password@myfakeurl.com/myconf.zip\"\n        fake_url_hidden_password = \"http://test_user:<hidden>@myfakeurl.com/myconf.zip\"\n\n        def my_download(obj, url, file_path, **kwargs):  # noqa\n            assert url == fake_url_with_credentials\n            self._create_zip(file_path)\n\n        c = TestClient(light=True)\n        with patch.object(FileDownloader, 'download', new=my_download):\n            c.run(\"config install %s\" % fake_url_with_credentials)\n\n            # Check credentials are not displayed in output\n            assert fake_url_with_credentials not in c.out\n            assert fake_url_hidden_password in c.out\n\n            # Check credentials still stored in configuration\n            self._check(c)\n\n    def test_ssl_verify(self):\n        c = TestClient(light=True)\n\n        fake_url = \"https://fakeurl.com/myconf.zip\"\n\n        def download_verify_false(obj, url, file_path, **kwargs):  # noqa\n            assert kwargs[\"verify_ssl\"] is False\n            self._create_zip(file_path)\n\n        def download_verify_true(obj, url, file_path, **kwargs):  # noqa\n            assert kwargs[\"verify_ssl\"] is True\n            self._create_zip(file_path)\n\n        with patch.object(FileDownloader, 'download', new=download_verify_false):\n            c.run(\"config install %s --verify-ssl=False\" % fake_url)\n\n        with patch.object(FileDownloader, 'download', new=download_verify_true):\n            c.run(\"config install %s --verify-ssl=True\" % fake_url)\n\n        with patch.object(FileDownloader, 'download', new=download_verify_true):\n            c.run(f\"config install {fake_url}\")\n\n        with patch.object(FileDownloader, 'download', new=download_verify_false):\n            c.run(f\"config install {fake_url} --insecure\")\n\n    @pytest.mark.tool(\"git\")\n    def test_git_checkout_is_possible(self):\n        folder = self._create_profile_folder()\n        c = TestClient(light=True)\n        with c.chdir(folder):\n            c.run_command('git init .')\n            c.run_command('git checkout -b master')\n            c.run_command('git add .')\n            c.run_command('git config user.name myname')\n            c.run_command('git config user.email myname@mycompany.com')\n            c.run_command('git commit -m \"mymsg\"')\n            c.run_command('git checkout -b other_branch')\n            save(os.path.join(folder, \"extensions\", \"hooks\", \"cust\", \"cust.py\"), \"\")\n            c.run_command('git add .')\n            c.run_command('git commit -m \"my file\"')\n\n        c.run('config install \"%s/.git\" --args \"-b other_branch\"' % folder)\n        self._check(c)\n        file_path = os.path.join(c.paths.hooks_path, \"cust\", \"cust.py\")\n        assert load(file_path) == \"\"\n\n        # Add changes to that branch and update\n        with c.chdir(folder):\n            save(os.path.join(folder, \"extensions\", \"hooks\", \"cust\", \"cust.py\"), \"new content\")\n            c.run_command('git add .')\n            c.run_command('git commit -m \"my other file\"')\n            c.run_command('git checkout master')\n        c.run('config install \"%s/.git\" --args \"-b other_branch\"' % folder)\n        self._check(c)\n        assert load(file_path) == \"new content\"\n\n    def test_config_install_requester(self):\n        # https://github.com/conan-io/conan/issues/4169\n        path = self._create_zip()\n        c = TestClient(light=True)\n        file_server = TestFileServer(os.path.dirname(path))\n        c.servers[\"file_server\"] = file_server\n\n        c.run(f\"config install {file_server.fake_url}/myconfig.zip\")\n        assert \"Defining remotes from remotes.json\" in c.out\n        assert \"Copying file myfuncs.py\" in c.out\n\n    def test_overwrite_read_only_file(self):\n        c = TestClient(light=True)\n        source_folder = self._create_profile_folder()\n        c.run('config install \"%s\"' % source_folder)\n        # make existing settings.yml read-only\n        make_file_read_only(c.paths.settings_path)\n        assert not os.access(c.paths.settings_path, os.W_OK)\n\n        # config install should overwrite the existing read-only file\n        c.run('config install \"%s\"' % source_folder)\n        assert os.access(c.paths.settings_path, os.W_OK)\n\n    def test_dont_copy_file_permissions(self):\n        source_folder = self._create_profile_folder()\n        # make source settings.yml read-only\n        make_file_read_only(os.path.join(source_folder, 'remotes.json'))\n\n        c = TestClient(light=True)\n        c.run('config install \"%s\"' % source_folder)\n        assert os.access(c.paths.settings_path, os.W_OK)\n\n\nclass TestConfigInstallSched:\n\n    def test_execute_more_than_once(self):\n        \"\"\" Once executed by the scheduler, conan config install must executed again\n            when invoked manually\n        \"\"\"\n        folder = temp_folder(path_with_spaces=False)\n        save_files(folder, {\"global.conf\": \"core.download:parallel=0\"})\n        c = TestClient(light=True)\n        c.run('config install \"%s\"' % folder)\n        assert \"Copying file global.conf\" in c.out\n\n        c.run('config install \"%s\"' % folder)\n        assert \"Copying file global.conf\" in c.out\n\n    @pytest.mark.tool(\"git\")\n    def test_config_install_remove_git_repo(self):\n        \"\"\" config_install_interval must break when remote git has been removed\n        \"\"\"\n        folder = temp_folder(path_with_spaces=False)\n        save_files(folder, {\"global.conf\": \"core.download:parallel=0\"})\n        c = TestClient(light=True)\n        with c.chdir(folder):\n            c.run_command('git init .')\n            c.run_command('git add .')\n            c.run_command('git config user.name myname')\n            c.run_command('git config user.email myname@mycompany.com')\n            c.run_command('git commit -m \"mymsg\"')\n        c.run('config install \"%s/.git\" --type git' % folder)\n        assert \"Copying file global.conf\" in c.out\n        assert \"Repo cloned!\" in c.out  # git clone executed by scheduled task\n\n    def test_config_fails_git_folder(self):\n        # https://github.com/conan-io/conan/issues/8594\n        config_folder = temp_folder(path_with_spaces=False)\n        save_files(config_folder, {\"global.conf\": \"core.download:parallel=0\"})\n        folder = os.path.join(temp_folder(), \".gitlab-conan\", DEFAULT_CONAN_HOME)\n        client = TestClient(cache_folder=folder)\n        with client.chdir(config_folder):\n            client.run_command('git init .')\n            client.run_command('git add .')\n            client.run_command('git config user.name myname')\n            client.run_command('git config user.email myname@mycompany.com')\n            client.run_command('git commit -m \"mymsg\"')\n        assert \".gitlab-conan\" in client.cache_folder\n        assert os.path.basename(client.cache_folder) == DEFAULT_CONAN_HOME\n        client.run('config install \"%s/.git\" --type git' % config_folder)\n        client.load_home(\"global.conf\")  # check it is there\n        dirs = os.listdir(client.cache_folder)\n        assert \".git\" not in dirs\n\n\nclass TestConfigInstall2:\n    def test_config_install_reestructuring_source(self):\n        \"\"\"  https://github.com/conan-io/conan/issues/9885 \"\"\"\n\n        folder = temp_folder()\n        client = TestClient()\n        with client.chdir(folder):\n            client.save({\"profiles/debug/address-sanitizer\": \"\"})\n            client.run(\"config install .\")\n\n        debug_cache_folder = os.path.join(client.cache_folder, \"profiles\", \"debug\")\n        assert os.path.isdir(debug_cache_folder)\n\n        # Now reestructure the files, what it was already a directory in the cache now we want\n        # it to be a file\n        folder = temp_folder()\n        with client.chdir(folder):\n            client.save({\"profiles/debug\": \"\"})\n            client.run(\"config install .\")\n        assert os.path.isfile(debug_cache_folder)\n\n        # And now is a directory again\n        folder = temp_folder()\n        with client.chdir(folder):\n            client.save({\"profiles/debug/address-sanitizer\": \"\"})\n            client.run(\"config install .\")\n        assert os.path.isdir(debug_cache_folder)\n"
  },
  {
    "path": "test/functional/command/test_config_install_pkg.py",
    "content": "import json\nimport os\nimport textwrap\n\nimport pytest\nimport yaml\n\nfrom conan.api.model import RecipeReference\nfrom conan.internal.cache.home_paths import HomePaths\nfrom conan.internal.util.files import load\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.fixture(scope=\"module\")\ndef servers():\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import copy\n        class Conf(ConanFile):\n            package_type = \"configuration\"\n            def package(self):\n                copy(self, \"*.conf\", src=self.build_folder, dst=self.package_folder)\n        \"\"\")\n    c = TestClient(default_server_user=True, light=True)\n    c.save({\"conanfile.py\": conanfile})\n    for pkg in (\"myconf_a\", \"myconf_b\", \"myconf_c\"):\n        for version in (\"0.1\", \"0.2\"):\n            c.save({\"global.conf\": f\"user.myteam:myconf=my_{pkg}/{version}_value\"})\n            c.run(f\"export-pkg . --name={pkg} --version={version}\")\n    c.run(\"upload * -r=default -c\")\n    c.run(\"remove * -c\")\n    return c.servers\n\n\ndef _check_conf(c, pkg):\n    c.run(\"config show *\")\n    assert f\"user.myteam:myconf: my_{pkg}_value\" in c.out\n\n\ndef _check_conf_file(c, refs):\n    content = json.loads(c.load_home(\"config_version.json\"))[\"config_version\"]\n    for a, b in zip(refs, content):\n        assert a in b\n\n\nclass TestConfigInstallPkg:\n\n    def test_install_pkg(self, servers):\n        c = TestClient(servers=servers, light=True)\n        c.run(\"config install-pkg myconf_a/0.1\")\n        assert \"Installing new or updating configuration packages\" in c.out\n        _check_conf(c, \"myconf_a/0.1\")\n        _check_conf_file(c, [\"myconf_a/0.1\"])\n        cache_files = os.listdir(c.cache_folder)\n        assert \"conaninfo.txt\" not in cache_files\n        assert \"conanmanifest.txt\" not in cache_files\n\n        # skip reinstall\n        c.run(\"config install-pkg myconf_a/0.1\")\n        assert (\"The requested configurations are identical to the already installed ones, \"\n                \"skipping re-installation\") in c.out\n        _check_conf(c, \"myconf_a/0.1\")\n        _check_conf_file(c, [\"myconf_a/0.1\"])\n\n        # forced reinstall\n        c.save_home({\"global.conf\": \"\"})\n        c.run(\"config install-pkg myconf_a/0.1 --force\")\n        assert \"forcing re-installation because --force\" in c.out\n        _check_conf(c, \"myconf_a/0.1\")\n        _check_conf_file(c, [\"myconf_a/0.1\"])\n\n    def test_with_url(self, servers):\n        c = TestClient(servers=servers, light=True)\n        url = servers[\"default\"].fake_url\n        c.run(\"remote remove default\")\n        c.run(f\"config install-pkg myconf_a/0.1 --url={url}\")\n        assert \"Installing new or updating configuration packages\" in c.out\n        _check_conf(c, \"myconf_a/0.1\")\n        _check_conf_file(c, [\"myconf_a/0.1\"])\n\n    def test_update(self, servers):\n        c = TestClient(servers=servers, light=True)\n        c.run(\"config install-pkg myconf_a/0.1\")\n        c.run(\"config install-pkg myconf_a/0.2\")\n        assert \"Installing new or updating configuration packages\" in c.out\n        _check_conf(c, \"myconf_a/0.2\")\n        _check_conf_file(c, [\"myconf_a/0.2\"])\n\n    def test_addition(self, servers):\n        c = TestClient(servers=servers, light=True)\n        c.run(\"config install-pkg myconf_a/0.1\")\n        c.run(\"config install-pkg myconf_b/0.1\")\n        assert \"Installing new or updating configuration packages\" in c.out\n        _check_conf(c, \"myconf_b/0.1\")\n        _check_conf_file(c, [\"myconf_a/0.1\", \"myconf_b/0.1\"])\n\n    def test_update_first(self, servers):\n        c = TestClient(servers=servers, light=True)\n        c.run(\"config install-pkg myconf_a/0.1\")\n        c.run(\"config install-pkg myconf_b/0.1\")\n\n        # update of the first fail\n        c.run(\"config install-pkg myconf_a/[*]\", assert_error=True)\n        assert \"ERROR: Installing these configuration packages will break\" in c.out\n        assert \"use 'conan config install-pkg --force' to force\" in c.out\n        assert \"Use 'conan config clean' first to fully reset your configuration\" in c.out\n        _check_conf(c, \"myconf_b/0.1\")\n        _check_conf_file(c, [\"myconf_a/0.1\", \"myconf_b/0.1\"])\n\n        # Now force the first\n        c.run(\"config install-pkg myconf_a/[*] --force\")\n        assert \"Forcing the installation because --force was defined\" in c.out\n        _check_conf(c, \"myconf_a/0.2\")\n        _check_conf_file(c, [\"myconf_b/0.1\", \"myconf_a/0.2\"])\n\n    def test_update_second(self, servers):\n        c = TestClient(servers=servers, light=True)\n        c.run(\"config install-pkg myconf_a/0.1\")\n        c.run(\"config install-pkg myconf_b/0.1\")\n\n        # update of the second works without problem\n        c.run(\"config install-pkg myconf_b/[*]\")\n        assert \"Installing new or updating configuration packages\" in c.out\n        _check_conf(c, \"myconf_b/0.2\")\n        _check_conf_file(c, [\"myconf_a/0.1\", \"myconf_b/0.2\"])\n\n    def test_error_cant_use_as_dependency(self):\n        c = TestClient(light=True)\n        conanfile = GenConanfile(\"myconf\", \"0.1\").with_package_type(\"configuration\")\n        c.save({\"myconf/conanfile.py\": conanfile,\n                \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_requires(\"myconf/0.1\")})\n        c.run(\"create myconf\")\n        c.run(\"install pkg\", assert_error=True)\n        assert \"ERROR: Configuration package myconf/0.1 cannot be used as requirement, \" \\\n               \"but pkg/0.1 is requiring it\" in c.out\n\n    def test_error_cant_use_without_type(self):\n        c = TestClient(light=True)\n        c.save({\"myconf/conanfile.py\": GenConanfile(\"myconf\", \"0.1\")})\n        c.run(\"create myconf\")\n        c.run(\"config install-pkg myconf/[*]\", assert_error=True)\n        assert 'ERROR: myconf/0.1 is not of package_type=\"configuration\"' in c.out\n\n    def test_create_also(self):\n        conanfile = textwrap.dedent(\"\"\"\n           from conan import ConanFile\n           from conan.tools.files import copy\n           class Conf(ConanFile):\n               name = \"myconf\"\n               version = \"0.1\"\n               package_type = \"configuration\"\n               exports_sources = \"*.conf\"\n               def package(self):\n                   copy(self, \"*.conf\", src=self.build_folder, dst=self.package_folder)\n               \"\"\")\n\n        c = TestClient(default_server_user=True, light=True)\n        c.save({\"conanfile.py\": conanfile,\n                \"global.conf\": \"user.myteam:myconf=my_myconf/0.1_value\"})\n        c.run(\"create .\")\n        c.run(\"upload * -r=default -c\")\n        c.run(\"remove * -c\")\n\n        c.run(\"config install-pkg myconf/[*]\")\n        _check_conf(c, \"myconf/0.1\")\n        _check_conf_file(c, [\"myconf/0.1\"])\n\n    def test_lockfile(self, servers):\n        \"\"\" it should be able to install the config older version using a lockfile\n        \"\"\"\n        c = TestClient(servers=servers, light=True)\n        c.run(\"config install-pkg myconf_a/0.1 --lockfile-out=config.lock\")\n        c.run(\"config install-pkg myconf_a/[*] --lockfile=config.lock\")\n        assert (\"The requested configurations are identical to the already installed ones, \"\n                \"skipping re-installation\") in c.out\n        _check_conf(c, \"myconf_a/0.1\")\n        _check_conf_file(c, [\"myconf_a/0.1\"])\n\n        # Without the lockfile, it is free to update\n        c.run(\"config install-pkg myconf_a/[*] --lockfile-out=config.lock\")\n        assert \"Installing new or updating configuration packages\"\n        _check_conf(c, \"myconf_a/0.2\")\n        _check_conf_file(c, [\"myconf_a/0.2\"])\n        result = json.loads(c.load(\"config.lock\"))\n        assert \"myconf_a/0.2\" in result[\"config_requires\"][0]\n\n    def test_package_id_effect(self):\n        # full integration, as \"test_config_package_id.py\" tests from hardcoded cache json files\n        c = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import copy\n            class Conf(ConanFile):\n                name = \"myconf\"\n                version = \"0.1\"\n                package_type = \"configuration\"\n                def package(self):\n                    copy(self, \"*.conf\", src=self.build_folder, dst=self.package_folder)\n            \"\"\")\n        c.save({\"conanfile.py\": conanfile,\n                \"global.conf\": f\"core.package_id:config_mode=minor_mode\"})\n        c.run(f\"export-pkg .\")\n\n        c.run(\"config install-pkg myconf/0.1\")\n\n        c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")}, clean_first=True)\n        c.run(\"create .\")\n        assert f\"pkg/0.1: config_version: myconf/0.1.Z\" in c.out\n        c.run(\"list pkg/0.1:* --format=json\")\n        info = json.loads(c.stdout)\n        rrev = info[\"Local Cache\"][\"pkg/0.1\"][\"revisions\"][\"485dad6cb11e2fa99d9afbe44a57a164\"]\n        pkg = rrev[\"packages\"][\"b683aa607d81f4a3b6f0c87c8191387133f2ff4a\"]\n        assert pkg[\"info\"] == {\"config_version\": [\"myconf/0.1.Z\"]}\n\n\nclass TestConfigInstallPkgFromFile:\n    def test_install_from_file(self, servers):\n        c = TestClient(servers=servers, light=True)\n        # To make explicit the format of the conanconfig file\n        conanconfig = textwrap.dedent(\"\"\"\\\n            packages:\n                - myconf_a/0.1\n                - myconf_b/0.1\n            \"\"\")\n        c.save({\"conanconfig.yml\": conanconfig})\n        # Admits the default location .\n        c.run(\"config install-pkg\")\n        _check_conf(c, \"myconf_b/0.1\")\n        _check_conf_file(c, [\"myconf_a/0.1\", \"myconf_b/0.1\"])\n\n        # install same file again:\n        c.run(\"config install-pkg .\")\n        assert (\"The requested configurations are identical to the already installed ones, \"\n                \"skipping re-installation\") in c.out\n        _check_conf(c, \"myconf_b/0.1\")\n        _check_conf_file(c, [\"myconf_a/0.1\", \"myconf_b/0.1\"])\n\n        # Forced re-install\n        c.save_home({\"global.conf\": \"\"})\n        c.run(\"config install-pkg . --force\")\n        assert \"forcing re-installation because --force\" in c.out\n        _check_conf(c, \"myconf_b/0.1\")\n        _check_conf_file(c, [\"myconf_a/0.1\", \"myconf_b/0.1\"])\n\n    def test_install_from_file_with_url(self, servers):\n        c = TestClient(servers=servers, light=True)\n        c.run(\"remote remove default\")\n        server_url = servers[\"default\"].fake_url\n        conanconfig = yaml.dump({\"packages\": [\"myconf_a/0.1\"], \"urls\": [server_url]})\n        c.save({\"conanconfig.yml\": conanconfig})\n        c.run(\"config install-pkg .\")\n        _check_conf(c, \"myconf_a/0.1\")\n        _check_conf_file(c, [\"myconf_a/0.1\"])\n\n    def test_update_with_file(self, servers):\n        c = TestClient(servers=servers, light=True)\n        conanconfig = yaml.dump({\"packages\": [\"myconf_a/0.1\", \"myconf_b/0.1\"]})\n        c.save({\"conanconfig.yml\": conanconfig})\n        c.run(\"config install-pkg .\")\n\n        # Now installing \"updates\" without disrupting the order\n        c.run(\"config install-pkg myconf_c/0.1\")\n        assert \"Installing new or updating configuration packages\"\n        _check_conf(c, \"myconf_c/0.1\")\n        _check_conf_file(c, [\"myconf_a/0.1\", \"myconf_b/0.1\", \"myconf_c/0.1\"])\n\n        # Now installing \"updates\" without disrupting the order\n        conanconfig = textwrap.dedent(\"\"\"\\\n            packages:\n                - myconf_a/0.1\n                - myconf_b/0.1\n                - myconf_c/[*]\n            \"\"\")\n        c.save({\"conanconfig.yml\": conanconfig})\n        c.run(\"config install-pkg .\")\n        assert \"Installing new or updating configuration packages\" in c.out\n        _check_conf(c, \"myconf_c/0.2\")\n        _check_conf_file(c, [\"myconf_a/0.1\", \"myconf_b/0.1\", \"myconf_c/0.2\"])\n\n        # This is also an update of the existing ones, keeping the order\n        conanconfig = textwrap.dedent(\"\"\"\\\n            packages:\n                - myconf_a/[*]\n                - myconf_b/0.1\n                - myconf_c/[*]\n            \"\"\")\n        c.save({\"conanconfig.yml\": conanconfig})\n        c.run(\"config install-pkg .\")\n        assert \"Installing new or updating configuration packages\" in c.out\n        _check_conf(c, \"myconf_c/0.2\")\n        _check_conf_file(c, [\"myconf_a/0.2\", \"myconf_b/0.1\", \"myconf_c/0.2\"])\n\n    def test_failed_update_force(self, servers):\n        c = TestClient(servers=servers, light=True)\n        conanconfig = yaml.dump({\"packages\": [\"myconf_a/0.1\", \"myconf_b/0.1\"]})\n        c.save({\"conanconfig.yml\": conanconfig})\n        c.run(\"config install-pkg .\")\n\n        # Now installing \"updates\" without disrupting the order\n        conanconfig = textwrap.dedent(\"\"\"\\\n            packages:\n                - myconf_a/0.2\n            \"\"\")\n        c.save({\"conanconfig.yml\": conanconfig})\n        c.run(\"config install-pkg .\", assert_error=True)\n        assert \"use 'conan config install-pkg --force' to force\" in c.out\n        assert \"Use 'conan config clean' first to fully reset\" in c.out\n        _check_conf(c, \"myconf_b/0.1\")\n        _check_conf_file(c, [\"myconf_a/0.1\", \"myconf_b/0.1\"])\n\n        c.run(\"config install-pkg . --force\")\n        assert \"Forcing the installation because --force was defined\" in c.out\n        _check_conf(c, \"myconf_a/0.2\")\n        _check_conf_file(c, [\"myconf_b/0.1\", \"myconf_a/0.2\"])\n\n    def test_install_from_file_with_lockfile(self, servers):\n        # it should stay in version 0.1\n        c = TestClient(servers=servers)\n        c.run(\"config install-pkg myconf_a/0.1 --lockfile-out=conan.lock\")\n        conanconfig = yaml.dump({\"packages\": [\"myconf_a/[>=0.1 <1.0]\"]})\n        c.save({\"conanconfig.yml\": conanconfig})\n        c.run(\"config install-pkg .\")\n        path = HomePaths(c.cache_folder).config_version_path\n        # First are the newest installed\n        configs = json.loads(load(path))[\"config_version\"]\n        configs = [str(RecipeReference.loads(r)) for r in configs]\n        assert configs == [\"myconf_a/0.1\"]\n\n\nclass TestConfigInstallPkgSettings:\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import copy\n        class Conf(ConanFile):\n            name = \"myconf\"\n            version = \"0.1\"\n            settings = \"os\"\n            package_type = \"configuration\"\n            def package(self):\n                f = \"win\" if self.settings.os == \"Windows\" else \"nix\"\n                copy(self, \"*.conf\", src=os.path.join(self.build_folder, f), dst=self.package_folder)\n            \"\"\")\n\n    @pytest.fixture()\n    def client(self):\n        c = TestClient(default_server_user=True)\n        c.save({\"conanfile.py\": self.conanfile,\n                \"win/global.conf\": \"user.myteam:myconf=mywinvalue\",\n                \"nix/global.conf\": \"user.myteam:myconf=mynixvalue\",\n                })\n        c.run(\"export-pkg . -s os=Windows\")\n        c.run(\"export-pkg . -s os=Linux\")\n        c.run(\"upload * -r=default -c\")\n        c.run(\"remove * -c\")\n        return c\n\n    @pytest.mark.parametrize(\"default_profile\", [False, True])\n    def test_config_install_from_pkg(self, client, default_profile):\n        # Now install it\n        c = client\n        if not default_profile:\n            os.remove(os.path.join(c.cache_folder, \"profiles\", \"default\"))\n        c.run(\"config install-pkg myconf/[*] -s os=Windows\")\n        assert \"myconf/0.1: Downloaded package revision\" in c.out\n        assert \"Copying file global.conf\" in c.out\n        c.run(\"config show *\")\n        assert \"user.myteam:myconf: mywinvalue\" in c.out\n\n        c.run(\"config install-pkg myconf/[*] -s os=Linux --force\")\n        assert \"myconf/0.1: Downloaded package revision\" in c.out\n        assert \"Copying file global.conf\" in c.out\n        c.run(\"config show *\")\n        assert \"user.myteam:myconf: mynixvalue\" in c.out\n\n    def test_error_no_settings_defined(self, client):\n        c = client\n        os.remove(os.path.join(c.cache_folder, \"profiles\", \"default\"))\n        c.run(\"config install-pkg myconf/[*]\", assert_error=True)\n        assert \"There are invalid packages:\" in c.out\n        assert \"myconf/0.1: Invalid: 'settings.os' value not defined\" in c.out\n\n    def test_config_install_from_pkg_profile(self, client):\n        # Now install it\n        c = client\n        c.save({\"win.profile\": \"[settings]\\nos=Windows\",\n                \"nix.profile\": \"[settings]\\nos=Linux\"})\n        c.run(\"config install-pkg myconf/[*] -pr=win.profile\")\n        assert \"myconf/0.1: Downloaded package revision\" in c.out\n        assert \"Copying file global.conf\" in c.out\n        c.run(\"config show *\")\n        assert \"user.myteam:myconf: mywinvalue\" in c.out\n\n        c.run(\"config install-pkg myconf/[*] -pr=nix.profile --force\")\n        assert \"myconf/0.1: Downloaded package revision\" in c.out\n        assert \"Copying file global.conf\" in c.out\n        c.run(\"config show *\")\n        assert \"user.myteam:myconf: mynixvalue\" in c.out\n\n    def test_config_install_from_pkg_profile_default(self, client):\n        # Now install it\n        c = client\n        c.save_home({\"profiles/default\": \"[settings]\\nos=Windows\"})\n        c.run(\"config install-pkg myconf/[*]\")\n        assert \"myconf/0.1: Downloaded package revision\" in c.out\n        assert \"Copying file global.conf\" in c.out\n        c.run(\"config show *\")\n        assert \"user.myteam:myconf: mywinvalue\" in c.out\n\n        c.save_home({\"profiles/default\": \"[settings]\\nos=Linux\"})\n        c.run(\"config install-pkg myconf/[*] --force\")\n        assert \"myconf/0.1: Downloaded package revision\" in c.out\n        assert \"Copying file global.conf\" in c.out\n        c.run(\"config show *\")\n        assert \"user.myteam:myconf: mynixvalue\" in c.out\n\n\nclass TestConfigInstallPkgOptions:\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import copy\n        class Conf(ConanFile):\n            name = \"myconf\"\n            version = \"0.1\"\n            options = {\"project\": [\"project1\", \"project2\"]}\n            default_options = {\"project\": \"project1\"}\n            package_type = \"configuration\"\n            def package(self):\n                copy(self, \"*.conf\", src=os.path.join(self.build_folder, str(self.options.project)),\n                     dst=self.package_folder)\n            \"\"\")\n\n    @pytest.fixture()\n    def client(self):\n        c = TestClient(default_server_user=True)\n        c.save({\"conanfile.py\": self.conanfile,\n                \"project1/global.conf\": \"user.myteam:myconf=my1value\",\n                \"project2/global.conf\": \"user.myteam:myconf=my2value\",\n                })\n        c.run(\"export-pkg .\")\n        c.run(\"export-pkg . -o project=project2\")\n        c.run(\"upload * -r=default -c\")\n        c.run(\"remove * -c\")\n        return c\n\n    @pytest.mark.parametrize(\"default_profile\", [False, True])\n    def test_config_install_from_pkg(self, client, default_profile):\n        # Now install it\n        c = client\n        if not default_profile:\n            os.remove(os.path.join(c.cache_folder, \"profiles\", \"default\"))\n        c.run(\"config install-pkg myconf/[*] -o &:project=project1\")\n        assert \"myconf/0.1: Downloaded package revision\" in c.out\n        assert \"Copying file global.conf\" in c.out\n        c.run(\"config show *\")\n        assert \"user.myteam:myconf: my1value\" in c.out\n\n        c.run(\"config install-pkg myconf/[*] -o &:project=project2 --force\")\n        assert \"myconf/0.1: Downloaded package revision\" in c.out\n        assert \"Copying file global.conf\" in c.out\n        c.run(\"config show *\")\n        assert \"user.myteam:myconf: my2value\" in c.out\n\n    def test_no_option_defined(self, client):\n        c = client\n        os.remove(os.path.join(c.cache_folder, \"profiles\", \"default\"))\n        c.run(\"config install-pkg myconf/[*]\")\n        assert \"Copying file global.conf\" in c.out\n        c.run(\"config show *\")\n        assert \"user.myteam:myconf: my1value\" in c.out\n\n    def test_config_install_from_pkg_profile(self, client):\n        # Now install it\n        c = client\n        c.save({\"win.profile\": \"[options]\\n&:project=project1\",\n                \"nix.profile\": \"[options]\\n&:project=project2\"})\n        c.run(\"config install-pkg myconf/[*] -pr=win.profile\")\n        assert \"myconf/0.1: Downloaded package revision\" in c.out\n        assert \"Copying file global.conf\" in c.out\n        c.run(\"config show *\")\n        assert \"user.myteam:myconf: my1value\" in c.out\n\n        c.run(\"config install-pkg myconf/[*] -pr=nix.profile --force\")\n        assert \"myconf/0.1: Downloaded package revision\" in c.out\n        assert \"Copying file global.conf\" in c.out\n        c.run(\"config show *\")\n        assert \"user.myteam:myconf: my2value\" in c.out\n\n    def test_config_install_from_pkg_profile_default(self, client):\n        # Now install it\n        c = client\n        c.save_home({\"profiles/default\": \"[options]\\n&:project=project1\"})\n        c.run(\"config install-pkg myconf/[*]\")\n        assert \"myconf/0.1: Downloaded package revision\" in c.out\n        assert \"Copying file global.conf\" in c.out\n        c.run(\"config show *\")\n        assert \"user.myteam:myconf: my1value\" in c.out\n\n        c.save_home({\"profiles/default\": \"[options]\\n&:project=project2\"})\n        c.run(\"config install-pkg myconf/[*] --force\")\n        assert \"myconf/0.1: Downloaded package revision\" in c.out\n        assert \"Copying file global.conf\" in c.out\n        c.run(\"config show *\")\n        assert \"user.myteam:myconf: my2value\" in c.out\n"
  },
  {
    "path": "test/functional/command/test_custom_symlink_home.py",
    "content": "import os\nimport platform\n\nimport pytest\n\nfrom conan.test.utils.scm import create_local_git_repo\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import save\n\n\n@pytest.mark.skipif(platform.system() == \"Windows\", reason=\"Uses symlinks\")\ndef test_custom_symlinked_home_config_install():\n    base_cache = temp_folder()\n    real_cache = os.path.join(base_cache, \"real_cache\")\n    os.makedirs(real_cache)\n    symlink_cache = os.path.join(base_cache, \"symlink_cache\")\n    os.symlink(real_cache, symlink_cache)\n    origin_folder = temp_folder()\n    save(os.path.join(origin_folder, \"myfile.txt\"), \"some contents\")\n    create_local_git_repo(folder=origin_folder)\n    c = TestClient(cache_folder=symlink_cache)\n    c.run(f'config install \"{origin_folder}\" --type=git')\n    assert \"Copying file myfile.txt to\" in c.out\n"
  },
  {
    "path": "test/functional/command/test_install_deploy.py",
    "content": "import os\nimport platform\nimport shutil\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.cmake import gen_cmakelists\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.assets.sources import gen_function_cpp\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import save\n\n\n@pytest.fixture()\ndef client(matrix_client_shared):\n    c = matrix_client_shared\n    conanfile = textwrap.dedent(\"\"\"\n       import os\n       from conan import ConanFile\n       from conan.tools.files import save\n       class Tool(ConanFile):\n           name = \"tool\"\n           version = \"1.0\"\n           def package(self):\n               save(self, os.path.join(self.package_folder, \"build\", \"my_tools.cmake\"),\n                    'set(MY_TOOL_VARIABLE \"Hello world!\")')\n\n           def package_info(self):\n               self.cpp_info.includedirs = []\n               self.cpp_info.libdirs = []\n               self.cpp_info.bindirs = []\n               path_build_modules = os.path.join(\"build\", \"my_tools.cmake\")\n               self.cpp_info.set_property(\"cmake_build_modules\", [path_build_modules])\n           \"\"\")\n    c.save({\"conanfile.py\": conanfile}, clean_first=True)\n    c.run(\"create .\")\n    return c\n\n\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.parametrize(\"powershell\", [False, True])\ndef test_install_deploy(client, powershell):\n    c = client\n    custom_content = 'message(STATUS \"MY_TOOL_VARIABLE=${MY_TOOL_VARIABLE}!\")'\n    cmake = gen_cmakelists(appname=\"my_app\", appsources=[\"main.cpp\"], find_package=[\"matrix\", \"tool\"],\n                           custom_content=custom_content)\n    deploy = textwrap.dedent(\"\"\"\n        import os, shutil\n\n        # USE **KWARGS to be robust against changes\n        def deploy(graph, output_folder, **kwargs):\n            conanfile = graph.root.conanfile\n            for r, d in conanfile.dependencies.items():\n                new_folder = os.path.join(output_folder, d.ref.name)\n                shutil.copytree(d.package_folder, new_folder)\n                d.set_deploy_folder(new_folder)\n        \"\"\")\n    c.save({\"conanfile.txt\": \"[requires]\\nmatrix/1.0\\ntool/1.0\",\n            \"deploy.py\": deploy,\n            \"CMakeLists.txt\": cmake,\n            \"main.cpp\": gen_function_cpp(name=\"main\", includes=[\"matrix\"], calls=[\"matrix\"])},\n           clean_first=True)\n    pwsh = \"-c tools.env.virtualenv:powershell=True\" if powershell else \"\"\n    c.run(\"install . -o *:shared=True \"\n          f\"--deployer=deploy.py -of=mydeploy -g CMakeToolchain -g CMakeDeps {pwsh}\")\n    c.run(\"remove * -c\")  # Make sure the cache is clean, no deps there\n    arch = c.get_default_host_profile().settings['arch']\n    deps = c.load(f\"mydeploy/matrix-release-{arch}-data.cmake\")\n    assert 'set(matrix_PACKAGE_FOLDER_RELEASE \"${CMAKE_CURRENT_LIST_DIR}/matrix\")' in deps\n    assert 'set(matrix_INCLUDE_DIRS_RELEASE \"${matrix_PACKAGE_FOLDER_RELEASE}/include\")' in deps\n    assert 'set(matrix_LIB_DIRS_RELEASE \"${matrix_PACKAGE_FOLDER_RELEASE}/lib\")' in deps\n\n    # We can fully move it to another folder, and still works\n    tmp = os.path.join(temp_folder(), \"relocated\")\n    shutil.copytree(c.current_folder, tmp)\n    shutil.rmtree(c.current_folder)\n    c2 = TestClient(current_folder=tmp)\n    # I can totally build without errors with deployed\n    c2.run_command(\"cmake . -DCMAKE_TOOLCHAIN_FILE=mydeploy/conan_toolchain.cmake \"\n                   \"-DCMAKE_BUILD_TYPE=Release\")\n    assert \"MY_TOOL_VARIABLE=Hello world!!\" in c2.out\n    c2.run_command(\"cmake --build . --config Release\")\n    if platform.system() == \"Windows\":  # Only the .bat env-generators are relocatable\n        if powershell:\n            cmd = r\"powershell.exe mydeploy\\conanrun.ps1 ; Release\\my_app.exe\"\n        else:\n            cmd = r\"mydeploy\\conanrun.bat && Release\\my_app.exe\"\n        # For Lunux: cmd = \". mydeploy/conanrun.sh && ./my_app\"\n        c2.run_command(cmd)\n        assert \"matrix/1.0: Hello World Release!\" in c2.out\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_install_full_deploy_layout(client):\n    c = client\n    custom_content = 'message(STATUS \"MY_TOOL_VARIABLE=${MY_TOOL_VARIABLE}!\")'\n    cmake = gen_cmakelists(appname=\"my_app\", appsources=[\"main.cpp\"], find_package=[\"matrix\", \"tool\"],\n                           custom_content=custom_content)\n    conanfile = textwrap.dedent(\"\"\"\n        [requires]\n        matrix/1.0\n        tool/1.0\n        [generators]\n        CMakeDeps\n        CMakeToolchain\n        [layout]\n        cmake_layout\n        \"\"\")\n    c.save({\"conanfile.txt\": conanfile,\n            \"CMakeLists.txt\": cmake,\n            \"main.cpp\": gen_function_cpp(name=\"main\", includes=[\"matrix\"], calls=[\"matrix\"])},\n           clean_first=True)\n    c.run(\"install . -o *:shared=True --deployer=full_deploy.py\")\n    c.run(\"remove * -c\")  # Make sure the cache is clean, no deps there\n    arch = c.get_default_host_profile().settings['arch']\n    folder = \"/Release\" if platform.system() != \"Windows\" else \"\"\n    rel_path = \"../../\" if platform.system() == \"Windows\" else \"../../../\"\n    deps = c.load(f\"build{folder}/generators/matrix-release-{arch}-data.cmake\")\n    assert 'set(matrix_PACKAGE_FOLDER_RELEASE \"${CMAKE_CURRENT_LIST_DIR}/' \\\n           f'{rel_path}full_deploy/host/matrix/1.0/Release/{arch}\")' in deps\n    assert 'set(matrix_INCLUDE_DIRS_RELEASE \"${matrix_PACKAGE_FOLDER_RELEASE}/include\")' in deps\n    assert 'set(matrix_LIB_DIRS_RELEASE \"${matrix_PACKAGE_FOLDER_RELEASE}/lib\")' in deps\n\n    # We can fully move it to another folder, and still works\n    tmp = os.path.join(temp_folder(), \"relocated\")\n    shutil.copytree(c.current_folder, tmp)\n    shutil.rmtree(c.current_folder)\n    c2 = TestClient(current_folder=tmp)\n    with c2.chdir(f\"build{folder}\"):\n        # I can totally build without errors with deployed\n        cmakelist = \"../..\" if platform.system() != \"Windows\" else \"..\"\n        c2.run_command(f\"cmake {cmakelist} -DCMAKE_TOOLCHAIN_FILE=generators/conan_toolchain.cmake \"\n                       \"-DCMAKE_BUILD_TYPE=Release\")\n        assert \"MY_TOOL_VARIABLE=Hello world!!\" in c2.out\n        c2.run_command(\"cmake --build . --config Release\")\n        if platform.system() == \"Windows\":  # Only the .bat env-generators are relocatable atm\n            cmd = r\"generators\\conanrun.bat && Release\\my_app.exe\"\n            # For Lunux: cmd = \". mydeploy/conanrun.sh && ./my_app\"\n            c2.run_command(cmd)\n            assert \"matrix/1.0: Hello World Release!\" in c2.out\n\n\ndef test_copy_files_deploy():\n    c = TestClient()\n    deploy = textwrap.dedent(\"\"\"\n        import os, shutil\n\n        def deploy(graph, output_folder, **kwargs):\n            conanfile = graph.root.conanfile\n            for r, d in conanfile.dependencies.items():\n                bindir = os.path.join(d.package_folder, \"bin\")\n                for f in os.listdir(bindir):\n                    shutil.copy2(os.path.join(bindir, f), os.path.join(output_folder, f))\n        \"\"\")\n    c.save({\"conanfile.txt\": \"[requires]\\nhello/0.1\",\n            \"deploy.py\": deploy,\n            \"hello/conanfile.py\": GenConanfile(\"hello\", \"0.1\").with_package_file(\"bin/file.txt\",\n                                                                                 \"content!!\")})\n    c.run(\"create hello\")\n    c.run(\"install . --deployer=deploy.py -of=mydeploy\")\n\n\ndef test_multi_deploy():\n    \"\"\" check that we can add more than 1 deployer in the command line, both in local folders\n    and in cache.\n    Also testing that using .py extension or not, is the same\n    Also, the local folder have precedence over the cache extensions\n    \"\"\"\n    c = TestClient()\n    deploy1 = textwrap.dedent(\"\"\"\n        def deploy(graph, output_folder, **kwargs):\n            conanfile = graph.root.conanfile\n            conanfile.output.info(\"deploy1!!\")\n        \"\"\")\n    deploy2 = textwrap.dedent(\"\"\"\n        def deploy(graph, output_folder, **kwargs):\n            conanfile = graph.root.conanfile\n            conanfile.output.info(\"sub/deploy2!!\")\n        \"\"\")\n    deploy_cache = textwrap.dedent(\"\"\"\n        def deploy(graph, output_folder, **kwargs):\n            conanfile = graph.root.conanfile\n            conanfile.output.info(\"deploy cache!!\")\n        \"\"\")\n    save(os.path.join(c.cache_folder, \"extensions\", \"deploy\", \"deploy_cache.py\"), deploy_cache)\n    # This should never be called in this test, always the local is found first\n    save(os.path.join(c.cache_folder, \"extensions\", \"deploy\", \"mydeploy.py\"), \"CRASH!!!!\")\n    c.save({\"conanfile.txt\": \"\",\n            \"mydeploy.py\": deploy1,\n            \"sub/mydeploy2.py\": deploy2})\n\n    c.run(\"install . --deployer=mydeploy --deployer=sub/mydeploy2 --deployer=deploy_cache\")\n    assert \"conanfile.txt: deploy1!!\" in c.out\n    assert \"conanfile.txt: sub/deploy2!!\" in c.out\n    assert \"conanfile.txt: deploy cache!!\" in c.out\n\n    # Now with .py extension\n    c.run(\"install . --deployer=mydeploy.py --deployer=sub/mydeploy2.py --deployer=deploy_cache.py\")\n    assert \"conanfile.txt: deploy1!!\" in c.out\n    assert \"conanfile.txt: sub/deploy2!!\" in c.out\n    assert \"conanfile.txt: deploy cache!!\" in c.out\n\n\ndef test_deploy_local_import():\n    \"\"\" test that deployers can share some Python code with local imports\n    \"\"\"\n    c = TestClient()\n    helper = textwrap.dedent(\"\"\"\n        def myhelper(conanfile):\n            conanfile.output.info(\"My HELPER!!\")\n        \"\"\")\n    deploy_cache = textwrap.dedent(\"\"\"\n        from helper import myhelper\n        def deploy(graph, output_folder, **kwargs):\n            myhelper(graph.root.conanfile)\n        \"\"\")\n    save(os.path.join(c.cache_folder, \"extensions\", \"deployers\", \"deploy_cache.py\"), deploy_cache)\n    save(os.path.join(c.cache_folder, \"extensions\", \"deployers\", \"helper.py\"), helper)\n    c.save({\"conanfile.txt\": \"\"})\n    c.run(\"install . --deployer=deploy_cache\")\n    assert \"conanfile.txt: My HELPER!!\" in c.out\n\n\ndef test_builtin_full_deploy():\n    \"\"\" check the built-in full_deploy\n    \"\"\"\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import save\n        class Pkg(ConanFile):\n            settings = \"arch\", \"build_type\"\n            def package(self):\n                content = f\"{self.settings.build_type}-{self.settings.arch}\"\n                save(self, os.path.join(self.package_folder, \"include/hello.h\"), content)\n\n            def package_info(self):\n                path_build_modules = os.path.join(\"build\", \"my_tools_{}.cmake\".format(self.context))\n                self.cpp_info.set_property(\"cmake_build_modules\", [path_build_modules])\n            \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"create . --name=dep --version=0.1\")\n    c.run(\"create . --name=dep --version=0.1 -s build_type=Debug -s arch=x86\")\n    c.save({\"conanfile.txt\": \"[requires]\\ndep/0.1\"}, clean_first=True)\n    c.run(\"install . --deployer=full_deploy -of=output -g CMakeDeps\")\n    assert \"Conan built-in full deployer\" in c.out\n    c.run(\"install . --deployer=full_deploy -of=output -g CMakeDeps \"\n          \"-s build_type=Debug -s arch=x86\")\n\n    host_arch = c.get_default_host_profile().settings['arch']\n    release = c.load(f\"output/full_deploy/host/dep/0.1/Release/{host_arch}/include/hello.h\")\n    assert f\"Release-{host_arch}\" in release\n    debug = c.load(\"output/full_deploy/host/dep/0.1/Debug/x86/include/hello.h\")\n    assert \"Debug-x86\" in debug\n    cmake_release = c.load(f\"output/dep-release-{host_arch}-data.cmake\")\n    assert 'set(dep_INCLUDE_DIRS_RELEASE \"${dep_PACKAGE_FOLDER_RELEASE}/include\")' in cmake_release\n    assert f\"${{CMAKE_CURRENT_LIST_DIR}}/full_deploy/host/dep/0.1/Release/{host_arch}\" in cmake_release\n    assert 'set(dep_BUILD_MODULES_PATHS_RELEASE ' \\\n           '\"${dep_PACKAGE_FOLDER_RELEASE}/build/my_tools_host.cmake\")' in cmake_release\n    cmake_debug = c.load(\"output/dep-debug-x86-data.cmake\")\n    assert 'set(dep_INCLUDE_DIRS_DEBUG \"${dep_PACKAGE_FOLDER_DEBUG}/include\")' in cmake_debug\n    assert \"${CMAKE_CURRENT_LIST_DIR}/full_deploy/host/dep/0.1/Debug/x86\" in cmake_debug\n    assert 'set(dep_BUILD_MODULES_PATHS_DEBUG ' \\\n           '\"${dep_PACKAGE_FOLDER_DEBUG}/build/my_tools_host.cmake\")' in cmake_debug\n\n\ndef test_deploy_reference():\n    \"\"\" check that we can also deploy a reference\n    \"\"\"\n    c = TestClient()\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_package_file(\"include/hi.h\", \"hi\")})\n    c.run(\"create .\")\n\n    c.run(\"install  --requires=pkg/1.0 --deployer=full_deploy --output-folder=output\")\n    # NOTE: Full deployer always use build_type/arch, even if None/None in the path, same structure\n    header = c.load(\"output/full_deploy/host/pkg/1.0/include/hi.h\")\n    assert \"hi\" in header\n\n    # Testing that we can deploy to the current folder too\n    c.save({}, clean_first=True)\n    c.run(\"install  --requires=pkg/1.0 --deployer=full_deploy\")\n    # NOTE: Full deployer always use build_type/arch, even if None/None in the path, same structure\n    header = c.load(\"full_deploy/host/pkg/1.0/include/hi.h\")\n    assert \"hi\" in header\n\n\ndef test_deploy_overwrite():\n    \"\"\" calling several times the install --deploy doesn't crash if files already exist\n    \"\"\"\n    c = TestClient()\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_package_file(\"include/hi.h\", \"hi\")})\n    c.run(\"create .\")\n\n    c.run(\"install  --requires=pkg/1.0 --deployer=full_deploy --output-folder=output\")\n    header = c.load(\"output/full_deploy/host/pkg/1.0/include/hi.h\")\n    assert \"hi\" in header\n\n    # modify the package\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_package_file(\"include/hi.h\", \"bye\")})\n    c.run(\"create .\")\n    c.run(\"install  --requires=pkg/1.0 --deployer=full_deploy --output-folder=output\")\n    header = c.load(\"output/full_deploy/host/pkg/1.0/include/hi.h\")\n    assert \"bye\" in header\n\n\ndef test_deploy_editable():\n    \"\"\" when deploying something that is editable, with the full_deploy built-in, it will copy the\n    editable files as-is, but it doesn't fail at this moment\n    \"\"\"\n\n    c = TestClient()\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\"),\n            \"src/include/hi.h\": \"hi\"})\n    c.run(\"editable add .\")\n\n    # If we don't change to another folder, the full_deploy will be recursive and fail\n    with c.chdir(temp_folder()):\n        c.run(\"install  --requires=pkg/1.0 --deployer=full_deploy --output-folder=output\")\n        header = c.load(\"output/full_deploy/host/pkg/1.0/src/include/hi.h\")\n        assert \"hi\" in header\n\n\ndef test_deploy_aggregate_components():\n    \"\"\"\n    The caching of aggregated components can be causing issues when deploying and using\n    generators that would still point to the packages with components in the cache\n    https://github.com/conan-io/conan/issues/14022\n    \"\"\"\n    c = TestClient()\n    dep = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"dep\"\n            version = \"0.1\"\n\n            def package_info(self):\n                self.cpp_info.components[\"mycomp\"].libs = [\"mycomp\"]\n            \"\"\")\n    c.save({\"dep/conanfile.py\": dep,\n            \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_settings(\"build_type\")\n                                                          .with_requires(\"dep/0.1\")\n                                                          .with_generator(\"CMakeDeps\"),\n            \"consumer/conanfile.py\": GenConanfile().with_settings(\"build_type\")\n                                                   .with_requires(\"pkg/0.1\")\n                                                   .with_generator(\"CMakeDeps\")})\n    c.run(\"export dep\")\n    c.run(\"export pkg\")\n\n    # If we don't change to another folder, the full_deploy will be recursive and fail\n    c.run(\"install consumer --build=missing --deployer=full_deploy --output-folder=output\")\n    data = c.load(\"output/dep-release-data.cmake\")\n    assert 'set(dep_PACKAGE_FOLDER_RELEASE ' \\\n           '\"${CMAKE_CURRENT_LIST_DIR}/full_deploy/host/dep/0.1\")' in data\n    assert 'set(dep_INCLUDE_DIRS_RELEASE \"${dep_PACKAGE_FOLDER_RELEASE}/include\")' in data\n\n\ndef test_deploy_single_package():\n    \"\"\" Let's try a deploy that executes on a single package reference\n    \"\"\"\n    c = TestClient()\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_package_file(\"include/hi.h\", \"hi\"),\n            \"consumer/conanfile.txt\": \"[requires]\\npkg/1.0\"})\n    c.run(\"create .\")\n\n    # if we deploy one --requires, we get that package\n    c.run(\"install  --requires=pkg/1.0 --deployer=direct_deploy --output-folder=output\")\n    header = c.load(\"output/direct_deploy/pkg/include/hi.h\")\n    assert \"hi\" in header\n\n    # If we deploy a local conanfile.txt, we get deployed its direct dependencies\n    c.run(\"install consumer/conanfile.txt --deployer=direct_deploy --output-folder=output2\")\n    header = c.load(\"output2/direct_deploy/pkg/include/hi.h\")\n    assert \"hi\" in header\n\n\ndef test_deploy_output_locations():\n    tc = TestClient()\n    deployer = textwrap.dedent(\"\"\"\n    def deploy(graph, output_folder, **kwargs):\n        graph.root.conanfile.output.info(f\"Deployer output: {output_folder}\")\n    \"\"\")\n    tc.save({\"conanfile.txt\": \"\",\n             \"my_deploy.py\": deployer})\n\n    tmp_folder = temp_folder()\n    tc.run(f\"install . --deployer=my_deploy -of='{tmp_folder}'\")\n    assert f\"Deployer output: {tmp_folder}\" in tc.out\n\n    deployer_output = temp_folder()\n    tc.run(f\"install . --deployer=my_deploy -of='{tmp_folder}' --deployer-folder='{deployer_output}'\")\n    assert f\"Deployer output: {deployer_output}\" in tc.out\n    assert f\"Deployer output: {tmp_folder}\" not in tc.out\n\n\ndef test_not_deploy_absolute_paths():\n    \"\"\" Absolute paths, for system packages, don't need to be relativized\n    https://github.com/conan-io/conan/issues/15242\n    \"\"\"\n    c = TestClient()\n    some_abs_path = temp_folder().replace(\"\\\\\", \"/\")\n    conanfile = textwrap.dedent(f\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"1.0\"\n            def package_info(self):\n                self.cpp_info.includedirs = [\"{some_abs_path}/myusr/include\"]\n                self.cpp_info.libdirs = [\"{some_abs_path}/myusr/lib\"]\n                self.buildenv_info.define_path(\"MYPATH\", \"{some_abs_path}/mypath\")\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"create .\")\n\n    # if we deploy one --requires, we get that package\n    c.run(\"install  --requires=pkg/1.0 --deployer=full_deploy -g CMakeDeps -g CMakeToolchain \"\n          \"-s os=Linux -s:b os=Linux -s arch=x86_64 -s:b arch=x86_64\")\n    data = c.load(\"pkg-release-x86_64-data.cmake\")\n    assert f'set(pkg_INCLUDE_DIRS_RELEASE \"{some_abs_path}/myusr/include\")' in data\n    assert f'set(pkg_LIB_DIRS_RELEASE \"{some_abs_path}/myusr/lib\")' in data\n\n    env = c.load(\"conanbuildenv-release-x86_64.sh\")\n    assert f'export MYPATH=\"{some_abs_path}/mypath\"' in env\n\n\ndef test_deploy_incorrect_folder():\n    # https://github.com/conan-io/cmake-conan/issues/658\n    c = TestClient()\n    c.save({\"conanfile.txt\": \"\"})\n    c.run('install . --deployer=full_deploy --deployer-folder=\"mydep fold\"')\n    assert os.path.exists(os.path.join(c.current_folder, \"mydep fold\"))\n    if platform.system() == \"Windows\":  # This only fails in Windows\n        c.run(r'install . --deployer=full_deploy --deployer-folder=\"\\\"mydep fold\\\"\"',\n              assert_error=True)\n        assert \"ERROR: Deployer folder cannot be created\" in c.out\n\n\nclass TestRuntimeDeployer:\n    def test_runtime_deploy(self):\n        c = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n           from conan import ConanFile\n           from conan.tools.files import copy\n           class Pkg(ConanFile):\n               package_type = \"shared-library\"\n               def package(self):\n                   copy(self, \"*.so\", src=self.build_folder, dst=self.package_folder)\n                   copy(self, \"*.dll\", src=self.build_folder, dst=self.package_folder)\n           \"\"\")\n        c.save({\"pkga/conanfile.py\": conanfile,\n                \"pkga/lib/pkga.so\": \"\",\n                \"pkga/bin/pkga.dll\": \"\",\n                \"pkgb/conanfile.py\": conanfile,\n                \"pkgb/lib/pkgb.so\": \"\"})\n        c.run(\"export-pkg pkga --name=pkga --version=1.0\")\n        c.run(\"export-pkg pkgb --name=pkgb --version=1.0\")\n        c.run(\"install --requires=pkga/1.0 --requires=pkgb/1.0 --deployer=runtime_deploy \"\n              \"--deployer-folder=myruntime -vvv\")\n\n        expected = sorted([\"pkga.so\", \"pkgb.so\", \"pkga.dll\"])\n        assert sorted(os.listdir(os.path.join(c.current_folder, \"myruntime\"))) == expected\n\n        c.run(\"install --requires=pkga/1.0 --requires=pkgb/1.0 --deployer=runtime_deploy \"\n              \"--deployer-folder=myruntime -vvv\")\n        assert \"pkga.dll exists with same contents, skipping copy\" in c.out\n        assert \"pkga.so exists with same contents, skipping copy\" in c.out\n        assert \"pkgb.so exists with same contents, skipping copy\" in c.out\n        c.save({\"myruntime/pkga.dll\": \"other content\"})\n        c.run(\"install --requires=pkga/1.0 --requires=pkgb/1.0 --deployer=runtime_deploy \"\n              \"--deployer-folder=myruntime -vvv\")\n        assert \"pkga.dll exists and will be overwritten\" in c.out\n\n    def test_runtime_not_deploy(self):\n        # https://github.com/conan-io/conan/issues/16712\n        # If no run=False (no package-type), then no runtime is deployed\n        c = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n           from conan import ConanFile\n           from conan.tools.files import copy\n           class Pkg(ConanFile):\n               def package(self):\n                   copy(self, \"*.so\", src=self.build_folder, dst=self.package_folder)\n                   copy(self, \"*.dll\", src=self.build_folder, dst=self.package_folder)\n           \"\"\")\n        c.save({\"pkga/conanfile.py\": conanfile,\n                \"pkga/lib/pkga.so\": \"\",\n                \"pkga/bin/pkga.dll\": \"\"})\n        c.run(\"export-pkg pkga --name=pkga --version=1.0\")\n        c.run(\"install --requires=pkga/1.0 --deployer=runtime_deploy --deployer-folder=myruntime\")\n        assert os.listdir(os.path.join(c.current_folder, \"myruntime\")) == []\n\n    def test_runtime_deploy_components(self):\n        c = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.files import copy\n            class Pkg(ConanFile):\n               package_type = \"shared-library\"\n               def package(self):\n                   copy(self, \"*.so\", src=self.build_folder,\n                        dst=os.path.join(self.package_folder, \"a\"))\n                   copy(self, \"*.dll\", src=self.build_folder,\n                        dst=os.path.join(self.package_folder, \"b\"))\n               def package_info(self):\n                   self.cpp_info.components[\"a\"].libdirs = [\"a\"]\n                   self.cpp_info.components[\"b\"].bindirs = [\"b\"]\n           \"\"\")\n        c.save({\"pkga/conanfile.py\": conanfile,\n                \"pkga/lib/pkga.so\": \"\",\n                \"pkga/bin/pkga.dll\": \"\",\n                \"pkgb/conanfile.py\": conanfile,\n                \"pkgb/lib/pkgb.so\": \"\"})\n        c.run(\"export-pkg pkga --name=pkga --version=1.0\")\n        c.run(\"export-pkg pkgb --name=pkgb --version=1.0\")\n        c.run(\"install --requires=pkga/1.0 --requires=pkgb/1.0 --deployer=runtime_deploy \"\n              \"--deployer-folder=myruntime -vvv\")\n\n        assert (sorted(os.listdir(os.path.join(c.current_folder, \"myruntime\")))\n                == sorted([\"bin\", \"lib\"]))\n        assert (sorted(os.listdir(os.path.join(c.current_folder, \"myruntime\", \"lib\")))\n                == sorted(['pkga.so', 'pkgb.so']))\n        assert (sorted(os.listdir(os.path.join(c.current_folder, \"myruntime\", \"bin\")))\n                == sorted(['pkga.dll']))\n\n    @pytest.mark.parametrize(\"symlink, expected\",\n                             [(True, [\"libfoo.so.0.1.0\", \"libfoo.so.0\", \"libfoo.so\"]),\n                              (False, [\"libfoo.so.0.1.0\"])])\n    def test_runtime_deploy_symlinks(self, symlink, expected):\n        \"\"\" The deployer runtime_deploy should preserve symlinks when deploying shared libraries\n        \"\"\"\n        c = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n               from conan import ConanFile\n               from conan.tools.files import copy, chdir\n               import os\n               class Pkg(ConanFile):\n                   package_type = \"shared-library\"\n                   def package(self):\n                       copy(self, \"*.so*\", src=self.build_folder, dst=self.package_folder)\n                       with chdir(self, os.path.join(self.package_folder, \"lib\")):\n                           os.symlink(src=\"libfoo.so.0.1.0\", dst=\"libfoo.so.0\")\n                           os.symlink(src=\"libfoo.so.0\", dst=\"libfoo.so\")\n               \"\"\")\n        c.save({\"foo/conanfile.py\": conanfile,\n                \"foo/lib/libfoo.so.0.1.0\": \"\"})\n        c.run(\"export-pkg foo/ --name=foo --version=0.1.0\")\n        c.run(f\"install --requires=foo/0.1.0 --deployer=runtime_deploy --deployer-folder=output \"\n              f\"-c:a tools.deployer:symlinks={symlink}\")\n\n        sorted_expected = sorted(expected)\n        assert sorted(os.listdir(os.path.join(c.current_folder, \"output\"))) == sorted_expected\n        link_so_0 = os.path.join(c.current_folder, \"output\", \"libfoo.so.0\")\n        link_so = os.path.join(c.current_folder, \"output\", \"libfoo.so\")\n        lib = os.path.join(c.current_folder, \"output\", \"libfoo.so.0.1.0\")\n        # INFO: This test requires in Windows to have symlinks enabled, otherwise it will fail\n        if symlink and platform.system() != \"Windows\":\n            assert os.path.islink(link_so_0)\n            assert os.path.islink(link_so)\n            assert not os.path.isabs(os.readlink(link_so_0))\n            assert not os.path.isabs(os.readlink(os.path.join(link_so)))\n            assert os.path.realpath(link_so) == os.path.realpath(link_so_0)\n            assert os.path.realpath(link_so_0) == os.path.realpath(lib)\n            assert not os.path.islink(lib)\n        else:\n            assert not os.path.islink(lib)\n\n    def test_runtime_deploy_subfolder(self):\n        \"\"\" The deployer runtime_deploy should preserve subfolder structure when deploying\n        shared libraries\n        \"\"\"\n        c = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n               from conan import ConanFile\n               from conan.tools.files import copy\n               import os\n               class Pkg(ConanFile):\n                   package_type = \"shared-library\"\n                   def package(self):\n                       copy(self, \"*.so*\", src=self.build_folder, dst=self.package_folder,\n                            keep_path=True)\n               \"\"\")\n        c.save({\"foo/conanfile.py\": conanfile,\n                \"foo/lib/libfoo.so\": \"\",\n                \"foo/lib/subfolder/libbar.so\": \"\",\n                \"foo/lib/subfolder/subsubfolder/libqux.so\": \"\",})\n        c.run(\"export-pkg foo/ --name=foo --version=0.1.0\")\n        c.run(f\"install --requires=foo/0.1.0 --deployer=runtime_deploy --deployer-folder=output\")\n\n        assert (sorted(os.listdir(os.path.join(c.current_folder, \"output\"))) ==\n                [\"libfoo.so\", \"subfolder\"])\n        assert (sorted(os.listdir(os.path.join(c.current_folder, \"output\", \"subfolder\"))) ==\n                [\"libbar.so\", \"subsubfolder\"])\n        assert sorted(os.listdir(os.path.join(c.current_folder, \"output\", \"subfolder\",\n                                              \"subsubfolder\"))) == [\"libqux.so\"]\n\n    def test_runtime_deploy_subfolder_symlink(self):\n        \"\"\" The deployer runtime_deploy should preserve subfolder structure when deploying shared\n            libraries with symlinks\n        \"\"\"\n        c = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n               from conan import ConanFile\n               from conan.tools.files import copy, chdir, mkdir\n               import os\n               class Pkg(ConanFile):\n                   package_type = \"shared-library\"\n                   def package(self):\n                       copy(self, \"*.so*\", src=self.build_folder, dst=self.package_folder)\n                       with chdir(self, os.path.join(self.package_folder, \"lib\")):\n                            os.symlink(src=\"subfolder/libfoo.so.1.0\", dst=\"libfoo.so.1\")\n                            os.symlink(src=\"libfoo.so.1\", dst=\"libfoo.so\")\n               \"\"\")\n        c.save({\"foo/conanfile.py\": conanfile,\n                \"foo/lib/subfolder/libfoo.so.1.0\": \"\",})\n        c.run(\"export-pkg foo/ --name=foo --version=0.1.0\")\n        c.run(f\"install --requires=foo/0.1.0 --deployer=runtime_deploy --deployer-folder=output \"\n              f\"-c:a tools.deployer:symlinks=True\")\n\n        assert os.listdir(os.path.join(c.current_folder, \"output\", \"subfolder\")) == [\"libfoo.so.1.0\"]\n        # INFO: This test requires in Windows to have symlinks enabled, otherwise it will fail\n        if platform.system() != \"Windows\":\n            assert (sorted(os.listdir(os.path.join(c.current_folder, \"output\"))) ==\n                    [\"libfoo.so\", \"libfoo.so.1\", \"subfolder\"])\n            link_so_0 = os.path.join(c.current_folder, \"output\", \"libfoo.so.1\")\n            link_so = os.path.join(c.current_folder, \"output\", \"libfoo.so\")\n            lib = os.path.join(c.current_folder, \"output\", \"subfolder\", \"libfoo.so.1.0\")\n            assert os.path.islink(link_so_0)\n            assert os.path.islink(link_so)\n            assert not os.path.isabs(os.readlink(link_so_0))\n            assert not os.path.isabs(os.readlink(os.path.join(link_so)))\n            assert os.path.realpath(link_so) == os.path.realpath(link_so_0)\n            assert os.path.realpath(link_so_0) == os.path.realpath(lib)\n\n\ndef test_deployer_errors():\n    c = TestClient()\n    c.save({\"conanfile.txt\": \"\",\n            \"mydeploy.py\": \"\",\n            \"mydeploy2.py\": \"nonsense\"})\n    c.run(\"install . --deployer=nonexisting.py\", assert_error=True)\n    assert \"ERROR: Cannot find deployer 'nonexisting.py'\" in c.out\n    c.run(\"install . --deployer=mydeploy.py\", assert_error=True)\n    assert \"ERROR: Deployer does not contain 'deploy()' function\" in c.out\n    c.run(\"install . --deployer=mydeploy2.py\", assert_error=True)\n    # The error message says conanfile, not a big deal still path to file is shown\n    assert \"ERROR: Unable to load conanfile\" in c.out\n\n\ndef test_deploy_relative_paths():\n    c = TestClient()\n    consumer = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        class Consumer(ConanFile):\n            requires = \"pkg/0.1\"\n            settings = \"build_type\"\n            os = \"build_type\"\n            generators = \"CMakeDeps\"\n            def layout(self):\n                self.folders.build = os.path.join(\"some/sub/folders\")\n                self.folders.generators = os.path.join(self.folders.build, \"generators\")\n        \"\"\")\n    deploy = textwrap.dedent(\"\"\"\n        import os, shutil\n        def deploy(graph, output_folder):\n            conanfile = graph.root.conanfile\n            output_folder = os.path.join(conanfile.build_folder, \"installed\")\n            for dep in conanfile.dependencies.values():\n                new_folder = os.path.join(output_folder, dep.ref.name)\n                shutil.copytree(dep.package_folder, new_folder, symlinks=True)\n                dep.set_deploy_folder(new_folder)\n        \"\"\")\n    c.save({\"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\"),\n            \"consumer/conanfile.py\": consumer,\n            \"mydeploy.py\": deploy})\n    c.run(\"create pkg\")\n\n    # If we don't change to another folder, the full_deploy will be recursive and fail\n    c.run(\"install consumer --build=missing --deployer=mydeploy.py\")\n    data = c.load(\"consumer/some/sub/folders/generators/pkg-release-data.cmake\")\n    assert 'set(pkg_PACKAGE_FOLDER_RELEASE \"${CMAKE_CURRENT_LIST_DIR}/../installed/pkg\")' in data\n\n\n@pytest.mark.parametrize(\"absolute_path\", [True, False])\ndef test_deploy_output_absolute(absolute_path):\n    # https://github.com/conan-io/conan/issues/18560\n    c = TestClient()\n    c.save({\"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_package_file(\"myfile.txt\", \"c\"),\n            \"consumer/conanfile.txt\": \"[requires]\\npkg/0.1\"})\n    c.run(\"create pkg\")\n\n    # It is important to use the forward /myout in Windows, this was the breaking input\n    out_path = f\"{c.current_folder}/myout\" if absolute_path else \"myout\"\n    c.run(\"install consumer/conanfile.txt -s arch=x86_64 --deployer=full_deploy -g CMakeDeps \"\n          f'-of=\"{out_path}\"')\n    assert c.load(\"myout/full_deploy/host/pkg/0.1/myfile.txt\") == \"c\"\n    data = c.load(\"myout/pkg-release-x86_64-data.cmake\")\n    assert ('set(pkg_PACKAGE_FOLDER_RELEASE '\n            '\"${CMAKE_CURRENT_LIST_DIR}/full_deploy/host/pkg/0.1\")') in data\n"
  },
  {
    "path": "test/functional/command/test_new.py",
    "content": "import os\nimport platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_conan_new_compiles():\n    # TODO: Maybe add more templates that are not used in the rest of the test suite?\n    tc = TestClient()\n    tc.run(\"new header_lib -d name=hello -d version=1.0 -o=hello\")\n    tc.run(\"new header_lib -d name=bye -d version=1.0 -d requires=hello/1.0 -o=bye\")\n\n    tc.run(\"create hello -tf=\")\n    tc.run(\"create bye\")\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_conan_new_empty():\n    c = TestClient()\n    c.run(\"new\")\n    cmakelists = textwrap.dedent(\"\"\"\n    cmake_minimum_required(VERSION 3.15)\n    project(PackageTest CXX)\n    add_executable(example main.cpp)\n    \"\"\")\n    main = textwrap.dedent(r\"\"\"\n    #include <iostream>\n\n    int main() {\n        std::cout << \"Hello World!\\n\";\n    }\n    \"\"\")\n    c.save({\n        \"CMakeLists.txt\": cmakelists,\n        \"main.cpp\": main,\n    })\n    c.run(\"build\")\n    suffix = \".exe\" if platform.system() == \"Windows\" else \"\"\n    assert os.path.exists(os.path.join(c.current_folder, \"build\", \"Release\", f\"example{suffix}\"))\n"
  },
  {
    "path": "test/functional/conftest.py",
    "content": "import os\nimport shutil\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.sources import gen_function_h, gen_function_cpp\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.fixture(scope=\"session\")\ndef _matrix_client():\n    \"\"\"\n    matrix/1.0, just static, no test_package\n    \"\"\"\n    c = TestClient()\n    c.run(\"new cmake_lib -d name=matrix -d version=1.0\")\n    c.run(\"create . -tf=\")\n    return c\n\n\n@pytest.fixture(scope=\"session\")\ndef _matrix_client_shared(_matrix_client):\n    _matrix_client.run(\"create . -o *:shared=True -tf=\")\n    return _matrix_client\n\n\n@pytest.fixture(scope=\"session\")\ndef _matrix_client_debug(_matrix_client):\n    _matrix_client.run(\"create . -s build_type=Debug -tf=\")\n    return _matrix_client\n\n\n@pytest.fixture()\ndef matrix_client(_matrix_client):\n    c = TestClient()\n    c.cache_folder = os.path.join(temp_folder(), \".conan2\")\n    shutil.copytree(_matrix_client.cache_folder, c.cache_folder)\n    return c\n\n\n@pytest.fixture()\ndef matrix_client_nospace(_matrix_client):\n    c = TestClient(path_with_spaces=False)\n    c.cache_folder = os.path.join(temp_folder(path_with_spaces=False), \".conan2\")\n    shutil.copytree(_matrix_client.cache_folder, c.cache_folder)\n    return c\n\n\n@pytest.fixture()\ndef matrix_client_shared(_matrix_client_shared):\n    c = TestClient()\n    c.cache_folder = os.path.join(temp_folder(), \".conan2\")\n    shutil.copytree(_matrix_client_shared.cache_folder, c.cache_folder)\n    return c\n\n\n@pytest.fixture()\ndef matrix_client_shared_debug(_matrix_client_shared, _matrix_client_debug):\n    c = TestClient()\n    c.cache_folder = os.path.join(temp_folder(), \".conan2\")\n    shutil.copytree(_matrix_client_shared.cache_folder, c.cache_folder)\n    return c\n\n\n@pytest.fixture()\ndef matrix_client_debug(_matrix_client_debug):\n    c = TestClient()\n    c.cache_folder = os.path.join(temp_folder(), \".conan2\")\n    shutil.copytree(_matrix_client_debug.cache_folder, c.cache_folder)\n    return c\n\n\n@pytest.fixture(scope=\"session\")\ndef _transitive_libraries(_matrix_client):\n    \"\"\"\n    engine/1.0->matrix/1.0\n    \"\"\"\n    c = TestClient()\n    c.cache_folder = os.path.join(temp_folder(), \".conan2\")\n    shutil.copytree(_matrix_client.cache_folder, c.cache_folder)\n    c.save({}, clean_first=True)\n    c.run(\"new cmake_lib -d name=engine -d version=1.0 -d requires=matrix/1.0\")\n    # create both static and shared\n    c.run(\"create . -tf=\")\n    c.run(\"create . -o engine/*:shared=True -tf=\")\n    return c\n\n\n@pytest.fixture()\ndef transitive_libraries(_transitive_libraries):\n    c = TestClient()\n    c.cache_folder = os.path.join(temp_folder(), \".conan2\")\n    shutil.copytree(_transitive_libraries.cache_folder, c.cache_folder)\n    return c\n\n\n@pytest.fixture(scope=\"session\")\ndef _matrix_client_components():\n    \"\"\"\n    2 components, different than the package name\n    \"\"\"\n    c = TestClient()\n    headers_h = textwrap.dedent(\"\"\"\n        #include <iostream>\n        #ifndef MY_MATRIX_HEADERS_DEFINE\n        #error \"Fatal error MY_MATRIX_HEADERS_DEFINE not defined\"\n        #endif\n        void headers(){ std::cout << \"Matrix headers: Release!\" << std::endl;\n            #if __cplusplus\n            std::cout << \"  Matrix headers __cplusplus: __cplusplus\" << __cplusplus << std::endl;\n            #endif\n        }\n        \"\"\")\n    vector_h = gen_function_h(name=\"vector\")\n    vector_cpp = gen_function_cpp(name=\"vector\", includes=[\"vector\"])\n    module_h = gen_function_h(name=\"module\")\n    module_cpp = gen_function_cpp(name=\"module\", includes=[\"module\", \"vector\"], calls=[\"vector\"])\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n\n        class Matrix(ConanFile):\n            name = \"matrix\"\n            version = \"1.0\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"CMakeToolchain\"\n            exports_sources = \"src/*\", \"CMakeLists.txt\"\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n\n            def package(self):\n                cmake = CMake(self)\n                cmake.install()\n\n            def package_info(self):\n                self.cpp_info.default_components = [\"vector\", \"module\"]\n\n                self.cpp_info.components[\"headers\"].includedirs = [\"include/headers\"]\n                self.cpp_info.components[\"headers\"].set_property(\"cmake_target_name\", \"MatrixHeaders\")\n                self.cpp_info.components[\"headers\"].defines = [\"MY_MATRIX_HEADERS_DEFINE=1\"]\n                # Few flags to cover that CMakeDeps doesn't crash with them\n                if self.settings.compiler == \"msvc\":\n                    self.cpp_info.components[\"headers\"].cxxflags = [\"/Zc:__cplusplus\"]\n                    self.cpp_info.components[\"headers\"].cflags = [\"/Zc:__cplusplus\"]\n                    self.cpp_info.components[\"headers\"].system_libs = [\"ws2_32\"]\n                else:\n                    self.cpp_info.components[\"headers\"].system_libs = [\"m\"]\n                    # Just to verify CMake don't break\n                    self.cpp_info.sharedlinkflags = [\"-z now\", \"-z relro\"]\n                    self.cpp_info.exelinkflags = [\"-z now\", \"-z relro\"]\n\n                self.cpp_info.components[\"vector\"].libs = [\"vector\"]\n                self.cpp_info.components[\"vector\"].includedirs = [\"include\"]\n                self.cpp_info.components[\"vector\"].libdirs = [\"lib\"]\n\n                self.cpp_info.components[\"module\"].libs = [\"module\"]\n                self.cpp_info.components[\"module\"].includedirs = [\"include\"]\n                self.cpp_info.components[\"module\"].libdirs = [\"lib\"]\n                self.cpp_info.components[\"module\"].requires = [\"vector\"]\n          \"\"\")\n\n    cmakelists = textwrap.dedent(\"\"\"\n       set(CMAKE_CXX_COMPILER_WORKS 1)\n       set(CMAKE_CXX_ABI_COMPILED 1)\n       cmake_minimum_required(VERSION 3.15)\n       project(matrix CXX)\n\n       add_library(vector src/vector.cpp)\n       add_library(module src/module.cpp)\n       add_library(headers INTERFACE)\n       target_link_libraries(module PRIVATE vector)\n\n       set_target_properties(headers PROPERTIES PUBLIC_HEADER \"src/headers.h\")\n       set_target_properties(module PROPERTIES PUBLIC_HEADER \"src/module.h\")\n       set_target_properties(vector PROPERTIES PUBLIC_HEADER \"src/vector.h\")\n       install(TARGETS vector module)\n       install(TARGETS headers PUBLIC_HEADER DESTINATION include/headers)\n       \"\"\")\n    c.save({\"src/headers.h\": headers_h,\n            \"src/vector.h\": vector_h,\n            \"src/vector.cpp\": vector_cpp,\n            \"src/module.h\": module_h,\n            \"src/module.cpp\": module_cpp,\n            \"CMakeLists.txt\": cmakelists,\n            \"conanfile.py\": conanfile})\n    c.run(\"create .\")\n    return c\n\n\n@pytest.fixture()\ndef matrix_client_components(_matrix_client_components):\n    c = TestClient()\n    c.cache_folder = os.path.join(temp_folder(), \".conan2\")\n    shutil.copytree(_matrix_client_components.cache_folder, c.cache_folder)\n    return c\n\n\n@pytest.fixture(scope=\"session\")\ndef _matrix_c_interface_client():\n    c = TestClient()\n    matrix_h = textwrap.dedent(\"\"\"\\\n        #pragma once\n        #ifdef __cplusplus\n        extern \"C\" {\n        #endif\n            void matrix();\n        #ifdef __cplusplus\n        }\n        #endif\n        \"\"\")\n    matrix_cpp = textwrap.dedent(\"\"\"\\\n        #include \"matrix.h\"\n        #include <iostream>\n        #include <string>\n        void matrix(){\n            std::cout<< std::string(\"Hello Matrix!\") <<std::endl;\n        }\n        \"\"\")\n    # Having here the config.cmake code to be able to manually check what CMake generates\n    cmake = textwrap.dedent(\"\"\"\\\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.15)\n        project(matrix C CXX)\n        add_library(matrix STATIC src/matrix.cpp)\n        target_include_directories(matrix PUBLIC\n          $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>\n          $<INSTALL_INTERFACE:include>\n        )\n        set_target_properties(matrix PROPERTIES PUBLIC_HEADER \"include/matrix.h\")\n        install(TARGETS matrix EXPORT matrixConfig)\n        export(TARGETS matrix\n            NAMESPACE matrix::\n            FILE \"${CMAKE_CURRENT_BINARY_DIR}/matrixConfig.cmake\"\n        )\n        install(EXPORT matrixConfig\n            DESTINATION \"matrix/cmake\"\n            NAMESPACE matrix::\n        )\n        \"\"\")\n    conanfile = textwrap.dedent(\"\"\"\\\n        from conan import ConanFile\n        from conan.tools.cmake import CMake, cmake_layout\n        class Recipe(ConanFile):\n            name = \"matrix\"\n            version = \"0.1\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            package_type = \"static-library\"\n            generators = \"CMakeToolchain\"\n            exports_sources = \"CMakeLists.txt\", \"src/*\", \"include/*\"\n            languages = \"C++\"\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n            def layout(self):\n                cmake_layout(self)\n            def package(self):\n                cmake = CMake(self)\n                cmake.install()\n            def package_info(self):\n                self.cpp_info.libs = [\"matrix\"]\n        \"\"\")\n    c.save({\"include/matrix.h\": matrix_h,\n            \"src/matrix.cpp\": matrix_cpp,\n            \"conanfile.py\": conanfile,\n            \"CMakeLists.txt\": cmake})\n    c.run(\"create .\")\n    return c\n\n\n@pytest.fixture()\ndef matrix_c_interface_client(_matrix_c_interface_client):\n    c = TestClient()\n    c.cache_folder = os.path.join(temp_folder(), \".conan2\")\n    shutil.copytree(_matrix_c_interface_client.cache_folder, c.cache_folder)\n    return c\n"
  },
  {
    "path": "test/functional/layout/__init__.py",
    "content": ""
  },
  {
    "path": "test/functional/layout/test_build_system_layout_helpers.py",
    "content": "import os\nimport platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import save, load\n\n\n@pytest.fixture\ndef conanfile():\n    conanfile = str(GenConanfile()\n                    .with_import(\"import os\")\n                    .with_setting(\"build_type\").with_setting(\"arch\")\n                    .with_import(\"from conan.tools.microsoft import vs_layout\")\n                    .with_import(\"from conan.tools.files import save, copy\"))\n\n    conanfile += \"\"\"\n    def source(self):\n        save(self, \"include/myheader.h\", \"\")\n\n    def build(self):\n        save(self, \"{libpath}/mylib.lib\", \"\")\n\n    def layout(self):\n        vs_layout(self)\n\n    def package(self):\n        copy(self, \"*\", self.source_folder, self.package_folder)\n        copy(self, \"*\", self.build_folder, os.path.join(self.package_folder, \"lib\"), keep_path=False)\n    \"\"\"\n    return conanfile\n\n\nsubfolders_arch = {\"armv7\": \"ARM\", \"armv8\": \"ARM64\", \"x86\": None, \"x86_64\": \"x64\"}\n\n\n@pytest.mark.parametrize(\"arch\", [\"x86_64\", \"x86\", \"armv7\", \"armv8\"])\n@pytest.mark.parametrize(\"build_type\", [\"Debug\", \"Release\"])\ndef test_layout_in_cache(conanfile, build_type, arch):\n    \"\"\"The layout in the cache is used too, always relative to the \"base\" folders that the cache\n    requires. But by the default, the \"package\" is not followed\n    \"\"\"\n    client = TestClient()\n\n    libarch = subfolders_arch.get(arch)\n    libpath = \"{}{}\".format(libarch + \"/\" if libarch else \"\", build_type)\n\n    client.save({\"conanfile.py\": conanfile.format(libpath=libpath)})\n    client.run(f\"create . --name=lib --version=1.0 -s build_type={build_type} -s arch={arch}\")\n\n    layout = client.created_layout()\n    bf = layout.build()\n    pf = layout.package()\n\n    # Check the build folder\n    assert os.path.exists(os.path.join(os.path.join(bf, libpath), \"mylib.lib\"))\n\n    # Check the package folder\n    assert os.path.exists(os.path.join(pf, \"lib/mylib.lib\"))\n    assert os.path.exists(os.path.join(pf, \"include\", \"myheader.h\"))\n\n\n@pytest.mark.parametrize(\"arch\", [\"x86_64\", \"x86\", \"armv7\", \"armv8\"])\n@pytest.mark.parametrize(\"build_type\", [\"Debug\", \"Release\"])\ndef test_layout_with_local_methods(conanfile, build_type, arch):\n    \"\"\"The layout in the cache is used too, always relative to the \"base\" folders that the cache\n        requires. But by the default, the \"package\" is not followed\n        \"\"\"\n    client = TestClient()\n    libarch = subfolders_arch.get(arch)\n    libpath = \"{}{}\".format(libarch + \"/\" if libarch else \"\", build_type)\n    client.save({\"conanfile.py\": conanfile.format(libpath=libpath)})\n    client.run(\"install . --name=lib --version=1.0 -s build_type={} -s arch={}\".format(build_type, arch))\n    client.run(\"source .\")\n    # Check the source folder (release)\n    assert os.path.exists(os.path.join(client.current_folder, \"include\", \"myheader.h\"))\n    client.run(\"build . --name=lib --version=1.0 -s build_type={} -s arch={}\".format(build_type,\n                                                                                     arch))\n    # Check the build folder (release)\n    assert os.path.exists(os.path.join(os.path.join(client.current_folder, libpath), \"mylib.lib\"))\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Removing msvc compiler\")\ndef test_error_no_msvc():\n    # https://github.com/conan-io/conan/issues/9953\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import cmake_layout\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            def layout(self):\n                cmake_layout(self)\n        \"\"\")\n    settings_yml = textwrap.dedent(\"\"\"\n        os: [Windows]\n        os_build: [Windows]\n        arch_build: [x86_64]\n        compiler:\n            gcc:\n                version: [\"8\"]\n        build_type: [Release]\n        arch: [x86_64]\n        \"\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    save(client.paths.settings_path, settings_yml)\n    client.run('install . -s os=Windows -s build_type=Release -s arch=x86_64 '\n               '-s compiler=gcc -s compiler.version=8 '\n               '-s:b os=Windows -s:b build_type=Release -s:b arch=x86_64 '\n               '-s:b compiler=gcc -s:b compiler.version=8')\n    assert \"Installing\" in client.out\n\n\ndef test_error_no_build_type():\n    # https://github.com/conan-io/conan/issues/9953\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import cmake_layout\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"arch\"\n            def layout(self):\n                cmake_layout(self)\n        \"\"\")\n\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run('install .',  assert_error=True)\n    assert \" 'build_type' setting not defined, it is necessary for cmake_layout()\" in client.out\n\n\ndef test_cmake_layout_external_sources():\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.cmake import cmake_layout\n        from conan.tools.files import save, copy, load\n        class Pkg(ConanFile):\n            settings = \"os\", \"build_type\"\n            exports_sources = \"exported.txt\"\n\n            def layout(self):\n                cmake_layout(self, src_folder=\"src\")\n\n            def generate(self):\n                save(self, \"generate.txt\", \"generate\")\n\n            def source(self):\n                save(self, \"source.txt\", \"foo\")\n\n            def build(self):\n                c1 = load(self, os.path.join(self.source_folder, \"source.txt\"))\n                c2 = load(self, os.path.join(self.source_folder, \"..\", \"exported.txt\"))\n                save(self, \"build.txt\", c1 + c2)\n\n            def package(self):\n                copy(self, \"build.txt\", self.build_folder, os.path.join(self.package_folder, \"res\"))\n        \"\"\")\n\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile, \"exported.txt\": \"exported_contents\"})\n    client.run(\"create . --name=foo --version=1.0 -s os=Linux\")\n    assert \"Packaged 1 '.txt' file: build.txt\" in client.out\n\n    # Local flow\n    client.run(\"install . --name=foo --version=1.0 -s os=Linux\")\n    assert os.path.exists(os.path.join(client.current_folder,\n                                       \"build\", \"Release\", \"generators\", \"generate.txt\"))\n    client.run(\"source .\")\n    assert os.path.exists(os.path.join(client.current_folder, \"src\", \"source.txt\"))\n    client.run(\"build .\")\n    contents = load(os.path.join(client.current_folder, \"build\", \"Release\", \"build.txt\"))\n    assert contents == \"fooexported_contents\"\n    client.run(\"export-pkg . --name=foo --version=1.0\")\n    assert \"Packaged 1 '.txt' file: build.txt\" in client.out\n\n\n@pytest.mark.parametrize(\"with_build_type\", [True, False])\ndef test_basic_layout_external_sources(with_build_type):\n    conanfile = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.layout import basic_layout\n            from conan.tools.files import save, load, copy\n            class Pkg(ConanFile):\n                settings = \"os\", \"compiler\", \"arch\"{}\n                exports_sources = \"exported.txt\"\n\n                def layout(self):\n                    basic_layout(self, src_folder=\"src\")\n\n                def generate(self):\n                    save(self, \"generate.txt\", \"generate\")\n\n                def source(self):\n                    save(self, \"source.txt\", \"foo\")\n\n                def build(self):\n                    c1 = load(self, os.path.join(self.source_folder, \"source.txt\"))\n                    c2 = load(self, os.path.join(self.source_folder, \"..\", \"exported.txt\"))\n                    save(self, \"build.txt\", c1 + c2)\n\n                def package(self):\n                    copy(self, \"build.txt\", self.build_folder, os.path.join(self.package_folder, \"res\"))\n            \"\"\")\n    if with_build_type:\n        conanfile = conanfile.format(', \"build_type\"')\n    else:\n        conanfile = conanfile.format(\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile, \"exported.txt\": \"exported_contents\"})\n    client.run(\"create . --name=foo --version=1.0 -s os=Linux\")\n    assert \"Packaged 1 '.txt' file: build.txt\" in client.out\n\n    # Local flow\n    build_folder = \"build-release\" if with_build_type else \"build\"\n    client.run(\"install . --name=foo --version=1.0 -s os=Linux\")\n    assert os.path.exists(os.path.join(client.current_folder, build_folder, \"conan\", \"generate.txt\"))\n    client.run(\"source .\")\n    assert os.path.exists(os.path.join(client.current_folder, \"src\", \"source.txt\"))\n    client.run(\"build .\")\n    contents = load(os.path.join(client.current_folder, build_folder, \"build.txt\"))\n    assert contents == \"fooexported_contents\"\n    client.run(\"export-pkg . --name=foo --version=1.0\")\n    assert \"Packaged 1 '.txt' file: build.txt\" in client.out\n\n\n@pytest.mark.parametrize(\"with_build_type\", [True, False])\ndef test_basic_layout_no_external_sources(with_build_type):\n    conanfile = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.layout import basic_layout\n            from conan.tools.files import save, load, copy\n            class Pkg(ConanFile):\n                settings = \"os\", \"compiler\", \"arch\"{}\n                exports_sources = \"exported.txt\"\n\n                def layout(self):\n                    basic_layout(self)\n\n                def generate(self):\n                    save(self, \"generate.txt\", \"generate\")\n\n                def build(self):\n                    contents = load(self, os.path.join(self.source_folder, \"exported.txt\"))\n                    save(self, \"build.txt\", contents)\n\n                def package(self):\n                    copy(self, \"build.txt\", self.build_folder, os.path.join(self.package_folder,\n                                                                            \"res\"))\n            \"\"\")\n    if with_build_type:\n        conanfile = conanfile.format(', \"build_type\"')\n    else:\n        conanfile = conanfile.format(\"\")\n\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile, \"exported.txt\": \"exported_contents\"})\n    client.run(\"create . --name=foo --version=1.0 -s os=Linux\")\n    assert \"Packaged 1 '.txt' file: build.txt\" in client.out\n\n    # Local flow\n    client.run(\"install . --name=foo --version=1.0 -s os=Linux\")\n\n    build_folder = \"build-release\" if with_build_type else \"build\"\n    assert os.path.exists(os.path.join(client.current_folder, build_folder, \"conan\", \"generate.txt\"))\n\n    client.run(\"build .\")\n    contents = load(os.path.join(client.current_folder, build_folder, \"build.txt\"))\n    assert contents == \"exported_contents\"\n    client.run(\"export-pkg . --name=foo --version=1.0\")\n    assert \"Packaged 1 '.txt' file: build.txt\" in client.out\n\n\ndef test_cmake_layout_custom_build_folder():\n    # https://github.com/conan-io/conan/issues/11838\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import cmake_layout\n        class Pkg(ConanFile):\n            settings = \"os\", \"build_type\"\n            generators = \"CMakeToolchain\"\n            def layout(self):\n                cmake_layout(self, src_folder=\"src\", build_folder=\"mybuild\")\n        \"\"\")\n\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"install .\")\n    assert os.path.exists(os.path.join(client.current_folder,\n                                       \"mybuild/Release/generators/conan_toolchain.cmake\"))\n"
  },
  {
    "path": "test/functional/layout/test_editable_cmake.py",
    "content": "import os\nimport platform\n\nimport pytest\n\nfrom conan.test.utils.mocks import ConanFileMock\nfrom conan.tools.env.environment import environment_wrap_command\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient\n\n\ndef editable_cmake(generator, build_folder=None):\n    c = TestClient()\n    if generator is not None:\n        c.save_home({\"global.conf\": \"tools.cmake.cmaketoolchain:generator={}\".format(generator)})\n    with c.chdir(\"dep\"):\n        c.run(\"new cmake_lib -d name=dep -d version=0.1\")\n    with c.chdir(\"pkg\"):\n        c.run(\"new cmake_exe -d name=pkg -d version=0.1 -d requires=dep/0.1\")\n\n    output_folder = '--output-folder=\"{}\"'.format(build_folder) if build_folder else \"\"\n\n    def build_dep():\n        c.run(\"build . {}\".format(output_folder))\n        c.run(\"build . -s build_type=Debug {}\".format(output_folder))\n\n    with c.chdir(\"dep\"):\n        c.run(\"editable add . {}\".format(output_folder))\n        build_dep()\n\n    def build_pkg(msg, build_editable=False):\n        build_editable = \"--build=editable\" if build_editable else \"\"\n        c.run(f\"build . {build_editable}\")\n        folder = os.path.join(\"build\", \"Release\")\n        c.run_command(os.sep.join([\".\", folder, \"pkg\"]))\n        assert \"pkg/0.1: Hello World Release!\" in c.out\n        assert \"{}: Hello World Release!\".format(msg) in c.out\n        c.run(f\"build . -s build_type=Debug {build_editable}\")\n        folder = os.path.join(\"build\", \"Debug\")\n        c.run_command(os.sep.join([\".\", folder, \"pkg\"]))\n        assert \"pkg/0.1: Hello World Debug!\" in c.out\n        assert \"{}: Hello World Debug!\".format(msg) in c.out\n\n    with c.chdir(\"pkg\"):\n        c.run(\"install . \")\n        c.run(\"install . -s build_type=Debug\")\n        build_pkg(\"dep/0.1\")\n\n    # Do a source change in the editable!\n    with c.chdir(\"dep\"):\n        f = c.load(\"src/dep.cpp\")\n        f = f.replace(\"dep/0.1\", \"SUPERDEP/0.1\")\n        c.save({\"src/dep.cpp\": f})\n        build_dep()\n\n    with c.chdir(\"pkg\"):\n        build_pkg(\"SUPERDEP/0.1\")\n\n    # Do a source change in the editable, but do NOT build yet\n    with c.chdir(\"dep\"):\n        f = c.load(\"src/dep.cpp\")\n        f = f.replace(\"SUPERDEP/0.1\", \"MEGADEP/0.1\")\n        c.save({\"src/dep.cpp\": f})\n    # And build with --build=editable\n    with c.chdir(\"pkg\"):\n        build_pkg(\"MEGADEP/0.1\", build_editable=True)\n\n    # Check that create is still possible\n    c.run(\"editable remove dep\")\n    c.run(\"create dep\")\n    c.run(\"create pkg\")\n    # print(c.out)\n    assert \"pkg/0.1: Created package\" in c.out\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Only windows\")\n@pytest.mark.parametrize(\"generator\", [None, \"MinGW Makefiles\"])\n@pytest.mark.tool(\"mingw64\")\ndef test_editable_cmake_windows(generator):\n    editable_cmake(generator)\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_editable_cmake_windows_folders():\n    build_folder = temp_folder()\n    editable_cmake(generator=None, build_folder=build_folder)\n\n\n@pytest.mark.skipif(platform.system() != \"Linux\", reason=\"Only linux\")\n@pytest.mark.parametrize(\"generator\", [None, \"Ninja\", \"Ninja Multi-Config\"])\n@pytest.mark.tool(\"cmake\", \"3.19\")\ndef test_editable_cmake_linux(generator):\n    editable_cmake(generator)\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Requires Macos\")\n@pytest.mark.parametrize(\"generator\", [None, \"Ninja\", \"Xcode\"])\n@pytest.mark.tool(\"cmake\", \"3.23\")\ndef test_editable_cmake_osx(generator):\n    editable_cmake(generator)\n\n\ndef editable_cmake_exe(generator):\n    c = TestClient()\n    if generator is not None:\n        c.save_home({\"global.conf\": \"tools.cmake.cmaketoolchain:generator={}\".format(generator)})\n\n    c.run(\"new cmake_exe -d name=dep -d version=0.1 -o=dep\")\n\n    def build_dep():\n        c.run(\"build .\")\n        c.run(\"build . -s build_type=Debug\")\n\n    with c.chdir(\"dep\"):\n        c.run(\"editable add .\")\n        build_dep()\n\n    def run_pkg(msg):\n        host_arch = c.get_default_host_profile().settings['arch']\n        cmd_release = environment_wrap_command(ConanFileMock(), f\"conanrunenv-release-{host_arch}\",\n                                               c.current_folder, \"dep\")\n        c.run_command(cmd_release)\n        assert \"{}: Hello World Release!\".format(msg) in c.out\n        cmd_release = environment_wrap_command(ConanFileMock(), f\"conanrunenv-debug-{host_arch}\",\n                                               c.current_folder, \"dep\")\n        c.run_command(cmd_release)\n        assert \"{}: Hello World Debug!\".format(msg) in c.out\n\n    with c.chdir(\"pkg\"):\n        c.run(\"install --requires=dep/0.1\")\n        c.run(\"install --requires=dep/0.1 -s build_type=Debug\")\n        run_pkg(\"dep/0.1\")\n\n    # Do a source change in the editable!\n    with c.chdir(\"dep\"):\n        dep = c.load(\"src/dep.cpp\")\n        dep = dep.replace(\"dep/0.1\", \"SUPERDEP/0.1\")\n        c.save({\"src/dep.cpp\": dep})\n        build_dep()\n\n    with c.chdir(\"pkg\"):\n        run_pkg(\"SUPERDEP/0.1\")\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Only windows\")\n@pytest.mark.parametrize(\"generator\", [None, \"MinGW Makefiles\"])\n@pytest.mark.tool(\"mingw64\")\ndef test_editable_cmake_windows_exe(generator):\n    editable_cmake_exe(generator)\n\n\n@pytest.mark.skipif(platform.system() != \"Linux\", reason=\"Only linux\")\n@pytest.mark.parametrize(\"generator\", [None, \"Ninja\", \"Ninja Multi-Config\"])\n@pytest.mark.tool(\"cmake\", \"3.19\")\ndef test_editable_cmake_linux_exe(generator):\n    editable_cmake_exe(generator)\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Requires Macos\")\n@pytest.mark.parametrize(\"generator\", [None, \"Ninja\", \"Xcode\"])\n@pytest.mark.tool(\"cmake\", \"3.23\")\ndef test_editable_cmake_osx_exe(generator):\n    editable_cmake_exe(generator)\n"
  },
  {
    "path": "test/functional/layout/test_editable_cmake_components.py",
    "content": "import os\nimport shutil\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.sources import gen_function_cpp, gen_function_h\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_editable_cmake_components():\n    hello_h = gen_function_h(name=\"hello\")\n    hello_cpp = gen_function_cpp(name=\"hello\", includes=[\"hello\"])\n    bye_h = gen_function_h(name=\"bye\")\n    bye_cpp = gen_function_cpp(name=\"bye\", includes=[\"bye\"])\n\n    conanfile_greetings = textwrap.dedent(\"\"\"\n        from os.path import join\n        from conan import ConanFile\n        from conan.tools.cmake import CMake, cmake_layout\n        from conan.tools.files import copy\n\n        class GreetingsConan(ConanFile):\n            name = \"greetings\"\n            version = \"0.1\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"CMakeDeps\", \"CMakeToolchain\"\n            exports_sources = \"src/*\"\n\n            def build(self):\n               cmake = CMake(self)\n               cmake.configure()\n               cmake.build()\n\n            def layout(self):\n                cmake_layout(self, src_folder=\"src\")\n                self.cpp.source.components[\"hello\"].includedirs = [\".\"]\n                self.cpp.source.components[\"bye\"].includedirs = [\".\"]\n                bt = \".\" if self.settings.os != \"Windows\" else str(self.settings.build_type)\n                self.cpp.build.components[\"hello\"].libdirs = [bt]\n                self.cpp.build.components[\"bye\"].libdirs = [bt]\n\n            def package(self):\n               copy(self, \"*.h\", src=self.source_folder,\n                                 dst=join(self.package_folder, \"include\"))\n               copy(self, \"*.lib\", src=self.build_folder,\n                                   dst=join(self.package_folder, \"lib\"), keep_path=False)\n               copy(self, \"*.a\", src=self.build_folder,\n                                 dst=join(self.package_folder, \"lib\"), keep_path=False)\n\n            def package_info(self):\n               self.cpp_info.components[\"hello\"].libs = [\"hello\"]\n               self.cpp_info.components[\"bye\"].libs = [\"bye\"]\n\n               self.cpp_info.set_property(\"cmake_file_name\", \"MYG\")\n               self.cpp_info.set_property(\"cmake_target_name\", \"MyGreetings::MyGreetings\")\n               self.cpp_info.components[\"hello\"].set_property(\"cmake_target_name\", \"MyGreetings::MyHello\")\n               self.cpp_info.components[\"bye\"].set_property(\"cmake_target_name\", \"MyGreetings::MyBye\")\n           \"\"\")\n\n    cmakelists_greetings = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.0)\n        project(greetings CXX)\n\n        add_library(hello hello.cpp)\n        target_include_directories(hello PRIVATE hello)\n        add_library(bye bye.cpp)\n        target_include_directories(bye PRIVATE bye)\n        \"\"\")\n\n    app_conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.cmake import CMake, cmake_layout\n\n        class GreetingsTestConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"CMakeDeps\", \"CMakeToolchain\"\n\n            def requirements(self):\n                self.requires(\"greetings/0.1\")\n\n            def layout(self):\n                cmake_layout(self)\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n                self.run(os.path.join(self.cpp.build.bindirs[0], \"example\"))\n                self.run(os.path.join(self.cpp.build.bindirs[0], \"example2\"))\n            \"\"\")\n    app_cpp = gen_function_cpp(name=\"main\", includes=[\"hello/hello\", \"bye/bye\"],\n                               calls=[\"hello\", \"bye\"])\n    app_cpp2 = gen_function_cpp(name=\"main\", includes=[\"hello/hello\"], calls=[\"hello\"])\n\n    app_cmakelists = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.0)\n        project(PackageTest CXX)\n\n        find_package(MYG)\n\n        add_executable(example example.cpp)\n        target_link_libraries(example MyGreetings::MyGreetings)\n\n        add_executable(example2 example2.cpp)\n        target_link_libraries(example2 MyGreetings::MyHello)\n        \"\"\")\n\n    client = TestClient()\n    client.save({\"greetings/conanfile.py\": conanfile_greetings,\n                 \"greetings/src/CMakeLists.txt\": cmakelists_greetings,\n                 \"greetings/src/hello/hello.h\": hello_h,\n                 \"greetings/src/hello.cpp\": hello_cpp,\n                 \"greetings/src/bye/bye.h\": bye_h,\n                 \"greetings/src/bye.cpp\": bye_cpp,\n                 \"app/conanfile.py\": app_conanfile,\n                 \"app/example.cpp\": app_cpp,\n                 \"app/example2.cpp\": app_cpp2,\n                 \"app/CMakeLists.txt\": app_cmakelists})\n    client.run(\"create greetings\")\n    client.run(\"build app\")\n    assert \"hello: Release!\" in client.out\n    assert \"bye: Release!\" in client.out\n\n    client.run(\"remove * -c\")\n    shutil.rmtree(os.path.join(client.current_folder, \"app\", \"build\"))\n    client.run(\"editable add greetings\")\n    client.run(\"build greetings\")\n    client.run(\"build app\")\n    assert str(client.out).count(\"hello: Release!\") == 2\n    assert str(client.out).count(\"bye: Release!\") == 1\n\n    # Do a modification to one component, to verify it is used correctly\n    bye_cpp = gen_function_cpp(name=\"bye\", includes=[\"bye\"], msg=\"Adios\")\n    client.save({\"greetings/src/bye.cpp\": bye_cpp})\n    client.run(\"build greetings\")\n    client.run(\"build app\")\n    assert str(client.out).count(\"hello: Release!\") == 2\n    assert str(client.out).count(\"Adios: Release!\") == 1\n"
  },
  {
    "path": "test/functional/layout/test_editable_msbuild.py",
    "content": "import os\nimport platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Only windows\")\ndef test_editable_msbuild():\n    c = TestClient()\n    c.run(\"new msbuild_lib -d name=dep -d version=0.1 -o dep\")\n    c.run(\"new cmake_exe -d name=pkg -d version=0.1 -d requires=dep/0.1 -o pkg\")\n\n    build_folder = \"\"\n    output_folder = '--output-folder=\"{}\"'.format(build_folder) if build_folder else \"\"\n    build_folder = '--build-folder=\"{}\"'.format(build_folder) if build_folder else \"\"\n\n    def build_dep():\n        c.run(\"install . {}\".format(output_folder))\n        c.run(\"build . {}\".format(build_folder))\n        c.run(\"install . -s build_type=Debug {}\".format(output_folder))\n        c.run(\"build . -s build_type=Debug {}\".format(build_folder))\n\n    with c.chdir(\"dep\"):\n        c.run(\"editable add . {}\".format(output_folder))\n        build_dep()\n\n    def build_pkg(msg):\n        c.run(\"build . \")\n        folder = os.path.join(\"build\", \"Release\")\n        c.run_command(os.sep.join([\".\", folder, \"pkg\"]))\n        assert \"pkg/0.1: Hello World Release!\" in c.out\n        assert \"{}: Hello World Release!\".format(msg) in c.out\n        c.run(\"build . -s build_type=Debug\")\n        folder = os.path.join(\"build\", \"Debug\")\n        c.run_command(os.sep.join([\".\", folder, \"pkg\"]))\n        assert \"pkg/0.1: Hello World Debug!\" in c.out\n        assert \"{}: Hello World Debug!\".format(msg) in c.out\n\n    with c.chdir(\"pkg\"):\n        c.run(\"install . \")\n        c.run(\"install . -s build_type=Debug\")\n        build_pkg(\"dep/0.1\")\n\n    # Do a source change in the editable!\n    with c.chdir(\"dep\"):\n        dep_cpp = c.load(\"src/dep.cpp\")\n        dep_cpp = dep_cpp.replace(\"dep/\", \"SUPERDEP/\")\n        c.save({\"src/dep.cpp\": dep_cpp})\n        build_dep()\n\n    with c.chdir(\"pkg\"):\n        build_pkg(\"SUPERDEP/0.1\")\n\n    # Check that create is still possible\n    c.run(\"editable remove dep\")\n    c.run(\"create dep\")\n    c.run(\"create pkg\")\n    # print(c.out)\n    assert \"pkg/0.1: Created package\" in c.out\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Only for windows\")\ndef test_editable_msbuilddeps():\n    # https://github.com/conan-io/conan/issues/12521\n    c = TestClient()\n    dep = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Dep(ConanFile):\n            name = \"dep\"\n            version = \"0.1\"\n            def layout(self):\n                pass\n            \"\"\")\n    c.save({\"dep/conanfile.py\": dep,\n            \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_settings(\"build_type\", \"arch\")\n                                                          .with_requires(\"dep/0.1\")\n                                                          .with_generator(\"MSBuildDeps\")})\n    c.run(\"editable add dep\")\n    c.run(\"install pkg\")\n    # It doesn't crash anymore\n    assert \"dep/0.1:da39a3ee5e6b4b0d3255bfef95601890afd80709 - Editable\" in c.out\n"
  },
  {
    "path": "test/functional/layout/test_exports_sources.py",
    "content": "import textwrap\n\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_exports_sources_patch():\n    \"\"\"\n    tests that using ``self.export_sources_folder`` we can access both from the source() and build()\n    methods the folder where the exported sources (patches, new build files) are. And maintain\n    a local flow without exports copies\n    \"\"\"\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        import os, shutil\n        from conan import ConanFile\n        from conan.tools.files import load, copy, save\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n\n            exports_sources = \"CMakeLists.txt\", \"patches*\"\n\n            def layout(self):\n                self.folders.source = \"src\"\n\n            def source(self):\n                save(self, \"CMakeLists.txt\", \"old, bad\") # EMULATE A DOWNLOAD!\n                base_source = self.export_sources_folder\n                mypatch = load(self, os.path.join(base_source, \"patches/mypatch\"))\n                self.output.info(\"MYPATCH-SOURCE {}\".format(mypatch))\n                shutil.copy(os.path.join(base_source, \"CMakeLists.txt\"),\n                            \"CMakeLists.txt\")\n\n            def build(self):\n                path = os.path.join(self.source_folder, \"CMakeLists.txt\")\n                cmake = load(self, path)\n                self.output.info(\"MYCMAKE-BUILD: {}\".format(cmake))\n                path = os.path.join(self.export_sources_folder, \"patches/mypatch\")\n                cmake = load(self, path)\n                self.output.info(\"MYPATCH-BUILD: {}\".format(cmake))\n            \"\"\")\n    c.save({\"conanfile.py\": conanfile,\n            \"patches/mypatch\": \"mypatch!\",\n            \"CMakeLists.txt\": \"mycmake!\"})\n    c.run(\"create .\")\n    assert \"pkg/0.1: MYPATCH-SOURCE mypatch!\" in c.out\n    assert \"pkg/0.1: MYCMAKE-BUILD: mycmake!\" in c.out\n    assert \"pkg/0.1: MYPATCH-BUILD: mypatch!\" in c.out\n\n    # Local flow\n    c.run(\"install .\")\n    c.run(\"source .\")\n    assert \"conanfile.py (pkg/0.1): MYPATCH-SOURCE mypatch!\" in c.out\n    assert c.load(\"CMakeLists.txt\") == \"mycmake!\"  # My original one\n    assert c.load(\"src/CMakeLists.txt\") == \"mycmake!\"  # The one patched by \"source()\"\n    c.run(\"build .\")\n    assert \"conanfile.py (pkg/0.1): MYCMAKE-BUILD: mycmake!\" in c.out\n    assert \"conanfile.py (pkg/0.1): MYPATCH-BUILD: mypatch!\" in c.out\n"
  },
  {
    "path": "test/functional/layout/test_in_cache.py",
    "content": "import os\nimport textwrap\n\nimport pytest\n\nfrom conan.api.model import PkgReference\nfrom conan.api.model import RecipeReference\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient, NO_SETTINGS_PACKAGE_ID\n\n\n@pytest.fixture\ndef conanfile():\n    conan_file = str(GenConanfile()\n                     .with_import(\"import os\")\n                     .with_import(\"from conan.tools.files import copy, save\").\n                     with_require(\"base/1.0\"))\n\n    conan_file += \"\"\"\n    no_copy_sources = True\n\n    def layout(self):\n        self.folders.source = \"my_sources\"\n        self.folders.build = \"my_build\"\n\n    def source(self):\n        self.output.warning(\"Source folder: {}\".format(self.source_folder))\n        # The layout describes where the sources are, not force them to be there\n        save(self, \"source.h\", \"foo\")\n\n    def build(self):\n        self.output.warning(\"Build folder: {}\".format(self.build_folder))\n        save(self, \"build.lib\", \"bar\")\n\n    def package(self):\n        self.output.warning(\"Package folder: {}\".format(self.package_folder))\n        save(self, os.path.join(self.package_folder, \"LICENSE\"), \"bar\")\n        copy(self, \"*.h\", self.source_folder, os.path.join(self.package_folder, \"include\"))\n        copy(self, \"*.lib\", self.build_folder, os.path.join(self.package_folder, \"lib\"))\n\n    def package_info(self):\n        # This will be easier when the layout declares also the includedirs etc\n        self.cpp_info.includedirs = [\"include\"]\n        self.cpp_info.libdirs = [\"lib\"]\n    \"\"\"\n    return conan_file\n\n\ndef test_create_test_package_no_layout():\n    \"\"\"The test package using the new generators work (having the generated files in the build\n    folder)\"\"\"\n    client = TestClient()\n    conanfile_test = textwrap.dedent(\"\"\"\n        import os\n\n        from conan import ConanFile, tools\n\n        class HelloTestConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"CMakeDeps\", \"CMakeToolchain\"\n\n            def requirements(self):\n                self.requires(self.tested_reference_str)\n\n            def build(self):\n                assert os.path.exists(\"conan_toolchain.cmake\")\n                self.output.warning(\"hey! building\")\n                self.output.warning(os.getcwd())\n\n            def test(self):\n                self.output.warning(\"hey! testing\")\n    \"\"\")\n    client.save({\"conanfile.py\": GenConanfile(), \"test_package/conanfile.py\": conanfile_test})\n    client.run(\"create . --name=lib --version=1.0\")\n    assert \"hey! building\" in client.out\n    assert \"hey! testing\" in client.out\n\n\ndef test_create_test_package_with_layout():\n    \"\"\"The test package using the new generators work (having the generated files in the build\n    folder)\"\"\"\n    client = TestClient()\n    conanfile_test = textwrap.dedent(\"\"\"\n        import os\n\n        from conan import ConanFile, tools\n        from conan.tools.cmake import CMakeToolchain, CMake, CMakeDeps\n\n        class HelloTestConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n            def requirements(self):\n                self.requires(self.tested_reference_str)\n\n            def generate(self):\n                deps = CMakeDeps(self)\n                deps.generate()\n                tc = CMakeToolchain(self)\n                tc.generate()\n\n            def layout(self):\n                self.folders.generators = \"my_generators\"\n\n            def build(self):\n                assert os.path.exists(\"my_generators/conan_toolchain.cmake\")\n                self.output.warning(\"hey! building\")\n                self.output.warning(os.getcwd())\n\n            def test(self):\n                self.output.warning(\"hey! testing\")\n    \"\"\")\n    client.save({\"conanfile.py\": GenConanfile(), \"test_package/conanfile.py\": conanfile_test})\n    client.run(\"create . --name=lib --version=1.0\")\n    assert \"hey! building\" in client.out\n    assert \"hey! testing\" in client.out\n\n\ndef test_cache_in_layout(conanfile):\n    \"\"\"The layout in the cache is used too, always relative to the \"base\" folders that the cache\n    requires. But by the default, the \"package\" is not followed\n    \"\"\"\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"create . --name=base --version=1.0\")\n\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=lib --version=1.0\")\n    pkg_layout = client.created_layout()\n    sf = client.exported_layout().source()\n    bf = pkg_layout.build()\n    pf = pkg_layout.package()\n\n    source_folder = os.path.join(sf, \"my_sources\")\n    build_folder = os.path.join(bf, \"my_build\")\n\n    # Check folders match with the declared by the layout\n    assert \"Source folder: {}\".format(source_folder) in client.out\n    assert \"Build folder: {}\".format(build_folder) in client.out\n    # Check the source folder\n    assert os.path.exists(os.path.join(source_folder, \"source.h\"))\n\n    # Check the build folder\n    assert os.path.exists(os.path.join(build_folder, \"build.lib\"))\n\n    # Check the conaninfo\n    assert os.path.exists(os.path.join(pf, \"conaninfo.txt\"))\n\n\ndef test_same_conanfile_local(conanfile):\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"create . --name=base --version=1.0\")\n\n    client.save({\"conanfile.py\": conanfile})\n\n    source_folder = os.path.join(client.current_folder, \"my_sources\")\n    build_folder = os.path.join(client.current_folder, \"install\", \"my_build\")\n\n    client.run(\"install . --name=lib --version=1.0 -of=install\")\n    client.run(\"source .\")\n    assert \"Source folder: {}\".format(source_folder) in client.out\n    assert os.path.exists(os.path.join(source_folder, \"source.h\"))\n\n    client.run(\"build .  -of=install\")\n    assert \"Build folder: {}\".format(build_folder) in client.out\n    assert os.path.exists(os.path.join(build_folder, \"build.lib\"))\n\n\ndef test_cpp_package():\n    client = TestClient()\n\n    conan_hello = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import save\n        class Pkg(ConanFile):\n            def package(self):\n                save(self, os.path.join(self.package_folder, \"foo/include/foo.h\"), \"\")\n                save(self, os.path.join(self.package_folder,\"foo/libs/foo.lib\"), \"\")\n\n            def layout(self):\n                self.cpp.package.includedirs = [\"foo/include\"]\n                self.cpp.package.libdirs = [\"foo/libs\"]\n                self.cpp.package.libs = [\"foo\"]\n             \"\"\")\n\n    client.save({\"conanfile.py\": conan_hello})\n    client.run(\"create . --name=hello --version=1.0\")\n    rrev = client.exported_recipe_revision()\n    ref = RecipeReference.loads(\"hello/1.0\")\n    ref.revision = rrev\n    pref = PkgReference(ref, NO_SETTINGS_PACKAGE_ID)\n    package_folder = client.get_latest_pkg_layout(pref).package().replace(\"\\\\\", \"/\") + \"/\"\n\n    conan_consumer = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class HelloTestConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            requires = \"hello/1.0\"\n            generators = \"CMakeDeps\"\n            def generate(self):\n                info = self.dependencies[\"hello\"].cpp_info\n                self.output.warning(\"**includedirs:{}**\".format(info.includedirs))\n                self.output.warning(\"**libdirs:{}**\".format(info.libdirs))\n                self.output.warning(\"**libs:{}**\".format(info.libs))\n        \"\"\")\n\n    client.save({\"conanfile.py\": conan_consumer})\n    client.run(\"install .\")\n    out = str(client.out).replace(r\"\\\\\", \"/\").replace(package_folder, \"\")\n    assert \"**includedirs:['foo/include']**\" in out\n    assert \"**libdirs:['foo/libs']**\" in out\n    assert \"**libs:['foo']**\" in out\n    host_arch = client.get_default_host_profile().settings['arch']\n    cmake = client.load(f\"hello-release-{host_arch}-data.cmake\")\n\n    assert 'set(hello_INCLUDE_DIRS_RELEASE \"${hello_PACKAGE_FOLDER_RELEASE}/foo/include\")' in cmake\n    assert 'set(hello_LIB_DIRS_RELEASE \"${hello_PACKAGE_FOLDER_RELEASE}/foo/libs\")' in cmake\n    assert 'set(hello_LIBS_RELEASE foo)' in cmake\n\n\ndef test_git_clone_with_source_layout():\n    client = TestClient()\n    repo = temp_folder()\n    conanfile = textwrap.dedent(\"\"\"\n           import os\n           from conan import ConanFile\n           class Pkg(ConanFile):\n               exports_sources = \"*.txt\"\n\n               def layout(self):\n                   self.folders.source = \"src\"\n\n               def source(self):\n                   self.run('git clone \"{}\" .')\n       \"\"\").format(repo.replace(\"\\\\\", \"/\"))\n\n    client.save({\"conanfile.py\": conanfile,\n                 \"myfile.txt\": \"My file is copied\"})\n    with client.chdir(repo):\n        client.save({\"cloned.txt\": \"foo\"}, repo)\n        client.init_git_repo()\n\n    client.run(\"create . --name=hello --version=1.0\")\n    sf = client.exported_layout().source()\n    assert os.path.exists(os.path.join(sf, \"myfile.txt\"))\n    # The conanfile is cleared from the root before cloning\n    assert not os.path.exists(os.path.join(sf, \"conanfile.py\"))\n    assert not os.path.exists(os.path.join(sf, \"cloned.txt\"))\n\n    assert os.path.exists(os.path.join(sf, \"src\", \"cloned.txt\"))\n    assert not os.path.exists(os.path.join(sf, \"src\", \"myfile.txt\"))\n"
  },
  {
    "path": "test/functional/layout/test_in_subfolder.py",
    "content": "import textwrap\n\nimport pytest\n\nfrom conan.test.assets.cmake import gen_cmakelists\nfrom conan.test.assets.sources import gen_function_cpp\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_exports_sources_own_code_in_subfolder():\n    \"\"\" test that we can put the conanfile in a subfolder, and it can work. The key is\n    the exports_sources() method that can do:\n        os.path.join(self.recipe_folder, \"..\")\n    And the layout: self.folders.root = \"..\"\n    \"\"\"\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import load, copy, save\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n\n            def layout(self):\n                self.folders.root = \"..\"\n                self.folders.source = \".\"\n                self.folders.build = \"build\"\n                self.folders.generators = \"conangen\"\n\n            def generate(self):\n                save(self, \"mygen.txt\", \"mycontent\")\n\n            def export_sources(self):\n                source_folder = os.path.join(self.recipe_folder, \"..\")\n                copy(self, \"*.txt\", source_folder, self.export_sources_folder)\n\n            def source(self):\n                cmake = load(self, \"CMakeLists.txt\")\n                self.output.info(\"MYCMAKE-SRC: {}\".format(cmake))\n\n            def build(self):\n                path = os.path.join(self.source_folder, \"CMakeLists.txt\")\n                cmake = load(self, path)\n                self.output.info(\"MYCMAKE-BUILD: {}\".format(cmake))\n                save(self, \"mylib.a\", \"mylib\")\n            \"\"\")\n    c.save({\"conan/conanfile.py\": conanfile,\n            \"CMakeLists.txt\": \"mycmake!\"})\n    c.run(\"create conan\")\n    assert \"pkg/0.1: MYCMAKE-SRC: mycmake!\" in c.out\n    assert \"pkg/0.1: MYCMAKE-BUILD: mycmake!\" in c.out\n\n    # Local flow\n    c.run(\"install conan\")\n    assert c.load(\"conangen/mygen.txt\") == \"mycontent\"\n    # SOURCE NOT CALLED! It doesnt make sense (will fail due to local exports)\n    c.run(\"build conan\")\n    assert \"conanfile.py (pkg/0.1): MYCMAKE-BUILD: mycmake!\" in c.out\n    assert c.load(\"build/mylib.a\") == \"mylib\"\n\n\ndef test_exports_sources_common_code():\n    \"\"\" very similar to the above, but intended for a multi-package project sharing some\n    common code\n    \"\"\"\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import load, copy, save\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n\n            def layout(self):\n                self.folders.root = \"..\"\n                self.folders.source = \"pkg\"\n                self.folders.build = \"build\"\n\n            def export_sources(self):\n                source_folder = os.path.join(self.recipe_folder, \"..\")\n                copy(self, \"*.txt\", source_folder, self.export_sources_folder)\n                copy(self, \"*.cmake\", source_folder, self.export_sources_folder)\n\n            def source(self):\n                cmake = load(self, \"CMakeLists.txt\")\n                self.output.info(\"MYCMAKE-SRC: {}\".format(cmake))\n\n            def build(self):\n                path = os.path.join(self.source_folder, \"CMakeLists.txt\")\n                cmake = load(self, path)\n                self.output.info(\"MYCMAKE-BUILD: {}\".format(cmake))\n\n                path = os.path.join(self.export_sources_folder, \"common\", \"myutils.cmake\")\n                cmake = load(self, path)\n                self.output.info(\"MYUTILS-BUILD: {}\".format(cmake))\n            \"\"\")\n    c.save({\"pkg/conanfile.py\": conanfile,\n            \"pkg/CMakeLists.txt\": \"mycmake!\",\n            \"common/myutils.cmake\": \"myutils!\"})\n    c.run(\"create pkg\")\n    assert \"pkg/0.1: MYCMAKE-SRC: mycmake!\" in c.out\n    assert \"pkg/0.1: MYCMAKE-BUILD: mycmake!\" in c.out\n    assert \"pkg/0.1: MYUTILS-BUILD: myutils!\" in c.out\n\n    # Local flow\n    c.run(\"install pkg\")\n    # SOURCE NOT CALLED! It doesnt make sense (will fail due to local exports)\n    c.run(\"build pkg\")\n    assert \"conanfile.py (pkg/0.1): MYCMAKE-BUILD: mycmake!\" in c.out\n    assert \"conanfile.py (pkg/0.1): MYUTILS-BUILD: myutils!\" in c.out\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_exports_sources_common_code_layout():\n    \"\"\" Equal to the previous test, but actually building and using cmake_layout\n    \"\"\"\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.cmake import cmake_layout, CMake\n        from conan.tools.files import load, copy, save\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"CMakeToolchain\"\n\n            def layout(self):\n                self.folders.root = \"..\"\n                self.folders.subproject = \"pkg\"\n                cmake_layout(self)\n\n            def export_sources(self):\n                source_folder = os.path.join(self.recipe_folder, \"..\")\n                copy(self, \"*\", source_folder, self.export_sources_folder)\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n                self.run(os.path.join(self.cpp.build.bindirs[0], \"myapp\"))\n            \"\"\")\n    cmake_include = \"include(${CMAKE_CURRENT_LIST_DIR}/../common/myutils.cmake)\"\n    c.save({\"pkg/conanfile.py\": conanfile,\n            \"pkg/app.cpp\": gen_function_cpp(name=\"main\", includes=[\"../common/myheader\"],\n                                            preprocessor=[\"MYDEFINE\"]),\n            \"pkg/CMakeLists.txt\": gen_cmakelists(appsources=[\"app.cpp\"],\n                                                 custom_content=cmake_include),\n            \"common/myutils.cmake\": 'message(STATUS \"MYUTILS.CMAKE!\")',\n            \"common/myheader.h\": '#define MYDEFINE \"MYDEFINEVALUE\"'})\n    c.run(\"create pkg\")\n    assert \"MYUTILS.CMAKE!\" in c.out\n    assert \"main: Release!\" in c.out\n    assert \"MYDEFINE: MYDEFINEVALUE\" in c.out\n\n    # Local flow\n    c.run(\"build pkg\")\n    assert \"MYUTILS.CMAKE!\" in c.out\n    assert \"main: Release!\" in c.out\n    assert \"MYDEFINE: MYDEFINEVALUE\" in c.out\n\n    c.run(\"build pkg -s build_type=Debug\")\n    assert \"MYUTILS.CMAKE!\" in c.out\n    assert \"main: Debug!\" in c.out\n    assert \"MYDEFINE: MYDEFINEVALUE\" in c.out\n"
  },
  {
    "path": "test/functional/layout/test_local_commands.py",
    "content": "import os\nimport platform\nimport textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_local_static_generators_folder():\n    \"\"\"If we configure a generators folder in the layout, the generator files:\n      - If belong to new generators: go to the specified folder: \"my_generators\"\n      - If belong to old generators or txt: remains in the install folder\n    \"\"\"\n    client = TestClient()\n    conan_file = str(GenConanfile().with_settings(\"build_type\"))\n    conan_file += \"\"\"\n    generators = \"CMakeToolchain\"\n    def layout(self):\n        self.folders.build = \"build-{}\".format(self.settings.build_type)\n        self.folders.generators = \"{}/generators\".format(self.folders.build)\n    \"\"\"\n    client.save({\"conanfile.py\": conan_file})\n    client.run(\"install . -of=my_install\")\n\n    old_install_folder = os.path.join(client.current_folder, \"my_install\")\n    cmake_toolchain_generator_path = os.path.join(old_install_folder, \"conan_toolchain.cmake\")\n    assert not os.path.exists(cmake_toolchain_generator_path)\n\n    build_folder = os.path.join(client.current_folder, \"my_install\", \"build-Release\")\n    generators_folder = os.path.join(build_folder, \"generators\")\n    cmake_toolchain_generator_path = os.path.join(generators_folder, \"conan_toolchain.cmake\")\n    assert os.path.exists(cmake_toolchain_generator_path)\n\n\ndef test_local_dynamic_generators_folder():\n    \"\"\"If we configure a generators folder in the layout, the generator files:\n      - If belong to new generators: go to the specified folder: \"my_generators\"\n      - \"txt\" and old ones always to the install folder\n    \"\"\"\n    client = TestClient()\n    conan_file = str(GenConanfile().with_settings(\"build_type\").\n                     with_import(\"from conan.tools.cmake import CMakeToolchain, CMake\"))\n    conan_file += \"\"\"\n    def generate(self):\n        tc = CMakeToolchain(self)\n        tc.generate()\n    def layout(self):\n        self.folders.build = \"build-{}\".format(self.settings.build_type)\n        self.folders.generators = \"{}/generators\".format(self.folders.build)\n    \"\"\"\n    client.save({\"conanfile.py\": conan_file})\n    client.run(\"install . -of=my_install\")\n\n    old_install_folder = os.path.join(client.current_folder, \"my_install\")\n    cmake_toolchain_generator_path = os.path.join(old_install_folder, \"conan_toolchain.cmake\")\n    assert not os.path.exists(cmake_toolchain_generator_path)\n\n    build_folder = os.path.join(client.current_folder, \"my_install\", \"build-Release\")\n    generators_folder = os.path.join(build_folder, \"generators\")\n    cmake_toolchain_generator_path = os.path.join(generators_folder, \"conan_toolchain.cmake\")\n    assert os.path.exists(cmake_toolchain_generator_path)\n\n\ndef test_no_layout_generators_folder():\n    \"\"\"If we don't configure a generators folder in the layout, the generator files:\n      - all go to the install_folder\n    \"\"\"\n    client = TestClient()\n    conan_file = str(GenConanfile().with_settings(\"build_type\").\n                     with_import(\"from conan.tools.cmake import CMakeToolchain, CMake\"))\n    conan_file += \"\"\"\n    def generate(self):\n        tc = CMakeToolchain(self)\n        tc.generate()\n    \"\"\"\n    client.save({\"conanfile.py\": conan_file})\n    client.run(\"install . -of=my_install\")\n\n    old_install_folder = os.path.join(client.current_folder, \"my_install\")\n    cmake_toolchain_generator_path = os.path.join(old_install_folder, \"conan_toolchain.cmake\")\n\n    # In the install_folder\n    assert os.path.exists(cmake_toolchain_generator_path)\n\n    # But not in the base folder\n    assert not os.path.exists(os.path.join(client.current_folder, \"conan_toolchain.cmake\"))\n\n\ndef test_local_build():\n    \"\"\"If we configure a build folder in the layout, the installed files in a \"conan build .\"\n    go to the specified folder: \"my_build\"\n    \"\"\"\n    client = TestClient()\n    conan_file = str(GenConanfile().with_import(\"from conan.tools.files import save\"))\n    conan_file += \"\"\"\n    def layout(self):\n        self.folders.generators = \"my_generators\"\n        self.folders.build = \"my_build\"\n    def build(self):\n        self.output.warning(\"Generators folder: {}\".format(self.folders.generators_folder))\n        save(self, \"build_file.dll\", \"bar\")\n\"\"\"\n    client.save({\"conanfile.py\": conan_file})\n    client.run(\"build . --output-folder=my_install\")\n    dll = os.path.join(client.current_folder, \"my_install\", \"my_build\", \"build_file.dll\")\n    assert os.path.exists(dll)\n\n\ndef test_local_build_change_base():\n    \"\"\"If we configure a build folder in the layout, the build files in a \"conan build .\"\n    go to the specified folder: \"my_build under the modified base one \"common\"\n    \"\"\"\n    client = TestClient()\n    conan_file = str(GenConanfile().with_import(\"from conan.tools.files import save\"))\n    conan_file += \"\"\"\n    def layout(self):\n        self.folders.build = \"my_build\"\n    def build(self):\n        save(self, \"build_file.dll\", \"bar\")\n    \"\"\"\n    client.save({\"conanfile.py\": conan_file})\n    client.run(\"install . --output-folder=common\")\n    client.run(\"build . --output-folder=common\")\n    dll = os.path.join(client.current_folder, \"common\", \"my_build\", \"build_file.dll\")\n    assert os.path.exists(dll)\n\n\ndef test_local_source():\n    \"\"\"The \"conan source\" is NOT affected by the --output-folder\n    \"\"\"\n    client = TestClient()\n    conan_file = str(GenConanfile().with_import(\"from conan.tools.files import save\"))\n    conan_file += \"\"\"\n    def layout(self):\n        self.folders.source = \"my_source\"\n    def source(self):\n        save(self, \"downloaded.h\", \"bar\")\n    \"\"\"\n    client.save({\"conanfile.py\": conan_file})\n    client.run(\"install . -of=my_install\")\n    client.run(\"source .\")\n    header = os.path.join(client.current_folder, \"my_source\", \"downloaded.h\")\n    assert os.path.exists(header)\n\n\ndef test_export_pkg():\n    \"\"\"The export-pkg, calling the \"package\" method, follows the layout if `cache_package_layout` \"\"\"\n    client = TestClient()\n    conan_file = str(GenConanfile(\"lib\", \"1.0\")\n                     .with_import(\"from conan.tools.files import copy, save\"))\n    conan_file += \"\"\"\n    no_copy_source = True\n    def layout(self):\n        self.folders.source = \"my_source\"\n        self.folders.build = \"my_build\"\n    def source(self):\n        save(self, \"downloaded.h\", \"bar\")\n    def build(self):\n        save(self, \"library.lib\", \"bar\")\n        save(self, \"generated.h\", \"bar\")\n    def package(self):\n        copy(self, \"*.h\", self.source_folder, self.package_folder)\n        copy(self, \"*.h\", self.build_folder, self.package_folder)\n        copy(self, \"*.lib\", self.build_folder, self.package_folder)\n    \"\"\"\n\n    client.save({\"conanfile.py\": conan_file})\n    client.run(\"source .\")\n    client.run(\"build .\")\n    client.run(\"export-pkg .\")\n\n    pf = client.created_layout().package()\n\n    # Check the artifacts packaged\n    assert os.path.exists(os.path.join(pf, \"downloaded.h\"))\n    assert os.path.exists(os.path.join(pf, \"generated.h\"))\n    assert os.path.exists(os.path.join(pf, \"library.lib\"))\n\n\ndef test_export_pkg_local():\n    \"\"\"The export-pkg, without calling \"package\" method, with local package, follows the layout\"\"\"\n    client = TestClient()\n    conan_file = str(GenConanfile(\"lib\", \"1.0\")\n                     .with_import(\"from conan.tools.files import copy, save\"))\n    conan_file += \"\"\"\n    no_copy_source = True\n    def layout(self):\n        self.folders.source = \"my_source\"\n        self.folders.build = \"my_build\"\n        self.folders.package = \"my_package\"\n    def source(self):\n        save(self, \"downloaded.h\", \"bar\")\n    def build(self):\n        save(self, \"library.lib\", \"bar\")\n        save(self, \"generated.h\", \"bar\")\n    def package(self):\n        copy(self, \"*.h\", self.source_folder, self.package_folder)\n        copy(self, \"*.h\", self.build_folder, self.package_folder)\n        copy(self, \"*.lib\", self.build_folder, self.package_folder)\n    \"\"\"\n\n    client.save({\"conanfile.py\": conan_file})\n    client.run(\"source .\")\n    client.run(\"build .\")\n\n    # assert \"WARN: Package folder: {}\".format(pf) in client.out\n\n    client.run(\"export-pkg .\")\n    pf = client.created_layout().package()\n\n    # Check the artifacts packaged, THERE IS NO \"my_package\" in the cache\n    assert \"my_package\" not in pf\n    assert os.path.exists(os.path.join(pf, \"downloaded.h\"))\n    assert os.path.exists(os.path.join(pf, \"generated.h\"))\n    assert os.path.exists(os.path.join(pf, \"library.lib\"))\n\n    # Doing a conan create: Same as export-pkg, there is \"my_package\" in the cache\n    client.run(\"create . \")\n    pf = client.created_layout().package()\n    assert \"my_package\" not in pf\n    assert os.path.exists(os.path.join(pf, \"downloaded.h\"))\n    assert os.path.exists(os.path.join(pf, \"generated.h\"))\n    assert os.path.exists(os.path.join(pf, \"library.lib\"))\n\n\ndef test_start_dir_failure():\n    c = TestClient()\n    c.run(\"new cmake_lib -d name=dep -d version=0.1\")\n    c.run(\"install .\")\n    if platform.system() != \"Windows\":\n        gen_folder = os.path.join(c.current_folder, \"build\", \"Release\", \"generators\")\n    else:\n        gen_folder = os.path.join(c.current_folder, \"build\", \"generators\")\n    expected_path = os.path.join(gen_folder, \"conan_toolchain.cmake\")\n    assert os.path.exists(expected_path)\n    os.unlink(expected_path)\n    with c.chdir(\"build\"):\n        c.run(\"install ..\")\n    assert os.path.exists(expected_path)\n\n\ndef test_local_folders_without_layout():\n    \"\"\" Test that the \"conan install\" can report the local source and build folder\n    \"\"\"\n    # https://github.com/conan-io/conan/issues/10566\n    client = TestClient()\n    conan_file = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Test(ConanFile):\n            version = \"1.2.3\"\n            name = \"test\"\n\n            def layout(self):\n                self.folders.source = \".\"\n                self.folders.build = \"build\"\n\n            def generate(self):\n                self.output.info(\"generate sf: {}\".format(self.source_folder))\n                self.output.info(\"generate bf: {}\".format(self.build_folder))\n        \"\"\")\n\n    client.save({\"conanfile.py\": conan_file})\n    client.run(\"install .\")\n    assert \"conanfile.py (test/1.2.3): generate sf: {}\".format(client.current_folder) in client.out\n    assert \"conanfile.py (test/1.2.3): generate bf: {}\".format(client.current_folder) in client.out\n"
  },
  {
    "path": "test/functional/layout/test_source_folder.py",
    "content": "import os\nimport platform\nfrom shutil import copy\n\nfrom unittest import mock\nimport pytest\n\nfrom conan.test.assets.cmake import gen_cmakelists\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.assets.sources import gen_function_cpp\nfrom conan.test.utils.tools import TestClient, zipdir\n\napp_name = \"Release/my_app.exe\" if platform.system() == \"Windows\" else \"my_app\"\n\n\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.parametrize(\"no_copy_source\", [\"False\", \"True\"])\ndef test_exports_source_with_src_subfolder(no_copy_source):\n    \"\"\"If we have the sources in a subfolder, specifying it in the self.folders.source will\n    work both locally (conan build) or in the cache (exporting the sources)\"\"\"\n    conan_file = GenConanfile() \\\n        .with_name(\"app\").with_version(\"1.0\") \\\n        .with_settings(\"os\", \"arch\", \"build_type\", \"compiler\") \\\n        .with_exports_sources(\"my_src/*\")\\\n        .with_cmake_build()\\\n        .with_class_attribute(\"no_copy_source={}\".format(no_copy_source))\n\n    conan_file = str(conan_file)\n    conan_file += \"\"\"\n    def layout(self):\n        self.folders.source = \"my_src\"\n        self.folders.build = str(self.settings.build_type)\n    \"\"\"\n    cmake = gen_cmakelists(appname=\"my_app\", appsources=[\"main.cpp\"])\n    app = gen_function_cpp(name=\"main\")\n\n    client = TestClient()\n    client.save({\"conanfile.py\": conan_file,\n                 \"my_src/main.cpp\": app,\n                 \"my_src/CMakeLists.txt\": cmake})\n    client.run(\"build .\")\n    assert os.path.exists(os.path.join(client.current_folder, \"Release\", app_name))\n    client.run(\"create . \")\n    assert \"Created package revision\" in client.out\n\n\ndef test_exports():\n    \"\"\"If we have some sources in the root (like the CMakeLists.txt)\n    we don't declare folders.source\"\"\"\n    conan_file = GenConanfile() \\\n        .with_name(\"app\").with_version(\"1.0\") \\\n        .with_settings(\"os\", \"arch\", \"build_type\", \"compiler\") \\\n        .with_exports(\"*.py\") \\\n        .with_import(\"from my_tools import FOO\")\n\n    conan_file = str(conan_file)\n    conan_file += \"\"\"\n    def layout(self):\n        self.folders.source = \"my_src\"\n    def build(self):\n        # This FOO comes from the my_tools.py\n        self.output.warning(\"FOO: {}\".format(FOO))\n    \"\"\"\n\n    client = TestClient()\n    client.save({\"conanfile.py\": conan_file,\n                 \"my_tools.py\": \"FOO=1\"})\n    client.run(\"build .\")\n    assert \"FOO: 1\" in client.out\n\n    client.run(\"create . \")\n    assert \"FOO: 1\" in client.out\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_exports_source_without_subfolder():\n    \"\"\"If we have some sources in the root (like the CMakeLists.txt)\n    we don't declare folders.source\"\"\"\n    conan_file = GenConanfile() \\\n        .with_name(\"app\").with_version(\"1.0\") \\\n        .with_settings(\"os\", \"arch\", \"build_type\", \"compiler\") \\\n        .with_exports_sources(\"CMakeLists.txt\", \"my_src/*\")\\\n        .with_cmake_build()\n\n    conan_file = str(conan_file)\n    conan_file += \"\"\"\n    def layout(self):\n        self.folders.build = str(self.settings.build_type)\n    \"\"\"\n    cmake = gen_cmakelists(appname=\"my_app\", appsources=[\"my_src/main.cpp\"])\n    app = gen_function_cpp(name=\"main\")\n\n    client = TestClient()\n    client.save({\"conanfile.py\": conan_file,\n                 \"my_src/main.cpp\": app,\n                 \"CMakeLists.txt\": cmake})\n    client.run(\"build .\")\n    assert os.path.exists(os.path.join(client.current_folder, \"Release\", app_name))\n    client.run(\"create . \")\n    assert \"Created package revision\" in client.out\n\n\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.parametrize(\"no_copy_source\", [\"False\", \"True\"])\ndef test_zip_download_with_subfolder_new_tools(no_copy_source):\n    \"\"\"If we have a zip with the sources in a subfolder, specifying it in the self.folders.source\n    will unzip in the base and will work both locally (conan build) or in the cache\n    (exporting the sources)\"\"\"\n\n    tmp = TestClient()  # Used only to save some files, sorry for the lazyness\n    cmake = gen_cmakelists(appname=\"my_app\", appsources=[\"main.cpp\"])\n    app = gen_function_cpp(name=\"main\")\n    tmp.save({\"subfolder/main.cpp\": app,\n              \"subfolder/CMakeLists.txt\": cmake,\n              \"ignored_subfolder/ignored.txt\": \"\"})\n    zippath = os.path.join(tmp.current_folder, \"my_sources.zip\")\n    zipdir(tmp.current_folder, zippath)\n\n    conan_file = GenConanfile() \\\n        .with_import(\"import os\") \\\n        .with_import(\"from conan.tools.files import get\") \\\n        .with_import(\"from conan.tools.cmake import CMake\") \\\n        .with_name(\"app\").with_version(\"1.0\") \\\n        .with_settings(\"os\", \"arch\", \"build_type\", \"compiler\") \\\n        .with_generator(\"CMakeToolchain\") \\\n        .with_class_attribute(\"no_copy_source={}\".format(no_copy_source))\n\n    conan_file = str(conan_file)\n    conan_file += \"\"\"\n    def source(self):\n        get(self, \"http://fake_url/my_sources.zip\")\n\n    def layout(self):\n        self.folders.source = \"src\"\n\n    def build(self):\n        assert os.path.exists(os.path.join(self.source_folder, \"subfolder\", \"CMakeLists.txt\"))\n        assert os.path.exists(os.path.join(self.source_folder,\n                                           \"ignored_subfolder\", \"ignored.txt\"))\n        cmake = CMake(self)\n        cmake.configure(build_script_folder=\"subfolder\")\n        cmake.build()\n    \"\"\"\n    client = TestClient()\n    client.save({\"conanfile.py\": conan_file})\n\n    with mock.patch(\"conan.tools.files.files.download\") as mock_download:\n        def download_zip(*args, **kwargs):\n            copy(zippath, os.getcwd())\n        mock_download.side_effect = download_zip\n        client.run(\"create . \")\n"
  },
  {
    "path": "test/functional/revisions_test.py",
    "content": "import copy\nimport time\nfrom collections import OrderedDict\n\nimport pytest\nfrom unittest.mock import patch\n\nfrom conan.internal.graph.graph_builder import DepsGraphBuilder\nfrom conan.test.utils.env import environment_update\nfrom conan.internal.errors import RecipeNotFoundException\nfrom conan.api.model import RecipeReference\nfrom conans.server.revision_list import RevisionList\nfrom conan.test.utils.tools import TestServer, GenConanfile, TestClient\nfrom conan.internal.util.files import load\n\n\ndef _create(c_v2, ref, conanfile=None, args=None, assert_error=False):\n    conanfile = conanfile or GenConanfile()\n    c_v2.save({\"conanfile.py\": str(conanfile)})\n    r = ref\n    c_v2.run(f\"create . --name {r.name} --version {r.version} \"\n             f\"--user {r.user} --channel {r.channel} {args or ''}\", assert_error=assert_error)\n    if not assert_error:\n        pref = c_v2.created_package_reference(str(ref))\n        return pref\n\n\nDepsGraphBuilder.ALLOW_ALIAS = True\n\n\n@pytest.mark.artifactory_ready\nclass TestInstallingPackagesWithRevisions:\n\n    @pytest.fixture(autouse=True)\n    def setup(self):\n        self.server = TestServer()\n        self.server2 = TestServer()\n        self.servers = OrderedDict([(\"default\", self.server),\n                                    (\"remote2\", self.server2)])\n        self.c_v2 = TestClient(servers=self.servers, inputs=2*[\"admin\", \"password\"])\n        self.ref = RecipeReference.loads(\"lib/1.0@conan/testing\")\n\n    def recipe_revision(self, ref):\n        tmp = copy.copy(ref)\n        tmp.revision = None\n        latest_rrev = self.c_v2.cache.get_latest_recipe_revision(tmp)\n        return latest_rrev.revision\n\n    def package_revision(self, pref):\n        tmp = copy.copy(pref)\n        tmp.revision = None\n        latest_prev = self.c_v2.cache.get_latest_package_revision(tmp)\n        return latest_prev.revision\n\n    def test_install_binary_iterating_remotes_same_rrev(self):\n        \"\"\"We have two servers (remote1 and remote2), first with a recipe but the\n        second one with a PREV of the binary.\n        If a client installs without specifying -r remote1, it will iterate remote2 also\"\"\"\n        conanfile = GenConanfile().with_package_file(\"file.txt\", env_var=\"MY_VAR\")\n        with environment_update({\"MY_VAR\": \"1\"}):\n            pref = _create(self.c_v2, self.ref, conanfile=conanfile)\n        the_time = time.time()\n        with patch.object(RevisionList, '_now', return_value=the_time):\n            self.c_v2.run(f\"upload {self.ref} -r=default -c\")\n        self.c_v2.run(\"remove {}#*:{} -c -r default\".format(self.ref, pref.package_id))\n        # Same RREV, different PREV\n        with environment_update({\"MY_VAR\": \"2\"}):\n            pref2 = _create(self.c_v2, self.ref, conanfile=conanfile)\n\n        the_time = the_time + 10.0\n        with patch.object(RevisionList, '_now', return_value=the_time):\n            self.c_v2.run(f\"upload {self.ref} -r=remote2 -c\")\n        self.c_v2.remove_all()\n\n        assert pref.ref.revision == pref2.ref.revision\n\n        self.c_v2.run(\"install --requires={}\".format(self.ref))\n        self.c_v2.assert_listed_require({str(self.ref): \"Downloaded (default)\"})\n        assert \"Retrieving package {} from remote 'remote2'\".format(pref.package_id) in self.c_v2.out\n\n    def test_diamond_revisions_conflict(self):\n        \"\"\" If we have a diamond because of pinned conflicting revisions in the requirements,\n        it gives an error\"\"\"\n\n        # Two revisions of \"lib1\" to the server\n        lib1 = RecipeReference.loads(\"lib1/1.0@conan/stable\")\n        lib1_pref = _create(self.c_v2, lib1)\n        self.c_v2.run(f\"upload {lib1} -r=default -c\")\n        lib1b_pref = _create(self.c_v2, lib1, conanfile=GenConanfile().with_build_msg(\"Rev2\"))\n        self.c_v2.run(f\"upload {lib1} -r=default -c\")\n\n        # Lib2 depending of lib1\n        self.c_v2.remove_all()\n        lib2 = RecipeReference.loads(\"lib2/1.0@conan/stable\")\n        _create(self.c_v2, lib2, conanfile=GenConanfile().with_requirement(lib1_pref.ref))\n        self.c_v2.run(f\"upload {lib2} -r=default -c\")\n\n        # Lib3 depending of lib1b\n        self.c_v2.remove_all()\n        lib3 = RecipeReference.loads(\"lib3/1.0@conan/stable\")\n        _create(self.c_v2, lib3, conanfile=GenConanfile().with_requirement(lib1b_pref.ref))\n        self.c_v2.run(f\"upload {lib3} -r=default -c\")\n\n        # Project depending on both lib3 and lib2\n        self.c_v2.remove_all()\n        project = RecipeReference.loads(\"project/1.0@conan/stable\")\n        _create(self.c_v2, project,\n                conanfile=GenConanfile().with_requirement(lib2).with_requirement(lib3),\n                assert_error=True)\n        assert \"ERROR: Version conflict\" in self.c_v2.out\n        # assert \"Different revisions of {} has been requested\".format(lib1), self.c_v2.out)\n\n    def test_alias_to_a_rrev(self):\n        \"\"\" If an alias points to a RREV, it resolved that RREV and no other\"\"\"\n\n        # Upload one revision\n        pref = _create(self.c_v2, self.ref)\n        self.c_v2.run(f\"upload {self.ref} -r=default -c\")\n\n        # Upload other revision\n        _create(self.c_v2, self.ref, conanfile=GenConanfile().with_build_msg(\"Build Rev 2\"))\n        self.c_v2.run(f\"upload {self.ref} -r=default -c\")\n        self.c_v2.remove_all()\n\n        # Create an alias to the first revision\n        self.c_v2.alias(\"lib/latest@conan/stable\", repr(pref.ref))\n        alias_ref = RecipeReference.loads(\"lib/latest@conan/stable\")\n        exported = load(self.c_v2.get_latest_ref_layout(alias_ref).conanfile())\n        assert 'alias = \"{}\"'.format(repr(pref.ref)) in exported\n\n        self.c_v2.run(f\"upload lib/latest@conan/stable -r=default -c\")\n        self.c_v2.remove_all()\n\n        self.c_v2.run(\"install --requires=lib/(latest)@conan/stable\")\n        # Shouldn't be packages in the cache\n        assert \"doesn't belong to the installed recipe revision\" not in self.c_v2.out\n\n        # Read current revision\n        assert pref.ref.revision == self.recipe_revision(self.ref)\n\n    def test_revision_metadata_update_on_install(self):\n        \"\"\"If a clean v2 client installs a RREV/PREV from a server, it get\n        the revision from upstream\"\"\"\n        # Upload with v2\n        pref = _create(self.c_v2, self.ref)\n        self.c_v2.run(f\"upload {self.ref} -r=default -c\")\n\n        # Remove all from c_v2 local\n        self.c_v2.remove_all()\n        assert len(self.c_v2.cache.get_recipe_revisions(self.ref)) == 0\n\n        self.c_v2.run(\"install --requires={}\".format(self.ref))\n        local_rev = self.recipe_revision(self.ref)\n        local_prev = self.package_revision(pref)\n        assert local_rev == pref.ref.revision\n        assert local_prev == pref.revision\n\n    def test_revision_update_on_package_update(self):\n        \"\"\"\n        A client v2 upload RREV with PREV1\n        Another client v2 upload the same RREV with PREV2\n        The first client can upgrade from the remote, only\n        in the package, because the recipe is the same and it is not updated\"\"\"\n        client = TestClient(servers={\"default\": self.server}, inputs=[\"admin\", \"password\"])\n        client2 = TestClient(servers={\"default\": self.server}, inputs=[\"admin\", \"password\"])\n\n        conanfile = GenConanfile(\"pkg\", \"0.1\").with_package_file(\"file\", env_var=\"MY_VAR\")\n        client.save({\"conanfile.py\": conanfile})\n        with environment_update({\"MY_VAR\": \"1\"}):\n            client.run(\"create .\")\n            pref = client.created_package_reference(\"pkg/0.1\")\n\n        time.sleep(1)\n\n        with patch.object(RevisionList, '_now', return_value=time.time()):\n            client.run(f\"upload * -r=default -c\")\n\n        client2.save({\"conanfile.py\": conanfile})\n        with environment_update({\"MY_VAR\": \"2\"}):\n            client2.run(\"create .\")\n            pref2 = client2.created_package_reference(\"pkg/0.1\")\n\n        with patch.object(RevisionList, '_now', return_value=time.time() + 20.0):\n            client2.run(f\"upload * -r=default -c\")\n\n        prev1_time_remote = self.server.package_revision_time(pref)\n        prev2_time_remote = self.server.package_revision_time(pref2)\n        assert prev1_time_remote != prev2_time_remote  # Two package revisions\n\n        client.run(\"install --requires=pkg/0.1 --update\")\n        client.assert_listed_require({\"pkg/0.1\": \"Cache (Updated date) (default)\"})\n        assert \"Retrieving package {}\".format(pref.package_id) in client.out\n\n    def test_revision_mismatch_packages_in_local(self):\n        \"\"\"Test adapted for the new cache: we create a revision but we export again a  recipe\n        to create a new revision, then we won't have a package for the latest recipe revision\n        of the cache.\n        TODO: cache2.0 check this case\"\"\"\n        client = self.c_v2\n        pref = _create(self.c_v2, self.ref)\n        ref2 = client.export(self.ref, conanfile=GenConanfile().with_build_msg(\"REV2\"))\n        # Now we have two RREVs and a PREV corresponding to the first one\n        sot1 = copy.copy(pref.ref)\n        sot1.revision = None\n        sot2 = copy.copy(ref2)\n        sot2.revision = None\n        assert sot1 == sot2\n        assert pref.ref.revision != ref2.revision\n\n        # Now we try to install the self.ref, the binary is missing when using revisions\n        command = \"install --requires={}\".format(self.ref)\n        client.run(command, assert_error=True)\n        assert \"ERROR: Missing prebuilt package for '{}'\".format(self.ref) in client.out\n\n    def test_revision_install_explicit_mismatch_rrev(self):\n        # If we have a recipe in local, but we request to install a different one with RREV\n        # It fail and won't look the remotes unless --update\n        client = self.c_v2\n        ref = client.export(self.ref)\n        command = \"install --requires={}#fakerevision\".format(ref)\n        client.run(command, assert_error=True)\n        assert \"Unable to find '{}#fakerevision' in remotes\".format(ref) in client.out\n        command = \"install --requires={}#fakerevision --update\".format(ref)\n        client.run(command, assert_error=True)\n        assert \"Unable to find '{}#fakerevision' in remotes\".format(ref) in client.out\n\n        # Now create a new revision with other client and upload it, we will request it\n        new_client = TestClient(servers=self.servers, inputs=[\"admin\", \"password\"])\n        new_client.save({\"conanfile.py\": GenConanfile(\"lib\", \"1.0\").with_build_msg(\"Rev2\")})\n        new_client.run(\"create . --user=conan --channel=testing\")\n        pref = new_client.created_package_reference(self.ref)\n        new_client.run(f\"upload * -r=default -c\")\n\n        # Repeat the install --update pointing to the new reference\n        client.run(\"install --requires={} --update\".format(repr(pref.ref)))\n        client.assert_listed_require({str(self.ref): \"Downloaded (default)\"})\n\n    def test_revision_mismatch_packages_remote(self):\n        \"\"\"If we have a recipe that doesn't match a remote recipe:\n         It is not resolved in the remote.\"\"\"\n        _create(self.c_v2, self.ref)\n        self.c_v2.run(f\"upload {self.ref} -r=default -c\")\n\n        client = self.c_v2\n        client.remove_all()\n        client.export(self.ref, conanfile=GenConanfile().with_build_msg(\"REV2\"))\n        command = \"install --requires={}\".format(self.ref)\n\n        client.run(command, assert_error=True)\n        assert \"Can't find a '{}' package\".format(self.ref) in client.out\n\n    def test_revision_build_requires(self):\n        conanfile = GenConanfile()\n\n        refs = []\n        for _ in range(1, 4):  # create different revisions\n            conanfile.with_build_msg(\"any change to get another rrev\")\n            pref = _create(self.c_v2, self.ref, conanfile=conanfile)\n            self.c_v2.run(f\"upload {pref.ref} -r=default -c\")\n            refs.append(pref.ref)\n            assert refs.count(pref.ref) == 1  # make sure that all revisions are different\n\n        client = self.c_v2  # revisions enabled\n        client.remove_all()\n\n        for ref in refs:\n            command = \"install --update --tool-require={}\".format(repr(ref))\n            client.run(command)\n            assert \"Downloaded recipe revision {}\".format(ref.revision) in client.out\n\n\nclass TestRemoveWithRevisions:\n\n    @pytest.fixture(autouse=True)\n    def setup(self):\n        self.server = TestServer()\n        self.c_v2 = TestClient(servers={\"default\": self.server}, inputs=[\"admin\", \"password\"])\n        self.ref = RecipeReference.loads(\"lib/1.0@conan/testing\")\n\n    def test_remove_local_recipe(self):\n        \"\"\"Locally: When I remove a recipe with RREV only if the local revision matches is removed\"\"\"\n        client = self.c_v2\n\n        # If I remove the ref, the revision is gone, of course\n        ref1 = client.export(self.ref)\n        ref1.revision = None\n        client.run(\"remove {} -c\".format(repr(ref1)))\n        assert not client.recipe_exists(self.ref)\n\n        # If I remove a ref with a wrong revision, the revision is not removed\n        ref1 = client.export(self.ref)\n        fakeref = copy.copy(ref1)\n        fakeref.revision = \"fakerev\"\n        full_ref = repr(fakeref)\n        client.run(\"remove {} -c\".format(repr(fakeref)), assert_error=True)\n        assert f\"ERROR: Recipe revision '{full_ref}' not found\" in client.out\n        assert client.recipe_exists(self.ref)\n\n    def test_remove_local_package(self):\n        \"\"\"Locally:\n            When I remove a recipe without RREV, the package is removed.\n            When I remove a recipe with RREV only if the local revision matches is removed\n            When I remove a package with PREV and not RREV it raises an error\n            When I remove a package with RREV and PREV only when both matches is removed\"\"\"\n        client = self.c_v2\n\n        # If I remove the ref without RREV, the packages are also removed\n        pref1 = _create(self.c_v2, self.ref)\n        tmp = copy.copy(pref1.ref)\n        tmp.revision = None\n        client.run(\"remove {} -c\".format(repr(tmp)))\n        assert not client.package_exists(pref1)\n\n        # If I remove the ref with fake RREV, the packages are not removed\n        pref1 = _create(self.c_v2, self.ref)\n        fakeref = copy.copy(pref1.ref)\n        fakeref.revision = \"fakerev\"\n        str_ref = repr(fakeref)\n        client.run(\"remove {} -c\".format(repr(fakeref)), assert_error=True)\n        assert client.package_exists(pref1)\n        assert \"Recipe revision '{}' not found\".format(str_ref) in client.out\n\n        # If I remove the ref with valid RREV, the packages are removed\n        pref1 = _create(self.c_v2, self.ref)\n        client.run(\"remove {} -c\".format(repr(pref1.ref)))\n        assert not client.package_exists(pref1)\n\n        # If I remove the ref without RREV but specifying PREV it raises\n        pref1 = _create(self.c_v2, self.ref)\n        tmp = copy.copy(pref1.ref)\n        tmp.revision = None\n        command = \"remove {}:{}#{} -c\".format(repr(tmp), pref1.package_id, pref1.revision)\n        client.run(command)\n        assert not client.package_exists(pref1)\n\n        # A wrong PREV doesn't remove the PREV\n        pref1 = _create(self.c_v2, self.ref)\n        command = \"remove {}:{}#fakeprev -c\".format(repr(pref1.ref), pref1.package_id)\n        client.run(command, assert_error=True)\n        assert client.package_exists(pref1)\n        assert \"ERROR: Package revision\" in client.out\n\n        # Everything correct, removes the unique local package revision\n        pref1 = _create(self.c_v2, self.ref)\n        command = \"remove {}:{}#{} -c\".format(repr(pref1.ref), pref1.package_id, pref1.revision)\n        client.run(command)\n        assert not client.package_exists(pref1)\n\n    def test_remove_remote_recipe(self):\n        \"\"\"When a client removes a reference, it removes ALL revisions, no matter\n        if the client is v1 or v2\"\"\"\n        pref1 = _create(self.c_v2, self.ref)\n        self.c_v2.run(f\"upload {pref1.ref} -r=default -c\")\n\n        pref2 = _create(self.c_v2, self.ref, conanfile=GenConanfile().with_build_msg(\"RREV 2!\"))\n        self.c_v2.run(f\"upload {pref2.ref} -r=default -c\")\n\n        assert pref1 != pref2\n\n        remover_client = self.c_v2\n\n        # Remove ref without revision in a remote\n        remover_client.run(\"remove {} -c -r default\".format(self.ref))\n        assert not self.server.recipe_exists(self.ref)\n        assert not self.server.recipe_exists(pref1.ref)\n        assert not self.server.recipe_exists(pref2.ref)\n        assert not self.server.package_exists(pref1)\n        assert not self.server.package_exists(pref2)\n\n    def test_remove_remote_recipe_revision(self):\n        \"\"\"If a client removes a recipe with revision:\n             - If the client is v2 will remove only that revision\"\"\"\n        pref1 = _create(self.c_v2, self.ref)\n        self.c_v2.run(f\"upload {pref1.ref} -r=default -c\")\n\n        pref2 = _create(self.c_v2, self.ref, conanfile=GenConanfile().with_build_msg(\"RREV 2!\"))\n        self.c_v2.run(f\"upload {pref2.ref} -r=default -c\")\n\n        assert pref1 != pref2\n\n        remover_client = self.c_v2\n\n        # Remove ref without revision in a remote\n        command = \"remove {} -c -r default\".format(repr(pref1.ref))\n        remover_client.run(command)\n        assert not self.server.recipe_exists(pref1.ref)\n        assert self.server.recipe_exists(pref2.ref)\n\n    def test_remove_remote_package(self):\n        \"\"\"When a client removes a package, without RREV, it removes the package from ALL\n        RREVs\"\"\"\n        pref1 = _create(self.c_v2, self.ref)\n        self.c_v2.run(f\"upload {pref1.ref} -r=default -c\")\n\n        pref2 = _create(self.c_v2, self.ref, conanfile=GenConanfile().with_build_msg(\"RREV 2!\"))\n        self.c_v2.run(f\"upload {pref2.ref} -r=default -c\")\n\n        assert pref1.package_id == pref2.package_id\n        # Both revisions exist in 2.0 cache\n        assert self.c_v2.package_exists(pref1)\n        assert self.c_v2.package_exists(pref2)\n\n        remover_client = self.c_v2\n\n        # Remove pref without RREV in a remote\n        remover_client.run(\"remove {}#*:{} -c -r default\".format(self.ref, pref2.package_id))\n        assert self.server.recipe_exists(pref1.ref)\n        assert self.server.recipe_exists(pref2.ref)\n        assert not self.server.package_exists(pref1)\n        assert not self.server.package_exists(pref2)\n\n    def test_remove_remote_package_revision(self):\n        \"\"\"When a client removes a package with PREV\n          (conan remove zlib/1.0@conan/stable:12312#PREV)\n            - If not RREV, the client fails\n            - If RREV and PREV:\n                - If v1 it fails in the client (cannot transmit revisions with v1)\n                - If v2 it removes only that PREV\n        \"\"\"\n        # First RREV\n        pref1 = _create(self.c_v2, self.ref)\n        self.c_v2.run(f\"upload {pref1.ref} -r=default -c\")\n\n        # Second RREV with two PREVS (exactly same conanfile, different package files)\n        rev2_conanfile = GenConanfile().with_build_msg(\"RREV 2!\")\\\n                                       .with_package_file(\"file\", env_var=\"MY_VAR\")\n        with environment_update({\"MY_VAR\": \"1\"}):\n            pref2 = _create(self.c_v2, self.ref, conanfile=rev2_conanfile)\n            self.c_v2.run(f\"upload {pref2.ref} -r=default -c\")\n\n        with environment_update({\"MY_VAR\": \"2\"}):\n            pref2b = _create(self.c_v2, self.ref, conanfile=rev2_conanfile)\n            self.c_v2.run(f\"upload {pref2b.ref} -r=default -c\")\n\n        # Check created revisions\n        assert pref1.package_id == pref2.package_id\n        assert pref2.package_id == pref2b.package_id\n        assert pref2.ref.revision == pref2b.ref.revision\n        assert pref2.revision != pref2b.revision\n\n        remover_client = self.c_v2\n\n        # Remove PREV without RREV in a remote, the client has to fail\n        command = \"remove {}:{}#{} -c -r default\".format(self.ref, pref2.package_id, pref2.revision)\n        remover_client.run(command)\n\n        assert self.server.recipe_exists(pref1.ref)\n        assert self.server.recipe_exists(pref2.ref)\n        assert self.server.recipe_exists(pref2b.ref)\n        assert self.server.package_exists(pref1)\n        assert self.server.package_exists(pref2b)\n        assert not self.server.package_exists(pref2)\n\n        # Try to remove a missing revision\n        command = \"remove {}:{}#fakerev -c -r default\".format(repr(pref2.ref), pref2.package_id)\n        remover_client.run(command, assert_error=True)\n        fakeref = copy.copy(pref2)\n        fakeref.revision = \"fakerev\"\n        assert f\"ERROR: Package revision '{fakeref.repr_notime()}' not found\" in remover_client.out\n\n\nclass TestUploadPackagesWithRevisions:\n\n    @pytest.fixture(autouse=True)\n    def setup(self):\n        self.server = TestServer()\n        self.c_v2 = TestClient(servers={\"default\": self.server}, inputs=[\"admin\", \"password\"])\n        self.ref = RecipeReference.loads(\"lib/1.0@conan/testing\")\n\n    def test_upload_a_recipe(self):\n        \"\"\"If we upload a package to a server:\n        Using v2 client it will upload RREV revision to the server. The rev time is NOT updated.\n        \"\"\"\n        client = self.c_v2\n        pref = _create(self.c_v2, self.ref)\n        client.run(f\"upload {self.ref} -r=default -c\")\n        revs = [r.revision for r in self.server.server_store.get_recipe_revisions_references(self.ref)]\n\n        assert revs == [pref.ref.revision]\n\n    def test_upload_no_overwrite_recipes(self):\n        \"\"\"If we upload a RREV to the server and create a new RREV in the client,\n        when we upload with --no-overwrite\n        Using v2 client it will warn an upload a new revision.\n        \"\"\"\n        client = self.c_v2\n        pref = _create(self.c_v2, self.ref, conanfile=GenConanfile().with_setting(\"os\"),\n                       args=\" -s os=Windows\")\n        client.run(f\"upload {self.ref} -r=default -c\")\n\n        pref2 = _create(self.c_v2, self.ref,\n                        conanfile=GenConanfile().with_setting(\"os\").with_build_msg(\"rev2\"),\n                        args=\" -s os=Linux\")\n\n        assert self.server.server_store.get_last_revision(self.ref)[0] == pref.ref.revision\n        client.run(f\"upload {self.ref} -r=default -c\")\n        assert self.server.server_store.get_last_revision(self.ref)[0] == pref2.ref.revision\n\n    def test_upload_no_overwrite_packages(self):\n        \"\"\"If we upload a PREV to the server and create a new PREV in the client,\n        when we upload with --no-overwrite\n        Using v2 client it will warn and upload a new revision.\n        \"\"\"\n        client = self.c_v2\n        conanfile = GenConanfile().with_package_file(\"file\", env_var=\"MY_VAR\")\n        with environment_update({\"MY_VAR\": \"1\"}):\n            pref = _create(self.c_v2, self.ref, conanfile=conanfile)\n        client.run(f\"upload {self.ref} -r=default -c\")\n\n        with environment_update({\"MY_VAR\": \"2\"}):\n            pref2 = _create(self.c_v2, self.ref, conanfile=conanfile)\n\n        assert pref.revision != pref2.revision\n\n        assert self.server.server_store.get_last_package_revision(pref2).revision == pref.revision\n        client.run(f\"upload {self.ref} -r=default -c\")\n        assert self.server.server_store.get_last_package_revision(pref2).revision == pref2.revision\n\n\ndef test_server_with_only_v2_capability():\n    server = TestServer(server_capabilities=[])\n    c_v2 = TestClient(servers={\"default\": server}, inputs=[\"admin\", \"password\"])\n    c_v2.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n    c_v2.run(\"create .\")\n    c_v2.run(f\"upload * -r=default -c\")\n\n\nclass TestServerRevisionsIndexes:\n\n    @pytest.fixture(autouse=True)\n    def setup(self):\n        self.server = TestServer()\n        self.c_v2 = TestClient(servers={\"default\": self.server}, inputs=[\"admin\", \"password\"])\n        self.ref = RecipeReference.loads(\"lib/1.0@conan/testing\")\n\n    def test_rotation_deleting_recipe_revisions(self):\n        \"\"\"\n        - If we have two RREVs in the server and we remove the first one,\n        the last one is the latest\n        - If we have two RREvs in the server and we remove the second one,\n        the first is now the latest\n        \"\"\"\n        ref1 = self.c_v2.export(self.ref, conanfile=GenConanfile())\n        self.c_v2.run(f\"upload {ref1} -r=default -c\")\n        assert self.server.server_store.get_last_revision(self.ref).revision == ref1.revision\n        ref2 = self.c_v2.export(self.ref, conanfile=GenConanfile().with_build_msg(\"I'm rev2\"))\n        self.c_v2.run(f\"upload {ref2} -r=default -c\")\n        assert self.server.server_store.get_last_revision(self.ref).revision == ref2.revision\n        ref3 = self.c_v2.export(self.ref, conanfile=GenConanfile().with_build_msg(\"I'm rev3\"))\n        self.c_v2.run(f\"upload {ref2} -r=default -c\")\n        assert self.server.server_store.get_last_revision(self.ref).revision == ref3.revision\n\n        revs = [r.revision for r in self.server.server_store.get_recipe_revisions_references(self.ref)]\n        assert revs == [ref3.revision, ref2.revision, ref1.revision]\n        assert self.server.server_store.get_last_revision(self.ref).revision == ref3.revision\n\n        # Delete the latest from the server\n        self.c_v2.run(\"remove {} -r default -c\".format(repr(ref3)))\n        revs = [r.revision for r in self.server.server_store.get_recipe_revisions_references(self.ref)]\n        assert revs == [ref2.revision, ref1.revision]\n        assert self.server.server_store.get_last_revision(self.ref).revision == ref2.revision\n\n    def test_rotation_deleting_package_revisions(self):\n        \"\"\"\n        - If we have two PREVs in the server and we remove the first one,\n        the last one is the latest\n        - If we have two PREVs in the server and we remove the second one,\n        the first is now the latest\n        \"\"\"\n        conanfile = GenConanfile().with_package_file(\"file\", env_var=\"MY_VAR\")\n        with environment_update({\"MY_VAR\": \"1\"}):\n            pref1 = _create(self.c_v2, self.ref, conanfile=conanfile)\n        self.c_v2.run(\"upload * -r=default -c\")\n        assert self.server.server_store.get_last_package_revision(pref1).revision == pref1.revision\n        with environment_update({\"MY_VAR\": \"2\"}):\n            pref2 = _create(self.c_v2, self.ref, conanfile=conanfile)\n        self.c_v2.run(\"upload * -r=default -c\")\n        assert self.server.server_store.get_last_package_revision(pref1).revision == pref2.revision\n        with environment_update({\"MY_VAR\": \"3\"}):\n            pref3 = _create(self.c_v2, self.ref, conanfile=conanfile)\n        self.c_v2.run(\"upload * -r=default -c\")\n        assert self.server.server_store.get_last_package_revision(pref1).revision == pref3.revision\n\n        assert pref1.ref.revision == pref2.ref.revision\n        assert pref2.ref.revision == pref3.ref.revision\n        assert pref3.ref.revision == pref3.ref.revision\n\n        pref = copy.copy(pref1)\n        pref.revision = None\n        revs = [r.revision\n                for r in self.server.server_store.get_package_revisions_references(pref)]\n        assert revs == [pref3.revision, pref2.revision, pref1.revision]\n        assert self.server.server_store.get_last_package_revision(pref).revision == pref3.revision\n\n        # Delete the latest from the server\n        self.c_v2.run(\"remove {}:{}#{} -r default -c\".format(repr(pref3.ref), pref3.package_id,\n                                                             pref3.revision))\n        revs = [r.revision\n                for r in self.server.server_store.get_package_revisions_references(pref)]\n        assert revs == [pref2.revision, pref1.revision]\n        assert self.server.server_store.get_last_package_revision(pref).revision == pref2.revision\n\n    def test_deleting_all_rrevs(self):\n        \"\"\"\n        If we delete all the recipe revisions in the server. There is no latest.\n        If then a client uploads a RREV it is the latest\n        \"\"\"\n        ref1 = self.c_v2.export(self.ref, conanfile=GenConanfile())\n        self.c_v2.run(\"upload * -r=default -c\")\n        ref2 = self.c_v2.export(self.ref, conanfile=GenConanfile().with_build_msg(\"I'm rev2\"))\n        self.c_v2.run(\"upload * -r=default -c\")\n        ref3 = self.c_v2.export(self.ref, conanfile=GenConanfile().with_build_msg(\"I'm rev3\"))\n        self.c_v2.run(\"upload * -r=default -c\")\n\n        self.c_v2.run(\"remove {} -r default -c\".format(repr(ref1)))\n        self.c_v2.run(\"remove {} -r default -c\".format(repr(ref2)))\n        self.c_v2.run(\"remove {} -r default -c\".format(repr(ref3)))\n\n        with pytest.raises(RecipeNotFoundException):\n            self.server.server_store.get_recipe_revisions_references(self.ref)\n\n        ref4 = self.c_v2.export(self.ref, conanfile=GenConanfile().with_build_msg(\"I'm rev4\"))\n        self.c_v2.run(\"upload * -r=default -c\")\n\n        revs = [r.revision for r in self.server.server_store.get_recipe_revisions_references(self.ref)]\n        assert revs == [ref4.revision]\n\n    def test_deleting_all_prevs(self):\n        \"\"\"\n        If we delete all the package revisions in the server. There is no latest.\n        If then a client uploads a RREV/PREV it is the latest\n        \"\"\"\n        conanfile = GenConanfile().with_package_file(\"file\", env_var=\"MY_VAR\")\n        with environment_update({\"MY_VAR\": \"1\"}):\n            pref1 = _create(self.c_v2, self.ref, conanfile=conanfile)\n        self.c_v2.run(f\"upload {self.ref} -r=default -c\")\n        with environment_update({\"MY_VAR\": \"2\"}):\n            pref2 = _create(self.c_v2, self.ref, conanfile=conanfile)\n        self.c_v2.run(f\"upload {self.ref} -r=default -c\")\n        with environment_update({\"MY_VAR\": \"3\"}):\n            pref3 = _create(self.c_v2, self.ref, conanfile=conanfile)\n        self.c_v2.run(f\"upload {self.ref} -r=default -c\")\n\n        # Delete the package revisions (all of them have the same ref#rev and id)\n        command = \"remove {}:{}#{{}} -r default -c\".format(pref3.ref.repr_notime(), pref3.package_id)\n        self.c_v2.run(command.format(pref3.revision))\n        self.c_v2.run(command.format(pref2.revision))\n        self.c_v2.run(command.format(pref1.revision))\n\n        with environment_update({\"MY_VAR\": \"4\"}):\n            pref4 = _create(self.c_v2, self.ref, conanfile=conanfile)\n        self.c_v2.run(\"upload {} -r default -c\".format(pref4.repr_notime()))\n\n        pref = copy.copy(pref1)\n        pref.revision = None\n        revs = [r.revision\n                for r in self.server.server_store.get_package_revisions_references(pref)]\n        assert revs == [pref4.revision]\n\n\ndef test_touching_other_server():\n    # https://github.com/conan-io/conan/issues/9333\n    servers = OrderedDict([(\"remote1\", TestServer()),\n                           (\"remote2\", None)])  # None server will crash if touched\n    c = TestClient(servers=servers, inputs=[\"admin\", \"password\"])\n    c.save({\"conanfile.py\": GenConanfile().with_settings(\"os\")})\n    c.run(\"create . --name=pkg --version=0.1 --user=conan --channel=channel -s os=Windows\")\n    c.run(\"upload * -c -r=remote1\")\n    c.run(\"remove * -c\")\n\n    # This is OK, binary found\n    c.run(\"install --requires=pkg/0.1@conan/channel -r=remote1 -s os=Windows\")\n    c.run(\"install --requires=pkg/0.1@conan/channel -r=remote1 -s os=Linux\", assert_error=True)\n    assert \"ERROR: Missing binary: pkg/0.1@conan/channel\" in c.out\n\n\n@pytest.mark.artifactory_ready\ndef test_reupload_older_revision():\n    \"\"\" upload maintains the server history\n        https://github.com/conan-io/conan/issues/7331\n    \"\"\"\n    c = TestClient(default_server_user=True)\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n    c.run(\"export .\")\n    rrev1 = c.exported_recipe_revision()\n    c.run(\"upload * -r=default -c\")\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_class_attribute(\"potato = 42\")})\n    c.run(\"export .\")\n    rrev2 = c.exported_recipe_revision()\n    c.run(\"upload * -r=default -c\")\n\n    def check_order(inverse=False):\n        c.run(\"list pkg/0.1#* -r=default\")\n        out = str(c.out)\n        assert rrev1 in out\n        assert rrev2 in out\n        if inverse:\n            assert out.find(rrev1) > out.find(rrev2)\n        else:\n            assert out.find(rrev1) < out.find(rrev2)\n\n    check_order()\n\n    # If we create the same older revision, and upload, still the same order\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n    c.run(\"export .\")\n    c.run(\"upload * -r=default -c\")\n    check_order()\n\n    # Force doesn't change it, same order\n    c.run(\"upload * -r=default -c --force\")\n    check_order()\n\n    # the only way is to remove it, then upload\n    c.run(f\"remove pkg/0.1#{rrev1} -r=default -c\")\n    c.run(\"upload * -r=default -c --force\")\n    check_order(inverse=True)\n\n\n@pytest.mark.artifactory_ready\ndef test_reupload_older_revision_new_binaries():\n    \"\"\" upload maintains the server history\n        https://github.com/conan-io/conan/pull/16621\n    \"\"\"\n    c = TestClient(default_server_user=True)\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_settings(\"os\")})\n    c.run(\"create . -s os=Linux\")\n    rrev1 = c.exported_recipe_revision()\n    c.run(\"upload * -r=default -c\")\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_settings(\"os\")\n                                                      .with_class_attribute(\"potato = 42\")})\n    c.run(\"create . -s os=Linux\")\n    rrev2 = c.exported_recipe_revision()\n    c.run(\"upload * -r=default -c\")\n\n    def check_order():\n        c.run(\"list pkg/0.1#* -r=default\")\n        out = str(c.out)\n        assert rrev1 in out\n        assert rrev2 in out\n        assert out.find(rrev1) < out.find(rrev2)\n\n    check_order()\n\n    # If we create the same older revision, and upload, still the same order\n    # c.run(\"remove * -c\")  # Make sure no other revision\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_settings(\"os\")})\n    c.run(\"create . -s os=Windows\")\n    rrev3 = c.exported_recipe_revision()\n    assert rrev3 == rrev1\n    c.run(f\"upload pkg*#{rrev3} -r=default -c --force\")\n    check_order()\n"
  },
  {
    "path": "test/functional/sbom/__init__.py",
    "content": ""
  },
  {
    "path": "test/functional/sbom/test_cyclonedx.py",
    "content": "import json\nimport os\n\nimport pytest\n\nfrom conan.internal.util.files import save\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n# Using the sbom tool with \"conan create\"\nsbom_hook_post_package = \"\"\"\nimport json\nimport os\nfrom conan.errors import ConanException\nfrom conan.api.output import ConanOutput\nfrom conan.tools.sbom import cyclonedx_1_4, cyclonedx_1_6\n\ndef post_package(conanfile):\n    sbom_cyclonedx_1_4 = cyclonedx_1_4(conanfile, add_build=True, add_tests=True)\n    sbom_cyclonedx_1_6 = cyclonedx_1_6(conanfile, add_build=True, add_tests=True)\n    with open(os.path.join(conanfile.package_metadata_folder, \"sbom14.cdx.json\"), 'w') as f:\n        json.dump(sbom_cyclonedx_1_4, f, indent=4)\n    with open(os.path.join(conanfile.package_metadata_folder, \"sbom16.cdx.json\"), 'w') as f:\n        json.dump(sbom_cyclonedx_1_6, f, indent=4)\n\"\"\"\n\n\nclass TestCyclonedx:\n\n    @pytest.fixture()\n    def hook_setup_post_package_tl(self, transitive_libraries):\n        tc = transitive_libraries\n        hook_path = os.path.join(tc.paths.hooks_path, \"hook_sbom.py\")\n        save(hook_path, sbom_hook_post_package)\n        return tc\n\n    @pytest.mark.tool(\"cmake\")\n    def test_sbom_generation_create(self, hook_setup_post_package_tl):\n        # TODO This doesn't need to be a functional test, check why\n        tc = hook_setup_post_package_tl\n        tc.run(\"new cmake_lib -d name=bar -d version=1.0 -d requires=engine/1.0 -f\")\n        # bar -> engine/1.0 -> matrix/1.0\n        tc.run(\"create . -tf=\")\n        bar_layout = tc.created_layout()\n        assert os.path.exists(os.path.join(bar_layout.metadata(), \"sbom14.cdx.json\"))\n        assert os.path.exists(os.path.join(bar_layout.metadata(), \"sbom16.cdx.json\"))\n\n    @pytest.mark.tool(\"cmake\")\n    @pytest.mark.parametrize(\"user, channel, user_dep, channel_dep\",\n                             [(\"user\", None, \"user_dep\", None),\n                              (\"user\", \"channel\", \"user_dep\", \"channel_dep\")])\n    def test_sbom_user_path(self, user, channel, user_dep, channel_dep):\n        tc = TestClient(light=True)\n        hook_path = os.path.join(tc.paths.hooks_path, \"hook_sbom.py\")\n        save(hook_path, sbom_hook_post_package)\n        channel_ref = f\"/{channel_dep}\" if channel_dep else \"\"\n        tc.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"1.0\"),\n                 \"conanfile.py\": GenConanfile(\"main\", \"1.0\").with_requires(\n                     f\"dep/1.0@{user_dep}{channel_ref}\")})\n        command = \"create dep\"\n        if user:\n            command += f\" --user={user_dep}\"\n        if channel:\n            command += f\" --channel={channel_dep}\"\n\n        tc.run(command)\n\n        command = \"create .\"\n        if user:\n            command += f\" --user={user}\"\n        if channel:\n            command += f\" --channel={channel}\"\n        tc.run(command)\n\n        for version in (\"14\", \"16\"):\n            create_layout = tc.created_layout()\n            cyclone_path = os.path.join(create_layout.metadata(), f\"sbom{version}.cdx.json\")\n            content = tc.load(cyclone_path)\n            content_json = json.loads(content)\n\n            assert content_json[\"components\"][0][\"bom-ref\"].split(\"&user=\")[\n                       1] == f\"{user}&channel={channel}\" if channel else user\n            assert content_json[\"dependencies\"][0][\"dependsOn\"][0].split(\"&user=\")[\n                       1] == f\"{user_dep}&channel={channel_dep}\" if channel_dep else user_dep\n"
  },
  {
    "path": "test/functional/subsystems_build_test.py",
    "content": "import platform\nimport tempfile\n\nimport pytest\nimport textwrap\n\nfrom conan.test.assets.autotools import gen_makefile\nfrom conan.test.assets.sources import gen_function_cpp\nfrom test.functional.utils import check_exe_run, check_vs_runtime\nfrom conan.test.utils.tools import TestClient\nfrom conan.test.utils.env import environment_update\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Tests Windows Subsystems\")\nclass TestSubsystems:\n\n    @pytest.mark.tool(\"msys2\")\n    def test_msys2_available(self):\n        \"\"\"\n        Msys2 needs to be installed:\n        - Go to https://www.msys2.org/, download the exe installer and run it\n        - Follow instructions in https://www.msys2.org/ to update the package DB\n        - Install msys2 autotools \"pacman -S autotools\"\n        - Make sure the entry in conftest_user.py of msys2 points to the right location\n        \"\"\"\n        client = TestClient()\n        client.run_command('uname')\n        assert \"MSYS\" in client.out\n\n    @pytest.mark.tool(\"cygwin\")\n    def test_cygwin_available(self):\n        \"\"\" Cygwin is necessary\n        - Install from https://www.cygwin.com/install.html, use the default packages\n        - Install automake 1.16, gcc-g++, make and binutils packages (will add autoconf and more)\n        - Make sure that the path in conftest_user.py is pointing to cygwin \"bin\" folder\n        \"\"\"\n        client = TestClient()\n        client.run_command('uname')\n        assert \"CYGWIN\" in client.out\n\n    @pytest.mark.tool(\"msys2\")\n    @pytest.mark.tool(\"mingw32\")\n    def test_mingw32_available(self):\n        \"\"\" Mingw32 needs to be installed. We use msys2, don't know if others work\n        - Inside msys2, install pacman -S mingw-w64-i686-toolchain (all pkgs)\n        \"\"\"\n        client = TestClient()\n        client.run_command('uname')\n        assert \"MINGW32_NT\" in client.out\n\n    @pytest.mark.tool(\"msys2\")\n    @pytest.mark.tool(\"ucrt64\")\n    def test_ucrt64_available(self):\n        \"\"\" ucrt64 needs to be installed. We use msys2, don't know if others work\n        - Inside msys2, install pacman -S mingw-w64-ucrt-x86_64-toolchain (all pkgs)\n        \"\"\"\n        client = TestClient()\n        client.run_command('uname')\n        assert \"MINGW64_NT\" in client.out\n\n    @pytest.mark.tool(\"msys2\")\n    @pytest.mark.tool(\"msys2_clang64\")\n    def test_clang64_available(self):\n        client = TestClient()\n        client.run_command('uname')\n        assert \"MINGW64_NT\" in client.out\n\n    @pytest.mark.tool(\"msys2\")\n    @pytest.mark.tool(\"mingw64\")\n    def test_mingw64_available(self):\n        \"\"\" Mingw64 needs to be installed. We use msys2, don't know if others work\n        - Inside msys2, install pacman -S mingw-w64-x86_64-toolchain (all pkgs)\n        \"\"\"\n        client = TestClient()\n        client.run_command('uname')\n        assert \"MINGW64_NT\" in client.out\n\n    # It's important not to have uname in Path, that could\n    # mean that we have Git bash or MingW in the Path and\n    # we mistakenly use tools from there when we want to use msys2 tools\n    def test_tool_not_available(self):\n        client = TestClient()\n        client.run_command('uname', assert_error=True)\n        assert \"'uname' is not recognized as an internal or external command\" in client.out\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Tests Windows Subsystems\")\nclass TestSubsystemsBuild:\n\n    @staticmethod\n    def _build(client, static_runtime=None, make=\"make\"):\n        makefile = gen_makefile(apps=[\"app\"], static_runtime=static_runtime)\n        main_cpp = gen_function_cpp(name=\"main\")\n        client.save({\"Makefile\": makefile,\n                     \"app.cpp\": main_cpp})\n        client.run_command(make)\n        client.run_command(\"app\")\n\n    @pytest.mark.tool(\"msys2\")\n    @pytest.mark.parametrize(\"static\", [True, False])\n    def test_msys2(self, static):\n        \"\"\"\n        native MSYS environment, binaries depend on MSYS runtime (msys-2.0.dll)\n        Install:\n        - pacman -S gcc\n        posix-compatible, intended to be run only in MSYS environment (not in pure Windows)\n        \"\"\"\n        client = TestClient()\n        self._build(client, static_runtime=static)\n\n        check_exe_run(client.out, \"main\", \"gcc\", None, \"Debug\", \"x86_64\", None, subsystem=\"msys2\")\n        assert \"_M_X64\" not in client.out\n        # TODO: Do not hardcode the visual version\n        check_vs_runtime(\"app.exe\", client, \"15\", \"Debug\", static_runtime=static,\n                         subsystem=\"msys2\")\n\n    @pytest.mark.parametrize(\"static\", [True, False])\n    @pytest.mark.tool(\"mingw\")\n    def test_mingw(self, static):\n        \"\"\"\n        This will work if you installed the Mingw toolchain outside msys2, from\n        https://sourceforge.net/projects/mingw/, and installed gcc, autotools, mingw32-make, etc\n\n        But this doesn't contain \"make\", only \"mingw32-make\"\n        \"\"\"\n        client = TestClient()\n        self._build(client, static_runtime=static, make=\"mingw32-make\")\n\n        check_exe_run(client.out, \"main\", \"gcc\", None, \"Debug\", \"x86\", None, subsystem=\"mingw32\")\n        check_vs_runtime(\"app.exe\", client, \"15\", \"Debug\", static_runtime=static,\n                         subsystem=\"mingw64\")\n\n    @pytest.mark.parametrize(\"static\", [True, False])\n    @pytest.mark.tool(\"msys2\")\n    @pytest.mark.tool(\"mingw64\")\n    def test_mingw64(self, static):\n        \"\"\"\n        This will work if you installed the Mingw toolchain inside msys2 as TestSubystems above\n        64-bit GCC, binaries\n        \"\"\"\n        client = TestClient()\n        # pacman -S mingw-w64-x86_64-gcc\n        self._build(client, static_runtime=static)\n\n        check_exe_run(client.out, \"main\", \"gcc\", None, \"Debug\", \"x86_64\", None, subsystem=\"mingw64\")\n        # it also defines the VS 64 bits macro\n        assert \"main _M_X64 defined\" in client.out\n        check_vs_runtime(\"app.exe\", client, \"15\", \"Debug\", static_runtime=static,\n                         subsystem=\"mingw64\")\n\n    @pytest.mark.parametrize(\"static\", [True, False])\n    @pytest.mark.tool(\"msys2\")\n    @pytest.mark.tool(\"msys2_clang64\")\n    def test_msys2_clang64(self, static):\n        \"\"\"\n        in msys2\n        $ pacman -S mingw-w64-x86_64-clang (NO, this is the mingw variant in ming64)\n        $ pacman -S mingw-w64-clang-x86_64-toolchain\n        \"\"\"\n        client = TestClient()\n        # Not defined in msys2 clang by default\n        with environment_update({\"CC\": \"clang\", \"CXX\": \"clang++\"}):\n            self._build(client, static_runtime=static)\n\n        check_exe_run(client.out, \"main\", \"clang\", None, \"Debug\", \"x86_64\", None,\n                      subsystem=\"mingw64\")\n        # it also defines the VS 64 bits macro\n        assert \"main _M_X64 defined\" in client.out\n        check_vs_runtime(\"app.exe\", client, \"15\", \"Debug\", static_runtime=static,\n                         subsystem=\"clang64\")\n\n    @pytest.mark.tool(\"msys2\")\n    @pytest.mark.tool(\"mingw64\")\n    def test_mingw64_recipe(self):\n        \"\"\"\n        A recipe with self.run_bash=True and msys2 configured, using mingw to build stuff with make\n        from the subsystem\n        \"\"\"\n        client = TestClient()\n        makefile = gen_makefile(apps=[\"app\"])\n        main_cpp = gen_function_cpp(name=\"main\")\n        conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.gnu import Autotools\n        from conan.tools.layout import basic_layout\n        from conan.tools.files import copy\n        class HelloConan(ConanFile):\n            exports_sources = \"*.cpp\", \"Makefile\"\n            generators = \"AutotoolsToolchain\"\n            win_bash = True\n\n            def build(self):\n                self.output.warning(self.build_folder)\n                auto = Autotools(self)\n                auto.make()\n\n            def package(self):\n                copy(self, \"app*\", self.build_folder, os.path.join(self.package_folder, \"bin\"))\n\n        \"\"\")\n        test_conanfile = textwrap.dedent(\"\"\"\n                import os\n                from conan import ConanFile\n                class TestConan(ConanFile):\n\n                    def requirements(self):\n                        self.tool_requires(self.tested_reference_str)\n\n                    def test(self):\n                        self.run(\"app\")\n                \"\"\")\n        profile = textwrap.dedent(\"\"\"\n        include(default)\n        [conf]\n        tools.microsoft.bash:subsystem=msys2\n        tools.microsoft.bash:path=bash\n        \"\"\")\n        client.save({\"conanfile.py\": conanfile,\n                     \"Makefile\": makefile,\n                     \"app.cpp\": main_cpp,\n                     \"test_package/conanfile.py\": test_conanfile,\n                     \"myprofile\": profile})\n\n        client.run(\"create . --name foo --version 1.0 --profile:build myprofile --build-require\")\n        assert \"__MINGW64__\" in client.out\n        assert \"__CYGWIN__\" not in client.out\n\n    @pytest.mark.tool(\"msys2\")\n    @pytest.mark.tool(\"msys2_mingw64_clang64\")\n    def test_msys2_mingw64_clang64(self):\n        \"\"\"\n        in msys2\n        $ pacman -S mingw-w64-x86_64-clang\n        $ pacman -S mingw-w64-clang-x86_64-toolchain (NO, this is the clang)\n        \"\"\"\n        client = TestClient()\n        static = False  # This variant needs --static-glibc -static-libstdc++ (weird) to link static\n        # Need to redefine CXX otherwise is gcc\n        with environment_update({\"CXX\": \"clang++\"}):\n            self._build(client, static_runtime=static)\n\n        check_exe_run(client.out, \"main\", \"clang\", None, \"Debug\", \"x86_64\", None,\n                      subsystem=\"mingw64\")\n        # it also defines the VS 64 bits macro\n        assert \"main _M_X64 defined\" in client.out\n        check_vs_runtime(\"app.exe\", client, \"15\", \"Debug\", static_runtime=static,\n                         subsystem=\"mingw64\")\n\n    @pytest.mark.parametrize(\"static\", [True, False])\n    @pytest.mark.tool(\"msys2\")\n    @pytest.mark.tool(\"mingw32\")\n    def test_mingw32(self, static):\n        \"\"\"\n        This will work if you installed the Mingw toolchain inside msys2 as TestSubystems above\n        32-bit GCC, binaries for generic Windows (no dependency on MSYS runtime)\n        \"\"\"\n        client = TestClient()\n        # pacman -S mingw-w64-i686-gcc\n        self._build(client, static_runtime=static)\n\n        check_exe_run(client.out, \"main\", \"gcc\", None, \"Debug\", \"x86\", None, subsystem=\"mingw32\")\n        # It also defines the VS flag\n        assert \"main _M_IX86 defined\" in client.out\n        check_vs_runtime(\"app.exe\", client, \"15\", \"Debug\", static_runtime=static,\n                         subsystem=\"mingw32\")\n\n    @pytest.mark.parametrize(\"static\", [True, False])\n    @pytest.mark.tool(\"msys2\")\n    @pytest.mark.tool(\"ucrt64\")\n    def test_ucrt64(self, static):\n        \"\"\"\n        This will work if you installed the Mingw toolchain inside msys2 as TestSubystems above\n        \"\"\"\n        client = TestClient()\n        self._build(client, static_runtime=static)\n        check_exe_run(client.out, \"main\", \"gcc\", None, \"Debug\", \"x86_64\", None, subsystem=\"mingw32\")\n        # it also defines the VS macro\n        assert \"main _M_X64 defined\" in client.out\n        check_vs_runtime(\"app.exe\", client, \"15\", \"Debug\", static_runtime=static,\n                         subsystem=\"ucrt64\")\n\n    @pytest.mark.parametrize(\"static\", [True, False])\n    @pytest.mark.tool(\"cygwin\")\n    def test_cygwin(self, static):\n        \"\"\"\n        Cygwin environment, binaries depend on Cygwin runtime (cygwin1.dll)\n        posix-compatible, intended to be run only in Cygwin environment (not in pure Windows)\n        \"\"\"\n        client = TestClient()\n        self._build(client, static_runtime=static)\n        check_exe_run(client.out, \"main\", \"gcc\", None, \"Debug\", \"x86_64\", None, subsystem=\"cygwin\")\n        check_vs_runtime(\"app.exe\", client, \"15\", \"Debug\", static_runtime=static,\n                         subsystem=\"cygwin\")\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Tests Windows Subsystems\")\nclass TestSubsystemsAutotoolsBuild:\n    configure_ac = textwrap.dedent(\"\"\"\n        AC_INIT([Tutorial Program], 1.0)\n        AM_INIT_AUTOMAKE([foreign])\n        AC_PROG_CXX\n        AC_CONFIG_FILES(Makefile)\n        AC_OUTPUT\n        \"\"\")  # newline is important\n\n    makefile_am = textwrap.dedent(\"\"\"\n        bin_PROGRAMS = app\n        app_SOURCES = main.cpp\n        \"\"\")\n\n    def _build(self, client):\n        main_cpp = gen_function_cpp(name=\"main\")\n        client.save({\"configure.ac\": self.configure_ac,\n                     \"Makefile.am\": self.makefile_am,\n                     \"main.cpp\": main_cpp})\n\n        path = client.current_folder  # Seems unix_path not necessary for this to pass\n        client.run_command('bash -lc \"cd \\\\\"%s\\\\\" && autoreconf -fiv\"' % path)\n        client.run_command('bash -lc \"cd \\\\\"%s\\\\\" && ./configure\"' % path)\n        client.run_command(\"make\")\n        client.run_command(\"app\")\n\n    @pytest.mark.tool(\"msys2\")\n    def test_msys(self):\n        \"\"\"\n        native MSYS environment, binaries depend on MSYS runtime (msys-2.0.dll)\n        posix-compatible, intended to be run only in MSYS environment (not in pure Windows)\n        \"\"\"\n        client = TestClient()\n        # pacman -S gcc\n        self._build(client)\n        check_exe_run(client.out, \"main\", \"gcc\", None, \"Debug\", \"x86_64\", None, subsystem=\"msys2\")\n        check_vs_runtime(\"app.exe\", client, \"15\", \"Debug\", subsystem=\"msys2\")\n\n    @pytest.mark.tool(\"msys2\")\n    @pytest.mark.tool(\"mingw64\")\n    def test_mingw64(self):\n        \"\"\"\n        64-bit GCC, binaries for generic Windows (no dependency on MSYS runtime)\n        \"\"\"\n        client = TestClient()\n        # pacman -S mingw-w64-x86_64-gcc\n        self._build(client)\n        check_exe_run(client.out, \"main\", \"gcc\", None, \"Debug\", \"x86_64\", None, subsystem=\"mingw64\")\n        check_vs_runtime(\"app.exe\", client, \"15\", \"Debug\", subsystem=\"mingw64\")\n\n    @pytest.mark.tool(\"msys2\")\n    @pytest.mark.tool(\"mingw32\")\n    def test_mingw32(self):\n        \"\"\"\n        32-bit GCC, binaries for generic Windows (no dependency on MSYS runtime)\n        \"\"\"\n        client = TestClient()\n        # pacman -S mingw-w64-i686-gcc\n        self._build(client)\n        check_exe_run(client.out, \"main\", \"gcc\", None, \"Debug\", \"x86\", None, subsystem=\"mingw32\")\n        check_vs_runtime(\"app.exe\", client, \"15\", \"Debug\", subsystem=\"mingw32\")\n\n    @pytest.mark.tool(\"cygwin\")\n    def test_cygwin(self):\n        \"\"\"\n        Cygwin environment, binaries depend on Cygwin runtime (cygwin1.dll)\n        posix-compatible, intended to be run only in Cygwin environment (not in pure Windows)\n        # install autotools, autoconf, libtool, \"gcc-c++\" and \"make\" packages\n        \"\"\"\n        client = TestClient()\n        self._build(client)\n        check_exe_run(client.out, \"main\", \"gcc\", None, \"Debug\", \"x86_64\", None, subsystem=\"cygwin\")\n        check_vs_runtime(\"app.exe\", client, \"15\", \"Debug\", subsystem=\"cygwin\")\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Tests Windows Subsystems\")\nclass TestSubsystemsCMakeBuild:\n    \"\"\" These tests are running the CMake INSIDE THE subsystem, not the Windows native one\n    The results are basically the same if CMake is outside the subsystem, but it is NOT\n    enough to define CMAKE_CXX_COMPILER full path to the compiler, but it must be in the path\n\n    \"\"\"\n    cmakelists = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.15)\n        project(app CXX)\n        message(STATUS \"MYCMAKE VERSION=${CMAKE_VERSION}\")\n        add_executable(app main.cpp)\n        \"\"\")\n\n    def _build(self, client, generator=\"Unix Makefiles\", compiler=None, toolset=None):\n        main_cpp = gen_function_cpp(name=\"main\")\n        client.save({\"CMakeLists.txt\": self.cmakelists,\n                     \"main.cpp\": main_cpp})\n\n        cmake_compiler = \"\"\n        if compiler:\n            cmake_compiler += \" -DCMAKE_C_COMPILER={}\".format(compiler)\n            compilerpp = \"clang++\" if compiler == \"clang\" else \"g++\"\n            cmake_compiler += \" -DCMAKE_CXX_COMPILER={}\".format(compilerpp)\n            cmake_compiler += \" -DCMAKE_RC_COMPILER={}\".format(compiler)\n        toolset = \"-T {}\".format(toolset) if toolset else \"\"\n        client.run_command(\"cmake {} {}\"\n                           \" -DCMAKE_SH=\\\"CMAKE_SH-NOTFOUND\\\" -G \\\"{}\\\" .\".format(cmake_compiler,\n                                                                                  toolset,\n                                                                                  generator))\n        build_out = client.out\n        client.run_command(\"cmake --build .\")\n        app = \"app\" if \"Visual\" not in generator else r\"Debug\\app\"\n        client.run_command(app)\n        return build_out\n\n    @pytest.mark.tool(\"msys2\")\n    def test_msys(self):\n        \"\"\"\n        pacman -S cmake\n        \"\"\"\n        client = TestClient()\n        self._build(client)\n        check_exe_run(client.out, \"main\", \"gcc\", None, \"Debug\", \"x86_64\", None, subsystem=\"msys2\")\n        check_vs_runtime(\"app.exe\", client, \"15\", \"Debug\", subsystem=\"msys2\")\n\n    @pytest.mark.tool(\"msys2\")\n    @pytest.mark.tool(\"mingw64\")\n    def test_mingw64(self):\n        \"\"\"\n        $ pacman -S mingw-w64-x86_64-cmake\n        \"\"\"\n        client = TestClient()\n        self._build(client, generator=\"MinGW Makefiles\")\n        check_exe_run(client.out, \"main\", \"gcc\", None, \"Debug\", \"x86_64\", None, subsystem=\"mingw64\")\n        check_vs_runtime(\"app.exe\", client, \"15\", \"Debug\", subsystem=\"mingw64\")\n\n    @pytest.mark.tool(\"msys2\")\n    @pytest.mark.tool(\"msys2_clang64\")\n    @pytest.mark.skip(reason=\"This doesn't work, seems CMake issue\")\n    def test_msys2_clang64(self):\n        \"\"\"\n        FAILS WITH:\n        System is unknown to cmake, create:\n        Platform/MINGW64_NT-10.0-19044 to use this system,\n        \"\"\"\n        client = TestClient()\n        self._build(client, generator=\"Unix Makefiles\")\n        check_exe_run(client.out, \"main\", \"clang\", None, \"Debug\", \"x86_64\", None,\n                      subsystem=\"mingw64\")\n        check_vs_runtime(\"app.exe\", client, \"15\", \"Debug\", subsystem=\"clang64\")\n\n    @pytest.mark.tool(\"msys2\")\n    @pytest.mark.tool(\"msys2_clang64\")\n    @pytest.mark.tool(\"cmake\", \"3.19\")\n    def test_msys2_clang64_external(self):\n        \"\"\"\n        Exactly the same as the previous tests, but with a native cmake 3.19 (higher priority)\n        \"\"\"\n        client = TestClient()\n        build_out = self._build(client)\n        assert \"MYCMAKE VERSION=3.19\" in build_out\n        check_exe_run(client.out, \"main\", \"clang\", None, \"Debug\", \"x86_64\", None,\n                      subsystem=\"mingw64\")\n        check_vs_runtime(\"app.exe\", client, \"15\", \"Debug\", subsystem=\"clang64\")\n\n    @pytest.mark.tool(\"msys2\")\n    @pytest.mark.tool(\"msys2_mingw64_clang64\")\n    def test_msys2_mingw64_clang64(self):\n        \"\"\"\n        \"\"\"\n        client = TestClient()\n        # IMPORTANT: Need to redefine the CXX, otherwise CMake will use GCC by default\n        with environment_update({\"CXX\": \"clang++\"}):\n            self._build(client, generator=\"MinGW Makefiles\")\n        check_exe_run(client.out, \"main\", \"clang\", None, \"Debug\", \"x86_64\", None,\n                      subsystem=\"mingw64\")\n        check_vs_runtime(\"app.exe\", client, \"15\", \"Debug\", subsystem=\"mingw64\")\n\n    @pytest.mark.tool(\"msys2\")\n    @pytest.mark.tool(\"mingw32\")\n    def test_mingw32(self):\n        \"\"\"\n        $ pacman -S mingw-w64-i686-cmake\n        \"\"\"\n        client = TestClient()\n        self._build(client, generator=\"MinGW Makefiles\")\n        check_exe_run(client.out, \"main\", \"gcc\", None, \"Debug\", \"x86\", None, subsystem=\"mingw32\")\n        check_vs_runtime(\"app.exe\", client, \"15\", \"Debug\", subsystem=\"mingw32\")\n\n    @pytest.mark.tool(\"cygwin\")\n    def test_cygwin(self):\n        \"\"\"\n        Needs to install cmake from the cygwin setup.exe\n        \"\"\"\n        client = TestClient()\n        # install \"gcc-c++\" and \"make\" packages\n        self._build(client)\n        check_exe_run(client.out, \"main\", \"gcc\", None, \"Debug\", \"x86_64\", None, subsystem=\"cygwin\")\n        check_vs_runtime(\"app.exe\", client, \"15\", \"Debug\", subsystem=\"cygwin\")\n\n    @pytest.mark.tool(\"ninja\")\n    @pytest.mark.tool(\"clang\", \"20\")\n    def test_clang(self):\n        \"\"\"\n        native, LLVM/Clang compiler\n        Installing the binary from LLVM site\n        https://github.com/llvm/llvm-project/releases/tag/llvmorg-14.0.6\n        \"\"\"\n        client = TestClient()\n        self._build(client, generator=\"Ninja\", compiler=\"clang\")\n        check_exe_run(client.out, \"main\", \"clang\", None, \"Debug\", \"x86_64\", None, subsystem=None)\n        check_vs_runtime(\"app.exe\", client, \"15\", \"Debug\", subsystem=None)\n\n    @pytest.mark.tool(\"cmake\", \"3.23\")\n    @pytest.mark.tool(\"visual_studio\", \"17\")\n    def test_vs_clang(self):\n        \"\"\"\n        native, LLVM/Clang compiler installed with VS 2022 -T ClangCL\n        \"\"\"\n        # IMPORTANT: VS CLang not found if in another unit\n        folder = tempfile.mkdtemp(suffix='conans')\n        client = TestClient(current_folder=folder)\n        self._build(client, generator=\"Visual Studio 17 2022\", toolset=\"ClangCL\")\n        check_exe_run(client.out, \"main\", \"clang\", None, \"Debug\", \"x86_64\", None, subsystem=None)\n        check_vs_runtime(\"Debug/app.exe\", client, \"15\", \"Debug\", subsystem=None)\n\n\n@pytest.mark.tool(\"msys2\")\ndef test_msys2_env_vars_paths():\n    c = TestClient()\n    # A tool-requires injecting PATHs for native, should not use \"_path\" calls, and use\n    # 'separator=;' explicitly\n    tool = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class HelloConan(ConanFile):\n            name = \"tool\"\n            version = \"0.1\"\n            def package_info(self):\n                self.buildenv_info.append(\"INCLUDE\", \"C:/mytool/path\", separator=\";\")\n        \"\"\")\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class HelloConan(ConanFile):\n            win_bash = True\n            tool_requires = \"tool/0.1\"\n\n            def build(self):\n                self.run('echo \"INCLUDE=$INCLUDE\"')\n        \"\"\")\n    profile = textwrap.dedent(\"\"\"\n        [conf]\n        tools.microsoft.bash:subsystem=msys2\n        tools.microsoft.bash:path=bash\n\n        [buildenv]\n        INCLUDE=+(sep=;)C:/prepended/path\n        INCLUDE+=(sep=;)C:/appended/path\n        \"\"\")\n    c.save({\"tool/conanfile.py\": tool,\n            \"consumer/conanfile.py\": conanfile,\n            \"profile\": profile})\n    c.run(\"create tool\")\n    with environment_update({\"INCLUDE\": \"C:/my/abs path/folder;C:/other path/subfolder\"}):\n        c.run(\"build consumer -pr=profile\")\n\n    # Check the profile is outputed correctly\n    assert \"INCLUDE=+(sep=;)C:/prepended/path\" in c.out\n    assert \"INCLUDE+=(sep=;)C:/appended/path\" in c.out\n    # check the composition is correct\n    assert \"INCLUDE=C:/prepended/path;C:/my/abs path/folder;C:/other path/subfolder;\" \\\n           \"C:/mytool/path;C:/appended/path\" in c.out\n"
  },
  {
    "path": "test/functional/test_local_recipes_index.py",
    "content": "import os\nimport textwrap\n\nfrom conan.test.assets.cmake import gen_cmakelists\nfrom conan.test.assets.sources import gen_function_cpp, gen_function_h\nfrom conan.test.utils.file_server import TestFileServer\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient, zipdir\nfrom conan.internal.util.files import save_files, sha256sum\n\n\nclass TestLocalRecipeIndexNew:\n    def test_conan_new_local_recipes_index(self):\n        # Setup the release pkg0.1.zip http server\n        file_server = TestFileServer()\n        zippath = os.path.join(file_server.store, \"pkg0.1.zip\")\n        repo_folder = temp_folder()\n        cmake = gen_cmakelists(libname=\"pkg\", libsources=[\"pkg.cpp\"], install=True,\n                               public_header=\"pkg.h\")\n        save_files(repo_folder, {\"pkg/CMakeLists.txt\": cmake,\n                                 \"pkg/pkg.h\": gen_function_h(name=\"pkg\"),\n                                 \"pkg/pkg.cpp\": gen_function_cpp(name=\"pkg\")})\n        zipdir(repo_folder, zippath)\n        sha256 = sha256sum(zippath)\n        url = f\"{file_server.fake_url}/pkg0.1.zip\"\n\n        c0 = TestClient()\n        c0.servers[\"file_server\"] = file_server\n        c0.run(f\"new local_recipes_index -d name=pkg -d version=0.1 -d url={url} -d sha256={sha256}\")\n        # A local create is possible, and it includes a test_package\n        c0.run(\"create recipes/pkg/all --version=0.1\")\n        assert \"pkg: Release!\" in c0.out\n        remote_folder = c0.current_folder\n\n        c = TestClient()\n        c.servers[\"file_server\"] = file_server\n        c.run(f\"remote add local '{remote_folder}'\")\n        c.run(\"new cmake_exe -d name=app -d version=0.1 -d requires=pkg/0.1\")\n        c.run(\"create . --version=0.1 --build=missing\")\n        assert \"pkg: Release!\" in c.out\n\n\nclass TestInRepo:\n    def test_in_repo(self):\n        \"\"\"testing that it is possible to put a \"recipes\" folder inside a source repo, and\n        use it as local-recipes-index repository, exporting the source from itself\n        \"\"\"\n        repo_folder = temp_folder()\n        cmake = gen_cmakelists(libname=\"pkg\", libsources=[\"pkg.cpp\"], install=True,\n                               public_header=\"pkg.h\")\n        config_yml = textwrap.dedent(\"\"\"\\\n            versions:\n              \"0.1\":\n                folder: all\n            \"\"\")\n        conanfile = textwrap.dedent(\"\"\"\\\n            import os\n            from conan import ConanFile\n            from conan.tools.cmake import CMake, cmake_layout\n            from conan.tools.files import copy\n\n            class PkgRecipe(ConanFile):\n                name = \"pkg\"\n                package_type = \"library\"\n\n                # Binary configuration\n                settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n                options = {\"shared\": [True, False], \"fPIC\": [True, False]}\n                default_options = {\"shared\": False, \"fPIC\": True}\n\n                generators = \"CMakeToolchain\"\n\n                def export_sources(self):\n                    src = os.path.dirname(os.path.dirname(os.path.dirname(self.recipe_folder)))\n                    copy(self, \"*\", src=src, dst=self.export_sources_folder, excludes=[\"recipes*\"])\n\n                def config_options(self):\n                    if self.settings.os == \"Windows\":\n                        self.options.rm_safe(\"fPIC\")\n\n                def configure(self):\n                    if self.options.shared:\n                        self.options.rm_safe(\"fPIC\")\n\n                def layout(self):\n                    cmake_layout(self)\n\n                def build(self):\n                    cmake = CMake(self)\n                    cmake.configure()\n                    cmake.build()\n\n                def package(self):\n                    cmake = CMake(self)\n                    cmake.install()\n\n                def package_info(self):\n                    self.cpp_info.libs = [self.name]\n            \"\"\")\n\n        save_files(repo_folder, {\"recipes/pkg/config.yml\": config_yml,\n                                 \"recipes/pkg/all/conanfile.py\": conanfile,\n                                 \"CMakeLists.txt\": cmake,\n                                 \"pkg.h\": gen_function_h(name=\"pkg\"),\n                                 \"pkg.cpp\": gen_function_cpp(name=\"pkg\")})\n\n        c = TestClient()\n        c.run(f\"remote add local '{repo_folder}'\")\n        c.run(\"new cmake_exe -d name=app -d version=0.1 -d requires=pkg/0.1\")\n        c.run(\"create . --build=missing\")\n        assert \"pkg: Release!\" in c.out\n\n        # Of course the recipe can also be created locally\n        path = os.path.join(repo_folder, \"recipes/pkg/all\")\n        c.run(f'create \"{path}\" --version=0.1')\n        assert \"pkg/0.1: Created package\" in c.out\n\n        # Finally lets remove the remote, check that the clone is cleared\n        c.run('remote remove local')\n        assert \"Removing temporary files for 'local' local-recipes-index remote\" in c.out\n\n    def test_not_found(self):\n        \"\"\"testing that the correct exception is raised when a recipe is not found\n        \"\"\"\n        repo1_folder = temp_folder()\n        repo2_folder = temp_folder()\n        config_yml = textwrap.dedent(\"\"\"\\\n            versions:\n              \"0.1\":\n                folder: all\n            \"\"\")\n        conanfile = textwrap.dedent(\"\"\"\\\n            import os\n            from conan import ConanFile\n            from conan.tools.files import copy\n\n            class PkgRecipe(ConanFile):\n                name = \"pkg\"\n\n                def export_sources(self):\n                    copy(self, \"*\", src=self.recipe_folder, dst=self.export_sources_folder)\n            \"\"\")\n\n        save_files(repo2_folder, {\"recipes/pkg/config.yml\": config_yml,\n                                  \"recipes/pkg/all/conanfile.py\": conanfile,\n                                  \"recipes/pkg/all/pkg.h\": gen_function_h(name=\"pkg\")})\n\n        c = TestClient()\n        c.run(f\"remote add local1 '{repo1_folder}'\")\n        c.run(f\"remote add local2 '{repo2_folder}'\")\n        c.run(\"install --requires=pkg/0.1 --build=missing\")\n        assert \"Install finished successfully\" in c.out\n"
  },
  {
    "path": "test/functional/test_profile_detect_api.py",
    "content": "import platform\nimport textwrap\n\nimport pytest\n\nfrom conan.internal.api.detect import detect_api\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestProfileDetectAPI:\n    @pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Only for windows\")\n    @pytest.mark.tool(\"visual_studio\", \"17\")\n    def test_profile_detect_compiler(self):\n\n        client = TestClient()\n        tpl1 = textwrap.dedent(\"\"\"\n            {% set compiler, version, compiler_exe = detect_api.detect_default_compiler() %}\n            {% set runtime, _ = detect_api.default_msvc_runtime(compiler) %}\n            [settings]\n            compiler={{compiler}}\n            compiler.version={{detect_api.default_compiler_version(compiler, version)}}\n            compiler.runtime={{runtime}}\n            compiler.cppstd={{detect_api.default_cppstd(compiler, version)}}\n            # detect_msvc_update returns the real update, like 12 for VS 17.12 so\n            # we have to convert to the setting that's 0-10\n            compiler.update={{ (detect_api.detect_msvc_update(version) | int) % 10 }}\n\n            [conf]\n            tools.microsoft.msbuild:vs_version={{detect_api.default_msvc_ide_version(version)}}\n            \"\"\")\n\n        client.save({\"profile1\": tpl1})\n        client.run(\"profile show -pr=profile1 --context=host\")\n        # FIXME: check update setting\n        update = str(int(detect_api.detect_msvc_update(\"194\")) % 10)\n        expected = textwrap.dedent(f\"\"\"\\\n            [settings]\n            compiler=msvc\n            compiler.cppstd=14\n            compiler.runtime=dynamic\n            compiler.runtime_type=Release\n            compiler.update={update}\n            compiler.version=194\n            [conf]\n            tools.microsoft.msbuild:vs_version=17\n            \"\"\")\n        assert expected in client.out\n\n    @pytest.mark.skipif(platform.system() != \"Linux\", reason=\"Only linux\")\n    def test_profile_detect_libc(self):\n        client = TestClient()\n        tpl1 = textwrap.dedent(\"\"\"\n            {% set compiler, version, _ = detect_api.detect_gcc_compiler() %}\n            {% set libc, libc_version = detect_api.detect_libc() %}\n            [settings]\n            os=Linux\n            compiler={{compiler}}\n            compiler.version={{version}}\n            [conf]\n            user.confvar:libc={{libc}}\n            user.confvar:libc_version={{libc_version}}\n            \"\"\")\n\n        client.save({\"profile1\": tpl1})\n        client.run(\"profile show -pr=profile1 --context=host\")\n        libc_name, libc_version = detect_api.detect_libc()\n        assert libc_name is not None\n        assert libc_version is not None\n        _, version, _ = detect_api.detect_gcc_compiler()\n        expected = textwrap.dedent(f\"\"\"\\\n            [settings]\n            compiler=gcc\n            compiler.version={version}\n            os=Linux\n            [conf]\n            user.confvar:libc={libc_name}\n            user.confvar:libc_version={libc_version}\n            \"\"\")\n        assert expected in client.out\n\n    @pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only OSX\")\n    def test_profile_detect_darwin_sdk(self):\n        client = TestClient()\n        tpl1 = textwrap.dedent(\"\"\"\\\n            [settings]\n            os = \"Macos\"\n            os.sdk_version = {{ detect_api.detect_sdk_version(sdk=\"macosx\")  }}\n            \"\"\")\n\n        client.save({\"profile1\": tpl1})\n        client.run(\"profile show -pr=profile1\")\n        sdk_version = detect_api.detect_sdk_version(sdk=\"macosx\")\n        assert f\"os.sdk_version={sdk_version}\" in client.out\n\n\n@pytest.mark.parametrize(\"context\", [None, \"host\", \"build\"])\n@pytest.mark.parametrize(\"f\", [\"json\", \"text\"])\ndef test_profile_show_aggregate_usecase(context, f):\n    tc = TestClient(light=True)\n\n    context_arg = f\"--context {context}\" if context else \"\"\n    tc.run(f'profile show {context_arg} -s:h=\"os=Windows\" -s:b=\"os=Linux\" --format={f}')\n\n    if context == \"host\":\n        if f == \"text\":\n            assert \"Host profile:\" not in tc.stdout\n            assert \"Host profile:\" in tc.stderr\n        assert \"Linux\" not in tc.out\n    if context == \"build\":\n        if f == \"text\":\n            assert \"Build profile:\" not in tc.stdout\n            assert \"Build profile:\" in tc.stderr\n        assert \"Windows\" not in tc.out\n\n    if context in (None, \"host\"):\n        assert \"Windows\" in tc.out\n    if context in (None, \"build\"):\n        assert \"Linux\" in tc.out\n"
  },
  {
    "path": "test/functional/test_third_party_patch_flow.py",
    "content": "import os\nimport textwrap\n\nfrom conan.test.utils.scm import create_local_git_repo\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import mkdir\n\n\ndef test_third_party_patch_flow():\n    \"\"\" this test emulates the work of a developer contributing recipes to ConanCenter, and having\n    to do multiple patches to the original library source code:\n    - Everything is local, not messing with the cache\n    - Using layout() to define location of things\n    \"\"\"\n    conanfile = textwrap.dedent(r\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import save, load, apply_conandata_patches\n\n        class Pkg(ConanFile):\n            name = \"mypkg\"\n            version = \"1.0\"\n            exports_sources = \"*\"\n\n            def layout(self):\n                self.folders.source = \"src\"\n                self.folders.build = \"build\"\n\n            def source(self):\n                # emulate a download from web site\n                save(self, \"myfile.cpp\", \"mistake1\\nsomething\\nmistake2\\nmistake3\\nsome\\n\")\n                apply_conandata_patches(self)\n\n            def build(self):\n                content = load(self,  os.path.join(self.source_folder, \"myfile.cpp\"))\n                for i in (1, 2, 3):\n                    if \"mistake{}\".format(i) in content:\n                        raise Exception(\"MISTAKE{} BUILD!\".format(i))\n        \"\"\")\n\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile,\n                 \"conandata.yml\": \"\"})\n    client.run(\"install .\")\n    client.run(\"source .\")\n    assert \"apply_conandata_patches(): No patches defined in conandata\" in client.out\n\n    client.save({\"conandata.yml\": \"patches: {}\"})\n    client.run(\"source .\")\n    client.run(\"build .\", assert_error=True)\n    assert \"MISTAKE1 BUILD!\" in client.out\n\n    # user decides to create patches, first init the repo\n    client.init_git_repo(folder=\"src\")  # Using helper for user/email repo init\n    client.save({\"src/myfile.cpp\": \"correct1\\nsomething\\nmistake2\\nmistake3\\nsome\\n\"})\n    # compute the patch\n    mkdir(os.path.join(client.current_folder, \"patches\"))\n    client.run_command(\"cd src && git diff > ../patches/patch1\")\n    client.run_command(\"cd src && git add . && git commit -m patch1\")\n    conandata = textwrap.dedent(\"\"\"\n        patches:\n          \"1.0\":\n            - patch_file: \"patches/patch1\"\n        \"\"\")\n    client.save({\"conandata.yml\": conandata})\n\n    client.run(\"source .\")\n    client.run(\"build .\", assert_error=True)\n    assert \"MISTAKE2 BUILD!\" in client.out\n\n    client.save({\"src/myfile.cpp\": \"correct1\\nsomething\\ncorrect2\\nmistake3\\nsome\\n\"})\n    # compute the patch\n    mkdir(os.path.join(client.current_folder, \"patches\"))\n    client.run_command(\"cd src && git diff > ../patches/patch2\")\n    client.run_command(\"cd src && git add . && git commit -m patch1\")\n\n    conandata = textwrap.dedent(\"\"\"\n        patches:\n          \"1.0\":\n            - patch_file: \"patches/patch1\"\n            - patch_file: \"patches/patch2\"\n        \"\"\")\n    client.save({\"conandata.yml\": conandata})\n    client.run(\"source .\")\n    client.run(\"build .\", assert_error=True)\n    assert \"MISTAKE3 BUILD!\" in client.out\n\n    client.save({\"src/myfile.cpp\": \"correct1\\nsomething\\ncorrect2\\ncorrect3\\nsome\\n\"})\n    # compute the patch\n    mkdir(os.path.join(client.current_folder, \"patches\"))\n    client.run_command(\"cd src && git diff > ../patches/patch3\")\n    client.run_command(\"cd src && git add . && git commit -m patch1\")\n\n    conandata = textwrap.dedent(\"\"\"\n           patches:\n             \"1.0\":\n               - patch_file: \"patches/patch1\"\n               - patch_file: \"patches/patch2\"\n               - patch_file: \"patches/patch3\"\n           \"\"\")\n    client.save({\"conandata.yml\": conandata})\n    client.run(\"source .\")\n    client.run(\"build .\")\n    assert \"conanfile.py (mypkg/1.0): Calling build()\" in client.out\n\n    # of course create should work too\n    client.run(\"create .\")\n    assert \"mypkg/1.0: Created package\" in client.out\n\n\ndef test_third_party_overwrite_build_file():\n    \"\"\" this test emulates the work of a developer contributing recipes to ConanCenter, and\n    replacing the original build script with your one one.\n\n    The export_sources is actually copying CMakeLists.txt into the \"src\" folder, but the\n    'download' will overwrite it, so it is necessary to copy it again\n    \"\"\"\n    conanfile = textwrap.dedent(r\"\"\"\n        import os, shutil\n        from conan import ConanFile\n        from conan.tools.files import save, load\n\n        class Pkg(ConanFile):\n            name = \"mypkg\"\n            version = \"1.0\"\n            exports_sources = \"CMakeLists.txt\"\n\n            def layout(self):\n                self.folders.source = \"src\"\n                self.folders.build = \"build\"\n\n            def source(self):\n                # emulate a download from web site\n                save(self, \"CMakeLists.txt\", \"MISTAKE: Very old CMakeLists to be replaced\")\n                # Now I fix it with one of the exported files\n                shutil.copy(\"../CMakeLists.txt\", \".\")\n\n            def build(self):\n                if \"MISTAKE\" in load(self, os.path.join(self.source_folder, \"CMakeLists.txt\")):\n                    raise Exception(\"MISTAKE BUILD!\")\n        \"\"\")\n\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile,\n                 \"conandata.yml\": \"\",\n                 \"CMakeLists.txt\": \"My better cmake\"})\n    client.run(\"install .\")\n    client.run(\"source .\")\n    client.run(\"build .\")\n    assert \"conanfile.py (mypkg/1.0): Calling build()\" in client.out\n\n    # of course create should work too\n    client.run(\"create .\")\n    assert \"mypkg/1.0: Created package\" in client.out\n\n\ndef test_third_party_git_overwrite_build_file():\n    \"\"\" Same as the above, but using git clone\n    The trick: \"git clone <url> .\" needs an empty directory. No reason why the ``src`` folder should\n    be polluted automatically with exports, so just removing things works\n    \"\"\"\n    git_repo = temp_folder().replace(\"\\\\\", \"/\")\n    create_local_git_repo({\"CMakeLists.txt\": \"MISTAKE Cmake\"}, folder=git_repo)\n\n    conanfile = textwrap.dedent(r\"\"\"\n        import os, shutil\n        from conan import ConanFile\n        from conan.tools.files import save, load\n\n        class Pkg(ConanFile):\n            name = \"mypkg\"\n            version = \"1.0\"\n            exports_sources = \"CMakeLists.txt\"\n\n            def layout(self):\n                self.folders.source = \"src\"\n                self.folders.build = \"build\"\n\n            def source(self):\n                self.output.info(\"CWD: {{}}!\".format(os.getcwd()))\n                self.output.info(\"FILES: {{}}!\".format(sorted(os.listdir(\".\"))))\n                self.run('git clone \"{}\" .')\n                # Now I fix it with one of the exported files\n                shutil.copy(\"../CMakeLists.txt\", \".\")\n\n            def build(self):\n                if \"MISTAKE\" in load(self, os.path.join(self.source_folder, \"CMakeLists.txt\")):\n                    raise Exception(\"MISTAKE BUILD!\")\n        \"\"\".format(git_repo))\n\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile,\n                 \"conandata.yml\": \"\",\n                 \"CMakeLists.txt\": \"My better cmake\"})\n    client.run(\"install .\")\n    client.run(\"source .\")\n    assert \"FILES: []!\" in client.out\n    client.run(\"build .\")\n    assert \"conanfile.py (mypkg/1.0): Calling build()\" in client.out\n\n    # of course create should work too\n    client.run(\"create .\")\n    assert \"mypkg/1.0: Created package\" in client.out\n"
  },
  {
    "path": "test/functional/toolchains/__init__.py",
    "content": ""
  },
  {
    "path": "test/functional/toolchains/android/__init__.py",
    "content": ""
  },
  {
    "path": "test/functional/toolchains/android/test_using_cmake.py",
    "content": "import platform\nimport tempfile\nimport textwrap\n\nimport pytest\n\nfrom test.conftest import tools_locations\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.slow\n@pytest.mark.tool(\"cmake\", \"3.23\")  # Android complains if <3.19\n@pytest.mark.tool(\"ninja\")  # so it easily works in Windows too\n@pytest.mark.tool(\"android_ndk\")\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"NDK only installed on MAC\")\ndef test_use_cmake_toolchain():\n    \"\"\" This is the naive approach, we follow instruction from CMake in its documentation\n        https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling-for-android\n    \"\"\"\n    # Overriding the default folders, so they are in the same unit drive in Windows\n    # otherwise AndroidNDK FAILS to build, it needs using the same unit drive\n    c = TestClient(cache_folder=tempfile.mkdtemp(),\n                   current_folder=tempfile.mkdtemp())\n    c.run(\"new cmake_lib -d name=hello -d version=0.1\")\n    ndk_path = tools_locations[\"android_ndk\"][\"system\"][\"path\"][platform.system()]\n    android = textwrap.dedent(f\"\"\"\n       [settings]\n       os=Android\n       os.api_level=23\n       arch=x86_64\n       compiler=clang\n       compiler.version=12\n       compiler.libcxx=c++_shared\n       build_type=Release\n       [conf]\n       tools.android:ndk_path={ndk_path}\n       tools.cmake.cmaketoolchain:generator=Ninja\n       \"\"\")\n    c.save({\"android\": android})\n    c.run('create . --profile:host=android')\n    assert \"hello/0.1 (test package): Running test()\" in c.out\n\n    # Build locally\n    c.run('build . --profile:host=android')\n    assert \"conanfile.py (hello/0.1): Running CMake.build()\" in c.out\n"
  },
  {
    "path": "test/functional/toolchains/apple/__init__.py",
    "content": ""
  },
  {
    "path": "test/functional/toolchains/apple/test_xcodebuild.py",
    "content": "import platform\nimport re\nimport textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\nxcode_project = textwrap.dedent(\"\"\"\n    name: app\n    targets:\n      app:\n        type: tool\n        platform: macOS\n        sources:\n          - app\n        configFiles:\n          Debug: conan_config.xcconfig\n          Release: conan_config.xcconfig\n    \"\"\")\n\nxcode_project_bare = textwrap.dedent(\"\"\"\n    name: app\n    targets:\n      app:\n        type: tool\n        platform: macOS\n        sources:\n          - app\n    \"\"\")\n\n\nmain = textwrap.dedent(\"\"\"\n    #include <iostream>\n    #include \"hello.h\"\n    int main(int argc, char *argv[]) {\n        hello();\n        #ifndef DEBUG\n        std::cout << \"App Release!\" << std::endl;\n        #else\n        std::cout << \"App Debug!\" << std::endl;\n        #endif\n    }\n    \"\"\")\n\ntest = textwrap.dedent(\"\"\"\n    import os\n    from conan import ConanFile, tools\n    from conan.tools.build import cross_building\n    class TestApp(ConanFile):\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n        def requirements(self):\n            self.requires(self.tested_reference_str)\n        def test(self):\n            if not cross_building(self):\n                self.run(\"app\", env=\"conanrun\")\n    \"\"\")\n\n\n@pytest.fixture(scope=\"module\")\ndef client():\n    client = TestClient()\n    client.run(\"new cmake_lib -d name=hello -d version=0.1\")\n    client.run(\"create . -s build_type=Release\")\n    client.run(\"create . -s build_type=Debug\")\n    return client\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only for MacOS\")\n@pytest.mark.tool(\"xcodebuild\")\n@pytest.mark.tool(\"xcodegen\")\ndef test_project_xcodebuild(client):\n\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.apple import XcodeBuild\n        from conan.tools.files import copy\n        class MyApplicationConan(ConanFile):\n            name = \"myapplication\"\n            version = \"1.0\"\n            requires = \"hello/0.1\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"XcodeDeps\"\n            exports_sources = \"app.xcodeproj/*\", \"app/*\"\n            package_type = \"application\"\n            def build(self):\n                xcode = XcodeBuild(self)\n                xcode.build(\"app.xcodeproj\")\n\n            def package(self):\n                copy(self, \"build/{}/app\".format(self.settings.build_type), self.source_folder,\n                     os.path.join(self.package_folder, \"bin\"), keep_path=False)\n\n            def package_info(self):\n                self.cpp_info.bindirs = [\"bin\"]\n        \"\"\")\n\n    client.save({\"conanfile.py\": conanfile,\n                 \"test_package/conanfile.py\": test,\n                 \"app/main.cpp\": main,\n                 \"project.yml\": xcode_project}, clean_first=True)\n    client.run(\"install . --build=missing\")\n    client.run(\"install . -s build_type=Debug --build=missing\")\n    client.run_command(\"xcodegen generate\")\n    client.run(\"create . --build=missing -s os.version=15.0 -c tools.build:verbosity=verbose -c tools.compilation:verbosity=verbose\")\n    assert \"MACOSX_DEPLOYMENT_TARGET=15.0\" in client.out\n    assert \"xcodebuild: error: invalid option\" not in client.out\n    assert \"hello/0.1: Hello World Release!\" in client.out\n    assert \"App Release!\" in client.out\n    client.run(\"create . -s build_type=Debug -s os.version=15.0 --build=missing\")\n    assert \"hello/0.1: Hello World Debug!\" in client.out\n    assert \"App Debug!\" in client.out\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only for MacOS\")\n@pytest.mark.tool(\"xcodebuild\")\n@pytest.mark.tool(\"xcodegen\")\n@pytest.mark.skip(reason=\"Different sdks not installed in CI\")\ndef test_xcodebuild_test_different_sdk(client):\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.apple import XcodeBuild\n        class MyApplicationConan(ConanFile):\n            name = \"myapplication\"\n            version = \"1.0\"\n            requires = \"hello/0.1\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"XcodeDeps\"\n            exports_sources = \"app.xcodeproj/*\", \"app/*\"\n            def build(self):\n                xcode = XcodeBuild(self)\n                xcode.build(\"app.xcodeproj\")\n                self.run(\"otool -l build/Release/app\")\n        \"\"\")\n\n    client.save({\"conanfile.py\": conanfile,\n                 \"app/main.cpp\": main,\n                 \"project.yml\": xcode_project}, clean_first=True)\n    client.run(\"install . --build=missing\")\n    client.run(\"install . -s build_type=Debug --build=missing\")\n    client.run_command(\"xcodegen generate\")\n    client.run(\"create . --build=missing -s os.sdk=macosx -s os.sdk_version=10.15 \"\n               \"-c tools.apple:sdk_path='/Applications/Xcode11.7.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk'\")\n    assert \"sdk 10.15.6\" in client.out\n    client.run(\"create . --build=missing -s os.sdk_version=11.3 \"\n               \"-c tools.apple:sdk_path='/Applications/Xcode12.5.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.3.sdk'\")\n    assert \"sdk 11.3\" in client.out\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only for MacOS\")\n@pytest.mark.tool(\"xcodebuild\")\n@pytest.mark.tool(\"xcodegen\")\ndef test_missing_sdk(client):\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.apple import XcodeBuild\n        class MyApplicationConan(ConanFile):\n            name = \"myapplication\"\n            version = \"1.0\"\n            requires = \"hello/0.1\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"XcodeDeps\"\n            exports_sources = \"app.xcodeproj/*\", \"app/*\"\n            def build(self):\n                xcode = XcodeBuild(self)\n                xcode.build(\"app.xcodeproj\")\n        \"\"\")\n\n    client.save({\"conanfile.py\": conanfile,\n                 \"app/main.cpp\": main,\n                 \"project.yml\": xcode_project}, clean_first=True)\n    client.run(\"install . --build=missing\")\n    client.run(\"install . -s build_type=Debug --build=missing\")\n    client.run_command(\"xcodegen generate\")\n    client.run(\"create . --build=missing -s os.sdk=macosx -s os.sdk_version=12.0 \"\n               \"-c tools.apple:sdk_path=notexistingsdk\", assert_error=True)\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only for MacOS\")\n@pytest.mark.tool(\"xcodebuild\")\n@pytest.mark.tool(\"xcodegen\")\n@pytest.mark.parametrize(\"no_copy_source\", [True, False])\ndef test_project_xcodebuild_cli_args(client, no_copy_source):\n\n    conanfile = textwrap.dedent(f\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.apple import XcodeBuild\n        from conan.tools.files import copy\n        class MyApplicationConan(ConanFile):\n            name = \"myapplication\"\n            version = \"1.0\"\n            requires = \"hello/0.1\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"XcodeDeps\"\n            exports_sources = \"app.xcodeproj/*\", \"app/*\"\n            package_type = \"application\"\n            no_copy_source = {str(no_copy_source)}\n            def build(self):\n                xb = XcodeBuild(self)\n                proj = os.path.join(self.source_folder, \"app.xcodeproj\")\n                xc = os.path.join(self.build_folder, \"conan_config.xcconfig\")\n                xb.build(proj, cli_args=[\"-xcconfig\", xc,\n                                        f\"SYMROOT={{self.build_folder}}\",\n                                        f\"OBJROOT={{self.build_folder}}\"])\n\n            def package(self):\n                copy(self, \"{{}}/app\".format(self.settings.build_type), self.build_folder,\n                     os.path.join(self.package_folder, \"bin\"), keep_path=False)\n\n            def package_info(self):\n                self.cpp_info.bindirs = [\"bin\"]\n        \"\"\")\n\n    client.save({\"conanfile.py\": conanfile,\n                      \"test_package/conanfile.py\": test,\n                      \"app/main.cpp\": main,\n                      \"project.yml\": xcode_project_bare}, clean_first=True)\n\n    client.run_command(\"xcodegen generate\")\n\n    for build_type in [\"Release\", \"Debug\"]:\n        client.run(f\"create . --build=missing -s build_type={build_type} -c tools.build:verbosity=verbose -c tools.compilation:verbosity=verbose\")\n\n        build_folder = re.search(r\"Building your package in (/.+)\", client.out).group(1)\n\n        assert f\"OBJROOT = {build_folder}\"\n        assert f\"SYMROOT = {build_folder}\"\n        assert \"-xcconfig\" in client.out\n        assert f\"App {build_type}!\" in client.out\n"
  },
  {
    "path": "test/functional/toolchains/apple/test_xcodebuild_targets.py",
    "content": "import platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\nxcode_project = textwrap.dedent(\"\"\"\n    name: HelloLibrary\n    targets:\n      hello-static:\n        type: library.static\n        platform: macOS\n        sources:\n          - src\n        configFiles:\n          Debug: static.xcconfig\n          Release: static.xcconfig\n      hello-dynamic:\n        type: library.dynamic\n        platform: macOS\n        sources:\n          - src\n        configFiles:\n          Debug: dynamic.xcconfig\n          Release: dynamic.xcconfig\n\n    \"\"\")\n\nhello_cpp = textwrap.dedent(\"\"\"\n    #include \"hello.hpp\"\n    #include <iostream>\n\n    void hellofunction(){\n        #ifndef DEBUG\n        std::cout << \"Hello Release!\" << std::endl;\n        #else\n        std::cout << \"Hello Debug!\" << std::endl;\n        #endif\n    }\n    \"\"\")\n\nhello_hpp = textwrap.dedent(\"\"\"\n    #ifndef hello_hpp\n    #define hello_hpp\n\n    void hellofunction();\n\n    #endif /* hello_hpp */\n    \"\"\")\n\ntest = textwrap.dedent(\"\"\"\n    import os\n\n    from conan import ConanFile\n    from conan.tools.cmake import CMake, cmake_layout\n    from conan.tools.build import cross_building\n\n\n    class HelloTestConan(ConanFile):\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n        generators = \"CMakeDeps\", \"CMakeToolchain\", \"VirtualBuildEnv\", \"VirtualRunEnv\"\n        options = {\"shared\": [True, False], \"fPIC\": [True, False]}\n        default_options = {\"shared\": False, \"fPIC\": True}\n\n        def requirements(self):\n            self.requires(self.tested_reference_str)\n\n        def build(self):\n            cmake = CMake(self)\n            cmake.configure()\n            cmake.build()\n\n        def layout(self):\n            cmake_layout(self)\n\n        def test(self):\n            if not cross_building(self):\n                cmd = os.path.join(self.cpp.build.bindirs[0], \"example\")\n                self.run(cmd, env=\"conanrun\")\n                if self.options.shared:\n                    self.run(\"otool -l {}\".format(os.path.join(self.cpp.build.bindirs[0], \"example\")))\n                else:\n                    self.run(\"nm {}\".format(os.path.join(self.cpp.build.bindirs[0], \"example\")))\n    \"\"\")\n\ncmakelists = textwrap.dedent(\"\"\"\n    set(CMAKE_CXX_COMPILER_WORKS 1)\n    set(CMAKE_CXX_ABI_COMPILED 1)\n    cmake_minimum_required(VERSION 3.15)\n    project(PackageTest CXX)\n\n    find_package(hello CONFIG REQUIRED)\n\n    add_executable(example src/example.cpp)\n    target_link_libraries(example hello::hello)\n    \"\"\")\n\ntest_src = textwrap.dedent(\"\"\"\n    #include \"hello.hpp\"\n\n    int main() {\n        hellofunction();\n    }\n    \"\"\")\n\nconanfile = textwrap.dedent(\"\"\"\n    import os\n    from conan import ConanFile\n    from conan.tools.apple import XcodeBuild\n    from conan.tools.files import copy\n\n    class HelloLib(ConanFile):\n        name = \"hello\"\n        version = \"1.0\"\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n        generators = \"XcodeToolchain\"\n        exports_sources = \"HelloLibrary.xcodeproj/*\", \"src/*\", \"static.xcconfig\", \"dynamic.xcconfig\"\n        options = {\"shared\": [True, False], \"fPIC\": [True, False]}\n        default_options = {\"shared\": False, \"fPIC\": True}\n\n        def build(self):\n            xcode = XcodeBuild(self)\n            if self.options.shared:\n                xcode.build(\"HelloLibrary.xcodeproj\", target=\"hello-dynamic\")\n            else:\n                xcode.build(\"HelloLibrary.xcodeproj\", target=\"hello-static\")\n\n        def package(self):\n            name = \"hello-dynamic.dylib\" if self.options.shared else \"libhello-static.a\"\n            copy(self, \"build/{}/{}\".format(self.settings.build_type, name),\n                 src=self.build_folder, dst=os.path.join(self.package_folder, \"lib\"), keep_path=False)\n            copy(self, \"*/*.hpp\", src=self.build_folder, dst=os.path.join(self.package_folder, \"include\"), keep_path=False)\n\n        def package_info(self):\n            self.cpp_info.libs = [\"hello-{}\".format(\"dynamic.dylib\" if self.options.shared else \"static\")]\n    \"\"\")\n\nstatic_xcconfig = textwrap.dedent(\"\"\"\n    #include \\\"conan_config.xcconfig\\\"\n    LD_DYLIB_INSTALL_NAME = @rpath/libhello-static.dylib\n\"\"\")\n\ndynamic_xcconfig = textwrap.dedent(\"\"\"\n    #include \\\"conan_config.xcconfig\\\"\n    LD_DYLIB_INSTALL_NAME = @rpath/hello-dynamic.dylib\n\"\"\")\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only for MacOS\")\n@pytest.mark.tool(\"xcodebuild\")\ndef test_shared_static_targets():\n    \"\"\"\n    The pbxproj has defined two targets, one for static and one for dynamic libraries, in the\n    XcodeBuild build helper we pass the target we want to build depending on the shared option\n    \"\"\"\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile,\n                 \"src/hello.cpp\": hello_cpp,\n                 \"src/hello.hpp\": hello_hpp,\n                 \"project.yml\": xcode_project,\n                 \"test_package/conanfile.py\": test,\n                 \"test_package/src/example.cpp\": test_src,\n                 \"test_package/CMakeLists.txt\": cmakelists,\n                 \"conan_config.xcconfig\": \"\",\n                 \"static.xcconfig\": static_xcconfig,\n                 \"dynamic.xcconfig\": dynamic_xcconfig})\n\n    client.run_command(\"xcodegen generate\")\n\n    client.run(\"create . -o *:shared=True -tf=\\\"\\\"\")\n    assert \"Packaged 1 '.dylib' file: hello-dynamic.dylib\" in client.out\n    client.run(\"test test_package hello/1.0@ -o *:shared=True\")\n    assert \"@rpath/hello-dynamic.dylib\" in client.out\n\n    client.run(\"create . -tf=\\\"\\\"\")\n    assert \"Packaged 1 '.a' file: libhello-static.a\" in client.out\n    client.run(\"test test_package hello/1.0@\")\n    # check the symbol hellofunction in in the executable\n    assert \"hellofunction\" in client.out\n"
  },
  {
    "path": "test/functional/toolchains/apple/test_xcodedeps_build_configs.py",
    "content": "import os\nimport platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\nxcode_project = textwrap.dedent(\"\"\"\n    name: app\n    targets:\n      app:\n        type: tool\n        platform: macOS\n        sources:\n          - main.cpp\n        configFiles:\n          Debug: conan_config.xcconfig\n          Release: conan_config.xcconfig\n    \"\"\")\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only for MacOS\")\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.tool(\"xcodebuild\")\n@pytest.mark.tool(\"xcodegen\")\ndef test_xcodedeps_build_configurations():\n    client = TestClient(path_with_spaces=False)\n\n    client.run(\"new cmake_lib -d name=hello -d version=0.1\")\n    client.run(\"export .\")\n\n    client.run(\"new cmake_lib -d name=bye -d version=0.1 -f\")\n    client.run(\"export .\")\n\n    main = textwrap.dedent(\"\"\"\n        #include <iostream>\n        #include \"hello.h\"\n        #include \"bye.h\"\n        int main(int argc, char *argv[]) {\n            hello();\n            bye();\n            #ifndef DEBUG\n            std::cout << \"App Release!\" << std::endl;\n            #else\n            std::cout << \"App Debug!\" << std::endl;\n            #endif\n        }\n        \"\"\")\n\n    client.save({\n        \"conanfile.txt\": \"[requires]\\nhello/0.1\\nbye/0.1\\n\",\n        \"main.cpp\": main,\n        \"project.yml\": xcode_project,\n    }, clean_first=True)\n\n    for config in [\"Release\", \"Debug\"]:\n        client.run(\"install . -s build_type={} -s arch=x86_64 --build=missing -g XcodeDeps\".format(config))\n\n    client.run_command(\"xcodegen generate\")\n\n    for config in [\"Release\", \"Debug\"]:\n        client.run_command(\"xcodebuild -project app.xcodeproj -configuration {} -arch x86_64\".format(config))\n        client.run_command(\"./build/{}/app\".format(config))\n        assert \"App {}!\".format(config) in client.out\n        assert \"hello/0.1: Hello World {}!\".format(config).format(config) in client.out\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only for MacOS\")\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.tool(\"xcodebuild\")\n@pytest.mark.tool(\"xcodegen\")\ndef test_frameworks():\n    client = TestClient(path_with_spaces=False)\n\n    client.save({\"hello.py\": GenConanfile().with_settings(\"os\", \"arch\", \"compiler\", \"build_type\")\n                                           .with_package_info(cpp_info={\"frameworks\":\n                                                                        ['CoreFoundation']})})\n    client.run(\"export hello.py --name=hello --version=0.1\")\n\n    main = textwrap.dedent(\"\"\"\n        #include <CoreFoundation/CoreFoundation.h>\n        int main(int argc, char *argv[]) {\n            CFShow(CFSTR(\"Hello!\"));\n        }\n        \"\"\")\n\n    project_name = \"app\"\n    client.save({\"conanfile.txt\": \"[requires]\\nhello/0.1\\n\",\n                 \"main.cpp\": main,\n                 \"project.yml\": xcode_project}, clean_first=True)\n\n    client.run(\"install . -s build_type=Release -s arch=x86_64 --build=missing -g XcodeDeps\")\n    client.run_command(\"xcodegen generate\")\n    client.run_command(\"xcodebuild -project app.xcodeproj -configuration Release -arch x86_64\")\n    client.run_command(\"./build/Release/{}\".format(project_name))\n    assert \"Hello!\" in client.out\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only for MacOS\")\n@pytest.mark.tool(\"xcodebuild\")\n@pytest.mark.tool(\"xcodegen\")\ndef test_xcodedeps_dashes_names_and_arch():\n    # https://github.com/conan-io/conan/issues/9949\n    client = TestClient(path_with_spaces=False)\n    client.save({\"conanfile.py\": GenConanfile().with_name(\"hello-dashes\").with_version(\"0.1\")})\n    client.run(\"export .\")\n    main = \"int main(int argc, char *argv[]) { return 0; }\"\n    client.save({\"conanfile.txt\": \"[requires]\\nhello-dashes/0.1\\n\",\n                 \"main.cpp\": main,\n                 \"project.yml\": xcode_project}, clean_first=True)\n    client.run(\"install . -s arch=armv8 --build=missing -g XcodeDeps\")\n    assert os.path.exists(os.path.join(client.current_folder,\n                                       \"conan_hello_dashes_hello_dashes_release_arm64.xcconfig\"))\n    client.run_command(\"xcodegen generate\")\n    client.run_command(\"xcodebuild -project app.xcodeproj -arch arm64\")\n    assert \"BUILD SUCCEEDED\" in client.out\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only for MacOS\")\n@pytest.mark.tool(\"xcodebuild\")\n@pytest.mark.tool(\"xcodegen\")\ndef test_xcodedeps_definitions_escape():\n    client = TestClient(path_with_spaces=False)\n    conanfile = textwrap.dedent('''\n        from conan import ConanFile\n\n        class HelloLib(ConanFile):\n            def package_info(self):\n                self.cpp_info.defines.append(\"USER_CONFIG=\\\\\"user_config.h\\\\\"\")\n                self.cpp_info.defines.append('OTHER=\"other.h\"')\n        ''')\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"export . --name=hello --version=1.0\")\n    main = textwrap.dedent(\"\"\"\n                                #include <stdio.h>\n                                #define STR(x)   #x\n                                #define SHOW_DEFINE(x) printf(\"%s=%s\", #x, STR(x))\n                                int main(int argc, char *argv[]) {\n                                    SHOW_DEFINE(USER_CONFIG);\n                                    SHOW_DEFINE(OTHER);\n                                    return 0;\n                                }\n                                \"\"\")\n    client.save({\"conanfile.txt\": \"[requires]\\nhello/1.0\\n\",\n                 \"main.cpp\": main,\n                 \"project.yml\": xcode_project}, clean_first=True)\n    client.run(\"install . --build=missing -g XcodeDeps\")\n    client.run_command(\"xcodegen generate\")\n    client.run_command(\"xcodebuild -project app.xcodeproj -configuration Release\")\n    client.run_command(\"./build/Release/app\")\n    assert 'USER_CONFIG=\"user_config.h\"' in client.out\n    assert 'OTHER=\"other.h\"' in client.out\n"
  },
  {
    "path": "test/functional/toolchains/apple/test_xcodedeps_components.py",
    "content": "import os\nimport platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only for MacOS\")\n@pytest.mark.tool(\"cmake\")\ndef test_xcodedeps_components():\n    \"\"\"\n    tcp/1.0 is a lib without components\n    network/1.0 lib that requires tcp/1.0 and has three components:\n     - core\n     - client -> requires core component and tcp::tcp\n     - server -> requires core component and tcp::tcp\n\n    chat/1.0 -> lib that requires network::client component\n\n    We create an application called ChatApp that uses XcodeDeps for chat/1.0 dependency\n    And check that we are not requiring more than the needed components,\n    nothing from network::server for example\n    \"\"\"\n    client = TestClient(path_with_spaces=False)\n\n    client.run(\"new cmake_lib -d name=tcp -d version=1.0\")\n    client.run(\"create . -tf=\\\"\\\"\")\n\n    header = textwrap.dedent(\"\"\"\n        #pragma once\n        void {name}();\n        \"\"\")\n\n    source = textwrap.dedent(\"\"\"\n        #include <iostream>\n        #include \"{name}.h\"\n        {include}\n\n        void {name}(){{\n            {call}\n            #ifdef NDEBUG\n            std::cout << \"{name}/1.0: Hello World Release!\" << std::endl;\n            #else\n            std::cout << \"{name}/1.0: Hello World Debug!\" << std::endl;\n            #endif\n        }}\n        \"\"\")\n\n    cmakelists = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.15)\n        project(myproject CXX)\n\n        find_package(tcp REQUIRED CONFIG)\n\n        add_library(core src/core.cpp include/core.h)\n        add_library(client src/client.cpp include/client.h)\n        add_library(server src/server.cpp include/server.h)\n\n        target_include_directories(core PUBLIC include)\n        target_include_directories(client PUBLIC include)\n        target_include_directories(server PUBLIC include)\n\n        set_target_properties(core PROPERTIES PUBLIC_HEADER \"include/core.h\")\n        set_target_properties(client PROPERTIES PUBLIC_HEADER \"include/client.h\")\n        set_target_properties(server PROPERTIES PUBLIC_HEADER \"include/server.h\")\n\n        target_link_libraries(client core tcp::tcp)\n        target_link_libraries(server core tcp::tcp)\n\n        install(TARGETS core client server)\n        \"\"\")\n\n    conanfile_py = textwrap.dedent(\"\"\"\n        import os\n\n        from conan import ConanFile\n        from conan.tools.cmake import CMake, cmake_layout\n\n\n        class LibConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            exports_sources = \"CMakeLists.txt\", \"src/*\", \"include/*\"\n            {requires}\n            generators = \"CMakeToolchain\", \"CMakeDeps\"\n\n            def layout(self):\n                cmake_layout(self)\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n\n            def package(self):\n                cmake = CMake(self)\n                cmake.install()\n            {package_info}\n        \"\"\")\n\n    network_pi = \"\"\"\n    def package_info(self):\n        self.cpp_info.components[\"core\"].libs = [\"core\"]\n        self.cpp_info.components[\"core\"].includedirs.append(\"include\")\n        self.cpp_info.components[\"core\"].libdirs.append(\"lib\")\n\n        self.cpp_info.components[\"client-test++\"].libs = [\"client\"]\n        self.cpp_info.components[\"client-test++\"].includedirs.append(\"include\")\n        self.cpp_info.components[\"client-test++\"].libdirs.append(\"lib\")\n        self.cpp_info.components[\"client-test++\"].requires.extend([\"core\", \"tcp::tcp\"])\n\n        self.cpp_info.components[\"server\"].libs = [\"server\"]\n        self.cpp_info.components[\"server\"].includedirs.append(\"include\")\n        self.cpp_info.components[\"server\"].libdirs.append(\"lib\")\n        self.cpp_info.components[\"server\"].requires.extend([\"core\", \"tcp::tcp\"])\n    \"\"\"\n\n    client.save({\n        \"include/core.h\": header.format(name=\"core\"),\n        \"include/server.h\": header.format(name=\"server\"),\n        \"include/client.h\": header.format(name=\"client\"),\n        \"src/core.cpp\": source.format(name=\"core\", include=\"\", call=\"\"),\n        \"src/server.cpp\": source.format(name=\"server\", include='#include \"core.h\"\\n#include \"tcp.h\"',\n                                        call=\"core(); tcp();\"),\n        \"src/client.cpp\": source.format(name=\"client\", include='#include \"core.h\"\\n#include \"tcp.h\"',\n                                        call=\"core(); tcp();\"),\n        \"conanfile.py\": conanfile_py.format(requires='requires= \"tcp/1.0\"', package_info=network_pi),\n        \"CMakeLists.txt\": cmakelists,\n    }, clean_first=True)\n\n    client.run(\"create . --name=network --version=1.0\")\n\n    chat_pi = \"\"\"\n    def package_info(self):\n        self.cpp_info.libs = [\"chat\"]\n        self.cpp_info.includedirs.append(\"include\")\n        self.cpp_info.libdirs.append(\"lib\")\n        self.cpp_info.requires.append(\"network::client-test++\")\n    \"\"\"\n\n    cmakelists_chat = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.15)\n        project(chat CXX)\n        find_package(network REQUIRED CONFIG)\n        add_library(chat src/chat.cpp include/chat.h)\n        target_include_directories(chat PUBLIC include)\n        set_target_properties(chat PROPERTIES PUBLIC_HEADER \"include/chat.h\")\n        target_link_libraries(chat network::client-test++)\n        install(TARGETS chat)\n        \"\"\")\n\n    client.save({\n        \"include/chat.h\": header.format(name=\"chat\"),\n        \"src/chat.cpp\": source.format(name=\"chat\", include='#include \"client.h\"', call=\"client();\"),\n        \"conanfile.py\": conanfile_py.format(requires='requires= \"network/1.0\"',\n                                            package_info=chat_pi),\n        \"CMakeLists.txt\": cmakelists_chat,\n    }, clean_first=True)\n\n    client.run(\"create . --name=chat --version=1.0\")\n\n    xcode_project = textwrap.dedent(\"\"\"\n        name: ChatApp\n        fileGroups:\n          - conan\n        targets:\n          chat:\n            type: tool\n            platform: macOS\n            sources:\n              - src\n            configFiles:\n              Debug: conan/conan_config.xcconfig\n              Release: conan/conan_config.xcconfig\n        \"\"\")\n\n    client.save({\n        \"src/main.cpp\": '#include \"chat.h\"\\nint main(){chat();return 0;}',\n        \"project.yml\": xcode_project\n    }, clean_first=True)\n\n    client.run(\"install --requires=chat/1.0@ -g XcodeDeps --output-folder=conan\")\n    client.run(\"install --requires=chat/1.0@ -g XcodeDeps --output-folder=conan \"\n               \"-s build_type=Debug --build=missing\")\n    chat_xcconfig = client.load(os.path.join(\"conan\", \"conan_chat_chat.xcconfig\"))\n    assert '#include \"conan_network_client_test__.xcconfig\"' in chat_xcconfig\n    assert '#include \"conan_network_server.xcconfig\"' not in chat_xcconfig\n    assert '#include \"conan_network_network.xcconfig\"' not in chat_xcconfig\n    host_arch = client.get_default_host_profile().settings['arch']\n    arch = \"arm64\" if host_arch == \"armv8\" else host_arch\n    client.run_command(\"xcodegen generate\")\n    client.run_command(f\"xcodebuild -project ChatApp.xcodeproj -configuration Release -arch {arch}\")\n    client.run_command(f\"xcodebuild -project ChatApp.xcodeproj -configuration Debug -arch {arch}\")\n    client.run_command(\"build/Debug/chat\")\n    assert \"core/1.0: Hello World Debug!\" in client.out\n    assert \"tcp/1.0: Hello World Debug!\" in client.out\n    assert \"client/1.0: Hello World Debug!\" in client.out\n    assert \"chat/1.0: Hello World Debug!\" in client.out\n    client.run_command(\"build/Release/chat\")\n    assert \"core/1.0: Hello World Release!\" in client.out\n    assert \"tcp/1.0: Hello World Release!\" in client.out\n    assert \"client/1.0: Hello World Release!\" in client.out\n    assert \"chat/1.0: Hello World Release!\" in client.out\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only for MacOS\")\n@pytest.mark.tool(\"cmake\")\ndef test_cpp_info_require_whole_package():\n    \"\"\"\n    https://github.com/conan-io/conan/issues/12089\n\n    liba has two components liba::cmp1 liba::cmp2\n\n    libb has not components and requires liba::liba so should generate the same info as\n    if it was requiring liba::cmp1 and liba::cmp2\n\n    libc has components and one component requires liba::liba so should generate the same info as if\n    it was requiring liba::cmp1 and liba::cmp2\n    \"\"\"\n    client = TestClient(path_with_spaces=False)\n\n    liba = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        class LibConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            name = \"liba\"\n            version = \"1.0\"\n            def package_info(self):\n                self.cpp_info.components[\"cmp1\"].includedirs.append(\"cmp1\")\n                self.cpp_info.components[\"cmp2\"].includedirs.append(\"cmp2\")\n        \"\"\")\n\n    libb = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        class LibConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            name = \"libb\"\n            version = \"1.0\"\n            requires = \"liba/1.0\"\n            def package_info(self):\n                self.cpp_info.requires = [\"liba::liba\"]\n        \"\"\")\n\n    libc = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        class LibConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            name = \"libc\"\n            version = \"1.0\"\n            requires = \"liba/1.0\"\n            def package_info(self):\n                self.cpp_info.components[\"cmp1\"].includedirs.append(\"cmp1\")\n                self.cpp_info.components[\"cmp2\"].includedirs.append(\"cmp2\")\n                self.cpp_info.components[\"cmp1\"].requires = [\"liba::liba\"]\n        \"\"\")\n\n    client.save({\"liba.py\": liba, \"libb.py\": libb, \"libc.py\": libc})\n\n    client.run(\"create liba.py\")\n    client.run(\"create libb.py\")\n    client.run(\"create libc.py\")\n    client.run(\"install --requires=libb/1.0 -g XcodeDeps -of=libb\")\n\n    libb_xcconfig = client.load(os.path.join(\"libb\", \"conan_libb_libb.xcconfig\"))\n    assert '#include \"conan_liba.xcconfig\"' in libb_xcconfig\n    assert '#include \"conan_liba_liba.xcconfig\"' not in libb_xcconfig\n\n    client.run(\"install --requires=libc/1.0 -g XcodeDeps -of=libc\")\n\n    libc_comp1_xcconfig = client.load(os.path.join(\"libc\", \"conan_libc_cmp1.xcconfig\"))\n    assert '#include \"conan_liba.xcconfig\"' in libc_comp1_xcconfig\n    assert '#include \"conan_liba_liba.xcconfig\"' not in libc_comp1_xcconfig\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only for MacOS\")\n@pytest.mark.tool(\"cmake\")\ndef test_xcodedeps_test_require():\n    client = TestClient()\n    client.run(\"new cmake_lib -d name=gtest -d version=1.0\")\n    client.run(\"create . -tf=\\\"\\\"\")\n\n    # Create library having build and test requires\n    conanfile = textwrap.dedent(r'''\n        from conan import ConanFile\n        class HelloLib(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            def build_requirements(self):\n                self.test_requires('gtest/1.0')\n        ''')\n    client.save({\"conanfile.py\": conanfile}, clean_first=True)\n    client.run(\"install . -g XcodeDeps\")\n    host_arch = client.get_default_host_profile().settings['arch']\n    arch = \"arm64\" if host_arch == \"armv8\" else host_arch\n    assert os.path.isfile(os.path.join(client.current_folder, \"conan_gtest.xcconfig\"))\n    assert os.path.isfile(os.path.join(client.current_folder, \"conan_gtest_gtest.xcconfig\"))\n    assert os.path.isfile(os.path.join(client.current_folder,\n                                       f\"conan_gtest_gtest_release_{arch}.xcconfig\"))\n    assert '#include \"conan_gtest.xcconfig\"' in client.load(\"conandeps.xcconfig\")\n"
  },
  {
    "path": "test/functional/toolchains/apple/test_xcodetoolchain.py",
    "content": "import platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.sources import gen_function_cpp\nfrom conan.test.utils.tools import TestClient\n\ntest = textwrap.dedent(\"\"\"\n    import os\n    from conan import ConanFile, tools\n    from conan.tools.build import can_run\n    class TestApp(ConanFile):\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n        def requirements(self):\n            self.requires(self.tested_reference_str)\n        def test(self):\n            if can_run(self):\n                self.run(\"app\", env=\"conanrun\")\n    \"\"\")\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only for MacOS\")\n@pytest.mark.tool(\"xcodebuild\")\n@pytest.mark.parametrize(\"cppstd, cppstd_output, min_version\", [\n    (\"gnu14\", \"__cplusplus201402\", \"11.0\"),\n    (\"gnu17\", \"__cplusplus201703\", \"11.0\"),\n    (\"gnu17\", \"__cplusplus201703\", \"10.15\")\n])\ndef test_project_xcodetoolchain(cppstd, cppstd_output, min_version):\n\n    client = TestClient()\n    client.run(\"new cmake_lib -d name=hello -d version=0.1\")\n    client.run(\"export .\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.apple import XcodeBuild\n        from conan.tools.files import copy\n        class MyApplicationConan(ConanFile):\n            name = \"myapplication\"\n            version = \"1.0\"\n            requires = \"hello/0.1\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"XcodeDeps\", \"XcodeToolchain\"\n            exports_sources = \"app.xcodeproj/*\", \"app/*\"\n            package_type = \"application\"\n            def build(self):\n                xcode = XcodeBuild(self)\n                xcode.build(\"app.xcodeproj\")\n                self.run(\"otool -l build/{}/app\".format(self.settings.build_type))\n\n            def package(self):\n                copy(self, \"build/{}/app\".format(self.settings.build_type), self.build_folder,\n                     os.path.join(self.package_folder, \"bin\"), keep_path=False)\n\n            def package_info(self):\n                self.cpp_info.bindirs = [\"bin\"]\n        \"\"\")\n\n    xcode_project = textwrap.dedent(\"\"\"\n        name: app\n        targets:\n          app:\n            type: tool\n            platform: macOS\n            sources:\n              - app\n            configFiles:\n              Debug: conan_config.xcconfig\n              Release: conan_config.xcconfig\n        \"\"\")\n\n    client.save({\"conanfile.py\": conanfile,\n                 \"test_package/conanfile.py\": test,\n                 \"app/main.cpp\": gen_function_cpp(name=\"main\", includes=[\"hello\"], calls=[\"hello\"]),\n                 \"project.yml\": xcode_project,\n                 \"conan_config.xcconfig\": \"\"}, clean_first=True)\n\n    client.run_command(\"xcodegen generate\")\n\n    sdk_version = \"15.5\"\n    settings = \"-s arch=x86_64 -s os.sdk_version={} -s compiler.cppstd={} \" \\\n               \"-s compiler.libcxx=libc++ -s os.version={} \" \\\n               \"-c tools.build.cross_building:can_run=True \" \\\n               \"-c 'tools.build:cflags=[\\\"-fstack-protector-strong\\\"]'\".format(sdk_version, cppstd,\n                                                                               min_version)\n\n    client.run(\"create . -s build_type=Release {} --build=missing\".format(settings))\n    assert \"main __x86_64__ defined\" in client.out\n    assert \"main {}\".format(cppstd_output) in client.out\n    assert \"minos {}\".format(min_version) in client.out\n    assert \"sdk {}\".format(sdk_version) in client.out\n    assert \"libc++\" in client.out\n    assert \" -fstack-protector-strong\" in client.out\n"
  },
  {
    "path": "test/functional/toolchains/autotools/__init__.py",
    "content": ""
  },
  {
    "path": "test/functional/toolchains/autotools/test_universal_binaries.py",
    "content": "import os\nimport platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only OSX\")\ndef test_autotools_universal_binary():\n    client = TestClient(path_with_spaces=False)\n\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.gnu import AutotoolsToolchain, Autotools\n        from conan.tools.layout import basic_layout\n\n        class mylibraryRecipe(ConanFile):\n            name = \"mylibrary\"\n            version = \"1.0\"\n            package_type = \"library\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            options = {\"shared\": [True, False], \"fPIC\": [True, False]}\n            default_options = {\"shared\": False, \"fPIC\": True}\n\n            exports_sources = \"configure.ac\", \"Makefile.am\", \"src/*\"\n\n            def config_options(self):\n                if self.settings.os == \"Windows\":\n                    self.options.rm_safe(\"fPIC\")\n\n            def configure(self):\n                if self.options.shared:\n                    self.options.rm_safe(\"fPIC\")\n\n            def layout(self):\n                basic_layout(self)\n\n            def generate(self):\n                at_toolchain = AutotoolsToolchain(self)\n                at_toolchain.generate()\n\n            def build(self):\n                autotools = Autotools(self)\n                autotools.autoreconf()\n                autotools.configure()\n                autotools.make()\n\n            def package(self):\n                autotools = Autotools(self)\n                autotools.install()\n                self.run(f\"lipo -info {os.path.join(self.package_folder, 'lib', 'libmylibrary.a')}\")\n\n            def package_info(self):\n                self.cpp_info.libs = [\"mylibrary\"]\n\n    \"\"\")\n\n    client.run('new autotools_lib -d name=mylibrary -d version=0.1')\n\n    client.save({\"conanfile.py\": conanfile})\n\n    client.run('create . -s=\"arch=armv8|x86_64\" -tf=\"\"')\n\n    assert \"libmylibrary.a are: x86_64 arm64\" in client.out\n"
  },
  {
    "path": "test/functional/toolchains/cmake/__init__.py",
    "content": ""
  },
  {
    "path": "test/functional/toolchains/cmake/cmakeconfigdeps/__init__.py",
    "content": ""
  },
  {
    "path": "test/functional/toolchains/cmake/cmakeconfigdeps/test_cmakeconfigdeps_aliases.py",
    "content": "import textwrap\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\nnew_value = \"will_break_next\"\n\nconsumer = textwrap.dedent(\"\"\"\nfrom conan import ConanFile\nfrom conan.tools.cmake import CMake\n\nclass Consumer(ConanFile):\n    name = \"consumer\"\n    version = \"1.0\"\n    settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n    generators = \"CMakeDeps\", \"CMakeToolchain\"\n    exports_sources = [\"CMakeLists.txt\"]\n    requires = \"hello/1.0\"\n\n    def build(self):\n        cmake = CMake(self)\n        cmake.configure()\n        cmake.build()\n\"\"\")\n\n\n@pytest.mark.tool(\"cmake\", \"3.27\")\ndef test_global_alias():\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n\n    class Hello(ConanFile):\n        name = \"hello\"\n        version = \"1.0\"\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n        def package_info(self):\n            # the default global target is \"hello::hello\"\n            self.cpp_info.set_property(\"cmake_target_aliases\", [\"hello\"])\n    \"\"\")\n\n    cmakelists = textwrap.dedent(\"\"\"\n    cmake_minimum_required(VERSION 3.15)\n    project(test NONE)\n\n    find_package(hello REQUIRED)\n    get_target_property(_aliased_target hello ALIASED_TARGET)\n    message(\"hello aliased target: ${_aliased_target}\")\n    \"\"\")\n\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(f\"create . -c tools.cmake.cmakedeps:new={new_value}\")\n\n    client.save({\"conanfile.py\": consumer, \"CMakeLists.txt\": cmakelists})\n    client.run(f\"create . -c tools.cmake.cmakedeps:new={new_value}\")\n\n    assert \"hello aliased target: hello::hello\" in client.out\n\n\n@pytest.mark.tool(\"cmake\", \"3.27\")\ndef test_component_alias():\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n\n    class Hello(ConanFile):\n        name = \"hello\"\n        version = \"1.0\"\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n        def package_info(self):\n            self.cpp_info.components[\"buy\"].set_property(\"cmake_target_aliases\",\n                [\"hola::adios\"])\n    \"\"\")\n\n    cmakelists = textwrap.dedent(\"\"\"\n    cmake_minimum_required(VERSION 3.15)\n    project(test NONE)\n\n    find_package(hello REQUIRED)\n    get_target_property(_aliased_target hola::adios ALIASED_TARGET)\n    message(\"hola::adios aliased target: ${_aliased_target}\")\n    \"\"\")\n\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(f\"create . -c tools.cmake.cmakedeps:new={new_value}\")\n\n    client.save({\"conanfile.py\": consumer, \"CMakeLists.txt\": cmakelists})\n    client.run(f\"create . -c tools.cmake.cmakedeps:new={new_value}\")\n\n    assert \"hola::adios aliased target: hello::buy\" in client.out\n\n\n@pytest.mark.tool(\"cmake\", \"3.27\")\ndef test_global_and_component_alias():\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n\n    class Hello(ConanFile):\n        name = \"hello\"\n        version = \"1.0\"\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n        def package_info(self):\n            self.cpp_info.set_property(\"cmake_target_aliases\", [\"hola::hola\"])\n            self.cpp_info.components[\"buy\"].set_property(\"cmake_target_aliases\",\n                [\"hola::adios\"])\n    \"\"\")\n\n    cmakelists = textwrap.dedent(\"\"\"\n    cmake_minimum_required(VERSION 3.15)\n    project(test NONE)\n\n    find_package(hello REQUIRED)\n    get_target_property(_aliased_target hola::hola ALIASED_TARGET)\n    message(\"hola::hola aliased target: ${_aliased_target}\")\n    \"\"\")\n\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(f\"create . -c tools.cmake.cmakedeps:new={new_value}\")\n\n    client.save({\"conanfile.py\": consumer, \"CMakeLists.txt\": cmakelists})\n    client.run(f\"create . -c tools.cmake.cmakedeps:new={new_value}\")\n\n    assert \"hola::hola aliased target: hello::hello\" in client.out\n\n\n@pytest.mark.tool(\"cmake\", \"3.27\")\ndef test_custom_name():\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n\n    class Hello(ConanFile):\n        name = \"hello\"\n        version = \"1.0\"\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n        def package_info(self):\n            self.cpp_info.set_property(\"cmake_target_name\", \"ola::comprar\")\n            self.cpp_info.set_property(\"cmake_target_aliases\", [\"hello\"])\n    \"\"\")\n\n    cmakelists = textwrap.dedent(\"\"\"\n    cmake_minimum_required(VERSION 3.15)\n    project(test NONE)\n\n    find_package(hello REQUIRED)\n    get_target_property(_aliased_target hello ALIASED_TARGET)\n    message(\"hello aliased target: ${_aliased_target}\")\n    \"\"\")\n\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(f\"create . -c tools.cmake.cmakedeps:new={new_value}\")\n\n    client.save({\"conanfile.py\": consumer, \"CMakeLists.txt\": cmakelists})\n    client.run(f\"create . -c tools.cmake.cmakedeps:new={new_value}\")\n\n    assert \"hello aliased target: ola::comprar\" in client.out\n\n\n@pytest.mark.tool(\"cmake\", \"3.27\")\ndef test_collide_component_alias():\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n\n    class Hello(ConanFile):\n        name = \"hello\"\n        version = \"1.0\"\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n        def package_info(self):\n            self.cpp_info.components[\"buy\"].set_property(\"cmake_target_aliases\", [\"hello::buy\"])\n    \"\"\")\n\n    cmakelists = textwrap.dedent(\"\"\"\n    cmake_minimum_required(VERSION 3.15)\n    project(test NONE)\n\n    find_package(hello REQUIRED)\n    \"\"\")\n\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(f\"create . -c tools.cmake.cmakedeps:new={new_value}\")\n\n    client.save({\"conanfile.py\": consumer, \"CMakeLists.txt\": cmakelists})\n    client.run(f\"create . -c tools.cmake.cmakedeps:new={new_value}\", assert_error=True)\n\n    assert \"Alias 'hello::buy' already defined as a target in hello/1.0\" in client.out\n\n\n@pytest.mark.tool(\"cmake\", \"3.27\")\ndef test_collide_component_alias_to_alias():\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n\n    class Hello(ConanFile):\n        name = \"hello\"\n        version = \"1.0\"\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n        def package_info(self):\n            self.cpp_info.components[\"ola\"].set_property(\"cmake_target_aliases\", [\"hello::foo\"])\n            self.cpp_info.components[\"buy\"].set_property(\"cmake_target_aliases\", [\"hello::foo\"])\n    \"\"\")\n\n    cmakelists = textwrap.dedent(\"\"\"\n    cmake_minimum_required(VERSION 3.15)\n    project(test NONE)\n\n    find_package(hello REQUIRED)\n    \"\"\")\n\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(f\"create . -c tools.cmake.cmakedeps:new={new_value}\")\n\n    client.save({\"conanfile.py\": consumer, \"CMakeLists.txt\": cmakelists})\n    client.run(f\"create . -c tools.cmake.cmakedeps:new={new_value}\", assert_error=True)\n\n    assert \"Alias 'hello::foo' already defined in hello/1.0\" in client.out\n\n\n@pytest.mark.tool(\"cmake\", \"3.27\")\n@pytest.mark.parametrize(\"root_target\", [\"hello::custom\", None])\ndef test_skip_global_if_aliased(root_target):\n    target_line = f'self.cpp_info.set_property(\"cmake_target_name\", \"{root_target}\")' if root_target else \"\"\n    target_name = root_target or \"hello::hello\"\n    conanfile = textwrap.dedent(f\"\"\"\n    from conan import ConanFile\n\n    class Hello(ConanFile):\n        name = \"hello\"\n        version = \"1.0\"\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n        def package_info(self):\n            {target_line}\n            self.cpp_info.components[\"foo\"].set_property(\"cmake_target_aliases\", [\"{target_name}\"])\n    \"\"\")\n\n    cmakelists = textwrap.dedent(\"\"\"\n    cmake_minimum_required(VERSION 3.15)\n    project(test NONE)\n\n    find_package(hello REQUIRED)\n    get_target_property(_aliased_target hello::hello ALIASED_TARGET)\n    message(\"hello::hello aliased target: ${_aliased_target}\")\n    \"\"\")\n\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(f\"create . -c tools.cmake.cmakedeps:new={new_value}\")\n\n    client.save({\"conanfile.py\": consumer, \"CMakeLists.txt\": cmakelists})\n    client.run(f\"create . -c tools.cmake.cmakedeps:new={new_value}\", assert_error=True)\n\n    assert f\"Can't define an alias '{target_name}' for the root target '{target_name}' in hello/1.0\" in client.out\n"
  },
  {
    "path": "test/functional/toolchains/cmake/cmakeconfigdeps/test_cmakeconfigdeps_frameworks.py",
    "content": "import platform\nimport textwrap\n\nimport pytest\n\nfrom conan.internal.model.pkg_type import PackageType\nfrom conan.test.utils.tools import TestClient\n\nnew_value = \"will_break_next\"\n\n\n@pytest.mark.parametrize(\"shared\", [True, False])\n@pytest.mark.tool(\"cmake\", \"3.27\")\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only OSX\")\ndef test_osx_frameworks(shared):\n    \"\"\"\n    Testing custom package frameworks + system frameworks + requirements\n    \"\"\"\n    client = TestClient()\n    client.run(\"new cmake_lib -d name=dep -d version=1.0\")\n    client.run(f\"create . -tf='' -o '&:shared={shared}'\")\n    cmakelists = textwrap.dedent(\"\"\"\n    set(CMAKE_CXX_COMPILER_WORKS 1)\n    set(CMAKE_CXX_ABI_COMPILED 1)\n    cmake_minimum_required(VERSION 3.15)\n    project(MyFramework CXX)\n\n    find_package(dep CONFIG REQUIRED)\n\n    add_library(MyFramework frame.cpp frame.h)\n\n    set_target_properties(MyFramework PROPERTIES\n      FRAMEWORK TRUE\n      FRAMEWORK_VERSION C # Version \"A\" is macOS convention\n      MACOSX_FRAMEWORK_IDENTIFIER MyFramework\n      PUBLIC_HEADER frame.h\n    )\n    target_link_libraries(MyFramework PRIVATE dep::dep)\n\n    if(BUILD_SHARED_LIBS)\n        target_link_libraries(MyFramework PRIVATE \"-framework CoreFoundation\")\n    endif()\n\n    install(TARGETS MyFramework\n      FRAMEWORK DESTINATION .)\n    \"\"\")\n    frame_cpp = textwrap.dedent(\"\"\"\n    #include \"frame.h\"\n    #include \"dep.h\"\n    #include <iostream>\n    #include <CoreFoundation/CoreFoundation.h>\n\n    void greet() {\n        // CoreFoundation\n        CFTypeRef keys[] = {CFSTR(\"key\")};\n        CFTypeRef values[] = {CFSTR(\"value\")};\n        CFDictionaryRef dict = CFDictionaryCreate(kCFAllocatorDefault, keys, values, sizeof(keys) / sizeof(keys[0]),\n                        &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);\n        if (dict)\n            CFRelease(dict);\n        // MyFramework\n        std::cout << \"Hello from MyFramework!\" << std::endl;\n\n        // dep requirement\n        dep();\n    }\n    \"\"\")\n    frame_h = textwrap.dedent(\"\"\"\n    #pragma once\n    #include <vector>\n    #include <string>\n    void greet();\n    \"\"\")\n    cpp_info_type = PackageType.SHARED if shared else PackageType.STATIC\n    conanfile = textwrap.dedent(f\"\"\"\n    import os\n    from conan import ConanFile\n    from conan.tools.cmake import CMake\n\n    class MyFramework(ConanFile):\n        name = \"frame\"\n        version = \"1.0\"\n        settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n        options = {{\"shared\": [True, False], \"fPIC\": [True, False]}}\n        default_options = {{\"shared\": False, \"fPIC\": True}}\n        exports_sources = \"frame.cpp\", \"frame.h\", \"CMakeLists.txt\"\n        generators = \"CMakeToolchain\", \"CMakeConfigDeps\"\n        requires = \"dep/1.0\"\n\n        def config_options(self):\n            if self.settings.os == \"Windows\":\n                self.options.rm_safe(\"fPIC\")\n\n        def configure(self):\n            if self.options.shared:\n                self.options.rm_safe(\"fPIC\")\n\n        def build(self):\n            cmake = CMake(self)\n            cmake.configure()\n            cmake.build()\n\n        def package(self):\n            cmake = CMake(self)\n            cmake.install()\n\n        def package_info(self):\n            self.cpp_info.type = \"{cpp_info_type}\"\n            self.cpp_info.package_framework = \"MyFramework\"\n            self.cpp_info.location = os.path.join(self.package_folder, \"MyFramework.framework\", \"MyFramework\")\n            # Using also a system framework\n            self.cpp_info.frameworks = [\"CoreFoundation\"]\n    \"\"\")\n    test_main_cpp = textwrap.dedent(\"\"\"\n    #include <MyFramework/frame.h>\n    int main() {\n        greet();\n    }\n    \"\"\")\n    test_conanfile = textwrap.dedent(\"\"\"\n    import os\n    from conan import ConanFile\n    from conan.tools.cmake import CMake, cmake_layout\n    from conan.tools.build import can_run\n\n    class LibTestConan(ConanFile):\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n        generators = \"CMakeConfigDeps\", \"CMakeToolchain\"\n\n        def requirements(self):\n            self.requires(self.tested_reference_str)\n\n        def build(self):\n            cmake = CMake(self)\n            cmake.configure()\n            cmake.build()\n\n        def layout(self):\n            cmake_layout(self)\n\n        def test(self):\n            if can_run(self):\n                cmd = os.path.join(self.cpp.build.bindir, \"example\")\n                self.run(cmd, env=\"conanrun\")\n    \"\"\")\n    test_cmakelists = textwrap.dedent(\"\"\"\n    set(CMAKE_CXX_COMPILER_WORKS 1)\n    set(CMAKE_CXX_ABI_COMPILED 1)\n    cmake_minimum_required(VERSION 3.15)\n    project(PackageTest CXX)\n    find_package(frame CONFIG REQUIRED)\n    add_executable(example main.cpp)\n    target_link_libraries(example frame::frame)\n    \"\"\")\n    client.save({\n        'test_package/main.cpp': test_main_cpp,\n        'test_package/CMakeLists.txt': test_cmakelists,\n        'test_package/conanfile.py': test_conanfile,\n        'CMakeLists.txt': cmakelists,\n        'frame.cpp': frame_cpp,\n        'frame.h': frame_h,\n        'conanfile.py': conanfile\n    }, clean_first=True)\n    client.run(f\"create . -c tools.cmake.cmakedeps:new={new_value} -o '*:shared={shared}'\")\n    assert \"Hello from MyFramework!\" in client.out\n    assert \"dep/1.0: Hello World\" in client.out\n"
  },
  {
    "path": "test/functional/toolchains/cmake/cmakeconfigdeps/test_cmakeconfigdeps_new.py",
    "content": "import os\nimport platform\nimport re\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.assets.sources import gen_function_h, gen_function_cpp\nfrom conan.test.utils.tools import TestClient\n\n\nnew_value = \"will_break_next\"\n\n\n@pytest.mark.tool(\"cmake\")\nclass TestExes:\n    @pytest.mark.parametrize(\"editable\", [False, True])\n    def test_exe(self, editable):\n        conanfile = textwrap.dedent(r\"\"\"\n            import os, platform\n            from conan import ConanFile\n            from conan.tools.cmake import CMake, cmake_layout\n\n            class Test(ConanFile):\n                name = \"mytool\"\n                version = \"0.1\"\n                package_type = \"application\"\n                settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n                generators = \"CMakeToolchain\"\n                exports_sources = \"*\"\n\n                def layout(self):\n                    cmake_layout(self)\n                    self.cpp.build.exe = \"mytool\"\n                    name = \"mytool.exe\" if platform.system() == \"Windows\" else \"mytool\"\n                    app_loc = os.path.join(\"build\", str(self.settings.build_type), name)\n                    self.cpp.build.location = app_loc\n\n                def build(self):\n                    cmake = CMake(self)\n                    cmake.configure()\n                    cmake.build()\n\n                def package(self):\n                    cmake = CMake(self)\n                    cmake.install()\n\n                def package_info(self):\n                    self.cpp_info.exe = \"mytool\"\n                    self.cpp_info.set_property(\"cmake_target_name\", \"MyTool::myexe\")\n                    self.cpp_info.location = os.path.join(\"bin\", \"mytool\")\n            \"\"\")\n        main = textwrap.dedent(\"\"\"\n            #include <iostream>\n            #include <fstream>\n\n            int main() {\n                std::cout << \"Mytool generating out.c!!!!!\" << std::endl;\n                std::ofstream f(\"out.c\");\n            }\n            \"\"\")\n        c = TestClient()\n        c.run(\"new cmake_exe -d name=mytool -d version=0.1\")\n        c.save({\"conanfile.py\": conanfile,\n                \"src/main.cpp\": main})\n        if editable:\n            c.run(\"editable add .\")\n        c.run(\"create .\")\n\n        for requires in (\"tool_requires\", \"requires\"):\n            consumer = textwrap.dedent(f\"\"\"\n                from conan import ConanFile\n                from conan.tools.cmake import CMakeDeps, CMakeToolchain, CMake, cmake_layout\n                class Consumer(ConanFile):\n                    settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n                    {requires} = \"mytool/0.1\"\n\n                    def generate(self):\n                        deps = CMakeDeps(self)\n                        deps.generate()\n                        tc = CMakeToolchain(self)\n                        tc.generate()\n\n                    def layout(self):\n                        cmake_layout(self)\n                    def build(self):\n                        cmake = CMake(self)\n                        cmake.configure()\n                        cmake.build()\n                \"\"\")\n            cmake = textwrap.dedent(\"\"\"\n                set(CMAKE_C_COMPILER_WORKS 1)\n                set(CMAKE_C_ABI_COMPILED 1)\n                cmake_minimum_required(VERSION 3.15)\n                project(consumer C)\n\n                find_package(mytool)\n                add_custom_command(OUTPUT out.c COMMAND MyTool::myexe)\n                add_library(myLib out.c)\n                \"\"\")\n            c.save({f\"consumer_{requires}/conanfile.py\": consumer,\n                    f\"consumer_{requires}/CMakeLists.txt\": cmake})\n            c.run(f\"build consumer_{requires} -c tools.cmake.cmakedeps:new={new_value}\")\n            assert \"find_package(mytool)\" in c.out\n            assert \"target_link_libraries(...\" not in c.out\n            assert \"Conan: Target declared imported executable 'MyTool::myexe'\" in c.out\n            assert \"Mytool generating out.c!!!!!\" in c.out\n\n    def test_exe_components(self):\n        conanfile = textwrap.dedent(r\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.cmake import CMake\n\n            class Test(ConanFile):\n                name = \"mytool\"\n                version = \"0.1\"\n                package_type = \"application\"\n                settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n                generators = \"CMakeToolchain\"\n                exports_sources = \"*\"\n\n                def build(self):\n                    cmake = CMake(self)\n                    cmake.configure()\n                    cmake.build()\n\n                def package(self):\n                    cmake = CMake(self)\n                    cmake.install()\n\n                def package_info(self):\n                    self.cpp_info.components[\"my1exe\"].exe = \"mytool1\"\n                    self.cpp_info.components[\"my1exe\"].set_property(\"cmake_target_name\", \"MyTool::my1exe\")\n                    self.cpp_info.components[\"my1exe\"].location = os.path.join(\"bin\", \"mytool1\")\n                    self.cpp_info.components[\"my2exe\"].exe = \"mytool2\"\n                    self.cpp_info.components[\"my2exe\"].set_property(\"cmake_target_name\", \"MyTool::my2exe\")\n                    self.cpp_info.components[\"my2exe\"].location = os.path.join(\"bin\", \"mytool2\")\n            \"\"\")\n        main = textwrap.dedent(\"\"\"\n            #include <iostream>\n            #include <fstream>\n\n            int main() {{\n                std::cout << \"Mytool{number} generating out{number}.c!!!!!\" << std::endl;\n                std::ofstream f(\"out{number}.c\");\n            }}\n            \"\"\")\n        cmake = textwrap.dedent(\"\"\"\n            set(CMAKE_CXX_COMPILER_WORKS 1)\n            set(CMAKE_CXX_ABI_COMPILED 1)\n            cmake_minimum_required(VERSION 3.15)\n            project(proj CXX)\n\n            add_executable(mytool1 src/main1.cpp)\n            add_executable(mytool2 src/main2.cpp)\n\n            install(TARGETS mytool1 DESTINATION \".\" RUNTIME DESTINATION bin)\n            install(TARGETS mytool2 DESTINATION \".\" RUNTIME DESTINATION bin)\n            \"\"\")\n        c = TestClient()\n        c.save({\"conanfile.py\": conanfile,\n                \"CMakeLists.txt\": cmake,\n                \"src/main1.cpp\": main.format(number=1),\n                \"src/main2.cpp\": main.format(number=2)\n                })\n        c.run(\"create .\")\n\n        consumer = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.cmake import CMakeDeps, CMakeToolchain, CMake, cmake_layout\n            class Consumer(ConanFile):\n                settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n                tool_requires = \"mytool/0.1\"\n\n                def generate(self):\n                    deps = CMakeDeps(self)\n                    deps.generate()\n                    tc = CMakeToolchain(self)\n                    tc.generate()\n                def layout(self):\n                    cmake_layout(self)\n                def build(self):\n                    cmake = CMake(self)\n                    cmake.configure()\n                    cmake.build()\n            \"\"\")\n        cmake = textwrap.dedent(\"\"\"\n            set(CMAKE_C_COMPILER_WORKS 1)\n            set(CMAKE_C_ABI_COMPILED 1)\n            cmake_minimum_required(VERSION 3.15)\n            project(consumer C)\n\n            find_package(mytool)\n            add_custom_command(OUTPUT out1.c COMMAND MyTool::my1exe)\n            add_custom_command(OUTPUT out2.c COMMAND MyTool::my2exe)\n            add_library(myLib out1.c out2.c)\n            \"\"\")\n        c.save({\"conanfile.py\": consumer,\n                \"CMakeLists.txt\": cmake}, clean_first=True)\n        c.run(f\"build . -c tools.cmake.cmakedeps:new={new_value}\")\n        assert \"Conan: Target declared imported executable 'MyTool::my1exe'\" in c.out\n        assert \"Mytool1 generating out1.c!!!!!\" in c.out\n        assert \"Conan: Target declared imported executable 'MyTool::my2exe'\" in c.out\n        assert \"Mytool2 generating out2.c!!!!!\" in c.out\n\n\n@pytest.mark.tool(\"cmake\")\nclass TestLibs:\n    def test_libs(self, matrix_client):\n        c = matrix_client\n        c.run(\"new cmake_lib -d name=app -d version=0.1 -d requires=matrix/1.0\")\n        c.run(f\"build . -c tools.cmake.cmakedeps:new={new_value}\")\n        assert \"find_package(matrix)\" in c.out\n        assert \"target_link_libraries(... matrix::matrix)\" in c.out\n        assert \"Conan: Target declared imported STATIC library 'matrix::matrix'\" in c.out\n\n    @pytest.mark.parametrize(\"shared\", [False, True])\n    def test_libs_transitive(self, transitive_libraries, shared):\n        c = transitive_libraries\n        c.run(\"new cmake_lib -d name=app -d version=0.1 -d requires=engine/1.0\")\n        shared = \"-o engine/*:shared=True\" if shared else \"\"\n        c.run(f\"build . {shared} -c tools.cmake.cmakedeps:new={new_value}\")\n        assert \"find_package(engine)\" in c.out\n        assert \"target_link_libraries(... engine::engine)\" in c.out\n        if shared:\n            assert \"matrix::matrix\" not in c.out  # It is hidden as static behind the engine\n            assert \"Conan: Target declared imported SHARED library 'engine::engine'\" in c.out\n        else:\n            assert \"Conan: Target declared imported STATIC library 'matrix::matrix'\" in c.out\n            assert \"Conan: Target declared imported STATIC library 'engine::engine'\" in c.out\n\n    # if not using cmake >= 3.23 the intermediate gamelib_test linkage fail\n    @pytest.mark.tool(\"cmake\", \"3.27\")\n    @pytest.mark.parametrize(\"shared\", [False, True])\n    def test_multilevel(self, shared):\n        # TODO: make this shared fixtures in conftest for multi-level shared testing\n        c = TestClient(default_server_user=True)\n        c.run(\"new cmake_lib -d name=matrix -d version=0.1\")\n        c.run(f\"create . -o *:shared={shared} -c tools.cmake.cmakedeps:new={new_value}\")\n\n        c.save({}, clean_first=True)\n        c.run(\"new cmake_lib -d name=engine -d version=0.1 -d requires=matrix/0.1\")\n        c.run(f\"create . -o *:shared={shared} -c tools.cmake.cmakedeps:new={new_value}\")\n\n        c.save({}, clean_first=True)\n        c.run(\"new cmake_lib -d name=gamelib -d version=0.1 -d requires=engine/0.1\")\n\n        # This specific CMake fails for shared libraries with old CMakeDeps in Linux\n        cmake = textwrap.dedent(\"\"\"\\\n            set(CMAKE_CXX_COMPILER_WORKS 1)\n            set(CMAKE_CXX_ABI_COMPILED 1)\n            cmake_minimum_required(VERSION 3.15)\n            project(gamelib CXX)\n\n            find_package(engine CONFIG REQUIRED)\n\n            add_library(gamelib src/gamelib.cpp)\n            target_include_directories(gamelib PUBLIC include)\n            target_link_libraries(gamelib PRIVATE engine::engine)\n\n            add_executable(gamelib_test src/gamelib_test.cpp)\n            target_link_libraries(gamelib_test PRIVATE gamelib)\n\n            set_target_properties(gamelib PROPERTIES PUBLIC_HEADER \"include/gamelib.h\")\n            install(TARGETS gamelib)\n            \"\"\")\n        # Testing that a local test executable links correctly with the new CMakeDeps\n        # It fails with the old CMakeDeps\n        c.save({\"CMakeLists.txt\": cmake,\n               \"src/gamelib_test.cpp\": '#include \"gamelib.h\"\\nint main() { gamelib(); }'})\n        c.run(f\"create . -o *:shared={shared} -c tools.cmake.cmakedeps:new={new_value}\")\n\n        c.save({}, clean_first=True)\n        c.run(\"new cmake_exe -d name=game -d version=0.1 -d requires=gamelib/0.1\")\n        c.run(f\"create . -o *:shared={shared} -c tools.cmake.cmakedeps:new={new_value}\")\n\n        assert \"matrix/0.1: Hello World Release!\"\n        assert \"engine/0.1: Hello World Release!\"\n        assert \"gamelib/0.1: Hello World Release!\"\n        assert \"game/0.1: Hello World Release!\"\n\n        # Make sure that transitive headers are private, fails to include, traits work\n        game_cpp = c.load(\"src/game.cpp\")\n        for header in (\"matrix\", \"engine\"):\n            new_game_cpp = f\"#include <{header}.h>\\n\" + game_cpp\n            c.save({\"src/game.cpp\": new_game_cpp})\n            c.run(f\"build . -o *:shared={shared} -c tools.cmake.cmakedeps:new={new_value}\",\n                  assert_error=True)\n            assert f\"{header}.h\" in c.out\n\n        # Make sure it works downloading to another cache\n        c.run(\"upload * -r=default -c\")\n        c.run(\"remove * -c\")\n\n        c2 = TestClient(servers=c.servers)\n        c2.run(\"new cmake_exe -d name=game -d version=0.1 -d requires=gamelib/0.1\")\n        c2.run(f\"create . -o *:shared={shared} -c tools.cmake.cmakedeps:new={new_value}\")\n\n        assert \"matrix/0.1: Hello World Release!\"\n        assert \"engine/0.1: Hello World Release!\"\n        assert \"gamelib/0.1: Hello World Release!\"\n        assert \"game/0.1: Hello World Release!\"\n\n\nclass TestLibsIntegration:\n    def test_libs_no_location(self):\n        # Integration test\n        # https://github.com/conan-io/conan/issues/17256\n        c = TestClient()\n        dep = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Dep(ConanFile):\n                name = \"dep\"\n                version = \"0.1\"\n                settings = \"build_type\"\n                def package_info(self):\n                    self.cpp_info.libs = [\"dep\"]\n            \"\"\")\n\n        c.save({\"dep/conanfile.py\": dep,\n                \"app/conanfile.py\": GenConanfile().with_requires(\"dep/0.1\")\n                                                  .with_settings(\"build_type\")})\n\n        c.run(\"create dep\")\n        c.run(f\"install app -c tools.cmake.cmakedeps:new={new_value} -g CMakeDeps\",\n              assert_error=True)\n        assert \"ERROR: Error in generator 'CMakeDeps': dep/0.1: Cannot obtain 'location' \" \\\n               \"for library 'dep'\" in c.out\n\n    def test_custom_file_targetname(self):\n        # Integration test\n        c = TestClient()\n        dep = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Dep(ConanFile):\n                name = \"dep\"\n                version = \"0.1\"\n                settings = \"build_type\"\n                def package_info(self):\n                    self.cpp_info.set_property(\"cmake_file_name\", \"MyDep\")\n                    self.cpp_info.set_property(\"cmake_target_name\", \"MyTargetDep\")\n                \"\"\")\n\n        c.save({\"dep/conanfile.py\": dep,\n                \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_requires(\"dep/0.1\"),\n                \"app/conanfile.py\": GenConanfile().with_requires(\"pkg/0.1\")\n               .with_settings(\"build_type\")})\n\n        c.run(\"create dep\")\n        c.run(\"create pkg\")\n        c.run(f\"install app -c tools.cmake.cmakedeps:new={new_value} -g CMakeDeps\")\n        targets_cmake = c.load(\"app/pkg-Targets-release.cmake\")\n        assert \"find_dependency(MyDep REQUIRED CONFIG)\" in targets_cmake\n        assert 'set_property(TARGET pkg::pkg APPEND PROPERTY INTERFACE_LINK_LIBRARIES\\n' \\\n               '             \"$<$<CONFIG:RELEASE>:MyTargetDep>\")' in targets_cmake\n\n\nclass TestLibsLinkageTraits:\n    def test_linkage_shared_static(self):\n        \"\"\"\n        the static library is skipped\n        \"\"\"\n        c = TestClient()\n        c.run(\"new cmake_lib -d name=matrix -d version=0.1\")\n        c.run(f\"create . -c tools.cmake.cmakedeps:new={new_value} -tf=\")\n\n        c.save({}, clean_first=True)\n        c.run(\"new cmake_lib -d name=engine -d version=0.1 -d requires=matrix/0.1\")\n        c.run(f\"create . -o engine/*:shared=True -c tools.cmake.cmakedeps:new={new_value} -tf=\")\n\n        c.save({}, clean_first=True)\n        c.run(\"new cmake_exe -d name=game -d version=0.1 -d requires=engine/0.1\")\n        c.run(f\"create . -o engine/*:shared=True -c tools.cmake.cmakedeps:new={new_value} \"\n              \"-c tools.compilation:verbosity=verbose\")\n        assert re.search(r\"Skipped binaries(\\s*)matrix/0.1\", c.out)\n        assert \"matrix/0.1: Hello World Release!\"\n        assert \"engine/0.1: Hello World Release!\"\n        assert \"game/0.1: Hello World Release!\"\n\n    @pytest.mark.tool(\"cmake\", \"3.27\")\n    @pytest.mark.parametrize(\"shared\", [False, True])\n    def test_transitive_headers(self, shared):\n        c = TestClient()\n        c.run(\"new cmake_lib -d name=matrix -d version=0.1\")\n        c.run(f\"create . -o *:shared={shared} -c tools.cmake.cmakedeps:new={new_value} -tf=\")\n\n        c.save({}, clean_first=True)\n        c.run(\"new cmake_lib -d name=engine -d version=0.1 -d requires=matrix/0.1\")\n        engine_h = c.load(\"include/engine.h\")\n        engine_h = \"#include <matrix.h>\\n\" + engine_h\n        c.save({\"include/engine.h\": engine_h})\n        conanfile = c.load(\"conanfile.py\")\n        conanfile = conanfile.replace('self.requires(\"matrix/0.1\")',\n                                      'self.requires(\"matrix/0.1\", transitive_headers=True)')\n        c.save({\"conanfile.py\": conanfile})\n        c.run(f\"create . -o *:shared={shared} -c tools.cmake.cmakedeps:new={new_value} -tf=\")\n\n        c.save({}, clean_first=True)\n        c.run(\"new cmake_exe -d name=game -d version=0.1 -d requires=engine/0.1\")\n        c.run(f\"build . -o *:shared={shared} -c tools.cmake.cmakedeps:new={new_value}\")\n        # it works\n\n    @pytest.mark.tool(\"cmake\", \"3.27\")\n    def test_link_features(self):\n        tc = TestClient()\n        tc.run(\"new cmake_lib -d name=matrix -d version=0.1\")\n        conanfile = tc.load(\"conanfile.py\")\n        # So that the custom link feature works\n        conanfile += (\"        self.cpp_info.set_property('cmake_extra_variables', \"\n                      \"{'CMAKE_LINK_LIBRARY_USING_MYFET_SUPPORTED': True,\"\n                      \"'CMAKE_LINK_LIBRARY_USING_MYFET': '<LIBRARY>'})\\n\")\n        # And set this library to use the custom link feature\n        conanfile += \"        self.cpp_info.set_property('cmake_link_feature', 'MYFET')\"\n        tc.save({\"conanfile.py\": conanfile})\n        tc.run(f\"create -c tools.cmake.cmakedeps:new={new_value}\")\n\n        tc.save({}, clean_first=True)\n        tc.run(\"new cmake_lib -d name=lib -d version=0.1 -d requires=matrix/0.1\")\n        tc.run(f\"create -c tools.cmake.cmakedeps:new={new_value}\")\n        test_build_folder = tc.created_test_build_folder(\"lib/0.1\")\n        test_generators_folder = os.path.join(\"test_package\", test_build_folder, \"generators\")\n        libs_targets = tc.load(os.path.join(test_generators_folder, \"lib-Targets-release.cmake\"))\n        assert '\"$<LINK_LIBRARY:MYFET,$<$<CONFIG:RELEASE>:matrix::matrix>>\"' in libs_targets\n\n\n@pytest.mark.tool(\"cmake\")\nclass TestLibsComponents:\n    def test_libs_components(self, matrix_client_components):\n        \"\"\"\n        explicit usage of components\n        \"\"\"\n        c = matrix_client_components\n\n        # TODO: Check that find_package(.. COMPONENTS nonexisting) fails\n        c.run(\"new cmake_exe -d name=app -d version=0.1 -d requires=matrix/1.0\")\n        cmake = textwrap.dedent(\"\"\"\n            set(CMAKE_CXX_COMPILER_WORKS 1)\n            set(CMAKE_CXX_ABI_COMPILED 1)\n            cmake_minimum_required(VERSION 3.15)\n            project(app CXX)\n\n            find_package(matrix CONFIG REQUIRED)\n            add_executable(app src/app.cpp)\n            # standard one, and a custom cmake_target_name one\n            target_link_libraries(app PRIVATE matrix::module MatrixHeaders)\n            \"\"\")\n        app_cpp = textwrap.dedent(\"\"\"\n            #include \"module.h\"\n            #include \"headers.h\"\n            int main() { module(); headers();}\n            \"\"\")\n        c.save({\"CMakeLists.txt\": cmake,\n                \"src/app.cpp\": app_cpp})\n        c.run(f\"build . -c tools.cmake.cmakedeps:new={new_value}\")\n        assert \"find_package(matrix)\" in c.out\n        assert \"target_link_libraries(... matrix::matrix)\" in c.out\n        assert \"Conan: Target declared imported STATIC library 'matrix::vector'\" in c.out\n        assert \"Conan: Target declared imported STATIC library 'matrix::module'\" in c.out\n        if platform.system() == \"Windows\":\n            c.run_command(r\".\\build\\Release\\app.exe\")\n            assert \"Matrix headers __cplusplus: __cplusplus2014\" in c.out\n\n    def test_libs_components_default(self, matrix_client_components):\n        \"\"\"\n        Test that the default components are used when no component is specified\n        \"\"\"\n        c = matrix_client_components\n\n        c.run(\"new cmake_exe -d name=app -d version=0.1 -d requires=matrix/1.0\")\n\n        app_cpp = textwrap.dedent(\"\"\"\n            #include \"module.h\"\n            int main() { module();}\n            \"\"\")\n        cmake = textwrap.dedent(\"\"\"\n            set(CMAKE_CXX_COMPILER_WORKS 1)\n            set(CMAKE_CXX_ABI_COMPILED 1)\n            cmake_minimum_required(VERSION 3.15)\n            project(app CXX)\n\n            find_package(matrix CONFIG REQUIRED)\n            add_executable(app src/app.cpp)\n            target_link_libraries(app PRIVATE matrix::matrix)\n            \"\"\")\n        c.save({\"src/app.cpp\": app_cpp,\n                \"CMakeLists.txt\": cmake})\n        c.run(f\"build . -c tools.cmake.cmakedeps:new={new_value}\")\n        assert \"Conan: Target declared imported STATIC library 'matrix::vector'\" in c.out\n        assert \"Conan: Target declared imported STATIC library 'matrix::module'\" in c.out\n        assert \"Conan: Target declared imported INTERFACE library 'MatrixHeaders'\" in c.out\n\n    def test_libs_components_default_error(self, matrix_client_components):\n        \"\"\"\n        Same as above, but it fails, because headers is not in the default components\n        \"\"\"\n        c = matrix_client_components\n\n        c.run(\"new cmake_exe -d name=app -d version=0.1 -d requires=matrix/1.0\")\n\n        app_cpp = textwrap.dedent(\"\"\"\n            #include \"module.h\"\n            #include \"headers.h\"\n            int main() { module();}\n            \"\"\")\n        cmake = textwrap.dedent(\"\"\"\n            set(CMAKE_CXX_COMPILER_WORKS 1)\n            set(CMAKE_CXX_ABI_COMPILED 1)\n            cmake_minimum_required(VERSION 3.15)\n            project(app CXX)\n\n            find_package(matrix CONFIG REQUIRED)\n            add_executable(app src/app.cpp)\n            target_link_libraries(app PRIVATE matrix::matrix)\n            \"\"\")\n        c.save({\"src/app.cpp\": app_cpp,\n                \"CMakeLists.txt\": cmake})\n        c.run(f\"build . -c tools.cmake.cmakedeps:new={new_value}\", assert_error=True)\n        assert \"Error in build() method, line 35\" in c.out\n        assert \"Conan: Target declared imported STATIC library 'matrix::vector'\" in c.out\n        assert \"Conan: Target declared imported STATIC library 'matrix::module'\" in c.out\n        cmake = textwrap.dedent(\"\"\"\n            set(CMAKE_CXX_COMPILER_WORKS 1)\n            set(CMAKE_CXX_ABI_COMPILED 1)\n            cmake_minimum_required(VERSION 3.15)\n            project(app CXX)\n\n            find_package(matrix CONFIG REQUIRED)\n            add_executable(app src/app.cpp)\n            target_link_libraries(app PRIVATE matrix::matrix MatrixHeaders)\n            \"\"\")\n        c.save({\"CMakeLists.txt\": cmake})\n        c.run(f\"build . -c tools.cmake.cmakedeps:new={new_value}\")\n        assert \"Running CMake.build()\" in c.out  # Now it doesn't fail\n\n    def test_libs_components_transitive(self, matrix_client_components):\n        \"\"\"\n        explicit usage of components\n        matrix::module -> matrix::vector\n\n        engine::bots -> engine::physix\n        engine::physix -> matrix::vector\n        engine::world -> engine::physix, matrix::module\n        \"\"\"\n        c = matrix_client_components\n        bots_h = gen_function_h(name=\"bots\")\n        bots_cpp = gen_function_cpp(name=\"bots\", includes=[\"bots\", \"physix\"], calls=[\"physix\"])\n        physix_h = gen_function_h(name=\"physix\")\n        physix_cpp = gen_function_cpp(name=\"physix\", includes=[\"physix\", \"vector\"], calls=[\"vector\"])\n        world_h = gen_function_h(name=\"world\")\n        world_cpp = gen_function_cpp(name=\"world\", includes=[\"world\", \"physix\", \"module\"],\n                                     calls=[\"physix\", \"module\"])\n\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.cmake import CMake\n            from conan.tools.files import copy\n\n            class Engine(ConanFile):\n              name = \"engine\"\n              version = \"1.0\"\n              settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n              generators = \"CMakeToolchain\"\n              exports_sources = \"src/*\", \"CMakeLists.txt\"\n\n              requires = \"matrix/1.0\"\n              generators = \"CMakeDeps\", \"CMakeToolchain\"\n\n              def build(self):\n                  cmake = CMake(self)\n                  cmake.configure()\n                  cmake.build()\n\n              def package(self):\n                  cmake = CMake(self)\n                  cmake.install()\n\n              def package_info(self):\n                  self.cpp_info.set_property(\"cmake_file_name\", \"MyEngine\")\n                  self.cpp_info.components[\"bots\"].libs = [\"bots\"]\n                  self.cpp_info.components[\"bots\"].includedirs = [\"include\"]\n                  self.cpp_info.components[\"bots\"].libdirs = [\"lib\"]\n                  self.cpp_info.components[\"bots\"].requires = [\"physix\"]\n\n                  self.cpp_info.components[\"physix\"].libs = [\"physix\"]\n                  self.cpp_info.components[\"physix\"].includedirs = [\"include\"]\n                  self.cpp_info.components[\"physix\"].libdirs = [\"lib\"]\n                  self.cpp_info.components[\"physix\"].requires = [\"matrix::vector\"]\n\n                  self.cpp_info.components[\"world\"].libs = [\"world\"]\n                  self.cpp_info.components[\"world\"].includedirs = [\"include\"]\n                  self.cpp_info.components[\"world\"].libdirs = [\"lib\"]\n                  self.cpp_info.components[\"world\"].requires = [\"physix\", \"matrix::module\"]\n                  \"\"\")\n\n        cmakelists = textwrap.dedent(\"\"\"\n               set(CMAKE_CXX_COMPILER_WORKS 1)\n               set(CMAKE_CXX_ABI_COMPILED 1)\n               cmake_minimum_required(VERSION 3.15)\n               project(matrix CXX)\n\n               find_package(matrix CONFIG REQUIRED)\n\n               add_library(physix src/physix.cpp)\n               add_library(bots src/bots.cpp)\n               add_library(world src/world.cpp)\n\n               target_link_libraries(physix PRIVATE matrix::vector)\n               target_link_libraries(bots PRIVATE physix)\n               target_link_libraries(world PRIVATE physix matrix::module)\n\n               set_target_properties(bots PROPERTIES PUBLIC_HEADER \"src/bots.h\")\n               set_target_properties(physix PROPERTIES PUBLIC_HEADER \"src/physix.h\")\n               set_target_properties(world PROPERTIES PUBLIC_HEADER \"src/world.h\")\n               install(TARGETS physix bots world)\n               \"\"\")\n        c.save({\"src/physix.h\": physix_h,\n                \"src/physix.cpp\": physix_cpp,\n                \"src/bots.h\": bots_h,\n                \"src/bots.cpp\": bots_cpp,\n                \"src/world.h\": world_h,\n                \"src/world.cpp\": world_cpp,\n                \"CMakeLists.txt\": cmakelists,\n                \"conanfile.py\": conanfile})\n        c.run(\"create .\")\n\n        c.save({}, clean_first=True)\n        c.run(\"new cmake_exe -d name=app -d version=0.1 -d requires=engine/1.0\")\n        cmake = textwrap.dedent(\"\"\"\n            set(CMAKE_CXX_COMPILER_WORKS 1)\n            set(CMAKE_CXX_ABI_COMPILED 1)\n            cmake_minimum_required(VERSION 3.15)\n            project(app CXX)\n\n            find_package(MyEngine CONFIG REQUIRED)\n\n            add_executable(app src/app.cpp)\n            target_link_libraries(app PRIVATE engine::bots)\n\n            install(TARGETS app)\n            \"\"\")\n        app_cpp = textwrap.dedent(\"\"\"\n            #include \"bots.h\"\n            int main() { bots();}\n            \"\"\")\n        c.save({\"CMakeLists.txt\": cmake,\n                \"src/app.cpp\": app_cpp})\n        c.run(f\"create . -c tools.cmake.cmakedeps:new={new_value}\")\n        assert \"find_package(MyEngine)\" in c.out\n        assert \"Conan: Target declared imported STATIC library 'matrix::vector'\" in c.out\n        assert \"Conan: Target declared imported STATIC library 'matrix::module'\" in c.out\n        assert \"Conan: Target declared imported INTERFACE library 'matrix::matrix'\" in c.out\n        assert \"Conan: Target declared imported STATIC library 'engine::bots'\" in c.out\n        assert \"Conan: Target declared imported STATIC library 'engine::physix'\" in c.out\n        assert \"Conan: Target declared imported STATIC library 'engine::world'\" in c.out\n        assert \"Conan: Target declared imported INTERFACE library 'engine::engine'\" in c.out\n\n        assert \"bots: Release!\" in c.out\n        assert \"physix: Release!\" in c.out\n        assert \"vector: Release!\" in c.out\n\n    def test_libs_components_multilib(self):\n        \"\"\"\n        cpp_info.libs = [\"lib1\", \"lib2\"]\n        \"\"\"\n        c = TestClient()\n        vector_h = gen_function_h(name=\"vector\")\n        vector_cpp = gen_function_cpp(name=\"vector\", includes=[\"vector\"])\n        module_h = gen_function_h(name=\"module\")\n        module_cpp = gen_function_cpp(name=\"module\", includes=[\"module\"])\n\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.cmake import CMake\n\n            class Matrix(ConanFile):\n                name = \"matrix\"\n                version = \"1.0\"\n                settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n                generators = \"CMakeToolchain\"\n                exports_sources = \"src/*\", \"CMakeLists.txt\"\n\n                generators = \"CMakeDeps\", \"CMakeToolchain\"\n\n                def build(self):\n                    cmake = CMake(self)\n                    cmake.configure()\n                    cmake.build()\n\n                def package(self):\n                    cmake = CMake(self)\n                    cmake.install()\n\n                def package_info(self):\n                    self.cpp_info.set_property(\"cmake_target_name\", \"MyMatrix::MyMatrix\")\n                    self.cpp_info.libs = [\"module\", \"vector\"]\n                  \"\"\")\n\n        cmakelists = textwrap.dedent(\"\"\"\n            set(CMAKE_CXX_COMPILER_WORKS 1)\n            set(CMAKE_CXX_ABI_COMPILED 1)\n            cmake_minimum_required(VERSION 3.15)\n            project(matrix CXX)\n\n            add_library(module src/module.cpp)\n            add_library(vector src/vector.cpp)\n\n            set_target_properties(vector PROPERTIES PUBLIC_HEADER \"src/vector.h\")\n            set_target_properties(module PROPERTIES PUBLIC_HEADER \"src/module.h\")\n            install(TARGETS module vector)\n            \"\"\")\n        c.save({\"src/module.h\": module_h,\n                \"src/module.cpp\": module_cpp,\n                \"src/vector.h\": vector_h,\n                \"src/vector.cpp\": vector_cpp,\n                \"CMakeLists.txt\": cmakelists,\n                \"conanfile.py\": conanfile})\n        c.run(\"create .\")\n\n        c.save({}, clean_first=True)\n        c.run(\"new cmake_exe -d name=app -d version=0.1 -d requires=matrix/1.0\")\n        cmake = textwrap.dedent(\"\"\"\n            set(CMAKE_CXX_COMPILER_WORKS 1)\n            set(CMAKE_CXX_ABI_COMPILED 1)\n            cmake_minimum_required(VERSION 3.15)\n            project(app CXX)\n\n            find_package(matrix CONFIG REQUIRED)\n\n            add_executable(app src/app.cpp)\n            target_link_libraries(app PRIVATE MyMatrix::MyMatrix)\n\n            install(TARGETS app)\n            \"\"\")\n        app_cpp = textwrap.dedent(\"\"\"\n            #include \"vector.h\"\n            #include \"module.h\"\n            int main() { vector();module();}\n            \"\"\")\n        c.save({\"CMakeLists.txt\": cmake,\n                \"src/app.cpp\": app_cpp})\n        c.run(f\"create . -c tools.cmake.cmakedeps:new={new_value}\")\n        assert \"Conan: Target declared imported STATIC library 'matrix::_vector'\" in c.out\n        assert \"Conan: Target declared imported STATIC library 'matrix::_module'\" in c.out\n        assert \"Conan: Target declared imported INTERFACE library 'MyMatrix::MyMatrix'\" in c.out\n        assert \"matrix::matrix\" not in c.out\n\n        assert \"vector: Release!\" in c.out\n        assert \"module: Release!\" in c.out\n        assert \"vector: Release!\" in c.out\n\n    def test_libs_components_multilib_component(self):\n        \"\"\"\n        cpp_info.components[\"mycomp\"].libs = [\"lib1\", \"lib2\"]\n        \"\"\"\n        c = TestClient()\n\n        vector_h = gen_function_h(name=\"vector\")\n        vector_cpp = gen_function_cpp(name=\"vector\", includes=[\"vector\"])\n        module_h = gen_function_h(name=\"module\")\n        module_cpp = gen_function_cpp(name=\"module\", includes=[\"module\"])\n\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.cmake import CMake\n\n            class Matrix(ConanFile):\n                name = \"matrix\"\n                version = \"1.0\"\n                settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n                generators = \"CMakeToolchain\"\n                exports_sources = \"src/*\", \"CMakeLists.txt\"\n\n                generators = \"CMakeDeps\", \"CMakeToolchain\"\n\n                def build(self):\n                    cmake = CMake(self)\n                    cmake.configure()\n                    cmake.build()\n\n                def package(self):\n                    cmake = CMake(self)\n                    cmake.install()\n\n                def package_info(self):\n                    self.cpp_info.set_property(\"cmake_target_name\", \"MyMatrix::MyMatrix\")\n                    self.cpp_info.components[\"mycomp\"].set_property(\"cmake_target_name\",\n                                                                    \"MyComp::MyComp\")\n                    self.cpp_info.components[\"mycomp\"].libs = [\"module\", \"vector\"]\n                  \"\"\")\n\n        cmakelists = textwrap.dedent(\"\"\"\n            set(CMAKE_CXX_COMPILER_WORKS 1)\n            set(CMAKE_CXX_ABI_COMPILED 1)\n            cmake_minimum_required(VERSION 3.15)\n            project(matrix CXX)\n\n            add_library(module src/module.cpp)\n            add_library(vector src/vector.cpp)\n\n            set_target_properties(vector PROPERTIES PUBLIC_HEADER \"src/vector.h\")\n            set_target_properties(module PROPERTIES PUBLIC_HEADER \"src/module.h\")\n            install(TARGETS module vector)\n            \"\"\")\n        c.save({\"src/module.h\": module_h,\n                \"src/module.cpp\": module_cpp,\n                \"src/vector.h\": vector_h,\n                \"src/vector.cpp\": vector_cpp,\n                \"CMakeLists.txt\": cmakelists,\n                \"conanfile.py\": conanfile})\n        c.run(\"create .\")\n\n        c.save({}, clean_first=True)\n        c.run(\"new cmake_exe -d name=app -d version=0.1 -d requires=matrix/1.0\")\n        cmake = textwrap.dedent(\"\"\"\n            set(CMAKE_CXX_COMPILER_WORKS 1)\n            set(CMAKE_CXX_ABI_COMPILED 1)\n            cmake_minimum_required(VERSION 3.15)\n            project(app CXX)\n\n            find_package(matrix CONFIG REQUIRED)\n\n            add_executable(app src/app.cpp)\n            target_link_libraries(app PRIVATE MyMatrix::MyMatrix)\n\n            install(TARGETS app)\n            \"\"\")\n        app_cpp = textwrap.dedent(\"\"\"\n            #include \"vector.h\"\n            #include \"module.h\"\n            int main() { vector();module();}\n            \"\"\")\n        c.save({\"CMakeLists.txt\": cmake,\n                \"src/app.cpp\": app_cpp})\n        c.run(f\"create . -c tools.cmake.cmakedeps:new={new_value}\")\n        assert \"Conan: Target declared imported STATIC library 'matrix::_mycomp_vector'\" in c.out\n        assert \"Conan: Target declared imported STATIC library 'matrix::_mycomp_module'\" in c.out\n        assert \"Conan: Target declared imported INTERFACE library 'MyMatrix::MyMatrix'\" in c.out\n        assert \"matrix::matrix\" not in c.out\n\n        assert \"vector: Release!\" in c.out\n        assert \"module: Release!\" in c.out\n        assert \"vector: Release!\" in c.out\n\n\n@pytest.mark.tool(\"cmake\")\nclass TestHeaders:\n    def test_header_lib(self, matrix_client):\n        c = matrix_client\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import copy\n            class EngineHeader(ConanFile):\n                name = \"engine\"\n                version = \"1.0\"\n                requires = \"matrix/1.0\"\n                exports_sources = \"*.h\"\n                settings = \"compiler\"\n                def package(self):\n                    copy(self, \"*.h\", src=self.source_folder, dst=self.package_folder)\n                def package_id(self):\n                    self.info.clear()\n                def package_info(self):\n                    self.cpp_info.defines = [\"MY_MATRIX_HEADERS_DEFINE=1\",\n                                             \"MY_MATRIX_HEADERS_DEFINE2=1\"]\n                    # Few flags to cover that CMakeDeps doesn't crash with them\n                    if self.settings.compiler == \"msvc\":\n                        self.cpp_info.cxxflags = [\"/Zc:__cplusplus\"]\n                        self.cpp_info.cflags = [\"/Zc:__cplusplus\"]\n                        self.cpp_info.system_libs = [\"ws2_32\"]\n                    else:\n                        self.cpp_info.system_libs = [\"m\", \"dl\"]\n                        # Just to verify CMake don't break\n                    if self.settings.compiler == \"gcc\":\n                        # This triggers errors when not quoted and list \";\" separated\n                        self.cpp_info.sharedlinkflags = [\"SHELL:-z lazy\", \"SHELL:-u symbol1\",\n                                                         \"SHELL:-u symbol2\", \"-s\"]\n                        self.cpp_info.exelinkflags = [\"SHELL:-z lazy\", \"SHELL:-u symbol1\",\n                                                      \"SHELL:-u symbol2\", \"-s\"]\n             \"\"\")\n        engine_h = textwrap.dedent(\"\"\"\n            #pragma once\n            #include <iostream>\n            #include \"matrix.h\"\n            #ifndef MY_MATRIX_HEADERS_DEFINE\n            #error \"Fatal error MY_MATRIX_HEADERS_DEFINE not defined\"\n            #endif\n            #ifndef MY_MATRIX_HEADERS_DEFINE2\n            #error \"Fatal error MY_MATRIX_HEADERS_DEFINE2 not defined\"\n            #endif\n            void engine(){ std::cout << \"Engine!\" <<std::endl; matrix(); }\n            \"\"\")\n\n        c.save({\"conanfile.py\": conanfile,\n                \"include/engine.h\": engine_h})\n        c.run(\"create .\")\n\n        app = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.cmake import CMake\n            class EngineHeader(ConanFile):\n                settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n                requires = \"engine/1.0\"\n                generators = \"CMakeDeps\", \"CMakeToolchain\"\n                def build(self):\n                    cmake = CMake(self)\n                    cmake.configure()\n                    cmake.build()\n             \"\"\")\n        cmake = textwrap.dedent(\"\"\"\n            set(CMAKE_CXX_COMPILER_WORKS 1)\n            set(CMAKE_CXX_ABI_COMPILED 1)\n            cmake_minimum_required(VERSION 3.15)\n            project(app CXX)\n            find_package(engine CONFIG REQUIRED)\n            add_executable(app src/app.cpp)\n            target_link_libraries(app PRIVATE engine::engine)\n            \"\"\")\n        c.save({\"conanfile.py\": app,\n                \"CMakeLists.txt\": cmake,\n                \"src/app.cpp\": gen_function_cpp(name=\"main\", includes=[\"engine\"], calls=[\"engine\"])},\n               clean_first=True)\n        c.run(f\"build . -c tools.cmake.cmakedeps:new={new_value}\")\n        assert \"Conan: Target declared imported STATIC library 'matrix::matrix'\" in c.out\n        assert \"Conan: Target declared imported INTERFACE library 'engine::engine'\" in c.out\n\n    @pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Only windows\")\n    def test_conditional_header(self):\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import copy\n            class EngineHeader(ConanFile):\n                name = \"engine\"\n                exports_sources = \"*.h\"\n                def package(self):\n                    copy(self, \"*.h\", src=self.source_folder, dst=self.package_folder)\n                def package_info(self):\n                    self.cpp_info.defines = [\"MY_MATRIX_HEADERS_{version}_DEFINE=1\"]\n            \"\"\")\n        engine_h = textwrap.dedent(\"\"\"\n            #pragma once\n            #include <iostream>\n\n            #ifndef MY_MATRIX_HEADERS_{version}_DEFINE\n            #error \"Fatal error MY_MATRIX_HEADERS_{version}_DEFINE not defined\"\n            #endif\n            void engine(){{ std::cout << \"Engine {version}!\" <<std::endl; }}\n            \"\"\")\n\n        c = TestClient()\n        c.save({\"conanfile.py\": conanfile.format(version=\"1_0\"),\n                \"include/engine.h\": engine_h.format(version=\"1_0\")})\n        c.run(\"create . --version=1_0\")\n        c.save({\"conanfile.py\": conanfile.format(version=\"1_1\"),\n                \"include/engine.h\": engine_h.format(version=\"1_1\")})\n        c.run(\"create . --version=1_1\")\n\n        app = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.cmake import CMake, cmake_layout\n            class EngineHeader(ConanFile):\n                settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n                generators = \"CMakeDeps\", \"CMakeToolchain\"\n                def requirements(self):\n                    v = \"1_0\" if self.settings.build_type == \"Debug\" else \"1_1\"\n                    self.requires(f\"engine/{v}\")\n                def layout(self):\n                    cmake_layout(self)\n                def build(self):\n                    cmake = CMake(self)\n                    cmake.configure()\n                    cmake.build()\n                    self.run(os.path.join(self.cpp.build.bindir, \"app\"))\n             \"\"\")\n        cmake = textwrap.dedent(\"\"\"\n            set(CMAKE_CXX_COMPILER_WORKS 1)\n            set(CMAKE_CXX_ABI_COMPILED 1)\n            cmake_minimum_required(VERSION 3.15)\n            project(app CXX)\n            find_package(engine CONFIG REQUIRED)\n            add_executable(app src/app.cpp)\n            target_link_libraries(app PRIVATE engine::engine)\n            \"\"\")\n        c.save({\"conanfile.py\": app,\n                \"CMakeLists.txt\": cmake,\n                \"src/app.cpp\": gen_function_cpp(name=\"main\", includes=[\"engine\"], calls=[\"engine\"])},\n               clean_first=True)\n        c.run(f\"build . -c tools.cmake.cmakedeps:new={new_value}\")\n        assert \"engine/1_1\" in c.out\n        assert \"engine/1_0\" not in c.out\n        assert \"Conan: Target declared imported INTERFACE library 'engine::engine'\" in c.out\n        assert \"Engine 1_1!\" in c.out\n\n        c.run(f\"build . -c tools.cmake.cmakedeps:new={new_value} -s build_type=Debug\")\n        assert \"engine/1_1\" not in c.out\n        assert \"engine/1_0\" in c.out\n        assert \"Conan: Target declared imported INTERFACE library 'engine::engine'\" in c.out\n        assert \"Engine 1_0!\" in c.out\n\n\nclass TestToolRequires:\n    def test_tool_requires(self):\n        \"\"\" tool-requires should not define the try-compile or global variables\n        for includedirs, libraries, definitions, otherwise the build-context would\n        override the host context\"\"\"\n        c = TestClient()\n        c.save({\"tool/conanfile.py\": GenConanfile(\"tool\", \"0.1\"),\n                \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_settings(\"build_type\")\n                                                              .with_tool_requires(\"tool/0.1\")})\n        c.run(\"create tool\")\n        c.run(f\"install pkg -g CMakeDeps -c tools.cmake.cmakedeps:new={new_value}\")\n        assert \"find_package(tool) # Optional. This is a tool-require, \" \\\n               \"can't link its targets\" in c.out\n        assert \"target_link_libraries\" not in c.out\n        tool_config = c.load(\"pkg/tool-config.cmake\")\n        assert 'set(tool_INCLUDE_DIRS' not in tool_config\n        assert 'set(tool_INCLUDE_DIR' not in tool_config\n        assert 'set(tool_LIBRARIES' not in tool_config\n\n    def test_libs_build_context(self):\n        c = TestClient()\n        c.run(\"new header_lib -d name=hello -d version=1.0 -o=hello\")\n        c.run(\"create hello -tf=\")\n        c.run(\"new cmake_lib -d name=bye -d version=1.0 -d requires=hello/1.0 -o=bye\")\n        # Ninja for same layout in all platforms\n        c.run(f\"install bye --build-require -c:a tools.cmake.cmakedeps:new={new_value} \"\n              f\"-c:a tools.cmake.cmaketoolchain:generator=Ninja\")\n        cmake = c.load(\"bye/build/Release/generators/hello-TargetsBuild-release.cmake\")\n        assert \"add_library(hello::hello INTERFACE IMPORTED)\" in cmake\n\n\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.parametrize(\"tool_requires\", [True, False])\ndef test_build_modules_custom_script(tool_requires):\n    \"\"\"\n    it works both as a tool_requires and as a regular requirement\n    \"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import copy\n\n        class Conan(ConanFile):\n            name = \"myfunctions\"\n            version = \"1.0\"\n            exports_sources = [\"*.cmake\"]\n\n            def package(self):\n                copy(self, \"*.cmake\", self.source_folder, self.package_folder)\n\n            def package_info(self):\n                self.cpp_info.set_property(\"cmake_build_modules\", [\"myfunction.cmake\"])\n        \"\"\")\n\n    myfunction = textwrap.dedent(\"\"\"\n        function(myfunction)\n            message(\"Hello myfunction!!!!\")\n        endfunction()\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile, \"myfunction.cmake\": myfunction})\n    client.run(\"create .\")\n\n    requires = \"tool_requires\" if tool_requires else \"requires\"\n    consumer = textwrap.dedent(f\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n\n        class Conan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"CMakeToolchain\", \"CMakeDeps\"\n            {requires} = \"myfunctions/1.0\"\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n        \"\"\")\n    cmakelists = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(test NONE)\n        find_package(myfunctions CONFIG REQUIRED)\n        myfunction()\n        \"\"\")\n    client.save({\"conanfile.py\": consumer,\n                 \"CMakeLists.txt\": cmakelists},\n                clean_first=True)\n    client.run(f\"build . -c tools.cmake.cmakedeps:new={new_value}\")\n    assert \"Hello myfunction!!!!\" in client.out\n\n\n@pytest.mark.tool(\"cmake\")\nclass TestProtobuf:\n\n    @pytest.fixture()\n    def protobuf(self):\n        conanfile = textwrap.dedent(r\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.cmake import CMake\n\n            class Protobuf(ConanFile):\n                name = \"protobuf\"\n                version = \"0.1\"\n                settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n                options = {\"shared\": [True, False]}\n                default_options = {\"shared\": False}\n\n                generators = \"CMakeToolchain\"\n                exports_sources = \"*\"\n\n                def build(self):\n                    cmake = CMake(self)\n                    cmake.configure()\n                    cmake.build()\n\n                def package(self):\n                    cmake = CMake(self)\n                    cmake.install()\n\n                def package_info(self):\n                    self.cpp_info.set_property(\"cmake_file_name\", \"MyProtobuf\")\n                    self.cpp_info.components[\"protobuf\"].libs = [\"protobuf\"]\n                    self.cpp_info.components[\"protoc\"].exe = \"protoc\"\n                    self.cpp_info.components[\"protoc\"].set_property(\"cmake_target_name\",\n                                                                    \"Protobuf::Protocompile\")\n                    self.cpp_info.components[\"protoc\"].location = os.path.join(\"bin\", \"protoc\")\n            \"\"\")\n        main = textwrap.dedent(\"\"\"\n            #include <iostream>\n            #include <fstream>\n            #include \"protobuf.h\"\n\n            int main() {\n                protobuf();\n                #ifdef NDEBUG\n                std::cout << \"Protoc RELEASE generating out.c!!!!!\" << std::endl;\n                #else\n                std::cout << \"Protoc DEBUG generating out.c!!!!!\" << std::endl;\n                #endif\n                std::ofstream f(\"out.c\");\n            }\n            \"\"\")\n        cmake = textwrap.dedent(\"\"\"\n            set(CMAKE_CXX_COMPILER_WORKS 1)\n            set(CMAKE_CXX_ABI_COMPILED 1)\n            cmake_minimum_required(VERSION 3.15)\n            project(protobuf CXX)\n\n            add_library(protobuf src/protobuf.cpp)\n            add_executable(protoc src/main.cpp)\n            target_link_libraries(protoc PRIVATE protobuf)\n            set_target_properties(protobuf PROPERTIES PUBLIC_HEADER \"src/protobuf.h\")\n\n            install(TARGETS protoc protobuf)\n            \"\"\")\n        c = TestClient()\n        c.save({\"conanfile.py\": conanfile,\n                \"CMakeLists.txt\": cmake,\n                \"src/protobuf.h\": gen_function_h(name=\"protobuf\"),\n                \"src/protobuf.cpp\": gen_function_cpp(name=\"protobuf\", includes=[\"protobuf\"]),\n                \"src/main.cpp\": main})\n        c.run(\"export .\")\n\n        consumer = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.cmake import CMake, cmake_layout\n            class Consumer(ConanFile):\n                settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n                requires = \"protobuf/0.1\"\n                generators = \"CMakeToolchain\", \"CMakeDeps\"\n\n                def layout(self):\n                    cmake_layout(self)\n                def build(self):\n                    cmake = CMake(self)\n                    cmake.configure()\n                    cmake.build()\n                    self.run(os.path.join(self.cpp.build.bindir, \"myapp\"))\n            \"\"\")\n        cmake = textwrap.dedent(\"\"\"\n            set(CMAKE_CXX_COMPILER_WORKS 1)\n            set(CMAKE_CXX_ABI_COMPILED 1)\n            cmake_minimum_required(VERSION 3.15)\n            project(consumer CXX)\n\n            find_package(MyProtobuf CONFIG REQUIRED)\n            add_custom_command(OUTPUT out.c COMMAND Protobuf::Protocompile)\n            add_executable(myapp myapp.cpp out.c)\n            target_link_libraries(myapp PRIVATE protobuf::protobuf)\n            get_target_property(imported_configs Protobuf::Protocompile IMPORTED_CONFIGURATIONS)\n            message(STATUS \"Protoc imported configurations: ${imported_configs}!!!\")\n            \"\"\")\n        myapp = textwrap.dedent(\"\"\"\n            #include <iostream>\n            #include \"protobuf.h\"\n\n            int main() {\n                protobuf();\n                std::cout << \"MyApp\" << std::endl;\n            }\n            \"\"\")\n        c.save({\"conanfile.py\": consumer,\n                \"CMakeLists.txt\": cmake,\n                \"myapp.cpp\": myapp}, clean_first=True)\n        return c\n\n    def test_requires(self, protobuf):\n        c = protobuf\n        c.run(f\"build . --build=missing -c tools.cmake.cmakedeps:new={new_value}\")\n        assert \"Conan: Target declared imported STATIC library 'protobuf::protobuf'\" in c.out\n        assert \"Conan: Target declared imported executable 'Protobuf::Protocompile'\" in c.out\n        assert \"Protoc RELEASE generating out.c!!!!!\" in c.out\n        assert 'Protoc imported configurations: RELEASE!!!' in c.out\n\n    def test_both(self, protobuf):\n        consumer = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.cmake import CMake, cmake_layout\n            class Consumer(ConanFile):\n                settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n                requires = \"protobuf/0.1\"\n                tool_requires = \"protobuf/0.1\"\n                generators = \"CMakeToolchain\", \"CMakeDeps\"\n\n                def layout(self):\n                    cmake_layout(self)\n                def build(self):\n                    cmake = CMake(self)\n                    cmake.configure()\n                    cmake.build()\n            \"\"\")\n        c = protobuf\n        c.save({\"conanfile.py\": consumer})\n        c.run(\"build . -s:h build_type=Debug --build=missing \"\n              f\"-c tools.cmake.cmakedeps:new={new_value}\")\n\n        assert \"Conan: Target declared imported STATIC library 'protobuf::protobuf'\" in c.out\n        assert \"Conan: Target declared imported executable 'Protobuf::Protocompile'\" in c.out\n        assert \"Protoc RELEASE generating out.c!!!!!\" in c.out\n        assert \"protobuf: Release!\" in c.out\n        assert \"protobuf: Debug!\" not in c.out\n        assert 'Protoc imported configurations: RELEASE!!!' in c.out\n\n        cmd = \"./build/Debug/myapp\" if platform.system() != \"Windows\" else r\"build\\Debug\\myapp\"\n        c.run_command(cmd)\n        assert \"protobuf: Debug!\" in c.out\n        assert \"protobuf: Release!\" not in c.out\n\n        c.run(\"build . --build=missing \"\n              f\"-c tools.cmake.cmakedeps:new={new_value}\")\n\n        assert \"Conan: Target declared imported STATIC library 'protobuf::protobuf'\" in c.out\n        assert \"Conan: Target declared imported executable 'Protobuf::Protocompile'\" in c.out\n        assert \"Protoc RELEASE generating out.c!!!!!\" in c.out\n        assert \"protobuf: Release!\" in c.out\n        assert \"protobuf: Debug!\" not in c.out\n        assert 'Protoc imported configurations: RELEASE!!!' in c.out\n\n        cmd = \"./build/Release/myapp\" if platform.system() != \"Windows\" else r\"build\\Release\\myapp\"\n        c.run_command(cmd)\n        assert \"protobuf: Debug!\" not in c.out\n        assert \"protobuf: Release!\" in c.out\n\n\n@pytest.mark.tool(\"cmake\", \"3.27\")\nclass TestConfigs:\n    @pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Only MSVC multi-conf\")\n    def test_multi_config(self, matrix_client):\n        c = matrix_client\n        c.run(\"new cmake_exe -d name=app -d version=0.1 -d requires=matrix/1.0\")\n        c.run(f\"install . -c tools.cmake.cmakedeps:new={new_value}\")\n        c.run(\"install . -s build_type=Debug --build=missing \"\n              f\"-c tools.cmake.cmakedeps:new={new_value}\")\n\n        c.run_command(\"cmake --preset conan-default\")\n        c.run_command(\"cmake --build --preset conan-release\")\n        c.run_command(\"cmake --build --preset conan-debug\")\n\n        c.run_command(\"build\\\\Release\\\\app\")\n        assert \"matrix/1.0: Hello World Release!\" in c.out\n        assert \"app/0.1: Hello World Release!\" in c.out\n        c.run_command(\"build\\\\Debug\\\\app\")\n        assert \"matrix/1.0: Hello World Debug!\" in c.out\n        assert \"app/0.1: Hello World Debug!\" in c.out\n\n    def test_cross_config(self, matrix_client):\n        # Release dependencies, but compiling app in Debug\n        c = matrix_client\n        c.run(\"new cmake_exe -d name=app -d version=0.1 -d requires=matrix/1.0\")\n        c.run(f\"install . -s &:build_type=Debug -c tools.cmake.cmakedeps:new={new_value}\")\n\n        # With modern CMake > 3.26 not necessary set(CMAKE_MAP_IMPORTED_CONFIG_DEBUG Release)\n        cmake = textwrap.dedent(\"\"\"\n            set(CMAKE_CXX_COMPILER_WORKS 1)\n            set(CMAKE_CXX_ABI_COMPILED 1)\n            cmake_minimum_required(VERSION 3.27)\n            project(app CXX)\n            # set(CMAKE_MAP_IMPORTED_CONFIG_DEBUG Release)\n            find_package(matrix CONFIG REQUIRED)\n\n            add_executable(app src/app.cpp src/main.cpp)\n            target_link_libraries(app PRIVATE matrix::matrix)\n            \"\"\")\n        c.save({\"CMakeLists.txt\": cmake})\n\n        preset = \"conan-default\" if platform.system() == \"Windows\" else \"conan-debug\"\n        c.run_command(f\"cmake --preset {preset}\")\n        c.run_command(\"cmake --build --preset conan-debug\")\n\n        c.run_command(os.path.join(\"build\", \"Debug\", \"app\"))\n        assert \"matrix/1.0: Hello World Release!\" in c.out\n        assert \"app/0.1: Hello World Debug!\" in c.out\n\n    def test_cross_config_components(self, matrix_client_components):\n        # Release dependencies, but compiling app in Debug\n        c = matrix_client_components\n        c.run(\"new cmake_exe -d name=app -d version=0.1 -d requires=matrix/1.0\")\n        app_cpp = textwrap.dedent(\"\"\"\n            #include \"app.h\"\n            #include \"module.h\"\n            void app(){\n               module();\n            }\"\"\")\n        c.save({\"src/app.cpp\": app_cpp,\n                \"src/main.cpp\": gen_function_cpp(name=\"main\", includes=[\"app\"], calls=[\"app\"])})\n\n        c.run(f\"install . -s &:build_type=Debug -c tools.cmake.cmakedeps:new={new_value}\")\n        # With modern CMake > 3.26 not necessary set(CMAKE_MAP_IMPORTED_CONFIG_DEBUG Release)\n        cmake = textwrap.dedent(\"\"\"\n            set(CMAKE_CXX_COMPILER_WORKS 1)\n            set(CMAKE_CXX_ABI_COMPILED 1)\n            cmake_minimum_required(VERSION 3.27)\n            project(app CXX)\n            # set(CMAKE_MAP_IMPORTED_CONFIG_DEBUG Release)\n            find_package(matrix CONFIG REQUIRED)\n\n            add_executable(app src/app.cpp src/main.cpp)\n            target_link_libraries(app PRIVATE matrix::matrix)\n            \"\"\")\n        c.save({\"CMakeLists.txt\": cmake})\n\n        preset = \"conan-default\" if platform.system() == \"Windows\" else \"conan-debug\"\n        c.run_command(f\"cmake --preset {preset}\")\n        c.run_command(\"cmake --build --preset conan-debug\")\n\n        c.run_command(os.path.join(\"build\", \"Debug\", \"app\"))\n        assert \"main: Debug!\" in c.out\n        assert \"module: Release!\" in c.out\n        assert \"vector: Release!\" in c.out\n\n    @pytest.mark.skipif(platform.system() == \"Windows\", reason=\"This doesn't work in MSVC\")\n    def test_cross_config_implicit(self, matrix_client):\n        # Release dependencies, but compiling app in Debug, without specifying it\n        c = matrix_client\n        c.run(\"new cmake_exe -d name=app -d version=0.1 -d requires=matrix/1.0\")\n        c.run(f\"install . -c tools.cmake.cmakedeps:new={new_value}\")\n\n        # With modern CMake > 3.26 not necessary set(CMAKE_MAP_IMPORTED_CONFIG_DEBUG Release)\n        cmake = textwrap.dedent(\"\"\"\n            set(CMAKE_CXX_COMPILER_WORKS 1)\n            set(CMAKE_CXX_ABI_COMPILED 1)\n            cmake_minimum_required(VERSION 3.27)\n            project(app CXX)\n            # set(CMAKE_MAP_IMPORTED_CONFIG_DEBUG Release)\n            find_package(matrix CONFIG REQUIRED)\n\n            add_executable(app src/app.cpp src/main.cpp)\n            target_link_libraries(app PRIVATE matrix::matrix)\n            \"\"\")\n\n        c.save({\"CMakeLists.txt\": cmake})\n        # Now we can force the Debug build, even if dependencies are Release\n        c.run_command(\"cmake . -DCMAKE_BUILD_TYPE=Debug -B build \"\n                      \"-DCMAKE_PREFIX_PATH=build/Release/generators\")\n        c.run_command(\"cmake --build build\")\n        c.run_command(\"./build/app\")\n        assert \"matrix/1.0: Hello World Release!\" in c.out\n        assert \"app/0.1: Hello World Debug!\" in c.out\n\n\n@pytest.mark.tool(\"cmake\", \"3.23\")\nclass TestCMakeTry:\n\n    def test_check_c_source_compiles(self, matrix_client):\n        \"\"\"\n        https://github.com/conan-io/conan/issues/12012\n        \"\"\"\n        c = matrix_client  # it brings the \"matrix\" package dependency pre-built\n\n        consumer = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.cmake import CMakeDeps\n            class PkgConan(ConanFile):\n                settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n                requires = \"matrix/1.0\"\n                generators = \"CMakeToolchain\",\n                def generate(self):\n                    deps = CMakeDeps(self)\n                    deps.set_property(\"matrix\", \"cmake_additional_variables_prefixes\", [\"MyMatrix\"])\n                    deps.generate()\n            \"\"\")\n\n        cmakelist = textwrap.dedent(\"\"\"\\\n            set(CMAKE_CXX_COMPILER_WORKS 1)\n            set(CMAKE_CXX_ABI_COMPILED 1)\n            cmake_minimum_required(VERSION 3.15)\n            project(Hello LANGUAGES CXX)\n\n            find_package(matrix CONFIG REQUIRED)\n            include(CheckCXXSourceCompiles)\n\n            set(CMAKE_REQUIRED_INCLUDES ${MyMatrix_INCLUDE_DIRS})\n            set(CMAKE_REQUIRED_LIBRARIES ${MyMatrix_LIBRARIES})\n            check_cxx_source_compiles(\"#include <matrix.h>\n                                      int main(void) { matrix();return 0; }\" IT_COMPILES)\n            \"\"\")\n\n        c.save({\"conanfile.py\": consumer,\n                \"CMakeLists.txt\": cmakelist}, clean_first=True)\n        c.run(f\"install . -c tools.cmake.cmakedeps:new={new_value}\")\n\n        preset = \"conan-default\" if platform.system() == \"Windows\" else \"conan-release\"\n        c.run_command(f\"cmake --preset {preset} \")\n        assert \"Performing Test IT_COMPILES - Success\" in c.out\n\n\nclass TestCMakeComponents:\n\n    @pytest.mark.tool(\"cmake\")\n    @pytest.mark.parametrize(\"components, found\", [(\"comp1\", True), (\"compX\", False)])\n    def test_components(self, components, found):\n        c = TestClient()\n        dep = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                name = \"dep\"\n                version = \"0.1\"\n                def package_info(self):\n                    self.cpp_info.set_property(\"cmake_components\", [\"comp1\", \"comp2\"])\n            \"\"\")\n        c.save({\"conanfile.py\": dep})\n        c.run(\"create .\")\n\n        consumer = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.cmake import CMake\n            class PkgConan(ConanFile):\n                settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n                requires = \"dep/0.1\"\n                generators = \"CMakeToolchain\", \"CMakeDeps\"\n                def build(self):\n                    deps = CMake(self)\n                    deps.configure()\n            \"\"\")\n\n        cmakelist = textwrap.dedent(f\"\"\"\\\n            cmake_minimum_required(VERSION 3.15)\n            project(Hello LANGUAGES NONE)\n\n            find_package(dep CONFIG REQUIRED COMPONENTS {components})\n            \"\"\")\n\n        c.save({\"conanfile.py\": consumer,\n                \"CMakeLists.txt\": cmakelist}, clean_first=True)\n        c.run(f\"build . -c tools.cmake.cmakedeps:new={new_value}\", assert_error=not found)\n        if not found:\n            assert f\"Conan: Error: 'dep' required COMPONENT '{components}' not found\" in c.out\n\n    def test_components_default_definition(self):\n        c = TestClient()\n        dep = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                name = \"dep\"\n                version = \"0.1\"\n                def package_info(self):\n                    # private component that should be skipped\n                    self.cpp_info.components[\"_private\"].includedirs = [\"include\"]\n                    self.cpp_info.components[\"c1\"].set_property(\"cmake_target_name\", \"MyC1\")\n                    self.cpp_info.components[\"c2\"].set_property(\"cmake_target_name\", \"Dep::MyC2\")\n                    self.cpp_info.components[\"c3\"].includedirs = [\"include\"]\n            \"\"\")\n        c.save({\"conanfile.py\": dep})\n        c.run(\"create .\")\n        c.run(f\"install --requires=dep/0.1 -g CMakeDeps -c tools.cmake.cmakedeps:new={new_value}\")\n        cmake = c.load(\"dep-config.cmake\")\n        assert 'set(dep_PACKAGE_PROVIDED_COMPONENTS MyC1 MyC2 c3)' in cmake\n\n    def test_components_individual_names(self):\n        c = TestClient()\n        dep = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                name = \"dep\"\n                version = \"0.1\"\n                def package_info(self):\n                    self.cpp_info.components[\"c1\"].set_property(\"cmake_target_name\", \"MyC1\")\n                    self.cpp_info.components[\"c1\"].set_property(\"cmake_components\", [\"MyCompC1\"])\n                    self.cpp_info.components[\"c2\"].set_property(\"cmake_target_name\", \"Dep::MyC2\")\n                    self.cpp_info.components[\"c3\"].includedirs = [\"include\"]\n            \"\"\")\n        c.save({\"conanfile.py\": dep})\n        c.run(\"create .\")\n        c.run(f\"install --requires=dep/0.1 -g CMakeDeps -c tools.cmake.cmakedeps:new={new_value}\")\n        cmake = c.load(\"dep-config.cmake\")\n        assert 'set(dep_PACKAGE_PROVIDED_COMPONENTS MyCompC1 MyC2 c3)' in cmake\n\n\nclass TestCppInfoChecks:\n    def test_check_exe_libs(self):\n        c = TestClient()\n        dep = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                name = \"dep\"\n                version = \"0.1\"\n                def package_info(self):\n                    self.cpp_info.libs = [\"mylib\"]\n                    self.cpp_info.exe = \"myexe\"\n            \"\"\")\n        c.save({\"conanfile.py\": dep})\n        c.run(\"create .\")\n        args = f\"-g CMakeDeps -c tools.cmake.cmakedeps:new={new_value}\"\n        c.run(f\"install --requires=dep/0.1 {args}\", assert_error=True)\n        assert \"Error in generator 'CMakeDeps': dep/0.1 \" 'cpp_info has both .exe and .libs' in c.out\n\n    def test_exe_no_location(self):\n        c = TestClient()\n        dep = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                name = \"dep\"\n                version = \"0.1\"\n                def package_info(self):\n                    self.cpp_info.exe = \"myexe\"\n            \"\"\")\n        c.save({\"conanfile.py\": dep})\n        c.run(\"create .\")\n        args = f\"-g CMakeDeps -c tools.cmake.cmakedeps:new={new_value}\"\n        c.run(f\"install --requires=dep/0.1 {args}\", assert_error=True)\n        assert \"Error in generator 'CMakeDeps': dep/0.1 cpp_info has .exe and no .location\" in c.out\n\n    def test_check_exe_wrong_type(self):\n        c = TestClient()\n        dep = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                name = \"dep\"\n                version = \"0.1\"\n                def package_info(self):\n                    self.cpp_info.type = \"shared-library\"\n                    self.cpp_info.exe = \"myexe\"\n            \"\"\")\n        c.save({\"conanfile.py\": dep})\n        c.run(\"create .\")\n        args = f\"-g CMakeDeps -c tools.cmake.cmakedeps:new={new_value}\"\n        c.run(f\"install --requires=dep/0.1 {args}\", assert_error=True)\n        assert \"dep/0.1 cpp_info incorrect .type shared-library for .exe myexe\" in c.out\n\n\ndef test_multiple_find_package_subfolder():\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    class TestPackage(ConanFile):\n        name = \"matrix\"\n        version = \"1.0\"\n        def package_info(self):\n            self.cpp_info.system_libs = [\"mysystemlib\"]\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"create .\")\n\n    cmake = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(app NONE)\n\n        find_package(matrix CONFIG REQUIRED)\n        add_subdirectory(subdir)\n        \"\"\")\n    subcmake = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(subdir NONE)\n\n        find_package(matrix CONFIG REQUIRED)\n        \"\"\")\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n        class Pkg(ConanFile):\n            requires = \"matrix/1.0\"\n            generators = \"CMakeToolchain\", \"CMakeDeps\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile,\n            \"CMakeLists.txt\": cmake,\n            \"subdir/CMakeLists.txt\": subcmake}, clean_first=True)\n\n    c.run(f\"build . -c tools.cmake.cmakedeps:new={new_value}\")\n    assert \"find_package(matrix)\" in c.out\n    assert \"target_link_libraries(... matrix::matrix)\" in c.out\n    assert \"Conan: Target declared imported INTERFACE library 'matrix::matrix'\" in c.out\n\n\n@pytest.mark.tool(\"cmake\", \"3.27\")\ndef test_find_package_casing_non_fallback():\n    \"\"\" CMakeConfigDeps creates hello_DIR by default, but CMake looks for\n    the package name as given in find_package, so casing matters,\n    and it won't look for hello_DIR, but to HellO_DIR.\n\n    Note that this would work without the layout, because CMake would fallback\n    to find the lowercase hello-config.cmake file in the CMAKE_INSTALL_PREFIX,\n    which happens to be the same folder the generated config file ends up without the layout.\"\"\"\n    cmakelists = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(test NONE)\n\n        # As long as the package generates hello-config.cmake lowercase, it works\n        find_package(HellO REQUIRED)  # Casing!!!!!\n    \"\"\")\n    consumer = textwrap.dedent(\"\"\"\n       from conan import ConanFile\n       from conan.tools.cmake import CMake, cmake_layout\n       class Pkg(ConanFile):\n           requires = \"hello/1.0\"\n           generators = \"CMakeToolchain\", \"CMakeDeps\"\n           settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n           def layout(self):\n               cmake_layout(self)\n\n           def build(self):\n               cmake = CMake(self)\n               cmake.configure()\n       \"\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile(\"hello\", \"1.0\")})\n    client.run(f\"create .\")\n\n    client.save({\"conanfile.py\": consumer, \"CMakeLists.txt\": cmakelists})\n    client.run(f\"build . -c tools.cmake.cmakedeps:new={new_value}\", assert_error=True)\n    assert 'Could not find a package configuration file provided by \"HellO\"' in client.out\n\n\n@pytest.mark.tool(\"cmake\", \"3.27\")\ndef test_find_package_extra_variants():\n    \"\"\" Producers can now specify extra casing names for find_package.\n    If a consumer uses yet a different casing,\n    it should directly change the cmake_file_name property instead.\"\"\"\n    cmakelists = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(test NONE)\n\n        # As long as the package generates hello-config.cmake lowercase, it works\n        find_package(HellO REQUIRED)  # Casing!!!!!\n\n        if (HellO_FOUND)\n            message(STATUS \"Found HellO!\")\n        endif()\n        if (hello_FOUND)\n            message(STATUS \"Found hello!\")\n        endif()\n    \"\"\")\n    consumer = textwrap.dedent(\"\"\"\n       from conan import ConanFile\n       from conan.tools.cmake import CMake, cmake_layout\n       class Pkg(ConanFile):\n           requires = \"hello/1.0\"\n           generators = \"CMakeToolchain\", \"CMakeConfigDeps\"\n           settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n           def layout(self):\n               cmake_layout(self)\n\n           def build(self):\n               cmake = CMake(self)\n               cmake.configure()\n       \"\"\")\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n\n    class HelloConan(ConanFile):\n        name = \"hello\"\n        version = \"1.0\"\n\n        def package_info(self):\n            self.cpp_info.set_property(\"cmake_file_name_variants\", [\"HellO\"])\n    \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create\")\n\n    client.save({\"conanfile.py\": consumer, \"CMakeLists.txt\": cmakelists})\n    client.run(\"build\")\n    assert 'Conan: Configuring Targets for hello/1.0' in client.out\n    # And this follows the expected found variable generation\n    assert \"Found HellO!\" in client.out\n    assert \"Found hello!\" not in client.out\n"
  },
  {
    "path": "test/functional/toolchains/cmake/cmakeconfigdeps/test_cmakeconfigdeps_new_cpp_linkage.py",
    "content": "import platform\nimport textwrap\nimport pytest\n\nfrom conan.test.assets.sources import gen_function_c, gen_function_h\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_cxx_only_project_links_c_library():\n    \"\"\"\n    When the consumer enables only CXX (project(myapp CXX)), the generated CMake config\n    must not SEND_ERROR for a dependency with C linkage. CXX implies C linkage support,\n    so the template adds \"C\" to the enabled languages check when \"CXX\" is present.\n    \"\"\"\n    c = TestClient()\n    # C library package: builds a static C lib, declares languages = \"C\" so link_languages = [\"C\"]\n    hello_c = gen_function_c(name=\"hello\")\n    hello_h = gen_function_h(name=\"hello\")\n    hello_cmake = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(hello C)\n        add_library(hello STATIC src/hello.c)\n        target_include_directories(hello PUBLIC\n          $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>\n          $<INSTALL_INTERFACE:include>)\n        install(TARGETS hello\n          ARCHIVE DESTINATION lib\n          INCLUDES DESTINATION include)\n        install(FILES include/hello.h DESTINATION include)\n        \"\"\")\n    hello_conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake, cmake_layout\n\n        class Clib(ConanFile):\n            name = \"hello\"\n            version = \"0.1\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            package_type = \"static-library\"\n            generators = \"CMakeToolchain\"\n            exports_sources = \"CMakeLists.txt\", \"src/*\", \"include/*\"\n            languages = \"C\"\n\n            def layout(self):\n                cmake_layout(self)\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n\n            def package(self):\n                cmake = CMake(self)\n                cmake.install()\n\n            def package_info(self):\n                self.cpp_info.libs = [\"hello\"]\n        \"\"\")\n    c.save({\n        \"hello/conanfile.py\": hello_conanfile,\n        \"hello/CMakeLists.txt\": hello_cmake,\n        \"hello/src/hello.c\": hello_c,\n        \"hello/include/hello.h\": hello_h,\n    })\n    c.run(\"create hello\")\n\n    # Consumer: project(CXX) only - no C in project(). Links to C library.\n    consumer_cmake = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(myapp CXX)\n\n        find_package(hello CONFIG REQUIRED)\n\n        add_executable(app main.cpp)\n        target_link_libraries(app PRIVATE hello::hello)\n        \"\"\")\n    main_cpp = textwrap.dedent(\"\"\"\n        extern \"C\" {\n            #include \"hello.h\"\n        }\n        int main() {\n            hello();\n        }\n        \"\"\")\n    consumer_conanfile = textwrap.dedent(\"\"\"\\\n        import os\n        from conan import ConanFile\n        from conan.tools.cmake import CMake, cmake_layout\n\n        class Recipe(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            package_type = \"application\"\n            generators = \"CMakeToolchain\", \"CMakeConfigDeps\"\n            requires = \"hello/0.1\"\n\n            def layout(self):\n                cmake_layout(self)\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n                self.run(os.path.join(self.cpp.build.bindir, \"app\"), env=\"conanrun\")\n        \"\"\")\n    c.save({\n        \"consumer/conanfile.py\": consumer_conanfile,\n        \"consumer/CMakeLists.txt\": consumer_cmake,\n        \"consumer/main.cpp\": main_cpp,\n    })\n    c.run(\"build consumer\")\n\n    # If the fix were missing, CMake configure would SEND_ERROR: \"Target hello::hello has C\n    # linkage but C not enabled in project()\". So reaching here and running the app proves the fix.\n    assert \"hello: Release!\" in c.out\n\n\n@pytest.mark.skipif(platform.system() == \"Windows\", reason=\"Windows doesn't fail to link\")\ndef test_auto_cppstd(matrix_c_interface_client):\n    c = matrix_c_interface_client\n    # IMPORTANT: This must be a C and CXX CMake project!!\n    consumer = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(myapp C CXX)\n\n        find_package(matrix REQUIRED)\n\n        add_executable(app app.c)\n        target_link_libraries(app PRIVATE matrix::matrix)\n        \"\"\")\n\n    conanfile = textwrap.dedent(\"\"\"\\\n        import os\n        from conan import ConanFile\n        from conan.tools.cmake import CMake, cmake_layout\n\n        class Recipe(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            package_type = \"application\"\n            generators = \"CMakeToolchain\", \"CMakeConfigDeps\"\n            requires = \"matrix/0.1\"\n\n            def layout(self):\n                cmake_layout(self)\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n                self.run(os.path.join(self.cpp.build.bindir, \"app\"), env=\"conanrun\")\n        \"\"\")\n    app = textwrap.dedent(\"\"\"\n        #include \"matrix.h\"\n        int main(){\n            matrix();\n            return 0;\n        }\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile,\n            \"CMakeLists.txt\": consumer,\n            \"app.c\": app}, clean_first=True)\n    c.run(f\"build .\")\n    assert \"Hello Matrix!\" in c.out\n"
  },
  {
    "path": "test/functional/toolchains/cmake/cmakeconfigdeps/test_cmakeconfigdeps_new_paths.py",
    "content": "import re\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\nnew_value = \"will_break_next\"\n\n\n@pytest.fixture\ndef client():\n    c = TestClient()\n    pkg = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake, cmake_layout\n        import os\n        class Pkg(ConanFile):\n            settings = \"build_type\", \"os\", \"arch\", \"compiler\"\n            requires = \"dep/0.1\"\n            generators = \"CMakeDeps\", \"CMakeToolchain\"\n            def layout(self):  # Necessary to force config files in another location\n                cmake_layout(self)\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure(variables={\"CMAKE_FIND_DEBUG_MODE\": \"ON\"})\n       \"\"\")\n    cmake = textwrap.dedent(\"\"\"\n       cmake_minimum_required(VERSION 3.15)\n       project(pkgb LANGUAGES NONE)\n       find_package(dep CONFIG REQUIRED)\n       \"\"\")\n    c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\"),\n            \"pkg/conanfile.py\": pkg,\n            \"pkg/CMakeLists.txt\": cmake})\n    return c\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_cmake_generated(client):\n    c = client\n    c.run(\"create dep\")\n    c.run(f\"build pkg -c tools.cmake.cmakedeps:new={new_value}\")\n    assert \"Conan toolchain: Including CMakeDeps generated conan_cmakedeps_paths.cmake\" in c.out\n    assert \"Conan: Target declared imported INTERFACE library 'dep::dep'\" in c.out\n\n\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.parametrize(\"lowercase\", [False, True])\ndef test_cmake_in_package(client, lowercase):\n    c = client\n    # same, but in-package\n    f = \"dep-config\" if lowercase else \"depConfig\"\n    dep = textwrap.dedent(f\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import save\n        class Pkg(ConanFile):\n            name = \"dep\"\n            version = \"0.1\"\n\n            def package(self):\n                content = 'message(STATUS \"Hello from dep dep-Config.cmake!!!!!\")'\n                save(self, os.path.join(self.package_folder, \"cmake\", \"{f}.cmake\"), content)\n            def package_info(self):\n                self.cpp_info.set_property(\"cmake_find_mode\", \"none\")\n                self.cpp_info.builddirs = [\"cmake\"]\n        \"\"\")\n\n    c.save({\"dep/conanfile.py\": dep})\n    c.run(\"create dep\")\n    c.run(f\"build pkg -c tools.cmake.cmakedeps:new={new_value}\")\n    assert \"Conan toolchain: Including CMakeDeps generated conan_cmakedeps_paths.cmake\" in c.out\n    assert \"Hello from dep dep-Config.cmake!!!!!\" in c.out\n\n\nclass TestRuntimeDirs:\n\n    def test_runtime_lib_dirs_multiconf(self):\n        client = TestClient()\n        app = GenConanfile().with_requires(\"dep/1.0\").with_generator(\"CMakeDeps\")\\\n            .with_settings(\"build_type\")\n        client.save({\"lib/conanfile.py\": GenConanfile(),\n                     \"dep/conanfile.py\": GenConanfile(\"dep\").with_requires(\"onelib/1.0\",\n                                                                           \"twolib/1.0\"),\n                     \"app/conanfile.py\": app})\n        client.run(\"create lib --name=onelib --version=1.0\")\n        client.run(\"create lib --name=twolib --version=1.0\")\n        client.run(\"create dep  --version=1.0\")\n\n        client.run(f'install app -s build_type=Release -c tools.cmake.cmakedeps:new={new_value}')\n        client.run(f'install app -s build_type=Debug -c tools.cmake.cmakedeps:new={new_value}')\n\n        contents = client.load(\"app/conan_cmakedeps_paths.cmake\")\n        pattern_lib_dirs = r\"set\\(CONAN_RUNTIME_LIB_DIRS ([^)]*)\\)\"\n        runtime_lib_dirs = re.search(pattern_lib_dirs, contents).group(1)\n        assert \"<CONFIG:Release>\" in runtime_lib_dirs\n        assert \"<CONFIG:Debug>\" in runtime_lib_dirs\n        # too simple of a check, but this is impossible to test automatically\n        assert \"set(CMAKE_VS_DEBUGGER_ENVIRONMENT\" in contents\n\n\n@pytest.mark.tool(\"cmake\")\nclass TestCMakeDepsPaths:\n\n    @pytest.mark.parametrize(\"requires, tool_requires\", [(True, False), (False, True), (True, True)])\n    def test_find_program_path(self, requires, tool_requires):\n        \"\"\"Test that executables in bindirs of tool_requires can be found with\n        find_program() in consumer CMakeLists.\n        \"\"\"\n        c = TestClient()\n\n        conanfile = textwrap.dedent(\"\"\"\n            import os\n            from conan.tools.files import copy\n            from conan import ConanFile\n            class TestConan(ConanFile):\n                name = \"tool\"\n                version = \"1.0\"\n                exports_sources = \"*\"\n                def package(self):\n                    copy(self, \"*\", self.source_folder, os.path.join(self.package_folder, \"bin\"))\n        \"\"\")\n        c.save({\"conanfile.py\": conanfile, \"hello\": \"\", \"hello.exe\": \"\"})\n        c.run(\"create .\")\n\n        requires = 'requires = \"tool/1.0\"' if requires else \"\"\n        tool_requires = 'tool_requires = \"tool/1.0\"' if tool_requires else \"\"\n        conanfile = textwrap.dedent(f\"\"\"\n            from conan import ConanFile\n            from conan.tools.cmake import CMake\n            class PkgConan(ConanFile):\n                {requires}\n                {tool_requires}\n                settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n                generators = \"CMakeToolchain\", \"CMakeDeps\"\n                def build(self):\n                    cmake = CMake(self)\n                    cmake.configure()\n        \"\"\")\n        consumer = textwrap.dedent(\"\"\"\n            cmake_minimum_required(VERSION 3.15)\n            project(MyHello NONE)\n            find_program(HELLOPROG hello)\n            if(HELLOPROG)\n                message(STATUS \"Found hello prog: ${HELLOPROG}\")\n            endif()\n        \"\"\")\n        c.save({\"conanfile.py\": conanfile, \"CMakeLists.txt\": consumer}, clean_first=True)\n        c.run(f\"build . -c tools.cmake.cmakedeps:new={new_value}\")\n        assert \"Found hello prog\" in c.out\n        if requires and tool_requires:\n            assert \"There is already a 'tool/1.0' package contributing to CMAKE_PROGRAM_PATH\" in c.out\n\n    def test_find_include_and_lib_paths(self):\n        c = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            import os\n            from conan.tools.files import copy\n            from conan import ConanFile\n            class TestConan(ConanFile):\n                name = \"hello\"\n                version = \"1.0\"\n                exports_sources = \"*\"\n                def package(self):\n                    copy(self, \"*.h\", self.source_folder, os.path.join(self.package_folder, \"include\"))\n                    copy(self, \"*.lib\", self.source_folder, os.path.join(self.package_folder, \"lib\"))\n                    copy(self, \"*.a\", self.source_folder, os.path.join(self.package_folder, \"lib\"))\n                    copy(self, \"*.so\", self.source_folder, os.path.join(self.package_folder, \"lib\"))\n                    copy(self, \"*.dll\", self.source_folder, os.path.join(self.package_folder, \"lib\"))\n        \"\"\")\n        c.save({\"conanfile.py\": conanfile,\n                \"hello.h\": \"\", \"hello.lib\": \"\", \"libhello.a\": \"\",\n                \"libhello.so\": \"\", \"libhello.dll\": \"\"})\n        c.run(\"create .\")\n        conanfile = textwrap.dedent(f\"\"\"\n            from conan import ConanFile\n            from conan.tools.cmake import CMake\n            class PkgConan(ConanFile):\n                requires = \"hello/1.0\"\n                settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n                generators = \"CMakeToolchain\", \"CMakeDeps\"\n                def build(self):\n                    cmake = CMake(self)\n                    cmake.configure()\n        \"\"\")\n        consumer = textwrap.dedent(\"\"\"\n            cmake_minimum_required(VERSION 3.15)\n            project(MyHello NONE)\n            find_file(HELLOINC hello.h)\n            find_library(HELLOLIB hello)\n            if(HELLOINC)\n                message(STATUS \"Found hello header: ${HELLOINC}\")\n            endif()\n            if(HELLOLIB)\n                message(STATUS \"Found hello lib: ${HELLOLIB}\")\n            endif()\n        \"\"\")\n        c.save({\"conanfile.py\": conanfile, \"CMakeLists.txt\": consumer}, clean_first=True)\n        c.run(f\"build . -c tools.cmake.cmakedeps:new={new_value}\")\n        assert \"Found hello header\" in c.out\n        assert \"Found hello lib\" in c.out\n\n    @pytest.mark.parametrize(\"require_type\", [\"requires\", \"tool_requires\"])\n    def test_include_modules(self, require_type):\n        \"\"\"Test that cmake module files in builddirs of requires and tool_requires\n        are accessible with include() in consumer CMakeLists\n        \"\"\"\n        c = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import copy\n            class TestConan(ConanFile):\n                exports_sources = \"*\"\n                def package(self):\n                    copy(self, \"*\", self.source_folder, self.package_folder)\n                def package_info(self):\n                    self.cpp_info.builddirs.append(\"cmake\")\n        \"\"\")\n        c.save({\"conanfile.py\": conanfile,\n                \"cmake/myowncmake.cmake\": 'MESSAGE(\"MYOWNCMAKE FROM hello!\")'})\n        c.run(\"create . --name=hello --version=0.1\")\n\n        conanfile = textwrap.dedent(f\"\"\"\n            from conan import ConanFile\n            from conan.tools.cmake import CMake\n            class PkgConan(ConanFile):\n                settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n                {require_type} = \"hello/0.1\"\n                generators = \"CMakeToolchain\", \"CMakeConfigDeps\"\n\n                def build(self):\n                    cmake = CMake(self)\n                    cmake.configure()\n                    cmake.build()\n            \"\"\")\n        consumer = textwrap.dedent(\"\"\"\n            cmake_minimum_required(VERSION 3.15)\n            project(MyHello NONE)\n            include(myowncmake)\n        \"\"\")\n        c.save({\"conanfile.py\": conanfile,\n                \"CMakeLists.txt\": consumer}, clean_first=True)\n        c.run(f\"build . -c tools.cmake.cmakedeps:new={new_value}\")\n        assert \"MYOWNCMAKE FROM hello!\" in c.out\n\n    def test_include_modules_both_build_host(self):\n        c = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import copy\n            class TestConan(ConanFile):\n                exports_sources = \"*\"\n                def package(self):\n                    copy(self, \"*\", self.source_folder, self.package_folder)\n                def package_info(self):\n                    self.cpp_info.builddirs.append(\"cmake\")\n            \"\"\")\n        c.save({\"conanfile.py\": conanfile,\n                \"cmake/myowncmake.cmake\": 'MESSAGE(\"MYOWNCMAKE FROM hello!\")'})\n        c.run(\"create . --name=hello --version=0.1\")\n\n        conanfile = textwrap.dedent(f\"\"\"\n            from conan import ConanFile\n            from conan.tools.cmake import CMake\n            class PkgConan(ConanFile):\n                settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n                requires = \"hello/0.1\"\n                tool_requires = \"hello/0.1\"\n                generators = \"CMakeToolchain\", \"CMakeConfigDeps\"\n\n                def build(self):\n                    cmake = CMake(self)\n                    cmake.configure()\n                    cmake.build()\n            \"\"\")\n        consumer = textwrap.dedent(\"\"\"\n            cmake_minimum_required(VERSION 3.15)\n            project(MyHello NONE)\n            include(myowncmake)\n            \"\"\")\n        c.save({\"conanfile.py\": conanfile,\n                \"CMakeLists.txt\": consumer}, clean_first=True)\n        c.run(f\"build . -c tools.cmake.cmakedeps:new={new_value}\")\n        assert \"conanfile.py: There is already a 'hello/0.1' package \" \\\n               \"contributing to CMAKE_MODULE_PATH\" in c.out\n        assert \"MYOWNCMAKE FROM hello!\" in c.out\n"
  },
  {
    "path": "test/functional/toolchains/cmake/cmakeconfigdeps/test_cmakeconfigdeps_sources.py",
    "content": "import os\nimport platform\nimport textwrap\n\nimport pytest\n\nfrom conan.tools.files import replace_in_file\nfrom conan.test.utils.mocks import ConanFileMock\n\nfrom conan.test.utils.tools import TestClient\n\nnew_value = \"will_break_next\"\n\n\n@pytest.mark.skipif(platform.system() != \"Linux\", reason=\"No OS specific test\")\n@pytest.mark.tool(\"cmake\")\ndef test_cpp_info_sources():\n    c = TestClient()\n    c.run(\"new cmake_lib -d name=hello -d version=1.0\")\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import copy\n\n        class HelloConan(ConanFile):\n            name = \"hello\"\n            version = \"1.0\"\n            exports_sources = \"src/*\", \"include/*\"\n            package_type = \"header-library\"\n\n            def package(self):\n                copy(self, \"*.h\", self.source_folder, self.package_folder)\n                copy(self, \"*.cpp\", self.source_folder, self.package_folder)\n\n            def package_info(self):\n                self.cpp_info.sources = [\"src/hello.cpp\"]\n    \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    # Check that the hello library builds in test_package\n    c.run(f\"create . -c tools.cmake.cmakedeps:new={new_value}\")\n    # Check content of the generated files\n    c.run(f\"install --requires=hello/1.0 -g=CMakeConfigDeps \"\n          f\"-c tools.cmake.cmakedeps:new={new_value}\")\n    cmake = c.load(\"hello-Targets-release.cmake\")\n    assert \"add_library(hello::hello INTERFACE IMPORTED)\" in cmake\n    assert \"set_property(TARGET hello::hello APPEND PROPERTY INTERFACE_SOURCES\\n\"\\\n           \"             $<$<CONFIG:RELEASE>:${hello_PACKAGE_FOLDER_RELEASE}/src/hello.cpp>)\" in cmake\n\n\n@pytest.mark.skipif(platform.system() != \"Linux\", reason=\"No OS specific test\")\n@pytest.mark.tool(\"cmake\")\ndef test_cpp_info_component_sources():\n    c = TestClient()\n    c.run(\"new cmake_lib -d name=hello -d version=1.0\")\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import copy\n\n        class HelloConan(ConanFile):\n            name = \"hello\"\n            version = \"1.0\"\n            exports_sources = \"src/*\", \"include/*\"\n            package_type = \"header-library\"\n\n            def package(self):\n                copy(self, \"*.h\", self.source_folder, self.package_folder)\n                copy(self, \"*.cpp\", self.source_folder, self.package_folder)\n\n            def package_info(self):\n                self.cpp_info.components[\"my_comp\"].sources = [\"src/hello.cpp\", \"src/other.cpp\"]\n    \"\"\")\n    c.save({\n        \"conanfile.py\": conanfile,\n        \"src/other.cpp\": \"\",\n    })\n\n    # Make test_package link with component's target\n    test_package_cmakelists_path = os.path.join(c.current_folder, \"test_package\", \"CMakeLists.txt\")\n    replace_in_file(ConanFileMock(), test_package_cmakelists_path, \"hello::hello\", \"hello::my_comp\")\n    test_package_cmakelists_content = c.load(test_package_cmakelists_path)\n    assert \"target_link_libraries(example hello::my_comp)\" in test_package_cmakelists_content\n    # Check that the hello library builds in test_package\n    c.run(f\"create . -c tools.cmake.cmakedeps:new={new_value}\")\n    # Check the content of the generated files\n    c.run(f\"install --requires=hello/1.0 -g=CMakeConfigDeps \"\n          f\"-c tools.cmake.cmakedeps:new={new_value}\")\n    cmake = c.load(\"hello-Targets-release.cmake\")\n    assert \"add_library(hello::hello INTERFACE IMPORTED)\" in cmake\n    assert \"add_library(hello::my_comp INTERFACE IMPORTED)\" in cmake\n    assert \"set_property(TARGET hello::my_comp APPEND PROPERTY INTERFACE_SOURCES\\n\"\\\n           \"             $<$<CONFIG:RELEASE>:${hello_PACKAGE_FOLDER_RELEASE}/src/hello.cpp\"\\\n           \" ${hello_PACKAGE_FOLDER_RELEASE}/src/other.cpp>)\" in cmake\n"
  },
  {
    "path": "test/functional/toolchains/cmake/cmakedeps/__init__.py",
    "content": ""
  },
  {
    "path": "test/functional/toolchains/cmake/cmakedeps/test_apple_frameworks.py",
    "content": "import platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.sources import gen_function_cpp\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.fixture\ndef client():\n    lib_conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class FooLib(ConanFile):\n            name = \"foolib\"\n            version = \"1.0\"\n\n            def package_info(self):\n                self.cpp_info.frameworks.extend(['Foundation', 'CoreServices', 'CoreFoundation'])\n    \"\"\")\n\n    t = TestClient()\n    t.save({'conanfile.py': lib_conanfile})\n    t.run(\"create .\")\n    return t\n\n\napp_conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    from conan.tools.cmake import CMake\n\n    class App(ConanFile):\n        requires = \"foolib/1.0\"\n        generators = \"CMakeDeps\", \"CMakeToolchain\"\n        settings = \"build_type\", \"os\", \"arch\"\n\n        def build(self):\n            cmake = CMake(self)\n            cmake.configure()\n\"\"\")\n\n\n# needs at least 3.23.3 because of error with \"empty identity\"\n# https://stackoverflow.com/questions/72746725/xcode-14-beta-cmake-not-able-to-resolve-cmake-c-compiler-and-cmake-cxx-compiler\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only OSX\")\n@pytest.mark.tool(\"cmake\", \"3.23\")\ndef test_apple_framework_xcode(client):\n    app_cmakelists = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(Testing NONE)\n        find_package(foolib REQUIRED)\n        message(\">>> foolib_FRAMEWORKS_FOUND_DEBUG: ${foolib_FRAMEWORKS_FOUND_DEBUG}\")\n        message(\">>> foolib_FRAMEWORKS_FOUND_RELEASE: ${foolib_FRAMEWORKS_FOUND_RELEASE}\")\n    \"\"\")\n\n    client.save({'conanfile.py': app_conanfile,\n                 'CMakeLists.txt': app_cmakelists})\n\n    client.run(\"build . -c tools.cmake.cmaketoolchain:generator=Xcode\")\n    assert \"/System/Library/Frameworks/Foundation.framework;\" in client.out\n    assert \"/System/Library/Frameworks/CoreServices.framework;\" in client.out\n    assert \"/System/Library/Frameworks/CoreFoundation.framework\" in client.out\n\n\nconanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.cmake import CMake, CMakeToolchain\n\n            class AppleframeworkConan(ConanFile):\n                settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n                generators = \"CMakeDeps\", \"CMakeToolchain\"\n                exports_sources = \"src/*\"\n                name = \"mylibrary\"\n                version = \"1.0\"\n\n                def layout(self):\n                    self.folders.source = \"src\"\n\n                def build(self):\n                    cmake = CMake(self)\n                    cmake.configure()\n                    cmake.build()\n                    cmake.install()\n                    self.run(\"otool -L '%s/hello.framework/hello'\" % self.build_folder)\n                    self.run(\"otool -L '%s/hello.framework/hello'\" % self.package_folder)\n\n                def package_info(self):\n                    self.cpp_info.frameworkdirs.append(self.package_folder)\n                    self.cpp_info.frameworks.append(\"hello\")\n                    self.cpp_info.includedirs = []\n            \"\"\")\ncmake = textwrap.dedent(\"\"\"\n            set(CMAKE_CXX_COMPILER_WORKS 1)\n            set(CMAKE_CXX_ABI_COMPILED 1)\n            cmake_minimum_required(VERSION 3.15)\n            project(MyHello CXX)\n\n            # set @rpaths for libraries to link against\n            SET(CMAKE_SKIP_RPATH FALSE)\n            #SET(CMAKE_SKIP_BUILD_RPATH  FALSE)\n            #SET(CMAKE_INSTALL_RPATH \"@rpath/\")\n            #SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)\n\n            add_library(hello SHARED hello.cpp hello.h)\n            set_target_properties(hello PROPERTIES\n              FRAMEWORK TRUE\n              FRAMEWORK_VERSION A\n              MACOSX_FRAMEWORK_IDENTIFIER com.cmake.hello\n              MACOSX_FRAMEWORK_INFO_PLIST src/Info.plist\n              # \"current version\" in semantic format in Mach-O binary file\n              VERSION 1.6.0\n              # \"compatibility version\" in semantic format in Mach-O binary file\n              SOVERSION 1.6.0\n              PUBLIC_HEADER hello.h\n              INSTALL_NAME_DIR \"@rpath\"\n              MACOSX_RPATH TRUE\n            )\n            install(TARGETS hello DESTINATION \".\")\n        \"\"\")\nhello_h = textwrap.dedent(\"\"\"\n            #pragma once\n\n            #ifdef WIN32\n              #define HELLO_EXPORT __declspec(dllexport)\n            #else\n              #define HELLO_EXPORT __attribute__((visibility(\"default\")))\n            #endif\n\n            #ifdef __cplusplus\n            extern \"C\" {\n            #endif\n            class HELLO_EXPORT Hello\n            {\n                public:\n                    static void hello();\n            };\n            #ifdef __cplusplus\n            }\n            #endif\n        \"\"\")\nhello_cpp = textwrap.dedent(\"\"\"\n            #include <iostream>\n            #include \"hello.h\"\n\n            void Hello::hello(){\n                #ifdef NDEBUG\n                std::cout << \"Hello World Release!\" <<std::endl;\n                #else\n                std::cout << \"Hello World Debug!\" <<std::endl;\n                #endif\n            }\n        \"\"\")\ninfoplist = textwrap.dedent(\"\"\"\n            <?xml version=\"1.0\" encoding=\"UTF-8\"?>\n            <!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\"\n                     \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n            <plist version=\"1.0\">\n            <dict>\n                <key>CFBundleDisplayName</key>\n                <string>hello</string>\n                <key>CFBundleExecutable</key>\n                <string>hello</string>\n                <key>CFBundleIdentifier</key>\n                <string>com.test.hello</string>\n                <key>CFBundleInfoDictionaryVersion</key>\n                <string>6.0</string>\n                <key>CFBundleName</key>\n                <string>hello</string>\n                <key>CFBundlePackageType</key>\n                <string>FMWK</string>\n                <key>CFBundleShortVersionString</key>\n                <string>1.6.0</string>\n                <key>CFBundleVersion</key>\n                <string>1.6.0</string>\n                <key>Flavor_ID</key>\n                <string>0</string>\n                <key>NSAppTransportSecurity</key>\n                <dict>\n                    <key>NSAllowsArbitraryLoads</key>\n                    <true/>\n                </dict>\n                <key>NSPrincipalClass</key>\n                <string></string>\n            </dict>\n            </plist>\n        \"\"\")\ntimer_cpp = textwrap.dedent(\"\"\"\n    #include <hello/hello.h>\n    int main(){\n        Hello::hello();\n    }\n    \"\"\")\n\n\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only OSX\")\n@pytest.mark.parametrize(\"settings\",\n                         ['',\n                          '-s os=iOS -s os.sdk=iphoneos -s os.version=10.0 -s arch=armv8',\n                          \"-s os=tvOS -s os.sdk=appletvos -s os.version=11.0 -s arch=armv8\"])\ndef test_apple_own_framework_cross_build(settings):\n    client = TestClient()\n\n    test_cmake = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.15)\n        project(Testing CXX)\n\n        find_package(mylibrary REQUIRED)\n\n        add_executable(timer timer.cpp)\n        target_link_libraries(timer mylibrary::mylibrary)\n    \"\"\")\n\n    test_conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.cmake import CMake, CMakeToolchain, CMakeDeps, cmake_layout\n        from conan.tools.build import cross_building\n\n        class TestPkg(ConanFile):\n            generators = \"CMakeToolchain\"\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n\n            def layout(self):\n                cmake_layout(self)\n\n            def requirements(self):\n                self.requires(self.tested_reference_str)\n                self.tool_requires(self.tested_reference_str)\n\n            def generate(self):\n                cmake = CMakeDeps(self)\n                cmake.build_context_activated = [\"mylibrary\"]\n                cmake.build_context_suffix = {\"mylibrary\": \"_BUILD\"}\n                cmake.generate()\n\n            def build(self):\n                self.output.warning(\"Building test package at: {}\".format(self.build_folder))\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n\n            def test(self):\n                if not cross_building(self):\n                    cmd = os.path.join(self.cpp.build.bindirs[0], \"timer\")\n                    self.run(cmd, env=\"conanrunenv\")\n        \"\"\")\n\n    client.save({'conanfile.py': conanfile,\n                 \"src/CMakeLists.txt\": cmake,\n                 \"src/hello.h\": hello_h,\n                 \"src/hello.cpp\": hello_cpp,\n                 \"src/Info.plist\": infoplist,\n                 \"test_package/conanfile.py\": test_conanfile,\n                 'test_package/CMakeLists.txt': test_cmake,\n                 \"test_package/timer.cpp\": timer_cpp})\n    # First build it as build_require in the build-context, no testing\n    # the UX could be improved, but the simplest could be:\n    #  - Have users 2 test_packages, one for the host and other for the build, with some naming\n    #    convention. CI launches one after the other if found\n    client.run(\"create . %s -tf=\\\"\\\" --build-require\" % settings)\n    client.run(\"create . %s\" % settings)\n    if not len(settings):\n        assert \"Hello World Release!\" in client.out\n\n\n@pytest.mark.xfail(reason=\"run_environment=True no longer works\")\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only OSX\")\n@pytest.mark.tool(\"cmake\", \"3.19\")\ndef test_apple_own_framework_cmake_deps():\n    client = TestClient()\n\n    test_cmake = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.15)\n        project(Testing CXX)\n        message(STATUS \"CMAKE_BINARY_DIR ${CMAKE_BINARY_DIR}\")\n        find_package(mylibrary REQUIRED)\n        message(\">>> MYLIBRARY_FRAMEWORKS_FOUND_DEBUG: ${MYLIBRARY_FRAMEWORKS_FOUND_DEBUG}\")\n        message(\">>> MYLIBRARY_FRAMEWORKS_FOUND_RELEASE: ${MYLIBRARY_FRAMEWORKS_FOUND_RELEASE}\")\n        add_executable(timer timer.cpp)\n        target_link_libraries(timer mylibrary::mylibrary)\n    \"\"\")\n\n    test_conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n\n        class TestPkg(ConanFile):\n            generators = \"CMakeToolchain\"\n            name = \"app\"\n            version = \"1.0\"\n            requires = \"mylibrary/1.0\"\n            exports_sources = \"CMakeLists.txt\", \"timer.cpp\"\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n\n            def requirements(self):\n                self.tool_requires(self.tested_reference_str)\n\n            def generate(self):\n                cmake = CMakeDeps(self)\n                cmake.build_context_activated = [\"mylibrary\"]\n                cmake.build_context_suffix = {\"mylibrary\": \"_BUILD\"}\n                cmake.generate()\n\n            def layout(self):\n                self.folders.build = str(self.settings.build_type)\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n\n            def test(self):\n                self.run(os.path.join(str(self.settings.build_type), \"timer\"), env=\"conanrunenv\")\n        \"\"\")\n    client.save({'conanfile.py': conanfile,\n                 \"src/CMakeLists.txt\": cmake,\n                 \"src/hello.h\": hello_h,\n                 \"src/hello.cpp\": hello_cpp,\n                 \"src/Info.plist\": infoplist})\n    client.run(\"export . --name=mylibrary --version=1.0\")\n    client.run(\"create . --name=mylibrary --version=1.0 -s build_type=Debug\")\n    client.run(\"create . --name=mylibrary --version=1.0 -s build_type=Release\")\n\n    profile = textwrap.dedent(\"\"\"\n        include(default)\n        [conf]\n        tools.cmake.cmaketoolchain:generator=Xcode\n        \"\"\")\n    client.save({\"conanfile.py\": test_conanfile,\n                 'CMakeLists.txt': test_cmake,\n                 \"timer.cpp\": timer_cpp,\n                 \"profile\": profile})\n\n    client.run(\"install . -s build_type=Debug -pr=profile\")\n    client.run(\"install . -s build_type=Release -pr=profile\")\n    client.run(\"test . mylibrary/1.0@  -pr=profile\")\n    assert \"Hello World Release!\" in client.out\n    client.run(\"test . mylibrary/1.0@ -s:b build_type=Debug  -pr=profile\")\n    assert \"Hello World Debug!\" in client.out\n\n\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only OSX\")\ndef test_apple_own_framework_cmake_find_package_multi():\n    client = TestClient()\n\n    test_cmake = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.15)\n        project(Testing CXX)\n        set(CMAKE_RUNTIME_OUTPUT_DIRECTORY \"${CMAKE_CURRENT_BINARY_DIR}/bin\")\n        set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG \"${CMAKE_CURRENT_BINARY_DIR}/bin\")\n        set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE \"${CMAKE_CURRENT_BINARY_DIR}/bin\")\n        find_package(mylibrary REQUIRED)\n        message(\">>> CONAN_FRAMEWORKS_FOUND_MYLIBRARY: ${CONAN_FRAMEWORKS_FOUND_MYLIBRARY}\")\n        add_executable(timer timer.cpp)\n        target_link_libraries(timer mylibrary::mylibrary)\n    \"\"\")\n\n    test_conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n        class TestPkg(ConanFile):\n            generators = \"CMakeDeps\", \"CMakeToolchain\"\n            settings = \"build_type\", \"os\", \"arch\"\n\n            def requirements(self):\n                self.requires(self.tested_reference_str)\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n            def test(self):\n                self.run(\"bin/timer\", env=\"conanrunenv\")\n        \"\"\")\n    client.save({'conanfile.py': conanfile,\n                 \"src/CMakeLists.txt\": cmake,\n                 \"src/hello.h\": hello_h,\n                 \"src/hello.cpp\": hello_cpp,\n                 \"src/Info.plist\": infoplist,\n                 \"test_package/conanfile.py\": test_conanfile,\n                 'test_package/CMakeLists.txt': test_cmake,\n                 \"test_package/timer.cpp\": timer_cpp})\n    client.run(\"create .\")\n    assert \"Hello World Release!\" in client.out\n\n\n@pytest.mark.tool(\"cmake\", \"3.19\")\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only OSX\")\ndef test_component_uses_apple_framework():\n    conanfile_py = textwrap.dedent(\"\"\"\nfrom conan import ConanFile, tools\nfrom conan.tools.cmake import CMake\n\n\nclass HelloConan(ConanFile):\n    name = \"hello\"\n    description = \"example\"\n    topics = (\"conan\",)\n    url = \"https://github.com/conan-io/conan-center-index\"\n    homepage = \"https://www.example.com\"\n    license = \"MIT\"\n    exports_sources = [\"hello.cpp\", \"hello.h\", \"CMakeLists.txt\"]\n    generators = \"CMakeDeps\", \"CMakeToolchain\"\n    settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n\n    def build(self):\n        cmake = CMake(self)\n        cmake.configure()\n        cmake.build()\n        cmake.install()\n\n    def package_info(self):\n        self.cpp_info.set_property(\"cmake_file_name\", \"HELLO\")\n        self.cpp_info.components[\"libhello\"].set_property(\"cmake_target_name\", \"hello::libhello\")\n        self.cpp_info.components[\"libhello\"].libs = [\"hello\"]\n        # We need to add the information about the lib/include directories to be able to find them\n        self.cpp_info.components[\"libhello\"].libdirs = [\"lib\"]\n        self.cpp_info.components[\"libhello\"].includedirs = [\"include\"]\n\n        self.cpp_info.components[\"libhello\"].frameworks.extend([\"CoreFoundation\"])\n        \"\"\")\n    hello_cpp_core = textwrap.dedent(\"\"\"\n#include <CoreFoundation/CoreFoundation.h>\n\nvoid hello_api()\n{\n    CFTypeRef keys[] = {CFSTR(\"key\")};\n    CFTypeRef values[] = {CFSTR(\"value\")};\n    CFDictionaryRef dict = CFDictionaryCreate(kCFAllocatorDefault, keys, values, sizeof(keys) / sizeof(keys[0]), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);\n    if (dict)\n        CFRelease(dict);\n}\n        \"\"\")\n    hello_h_core = textwrap.dedent(\"\"\"\nvoid hello_api();\n        \"\"\")\n    cmakelists_txt = textwrap.dedent(\"\"\"\nset(CMAKE_CXX_COMPILER_WORKS 1)\nset(CMAKE_CXX_ABI_COMPILED 1)\ncmake_minimum_required(VERSION 3.15)\nproject(hello)\ninclude(GNUInstallDirs)\nfile(GLOB SOURCES *.cpp)\nfile(GLOB HEADERS *.h)\nadd_library(${PROJECT_NAME} ${SOURCES} ${HEADERS})\nset_target_properties(${PROJECT_NAME} PROPERTIES PUBLIC_HEADER ${HEADERS})\ninstall(TARGETS ${PROJECT_NAME}\n    RUNTIME DESTINATION bin\n    LIBRARY DESTINATION lib\n    ARCHIVE DESTINATION lib\n    PUBLIC_HEADER DESTINATION include)\n        \"\"\")\n    test_conanfile_py = textwrap.dedent(\"\"\"\nimport os\nfrom conan import ConanFile, tools\nfrom conan.tools.cmake import CMake, CMakeToolchain, CMakeDeps\nfrom conan.tools.build import cross_building\n\n\nclass TestPackageConan(ConanFile):\n    settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n    generators = \"CMakeToolchain\"\n\n    def requirements(self):\n        self.requires(self.tested_reference_str)\n        self.tool_requires(self.tested_reference_str)\n\n    def generate(self):\n        cmake = CMakeDeps(self)\n        cmake.build_context_activated = [\"hello\"]\n        cmake.build_context_suffix = {\"hello\": \"_BUILD\"}\n        cmake.generate()\n\n    def build(self):\n        cmake = CMake(self)\n        cmake.configure()\n        cmake.build()\n\n    def test(self):\n        if not cross_building(self):\n            self.run(\"./test_package\", env=\"conanrunenv\")\n        \"\"\")\n    test_test_package_cpp = textwrap.dedent(\"\"\"\n#include \"hello.h\"\n\nint main()\n{\n    hello_api();\n}\n        \"\"\")\n    test_cmakelists_txt = textwrap.dedent(\"\"\"\nset(CMAKE_CXX_COMPILER_WORKS 1)\nset(CMAKE_CXX_ABI_COMPILED 1)\ncmake_minimum_required(VERSION 3.15)\nproject(test_package CXX)\n\nfind_package(HELLO REQUIRED CONFIG)\n\nadd_executable(${PROJECT_NAME} test_package.cpp)\ntarget_link_libraries(${PROJECT_NAME} hello::libhello)\n        \"\"\")\n    t = TestClient()\n    t.save({'conanfile.py': conanfile_py,\n            'hello.cpp': hello_cpp_core,\n            'hello.h': hello_h_core,\n            'CMakeLists.txt': cmakelists_txt,\n            'test_package/conanfile.py': test_conanfile_py,\n            'test_package/CMakeLists.txt': test_cmakelists_txt,\n            'test_package/test_package.cpp': test_test_package_cpp})\n    t.run(\"create . --name=hello --version=1.0\")\n\n\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only OSX\")\ndef test_iphoneos_crossbuild():\n    profile = textwrap.dedent(\"\"\"\n        include(default)\n        [settings]\n        os=iOS\n        os.version=12.0\n        os.sdk=iphoneos\n        arch=armv8\n    \"\"\").format()\n\n    client = TestClient(path_with_spaces=False)\n    client.save({\"ios-armv8\": profile}, clean_first=True)\n    client.run(\"new cmake_lib -d name=hello -d version=0.1\")\n    client.run(\"create . --profile:build=default --profile:host=ios-armv8 -tf=\\\"\\\"\")\n\n    main = gen_function_cpp(name=\"main\", includes=[\"hello\"], calls=[\"hello\"])\n    # FIXME: The crossbuild for iOS etc is failing with find_package because cmake ignore the\n    #        cmake_prefix_path to point only to the Frameworks of the system. The only fix found\n    #        would require to introduce something like \"set (mylibrary_DIR \"${CMAKE_BINARY_DIR}\")\"\n    #        at the toolchain (but it would require the toolchain to know about the deps)\n    #        https://stackoverflow.com/questions/65494246/cmakes-find-package-ignores-the-paths-option-when-building-for-ios#\n    cmakelists = textwrap.dedent(\"\"\"\n    set(CMAKE_CXX_COMPILER_WORKS 1)\n    set(CMAKE_CXX_ABI_COMPILED 1)\n    cmake_minimum_required(VERSION 3.15)\n    project(MyApp CXX)\n    set(hello_DIR \"${CMAKE_BINARY_DIR}\")\n    find_package(hello)\n    add_executable(main main.cpp)\n    target_link_libraries(main hello::hello)\n    \"\"\")\n\n    hello = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n\n        class TestConan(ConanFile):\n            requires = \"hello/0.1\"\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            exports_sources = \"CMakeLists.txt\", \"main.cpp\"\n            generators = \"CMakeDeps\", \"CMakeToolchain\"\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n        \"\"\")\n\n    client.save({\"conanfile.py\": hello,\n                 \"CMakeLists.txt\": cmakelists,\n                 \"main.cpp\": main,\n                 \"ios-armv8\": profile}, clean_first=True)\n    client.run(\"install . --profile:build=default --profile:host=ios-armv8\")\n    client.run(\"build . --profile:build=default --profile:host=ios-armv8\")\n    main_path = \"./main.app/main\"\n    client.run_command(\"lipo -info {}\".format(main_path))\n    assert \"Non-fat file\" in client.out\n    assert \"is architecture: arm64\" in client.out\n    client.run_command(f\"vtool -show-build {main_path}\")\n    assert \"platform IOS\" in client.out\n    assert \"minos 12.0\" in client.out\n"
  },
  {
    "path": "test/functional/toolchains/cmake/cmakedeps/test_build_context_protobuf.py",
    "content": "import textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.fixture\ndef client():\n    c = TestClient()\n    conanfile = textwrap.dedent('''\n    from conan import ConanFile\n    from conan.tools.files import save, chdir\n    import os\n\n    class Protobuf(ConanFile):\n        settings = \"build_type\", \"os\", \"arch\", \"compiler\"\n\n        def package(self):\n            my_cmake_module = \"\"\"\n                  function(foo_generate)\n                     write_file(foo_generated.h \"int from_context = %s;\")\n                  endfunction()\n            \"\"\"\n\n            with chdir(self, self.package_folder):\n                save(self, \"include_build/protobuf.h\", \"int protubuff_stuff(){ return 1; }\")\n                save(self, \"include_host/protobuf.h\", \"int protubuff_stuff(){ return 2; }\")\n                save(self, \"build/my_tools_build.cmake\", my_cmake_module % \"1\")\n                save(self, \"build/my_tools_host.cmake\", my_cmake_module % \"2\")\n\n        def package_info(self):\n            # This info depends on self.context !!\n            self.cpp_info.includedirs = [\"include_{}\".format(self.context)]\n            path_build_modules = os.path.join(\"build\", \"my_tools_{}.cmake\".format(self.context))\n            self.cpp_info.set_property(\"cmake_build_modules\", [path_build_modules])\n\n    ''')\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"create . --name=protobuf --version=1.0\")\n    return c\n\n\nmain = textwrap.dedent(\"\"\"\n    #include <iostream>\n    #include \"protobuf.h\"\n    #include \"foo_generated.h\"\n\n\n    int main(){\n        int ret = protubuff_stuff();\n\n        if(ret == 1){\n            std::cout << \" Library from build context!\" << std::endl;\n        }\n        else if(ret == 2){\n            std::cout << \" Library from host context!\" << std::endl;\n        }\n\n        // Variable declared at the foo_generated\n        if(from_context == 1){\n            std::cout << \" Generated code in build context!\" << std::endl;\n        }\n        else if(from_context == 2){\n            std::cout << \" Generated code in host context!\" << std::endl;\n        }\n        return 0;\n    }\n    \"\"\")\n\nconsumer_conanfile = textwrap.dedent(\"\"\"\n    import os\n    from conan import ConanFile\n    from conan.tools.cmake import CMake, CMakeToolchain, CMakeDeps\n\n    class Consumer(ConanFile):\n        settings = \"build_type\", \"os\", \"arch\", \"compiler\"\n        exports_sources = \"CMakeLists.txt\", \"main.cpp\"\n        requires = \"protobuf/1.0\"\n\n        def build_requirements(self):\n            self.requires(\"protobuf/1.0\", visible=False, build=True)\n\n        def generate(self):\n            toolchain = CMakeToolchain(self)\n            toolchain.generate()\n\n            deps = CMakeDeps(self)\n            {}\n            deps.generate()\n\n        def build(self):\n            cmake = CMake(self)\n            cmake.configure()\n            cmake.build()\n            folder = str(self.settings.build_type) if self.settings.os == \"Windows\" else \".\"\n            self.run(os.sep.join([folder, \"app\"]))\n    \"\"\")\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_build_modules_from_build_context(client):\n    consumer_cmake = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.15)\n        project(MyApp CXX)\n\n        find_package(protobuf)\n        find_package(protobuf_BUILD)\n        add_executable(app main.cpp)\n        foo_generate()\n        target_link_libraries(app protobuf::protobuf)\n        \"\"\")\n\n    cmake_deps_conf = \"\"\"\n        deps.build_context_activated = [\"protobuf\"]\n        deps.build_context_build_modules = [\"protobuf\"]\n        deps.build_context_suffix = {\"protobuf\": \"_BUILD\"}\n    \"\"\"\n\n    client.save({\"conanfile.py\": consumer_conanfile.format(cmake_deps_conf),\n                 \"CMakeLists.txt\": consumer_cmake,\n                 \"main.cpp\": main})\n\n    client.run(\"create . --name=app --version=1.0 -pr:b default -pr:h default\")\n    assert \"Library from host context!\" in client.out\n    assert \"Generated code in build context!\" in client.out\n\n\ndef test_build_modules_and_target_from_build_context(client):\n    consumer_cmake = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.15)\n        project(MyApp CXX)\n\n        find_package(protobuf)\n        find_package(protobuf_BUILD)\n        add_executable(app main.cpp)\n        foo_generate()\n        target_link_libraries(app protobuf_BUILD::protobuf_BUILD)\n        \"\"\")\n\n    cmake_deps_conf = \"\"\"\n        deps.build_context_activated = [\"protobuf\"]\n        deps.build_context_build_modules = [\"protobuf\"]\n        deps.build_context_suffix = {\"protobuf\": \"_BUILD\"}\n    \"\"\"\n\n    client.save({\"conanfile.py\": consumer_conanfile.format(cmake_deps_conf),\n                 \"CMakeLists.txt\": consumer_cmake,\n                 \"main.cpp\": main})\n\n    client.run(\"create . --name=app --version=1.0 -pr:b default -pr:h default\")\n    assert \"Library from build context!\" in client.out\n    assert \"Generated code in build context!\" in client.out\n\n\ndef test_build_modules_from_host_and_target_from_build_context(client):\n    consumer_cmake = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.15)\n        project(MyApp CXX)\n\n        find_package(protobuf)\n        find_package(protobuf_BUILD)\n        add_executable(app main.cpp)\n        foo_generate()\n        target_link_libraries(app protobuf_BUILD::protobuf_BUILD)\n        \"\"\")\n\n    cmake_deps_conf = \"\"\"\n        deps.build_context_activated = [\"protobuf\"]\n        deps.build_context_suffix = {\"protobuf\": \"_BUILD\"}\n    \"\"\"\n\n    client.save({\"conanfile.py\": consumer_conanfile.format(cmake_deps_conf),\n                 \"CMakeLists.txt\": consumer_cmake,\n                 \"main.cpp\": main})\n\n    client.run(\"create . --name=app --version=1.0 -pr:b default -pr:h default\")\n    assert \"Library from build context!\" in client.out\n    assert \"Generated code in host context!\" in client.out\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_build_modules_and_target_from_host_context(client):\n    consumer_cmake = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.15)\n        project(MyApp CXX)\n\n        find_package(protobuf)\n        find_package(protobuf_BUILD)\n        add_executable(app main.cpp)\n        foo_generate()\n        target_link_libraries(app protobuf::protobuf)\n        \"\"\")\n\n    cmake_deps_conf = \"\"\"\n        deps.build_context_activated = [\"protobuf\"]\n        deps.build_context_build_modules = []\n        deps.build_context_suffix = {\"protobuf\": \"_BUILD\"}\n    \"\"\"\n\n    client.save({\"conanfile.py\": consumer_conanfile.format(cmake_deps_conf),\n                 \"CMakeLists.txt\": consumer_cmake,\n                 \"main.cpp\": main})\n\n    client.run(\"create . --name=app --version=1.0 -pr:b default -pr:h default\")\n    assert \"Conan: Target declared 'protobuf::protobuf'\" in client.out\n    assert \"Conan: Target declared 'protobuf_BUILD::protobuf_BUILD'\" in client.out\n    assert \"Library from host context!\" in client.out\n    assert \"Generated code in host context!\" in client.out\n\n\ndef test_exception_when_not_prefix_specified(client):\n    cmake_deps_conf = \"\"\"\n        deps.build_context_activated = [\"protobuf\"]\n    \"\"\"\n    client.save({\"conanfile.py\": consumer_conanfile.format(cmake_deps_conf),\n                 \"main.cpp\": main})\n\n    client.run(\"create . --name=app --version=1.0 -pr:b default -pr:h default\", assert_error=True)\n    assert \"The package 'protobuf' exists both as 'require' and as 'build require'. \" \\\n           \"You need to specify a suffix using the 'build_context_suffix' attribute at the \" \\\n           \"CMakeDeps generator.\" in client.out\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_not_activated_not_fail(client):\n    consumer_cmake = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.15)\n        project(MyApp CXX)\n\n        find_package(protobuf)\n        add_executable(app main.cpp)\n        foo_generate()\n        target_link_libraries(app protobuf::protobuf)\n        \"\"\")\n\n    client.save({\"conanfile.py\": consumer_conanfile.format(\"\"),\n                 \"CMakeLists.txt\": consumer_cmake,\n                 \"main.cpp\": main})\n\n    client.run(\"create . --name=app --version=1.0 -pr:b default -pr:h default\")\n    assert \"app/1.0: Created package\" in client.out\n    assert \"Library from host context!\" in client.out\n    assert \"Generated code in host context!\" in client.out\n"
  },
  {
    "path": "test/functional/toolchains/cmake/cmakedeps/test_build_context_transitive_build.py",
    "content": "import os\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.cmake import gen_cmakelists\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.assets.sources import gen_function_cpp\nfrom conan.test.utils.tools import TestClient\n\n\"\"\"\nIf we have a BR with transitive requires we won't generate 'xxx-config.cmake' files for them\nbut neither will be included as find_dependencies()\n\"\"\"\n\n\n@pytest.fixture\ndef client():\n    c = TestClient()\n    zlib_conanfile = textwrap.dedent('''\n    from conan import ConanFile\n\n    class Zlib(ConanFile):\n        name = \"zlib\"\n        version = \"1.2.11\"\n\n        def package_info(self):\n            self.cpp_info.includedirs = []\n            self.cpp_info.cxxflags = [\"foo\"]\n    ''')\n    c.save({\"conanfile.py\": zlib_conanfile})\n    c.run(\"create . \")\n\n    doxygen_conanfile = textwrap.dedent('''\n    from conan import ConanFile\n    from conan.tools.files import save, chdir\n    import os\n\n    class Doxygen(ConanFile):\n        settings = \"build_type\", \"os\", \"arch\", \"compiler\"\n        requires = \"zlib/1.2.11\"\n\n        def package(self):\n            with chdir(self, self.package_folder):\n                save(self, \"include/doxygen.h\", \"int foo=1;\")\n    ''')\n    c.save({\"conanfile.py\": doxygen_conanfile})\n    c.run(\"create . --name=doxygen --version=1.0\")\n    return c\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_zlib_not_included(client):\n\n    main = gen_function_cpp(name=\"main\", includes=[\"doxygen.h\"])\n    cmake = gen_cmakelists(find_package=[\"doxygen\"], appsources=[\"main.cpp\"], appname=\"main\")\n\n    conanfile_consumer = textwrap.dedent('''\n        from conan import ConanFile\n        from conan.tools.cmake import CMakeDeps\n\n        class Consumer(ConanFile):\n            settings = \"build_type\", \"os\", \"arch\", \"compiler\"\n            build_requires = [\"doxygen/1.0\"]\n            generators = \"CMakeToolchain\"\n\n            def generate(self):\n                d = CMakeDeps(self)\n                d.build_context_activated = [\"doxygen\"]\n                d.generate()\n        ''')\n\n    client.save({\"main.cpp\": main, \"CMakeLists.txt\": cmake, \"conanfile.py\": conanfile_consumer},\n                clean_first=True)\n    client.run(\"install . -pr:h=default -pr:b=default\")\n    # The compilation works, so it finds the doxygen without transitive failures\n    client.run_command(\"cmake . -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release\")\n\n    # Assert there is no zlib target\n    assert \"Target declared 'zlib::zlib'\" not in client.out\n\n    # Of course we find the doxygen-config.cmake\n    assert os.path.exists(os.path.join(client.current_folder, \"doxygen-config.cmake\"))\n\n    # The -config files for zlib are not there\n    assert not os.path.exists(os.path.join(client.current_folder, \"zlib-config.cmake\"))\n\n\ndef test_error_cmakedeps_transitive_build_requires():\n    \"\"\"\n    CMakeDeps when building an intermediate \"tool_requires\" that has a normal \"requires\"\n    to other package, needs to use ``require.build`` trait instead of the more global\n    \"dep.is_build_context\"\n    We do build \"protobuf\" in the \"build\" context to make sure the whole CMakeDeps is\n    working correctly\n    \"\"\"\n    c = TestClient()\n    c.run(\"new cmake_lib -d name=zlib -d version=0.1\")\n    c.run(\"create . -tf=\")\n    c.save({}, clean_first=True)\n    c.run(\"new cmake_lib -d name=openssl -d version=0.1 -d requires=zlib/0.1\")\n    c.run(\"create . -tf=\")\n\n    # Protobuf binary is missing, to force a build below with ``--build=missing``\n    c.save({}, clean_first=True)\n    c.run(\"new cmake_exe -d name=protobuf -d version=0.1 -d requires=openssl/0.1\")\n    c.run(\"export .\")\n\n    # This conanfile used to fail, creating protobuf_mybuild*.cmake files even if for \"tool\" the\n    # protobuf/0.1 is a regular \"requires\" and it is in its host context\n    tool = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.cmake import CMakeDeps\n\n        class Tool(ConanFile):\n            name = \"tool\"\n            version = \"0.1\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            requires = \"protobuf/0.1\"\n\n            def generate(self):\n                deps = CMakeDeps(self)\n                deps.build_context_activated = [\"protobuf\"]\n                deps.build_context_suffix = {\"protobuf\": \"_mybuild\"}\n                deps.generate()\n\n            def build(self):\n                assert os.path.exists(\"protobufTargets.cmake\")\n                assert os.path.exists(\"protobuf-Target-release.cmake\")\n        \"\"\")\n    c.save({\"tool/conanfile.py\": tool,\n            \"consumer/conanfile.py\": GenConanfile().with_build_requires(\"tool/0.1\")},\n           clean_first=True)\n    c.run(\"export tool\")\n    c.run(\"install consumer --build=missing -s:b build_type=Release -s:h build_type=Debug\")\n    assert \"tool/0.1: Created package\" in c.out\n\n\ndef test_transitive_tool_requires_visible():\n    # https://github.com/conan-io/conan/issues/16058\n    # The \"tool/0.1\", even if visible doesn't generate any files in the \"app\" consumer side,\n    # even if the \"app\" declares it in build_context_activated, because it only works for direct\n    # dependencies. tool_requires(..., visible=True) only affects at the moment and version conflict\n    # detection\n    c = TestClient()\n    c.save({\"tool/conanfile.py\": GenConanfile(\"tool\", \"0.1\").with_package_type(\"application\"),\n            \"pkgb/conanfile.py\": GenConanfile(\"pkgb\", \"0.1\").with_tool_requirement(\"tool/0.1\",\n                                                                                   visible=True),\n            \"app/conanfile.py\": GenConanfile(\"app\", \"0.1\").with_requires(\"pkgb/0.1\")\n                                                          .with_settings(\"build_type\")\n                                                          .with_generator(\"CMakeDeps\")})\n\n    c.run(\"create tool\")\n    c.run(\"create pkgb\")\n    c.run(\"install app\")\n    cmake = c.load(\"app/pkgb-release-data.cmake\")\n    # pkgb doesn't deepnd on tool, because it is a tool-require and not build-context activated\n    assert \"list(APPEND pkgb_FIND_DEPENDENCY_NAMES )\" in cmake\n"
  },
  {
    "path": "test/functional/toolchains/cmake/cmakedeps/test_cmakedeps.py",
    "content": "import os\nimport platform\nimport shutil\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.cmake import gen_cmakelists\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.assets.sources import gen_function_cpp, gen_function_h\nfrom conan.test.utils.mocks import ConanFileMock\nfrom conan.test.utils.tools import TestClient, NO_SETTINGS_PACKAGE_ID\nfrom conan.tools.files import replace_in_file\n\n\n@pytest.fixture\ndef client():\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import save\n        import os\n        class Pkg(ConanFile):\n            settings = \"build_type\", \"os\", \"arch\", \"compiler\"\n            {}\n            def package(self):\n                save(self, os.path.join(self.package_folder, \"include\", \"%s.h\" % self.name),\n                     '#define MYVAR%s \"%s\"' % (self.name, self.settings.build_type))\n        \"\"\")\n\n    c.save({\"conanfile.py\": conanfile.format(\"\")})\n    c.run(\"create . --name=liba --version=0.1 -s build_type=Release\")\n    c.run(\"create . --name=liba --version=0.1 -s build_type=Debug\")\n    c.save({\"conanfile.py\": conanfile.format(\"requires = 'liba/0.1'\")})\n    c.run(\"create . --name=libb --version=0.1 -s build_type=Release\")\n    c.run(\"create . --name=libb --version=0.1 -s build_type=Debug\")\n    return c\n\n\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Windows only multi-config\")\ndef test_transitive_multi_windows(client):\n    # Save conanfile and example\n    conanfile = textwrap.dedent(\"\"\"\n        [requires]\n        libb/0.1\n\n        [generators]\n        CMakeDeps\n        CMakeToolchain\n        \"\"\")\n    example_cpp = gen_function_cpp(name=\"main\", includes=[\"libb\", \"liba\"],\n                                   preprocessor=[\"MYVARliba\", \"MYVARlibb\"])\n    client.save({\"conanfile.txt\": conanfile,\n                 \"CMakeLists.txt\": gen_cmakelists(appname=\"example\",\n                                                  appsources=[\"example.cpp\"], find_package=[\"libb\"]),\n                 \"example.cpp\": example_cpp}, clean_first=True)\n\n    with client.chdir(\"build\"):\n        for bt in (\"Debug\", \"Release\"):\n            # NOTE: -of=. otherwise the output files are located in the parent directory\n            client.run(\"install .. --user=user --channel=channel -s build_type={} -of=.\".format(bt))\n\n        # Test that we are using find_dependency with the NO_MODULE option\n        # to skip finding first possible FindBye somewhere\n        assert \"find_dependency(${_DEPENDENCY} REQUIRED ${${_DEPENDENCY}_FIND_MODE})\" \\\n               in client.load(\"libb-config.cmake\")\n        assert 'set(liba_FIND_MODE \"NO_MODULE\")' in client.load(\"libb-release-x86_64-data.cmake\")\n\n        if platform.system() == \"Windows\":\n            client.run_command('cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake')\n            client.run_command('cmake --build . --config Debug')\n            client.run_command('cmake --build . --config Release')\n\n            client.run_command('Debug\\\\example.exe')\n            assert \"main: Debug!\" in client.out\n            assert \"MYVARliba: Debug\" in client.out\n            assert \"MYVARlibb: Debug\" in client.out\n\n            client.run_command('Release\\\\example.exe')\n            assert \"main: Release!\" in client.out\n            assert \"MYVARliba: Release\" in client.out\n            assert \"MYVARlibb: Release\" in client.out\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_system_libs():\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import save\n        import os\n\n        class Test(ConanFile):\n            name = \"test\"\n            version = \"2.0\"\n            settings = \"build_type\"\n            def package(self):\n                save(self, os.path.join(self.package_folder, \"lib/lib1.lib\"), \"\")\n                save(self, os.path.join(self.package_folder, \"lib/liblib1.a\"), \"\")\n\n            def package_info(self):\n                self.cpp_info.libs = [\"lib1\"]\n                if self.settings.build_type == \"Debug\":\n                    self.cpp_info.system_libs.append(\"sys1d\")\n                else:\n                    self.cpp_info.system_libs.append(\"sys1\")\n                self.cpp_info.set_property(\"cmake_config_version_compat\", \"AnyNewerVersion\")\n        \"\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . -s build_type=Release\")\n    client.run(\"create . -s build_type=Debug\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        [requires]\n        test/2.0\n\n        [generators]\n        CMakeDeps\n        \"\"\")\n    cmakelists = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(consumer NONE)\n        set(CMAKE_PREFIX_PATH ${CMAKE_BINARY_DIR})\n        set(CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR})\n        find_package(test 1.0)\n        message(\"System libs release: ${test_SYSTEM_LIBS_RELEASE}\")\n        message(\"Libraries to Link release: ${test_LIBS_RELEASE}\")\n        message(\"System libs debug: ${test_SYSTEM_LIBS_DEBUG}\")\n        message(\"Libraries to Link debug: ${test_LIBS_DEBUG}\")\n        get_target_property(tmp test::test INTERFACE_LINK_LIBRARIES)\n        message(\"Target libs: ${tmp}\")\n        get_target_property(tmp CONAN_LIB::test_lib1_%s INTERFACE_LINK_LIBRARIES)\n        message(\"Micro-target libs: ${tmp}\")\n        get_target_property(tmp test_DEPS_TARGET INTERFACE_LINK_LIBRARIES)\n        message(\"Micro-target deps: ${tmp}\")\n        \"\"\")\n\n    for build_type in [\"Release\", \"Debug\"]:\n        client.save({\"conanfile.txt\": conanfile,\n                     \"CMakeLists.txt\": cmakelists % build_type.upper()}, clean_first=True)\n        client.run(\"install conanfile.txt -s build_type=%s\" % build_type)\n        client.run_command('cmake . -DCMAKE_BUILD_TYPE={0}'.format(build_type))\n\n        library_name = \"sys1d\" if build_type == \"Debug\" else \"sys1\"\n        # FIXME: Note it is CONAN_LIB::test_lib1_RELEASE, not \"lib1\" as cmake_find_package\n        if build_type == \"Release\":\n            assert \"System libs release: %s\" % library_name in client.out\n            assert \"Libraries to Link release: lib1\" in client.out\n        else:\n            assert \"System libs debug: %s\" % library_name in client.out\n            assert \"Libraries to Link debug: lib1\" in client.out\n\n        assert (f\"Target libs: $<$<CONFIG:{build_type}>:>;\"\n                f\"$<$<CONFIG:{build_type}>:CONAN_LIB::test_lib1_{build_type.upper()}>\") in client.out\n        assert \"Micro-target libs: test_DEPS_TARGET\" in client.out\n        micro_target_deps = f\"Micro-target deps: $<$<CONFIG:{build_type}>:>;\" \\\n                            f\"$<$<CONFIG:{build_type}>:{library_name}>;\" \\\n                            f\"$<$<CONFIG:{build_type}>:>\"\n        assert micro_target_deps in client.out\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_system_libs_no_libs():\n    \"\"\"If the recipe doesn't declare cpp_info.libs then the target with the system deps, frameworks\n       and transitive deps has to be linked to the global target\"\"\"\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import save\n        import os\n\n        class Test(ConanFile):\n            name = \"test\"\n            version = \"0.1.1\"\n            settings = \"build_type\"\n\n            def package_info(self):\n                if self.settings.build_type == \"Debug\":\n                    self.cpp_info.system_libs.append(\"sys1d\")\n                else:\n                    self.cpp_info.system_libs.append(\"sys1\")\n                self.cpp_info.set_property(\"cmake_config_version_compat\", \"SameMinorVersion\")\n        \"\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . -s build_type=Release\")\n    client.run(\"create . -s build_type=Debug\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        [requires]\n        test/0.1.1\n\n        [generators]\n        CMakeDeps\n        \"\"\")\n    cmakelists = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(consumer NONE)\n        set(CMAKE_PREFIX_PATH ${CMAKE_BINARY_DIR})\n        set(CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR})\n        find_package(test 0.1)\n        message(\"System libs Release: ${test_SYSTEM_LIBS_RELEASE}\")\n        message(\"Libraries to Link release: ${test_LIBS_RELEASE}\")\n        message(\"System libs Debug: ${test_SYSTEM_LIBS_DEBUG}\")\n        message(\"Libraries to Link debug: ${test_LIBS_DEBUG}\")\n        get_target_property(tmp test::test INTERFACE_LINK_LIBRARIES)\n        message(\"Target libs: ${tmp}\")\n        get_target_property(tmp test_DEPS_TARGET INTERFACE_LINK_LIBRARIES)\n        message(\"DEPS TARGET: ${tmp}\")\n\n        \"\"\")\n\n    for build_type in [\"Release\", \"Debug\"]:\n        client.save({\"conanfile.txt\": conanfile, \"CMakeLists.txt\": cmakelists}, clean_first=True)\n        client.run(\"install conanfile.txt -s build_type=%s\" % build_type)\n        client.run_command('cmake . -DCMAKE_BUILD_TYPE={0}'.format(build_type))\n\n        library_name = \"sys1d\" if build_type == \"Debug\" else \"sys1\"\n\n        assert f\"System libs {build_type}: {library_name}\" in client.out\n        assert f\"Target libs: $<$<CONFIG:{build_type}>:>;\" \\\n               f\"$<$<CONFIG:{build_type}>:>;test_DEPS_TARGET\" in client.out\n        assert f\"DEPS TARGET: $<$<CONFIG:{build_type}>:>;\" \\\n               f\"$<$<CONFIG:{build_type}>:{library_name}>\" in client.out\n\n\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.parametrize(\"policy\",\n                         [\"AnyNewerVersion\", \"SameMajorVersion\", \"SameMinorVersion\", \"ExactVersion\"])\ndef test_cmake_config_version_compat_rejected(policy):\n    conanfile = textwrap.dedent(f\"\"\"\n        from conan import ConanFile\n\n        class Test(ConanFile):\n            def package_info(self):\n                self.cpp_info.set_property(\"cmake_config_version_compat\", \"{policy}\")\n        \"\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=mytest --version=2.2.1\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        [requires]\n        mytest/2.2.1\n\n        [generators]\n        CMakeDeps\n        CMakeToolchain\n        \"\"\")\n    version_to_reject = {\"AnyNewerVersion\": \"3.0\",\n                         \"SameMajorVersion\": \"1.0\",\n                         \"SameMinorVersion\": \"2.1\",\n                         \"ExactVersion\": \"2.2.0\"}[policy]\n    cmakelists = textwrap.dedent(f\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(consumer NONE)\n        message(STATUS \"CMAKE VERSION=${{CMAKE_VERSION}}\")\n        find_package(mytest {version_to_reject} CONFIG REQUIRED)\n        \"\"\")\n\n    client.save({\"conanfile.txt\": conanfile,\n                 \"CMakeLists.txt\": cmakelists}, clean_first=True)\n    client.run(\"install .\")\n    client.run_command('cmake . -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake', assert_error=True)\n    assert \"The following configuration files were considered but not accepted\" in client.out\n    assert \"2.2.1\" in client.out\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_system_libs_components_no_libs():\n    \"\"\"If the recipe doesn't declare cpp_info.libs then the target with the system deps, frameworks\n       and transitive deps has to be linked to the component target\"\"\"\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import save\n        import os\n\n        class Test(ConanFile):\n            name = \"test\"\n            version = \"0.1\"\n            settings = \"build_type\"\n\n            def package_info(self):\n                if self.settings.build_type == \"Debug\":\n                    self.cpp_info.components[\"foo\"].system_libs.append(\"sys1d\")\n                else:\n                    self.cpp_info.components[\"foo\"].system_libs.append(\"sys1\")\n        \"\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . -s build_type=Release\")\n    client.run(\"create . -s build_type=Debug\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        [requires]\n        test/0.1\n\n        [generators]\n        CMakeDeps\n        \"\"\")\n    cmakelists = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(consumer NONE)\n        set(CMAKE_PREFIX_PATH ${CMAKE_BINARY_DIR})\n        set(CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR})\n        find_package(test)\n        message(\"System libs Release: ${test_test_foo_SYSTEM_LIBS_RELEASE}\")\n        message(\"Libraries to Link release: ${test_test_foo_LIBS_RELEASE}\")\n        message(\"System libs Debug: ${test_test_foo_SYSTEM_LIBS_DEBUG}\")\n        message(\"Libraries to Link debug: ${test_test_foo_LIBS_DEBUG}\")\n\n        get_target_property(tmp test::foo INTERFACE_LINK_LIBRARIES)\n        message(\"Target libs: ${tmp}\")\n        get_target_property(tmp test_test_foo_DEPS_TARGET INTERFACE_LINK_LIBRARIES)\n        message(\"DEPS TARGET: ${tmp}\")\n\n        \"\"\")\n\n    for build_type in [\"Release\", \"Debug\"]:\n        client.save({\"conanfile.txt\": conanfile, \"CMakeLists.txt\": cmakelists}, clean_first=True)\n        client.run(\"install conanfile.txt -s build_type=%s\" % build_type)\n        client.run_command('cmake . -DCMAKE_BUILD_TYPE={0}'.format(build_type))\n\n        library_name = \"sys1d\" if build_type == \"Debug\" else \"sys1\"\n\n        assert f\"System libs {build_type}: {library_name}\" in client.out\n        assert (f\"Target libs: $<$<CONFIG:{build_type}>:>;\"\n                f\"$<$<CONFIG:{build_type}>:>;test_test_foo_DEPS_TARGET\") in client.out\n        assert f\"DEPS TARGET: $<$<CONFIG:{build_type}>:>;\" \\\n               f\"$<$<CONFIG:{build_type}>:{library_name}>\" in client.out\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_do_not_mix_cflags_cxxflags():\n    # TODO: Verify with components too\n    client = TestClient()\n    cpp_info = {\"cflags\": [\"one\", \"two\"], \"cxxflags\": [\"three\", \"four\"]}\n    client.save({\"conanfile.py\": GenConanfile(\"upstream\", \"1.0\").with_package_info(cpp_info=cpp_info)})\n    client.run(\"create .\")\n\n    consumer_conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n\n        class Consumer(ConanFile):\n            name = \"consumer\"\n            version = \"1.0\"\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            exports_sources = \"CMakeLists.txt\"\n            requires = \"upstream/1.0\"\n            generators = \"CMakeDeps\", \"CMakeToolchain\"\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n        \"\"\")\n    cmakelists = textwrap.dedent(\"\"\"\n       cmake_minimum_required(VERSION 3.15)\n       project(consumer NONE)\n       find_package(upstream CONFIG REQUIRED)\n       get_target_property(tmp upstream::upstream INTERFACE_COMPILE_OPTIONS)\n       message(\"compile options: ${tmp}\")\n       message(\"cflags: ${upstream_COMPILE_OPTIONS_C_RELEASE}\")\n       message(\"cxxflags: ${upstream_COMPILE_OPTIONS_CXX_RELEASE}\")\n       \"\"\")\n    client.save({\"conanfile.py\": consumer_conanfile,\n                 \"CMakeLists.txt\": cmakelists}, clean_first=True)\n    client.run(\"create .\")\n    assert \"compile options: $<$<CONFIG:Release>:\" \\\n           \"$<$<COMPILE_LANGUAGE:CXX>:three;four>;$<$<COMPILE_LANGUAGE:C>:one;two>>\" in client.out\n    assert \"cflags: one;two\" in client.out\n    assert \"cxxflags: three;four\" in client.out\n\n\ndef test_custom_configuration(client):\n    \"\"\"  The configuration in the build context is still the same than the host context\"\"\"\n    conanfile = textwrap.dedent(\"\"\"\n       from conan import ConanFile\n       from conan.tools.cmake import CMakeDeps\n\n       class Consumer(ConanFile):\n           name = \"consumer\"\n           version = \"1.0\"\n           settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n           requires = \"liba/0.1\"\n           build_requires = \"liba/0.1\"\n           generators = \"CMakeToolchain\"\n\n           def generate(self):\n               cmake = CMakeDeps(self)\n               cmake.configuration = \"Debug\"\n               cmake.build_context_activated = [\"liba\"]\n               cmake.build_context_suffix[\"liba\"] = \"_build\"\n               cmake.generate()\n       \"\"\")\n    host_arch = client.get_default_host_profile().settings['arch']\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"install . -pr:h default -s:b build_type=RelWithDebInfo\"\n               \" -pr:b default -s:b arch=x86 --build missing\")\n    curdir = client.current_folder\n    data_name_context_build = f\"liba_build-debug-{host_arch}-data.cmake\"\n    data_name_context_host = f\"liba-debug-{host_arch}-data.cmake\"\n    assert os.path.exists(os.path.join(curdir, data_name_context_build))\n    assert os.path.exists(os.path.join(curdir, data_name_context_host))\n\n    assert \"set(liba_build_INCLUDE_DIRS_DEBUG\" in \\\n           open(os.path.join(curdir, data_name_context_build)).read()\n    assert \"set(liba_INCLUDE_DIRS_DEBUG\" in \\\n           open(os.path.join(curdir, data_name_context_host)).read()\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_buildirs_working():\n    \"\"\"  If a recipe declares cppinfo.buildirs those dirs will be exposed to be consumer\n    to allow a cmake \"include\" function call after a find_package\"\"\"\n    c = TestClient()\n    conanfile = str(GenConanfile().with_name(\"my_lib\").with_version(\"1.0\")\n                                  .with_import(\"import os\")\n                                  .with_import(\"from conan.tools.files import save\"))\n    conanfile += \"\"\"\n    def package(self):\n        save(self, os.path.join(self.package_folder, \"my_build_dir\", \"my_cmake_script.cmake\"),\n                   'set(MYVAR \"Like a Rolling Stone\")')\n\n    def package_info(self):\n        self.cpp_info.builddirs=[\"my_build_dir\"]\n    \"\"\"\n\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"create .\")\n\n    consumer_conanfile = GenConanfile().with_name(\"consumer\").with_version(\"1.0\")\\\n        .with_cmake_build().with_require(\"my_lib/1.0\") \\\n        .with_settings(\"os\", \"arch\", \"build_type\", \"compiler\") \\\n        .with_exports_sources(\"*.txt\")\n    cmake = gen_cmakelists(find_package=[\"my_lib\"])\n    cmake += \"\"\"\n    message(\"CMAKE_MODULE_PATH: ${CMAKE_MODULE_PATH}\")\n    include(\"my_cmake_script\")\n    message(\"MYVAR=>${MYVAR}\")\n    \"\"\"\n    c.save({\"conanfile.py\": consumer_conanfile, \"CMakeLists.txt\": cmake})\n    c.run(\"create .\")\n    assert \"MYVAR=>Like a Rolling Stone\" in c.out\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_cpp_info_link_objects():\n    client = TestClient()\n    obj_ext = \"obj\" if platform.system() == \"Windows\" else \"o\"\n    cpp_info = {\"objects\": [os.path.join(\"lib\", \"myobject.{}\".format(obj_ext))]}\n    object_cpp = gen_function_cpp(name=\"myobject\")\n    object_h = gen_function_h(name=\"myobject\")\n    cmakelists = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        set(CMAKE_C_COMPILER_WORKS 1)\n        set(CMAKE_C_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.15)\n        project(MyObject C CXX)\n        file(GLOB HEADERS *.h)\n        add_library(myobject OBJECT myobject.cpp)\n        if( WIN32 )\n            set(OBJ_PATH \"myobject.dir/Release/myobject${CMAKE_C_OUTPUT_EXTENSION}\")\n        else()\n            set(OBJ_PATH \"CMakeFiles/myobject.dir/myobject.cpp${CMAKE_C_OUTPUT_EXTENSION}\")\n        endif()\n        install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${OBJ_PATH}\n                DESTINATION ${CMAKE_INSTALL_PREFIX}/lib\n                RENAME myobject${CMAKE_C_OUTPUT_EXTENSION})\n        install(FILES ${HEADERS}\n                DESTINATION ${CMAKE_INSTALL_PREFIX}/include)\n    \"\"\")\n\n    test_package_cpp = gen_function_cpp(name=\"main\", includes=[\"myobject\"], calls=[\"myobject\"])\n    test_package_cmakelists = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.15)\n        project(example CXX)\n        find_package(myobject REQUIRED)\n        add_executable(example example.cpp)\n        target_link_libraries(example myobject::myobject)\n    \"\"\")\n    test_conanfile = (GenConanfile().with_cmake_build().with_import(\"import os\")\n                      .with_test('path = \"{}\".format(self.settings.build_type) '\n                                 'if self.settings.os == \"Windows\" else \".\"')\n                      .with_test('self.run(\"{}{}example\".format(path, os.sep))'))\n    client.save({\"CMakeLists.txt\": cmakelists,\n                 \"conanfile.py\": GenConanfile(\"myobject\", \"1.0\").with_package_info(cpp_info=cpp_info)\n                                                                .with_exports_sources(\"*\")\n                                                                .with_cmake_build()\n                                                                .with_package(\"cmake = CMake(self)\",\n                                                                              \"cmake.install()\"),\n                 \"myobject.cpp\": object_cpp,\n                 \"myobject.h\": object_h,\n                 \"test_package/conanfile.py\": test_conanfile,\n                 \"test_package/example.cpp\": test_package_cpp,\n                 \"test_package/CMakeLists.txt\": test_package_cmakelists})\n\n    client.run(\"create . -s build_type=Release\")\n    assert \"myobject: Release!\" in client.out\n\n\ndef test_private_transitive():\n    # https://github.com/conan-io/conan/issues/9514\n    client = TestClient()\n    client.save({\"dep/conanfile.py\": GenConanfile(),\n                 \"pkg/conanfile.py\": GenConanfile().with_requirement(\"dep/0.1\", visible=False),\n                 \"consumer/conanfile.py\": GenConanfile().with_requires(\"pkg/0.1\")\n                                                        .with_settings(\"os\", \"build_type\", \"arch\")})\n    client.run(\"create dep --name=dep --version=0.1\")\n    client.run(\"create pkg --name=pkg --version=0.1\")\n    client.run(\"install consumer -g CMakeDeps -s arch=x86_64 -s build_type=Release -of=. -v\")\n    client.assert_listed_binary({\"dep/0.1\": (NO_SETTINGS_PACKAGE_ID, \"Skip\")})\n    data_cmake = client.load(\"pkg-release-x86_64-data.cmake\")\n    assert 'list(APPEND pkg_FIND_DEPENDENCY_NAMES )' in data_cmake\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_system_dep():\n    \"\"\"This test creates a zlib package and use the installation CMake FindZLIB.cmake to locate\n    the library of the package. That happens because:\n    - The package declares: self.cpp_info.set_property(\"cmake_find_mode\", \"none\")\n      so CMakeDeps does nothing\n    - The toolchain set the CMAKE_LIBRARY_PATH to the \"lib\" of the package,\n      so the library file is found\n    \"\"\"\n    client = TestClient()\n\n    client.run(\"new cmake_lib -d name=zlib -d version=0.1 -o zlib\")\n    conanfile = client.load(\"zlib/conanfile.py\")\n    conanfile += textwrap.indent(textwrap.dedent(\"\"\"\n        # This will use the FindZLIB from CMake but will find this library package\n        self.cpp_info.set_property(\"cmake_file_name\", \"ZLIB\")\n        self.cpp_info.set_property(\"cmake_target_name\", \"ZLIB::ZLIB\")\n        self.cpp_info.set_property(\"cmake_find_mode\", \"none\")\n    \"\"\"), \"        \")\n    client.save({\"zlib/conanfile.py\": conanfile})\n\n    client.run(\"new cmake_lib -d name=mylib -d version=0.1 -d requires=zlib/0.1 -o mylib\")\n    cmake = client.load(\"mylib/CMakeLists.txt\")\n    cmake = cmake.replace(\"find_package(zlib CONFIG\", \"find_package(ZLIB\")\n    cmake = cmake.replace(\"zlib::zlib\", \"ZLIB::ZLIB\")\n    client.save({\"mylib/CMakeLists.txt\": cmake})\n\n    client.run(\"new cmake_lib -d name=consumer -d version=0.1 -d requires=mylib/0.1 -o=consumer\")\n\n    client.run(\"create zlib -tf=\")\n    client.run(\"create mylib -tf=\")\n    client.run(\"create consumer -tf=\")\n    assert \"Found ZLIB:\" in client.out\n\n    client.run(\"install consumer\")\n    if platform.system() != \"Windows\":\n        host_arch = client.get_default_host_profile().settings['arch']\n        data = f\"consumer/build/Release/generators/mylib-release-{host_arch}-data.cmake\"\n        contents = client.load(data)\n        assert 'set(ZLIB_FIND_MODE \"\")' in contents\n\n\n# needs at least 3.23.3 because of error with \"empty identity\"\n@pytest.mark.tool(\"cmake\", \"3.23\")\ndef test_error_missing_build_type(matrix_client):\n    # https://github.com/conan-io/conan/issues/11168\n    c = matrix_client\n\n    conanfile = textwrap.dedent(\"\"\"\n        [requires]\n        matrix/1.0\n        [generators]\n        CMakeDeps\n        CMakeToolchain\n    \"\"\")\n\n    main = textwrap.dedent(\"\"\"\n        #include <matrix.h>\n        int main() {matrix();return 0;}\n    \"\"\")\n\n    cmakelists = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.15)\n        project(app CXX)\n        find_package(matrix REQUIRED)\n        add_executable(app)\n        target_link_libraries(app matrix::matrix)\n        target_sources(app PRIVATE main.cpp)\n    \"\"\")\n\n    if platform.system() != \"Windows\":\n        c.save({\n            \"conanfile.txt\": conanfile,\n            \"main.cpp\": main,\n            \"CMakeLists.txt\": cmakelists\n        }, clean_first=True)\n\n        c.run(\"install .\")\n        c.run_command(\"cmake . -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -G 'Unix Makefiles'\",\n                      assert_error=True)\n        assert \"Please, set the CMAKE_BUILD_TYPE variable when calling to CMake\" in c.out\n\n    c.save({\n        \"conanfile.txt\": conanfile,\n        \"main.cpp\": main,\n        \"CMakeLists.txt\": cmakelists\n    }, clean_first=True)\n\n    c.run(\"install .\")\n\n    generator = {\n        \"Windows\": '-G \"Visual Studio 15 2017\"',\n        \"Darwin\": '-G \"Xcode\"',\n        \"Linux\": '-G \"Ninja Multi-Config\"'\n    }.get(platform.system())\n\n    c.run_command(\"cmake . -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake {}\".format(generator))\n    c.run_command(\"cmake --build . --config Release\")\n    run_app = r\".\\Release\\app.exe\" if platform.system() == \"Windows\" else \"./Release/app\"\n    c.run_command(run_app)\n    assert \"matrix/1.0: Hello World Release!\" in c.out\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_map_imported_config(transitive_libraries):\n    # https://github.com/conan-io/conan/issues/12041\n    c = transitive_libraries\n\n    conanfile = textwrap.dedent(\"\"\"\n        [requires]\n        engine/1.0\n        [generators]\n        CMakeDeps\n        CMakeToolchain\n        \"\"\")\n\n    cmakelists = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.15)\n        project(app CXX)\n        set(CMAKE_MAP_IMPORTED_CONFIG_DEBUG Release)\n        find_package(engine REQUIRED)\n        add_executable(app main.cpp)\n        target_link_libraries(app engine::engine)\n        \"\"\")\n\n    c.save({\n        \"conanfile.txt\": conanfile,\n        \"main.cpp\": gen_function_cpp(name=\"main\", includes=[\"engine\"], calls=[\"engine\"]),\n        \"CMakeLists.txt\": cmakelists\n    }, clean_first=True)\n\n    c.run(\"install . -s build_type=Release\")\n    if platform.system() != \"Windows\":\n        c.run_command(\"cmake . -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake \"\n                      \"-DCMAKE_BUILD_TYPE=DEBUG\")\n        c.run_command(\"cmake --build .\")\n        c.run_command(\"./app\")\n    else:\n        c.run_command(\"cmake . -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake\")\n        c.run_command(\"cmake --build . --config Debug\")\n        c.run_command(\"Debug\\\\app.exe\")\n    assert \"matrix/1.0: Hello World Release!\" in c.out\n    assert \"engine/1.0: Hello World Release!\" in c.out\n    assert \"main: Debug!\" in c.out\n\n\n@pytest.mark.tool(\"cmake\", \"3.23\")\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Windows DLL specific\")\ndef test_cmake_target_runtime_dlls(transitive_libraries):\n    # https://github.com/conan-io/conan/issues/13504\n\n    c = transitive_libraries\n\n    c.run(\"new cmake_exe -d name=foo -d version=1.0 -d requires=engine/1.0 -f\")\n    cmakelists = textwrap.dedent(\"\"\"\n    set(CMAKE_CXX_COMPILER_WORKS 1)\n    set(CMAKE_CXX_ABI_COMPILED 1)\n    cmake_minimum_required(VERSION 3.15)\n    project(foo CXX)\n    find_package(engine CONFIG REQUIRED)\n    add_executable(foo src/foo.cpp src/main.cpp)\n    target_link_libraries(foo PRIVATE engine::engine)\n    # Make sure CMake copies DLLs from dependencies, next to the executable\n    # in this case it should copy engine.dll\n    add_custom_command(TARGET foo POST_BUILD\n        COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_RUNTIME_DLLS:foo> $<TARGET_FILE_DIR:foo>\n        COMMAND_EXPAND_LISTS)\n    \"\"\")\n    c.save({\"CMakeLists.txt\": cmakelists})\n    c.run('install . -s build_type=Release -o \"engine/*\":shared=True')\n    c.run_command(\"cmake -S . -B build/ \"\n                  \"-DCMAKE_TOOLCHAIN_FILE=build/generators/conan_toolchain.cmake\")\n    c.run_command(\"cmake --build build --config Release\")\n    c.run_command(\"build\\\\Release\\\\foo.exe\")\n\n    assert os.path.exists(os.path.join(c.current_folder, \"build\", \"Release\", \"engine.dll\"))\n    assert \"engine/1.0: Hello World Release!\" in c.out\n    # if the DLL wasn't copied, the application would not run and show output\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_quiet():\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Test(ConanFile):\n            name = \"test\"\n            version = \"0.1\"\n\n            def package_info(self):\n                self.cpp_info.system_libs = [\"lib1\"]\n        \"\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create .\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        [requires]\n        test/0.1\n\n        [generators]\n        CMakeDeps\n        \"\"\")\n    cmakelists = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(consumer NONE)\n        set(CMAKE_PREFIX_PATH ${CMAKE_BINARY_DIR})\n        set(CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR})\n        find_package(test QUIET)\n        \"\"\")\n\n    client.save({\"conanfile.txt\": conanfile,\n                 \"CMakeLists.txt\": cmakelists}, clean_first=True)\n    client.run(\"install .\")\n    client.run_command('cmake . -DCMAKE_BUILD_TYPE=Release')\n    # Because we used QUIET, not in output\n    assert \"Target declared 'test::test'\" not in client.out\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Only Windows and MSVC\")\n@pytest.mark.tool(\"meson\")\n@pytest.mark.tool(\"pkg_config\")\n@pytest.mark.tool(\"ninja\")\n@pytest.mark.tool(\"cmake\", \"3.23\")\ndef test_meson_and_cmakedeps_and_static_builds():\n    \"\"\"\n    Testing when library is built with Meson + MSVC as a static library (lib + name + .a)\n    and consumed using CMakeDeps (and CMakeConfigDeps) or PkgConfigDeps.\n\n    Issues related:\n        - https://github.com/conan-io/conan/issues/11866\n        - https://github.com/mesonbuild/meson/issues/7378\n    \"\"\"\n    client = TestClient()\n    profile = textwrap.dedent(\"\"\"\n    [settings]\n    os=Windows\n    arch=x86_64\n    compiler=msvc\n    compiler.version=191\n    compiler.runtime=dynamic\n    build_type=Release\n    \"\"\")\n    client.run(\"new meson_lib -d name=hello -d version=1.0\")\n    cmakelists = textwrap.dedent(\"\"\"\n    cmake_minimum_required(VERSION 3.15)\n    project(PackageTest CXX)\n\n    find_package(hello CONFIG REQUIRED)\n\n    add_executable(example src/example.cpp)\n    target_link_libraries(example hello::hello)\n    \"\"\")\n    cmake_conanfile = textwrap.dedent(\"\"\"\n    import os\n    from conan import ConanFile\n    from conan.tools.cmake import CMake, cmake_layout\n    from conan.tools.build import can_run\n    class pkgTestConan(ConanFile):\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n        generators = \"CMakeDeps\", \"CMakeToolchain\"\n\n        def requirements(self):\n            self.requires(self.tested_reference_str)\n\n        def build(self):\n            cmake = CMake(self)\n            cmake.configure()\n            cmake.build()\n\n        def layout(self):\n            cmake_layout(self)\n\n        def test(self):\n            if can_run(self):\n                cmd = os.path.join(self.cpp.build.bindir, \"example\")\n                self.run(cmd, env=\"conanrun\")\n        \"\"\")\n    client.save({\n        \"win\": profile,\n        \"test_package_cmake/conanfile.py\": cmake_conanfile,\n        \"test_package_cmake/CMakeLists.txt\": cmakelists\n    })\n    shutil.copytree(os.path.join(client.current_folder, \"test_package\", \"src\"),\n                    os.path.join(client.current_folder, \"test_package_cmake\", \"src\"))\n    client.run(\"create . -pr:a win\")  # meson + pkgconfigdeps (test_package) runs OK\n    # meson + CMakeDeps (test_package_cmake) runs OK\n    client.run(\"test --profile:all=win test_package_cmake hello/1.0\")\n    # Now, let's use the CMakeConfigDeps to demonstrate that it works with/without changing\n    replace_in_file(ConanFileMock(),\n                    os.path.join(client.current_folder, \"test_package_cmake\", \"conanfile.py\"),\n                    '\"CMakeDeps\"',\n                    '\"CMakeConfigDeps\"')\n    # meson + CMakeConfigDeps (test_package_cmake) runs OK\n    client.run(\"test --profile:all=win test_package_cmake hello/1.0 \"\n               \"-c tools.cmake.cmakedeps:new=will_break_next\")\n"
  },
  {
    "path": "test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_aggregator.py",
    "content": "import textwrap\n\nfrom conan.test.assets.sources import gen_function_cpp\n\n\ndef test_aggregator(transitive_libraries):\n    c = transitive_libraries\n\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.cmake import CMake, cmake_layout\n        class Pkg(ConanFile):\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            requires = \"engine/1.0\"\n            generators = \"CMakeDeps\", \"CMakeToolchain\"\n            exports_sources = \"*\"\n            def layout(self):\n                cmake_layout(self)\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n                self.run(os.path.join(self.cpp.build.bindir, \"app\"))\n        \"\"\")\n\n    cmakelists = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        project(app CXX)\n        include(${CMAKE_BINARY_DIR}/generators/conandeps_legacy.cmake)\n        add_executable(app main.cpp)\n        target_link_libraries(app ${CONANDEPS_LEGACY})\n        \"\"\")\n\n    c.save({\n        \"conanfile.py\": conanfile,\n        \"main.cpp\": gen_function_cpp(name=\"main\", includes=[\"engine\"], calls=[\"engine\"]),\n        \"CMakeLists.txt\": cmakelists\n    }, clean_first=True)\n    c.run(\"build .\")\n    assert \"matrix/1.0: Hello World Release!\" in c.out\n    assert \"engine/1.0: Hello World Release!\" in c.out\n"
  },
  {
    "path": "test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_aliases.py",
    "content": "import textwrap\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\nconsumer = textwrap.dedent(\"\"\"\nfrom conan import ConanFile\nfrom conan.tools.cmake import CMake\n\nclass Consumer(ConanFile):\n    name = \"consumer\"\n    version = \"1.0\"\n    settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n    generators = \"CMakeDeps\", \"CMakeToolchain\"\n    exports_sources = [\"CMakeLists.txt\"]\n    requires = \"hello/1.0\"\n\n    def build(self):\n        cmake = CMake(self)\n        cmake.configure()\n        cmake.build()\n\"\"\")\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_global_alias():\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n\n    class Hello(ConanFile):\n        name = \"hello\"\n        version = \"1.0\"\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n        def package_info(self):\n            # the default global target is \"hello::hello\"\n            self.cpp_info.set_property(\"cmake_target_aliases\", [\"hello\"])\n    \"\"\")\n\n    cmakelists = textwrap.dedent(\"\"\"\n    cmake_minimum_required(VERSION 3.15)\n    project(test NONE)\n\n    find_package(hello REQUIRED)\n    get_target_property(link_libraries hello INTERFACE_LINK_LIBRARIES)\n    message(\"hello link libraries: ${link_libraries}\")\n    \"\"\")\n\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create .\")\n\n    client.save({\"conanfile.py\": consumer, \"CMakeLists.txt\": cmakelists})\n    client.run(\"create .\")\n\n    assert \"hello link libraries: hello::hello\" in client.out\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_component_alias():\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n\n    class Hello(ConanFile):\n        name = \"hello\"\n        version = \"1.0\"\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n        def package_info(self):\n            self.cpp_info.components[\"buy\"].set_property(\"cmake_target_aliases\",\n                [\"hola::adios\"])\n    \"\"\")\n\n    cmakelists = textwrap.dedent(\"\"\"\n    cmake_minimum_required(VERSION 3.15)\n    project(test NONE)\n\n    find_package(hello REQUIRED)\n    get_target_property(link_libraries hola::adios INTERFACE_LINK_LIBRARIES)\n    message(\"hola::adios link libraries: ${link_libraries}\")\n    \"\"\")\n\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create .\")\n\n    client.save({\"conanfile.py\": consumer, \"CMakeLists.txt\": cmakelists})\n    client.run(\"create .\")\n\n    assert \"hola::adios link libraries: hello::buy\" in client.out\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_custom_name():\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n\n    class Hello(ConanFile):\n        name = \"hello\"\n        version = \"1.0\"\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n        def package_info(self):\n            self.cpp_info.set_property(\"cmake_target_name\", \"ola::comprar\")\n            self.cpp_info.set_property(\"cmake_target_aliases\", [\"hello\"])\n    \"\"\")\n\n    cmakelists = textwrap.dedent(\"\"\"\n    cmake_minimum_required(VERSION 3.15)\n    project(test NONE)\n\n    find_package(hello REQUIRED)\n    get_target_property(link_libraries hello INTERFACE_LINK_LIBRARIES)\n    message(\"hello link libraries: ${link_libraries}\")\n    \"\"\")\n\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create .\")\n\n    client.save({\"conanfile.py\": consumer, \"CMakeLists.txt\": cmakelists})\n    client.run(\"create .\")\n\n    assert \"hello link libraries: ola::comprar\" in client.out\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_collide_global_alias():\n    \"\"\"\n    FIXME: right now, having multiple aliases with same name doesn't emit any warning/error.\n    Possible alias collisions should be checked in CMakeDeps generator\n    \"\"\"\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n\n    class Hello(ConanFile):\n        name = \"hello\"\n        version = \"1.0\"\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n        def package_info(self):\n            # the default global target is \"hello::hello\"\n            self.cpp_info.set_property(\"cmake_target_aliases\", [\"hello::hello\"])\n    \"\"\")\n\n    cmakelists = textwrap.dedent(\"\"\"\n    cmake_minimum_required(VERSION 3.15)\n    project(test NONE)\n\n    find_package(hello REQUIRED)\n    \"\"\")\n\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create .\")\n\n    client.save({\"conanfile.py\": consumer, \"CMakeLists.txt\": cmakelists})\n    client.run(\"create .\")\n\n    # assert \"Target name 'hello::hello' already exists.\" in client.out\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_collide_component_alias():\n    \"\"\"\n    FIXME: right now, having multiple aliases with same name doesn't emit any warning/error.\n    Possible alias collisions should be checked in CMakeDeps generator\n    \"\"\"\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n\n    class Hello(ConanFile):\n        name = \"hello\"\n        version = \"1.0\"\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n        def package_info(self):\n            self.cpp_info.components[\"buy\"].set_property(\"cmake_target_aliases\", [\"hello::buy\"])\n    \"\"\")\n\n    cmakelists = textwrap.dedent(\"\"\"\n    cmake_minimum_required(VERSION 3.15)\n    project(test NONE)\n\n    find_package(hello REQUIRED)\n    \"\"\")\n\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create .\")\n\n    client.save({\"conanfile.py\": consumer, \"CMakeLists.txt\": cmakelists})\n    client.run(\"create .\")\n\n    # assert \"Target name 'hello::buy' already exists.\" in client.out\n"
  },
  {
    "path": "test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_and_linker_flags.py",
    "content": "import os\nimport platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.sources import gen_function_cpp, gen_function_h\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.skipif(platform.system() != \"Linux\", reason=\"Only Linux\")\n@pytest.mark.tool(\"cmake\")\ndef test_shared_link_flags():\n    \"\"\"\n    Testing CMakeDeps and linker flags injection\n\n    Issue: https://github.com/conan-io/conan/issues/9936\n    \"\"\"\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    from conan.tools.cmake import CMake, cmake_layout\n\n\n    class HelloConan(ConanFile):\n        name = \"hello\"\n        version = \"1.0\"\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n        options = {\"shared\": [True, False]}\n        default_options = {\"shared\": False}\n        exports_sources = \"CMakeLists.txt\", \"src/*\", \"include/*\"\n        generators = \"CMakeDeps\", \"CMakeToolchain\"\n\n        def layout(self):\n            cmake_layout(self)\n\n        def build(self):\n            cmake = CMake(self)\n            cmake.configure()\n            cmake.build()\n\n        def package(self):\n            cmake = CMake(self)\n            cmake.install()\n\n        def package_info(self):\n            self.cpp_info.libs = [\"hello\"]\n            self.cpp_info.sharedlinkflags = [\"-z now\", \"-z relro\"]\n            self.cpp_info.exelinkflags = [\"-z now\", \"-z relro\"]\n    \"\"\")\n\n    client = TestClient()\n    client.run(\"new cmake_lib -d name=hello -d version=1.0\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create .\")\n    host_arch = client.get_default_host_profile().settings['arch']\n    build_folder = client.created_test_build_folder(\"hello/1.0\")\n    t = os.path.join(\"test_package\", build_folder, \"generators\",\n                     f\"hello-release-{host_arch}-data.cmake\")\n    target_data_cmake_content = client.load(t)\n    assert 'set(hello_SHARED_LINK_FLAGS_RELEASE \"-z now;-z relro\")' in target_data_cmake_content\n    assert 'set(hello_EXE_LINK_FLAGS_RELEASE \"-z now;-z relro\")' in target_data_cmake_content\n    assert \"hello/1.0: Hello World Release!\" in client.out\n\n\ndef test_not_mixed_configurations():\n    # https://github.com/conan-io/conan/issues/11852\n\n    client = TestClient()\n    client.run(\"new cmake_lib -d name=foo  -d version=1.0\")\n\n    conanfile = client.load(\"conanfile.py\")\n    conanfile.replace(\"package_info(self)\", \"invalid(self)\")\n    conanfile += \"\"\"\n    def package_info(self):\n        self.cpp_info.libs = [\"foo\" if self.settings.build_type == \"Release\" else \"foo_d\"]\n    \"\"\"\n\n    cmake = textwrap.dedent(\"\"\"\n            set(CMAKE_CXX_COMPILER_WORKS 1)\n            set(CMAKE_CXX_ABI_COMPILED 1)\n            cmake_minimum_required(VERSION 3.15)\n            project(foo CXX)\n\n            add_library(foo \"src/foo.cpp\")\n            target_include_directories(foo PUBLIC include)\n            set_target_properties(foo PROPERTIES PUBLIC_HEADER \"include/foo.h\")\n\n            # Different name for Release or Debug\n            set_target_properties(foo PROPERTIES OUTPUT_NAME_DEBUG foo_d)\n            set_target_properties(foo PROPERTIES OUTPUT_NAME_RELEASE foo)\n            install(TARGETS foo)\n    \"\"\")\n\n    client.save({\"CMakeLists.txt\": cmake, \"conanfile.py\": conanfile})\n    client.run(\"create .\")\n    client.run(\"create . -s build_type=Debug\")\n    if platform.system() != \"Windows\":\n        assert \"libfoo_d.a\" in client.out  # Just to make sure we built the foo_d\n\n    # Now create a consumer of foo with CMakeDeps locally\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout\n\n        class ConsumerConan(ConanFile):\n            name = \"consumer\"\n            version = \"1.0\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            requires = \"foo/1.0\"\n            generators = \"CMakeDeps\"\n\n            def layout(self):\n                cmake_layout(self)\n\n            def generate(self):\n                tc = CMakeToolchain(self)\n                tc.cache_variables[\"CMAKE_VERBOSE_MAKEFILE:BOOL\"] = \"ON\"\n                tc.generate()\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n\n            \"\"\")\n    cmake = textwrap.dedent(\"\"\"\n            set(CMAKE_CXX_COMPILER_WORKS 1)\n            set(CMAKE_CXX_ABI_COMPILED 1)\n            cmake_minimum_required(VERSION 3.15)\n            project(consumer CXX)\n\n            find_package(foo)\n\n            add_executable(consumer src/consumer.cpp)\n            target_include_directories(consumer PUBLIC include)\n            target_link_libraries(consumer foo::foo)\n\n            set_target_properties(consumer PROPERTIES PUBLIC_HEADER \"include/consumer.h\")\"\"\")\n    consumer_cpp = gen_function_cpp(name=\"main\", includes=[\"foo\"], calls=[\"foo\"])\n    consumer_h = gen_function_h(name=\"consumer\")\n\n    client.save({\"conanfile.py\": conanfile, \"CMakeLists.txt\": cmake,\n                 \"src/consumer.cpp\": consumer_cpp, \"src/consumer.h\": consumer_h})\n\n    client.run(\"install . -s build_type=Debug\")\n    client.run(\"install . -s build_type=Release\")\n    # With the bug, this build only fail on windows\n    client.run(\"build .\")\n\n    # But we inspect the output for Macos/Linux to check that the library is not linked\n    if platform.system() != \"Windows\":\n        assert \"libfoo_d.a\" not in client.out\n        assert \"libfoo.a\" in client.out\n"
  },
  {
    "path": "test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_build_modules.py",
    "content": "import textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_build_modules_alias_target():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import copy\n\n        class Conan(ConanFile):\n            name = \"hello\"\n            version = \"1.0\"\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            exports_sources = [\"target-alias.cmake\"]\n\n            def package(self):\n                copy(self, \"target-alias.cmake\", self.source_folder,\n                     os.path.join(self.package_folder, \"share/cmake\"))\n\n            def package_info(self):\n                module = os.path.join(\"share\", \"cmake\", \"target-alias.cmake\")\n                self.cpp_info.set_property(\"cmake_build_modules\", [module])\n        \"\"\")\n\n    target_alias = textwrap.dedent(\"\"\"\n        add_library(otherhello INTERFACE IMPORTED)\n        target_link_libraries(otherhello INTERFACE hello::hello)\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile, \"target-alias.cmake\": target_alias})\n    client.run(\"create .\")\n\n    consumer = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n\n        class Conan(ConanFile):\n            name = \"consumer\"\n            version = \"1.0\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            exports_sources = [\"CMakeLists.txt\"]\n            generators = \"CMakeDeps\", \"CMakeToolchain\"\n            requires = \"hello/1.0\"\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n        \"\"\")\n    cmakelists = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.0)\n        project(test NONE)\n        find_package(hello CONFIG)\n        get_target_property(tmp otherhello INTERFACE_LINK_LIBRARIES)\n        message(\"otherhello link libraries: ${tmp}\")\n        \"\"\")\n    client.save({\"conanfile.py\": consumer, \"CMakeLists.txt\": cmakelists})\n    client.run(\"create .\")\n    assert \"otherhello link libraries: hello::hello\" in client.out\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_build_modules_custom_script():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import copy\n\n        class Conan(ConanFile):\n            name = \"myfunctions\"\n            version = \"1.0\"\n            exports_sources = [\"*.cmake\"]\n\n            def package(self):\n                copy(self, \"*.cmake\", self.source_folder, self.package_folder)\n\n            def package_info(self):\n                self.cpp_info.set_property(\"cmake_build_modules\", [\"myfunction.cmake\"])\n        \"\"\")\n\n    myfunction = textwrap.dedent(\"\"\"\n        function(myfunction)\n            message(\"Hello myfunction!!!!\")\n        endfunction()\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile, \"myfunction.cmake\": myfunction})\n    client.run(\"create .\")\n\n    consumer = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake, CMakeDeps\n\n        class Conan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"CMakeToolchain\"\n            tool_requires = \"myfunctions/1.0\"\n\n            def generate(self):\n                deps = CMakeDeps(self)\n                deps.build_context_activated = [\"myfunctions\"]\n                deps.build_context_build_modules = [\"myfunctions\"]\n                deps.set_property(\"myfunctions\", \"cmake_find_mode\", \"module\", build_context=True)\n                deps.generate()\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n        \"\"\")\n    cmakelists = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.0)\n        project(test NONE)\n        find_package(myfunctions MODULE REQUIRED)\n        myfunction()\n        \"\"\")\n    client.save({\"conanfile.py\": consumer,\n                 \"CMakeLists.txt\": cmakelists},\n                clean_first=True)\n    client.run(\"build .\")\n    assert \"Hello myfunction!!!!\" in client.out\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_build_modules_components_is_not_possible():\n    \"\"\"\n    The \"cmake_build_module\" property declared in the components is useless\n    \"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import copy\n\n        class Conan(ConanFile):\n            name = \"openssl\"\n            version = \"1.0\"\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            exports_sources = [\"crypto.cmake\", \"root.cmake\"]\n\n            def package(self):\n                copy(self, \"*.cmake\", self.source_folder, os.path.join(self.package_folder, \"share/cmake\"))\n\n            def package_info(self):\n                crypto_module = os.path.join(\"share\", \"cmake\", \"crypto.cmake\")\n                self.cpp_info.components[\"crypto\"].set_property(\"cmake_build_modules\", [crypto_module])\n\n                root_module = os.path.join(\"share\", \"cmake\", \"root.cmake\")\n                self.cpp_info.set_property(\"cmake_build_modules\", [root_module])\n        \"\"\")\n\n    crypto_cmake = textwrap.dedent(\"\"\"\n        function(crypto_message MESSAGE_OUTPUT)\n            message(\"CRYPTO MESSAGE:${ARGV${0}}\")\n        endfunction()\n        \"\"\")\n    root_cmake = textwrap.dedent(\"\"\"\n        function(root_message MESSAGE_OUTPUT)\n            message(\"ROOT MESSAGE:${ARGV${0}}\")\n        endfunction()\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile,\n                 \"crypto.cmake\": crypto_cmake,\n                 \"root.cmake\": root_cmake})\n    client.run(\"create .\")\n\n    consumer = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n\n        class Conan(ConanFile):\n            name = \"consumer\"\n            version = \"1.0\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            exports_sources = [\"CMakeLists.txt\"]\n            generators = \"CMakeDeps\", \"CMakeToolchain\"\n            requires = \"openssl/1.0\"\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n\n            def package_info(self):\n                self.cpp_info.requires = [\"openssl::crypto\"]\n        \"\"\")\n\n    cmakelists = textwrap.dedent(\"\"\"\n            cmake_minimum_required(VERSION 3.0)\n            project(test NONE)\n            find_package(openssl CONFIG)\n            crypto_message(\"hello!\")\n            root_message(\"hello!\")\n            \"\"\")\n    client.save({\"conanfile.py\": consumer, \"CMakeLists.txt\": cmakelists})\n    # As we are requiring only \"crypto\" but it doesn't matter, it is not possible to include\n    # only crypto build_modules\n    client.run(\"create .\", assert_error=True)\n    assert 'Unknown CMake command \"crypto_message\"' in client.out\n\n    # Comment the function call\n    client.save({\"CMakeLists.txt\": cmakelists.replace(\"crypto\", \"#crypto\")})\n    assert \"ROOT MESSAGE:hello!\" not in client.out\n\n\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.parametrize(\"editable\", [True, False])\ndef test_build_modules_custom_script_editable(editable):\n    c = TestClient()\n    conanfile = textwrap.dedent(r\"\"\"\n        import os, glob\n        from conan import ConanFile\n        from conan.tools.cmake import cmake_layout\n        from conan.tools.files import copy, save\n\n        class Conan(ConanFile):\n            name = \"myfunctions\"\n            version = \"1.0\"\n            exports_sources = [\"src/*.cmake\"]\n            settings = \"build_type\", \"arch\"\n\n            def build(self):\n                cmake = 'set(MY_CMAKE_PATH ${CMAKE_CURRENT_LIST_DIR})\\n'\\\n                        'macro(otherfunc)\\n'\\\n                        'file(READ \"${MY_CMAKE_PATH}/my.txt\" c)\\n'\\\n                        'message(\"Hello ${c}!!!!\")\\nendmacro()'\n                save(self, \"otherfuncs.cmake\", cmake)\n                save(self, \"my.txt\", \"contents of text file!!!!\")\n\n            def layout(self):\n                cmake_layout(self, src_folder=\"src\")\n                src = glob.glob(os.path.join(self.recipe_folder, self.folders.source, \"*.cmake\"))\n                build = glob.glob(os.path.join(self.recipe_folder, self.folders.build, \"*.cmake\"))\n                self.cpp.source.set_property(\"cmake_build_modules\", src)\n                self.cpp.build.set_property(\"cmake_build_modules\", build)\n\n            def package(self):\n                copy(self, \"*.cmake\", self.source_folder, os.path.join(self.package_folder, \"mods\"),\n                     keep_path=False)\n                copy(self, \"*.cmake\", self.build_folder, os.path.join(self.package_folder, \"mods\"),\n                     keep_path=False)\n                copy(self, \"*.txt\", self.build_folder, os.path.join(self.package_folder, \"mods\"),\n                     keep_path=False)\n\n            def package_info(self):\n                self.cpp_info.set_property(\"cmake_build_modules\", glob.glob(\"mods/*.cmake\"))\n        \"\"\")\n\n    myfunction = textwrap.dedent(\"\"\"\n        function(myfunction)\n            message(\"Hello myfunction!!!!\")\n        endfunction()\n        \"\"\")\n\n    consumer = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n\n        class Conan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"CMakeToolchain\", \"CMakeDeps\"\n            requires = \"myfunctions/1.0\"\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n        \"\"\")\n    cmakelists = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(test NONE)\n        find_package(myfunctions CONFIG REQUIRED)\n        myfunction()\n        otherfunc()\n        \"\"\")\n    c.save({\"functions/conanfile.py\": conanfile,\n            \"functions/src/myfunction.cmake\": myfunction,\n            \"app/conanfile.py\": consumer,\n            \"app/CMakeLists.txt\": cmakelists})\n\n    if editable:\n        c.run(\"editable add functions\")\n        c.run('build functions -c tools.cmake.cmake_layout:build_folder_vars=\"[\\'settings.arch\\']\"')\n    else:\n        c.run(\"create functions\")\n    c.run('build app -c tools.cmake.cmake_layout:build_folder_vars=\"[\\'settings.arch\\']\"')\n    assert \"Hello myfunction!!!!\" in c.out\n    assert \"Hello contents of text file!!!!\" in c.out\n\n\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.parametrize(\"editable\", [True, False])\ndef test_build_modules_custom_script_editable_package(editable):\n    # same as above, but with files from the package folder\n    c = TestClient()\n    conanfile = textwrap.dedent(r\"\"\"\n        import os, glob\n        from conan import ConanFile\n        from conan.tools.cmake import cmake_layout\n        from conan.tools.files import copy, save\n\n        class Conan(ConanFile):\n            name = \"myfunctions\"\n            version = \"1.0\"\n            exports_sources = [\"src/*.cmake\", \"src/vis/*.vis\"]\n            settings = \"build_type\", \"arch\"\n\n            def build(self):\n                config = str(self.settings.build_type).upper()\n                cmake = f'set(MY_CMAKE_PATH ${{{self.name}_RES_DIRS_{config}}})\\n'\\\n                        'macro(otherfunc)\\n'\\\n                        'file(READ \"${MY_CMAKE_PATH}/my.vis\" c)\\n'\\\n                        'message(\"Hello ${c}!!!!\")\\nendmacro()'\n                save(self, \"otherfuncs.cmake\", cmake)\n\n            def layout(self):\n                cmake_layout(self, src_folder=\"src\")\n                src = glob.glob(os.path.join(self.recipe_folder, self.folders.source, \"*.cmake\"))\n                build = glob.glob(os.path.join(self.recipe_folder, self.folders.build, \"*.cmake\"))\n                self.cpp.source.set_property(\"cmake_build_modules\", src)\n                self.cpp.build.set_property(\"cmake_build_modules\", build)\n                self.cpp.source.resdirs = [\"vis\"]\n\n            def package(self):\n                copy(self, \"*.cmake\", self.source_folder, os.path.join(self.package_folder, \"mods\"),\n                     keep_path=False)\n                copy(self, \"*.cmake\", self.build_folder, os.path.join(self.package_folder, \"mods\"),\n                     keep_path=False)\n                copy(self, \"*.vis\", self.source_folder, os.path.join(self.package_folder, \"mods\"),\n                     keep_path=False)\n\n            def package_info(self):\n                self.cpp_info.resdirs = [\"mods\"]\n                self.cpp_info.set_property(\"cmake_build_modules\", glob.glob(\"mods/*.cmake\"))\n        \"\"\")\n\n    myfunction = textwrap.dedent(\"\"\"\n        function(myfunction)\n            message(\"Hello myfunction!!!!\")\n        endfunction()\n        \"\"\")\n\n    consumer = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n\n        class Conan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"CMakeToolchain\", \"CMakeDeps\"\n            requires = \"myfunctions/1.0\"\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n        \"\"\")\n    cmakelists = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(test NONE)\n        find_package(myfunctions CONFIG REQUIRED)\n        myfunction()\n        otherfunc()\n        \"\"\")\n    c.save({\"functions/conanfile.py\": conanfile,\n            \"functions/src/myfunction.cmake\": myfunction,\n            \"functions/src/vis/my.vis\": \"contents of text file!!!!\",\n            \"app/conanfile.py\": consumer,\n            \"app/CMakeLists.txt\": cmakelists})\n\n    if editable:\n        c.run(\"editable add functions\")\n        c.run('build functions -c tools.cmake.cmake_layout:build_folder_vars=\"[\\'settings.arch\\']\"')\n    else:\n        c.run(\"create functions -vv\")\n    c.run('build app -c tools.cmake.cmake_layout:build_folder_vars=\"[\\'settings.arch\\']\"')\n    assert \"Hello myfunction!!!!\" in c.out\n    assert \"Hello contents of text file!!!!\" in c.out\n"
  },
  {
    "path": "test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_components.py",
    "content": "import textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestPropagateSpecificComponents:\n    \"\"\"\n        Feature: recipes can declare the components they are consuming from their requirements,\n        only those components should be propagated to their own consumers. If required components\n        doesn't exist, Conan will fail:\n         * Resolved versions/revisions of the requirement might provide different components or\n           no components at all.\n    \"\"\"\n\n    top = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Recipe(ConanFile):\n            name = \"top\"\n\n            def package_info(self):\n                self.cpp_info.components[\"cmp1\"].libs = [\"top_cmp1\"]\n                self.cpp_info.components[\"cmp2\"].libs = [\"top_cmp2\"]\n    \"\"\")\n\n    middle = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Recipe(ConanFile):\n            name = \"middle\"\n            requires = \"top/version\"\n            def package_info(self):\n                self.cpp_info.requires = [\"top::cmp1\"]\n    \"\"\")\n\n    app = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Recipe(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            name = \"app\"\n            requires = \"middle/version\"\n        \"\"\")\n\n    @pytest.fixture(autouse=True)\n    def setup(self):\n        client = TestClient()\n        client.save({\n            'top.py': self.top,\n            'middle.py': self.middle,\n            'app.py': self.app\n        })\n        client.run('create top.py --name=top --version=version')\n        client.run('create middle.py --name=middle --version=version')\n        self.cache_folder = client.cache_folder\n\n    def test_cmakedeps_app(self):\n        t = TestClient(cache_folder=self.cache_folder)\n        t.save({'conanfile.py': self.app})\n        t.run(\"install .  -g CMakeDeps\")\n        config = t.load(\"middle-Target-release.cmake\")\n        assert 'top::cmp1' in config\n        assert \"top::top\" not in config\n\n    def test_cmakedeps_multi(self):\n        t = TestClient(cache_folder=self.cache_folder)\n        t.run('install --requires=middle/version@ -g CMakeDeps')\n        host_arch = t.get_default_host_profile().settings['arch']\n\n        content = t.load(f'middle-release-{host_arch}-data.cmake')\n        assert \"list(APPEND middle_FIND_DEPENDENCY_NAMES top)\" in content\n\n        content = t.load('middle-Target-release.cmake')\n        assert \"top::top\" not in content\n        assert \"top::cmp2\" not in content\n        assert \"top::cmp1\" in content\n\n\n@pytest.fixture\ndef top_conanfile():\n    return textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Recipe(ConanFile):\n\n            def package_info(self):\n                self.cpp_info.components[\"cmp1\"].libs = [\"top_cmp1\"]\n                self.cpp_info.components[\"cmp2\"].libs = [\"top_cmp2\"]\n    \"\"\")\n\n\n@pytest.mark.parametrize(\"from_component\", [False, True])\ndef test_wrong_component(top_conanfile, from_component):\n    \"\"\" If the requirement doesn't provide the component, it fails.\n        We can only raise this error after the graph is fully resolved, it is when we\n        know the actual components that the requirement is going to provide.\n    \"\"\"\n    # TODO: This test is specific of CMakeDeps, could be made general?\n    consumer = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Recipe(ConanFile):\n            requires = \"top/version\"\n            def package_info(self):\n                self.cpp_info.{}requires = [\"top::not-existing\"]\n    \"\"\").format(\"components['foo'].\" if from_component else \"\")\n\n    t = TestClient()\n    t.save({'top.py': top_conanfile, 'consumer.py': consumer})\n    t.run('create top.py --name=top --version=version')\n    t.run('create consumer.py --name=wrong --version=version')\n\n    t.run('install --requires=wrong/version@ -g CMakeDeps', assert_error=True)\n    assert \"Component 'top::not-existing' not found in 'top' package requirement\" in t.out\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_components_system_libs():\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Requirement(ConanFile):\n            name = \"requirement\"\n            version = \"system\"\n\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n\n            def package_info(self):\n                self.cpp_info.components[\"component\"].system_libs = [\"system_lib_component\"]\n    \"\"\")\n    t = TestClient()\n    t.save({\"conanfile.py\": conanfile})\n    t.run(\"create .\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n\n        class Consumer(ConanFile):\n            name = \"consumer\"\n            version = \"0.1\"\n            requires = \"requirement/system\"\n            generators = \"CMakeDeps\", \"CMakeToolchain\"\n            exports_sources = \"CMakeLists.txt\"\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n    \"\"\")\n\n    cmakelists = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(consumer NONE)\n\n        find_package(requirement)\n        get_target_property(tmp_libs requirement::component INTERFACE_LINK_LIBRARIES)\n        get_target_property(tmp_options requirement::component INTERFACE_LINK_OPTIONS)\n        get_target_property(tmp_deps requirement_requirement_component_DEPS_TARGET\n                            INTERFACE_LINK_LIBRARIES)\n        message(\"component libs: ${tmp_libs}\")\n        message(\"component options: ${tmp_options}\")\n        message(\"component deps: ${tmp_deps}\")\n    \"\"\")\n\n    t.save({\"conanfile.py\": conanfile, \"CMakeLists.txt\": cmakelists})\n    t.run(\"create . --build missing -s build_type=Release\")\n    assert ('component libs: $<$<CONFIG:Release>:>;$<$<CONFIG:Release>:>;'\n            'requirement_requirement_component_DEPS_TARGET') in t.out\n    assert ('component deps: $<$<CONFIG:Release>:>;$<$<CONFIG:Release>:'\n            'system_lib_component>;') in t.out\n    assert ('component options: '\n            '$<$<CONFIG:Release>:'\n            '$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,SHARED_LIBRARY>:>;'\n            '$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,MODULE_LIBRARY>:>;'\n            '$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:>>') in t.out\n    # NOTE: If there is no \"conan install -s build_type=Debug\", the properties won't contain the\n    #       <CONFIG:Debug>\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_components_exelinkflags():\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Requirement(ConanFile):\n            name = \"requirement\"\n            version = \"system\"\n\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n\n            def package_info(self):\n                self.cpp_info.components[\"component\"].exelinkflags = [\"-Wl,-link1\", \"-Wl,-link2\"]\n    \"\"\")\n    t = TestClient()\n    t.save({\"conanfile.py\": conanfile})\n    t.run(\"create .\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n\n        class Consumer(ConanFile):\n            name = \"consumer\"\n            version = \"0.1\"\n            requires = \"requirement/system\"\n            generators = \"CMakeDeps\", \"CMakeToolchain\"\n            exports_sources = \"CMakeLists.txt\"\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n    \"\"\")\n\n    cmakelists = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(consumer NONE)\n        find_package(requirement)\n        get_target_property(tmp_options requirement::component INTERFACE_LINK_OPTIONS)\n        message(\"component options: ${tmp_options}\")\n    \"\"\")\n\n    t.save({\"conanfile.py\": conanfile, \"CMakeLists.txt\": cmakelists})\n    t.run(\"create . --build missing -s build_type=Release\")\n    assert ('component options: '\n            '$<$<CONFIG:Release>:'\n            '$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,SHARED_LIBRARY>:>;'\n            '$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,MODULE_LIBRARY>:>;'\n            '$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:-Wl,-link1;-Wl,-link2>>') in t.out\n    # NOTE: If there is no \"conan install -s build_type=Debug\", the properties won't contain the\n    #       <CONFIG:Debug>\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_components_sharedlinkflags():\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Requirement(ConanFile):\n            name = \"requirement\"\n            version = \"system\"\n\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n\n            def package_info(self):\n                self.cpp_info.components[\"component\"].sharedlinkflags = [\"-Wl,-link1\", \"-Wl,-link2\"]\n    \"\"\")\n    t = TestClient()\n    t.save({\"conanfile.py\": conanfile})\n    t.run(\"create .\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n\n        class Consumer(ConanFile):\n            name = \"consumer\"\n            version = \"0.1\"\n            requires = \"requirement/system\"\n            generators = \"CMakeDeps\", \"CMakeToolchain\"\n            exports_sources = \"CMakeLists.txt\"\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n    \"\"\")\n\n    cmakelists = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(consumer NONE)\n        find_package(requirement)\n        get_target_property(tmp_options requirement::component INTERFACE_LINK_OPTIONS)\n        message(\"component options: ${tmp_options}\")\n    \"\"\")\n\n    t.save({\"conanfile.py\": conanfile, \"CMakeLists.txt\": cmakelists})\n    t.run(\"create . --build missing -s build_type=Release\")\n    assert ('component options: '\n            '$<$<CONFIG:Release>:'\n            '$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,SHARED_LIBRARY>:-Wl,-link1;-Wl,-link2>;'\n            '$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,MODULE_LIBRARY>:-Wl,-link1;-Wl,-link2>;'\n            '$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:>>') in t.out\n    # NOTE: If there is no \"conan install -s build_type=Debug\", the properties won't contain the\n    #       <CONFIG:Debug>\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_cmake_add_subdirectory():\n    \"\"\"https://github.com/conan-io/conan/issues/11743\n       https://github.com/conan-io/conan/issues/11755\"\"\"\n\n    t = TestClient()\n    boost = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Consumer(ConanFile):\n            name = \"boost\"\n            version = \"1.0\"\n\n            def package_info(self):\n                self.cpp_info.set_property(\"cmake_file_name\", \"Boost\")\n                self.cpp_info.components[\"A\"].system_libs = [\"A_1\", \"A_2\"]\n                self.cpp_info.components[\"B\"].system_libs = [\"B_1\", \"B_2\"]\n    \"\"\")\n    t.save({\"conanfile.py\": boost})\n    t.run(\"create .\")\n    conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.cmake import CMake, cmake_layout\n\n            class Consumer(ConanFile):\n                name = \"consumer\"\n                version = \"0.1\"\n                requires = \"boost/1.0\"\n                generators = \"CMakeDeps\", \"CMakeToolchain\"\n                settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n\n                def layout(self):\n                    cmake_layout(self)\n\n                def build(self):\n                    cmake = CMake(self)\n                    cmake.configure()\n        \"\"\")\n\n    cmakelists = textwrap.dedent(\"\"\"\n            cmake_minimum_required(VERSION 3.15)\n            project(hello NONE)\n            find_package(Boost CONFIG)\n            add_subdirectory(src)\n\n    \"\"\")\n    sub_cmakelists = textwrap.dedent(\"\"\"\n            find_package(Boost REQUIRED COMPONENTS exception headers)\n\n            message(\"AGGREGATED LIBS: ${Boost_LIBRARIES}\")\n            get_target_property(tmp boost::boost INTERFACE_LINK_LIBRARIES)\n            message(\"AGGREGATED LINKED: ${tmp}\")\n\n            get_target_property(tmp boost::B INTERFACE_LINK_LIBRARIES)\n            message(\"BOOST_B LINKED: ${tmp}\")\n\n            get_target_property(tmp boost::A INTERFACE_LINK_LIBRARIES)\n            message(\"BOOST_A LINKED: ${tmp}\")\n\n            get_target_property(tmp boost_boost_B_DEPS_TARGET INTERFACE_LINK_LIBRARIES)\n            message(\"BOOST_B_DEPS LINKED: ${tmp}\")\n\n            get_target_property(tmp boost_boost_A_DEPS_TARGET INTERFACE_LINK_LIBRARIES)\n            message(\"BOOST_A_DEPS LINKED: ${tmp}\")\n\n    \"\"\")\n\n    t.save({\"conanfile.py\": conanfile,\n            \"CMakeLists.txt\": cmakelists, \"src/CMakeLists.txt\": sub_cmakelists})\n    t.run(\"install .\")\n    # only doing the configure failed before #11743 fix\n    t.run(\"build .\")\n    # The boost::boost target has linked the two components\n    assert \"AGGREGATED LIBS: boost::boost\" in t.out\n    assert \"AGGREGATED LINKED: boost::B;boost::A\" in t.out\n    assert (\"BOOST_B LINKED: $<$<CONFIG:Release>:>;$<$<CONFIG:Release>:>;\"\n            \"boost_boost_B_DEPS_TARGET\") in t.out\n    assert (\"BOOST_A LINKED: $<$<CONFIG:Release>:>;$<$<CONFIG:Release>:>;\"\n            \"boost_boost_A_DEPS_TARGET\") in t.out\n    assert \"BOOST_B_DEPS LINKED: $<$<CONFIG:Release>:>;$<$<CONFIG:Release>:B_1;B_2>\" in t.out\n    assert \"BOOST_A_DEPS LINKED: $<$<CONFIG:Release>:>;$<$<CONFIG:Release>:A_1;A_2>;\" in t.out\n"
  },
  {
    "path": "test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_components_names.py",
    "content": "import os\nimport shutil\nimport textwrap\n\nimport pytest\n\nfrom conan.api.model import RecipeReference\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.assets.sources import gen_function_h, gen_function_cpp\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.tool(\"cmake\")\n@pytest.fixture(scope=\"module\")\ndef setup_client_with_greetings():\n    \"\"\"\n    creates a multi-component package with 2 components \"hello\" and \"bye\n    \"\"\"\n    hello_h = gen_function_h(name=\"hello\")\n    hello_cpp = gen_function_cpp(name=\"hello\", includes=[\"hello\"])\n    bye_h = gen_function_h(name=\"bye\")\n    bye_cpp = gen_function_cpp(name=\"bye\", includes=[\"bye\"])\n\n    conanfile_greetings = textwrap.dedent(\"\"\"\n        from os.path import join\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n        from conan.tools.files import copy\n\n        class GreetingsConan(ConanFile):\n            name = \"greetings\"\n            version = \"0.0.1\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"CMakeDeps\", \"CMakeToolchain\"\n            exports_sources = \"src/*\"\n            options = {\"components\": [\"standard\", \"custom\", \"none\"]}\n            default_options = {\"components\": \"standard\"}\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure(build_script_folder=\"src\")\n                cmake.build()\n\n            def package(self):\n                copy(self, \"*.h\", src=join(self.source_folder, \"src\"),\n                                  dst=join(self.package_folder, \"include\"))\n                copy(self, \"*.lib\", src=self.build_folder,\n                                    dst=join(self.package_folder, \"lib\"), keep_path=False)\n                copy(self, \"*.a\", src=self.build_folder,\n                                  dst=join(self.package_folder, \"lib\"), keep_path=False)\n\n            def package_info(self):\n                def set_comp_default_dirs():\n                    self.cpp_info.components[\"hello\"].includedirs = [\"include\"]\n                    self.cpp_info.components[\"hello\"].libdirs = [\"lib\"]\n                    self.cpp_info.components[\"bye\"].includedirs = [\"include\"]\n                    self.cpp_info.components[\"bye\"].libdirs = [\"lib\"]\n\n                if self.options.components == \"standard\":\n                    self.cpp_info.components[\"hello\"].libs = [\"hello\"]\n                    self.cpp_info.components[\"bye\"].libs = [\"bye\"]\n                    set_comp_default_dirs()\n\n                elif self.options.components == \"custom\":\n                    self.cpp_info.set_property(\"cmake_file_name\", \"MYG\")\n                    self.cpp_info.set_property(\"cmake_target_name\", \"MyGreetings::MyGreetings\")\n\n                    self.cpp_info.components[\"hello\"].set_property(\"cmake_target_name\", \"MyGreetings::MyHello\")\n                    self.cpp_info.components[\"bye\"].set_property(\"cmake_target_name\", \"MyGreetings::MyBye\")\n\n                    self.cpp_info.components[\"hello\"].libs = [\"hello\"]\n                    self.cpp_info.components[\"bye\"].libs = [\"bye\"]\n\n                    set_comp_default_dirs()\n                else:\n                    self.cpp_info.libs = [\"hello\", \"bye\"]\n\n            def package_id(self):\n                del self.info.options.components\n        \"\"\")\n\n    cmakelists_greetings = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.0)\n        project(greetings CXX)\n\n        add_library(hello hello.cpp)\n        add_library(bye bye.cpp)\n        \"\"\")\n\n    test_package_greetings_conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n\n        class GreetingsTestConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"CMakeDeps\", \"CMakeToolchain\"\n\n            def requirements(self):\n                self.requires(self.tested_reference_str)\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n\n            def test(self):\n                path = \"{}\".format(self.settings.build_type) if self.settings.os == \"Windows\" else \".\"\n                self.run(\"{}{}example\".format(path, os.sep))\n        \"\"\")\n    test_package_greetings_cpp = gen_function_cpp(name=\"main\", includes=[\"hello\", \"bye\"],\n                                                  calls=[\"hello\", \"bye\"])\n\n    test_package_greetings_cmakelists = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.0)\n        project(PackageTest CXX)\n\n        find_package(greetings)\n\n        add_executable(example example.cpp)\n        target_link_libraries(example greetings::greetings)\n        \"\"\")\n\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile_greetings,\n                 \"src/CMakeLists.txt\": cmakelists_greetings,\n                 \"src/hello.h\": hello_h,\n                 \"src/hello.cpp\": hello_cpp,\n                 \"src/bye.h\": bye_h,\n                 \"src/bye.cpp\": bye_cpp,\n                 \"test_package/conanfile.py\": test_package_greetings_conanfile,\n                 \"test_package/example.cpp\": test_package_greetings_cpp,\n                 \"test_package/CMakeLists.txt\": test_package_greetings_cmakelists})\n    client.run(\"create . -s build_type=Release\")\n    assert \"hello: Release!\" in client.out\n    assert \"bye: Release!\" in client.out\n    client.run(\"create . -s build_type=Debug\")\n    assert \"hello: Debug!\" in client.out\n    assert \"bye: Debug!\" in client.out\n    return client\n\n\ndef create_chat(client, components, package_info, cmake_find, test_cmake_find):\n    conanfile = textwrap.dedent(\"\"\"\n        from os.path import join\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n        from conan.tools.files import copy\n\n        class Chat(ConanFile):\n            name = \"chat\"\n            version = \"0.0.1\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"CMakeDeps\", \"CMakeToolchain\"\n            exports_sources = \"src/*\"\n            requires = \"greetings/0.0.1\"\n            default_options = {{\"greetings*:components\": \"{}\"}}\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure(build_script_folder=\"src\")\n                cmake.build()\n\n            def package(self):\n                copy(self, \"*.h\", src=join(self.source_folder, \"src\"),\n                                  dst=join(self.package_folder, \"include\"))\n                copy(self, \"*.lib\", src=self.build_folder,\n                                    dst=join(self.package_folder, \"lib\"), keep_path=False)\n                copy(self, \"*.a\", src=self.build_folder,\n                                  dst=join(self.package_folder, \"lib\"), keep_path=False)\n\n            def package_info(self):\n                {}\n        \"\"\").format(components, \"\\n        \".join(package_info.splitlines()))\n    sayhello_h = gen_function_h(name=\"sayhello\")\n    sayhello_cpp = gen_function_cpp(name=\"sayhello\", includes=[\"hello\"], calls=[\"hello\"])\n    sayhellobye_h = gen_function_h(name=\"sayhellobye\")\n    sayhellobye_cpp = gen_function_cpp(name=\"sayhellobye\", includes=[\"sayhello\", \"bye\"],\n                                       calls=[\"sayhello\", \"bye\"])\n\n    cmakelists = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.0)\n        project(world CXX)\n\n        %s\n        \"\"\" % cmake_find)\n\n    test_conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n\n        class WorldTestConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"CMakeDeps\", \"CMakeToolchain\"\n\n            def requirements(self):\n                self.requires(self.tested_reference_str)\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n\n            def test(self):\n                path = \"{}\".format(self.settings.build_type) if self.settings.os == \"Windows\" else \".\"\n                self.run(\"{}{}example\".format(path, os.sep))\n                self.run(\"{}{}example2\".format(path, os.sep))\n        \"\"\")\n    test_example_cpp = gen_function_cpp(name=\"main\", includes=[\"sayhellobye\"], calls=[\"sayhellobye\"])\n\n    test_cmakelists = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.15)\n        project(PackageTest CXX)\n\n        %s\n        \"\"\" % test_cmake_find)\n    client.save({\"conanfile.py\": conanfile,\n                 \"src/CMakeLists.txt\": cmakelists,\n                 \"src/sayhello.h\": sayhello_h,\n                 \"src/sayhello.cpp\": sayhello_cpp,\n                 \"src/sayhellobye.h\": sayhellobye_h,\n                 \"src/sayhellobye.cpp\": sayhellobye_cpp,\n                 \"test_package/conanfile.py\": test_conanfile,\n                 \"test_package/CMakeLists.txt\": test_cmakelists,\n                 \"test_package/example.cpp\": test_example_cpp}, clean_first=True)\n    client.run(\"create . -s build_type=Release\")\n    assert \"sayhellobye: Release!\" in client.out\n    assert \"sayhello: Release!\" in client.out\n    assert \"hello: Release!\" in client.out\n    assert \"bye: Release!\" in client.out\n    client.run(\"create . -s build_type=Debug\")\n    assert \"sayhellobye: Debug!\" in client.out\n    assert \"sayhello: Debug!\" in client.out\n    assert \"hello: Debug!\" in client.out\n    assert \"bye: Debug!\" in client.out\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_standard_names(setup_client_with_greetings):\n    client = setup_client_with_greetings\n\n    package_info = textwrap.dedent(\"\"\"\n        self.cpp_info.components[\"sayhello\"].requires = [\"greetings::hello\"]\n        self.cpp_info.components[\"sayhello\"].libs = [\"sayhello\"]\n        self.cpp_info.components[\"sayhello\"].includedirs = [\"include\"]\n        self.cpp_info.components[\"sayhello\"].libdirs = [\"lib\"]\n        self.cpp_info.components[\"sayhellobye\"].requires = [\"sayhello\", \"greetings::bye\"]\n        self.cpp_info.components[\"sayhellobye\"].libs = [\"sayhellobye\"]\n        self.cpp_info.components[\"sayhellobye\"].includedirs = [\"include\"]\n        self.cpp_info.components[\"sayhellobye\"].libdirs = [\"lib\"]\n        \"\"\")\n    cmake_find = textwrap.dedent(\"\"\"\n        find_package(greetings COMPONENTS hello bye)\n\n        add_library(sayhello sayhello.cpp)\n        target_link_libraries(sayhello greetings::hello)\n\n        add_library(sayhellobye sayhellobye.cpp)\n        target_link_libraries(sayhellobye sayhello greetings::bye)\n        \"\"\")\n    test_cmake_find = textwrap.dedent(\"\"\"\n        find_package(chat)\n\n        add_executable(example example.cpp)\n        target_link_libraries(example chat::sayhellobye)\n\n        add_executable(example2 example.cpp)\n        target_link_libraries(example2 chat::chat)\n        \"\"\")\n\n    create_chat(client, \"standard\", package_info, cmake_find, test_cmake_find)\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_custom_names(setup_client_with_greetings):\n    client = setup_client_with_greetings\n\n    package_info = textwrap.dedent(\"\"\"\n        # NOTE: For the new CMakeDeps only filenames mean filename, it is not using the \"names\" field\n        self.cpp_info.set_property(\"cmake_target_name\", \"MyChat::MyChat\")\n        self.cpp_info.set_property(\"cmake_file_name\", \"MyChat\")\n\n        self.cpp_info.components[\"sayhello\"].set_property(\"cmake_target_name\", \"MyChat::MySay\")\n\n        self.cpp_info.components[\"sayhello\"].requires = [\"greetings::hello\"]\n        self.cpp_info.components[\"sayhello\"].libs = [\"sayhello\"]\n        self.cpp_info.components[\"sayhellobye\"].set_property(\"cmake_target_name\", \"MyChat::MySayBye\")\n\n        self.cpp_info.components[\"sayhellobye\"].requires = [\"sayhello\", \"greetings::bye\"]\n        self.cpp_info.components[\"sayhellobye\"].libs = [\"sayhellobye\"]\n\n        self.cpp_info.components[\"sayhello\"].libdirs = [\"lib\"]\n        self.cpp_info.components[\"sayhello\"].includedirs = [\"include\"]\n        self.cpp_info.components[\"sayhellobye\"].libdirs = [\"lib\"]\n        self.cpp_info.components[\"sayhellobye\"].includedirs = [\"include\"]\n\n        \"\"\")\n\n    cmake_find = textwrap.dedent(\"\"\"\n        find_package(MYG COMPONENTS MyHello MyBye)\n\n        add_library(sayhello sayhello.cpp)\n        target_link_libraries(sayhello MyGreetings::MyHello)\n\n        add_library(sayhellobye sayhellobye.cpp)\n        target_link_libraries(sayhellobye sayhello MyGreetings::MyBye)\n        \"\"\")\n\n    test_cmake_find = textwrap.dedent(\"\"\"\n        find_package(MyChat)\n\n        add_executable(example example.cpp)\n        target_link_libraries(example MyChat::MySayBye)\n\n        add_executable(example2 example.cpp)\n        target_link_libraries(example2 MyChat::MyChat)\n        \"\"\")\n    create_chat(client, \"custom\", package_info, cmake_find, test_cmake_find)\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_different_namespace(setup_client_with_greetings):\n    client = setup_client_with_greetings\n\n    package_info = textwrap.dedent(\"\"\"\n        self.cpp_info.set_property(\"cmake_target_name\", \"MyChat::MyGlobalChat\")\n        self.cpp_info.set_property(\"cmake_file_name\", \"MyChat\")\n\n        self.cpp_info.components[\"sayhello\"].set_property(\"cmake_target_name\", \"MyChat::MySay\")\n\n        self.cpp_info.components[\"sayhello\"].requires = [\"greetings::hello\"]\n        self.cpp_info.components[\"sayhello\"].libs = [\"sayhello\"]\n        self.cpp_info.components[\"sayhellobye\"].set_property(\"cmake_target_name\", \"MyChat::MySayBye\")\n\n        self.cpp_info.components[\"sayhellobye\"].requires = [\"sayhello\", \"greetings::bye\"]\n        self.cpp_info.components[\"sayhellobye\"].libs = [\"sayhellobye\"]\n\n        self.cpp_info.components[\"sayhello\"].libdirs = [\"lib\"]\n        self.cpp_info.components[\"sayhello\"].includedirs = [\"include\"]\n        self.cpp_info.components[\"sayhellobye\"].libdirs = [\"lib\"]\n        self.cpp_info.components[\"sayhellobye\"].includedirs = [\"include\"]\n        \"\"\")\n\n    cmake_find = textwrap.dedent(\"\"\"\n        find_package(MYG COMPONENTS MyHello MyBye)\n\n        add_library(sayhello sayhello.cpp)\n        target_link_libraries(sayhello MyGreetings::MyHello)\n\n        add_library(sayhellobye sayhellobye.cpp)\n        target_link_libraries(sayhellobye sayhello MyGreetings::MyBye)\n        \"\"\")\n\n    test_cmake_find = textwrap.dedent(\"\"\"\n        find_package(MyChat)\n\n        add_executable(example example.cpp)\n        target_link_libraries(example MyChat::MySayBye)\n\n        add_executable(example2 example.cpp)\n        target_link_libraries(example2 MyChat::MyGlobalChat)\n        \"\"\")\n    create_chat(client, \"custom\", package_info, cmake_find, test_cmake_find)\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_no_components(setup_client_with_greetings):\n    client = setup_client_with_greetings\n\n    package_info = textwrap.dedent(\"\"\"\n        self.cpp_info.components[\"sayhello\"].requires = [\"greetings::greetings\"]\n        self.cpp_info.components[\"sayhello\"].libs = [\"sayhello\"]\n        self.cpp_info.components[\"sayhellobye\"].requires = [\"sayhello\", \"greetings::greetings\"]\n        self.cpp_info.components[\"sayhellobye\"].libs = [\"sayhellobye\"]\n\n        self.cpp_info.components[\"sayhello\"].libdirs = [\"lib\"]\n        self.cpp_info.components[\"sayhello\"].includedirs = [\"include\"]\n        self.cpp_info.components[\"sayhellobye\"].libdirs = [\"lib\"]\n        self.cpp_info.components[\"sayhellobye\"].includedirs = [\"include\"]\n        \"\"\")\n\n    cmake_find = textwrap.dedent(\"\"\"\n        find_package(greetings)\n\n        add_library(sayhello sayhello.cpp)\n        target_link_libraries(sayhello greetings::greetings)\n\n        add_library(sayhellobye sayhellobye.cpp)\n        target_link_libraries(sayhellobye sayhello greetings::greetings)\n        \"\"\")\n\n    test_cmake_find = textwrap.dedent(\"\"\"\n        find_package(chat)\n\n        add_executable(example example.cpp)\n        target_link_libraries(example chat::sayhellobye)\n\n        add_executable(example2 example.cpp)\n        target_link_libraries(example2 chat::chat)\n        \"\"\")\n    create_chat(client, \"none\", package_info, cmake_find, test_cmake_find)\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_same_names():\n    client = TestClient()\n    conanfile_greetings = textwrap.dedent(\"\"\"\n        from os.path import join\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n        from conan.tools.files import copy\n\n        class HelloConan(ConanFile):\n            name = \"hello\"\n            version = \"0.0.1\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"CMakeDeps\", \"CMakeToolchain\"\n            exports_sources = \"src/*\"\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure(build_script_folder=\"src\")\n                cmake.build()\n\n            def package(self):\n                copy(self, \"*.h\", src=join(self.source_folder, \"src\"),\n                                  dst=join(self.package_folder, \"include\"))\n                copy(self, \"*.lib\", src=self.build_folder,\n                                    dst=join(self.package_folder, \"lib\"), keep_path=False)\n                copy(self, \"*.a\", src=self.build_folder,\n                                  dst=join(self.package_folder, \"lib\"), keep_path=False)\n\n            def package_info(self):\n                self.cpp_info.components[\"global\"].name = \"hello\"\n                self.cpp_info.components[\"global\"].libs = [\"hello\"]\n                self.cpp_info.components[\"global\"].includedirs = [\"include\"]\n                self.cpp_info.components[\"global\"].libdirs = [\"lib\"]\n        \"\"\")\n    hello_h = gen_function_h(name=\"hello\")\n    hello_cpp = gen_function_cpp(name=\"hello\", includes=[\"hello\"])\n\n    cmakelists_greetings = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.0)\n        project(greetings CXX)\n\n        add_library(hello hello.cpp)\n        \"\"\")\n    test_package_greetings_conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n\n        class HelloTestConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"CMakeDeps\", \"CMakeToolchain\"\n\n            def requirements(self):\n                self.requires(self.tested_reference_str)\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n\n            def test(self):\n                path = \"{}\".format(self.settings.build_type) if self.settings.os == \"Windows\" else \".\"\n                self.run(\"{}{}example\".format(path, os.sep))\n        \"\"\")\n    test_package_greetings_cpp = gen_function_cpp(name=\"main\", includes=[\"hello\"], calls=[\"hello\"])\n\n    test_package_greetings_cmakelists = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.0)\n        project(PackageTest CXX)\n\n        find_package(hello)\n\n        add_executable(example example.cpp)\n        target_link_libraries(example hello::hello)\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile_greetings,\n                 \"src/CMakeLists.txt\": cmakelists_greetings,\n                 \"src/hello.h\": hello_h,\n                 \"src/hello.cpp\": hello_cpp,\n                 \"test_package/conanfile.py\": test_package_greetings_conanfile,\n                 \"test_package/example.cpp\": test_package_greetings_cpp,\n                 \"test_package/CMakeLists.txt\": test_package_greetings_cmakelists})\n    client.run(\"create .\")\n    assert \"hello: Release!\" in client.out\n\n\n@pytest.mark.tool(\"cmake\")\nclass TestComponentsCMakeGenerators:\n\n    def test_component_not_found(self):\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class GreetingsConan(ConanFile):\n                def package_info(self):\n                    self.cpp_info.components[\"hello\"].libs = [\"hello\"]\n                    self.cpp_info.components[\"hello\"].libdirs = [\"lib\"]\n                    self.cpp_info.components[\"hello\"].includedirs = [\"include\"]\n        \"\"\")\n        client = TestClient()\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --name=greetings --version=0.0.1\")\n\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class WorldConan(ConanFile):\n                requires = \"greetings/0.0.1\"\n                def package_info(self):\n                    self.cpp_info.components[\"helloworld\"].requires = [\"greetings::non-existent\"]\n                    self.cpp_info.components[\"helloworld\"].libdirs = [\"lib\"]\n                    self.cpp_info.components[\"helloworld\"].includedirs = [\"include\"]\n        \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --name=world --version=0.0.1\")\n        client.run(\"install --requires=world/0.0.1@ -g CMakeDeps\", assert_error=True)\n        assert (\"Component 'greetings::non-existent' not found in 'greetings' \"\n                \"package requirement\" in client.out)\n\n    def test_component_not_found_same_name_as_pkg_require(self):\n        zlib = GenConanfile(\"zlib\", \"0.1\").with_setting(\"build_type\").with_generator(\"CMakeDeps\")\n        mypkg = GenConanfile(\"mypkg\", \"0.1\").with_setting(\"build_type\").with_generator(\"CMakeDeps\")\n        final = GenConanfile(\"final\", \"0.1\").with_setting(\"build_type\").with_generator(\"CMakeDeps\")\\\n            .with_require(RecipeReference(\"zlib\", \"0.1\", None, None))\\\n            .with_require(RecipeReference(\"mypkg\", \"0.1\", None, None))\\\n            .with_package_info(cpp_info={\"components\": {\"cmp\": {\"requires\": [\"mypkg::zlib\",\n                                                                             \"zlib::zlib\"]}}})\n\n        consumer = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.cmake import CMakeDeps\n            class HelloConan(ConanFile):\n                name = 'consumer'\n                version = '0.1'\n\n                def generate(self):\n                    deps = CMakeDeps(self)\n                    deps.check_components_exist = True\n                    deps.generate()\n\n                def requirements(self):\n                    self.requires(\"final/0.1\")\n\n                settings = \"build_type\"\n            \"\"\")\n\n        client = TestClient()\n        client.save({\"zlib.py\": zlib, \"mypkg.py\": mypkg, \"final.py\": final, \"consumer.py\": consumer})\n        client.run(\"create zlib.py\")\n        client.run(\"create mypkg.py\")\n        client.run(\"create final.py\")\n        client.run(\"install consumer.py\", assert_error=True)\n        assert \"Component 'mypkg::zlib' not found in 'mypkg' package requirement\" in client.out\n\n    def test_same_name_global_target_collision(self):\n        # https://github.com/conan-io/conan/issues/7889\n        conanfile_tpl = textwrap.dedent(\"\"\"\n            from os.path import join\n            from conan import ConanFile\n            from conan.tools.cmake import CMake\n            from conan.tools.files import copy\n\n            class Conan(ConanFile):\n                name = \"{name}\"\n                version = \"1.0\"\n                settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n                generators = \"CMakeDeps\", \"CMakeToolchain\"\n                exports_sources = \"src/*\", \"include/*\"\n\n                def build(self):\n                    cmake = CMake(self)\n                    cmake.configure(build_script_folder=\"src\")\n                    cmake.build()\n\n                def package(self):\n                    copy(self, \"*.h\", src=join(self.source_folder, \"include\"),\n                                      dst=join(self.package_folder, \"include\"))\n                    copy(self, \"*.lib\", src=self.build_folder,\n                                        dst=join(self.package_folder, \"lib\"), keep_path=False)\n                    copy(self, \"*.a\", src=self.build_folder,\n                                      dst=join(self.package_folder, \"lib\"), keep_path=False)\n\n                def package_info(self):\n                    self.cpp_info.set_property(\"cmake_target_name\", \"nonstd::nonstd\" )\n                    self.cpp_info.set_property(\"cmake_file_name\", \"{name}\")\n\n                    self.cpp_info.components[\"1\"].set_property(\"cmake_target_name\", \"nonstd::{name}\")\n                    self.cpp_info.components[\"1\"].libs = [\"{name}\"]\n                    self.cpp_info.components[\"1\"].includedirs = [\"include\"]\n                    self.cpp_info.components[\"1\"].libdirs = [\"lib\"]\n            \"\"\")\n        basic_cmake = textwrap.dedent(\"\"\"\n            cmake_minimum_required(VERSION 3.15)\n            set(CMAKE_CXX_COMPILER_WORKS 1)\n            set(CMAKE_CXX_ABI_COMPILED 1)\n            project(middle CXX)\n            add_library({name} {name}.cpp)\n            target_include_directories({name} PUBLIC ../include)\n            \"\"\")\n        client = TestClient()\n        for name in [\"expected\", \"variant\"]:\n            client.run(\"new cmake_lib -d name={name} -d version=1.0 -f\".format(name=name))\n            client.save({\"conanfile.py\": conanfile_tpl.format(name=name),\n                         \"src/CMakeLists.txt\": basic_cmake.format(name=name)})\n            shutil.rmtree(os.path.join(client.current_folder, \"test_package\"))\n            client.run(\"create .\")\n\n        middle_cmakelists = textwrap.dedent(\"\"\"\n            cmake_minimum_required(VERSION 3.15)\n            set(CMAKE_CXX_COMPILER_WORKS 1)\n            set(CMAKE_CXX_ABI_COMPILED 1)\n            project(middle CXX)\n\n            find_package(expected)\n            find_package(variant)\n\n            add_library(middle middle.cpp)\n            target_link_libraries(middle nonstd::nonstd)\n            \"\"\")\n        middle_h = gen_function_h(name=\"middle\")\n        middle_cpp = gen_function_cpp(name=\"middle\", includes=[\"middle\", \"expected\", \"variant\"],\n                                      calls=[\"expected\", \"variant\"])\n        middle_conanfile = textwrap.dedent(\"\"\"\n            from os.path import join\n            from conan import ConanFile\n            from conan.tools.cmake import CMake\n            from conan.tools.files import copy\n\n            class Conan(ConanFile):\n                name = \"middle\"\n                version = \"1.0\"\n                settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n                generators = \"CMakeDeps\", \"CMakeToolchain\"\n                exports_sources = \"src/*\"\n                requires = \"expected/1.0\", \"variant/1.0\"\n\n                def build(self):\n                    cmake = CMake(self)\n                    cmake.configure(build_script_folder=\"src\")\n                    cmake.build()\n\n                def package(self):\n                    copy(self, \"*.h\", src=join(self.source_folder, \"src\"),\n                                      dst=join(self.package_folder, \"include\"))\n                    copy(self, \"*.lib\", src=self.build_folder,\n                                        dst=join(self.package_folder, \"lib\"), keep_path=False)\n                    copy(self, \"*.a\", src=self.build_folder,\n                                      dst=join(self.package_folder, \"lib\"), keep_path=False)\n\n                def package_info(self):\n                    self.cpp_info.libs = [\"middle\"]\n            \"\"\")\n        client.save({\"conanfile.py\": middle_conanfile, \"src/CMakeLists.txt\": middle_cmakelists,\n                     \"src/middle.h\": middle_h, \"src/middle.cpp\": middle_cpp}, clean_first=True)\n        client.run(\"create . --name=middle --version=1.0\")\n        conanfile = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.cmake import CMake, cmake_layout\n\n            class Conan(ConanFile):\n                name = \"consumer\"\n                version = \"1.0\"\n                generators = \"CMakeDeps\", \"CMakeToolchain\"\n                settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n                exports_sources = \"src/*\"\n                requires = \"middle/1.0\"\n\n                def layout(self):\n                    cmake_layout(self)\n\n                def build(self):\n                    cmake = CMake(self)\n                    cmake.configure(build_script_folder=\"src\")\n                    cmake.build()\n                    cmd = os.path.join(self.cpp.build.bindirs[0], \"main\")\n                    self.run(cmd, env=\"conanrun\")\n            \"\"\")\n        cmakelists = textwrap.dedent(\"\"\"\n            cmake_minimum_required(VERSION 3.15)\n            set(CMAKE_CXX_COMPILER_WORKS 1)\n            set(CMAKE_CXX_ABI_COMPILED 1)\n            project(consumer CXX)\n\n            find_package(middle)\n\n            get_target_property(tmp middle::middle INTERFACE_LINK_LIBRARIES)\n            message(\"Middle link libraries: ${tmp}\")\n\n            add_executable(main main.cpp)\n            target_link_libraries(main middle::middle)\n            \"\"\")\n        main_cpp = gen_function_cpp(name=\"main\", includes=[\"middle\"], calls=[\"middle\"])\n        client.save({\"conanfile.py\": conanfile,\n                     \"src/CMakeLists.txt\": cmakelists,\n                     \"src/main.cpp\": main_cpp}, clean_first=True)\n        client.run(\"create . --name=consumer --version=1.0\")\n\n        assert 'main: Release!' in client.out\n        assert 'middle: Release!' in client.out\n        assert 'expected/1.0: Hello World Release!' in client.out\n        assert 'variant/1.0: Hello World Release!' in client.out\n\n\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.parametrize(\"check_components_exist\", [False, True, None])\ndef test_targets_declared_in_build_modules(check_components_exist):\n    \"\"\"If a require is declaring the component targets in a build_module, CMakeDeps is\n       fine with it, not needed to locate it as a conan declared component\"\"\"\n\n    client = TestClient()\n    conanfile_hello = str(GenConanfile().with_name(\"hello\").with_version(\"1.0\")\n                          .with_exports_sources(\"*.cmake\", \"*.h\")\n                          .with_import(\"from conan.tools.files import copy\")\n                          .with_import(\"from os.path import join\"))\n    conanfile_hello += \"\"\"\n    def package(self):\n         copy(self, \"*.h\", src=self.source_folder, dst=join(self.package_folder, \"include\"))\n         copy(self, \"*.cmake\", src=self.build_folder, dst=join(self.package_folder, \"cmake\"))\n\n    def package_info(self):\n        self.cpp_info.set_property(\"cmake_build_modules\", [\"cmake/my_modules.cmake\"])\n    \"\"\"\n    my_modules = textwrap.dedent(\"\"\"\n    add_library(cool_component INTERFACE)\n    target_include_directories(cool_component INTERFACE ${CMAKE_CURRENT_LIST_DIR}/../include/)\n    add_library(hello::invented ALIAS cool_component)\n    \"\"\")\n    hello_h = \"int cool_header_only=1;\"\n    client.save({\"conanfile.py\": conanfile_hello,\n                 \"my_modules.cmake\": my_modules, \"hello.h\": hello_h})\n    client.run(\"create .\")\n\n    conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.cmake import CMake, CMakeDeps\n\n            class HelloConan(ConanFile):\n                name = 'app'\n                version = '1.0'\n                exports_sources = \"*.txt\", \"*.cpp\"\n                generators = \"CMakeToolchain\"\n                requires = (\"hello/1.0\", )\n                settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n\n                def generate(self):\n                    deps = CMakeDeps(self)\n                    {}\n                    deps.generate()\n\n                def build(self):\n                    cmake = CMake(self)\n                    cmake.configure()\n                    cmake.build()\n\n    \"\"\")\n    if check_components_exist is False:\n        conanfile = conanfile.format(\"deps.check_components_exist=False\")\n    elif check_components_exist:\n        conanfile = conanfile.format(\"deps.check_components_exist=True\")\n    else:\n        conanfile = conanfile.format(\"\")\n\n    main_cpp = textwrap.dedent(\"\"\"\n        #include <iostream>\n        #include \"hello.h\"\n\n        int main(){\n            std::cout << \"cool header value: \" << cool_header_only;\n            return 0;\n        }\n        \"\"\")\n\n    cmakelist = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        set(CMAKE_C_COMPILER_WORKS 1)\n        set(CMAKE_C_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.15)\n        project(project CXX)\n\n        find_package(hello COMPONENTS hello::invented missing)\n        add_executable(myapp main.cpp)\n        target_link_libraries(myapp hello::invented)\n    \"\"\")\n    client.save({\"conanfile.py\": conanfile,\n                 \"CMakeLists.txt\": cmakelist, \"main.cpp\": main_cpp})\n    client.run(\"create .\", assert_error=check_components_exist)\n    assert bool(check_components_exist) == (\"Conan: Component 'missing' NOT found in package \"\n                                            \"'hello'\" in client.out)\n\n    assert \"Conan: Including build module\" in client.out\n    assert \"my_modules.cmake\" in client.out\n    assert bool(check_components_exist) == (\"Conan: Component 'hello::invented' found in package 'hello'\"\n                                            in client.out)\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_cmakedeps_targets_no_namespace():\n    \"\"\"\n    This test is checking that when we add targets with no namespace for the root cpp_info\n    and the components, the targets are correctly generated. Before Conan 1.43, Conan\n    only generated targets with namespace\n    \"\"\"\n    client = TestClient()\n    my_pkg = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class MyPkg(ConanFile):\n            name = \"my_pkg\"\n            version = \"0.1\"\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            def package_info(self):\n                self.cpp_info.set_property(\"cmake_target_name\", \"nonamespacepkg\")\n                self.cpp_info.components[\"MYPKGCOMP\"].set_property(\"cmake_target_name\", \"MYPKGCOMPNAME\")\n        \"\"\")\n    client.save({\"my_pkg/conanfile.py\": my_pkg}, clean_first=True)\n    client.run(\"create my_pkg\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class LibcurlConan(ConanFile):\n            name = \"libcurl\"\n            version = \"0.1\"\n            requires = \"my_pkg/0.1\"\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            def package_info(self):\n                self.cpp_info.set_property(\"cmake_target_name\", \"CURL\")\n                self.cpp_info.set_property(\"cmake_file_name\", \"CURLFILENAME\")\n                self.cpp_info.components[\"curl\"].set_property(\"cmake_target_name\", \"libcurl\")\n                self.cpp_info.components[\"curl2\"].set_property(\"cmake_target_name\", \"libcurl2\")\n                self.cpp_info.components[\"curl2\"].requires.extend([\"curl\", \"my_pkg::MYPKGCOMP\"])\n        \"\"\")\n    client.save({\"libcurl/conanfile.py\": conanfile})\n    client.run(\"create libcurl\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMakeDeps, CMake, CMakeToolchain\n        class Consumer(ConanFile):\n            name = \"consumer\"\n            version = \"0.1\"\n            requires = \"libcurl/0.1\"\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            exports_sources = \"CMakeLists.txt\"\n            def generate(self):\n                deps = CMakeDeps(self)\n                deps.check_components_exist=True\n                deps.generate()\n                tc = CMakeToolchain(self)\n                tc.generate()\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n        \"\"\")\n\n    cmakelists = textwrap.dedent(\"\"\"cmake_minimum_required(VERSION 3.15)\n        project(Consumer)\n        find_package(CURLFILENAME CONFIG REQUIRED COMPONENTS libcurl libcurl2)\n        \"\"\")\n\n    client.save({\"consumer/conanfile.py\": conanfile, \"consumer/CMakeLists.txt\": cmakelists})\n    client.run(\"create consumer\")\n    assert \"Component target declared 'libcurl'\" in client.out\n    assert \"Component target declared 'libcurl2'\" in client.out\n    assert \"Target declared 'CURL'\" in client.out\n    assert \"Component target declared 'MYPKGCOMPNAME'\" in client.out\n    assert \"Target declared 'nonamespacepkg'\" in client.out\n"
  },
  {
    "path": "test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_custom_configs.py",
    "content": "import os\nimport platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.assets.sources import gen_function_cpp\nfrom conan.test.utils.tools import TestClient\n\nfrom conan.internal.util.files import save\n\n\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Only for windows\")\ndef test_custom_config_generator_multi():\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.cmake import CMakeDeps\n        from conan.tools.files import copy\n        class App(ConanFile):\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            requires = \"hello/0.1\"\n\n            def generate(self):\n                cmake = CMakeDeps(self)\n                if self.dependencies[\"hello\"].options.shared:\n                    cmake.configuration = \"ReleaseShared\"\n                cmake.generate()\n\n                config = str(self.settings.build_type)\n                if self.dependencies[\"hello\"].options.shared:\n                    config = \"ReleaseShared\"\n                src = os.path.join(self.dependencies[\"hello\"].package_folder, \"bin\")\n                dst = os.path.join(self.build_folder, config)\n                copy(self, \"*.dll\", src, dst, keep_path=False)\n        \"\"\")\n\n    app = gen_function_cpp(name=\"main\", includes=[\"hello\"], calls=[\"hello\"])\n\n    cmakelist = textwrap.dedent(\"\"\"\n        set(CMAKE_CONFIGURATION_TYPES Debug Release ReleaseShared CACHE STRING\n            \"Available build-types: Debug, Release and ReleaseShared\")\n\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 2.8)\n        project(App C CXX)\n\n        set(CMAKE_PREFIX_PATH ${CMAKE_BINARY_DIR} ${CMAKE_PREFIX_PATH})\n        set(CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR} ${CMAKE_MODULE_PATH})\n\n        set(CMAKE_CXX_FLAGS_RELEASESHARED ${CMAKE_CXX_FLAGS_RELEASE})\n        set(CMAKE_C_FLAGS_RELEASESHARED ${CMAKE_C_FLAGS_RELEASE})\n        set(CMAKE_EXE_LINKER_FLAGS_RELEASESHARED ${CMAKE_EXE_LINKER_FLAGS_RELEASE})\n\n        find_package(hello REQUIRED)\n        add_executable(app app.cpp)\n        target_link_libraries(app PRIVATE hello::hello)\n        \"\"\")\n\n    c = TestClient(path_with_spaces=False)\n    c.run(\"new cmake_lib -d name=hello -d version=0.1\")\n    c.run(\"create . -s compiler.version=191 \"\n          \"-s build_type=Release -o hello/*:shared=True -tf=\\\"\\\"\")\n    c.run(\"create . --name=hello --version=0.1 -s compiler.version=191 \"\n          \"-s build_type=Release -tf=\\\"\\\"\")\n\n    # Prepare the actual consumer package\n    c.save({\"conanfile.py\": conanfile,\n            \"CMakeLists.txt\": cmakelist,\n            \"app.cpp\": app})\n\n    settings = {\"compiler\": \"msvc\",\n                \"compiler.version\": \"191\",\n                \"compiler.runtime\": \"dynamic\",\n                \"arch\": \"x86_64\",\n                \"build_type\": \"Release\",\n                }\n\n    settings = \" \".join('-s %s=\"%s\"' % (k, v) for k, v in settings.items() if v)\n\n    # Run the configure corresponding to this test case\n    with c.chdir('build'):\n        c.run(\"install .. %s -o hello/*:shared=True -of=.\" % settings)\n        c.run(\"install .. %s -o hello/*:shared=False -of=.\" % settings)\n        assert os.path.isfile(os.path.join(c.current_folder,\n                                           \"hello-Target-releaseshared.cmake\"))\n        assert os.path.isfile(os.path.join(c.current_folder,\n                                           \"hello-Target-release.cmake\"))\n\n        c.run_command('cmake .. -G \"Visual Studio 15 Win64\" --loglevel=DEBUG')\n        assert \"Found DLL and STATIC\" in c.out\n        c.run_command('cmake --build . --config Release')\n        c.run_command(r\"Release\\\\app.exe\")\n        assert \"hello/0.1: Hello World Release!\" in c.out\n        assert \"main: Release!\" in c.out\n        c.run_command('cmake --build . --config ReleaseShared')\n        c.run_command(r\"ReleaseShared\\\\app.exe\")\n        assert \"hello/0.1: Hello World Release!\" in c.out\n        assert \"main: Release!\" in c.out\n\n\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Only for windows\")\ndef test_custom_config_settings():\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMakeDeps\n\n        class App(ConanFile):\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            requires = \"hello/0.1\"\n            generators = \"CMakeToolchain\"\n\n            def generate(self):\n                cmake = CMakeDeps(self)\n                #cmake.configurations.append(\"MyRelease\") # NOT NECESSARY!!!\n                cmake.generate()\n        \"\"\")\n\n    app = gen_function_cpp(name=\"main\", includes=[\"hello\"], calls=[\"hello\"])\n\n    cmakelist = textwrap.dedent(\"\"\"\n        set(CMAKE_CONFIGURATION_TYPES Debug Release MyRelease CACHE STRING\n            \"Available build-types: Debug, Release and MyRelease\")\n\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        set(CMAKE_C_COMPILER_WORKS 1)\n        set(CMAKE_C_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.15)\n        project(App C CXX)\n\n        set(CMAKE_PREFIX_PATH ${CMAKE_BINARY_DIR} ${CMAKE_PREFIX_PATH})\n        set(CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR} ${CMAKE_MODULE_PATH})\n\n        set(CMAKE_CXX_FLAGS_MYRELEASE ${CMAKE_CXX_FLAGS_RELEASE})\n        set(CMAKE_C_FLAGS_MYRELEASE ${CMAKE_C_FLAGS_RELEASE})\n        set(CMAKE_EXE_LINKER_FLAGS_MYRELEASE ${CMAKE_EXE_LINKER_FLAGS_RELEASE})\n\n        find_package(hello REQUIRED)\n        add_executable(app app.cpp)\n        target_link_libraries(app PRIVATE hello::hello)\n        \"\"\")\n\n    c = TestClient(path_with_spaces=False)\n    settings = \"build_type: [MyRelease]\"\n    save(c.paths.settings_path_user, settings)\n    c.run(\"new cmake_lib -d name=hello -d version=0.1\")\n    cmake = c.load(\"CMakeLists.txt\")\n\n    cmake = cmake.replace(\"cmake_minimum_required\", \"\"\"\n        set(CMAKE_CONFIGURATION_TYPES Debug MyRelease Release CACHE STRING \"Types\")\n\n        cmake_minimum_required\"\"\")\n    cmake = cmake.replace(\"add_library\", textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_FLAGS_MYRELEASE ${CMAKE_CXX_FLAGS_RELEASE})\n        set(CMAKE_C_FLAGS_MYRELEASE ${CMAKE_C_FLAGS_RELEASE})\n        set(CMAKE_EXE_LINKER_FLAGS_MYRELEASE ${CMAKE_EXE_LINKER_FLAGS_RELEASE})\n        add_library\"\"\"))\n    cmake = cmake.replace(\"PUBLIC_HEADER\", \"CONFIGURATIONS MyRelease\\nPUBLIC_HEADER\")\n    c.save({\"CMakeLists.txt\": cmake})\n    c.run(\"create . --name=hello --version=0.1 -s compiler.version=191 \"\n          \"-s build_type=MyRelease -s:b build_type=MyRelease -tf=\\\"\\\"\")\n\n    # Prepare the actual consumer package\n    c.save({\"conanfile.py\": conanfile,\n            \"CMakeLists.txt\": cmakelist,\n            \"app.cpp\": app})\n\n    settings = {\"compiler\": \"msvc\",\n                \"compiler.version\": \"191\",\n                \"compiler.runtime\": \"dynamic\",\n                \"arch\": \"x86_64\",\n                \"build_type\": \"MyRelease\",\n                }\n\n    settings_h = \" \".join('-s %s=\"%s\"' % (k, v) for k, v in settings.items())\n    settings_b = \" \".join('-s:b %s=\"%s\"' % (k, v) for k, v in settings.items())\n\n    # Run the configure corresponding to this test case\n    build_directory = os.path.join(c.current_folder, \"build\").replace(\"\\\\\", \"/\")\n    with c.chdir(build_directory):\n        c.run(\"install .. %s %s -of=.\" % (settings_h, settings_b))\n        toolchain = c.load(\"conan_toolchain.cmake\")\n        # As it is a custom configuration, the TRY_COMPILE_CONFIFURATION not defined\n        assert \"CMAKE_TRY_COMPILE_CONFIGURATION\" not in toolchain\n        assert os.path.isfile(os.path.join(c.current_folder,\n                                           \"hello-Target-myrelease.cmake\"))\n\n        c.run_command('cmake .. -G \"Visual Studio 15\" '\n                      '-DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake')\n        c.run_command('cmake --build . --config MyRelease')\n        c.run_command(r\"MyRelease\\\\app.exe\")\n        assert \"hello/0.1: Hello World Release!\" in c.out\n        assert \"main: Release!\" in c.out\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_changing_build_type():\n    client = TestClient(path_with_spaces=False)\n    dep_conanfile = textwrap.dedent(r\"\"\"\n       import os\n       from conan import ConanFile\n       from conan.tools.files import copy, save\n\n       class Dep(ConanFile):\n           settings = \"build_type\"\n           def build(self):\n               save(self, \"hello.h\",\n               '# include <iostream>\\n'\n               'void hello(){{std::cout<<\"BUILD_TYPE={}!!\";}}'.format(self.settings.build_type))\n           def package(self):\n               copy(self, \"*.h\", self.source_folder, os.path.join(self.package_folder, \"include\"))\n           \"\"\")\n    client.save({\"conanfile.py\": dep_conanfile})\n    client.run(\"create . --name=dep --version=0.1 -s build_type=Release\")\n    client.run(\"create . --name=dep --version=0.1 -s build_type=Debug\")\n\n    cmakelists = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.15)\n        project(App CXX)\n\n        # NOTE: NO MAP necessary!!!\n        find_package(dep REQUIRED)\n        add_executable(app app.cpp)\n        target_link_libraries(app PRIVATE dep::dep)\n        \"\"\")\n    app = gen_function_cpp(name=\"main\", includes=[\"hello\"], calls=[\"hello\"])\n    pkg_conanfile = GenConanfile(\"pkg\", \"0.1\").with_requires(\"dep/0.1\").\\\n        with_generator(\"CMakeDeps\").with_generator(\"CMakeToolchain\").\\\n        with_settings(\"os\", \"compiler\", \"arch\", \"build_type\")\n    client.save({\"conanfile.py\": pkg_conanfile,\n                 \"CMakeLists.txt\": cmakelists,\n                 \"app.cpp\": app}, clean_first=True)\n\n    # in MSVC multi-config -s pkg/*:build_type=Debug is not really necesary, toolchain do nothing\n    # TODO: Challenge how to define consumer build_type for conanfile.txt\n    client.run(\"install . -s pkg*:build_type=Debug -s build_type=Release\")\n    client.run_command(\"cmake . -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake \"\n                       \"-DCMAKE_BUILD_TYPE=Debug\")\n    client.run_command(\"cmake --build . --config Debug\")\n    cmd = os.path.join(\".\", \"Debug\", \"app\") if platform.system() == \"Windows\" else \"./app\"\n    client.run_command(cmd)\n    assert \"main: Debug!\" in client.out\n    assert \"BUILD_TYPE=Release!!\" in client.out\n"
  },
  {
    "path": "test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_find_module_and_config.py",
    "content": "import textwrap\n\nimport pytest\n\nfrom conan.test.assets.cmake import gen_cmakelists\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.assets.sources import gen_function_cpp, gen_function_h\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.fixture(scope=\"module\")\ndef client():\n    t = TestClient()\n    cpp = gen_function_cpp(name=\"mydep\")\n    h = gen_function_h(name=\"mydep\")\n    cmake = gen_cmakelists(libname=\"mydep\", libsources=[\"mydep.cpp\"])\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n        from conan.tools.files import copy\n\n        class Conan(ConanFile):\n            name = \"mydep\"\n            version = \"1.0\"\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            exports_sources = \"*.cpp\", \"*.h\", \"CMakeLists.txt\"\n            generators = \"CMakeToolchain\"\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n\n            def package(self):\n                copy(self, \"*.h\", self.source_folder, os.path.join(self.package_folder, \"include\"))\n                copy(self, \"*.lib\", self.build_folder,\n                     os.path.join(self.package_folder, \"lib\"), keep_path=False)\n                copy(self, \"*.dll\", self.build_folder,\n                     os.path.join(self.package_folder, \"bin\"), keep_path=False)\n                copy(self, \"*.dylib*\", self.build_folder,\n                     os.path.join(self.package_folder, \"lib\"), keep_path=False)\n                copy(self, \"*.so\", self.build_folder,\n                     os.path.join(self.package_folder, \"lib\"), keep_path=False)\n                copy(self, \"*.a\", self.build_folder,\n                     os.path.join(self.package_folder, \"lib\"), keep_path=False)\n\n            def package_info(self):\n\n                self.cpp_info.set_property(\"cmake_find_mode\", \"both\")\n\n                self.cpp_info.set_property(\"cmake_file_name\", \"MyDep\")\n                self.cpp_info.set_property(\"cmake_target_name\", \"MyDepTarget::MyDepTarget\")\n\n                self.cpp_info.set_property(\"cmake_module_file_name\", \"mi_dependencia\")\n                self.cpp_info.set_property(\"cmake_module_target_name\", \"mi_dependencia_namespace::mi_dependencia_target\")\n\n                self.cpp_info.components[\"crispin\"].libs = [\"mydep\"]\n                self.cpp_info.components[\"crispin\"].libdirs = [\"lib\"]\n                self.cpp_info.components[\"crispin\"].includedirs = [\"include\"]\n                self.cpp_info.components[\"crispin\"].set_property(\"cmake_target_name\",\n                                                                 \"MyDepTarget::MyCrispinTarget\")\n                self.cpp_info.components[\"crispin\"].set_property(\"cmake_module_target_name\",\n                                                                 \"mi_dependencia_namespace::mi_crispin_target\")\n        \"\"\")\n\n    t.save({\"conanfile.py\": conanfile,\n            \"mydep.cpp\": cpp,\n            \"mydep.h\": h,\n            \"CMakeLists.txt\": cmake})\n\n    t.run(\"create .\")\n    return t\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_reuse_with_modules_and_config(client):\n    cpp = gen_function_cpp(name=\"main\")\n\n    cmake_exe_config = \"\"\"\n    add_executable(myapp main.cpp)\n    find_package(MyDep) # This one will find the config\n    target_link_libraries(myapp MyDepTarget::MyCrispinTarget)\n    \"\"\"\n\n    cmake_exe_module = \"\"\"\n    add_executable(myapp2 main.cpp)\n    find_package(mi_dependencia) # This one will find the module\n    target_link_libraries(myapp2 mi_dependencia_namespace::mi_crispin_target)\n    \"\"\"\n\n    cmake = \"\"\"\n    set(CMAKE_CXX_COMPILER_WORKS 1)\n    set(CMAKE_CXX_ABI_COMPILED 1)\n    set(CMAKE_C_COMPILER_WORKS 1)\n    set(CMAKE_C_ABI_COMPILED 1)\n\n    cmake_minimum_required(VERSION 3.15)\n    project(project CXX)\n    {}\n    \"\"\"\n\n    # test config\n    conanfile = GenConanfile().with_name(\"myapp\")\\\n        .with_cmake_build().with_exports_sources(\"*.cpp\", \"*.txt\").with_require(\"mydep/1.0\")\n    client.save({\"conanfile.py\": conanfile,\n                 \"main.cpp\": cpp,\n                 \"CMakeLists.txt\": cmake.format(cmake_exe_config)})\n\n    client.run(\"install .\")\n    client.run(\"build .\")\n\n    # test modules\n    conanfile = GenConanfile().with_name(\"myapp\")\\\n        .with_cmake_build().with_exports_sources(\"*.cpp\", \"*.txt\").with_require(\"mydep/1.0\")\n    client.save({\"conanfile.py\": conanfile,\n                 \"main.cpp\": cpp,\n                 \"CMakeLists.txt\": cmake.format(cmake_exe_module)}, clean_first=True)\n\n    client.run(\"install .\")\n    client.run(\"build .\")\n\n\nfind_modes = [\n    (\"both\", \"both\", \"\"),\n    (\"both\", \"both\", \"MODULE\"),\n    (\"config\", \"config\", \"\"),\n    (\"module\", \"module\", \"\"),\n    (None, \"both\", \"\"),\n    (None, \"both\", \"MODULE\")\n]\n\n\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.parametrize(\"find_mode_pkga, find_mode_pkgb, find_mode_consumer\", find_modes)\ndef test_transitive_modules_found(find_mode_pkga, find_mode_pkgb, find_mode_consumer):\n    \"\"\"\n    related to https://github.com/conan-io/conan/issues/10224\n    modules files variables were set with the pkg_name_FOUND or pkg_name_VERSION\n    instead of using filename_*, also there was missing doing a find_dependency of the\n    requires packages to find_package transitive dependencies\n    \"\"\"\n    client = TestClient()\n    conan_pkg = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            {requires}\n            def package_info(self):\n                if \"{mode}\" != \"None\":\n                    self.cpp_info.set_property(\"cmake_find_mode\", \"{mode}\")\n                self.cpp_info.set_property(\"cmake_file_name\", \"{filename}\")\n                self.cpp_info.set_property(\"cmake_module_file_name\", \"{module_filename}\")\n                self.cpp_info.defines.append(\"DEFINE_{filename}\")\n            \"\"\")\n\n    consumer = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n        class Consumer(ConanFile):\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            requires = \"pkgb/1.0\"\n            generators = \"CMakeDeps\", \"CMakeToolchain\"\n            exports_sources = \"CMakeLists.txt\"\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n        \"\"\")\n\n    cmakelist = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.1)\n        project(test_package NONE)\n        find_package(MYPKGB REQUIRED {find_mode})\n        message(\"MYPKGB_VERSION: ${{MYPKGB_VERSION}}\")\n        message(\"MYPKGB_VERSION_STRING: ${{MYPKGB_VERSION_STRING}}\")\n        message(\"MYPKGB_INCLUDE_DIRS: ${{MYPKGB_INCLUDE_DIRS}}\")\n        message(\"MYPKGB_INCLUDE_DIR: ${{MYPKGB_INCLUDE_DIR}}\")\n        message(\"MYPKGB_LIBRARIES: ${{MYPKGB_LIBRARIES}}\")\n\n        get_target_property(linked_libs pkgb::pkgb INTERFACE_LINK_LIBRARIES)\n        message(\"MYPKGB_LINKED_LIBRARIES: '${{linked_libs}}'\")\n\n        get_target_property(linked_deps pkgb_DEPS_TARGET INTERFACE_LINK_LIBRARIES)\n        message(\"MYPKGB_DEPS_LIBRARIES: '${{linked_deps}}'\")\n\n        message(\"MYPKGB_DEFINITIONS: ${{MYPKGB_DEFINITIONS}}\")\n        \"\"\")\n\n    client.save({\"pkgb.py\": conan_pkg.format(requires='requires=\"pkga/1.0\"', filename='MYPKGB', module_filename='MYPKGB',\n                                             mode=find_mode_pkgb),\n                 \"pkga.py\": conan_pkg.format(requires='', filename='MYPKGA', module_filename='unicorns', mode=find_mode_pkga),\n                 \"consumer.py\": consumer,\n                 \"CMakeLists.txt\": cmakelist.format(find_mode=find_mode_consumer)})\n\n    client.run(\"create pkga.py --name=pkga --version=1.0\")\n    client.run(\"create pkgb.py --name=pkgb --version=1.0\")\n    client.run(\"create consumer.py --name=consumer --version=1.0\")\n\n    assert \"MYPKGB_VERSION: 1.0\" in client.out\n    assert \"MYPKGB_VERSION_STRING: 1.0\" in client.out\n    assert \"MYPKGB_INCLUDE_DIRS:\" in client.out\n    assert \"MYPKGB_INCLUDE_DIR:\" in client.out\n    # The MYPKG_LIBRARIES contains the target for the current package, but the target is linked\n    # with the dependencies also:\n    assert \"MYPKGB_LIBRARIES: pkgb::pkgb\" in client.out\n    assert \"MYPKGB_LINKED_LIBRARIES: '$<$<CONFIG:Release>:>;$<$<CONFIG:Release>:>;pkgb_DEPS_TARGET'\" in client.out\n    assert \"MYPKGB_DEPS_LIBRARIES: '$<$<CONFIG:Release>:>;$<$<CONFIG:Release>:>;\" \\\n           \"$<$<CONFIG:Release>:pkga::pkga>'\" in client.out\n\n    assert \"MYPKGB_DEFINITIONS: -DDEFINE_MYPKGB\" in client.out\n    assert \"Conan: Target declared 'pkga::pkga'\"\n\n    if find_mode_pkga == \"module\":\n        assert 'Found unicorns: 1.0 (found version \"1.0\")' in client.out\n\n"
  },
  {
    "path": "test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_transitivity.py",
    "content": "import os\nimport platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.utils.mocks import ConanFileMock\nfrom conan.tools.env.environment import environment_wrap_command\nfrom conan.test.assets.cmake import gen_cmakelists\nfrom conan.test.assets.sources import gen_function_cpp\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires MSBuild\")\n@pytest.mark.tool(\"cmake\")\ndef test_transitive_headers_not_public(transitive_libraries):\n    c = transitive_libraries\n\n    conanfile = textwrap.dedent(\"\"\"\\\n       from conan import ConanFile\n       from conan.tools.cmake import CMake\n       class Pkg(ConanFile):\n           exports = \"*\"\n           requires = \"engine/1.0\"\n           settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n           generators = \"CMakeToolchain\", \"CMakeDeps\"\n\n           def layout(self):\n               self.folders.source = \"src\"\n\n           def build(self):\n               cmake = CMake(self)\n               cmake.configure()\n               cmake.build()\n        \"\"\")\n    cmake = gen_cmakelists(appsources=[\"main.cpp\"], find_package=[\"engine\"])\n    main = gen_function_cpp(name=\"main\", includes=[\"engine\"], calls=[\"engine\"])\n    c.save({\"src/main.cpp\": main,\n            \"src/CMakeLists.txt\": cmake,\n            \"conanfile.py\": conanfile}, clean_first=True)\n\n    c.run(\"build .\")\n    c.run_command(\".\\\\Release\\\\myapp.exe\")\n    assert \"matrix/1.0: Hello World Release!\" in c.out\n\n    # If we try to include transitivity matrix headers, it will fail!!\n    main = gen_function_cpp(name=\"main\", includes=[\"engine\", \"matrix\"], calls=[\"engine\"])\n    c.save({\"src/main.cpp\": main})\n    c.run(\"build .\", assert_error=True)\n    assert \"Conan: Target declared 'matrix::matrix'\" in c.out\n    assert \"Cannot open include file: 'matrix.h'\" in c.out\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires MSBuild\")\n@pytest.mark.tool(\"cmake\")\ndef test_shared_requires_static(transitive_libraries):\n    c = transitive_libraries\n\n    conanfile = textwrap.dedent(\"\"\"\\\n       from conan import ConanFile\n       from conan.tools.cmake import CMake\n       class Pkg(ConanFile):\n           exports = \"*\"\n           requires = \"engine/1.0\"\n           default_options = {\"engine/*:shared\": True}\n           settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n           generators = \"CMakeToolchain\", \"CMakeDeps\", \"VirtualBuildEnv\", \"VirtualRunEnv\"\n\n           def layout(self):\n               self.folders.source = \"src\"\n\n           def build(self):\n               cmake = CMake(self)\n               cmake.configure()\n               cmake.build()\n        \"\"\")\n    cmake = gen_cmakelists(appsources=[\"main.cpp\"], find_package=[\"engine\"])\n    main = gen_function_cpp(name=\"main\", includes=[\"engine\"], calls=[\"engine\"])\n    c.save({\"src/main.cpp\": main,\n            \"src/CMakeLists.txt\": cmake,\n            \"conanfile.py\": conanfile}, clean_first=True)\n\n    c.run(\"build .\")\n    command = environment_wrap_command(ConanFileMock(), \"conanrun\", c.current_folder, \".\\\\Release\\\\myapp.exe\")\n    c.run_command(command)\n    assert \"matrix/1.0: Hello World Release!\" in c.out\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires MSBuild\")\n@pytest.mark.tool(\"cmake\")\ndef test_transitive_binary_skipped(transitive_libraries):\n    c = transitive_libraries\n    # IMPORTANT: matrix binary can be removed, no longer necessary\n    c.run(\"remove matrix*:* -c\")\n\n    conanfile = textwrap.dedent(\"\"\"\\\n       from conan import ConanFile\n       from conan.tools.cmake import CMake\n       class Pkg(ConanFile):\n           exports = \"*\"\n           requires = \"engine/1.0\"\n           default_options = {\"engine/*:shared\": True}\n           settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n           generators = \"CMakeToolchain\", \"CMakeDeps\"\n\n           def layout(self):\n               self.folders.source = \"src\"\n\n           def build(self):\n               cmake = CMake(self)\n               cmake.configure()\n               cmake.build()\n        \"\"\")\n    cmake = gen_cmakelists(appsources=[\"main.cpp\"], find_package=[\"engine\"])\n    main = gen_function_cpp(name=\"main\", includes=[\"engine\"], calls=[\"engine\"])\n    c.save({\"src/main.cpp\": main,\n            \"src/CMakeLists.txt\": cmake,\n            \"conanfile.py\": conanfile}, clean_first=True)\n\n    c.run(\"build . \")\n    command = environment_wrap_command(ConanFileMock(), \"conanrun\", c.current_folder, \".\\\\Release\\\\myapp.exe\")\n    c.run_command(command)\n    assert \"matrix/1.0: Hello World Release!\" in c.out\n\n    # If we try to include transitivity matrix headers, it will fail!!\n    main = gen_function_cpp(name=\"main\", includes=[\"engine\", \"matrix\"], calls=[\"engine\"])\n    c.save({\"src/main.cpp\": main})\n    c.run(\"build .\", assert_error=True)\n    assert \"Cannot open include file: 'matrix.h'\" in c.out\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_shared_requires_static_build_all(transitive_libraries):\n    c = transitive_libraries\n\n    conanfile = textwrap.dedent(\"\"\"\\\n       from conan import ConanFile\n\n       class Pkg(ConanFile):\n           requires = \"engine/1.0\"\n           settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n           generators = \"CMakeDeps\"\n        \"\"\")\n\n    c.save({\"conanfile.py\": conanfile}, clean_first=True)\n\n    arch = c.get_default_host_profile().settings['arch']\n\n    c.run(\"install . -o engine*:shared=True\")\n    assert not os.path.exists(os.path.join(c.current_folder, f\"matrix-release-{arch}-data.cmake\"))\n    cmake = c.load(f\"engine-release-{arch}-data.cmake\")\n    assert 'list(APPEND engine_FIND_DEPENDENCY_NAMES )' in cmake\n\n    c.run(\"install . -o engine*:shared=True --build=engine*\")\n    assert not os.path.exists(os.path.join(c.current_folder, f\"matrix-release-{arch}-data.cmake\"))\n    cmake = c.load(f\"engine-release-{arch}-data.cmake\")\n    assert 'list(APPEND engine_FIND_DEPENDENCY_NAMES )' in cmake\n"
  },
  {
    "path": "test/functional/toolchains/cmake/cmakedeps/test_cmakedeps_versions.py",
    "content": "import os\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.fixture(scope=\"module\")\ndef hello_client():\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile(\"hello\", \"1.1\")})\n    client.run(\"create .\")\n    return client\n\n\n@pytest.mark.parametrize(\"name, version, params, cmake_fails, package_found\", [\n    (\"hello\", \"1.0\", \"\", False, True),\n    (\"Hello\", \"1.0\", \"\", False, True),\n    (\"HELLO\", \"1.0\", \"\", False, True),\n    (\"hello\", \"1.1\", \"\", False, True),\n    (\"hello\", \"1.2\", \"\", False, False),\n    (\"hello\", \"1.0\", \"EXACT\", False, False),\n    (\"hello\", \"1.1\", \"EXACT\", False, True),\n    (\"hello\", \"1.2\", \"EXACT\", False, False),\n    (\"hello\", \"0.1\", \"\", False, False),\n    (\"hello\", \"2.0\", \"\", False, False),\n    (\"hello\", \"1.0\", \"REQUIRED\", False, True),\n    (\"hello\", \"1.1\", \"REQUIRED\", False, True),\n    (\"hello\", \"1.2\", \"REQUIRED\", True, False),\n    (\"hello\", \"1.0\", \"EXACT REQUIRED\", True, False),\n    (\"hello\", \"1.1\", \"EXACT REQUIRED\", False, True),\n    (\"hello\", \"1.2\", \"EXACT REQUIRED\", True, False),\n    (\"hello\", \"0.1\", \"REQUIRED\", True, False),\n    (\"hello\", \"2.0\", \"REQUIRED\", True, False)\n])\n@pytest.mark.tool(\"cmake\")\ndef test_version(hello_client, name, version, params, cmake_fails, package_found):\n    client = hello_client\n    cmakelists = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(consumer NONE)\n        find_package({name} {version} {params})\n        message(STATUS \"hello found: ${{{name}_FOUND}}\")\n        \"\"\").format(name=name, version=version, params=params)\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n\n        class Conan(ConanFile):\n            requires = \"hello/1.1\"\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            generators = \"CMakeDeps\", \"CMakeToolchain\"\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n        \"\"\")\n\n    client.save({\"conanfile.py\": conanfile, \"CMakeLists.txt\": cmakelists}, clean_first=True)\n    exit_code = client.run(\"build .\", assert_error=cmake_fails)\n    if cmake_fails:\n        assert exit_code != 0\n    elif package_found:\n        assert \"hello found: 1\" in client.out\n    else:\n        assert \"hello found: 0\" in client.out\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_no_version_file(hello_client):\n    client = hello_client\n\n    cmakelists = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.1)\n        project(consumer NONE)\n        find_package(hello 1.0 REQUIRED)\n        message(STATUS \"hello found: ${{hello_FOUND}}\")\n        \"\"\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n\n        class Conan(ConanFile):\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            requires = \"hello/1.1\"\n            generators = \"CMakeDeps\", \"CMakeToolchain\"\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n        \"\"\")\n\n    client.save({\"conanfile.py\": conanfile, \"CMakeLists.txt\": cmakelists}, clean_first=True)\n    client.run(\"install .\")\n    os.unlink(os.path.join(client.current_folder, \"hello-config-version.cmake\"))\n    exit_code = client.run(\"build .\", assert_error=True)\n    assert 0 != exit_code\n"
  },
  {
    "path": "test/functional/toolchains/cmake/cmakedeps/test_conditional_build_type.py",
    "content": "import textwrap\n\n\ndef test_conditional_build_type(matrix_client_debug):\n    # https://github.com/conan-io/conan/issues/15851\n    c = matrix_client_debug\n    # A header-only library can't be used for testing, it doesn't fail\n\n    c.save({}, clean_first=True)\n    c.run(\"new cmake_lib -d name=pkgb -d version=0.1 -d requires=matrix/1.0\")\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout, CMakeDeps\n\n        class pkgbRecipe(ConanFile):\n            name = \"pkgb\"\n            version = \"0.1\"\n            package_type = \"static-library\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            exports_sources = \"CMakeLists.txt\", \"src/*\", \"include/*\"\n\n            def layout(self):\n                cmake_layout(self)\n\n            def generate(self):\n                deps = CMakeDeps(self)\n                deps.generate()\n                tc = CMakeToolchain(self)\n                if self.settings.build_type == \"Debug\":\n                    tc.cache_variables[\"USE_MATRIX\"] = 1\n                    tc.preprocessor_definitions[\"USE_MATRIX\"] = 1\n                tc.generate()\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n\n            def package(self):\n                cmake = CMake(self)\n                cmake.install()\n\n            def package_info(self):\n                self.cpp_info.libs = [\"pkgb\"]\n\n            def requirements(self):\n                if self.settings.build_type == \"Debug\":\n                    self.requires(\"matrix/1.0\")\n        \"\"\")\n    cmake = textwrap.dedent(\"\"\"\\\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.15)\n        project(pkgb CXX)\n\n        add_library(pkgb src/pkgb.cpp)\n        target_include_directories(pkgb PUBLIC include)\n\n        if(USE_MATRIX)\n            find_package(matrix CONFIG REQUIRED)\n            target_link_libraries(pkgb PRIVATE matrix::matrix)\n        endif()\n\n        set_target_properties(pkgb PROPERTIES PUBLIC_HEADER \"include/pkgb.h\")\n        install(TARGETS pkgb)\n        \"\"\")\n    pkgb_cpp = textwrap.dedent(r\"\"\"\n        #include <iostream>\n        #include \"pkgb.h\"\n        #ifdef USE_MATRIX\n        #include \"matrix.h\"\n        #endif\n\n        void pkgb(){\n            #ifdef USE_MATRIX\n            matrix();\n            #endif\n\n            #ifdef NDEBUG\n            std::cout << \"pkgb/0.1: Hello World Release!\\n\";\n            #else\n            std::cout << \"pkgb/0.1: Hello World Debug!\\n\";\n            #endif\n        }\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile,\n            \"CMakeLists.txt\": cmake,\n            \"src/pkgb.cpp\": pkgb_cpp})\n    c.run(\"create . -s build_type=Debug -tf=\")\n    assert \"matrix/1.0\" in c.out\n    c.run(\"create . -s build_type=Release -tf=\")  # without dep to matrix\n    assert \"matrix\" not in c.out\n\n    c.save({}, clean_first=True)\n    c.run(\"new cmake_lib -d name=pkgc -d version=0.1 -d requires=pkgb/0.1\")\n    c.run(\"build . -s build_type=Debug\")\n    c.run(\"build . -s build_type=Release\")\n    # This used to crash because \"matrix::matrix\"\n    assert \"conanfile.py (pkgc/0.1): Running CMake.build()\" in c.out\n"
  },
  {
    "path": "test/functional/toolchains/cmake/cmakedeps/test_link_order.py",
    "content": "import os\nimport platform\nimport re\nimport textwrap\n\nimport pytest\nfrom jinja2 import Template\n\nfrom conan.api.model import RecipeReference\nfrom conan.test.utils.tools import TestClient\n\n\"\"\"\nCheck that the link order of libraries is preserved when using CMake generators\n    https://github.com/conan-io/conan/issues/6280\n\n\"\"\"\n\n\nconanfile = Template(textwrap.dedent(\"\"\"\n    import os\n    from conan import ConanFile\n    from conan.tools.files import copy\n\n    class Recipe(ConanFile):\n        name = \"{{ref.name}}\"\n        version = \"{{ref.version}}\"\n\n        {% if requires %}\n        requires =\n            {%- for req in requires -%}\n            \"{{ req }}\"{% if not loop.last %}, {% endif %}\n            {%- endfor -%}\n        {% endif %}\n\n        def build(self):\n            with open(\"lib\" + self.name + \".a\", \"w+\") as f:\n                f.write(\"fake library content\")\n            with open(self.name + \".lib\", \"w+\") as f:\n                f.write(\"fake library content\")\n\n            {% for it in libs_extra %}\n            with open(\"lib{{ it }}.a\", \"w+\") as f:\n                f.write(\"fake library content\")\n            with open(\"{{ it }}.lib\", \"w+\") as f:\n                f.write(\"fake library content\")\n            {% endfor %}\n\n        def package(self):\n            copy(self, \"*.a\", self.build_folder, os.path.join(self.package_folder, \"lib\"))\n            copy(self, \"*.lib\", self.build_folder, os.path.join(self.package_folder, \"lib\"))\n\n        def package_info(self):\n            self.cpp_info.includedirs = []\n            # Libraries\n            self.cpp_info.libs = [\"{{ ref.name }}\"]\n            {% for it in libs_extra %}\n            self.cpp_info.libs.append(\"{{ it }}\")\n            {% endfor %}\n            {% for it in libs_system %}\n            self.cpp_info.libs.append(\"{{ it }}\")\n            {% endfor %}\n\n            {% if system_libs %}\n            self.cpp_info.system_libs = [\n                {%- for it in system_libs -%}\n                \"{{ it }}\"{% if not loop.last %}, {% endif %}\n                {%- endfor -%}]\n            {% endif %}\n\n            {% if frameworks %}\n            self.cpp_info.frameworks.extend([\n                {%- for it in frameworks -%}\n                \"{{ it }}\"{% if not loop.last %}, {% endif %}\n                {%- endfor -%}])\n            {% endif %}\n\"\"\"))\n\nconanfile_headeronly = Template(textwrap.dedent(\"\"\"\n    from conan import ConanFile\n\n    class HeaderOnly(ConanFile):\n        name = \"{{ref.name}}\"\n        version = \"{{ref.version}}\"\n\n        {% if requires %}\n        requires =\n            {%- for req in requires -%}\n            \"{{ req }}\"{% if not loop.last %}, {% endif %}\n            {%- endfor -%}\n        {% endif %}\n\n        def package_id(self):\n            self.info.clear()\n\n        def package_info(self):\n            self.cpp_info.includedirs = []\n            # It may declare system libraries\n            {% for it in libs_system %}\n            self.cpp_info.libs.append(\"{{ it }}\")\n            {% endfor %}\n\n            {% if system_libs %}\n            self.cpp_info.system_libs = [\n                {%- for it in system_libs -%}\n                \"{{ it }}\"{% if not loop.last %}, {% endif %}\n                {%- endfor -%}]\n            {% endif %}\n\n            {% if frameworks %}\n            self.cpp_info.frameworks.extend([\n                {%- for it in frameworks -%}\n                \"{{ it }}\"{% if not loop.last %}, {% endif %}\n                {%- endfor -%}])\n            {% endif %}\n\"\"\"))\n\nmain_cpp = textwrap.dedent(\"\"\"\n    int main() {return 0;}\n\"\"\")\n\n\n@pytest.fixture(scope=\"module\")\ndef client():\n    libz_ref = RecipeReference.loads(\"libz/version\")\n    libh2_ref = RecipeReference.loads(\"header2/version\")\n    libh_ref = RecipeReference.loads(\"header/version\")\n    liba_ref = RecipeReference.loads(\"liba/version\")\n    libb_ref = RecipeReference.loads(\"libb/version\")\n    libc_ref = RecipeReference.loads(\"libc/version\")\n    libd_ref = RecipeReference.loads(\"libd/version\")\n\n    t = TestClient(path_with_spaces=False)\n    t.save({\n        'libz/conanfile.py': conanfile.render(\n            ref=libz_ref,\n            libs_extra=[\"Z2\"],\n            system_libs=[\"system_lib\"],\n            frameworks=[\"Carbon\"]),\n        'libh2/conanfile.py': conanfile_headeronly.render(\n            ref=libh2_ref,\n            system_libs=[\"header2_system_lib\"],\n            frameworks=[\"Security\"]),\n        'libh/conanfile.py': conanfile_headeronly.render(\n            ref=libh_ref,\n            requires=[libh2_ref, libz_ref],\n            system_libs=[\"header_system_lib\"],\n            frameworks=[\"CoreAudio\"]),\n        'liba/conanfile.py': conanfile.render(\n            ref=liba_ref,\n            requires=[libh_ref],\n            libs_extra=[\"A2\"],\n            system_libs=[\"system_lib\"],\n            frameworks=[\"Carbon\"]),\n        'libb/conanfile.py': conanfile.render(\n            ref=libb_ref,\n            requires=[liba_ref],\n            libs_extra=[\"B2\"],\n            system_libs=[\"system_lib\"],\n            frameworks=[\"Carbon\"]),\n        'libc/conanfile.py': conanfile.render(\n            ref=libc_ref,\n            requires=[liba_ref],\n            libs_extra=[\"C2\"],\n            system_libs=[\"system_lib\"],\n            frameworks=[\"Carbon\"]),\n        'libd/conanfile.py': conanfile.render(\n            ref=libd_ref,\n            requires=[libb_ref, libc_ref],\n            libs_extra=[\"D2\"],\n            system_libs=[\"system_lib\"],\n            frameworks=[\"Carbon\"]),\n    })\n\n    # Create all of them\n    t.run(\"create libz\")\n    t.run(\"create libh2\")\n    t.run(\"create libh\")\n    t.run(\"create liba\")\n    t.run(\"create libb\")\n    t.run(\"create libc\")\n    t.run(\"create libd\")\n    return t\n\n\ndef _validate_link_order(libs):\n    # Check that all the libraries are there:\n    assert len(libs) == 16 if platform.system() == \"Darwin\" else (13 if platform.system() == \"Linux\"\n                                                                  else 23)\n    # - Regular libs\n    ext = \".lib\" if platform.system() == \"Windows\" else \".a\"\n    prefix = \"\" if platform.system() == \"Windows\" else \"lib\"\n    expected_libs = {prefix + it + ext for it in ['libd', 'D2', 'libb', 'B2', 'libc', 'C2',\n                                                  'liba', 'A2', 'libz', 'Z2']}\n    # - System libs\n    ext_system = \".lib\" if platform.system() == \"Windows\" else \"\"\n    expected_libs.update([it + ext_system for it in ['header_system_lib',\n                                                     'header2_system_lib',\n                                                     'system_lib']])\n    # - Add MacOS frameworks\n    if platform.system() == \"Darwin\":\n        expected_libs.update(['CoreAudio', 'Security', 'Carbon'])\n    # - Add Windows libs\n    if platform.system() == \"Windows\":\n        expected_libs.update(['kernel32.lib', 'user32.lib', 'gdi32.lib', 'winspool.lib',\n                              'shell32.lib', 'ole32.lib', 'oleaut32.lib', 'uuid.lib',\n                              'comdlg32.lib', 'advapi32.lib'])\n    assert set(libs) == expected_libs\n\n    # These are the first libraries and order is mandatory\n    mandatory_1 = [prefix + it + ext for it in ['libd', 'D2', 'libb', 'B2', 'libc',\n                                                'C2', 'liba', 'A2', ]]\n    assert mandatory_1 == libs[:len(mandatory_1)]\n\n    # Then, libz ones must be before system libraries that are consuming\n    assert libs.index(prefix + 'libz' + ext) < libs.index('system_lib' + ext_system)\n    assert libs.index(prefix + 'Z2' + ext) < libs.index('system_lib' + ext_system)\n\n    if platform.system() == \"Darwin\":\n        assert libs.index('liblibz.a') < libs.index('Carbon')\n        assert libs.index('libZ2.a') < libs.index('Carbon')\n\n\ndef _get_link_order_from_cmake(content):\n    libs = []\n    for it in content.splitlines():\n        # This is for Linux and Mac\n        # Remove double spaces from output that appear in some platforms\n        line = ' '.join(it.split())\n        if 'main.cpp.o -o example' in line:\n            _, links = line.split(\"main.cpp.o -o example\")\n            for it_lib in links.split():\n                if it_lib.startswith(\"-L\") or it_lib.startswith(\"-Wl,-rpath\"):\n                    continue\n                elif it_lib.startswith(\"-l\"):\n                    libs.append(it_lib[2:])\n                elif it_lib == \"-framework\":\n                    continue\n                else:\n                    try:\n                        _, libname = it_lib.rsplit('/', 1)\n                    except ValueError:\n                        libname = it_lib\n                    finally:\n                        libs.append(libname)\n            break\n        # Windows\n        if 'example.exe\" /INCREMENTAL:NO /NOLOGO' in it:\n            for it_lib in it.split():\n                it_lib = it_lib.strip()\n                if it_lib.endswith(\".lib\"):\n                    try:\n                        _, libname = it_lib.rsplit('\\\\', 1)\n                    except ValueError:\n                        libname = it_lib\n                    finally:\n                        libs.append(libname)\n            break\n    return libs\n\n\ndef _get_link_order_from_xcode(content):\n    libs = []\n\n    # Find the right Release block in the XCode file\n    results = re.finditer(r'/\\* Release \\*/ = {', content)\n    header_found = False\n    for r in results:\n        release_section = content[r.start():].split(\"name = Release;\", 1)[0]\n        if \"-headerpad_max_install_names\" in release_section:\n            header_found = True\n            break\n    assert header_found, \"Cannot find the Release block linking the expected libraries\"\n\n    start_key = '-Wl,-headerpad_max_install_names'\n    end_key = ');'\n    libs_content = release_section.split(start_key, 1)[1].split(end_key, 1)[0]\n    libs_unstripped = libs_content.split(\",\")\n    for lib in libs_unstripped:\n        if \".a\" in lib:\n            libs.append(lib.strip('\"').rsplit('/', 1)[1])\n        elif \"-l\" in lib:\n            libs.append(lib.strip('\"')[2:])\n        elif \"-framework\" in lib:\n            libs.append(lib.strip('\"')[11:])\n    return libs\n\n\ndef _create_find_package_project(client):\n    t = TestClient(cache_folder=client.cache_folder)\n    t.save({\n        'conanfile.txt': textwrap.dedent(\"\"\"\n            [requires]\n            libd/version\n            [generators]\n            CMakeDeps\n            CMakeToolchain\n            \"\"\"),\n        'CMakeLists.txt': textwrap.dedent(\"\"\"\n            set(CMAKE_CXX_COMPILER_WORKS 1)\n            set(CMAKE_CXX_ABI_COMPILED 1)\n            cmake_minimum_required(VERSION 3.15)\n            project(executable CXX)\n\n            find_package(libd)\n            add_executable(example main.cpp)\n            target_link_libraries(example libd::libd)\n            \"\"\"),\n        'main.cpp': main_cpp\n    })\n\n    t.run(\"install . -s build_type=Release\")\n    return t\n\n\ndef _run_and_get_lib_order(t, generator):\n    if generator == \"Xcode\":\n        t.run_command(\"cmake . -G Xcode -DCMAKE_VERBOSE_MAKEFILE:BOOL=True\"\n                      \" -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake\")\n        # This is building by default the Debug configuration that contains nothing, so it works\n        t.run_command(\"cmake --build .\")\n        # This is building the release and fails because invented system libraries are missing\n        t.run_command(\"cmake --build . --config Release\", assert_error=True)\n        # Get the actual link order from the CMake call\n        libs = _get_link_order_from_xcode(t.load(os.path.join('executable.xcodeproj',\n                                                              'project.pbxproj')))\n    else:\n        t.run_command(\"cmake . -DCMAKE_VERBOSE_MAKEFILE:BOOL=True\"\n                      \" -DCMAKE_BUILD_TYPE=Release\"\n                      \" -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake\")\n        extra_build = \"--config Release\" if platform.system() == \"Windows\" else \"\"  # Windows VS\n        t.run_command(\"cmake --build . {}\".format(extra_build), assert_error=True)\n        # Get the actual link order from the CMake call\n        libs = _get_link_order_from_cmake(str(t.out))\n    return libs\n\n\n# needs at least 3.23.3 because of error with \"empty identity\"\n@pytest.mark.parametrize(\"generator\", [None, \"Xcode\"])\n@pytest.mark.tool(\"cmake\", \"3.23\")\ndef test_cmake_deps(client, generator):\n    if generator == \"Xcode\" and platform.system() != \"Darwin\":\n        pytest.skip(\"Xcode is needed\")\n\n    t = _create_find_package_project(client)\n    libs = _run_and_get_lib_order(t, generator)\n    _validate_link_order(libs)\n"
  },
  {
    "path": "test/functional/toolchains/cmake/cmakedeps/test_weird_library_names.py",
    "content": "import textwrap\n\nimport pytest\n\nfrom conan.test.assets.cmake import gen_cmakelists\nfrom conan.test.assets.sources import gen_function_h, gen_function_cpp\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.fixture(scope=\"module\")\ndef client_weird_lib_name():\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        import os, platform\n        from conan import ConanFile\n        from conan.tools.cmake import CMake, cmake_layout\n        from conan.tools.files import copy\n\n        class Pkg(ConanFile):\n            exports_sources = \"CMakeLists.txt\", \"src/*\"\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            generators = \"CMakeToolchain\", \"CMakeDeps\"\n\n            def layout(self):\n                cmake_layout(self)\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n\n            def package(self):\n                copy(self, \"*.h\", os.path.join(self.source_folder, \"src\"),\n                                  os.path.join(self.package_folder, \"include\"))\n                copy(self, \"*.lib\", self.build_folder, os.path.join(self.package_folder, \"lib\"),\n                     keep_path=False)\n                copy(self, \"*.a\", self.build_folder, os.path.join(self.package_folder, \"lib\"),\n                     keep_path=False)\n                ext = \"a\" if platform.system() != \"Windows\" else \"lib\"\n                prefix = \"lib\" if platform.system() != \"Windows\" else \"\"\n                os.chdir(os.path.join(self.package_folder, \"lib\"))\n                os.rename(\"{}hello_0.1.{}\".format(prefix, ext),\n                          \"{}he!llo@0.1.{}\".format(prefix, ext))\n\n            def package_info(self):\n                self.cpp_info.libs = [\"he!llo@0.1\"]\n            \"\"\")\n\n    hdr = gen_function_h(name=\"hello\")\n    src = gen_function_cpp(name=\"hello\")\n    cmake = gen_cmakelists(libname=\"hello_0.1\", libsources=[\"src/hello.cpp\"])\n\n    c.save({\"src/hello.h\": hdr,\n            \"src/hello.cpp\": src,\n            \"CMakeLists.txt\": cmake,\n            \"conanfile.py\": conanfile})\n    c.run(\"create . --name=hello --version=0.1\")\n    return c\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_cmakedeps(client_weird_lib_name):\n    c = client_weird_lib_name\n    c.save({}, clean_first=True)\n    c.run(\"new cmake_lib -d name=chat -d version=0.1 -d requires=hello/0.1\")\n    c.run(\"create .\")\n    assert \"chat/0.1: Created package\" in c.out\n"
  },
  {
    "path": "test/functional/toolchains/cmake/test_cmake.py",
    "content": "import os\nimport platform\nimport textwrap\nimport time\n\nimport pytest\n\nfrom conan.test.assets.cmake import gen_cmakelists\nfrom conan.test.assets.sources import gen_function_cpp, gen_function_h\nfrom test.functional.utils import check_vs_runtime, check_exe_run\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.tool(\"cmake\", \"3.15\")\n@pytest.mark.tool(\"mingw64\")\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Needs windows\")\ndef test_simple_cmake_mingw():\n    client = TestClient()\n    client.run(\"new cmake_lib -d name=hello -d version=1.0\")\n    client.save({\"mingw\": \"\"\"\n        [settings]\n        os=Windows\n        arch=x86_64\n        build_type=Release\n        compiler=gcc\n        compiler.exception=seh\n        compiler.libcxx=libstdc++11\n        compiler.threads=win32\n        compiler.version=11.2\n        compiler.cppstd=17\n        \"\"\"})\n    client.run(\"create . --profile=mingw\")\n    build_folder = client.created_test_build_folder(\"hello/1.0\")\n    # FIXME: Note that CI contains 10.X, so it uses another version rather than the profile one\n    #  and no one notices. It would be good to have some details in confuser.py to be consistent\n    check_exe_run(client.out, \"hello/1.0:\", \"gcc\", None, \"Release\", \"x86_64\", \"17\",\n                  subsystem=\"mingw64\", extra_msg=\"Hello World\", cxx11_abi=\"1\")\n    check_vs_runtime(f\"test_package/{build_folder}/example.exe\", client, \"15\",\n                     build_type=\"Release\", static_runtime=False, subsystem=\"mingw64\")\n\n# TODO: How to link with mingw statically?\n\n\n@pytest.mark.tool(\"cmake\")\nclass Base:\n\n    conanfile = textwrap.dedent(r\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake, CMakeToolchain\n        class App(ConanFile):\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            requires = \"hello/0.1\"\n            generators = \"CMakeDeps\"\n            options = {\"shared\": [True, False], \"fPIC\": [True, False]}\n            default_options = {\"shared\": False, \"fPIC\": True}\n            implements = [\"auto_shared_fpic\", \"auto_header_only\"]\n\n            def generate(self):\n                tc = CMakeToolchain(self)\n                tc.variables[\"MYVAR\"] = \"MYVAR_VALUE\"\n                tc.variables[\"MYVAR2\"] = \"MYVAR_VALUE2\"\n                tc.variables.debug[\"MYVAR_CONFIG\"] = \"MYVAR_DEBUG\"\n                tc.variables.release[\"MYVAR_CONFIG\"] = \"MYVAR_RELEASE\"\n                tc.variables.debug[\"MYVAR2_CONFIG\"] = \"MYVAR2_DEBUG\"\n                tc.variables.release[\"MYVAR2_CONFIG\"] = \"MYVAR2_RELEASE\"\n                tc.preprocessor_definitions[\"MYDEFINE\"] = \"\\\"MYDEF_VALUE\\\"\"\n                tc.preprocessor_definitions[\"MYDEFINEINT\"] = 42\n                tc.preprocessor_definitions.debug[\"MYDEFINE_CONFIG\"] = \"\\\"MYDEF_DEBUG\\\"\"\n                tc.preprocessor_definitions.release[\"MYDEFINE_CONFIG\"] = \"\\\"MYDEF_RELEASE\\\"\"\n                tc.preprocessor_definitions.debug[\"MYDEFINEINT_CONFIG\"] = 421\n                tc.preprocessor_definitions.release[\"MYDEFINEINT_CONFIG\"] = 422\n                tc.generate()\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n        \"\"\")\n\n    lib_h = gen_function_h(name=\"app\")\n    lib_cpp = gen_function_cpp(name=\"app\", msg=\"App\", includes=[\"hello\"], calls=[\"hello\"],\n                               preprocessor=[\"MYVAR\", \"MYVAR_CONFIG\", \"MYDEFINE\", \"MYDEFINE_CONFIG\",\n                                             \"MYDEFINEINT\", \"MYDEFINEINT_CONFIG\"])\n    main = gen_function_cpp(name=\"main\", includes=[\"app\"], calls=[\"app\"])\n\n    cmakelist = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_C_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        set(CMAKE_C_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.15)\n        project(App C CXX)\n\n        if(NOT CMAKE_TOOLCHAIN_FILE)\n            message(FATAL \">> Not using toolchain\")\n        endif()\n        message(\">> CMAKE_GENERATOR_PLATFORM: ${CMAKE_GENERATOR_PLATFORM}\")\n        message(\">> CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}\")\n        message(\">> CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}\")\n        message(\">> CMAKE_CXX_FLAGS_DEBUG: ${CMAKE_CXX_FLAGS_DEBUG}\")\n        message(\">> CMAKE_CXX_FLAGS_RELEASE: ${CMAKE_CXX_FLAGS_RELEASE}\")\n        message(\">> CMAKE_C_FLAGS: ${CMAKE_C_FLAGS}\")\n        message(\">> CMAKE_C_FLAGS_DEBUG: ${CMAKE_C_FLAGS_DEBUG}\")\n        message(\">> CMAKE_C_FLAGS_RELEASE: ${CMAKE_C_FLAGS_RELEASE}\")\n        message(\">> CMAKE_SHARED_LINKER_FLAGS: ${CMAKE_SHARED_LINKER_FLAGS}\")\n        message(\">> CMAKE_EXE_LINKER_FLAGS: ${CMAKE_EXE_LINKER_FLAGS}\")\n        message(\">> CMAKE_CXX_STANDARD: ${CMAKE_CXX_STANDARD}\")\n        message(\">> CMAKE_CXX_EXTENSIONS: ${CMAKE_CXX_EXTENSIONS}\")\n        message(\">> CMAKE_POSITION_INDEPENDENT_CODE: ${CMAKE_POSITION_INDEPENDENT_CODE}\")\n        message(\">> CMAKE_SKIP_RPATH: ${CMAKE_SKIP_RPATH}\")\n        message(\">> CMAKE_INSTALL_NAME_DIR: ${CMAKE_INSTALL_NAME_DIR}\")\n        message(\">> CMAKE_MODULE_PATH: ${CMAKE_MODULE_PATH}\")\n        message(\">> CMAKE_PREFIX_PATH: ${CMAKE_PREFIX_PATH}\")\n        message(\">> BUILD_SHARED_LIBS: ${BUILD_SHARED_LIBS}\")\n        get_directory_property(_COMPILE_DEFS DIRECTORY ${CMAKE_SOURCE_DIR} COMPILE_DEFINITIONS)\n        message(\">> COMPILE_DEFINITIONS: ${_COMPILE_DEFS}\")\n\n        find_package(hello REQUIRED)\n        add_library(app_lib app_lib.cpp)\n        target_link_libraries(app_lib PRIVATE hello::hello)\n        target_compile_definitions(app_lib PRIVATE MYVAR=\"${MYVAR}\")\n        target_compile_definitions(app_lib PRIVATE MYVAR_CONFIG=\"${MYVAR_CONFIG}\")\n        add_executable(app app.cpp)\n        target_link_libraries(app PRIVATE app_lib)\n        \"\"\")\n\n    @pytest.fixture(autouse=True)\n    def setup(self):\n        self.client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import save\n            import os\n            class Pkg(ConanFile):\n                settings = \"build_type\"\n                def package(self):\n                    save(self, os.path.join(self.package_folder, \"include/hello.h\"),\n                         '''#include <iostream>\n                         void hello(){std::cout<< \"Hello: %s\" <<std::endl;}'''\n                         % self.settings.build_type)\n            \"\"\")\n        self.client.save({\"conanfile.py\": conanfile})\n        self.client.run(\"create . --name=hello --version=0.1 -s build_type=Debug\")\n        self.client.run(\"create . --name=hello --version=0.1 -s build_type=Release\")\n\n        # Prepare the actual consumer package\n        self.client.save({\"conanfile.py\": self.conanfile,\n                          \"CMakeLists.txt\": self.cmakelist,\n                          \"app.cpp\": self.main,\n                          \"app_lib.cpp\": self.lib_cpp,\n                          \"app.h\": self.lib_h})\n\n    def _run_build(self, settings=None, options=None):\n        # Build the profile according to the settings provided\n        settings = settings or {}\n        settings = \" \".join('-s %s=\"%s\"' % (k, v) for k, v in settings.items() if v)\n        options = \" \".join(\"-o %s=%s\" % (k, v) for k, v in options.items()) if options else \"\"\n\n        # Run the configure corresponding to this test case\n        build_directory = os.path.join(self.client.current_folder, \"build\").replace(\"\\\\\", \"/\")\n        with self.client.chdir(build_directory):\n            self.client.run(\"build .. %s %s -of=.\" % (settings, options))\n            install_out = self.client.out\n        return install_out\n\n    def _modify_code(self):\n        lib_cpp = gen_function_cpp(name=\"app\", msg=\"AppImproved\", includes=[\"hello\"],\n                                   calls=[\"hello\"], preprocessor=[\"MYVAR\", \"MYVAR_CONFIG\",\n                                                                  \"MYDEFINE\", \"MYDEFINE_CONFIG\",\n                                                                  \"MYDEFINEINT\",\n                                                                  \"MYDEFINEINT_CONFIG\"])\n        self.client.save({\"app_lib.cpp\": lib_cpp})\n\n        content = self.client.load(\"CMakeLists.txt\")\n        content = content.replace(\">>\", \"++>>\")\n        self.client.save({\"CMakeLists.txt\": content})\n\n    def _incremental_build(self, build_type=None):\n        build_directory = os.path.join(self.client.current_folder, \"build\").replace(\"\\\\\", \"/\")\n        with self.client.chdir(build_directory):\n            config = \"--config %s\" % build_type if build_type else \"\"\n            self.client.run_command(\"cmake --build . %s\" % config)\n\n    def _run_app(self, build_type, bin_folder=False, msg=\"App\", dyld_path=None):\n        if dyld_path:\n            build_directory = os.path.join(self.client.current_folder, \"build\").replace(\"\\\\\", \"/\")\n            command_str = 'DYLD_LIBRARY_PATH=\"%s\" build/app' % build_directory\n        else:\n            command_str = \"build/%s/app.exe\" % build_type if bin_folder else \"build/app\"\n            if platform.system() == \"Windows\":\n                command_str = command_str.replace(\"/\", \"\\\\\")\n        self.client.run_command(command_str)\n        assert \"Hello: %s\" % build_type in self.client.out\n        assert \"%s: %s!\" % (msg, build_type) in self.client.out\n        assert \"MYVAR: MYVAR_VALUE\" in self.client.out\n        assert \"MYVAR_CONFIG: MYVAR_%s\" % build_type.upper() in self.client.out\n        assert \"MYDEFINE: MYDEF_VALUE\" in self.client.out\n        assert \"MYDEFINE_CONFIG: MYDEF_%s\" % build_type.upper() in self.client.out\n        assert \"MYDEFINEINT: 42\" in self.client.out\n        value = 421 if build_type == \"Debug\" else 422\n        assert f\"MYDEFINEINT_CONFIG: {value}\" in self.client.out\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Only for windows\")\nclass TestWin(Base):\n    @pytest.mark.parametrize(\"compiler, build_type, runtime, version, cppstd, arch, shared\",\n                             [(\"msvc\", \"Debug\", \"static\", \"191\", \"14\", \"x86\", True),\n                              (\"msvc\", \"Release\", \"dynamic\", \"191\", \"17\", \"x86_64\", False)]\n                             )\n    def test_toolchain_win(self, compiler, build_type, runtime, version, cppstd, arch, shared):\n        settings = {\"compiler\": compiler,\n                    \"compiler.version\": version,\n                    \"compiler.runtime\": runtime,\n                    \"compiler.cppstd\": cppstd,\n                    \"arch\": arch,\n                    \"build_type\": build_type,\n                    }\n        options = {\"shared\": shared}\n        self.client.save_home({\"global.conf\": \"tools.build:jobs=1\"})\n        self._run_build(settings, options)\n        assert ('cmake -G \"Visual Studio 15 2017\" '\n                '-DCMAKE_TOOLCHAIN_FILE=\"conan_toolchain.cmake\"') in self.client.out\n\n        generator_platform = \"x64\" if arch == \"x86_64\" else \"Win32\"\n        arch_flag = \"x64\" if arch == \"x86_64\" else \"X86\"\n        shared_str = \"ON\" if shared else \"OFF\"\n        vals = {\"CMAKE_GENERATOR_PLATFORM\": generator_platform,\n                \"CMAKE_BUILD_TYPE\": \"\",\n                \"CMAKE_CXX_FLAGS\": \"/MP1 /DWIN32 /D_WINDOWS /GR /EHsc\",\n                \"CMAKE_CXX_FLAGS_DEBUG\": \"/Zi /Ob0 /Od /RTC1\",\n                \"CMAKE_CXX_FLAGS_RELEASE\": \"/O2 /Ob2 /DNDEBUG\",\n                \"CMAKE_C_FLAGS\": \"/MP1 /DWIN32 /D_WINDOWS\",\n                \"CMAKE_C_FLAGS_DEBUG\": \"/Zi /Ob0 /Od /RTC1\",\n                \"CMAKE_C_FLAGS_RELEASE\": \"/O2 /Ob2 /DNDEBUG\",\n                \"CMAKE_SHARED_LINKER_FLAGS\": \"/machine:%s\" % arch_flag,\n                \"CMAKE_EXE_LINKER_FLAGS\": \"/machine:%s\" % arch_flag,\n                \"CMAKE_CXX_STANDARD\": cppstd,\n                \"CMAKE_CXX_EXTENSIONS\": \"OFF\",\n                \"BUILD_SHARED_LIBS\": shared_str}\n\n        def _verify_out(marker=\">>\"):\n            if shared:\n                assert \"app_lib.dll\" in self.client.out\n            else:\n                assert \"app_lib.dll\" not in self.client.out\n\n            out = str(self.client.out).splitlines()\n            for k, v in vals.items():\n                assert \"%s %s: %s\" % (marker, k, v) in out\n\n        _verify_out()\n\n        opposite_build_type = \"Release\" if build_type == \"Debug\" else \"Debug\"\n        settings[\"build_type\"] = opposite_build_type\n        self._run_build(settings, options)\n\n        self._run_app(\"Release\", bin_folder=True)\n        check_exe_run(self.client.out, \"main\", \"msvc\", version, \"Release\", arch, cppstd,\n                      {\"MYVAR\": \"MYVAR_VALUE\",\n                       \"MYVAR_CONFIG\": \"MYVAR_RELEASE\",\n                       \"MYDEFINE\": \"MYDEF_VALUE\",\n                       \"MYDEFINE_CONFIG\": \"MYDEF_RELEASE\"\n                       })\n        self._run_app(\"Debug\", bin_folder=True)\n        check_exe_run(self.client.out, \"main\", \"msvc\", version, \"Debug\", arch, cppstd,\n                      {\"MYVAR\": \"MYVAR_VALUE\",\n                       \"MYVAR_CONFIG\": \"MYVAR_DEBUG\",\n                       \"MYDEFINE\": \"MYDEF_VALUE\",\n                       \"MYDEFINE_CONFIG\": \"MYDEF_DEBUG\"\n                       })\n\n        static_runtime = True if runtime == \"static\" or \"MT\" in runtime else False\n        check_vs_runtime(\"build/Release/app.exe\", self.client, \"15\", build_type=\"Release\",\n                         static_runtime=static_runtime)\n        check_vs_runtime(\"build/Debug/app.exe\", self.client, \"15\", build_type=\"Debug\",\n                         static_runtime=static_runtime)\n\n        self._modify_code()\n        time.sleep(1)\n        self._incremental_build(build_type=build_type)\n        _verify_out(marker=\"++>>\")\n        self._run_app(build_type, bin_folder=True, msg=\"AppImproved\")\n        self._incremental_build(build_type=opposite_build_type)\n        self._run_app(opposite_build_type, bin_folder=True, msg=\"AppImproved\")\n\n    @pytest.mark.parametrize(\"build_type, libcxx, version, cppstd, arch, shared\",\n                             [(\"Debug\", \"libstdc++\", \"4.9\", \"98\", \"x86_64\", True),\n                              (\"Release\", \"libstdc++\", \"4.9\", \"11\", \"x86_64\", False)])\n    @pytest.mark.tool(\"mingw64\")\n    @pytest.mark.tool(\"cmake\", \"3.15\")\n    def test_toolchain_mingw_win(self, build_type, libcxx, version, cppstd, arch, shared):\n        # FIXME: The version and cppstd are wrong, toolchain doesn't enforce it\n        settings = {\"compiler\": \"gcc\",\n                    \"compiler.version\": version,\n                    \"compiler.libcxx\": libcxx,\n                    \"compiler.cppstd\": cppstd,\n                    \"arch\": arch,\n                    \"build_type\": build_type,\n                    }\n        options = {\"shared\": shared}\n        self._run_build(settings, options)\n        assert \"The C compiler identification is GNU\" in self.client.out\n        assert ('cmake -G \"MinGW Makefiles\" '\n                '-DCMAKE_TOOLCHAIN_FILE=\"conan_toolchain.cmake\"') in self.client.out\n        assert '-DCMAKE_SH=\"CMAKE_SH-NOTFOUND\"' in self.client.out\n\n        def _verify_out(marker=\">>\"):\n            cmake_vars = {\"CMAKE_GENERATOR_PLATFORM\": \"\",\n                          \"CMAKE_BUILD_TYPE\": build_type,\n                          \"CMAKE_CXX_FLAGS\": \"-m64\",\n                          \"CMAKE_CXX_FLAGS_DEBUG\": \"-g\",\n                          \"CMAKE_CXX_FLAGS_RELEASE\": \"-O3 -DNDEBUG\",\n                          \"CMAKE_C_FLAGS\": \"-m64\",\n                          \"CMAKE_C_FLAGS_DEBUG\": \"-g\",\n                          \"CMAKE_C_FLAGS_RELEASE\": \"-O3 -DNDEBUG\",\n                          \"CMAKE_SHARED_LINKER_FLAGS\": \"-m64\",\n                          \"CMAKE_EXE_LINKER_FLAGS\": \"-m64\",\n                          \"CMAKE_CXX_STANDARD\": cppstd,\n                          \"CMAKE_CXX_EXTENSIONS\": \"OFF\",\n                          \"BUILD_SHARED_LIBS\": \"ON\" if shared else \"OFF\"}\n            if shared:\n                assert \"app_lib.dll\" in self.client.out\n            else:\n                assert \"app_lib.dll\" not in self.client.out\n\n            out = str(self.client.out).splitlines()\n            for k, v in cmake_vars.items():\n                assert \"%s %s: %s\" % (marker, k, v) in out\n\n        _verify_out()\n        self._run_app(build_type)\n        check_exe_run(self.client.out, \"main\", \"gcc\", None, build_type, arch, None,\n                      {\"MYVAR\": \"MYVAR_VALUE\",\n                       \"MYVAR_CONFIG\": \"MYVAR_{}\".format(build_type.upper()),\n                       \"MYDEFINE\": \"MYDEF_VALUE\",\n                       \"MYDEFINE_CONFIG\": \"MYDEF_{}\".format(build_type.upper())\n                       }, subsystem=\"mingw64\")\n\n        self._modify_code()\n        time.sleep(2)\n        self._incremental_build()\n        _verify_out(marker=\"++>>\")\n        self._run_app(build_type, msg=\"AppImproved\")\n\n\n@pytest.mark.skipif(platform.system() != \"Linux\", reason=\"Only for Linux\")\nclass TestLinux(Base):\n    @pytest.mark.parametrize(\"build_type, cppstd, arch, libcxx, shared\",\n                             [(\"Debug\",  \"14\", \"x86\", \"libstdc++\", True),\n                              (\"Release\", \"gnu14\", \"x86_64\", \"libstdc++11\", False)])\n    def test_toolchain_linux(self, build_type, cppstd, arch, libcxx, shared):\n        settings = {\"compiler\": \"gcc\",\n                    \"compiler.cppstd\": cppstd,\n                    \"compiler.libcxx\": libcxx,\n                    \"arch\": arch,\n                    \"build_type\": build_type}\n        self._run_build(settings, {\"shared\": shared})\n        assert ('cmake -G \"Unix Makefiles\" '\n                '-DCMAKE_TOOLCHAIN_FILE=\"conan_toolchain.cmake\"') in self.client.out\n\n        extensions_str = \"ON\" if \"gnu\" in cppstd else \"OFF\"\n        arch_str = \"-m32\" if arch == \"x86\" else \"-m64\"\n        cxx11_abi_str = \"_GLIBCXX_USE_CXX11_ABI=0;\" if libcxx == \"libstdc++\" else \"\"\n        defines = '%sMYDEFINE=\"MYDEF_VALUE\";MYDEFINEINT=42;' \\\n                  '$<$<CONFIG:debug>:MYDEFINE_CONFIG=\"MYDEF_DEBUG\">' \\\n                  '$<$<CONFIG:release>:MYDEFINE_CONFIG=\"MYDEF_RELEASE\">;' \\\n                  '$<$<CONFIG:debug>:MYDEFINEINT_CONFIG=421>' \\\n                  '$<$<CONFIG:release>:MYDEFINEINT_CONFIG=422>' % cxx11_abi_str\n        vals = {\"CMAKE_CXX_STANDARD\": \"14\",\n                \"CMAKE_CXX_EXTENSIONS\": extensions_str,\n                \"CMAKE_BUILD_TYPE\": build_type,\n                \"CMAKE_CXX_FLAGS\": arch_str,\n                \"CMAKE_CXX_FLAGS_DEBUG\": \"-g\",\n                \"CMAKE_CXX_FLAGS_RELEASE\": \"-O3 -DNDEBUG\",\n                \"CMAKE_C_FLAGS\": arch_str,\n                \"CMAKE_C_FLAGS_DEBUG\": \"-g\",\n                \"CMAKE_C_FLAGS_RELEASE\": \"-O3 -DNDEBUG\",\n                \"CMAKE_SHARED_LINKER_FLAGS\": arch_str,\n                \"CMAKE_EXE_LINKER_FLAGS\": arch_str,\n                \"COMPILE_DEFINITIONS\": defines,\n                # fPIC is managed automatically depending on the shared option value\n                # if implements = [\"auto_shared_fpic\", \"auto_header_only\"]\n                \"CMAKE_POSITION_INDEPENDENT_CODE\": \"ON\" if not shared else \"\"\n                }\n\n        def _verify_out(marker=\">>\"):\n            if shared:\n                assert \"libapp_lib.so\" in self.client.out\n            else:\n                assert \"libapp_lib.a\" in self.client.out\n\n            out = str(self.client.out).splitlines()\n            for k, v in vals.items():\n                assert \"%s %s: %s\" % (marker, k, v) in out\n\n        _verify_out()\n\n        self._run_app(build_type)\n\n        self._modify_code()\n        self._incremental_build()\n        _verify_out(marker=\"++>>\")\n        self._run_app(build_type, msg=\"AppImproved\")\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only for Apple\")\nclass TestApple(Base):\n    @pytest.mark.parametrize(\"build_type, cppstd, shared\",\n                             [(\"Debug\",  \"14\",  True),\n                              (\"Release\", \"\", False)])\n    def test_toolchain_apple(self, build_type, cppstd, shared):\n        settings = {\"compiler\": \"apple-clang\",\n                    \"compiler.cppstd\": cppstd,\n                    \"build_type\": build_type}\n        self._run_build(settings, {\"shared\": shared})\n\n        assert ('cmake -G \"Unix Makefiles\" '\n                '-DCMAKE_TOOLCHAIN_FILE=\"conan_toolchain.cmake\"') in self.client.out\n\n        extensions_str = \"OFF\" if cppstd else \"\"\n        vals = {\"CMAKE_CXX_STANDARD\": cppstd,\n                \"CMAKE_CXX_EXTENSIONS\": extensions_str,\n                \"CMAKE_BUILD_TYPE\": build_type,\n                \"CMAKE_CXX_FLAGS_DEBUG\": \"-g\",\n                \"CMAKE_CXX_FLAGS_RELEASE\": \"-O3 -DNDEBUG\",\n                \"CMAKE_C_FLAGS_DEBUG\": \"-g\",\n                \"CMAKE_C_FLAGS_RELEASE\": \"-O3 -DNDEBUG\",\n                \"CMAKE_INSTALL_NAME_DIR\": \"\"\n                }\n\n        arch_flags = {\n            \"CMAKE_C_FLAGS\": \"-m64\",\n            \"CMAKE_CXX_FLAGS\": \"-m64 -stdlib=libc++\",\n            \"CMAKE_SHARED_LINKER_FLAGS\": \"-m64\",\n            \"CMAKE_EXE_LINKER_FLAGS\": \"-m64\",\n        }\n        host_profile = self.client.get_default_host_profile()\n        if host_profile.settings.get(\"arch\") != \"x86_64\":\n            arch_flags = {\"CMAKE_CXX_FLAGS\": \"-stdlib=libc++\"}\n        vals.update(arch_flags)\n\n        def _verify_out(marker=\">>\"):\n            if shared:\n                assert \"libapp_lib.dylib\" in self.client.out\n            else:\n                if marker == \">>\":\n                    assert \"libapp_lib.a\" in self.client.out\n                else:  # Incremental build not the same msg\n                    assert \"Built target app_lib\" in self.client.out\n            out = str(self.client.out).splitlines()\n            for k, v in vals.items():\n                assert \"%s %s: %s\" % (marker, k, v) in out\n\n        _verify_out()\n\n        self._run_app(build_type, dyld_path=shared)\n\n        self._modify_code()\n        time.sleep(1)\n        self._incremental_build()\n        _verify_out(marker=\"++>>\")\n        self._run_app(build_type, dyld_path=shared, msg=\"AppImproved\")\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Only for windows\")\ndef test_msvc_vs_versiontoolset():\n    settings = {\"compiler\": \"msvc\",\n                \"compiler.version\": \"191\",\n                \"compiler.runtime\": \"static\",\n                \"compiler.cppstd\": \"14\",\n                \"arch\": \"x86_64\",\n                \"build_type\": \"Release\",\n                }\n    client = TestClient()\n    client.save_home({\"global.conf\": \"tools.microsoft.msbuild:vs_version=15\"})\n    conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.cmake import CMake\n            class App(ConanFile):\n                settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n                generators = \"CMakeToolchain\"\n                options = {\"shared\": [True, False], \"fPIC\": [True, False]}\n                default_options = {\"shared\": False, \"fPIC\": True}\n                exports_sources = \"*\"\n\n                def build(self):\n                    cmake = CMake(self)\n                    cmake.configure()\n                    cmake.build()\n                    self.run(r\"Release\\\\myapp.exe\")\n            \"\"\")\n    cmakelists = gen_cmakelists(appname=\"myapp\", appsources=[\"app.cpp\"])\n    main = gen_function_cpp(name=\"main\")\n    client.save({\"conanfile.py\": conanfile,\n                 \"CMakeLists.txt\": cmakelists,\n                 \"app.cpp\": main,\n                 })\n    settings = \" \".join('-s %s=\"%s\"' % (k, v) for k, v in settings.items() if v)\n    client.run(\"create . --name=app --version=1.0 {}\".format(settings))\n    assert '-G \"Visual Studio 15 2017\"' in client.out\n\n    check_exe_run(client.out, \"main\", \"msvc\", \"191\",\n                  \"Release\", \"x86_64\", \"14\")\n\n\n@pytest.mark.tool(\"cmake\")\nclass TestCMakeInstall:\n\n    def test_install(self):\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.cmake import CMake, CMakeToolchain\n            class App(ConanFile):\n                settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n                exports_sources = \"CMakeLists.txt\", \"header.h\"\n                def generate(self):\n                    tc = CMakeToolchain(self)\n                    tc.generate()\n                def build(self):\n                    cmake = CMake(self)\n                    cmake.configure()\n                def package(self):\n                    cmake = CMake(self)\n                    cmake.install()\n            \"\"\")\n\n        cmakelist = textwrap.dedent(\"\"\"\n            cmake_minimum_required(VERSION 2.8)\n            project(App NONE)\n            install(FILES header.h DESTINATION include)\n            \"\"\")\n        client = TestClient(path_with_spaces=False)\n        client.save({\"conanfile.py\": conanfile,\n                     \"CMakeLists.txt\": cmakelist,\n                     \"header.h\": \"# my header file\"})\n\n        # The create flow must work\n        client.run(\"create . --name=pkg --version=0.1 -c tools.build:verbosity=verbose \"\n                   \"-c tools.compilation:verbosity=verbose\")\n        assert \"--loglevel=VERBOSE\" in client.out\n        assert \"unrecognized option\" not in client.out\n        assert \"--verbose\" in client.out\n        assert \"pkg/0.1: package(): Packaged 1 '.h' file: header.h\" in client.out\n        package_folder = client.created_layout().package()\n        assert os.path.exists(os.path.join(package_folder, \"include\", \"header.h\"))\n\n    def test_install_in_build(self):\n        \"\"\"\n        test that we can do a ``cmake.install()`` inside the ``build()`` method without\n        crashing\n        \"\"\"\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.cmake import CMake, CMakeToolchain\n            class App(ConanFile):\n                settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n\n                def generate(self):\n                    tc = CMakeToolchain(self)\n                    tc.generate()\n                def build(self):\n                    cmake = CMake(self)\n                    cmake.configure()\n                    cmake.install()\n            \"\"\")\n\n        cmakelist = textwrap.dedent(\"\"\"\n            cmake_minimum_required(VERSION 2.8)\n            project(App NONE)\n            install(FILES header.h DESTINATION include)\n            \"\"\")\n        client = TestClient(path_with_spaces=False)\n        client.save({\"conanfile.py\": conanfile,\n                     \"CMakeLists.txt\": cmakelist,\n                     \"header.h\": \"# my header file\"})\n\n        # The create flow must work\n        client.run(\"build .\")\n        assert \"conanfile.py: RUN: cmake --install\" in client.out\n\n\n@pytest.mark.tool(\"cmake\")\nclass TestCmakeTestMethod:\n    \"\"\"\n    test the cmake.test() helper\n    \"\"\"\n    def test_test(self, matrix_client_shared):\n        c = matrix_client_shared\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.cmake import CMake\n            class App(ConanFile):\n                settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n                generators = \"CMakeDeps\", \"CMakeToolchain\", \"VirtualBuildEnv\", \"VirtualRunEnv\"\n                exports_sources = \"CMakeLists.txt\", \"example.cpp\"\n\n                def build_requirements(self):\n                    self.test_requires(\"matrix/1.0\")\n\n                def build(self):\n                    cmake = CMake(self)\n                    cmake.configure()\n                    cmake.build()\n                    cmake.test()\n                    cmake.ctest()\n            \"\"\")\n\n        cmakelist = textwrap.dedent(\"\"\"\n            set(CMAKE_CXX_COMPILER_WORKS 1)\n            set(CMAKE_CXX_ABI_COMPILED 1)\n            cmake_minimum_required(VERSION 3.15)\n            project(App CXX)\n            find_package(matrix CONFIG REQUIRED)\n            add_executable(example example.cpp)\n            target_link_libraries(example matrix::matrix)\n\n            enable_testing()\n            add_test(NAME example\n                      COMMAND example)\n            \"\"\")\n\n        c.save({\"conanfile.py\": conanfile,\n                \"CMakeLists.txt\": cmakelist,\n                \"example.cpp\": gen_function_cpp(name=\"main\", includes=[\"matrix\"], calls=[\"matrix\"])},\n               clean_first=True)\n\n        # The create flow must work\n        c.run(\"create . --name=pkg --version=0.1 -pr:b=default -o matrix*:shared=True\")\n        assert str(c.out).count(\"1/1 Test #1: example ..........................   Passed\") == 2\n        assert \"pkg/0.1: RUN: ctest --build-config Release --parallel\"\n\n\n@pytest.mark.tool(\"cmake\")\nclass TestCMakeOverrideCache:\n\n    def test_cmake_cache_variables(self):\n        # https://github.com/conan-io/conan/issues/7832\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.cmake import CMake, CMakeToolchain\n            class App(ConanFile):\n                settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n                exports_sources = \"CMakeLists.txt\"\n                def generate(self):\n                    toolchain = CMakeToolchain(self)\n                    toolchain.variables[\"my_config_string\"] = \"my new value\"\n                    toolchain.generate()\n                def build(self):\n                    cmake = CMake(self)\n                    cmake.configure()\n            \"\"\")\n\n        cmakelist = textwrap.dedent(\"\"\"\n            cmake_minimum_required(VERSION 3.7)\n            project(my_project NONE)\n            set(my_config_string \"default value\" CACHE STRING \"my config string\")\n            message(STATUS \"VALUE OF CONFIG STRING: ${my_config_string}\")\n            \"\"\")\n        client = TestClient()\n        client.save({\"conanfile.py\": conanfile,\n                     \"CMakeLists.txt\": cmakelist})\n        client.run(\"build .\")\n        assert \"VALUE OF CONFIG STRING: my new value\" in client.out\n\n\n@pytest.mark.tool(\"cmake\")\nclass TestCMakeFindPackagePreferConfig:\n\n    def test_prefer_config(self):\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.cmake import CMake\n            class App(ConanFile):\n                settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n                generators = \"CMakeToolchain\"\n                def build(self):\n                    cmake = CMake(self)\n                    cmake.configure()\n            \"\"\")\n\n        cmakelist = textwrap.dedent(\"\"\"\n            cmake_minimum_required(VERSION 3.15)\n            project(my_project NONE)\n            find_package(Comandante REQUIRED)\n            \"\"\")\n\n        find = 'message(STATUS \"using FindComandante.cmake\")'\n        config = 'message(STATUS \"using ComandanteConfig.cmake\")'\n\n        profile = textwrap.dedent(\"\"\"\n            include(default)\n            [conf]\n            tools.cmake.cmaketoolchain:find_package_prefer_config={}\n            \"\"\")\n\n        client = TestClient()\n        client.save({\"conanfile.py\": conanfile,\n                     \"CMakeLists.txt\": cmakelist,\n                     \"FindComandante.cmake\": find,\n                     \"ComandanteConfig.cmake\": config,\n                     \"profile_true\": profile.format(True),\n                     \"profile_false\": profile.format(False)})\n\n        client.run(\"build .\")\n        assert \"using ComandanteConfig.cmake\" in client.out\n\n        client.run(\"build . --profile=profile_true\")\n        assert \"using ComandanteConfig.cmake\" in client.out\n\n        client.run(\"build . --profile=profile_false\")\n        assert \"using FindComandante.cmake\" in client.out\n"
  },
  {
    "path": "test/functional/toolchains/cmake/test_cmake_and_no_soname_flag.py",
    "content": "import os\nimport platform\nimport shutil\n\nimport pytest\n\nfrom conan.tools.env.environment import environment_wrap_command\nfrom conan.tools.files import replace_in_file\nfrom conan.test.utils.mocks import ConanFileMock\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.skipif(platform.system() != \"Linux\", reason=\"Only Linux\")\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.parametrize(\"nosoname_property\", [\n    True,  # without SONAME\n    False  # By default, with SONAME\n])\ndef test_no_soname_flag(nosoname_property):\n    \"\"\" This test case is testing this graph structure:\n            *   'Executable' -> 'LibB' -> 'LibNoSoname'\n        Where:\n            *   LibNoSoname: is a package built as shared and without the SONAME flag.\n            *   LibB: is a package which requires LibNoSoname.\n            *   Executable: is the final consumer building an application and depending on OtherLib.\n        How:\n            1- Creates LibNoSoname and upload it to remote server\n            2- Creates LibB and upload it to remote server\n            3- Remove the Conan cache folder\n            4- Creates an application and consume LibB\n        Goal:\n            * If `self.cpp_info.set_property(\"nosoname\", True), then the `Executable` runs OK.\n            * If `self.cpp_info.set_property(\"nosoname\", False), then the `Executable` fails.\n    \"\"\"\n    client = TestClient(default_server_user=True)\n    # Creating nosoname/0.1 library\n    client.run(\"new cmake_lib -d name=nosoname -d version=0.1\")\n\n    replace_in_file(ConanFileMock(), os.path.join(client.current_folder, \"conanfile.py\"),\n                    'self.cpp_info.libs = [\"nosoname\"]',\n                    f'self.cpp_info.libs = [\"nosoname\"]\\n        self.cpp_info.set_property(\"nosoname\", {nosoname_property})')\n    replace_in_file(ConanFileMock(), os.path.join(client.current_folder, \"CMakeLists.txt\"),\n                    'target_include_directories(nosoname PUBLIC include)',\n                    'target_include_directories(nosoname PUBLIC include)\\nset_target_properties(nosoname PROPERTIES NO_SONAME 1)')\n    client.run(\"create . -o nosoname/*:shared=True -tf=\")\n    # Creating lib_b/0.1 library (depends on nosoname/0.1)\n    client.save({}, clean_first=True)\n    client.run(\"new cmake_lib -d name=lib_b -d version=0.1 -d requires=nosoname/0.1\")\n    client.run(\"create . -o lib_b/*:shared=True -o nosoname/*:shared=True -tf=\")\n    # Creating app/0.1 application (depends on lib_b/0.1)\n    client.save({}, clean_first=True)\n    client.run(\"new cmake_exe -d name=app -d version=0.1 -d requires=lib_b/0.1\")\n    client.run(\"create . -o nosoname/*:shared=True -o lib_b/*:shared=True -tf=\")\n    client.run(\"upload * -c -r default\")\n    # Removing everything from the .conan2/p to ensure that we don't have anything saved in the cache\n    shutil.rmtree(client.cache.store)\n\n    client = TestClient(servers=client.servers)\n    client.run(\"install --requires=app/0.1@ -o nosoname*:shared=True -o lib_b/*:shared=True\")\n    # This only finds \"app\" executable because the \"app/0.1\" is declaring package_type=\"application\"\n    # otherwise, run=None and nothing can tell us if the conanrunenv should have the PATH.\n    command = environment_wrap_command(ConanFileMock(), \"conanrun\", client.current_folder, \"app\")\n\n    # If `nosoname_property` is False, and we have a library without the SONAME flag,\n    # then it should fail\n    if not nosoname_property:\n        client.run_command(command, assert_error=True)\n        assert \"libnosoname.so: cannot open shared object file: \" \\\n               \"No such file or directory\" in client.out\n    else:\n        client.run_command(command)\n        assert \"nosoname/0.1: Hello World Release!\" in client.out\n        assert \"lib_b/0.1: Hello World Release!\" in client.out\n        assert \"app/0.1: Hello World Release!\" in client.out\n"
  },
  {
    "path": "test/functional/toolchains/cmake/test_cmake_extra_variables.py",
    "content": "import textwrap\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\nnew_value = \"will_break_next\"\n\n\n@pytest.mark.tool(\"cmake\", \"3.27\")\n@pytest.mark.parametrize(\"generator\", [\"CMakeDeps\", \"CMakeConfigDeps\"])\ndef test_package_info_extra_variables(generator):\n    \"\"\" The dependencies can define extra variables to be used in CMake,\n        but if the user is setting the cmake_extra_variables conf,\n        those should have precedence.\n    \"\"\"\n    client = TestClient()\n    dep_conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Pkg(ConanFile):\n            name = \"dep\"\n            version = \"0.1\"\n\n            def package_info(self):\n                self.cpp_info.set_property(\"cmake_extra_variables\", {\"FOO\": 42})\n    \"\"\")\n    client.save({\"dep/conanfile.py\": dep_conanfile})\n    client.run(\"create dep\")\n\n    cmakelists = textwrap.dedent(\"\"\"\n    cmake_minimum_required(VERSION 3.27)\n    project(myproject CXX)\n    find_package(dep CONFIG REQUIRED)\n    message(STATUS \"FOO=${FOO}\")\n    message(STATUS \"BAR=${BAR}\")\n    message(STATUS \"BAZ=${BAZ}\")\n    message(STATUS \"BAR_CACHE=${BAR_CACHE}\")\n    message(STATUS \"BAZ_CACHE=${BAZ_CACHE}\")\n    message(STATUS \"BAR_CACHE_FORCE=${BAR_CACHE_FORCE}\")\n    \"\"\")\n\n    conanfile = textwrap.dedent(f\"\"\"\n    from conan import ConanFile\n    from conan.tools.cmake import CMake, {generator}, CMakeToolchain\n\n    class Pkg(ConanFile):\n        settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n        requires = \"dep/0.1\"\n\n        def generate(self):\n            deps = {generator}(self)\n            deps.generate()\n            tc = CMakeToolchain(self)\n            tc.cache_variables[\"BAR\"] = \"42\"\n            tc.variables[\"BAZ\"] = \"42\"\n            tc.cache_variables[\"BAR_CACHE\"] = \"42\"\n            tc.variables[\"BAZ_CACHE\"] = \"42\"\n            tc.cache_variables[\"BAR_CACHE_FORCE\"] = \"42\"\n            tc.generate()\n\n        def build(self):\n            cmake = CMake(self)\n            cmake.configure()\n    \"\"\")\n    client.save({\"CMakeLists.txt\": cmakelists,\n                 \"conanfile.py\": conanfile})\n    conf = f\"-c tools.cmake.cmakedeps:new={new_value}\" if generator == \"CMakeConfigDeps\" else \"\"\n    client.run(f\"build . {conf} \"\n               \"\"\"-c tools.cmake.cmaketoolchain:extra_variables=\"{'FOO': '9', 'BAR': '9', 'BAZ': '9', 'BAR_CACHE': {'value': '9', 'cache': True, 'type': 'STRING'}, 'BAZ_CACHE': {'value': '9', 'cache': True, 'type': 'STRING'}, 'BAR_CACHE_FORCE': {'value': '9', 'cache': True, 'type': 'STRING', 'force': True}}\" \"\"\")\n\n    assert \"-- FOO=9\" in client.out\n    assert \"-- BAR=9\" in client.out\n    assert \"-- BAZ=9\" in client.out\n    # No overwrite in this case. Cache - Cache keeps the first occurrence in the file, can't override\n    # from the profile\n    assert \"-- BAR_CACHE=42\" in client.out\n    assert \"-- BAZ_CACHE=9\" in client.out\n    assert \"-- BAR_CACHE_FORCE=9\" in client.out\n\n"
  },
  {
    "path": "test/functional/toolchains/cmake/test_cmake_find_none.py",
    "content": "import platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_cmake_find_none_transitive():\n    c = TestClient()\n\n    qt = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n\n        class pkgRecipe(ConanFile):\n            name = \"qt\"\n            version = \"0.1\"\n            package_type = \"static-library\"\n\n            # Binary configuration\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"CMakeToolchain\"\n\n            # Sources are located in the same place as this recipe, copy them to the recipe\n            exports_sources = \"CMakeLists.txt\", \"src/*\", \"include/*\"\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n\n            def package(self):\n                cmake = CMake(self)\n                cmake.install()\n\n            def package_info(self):\n                self.cpp_info.builddirs = [\"qt/cmake\"]\n                self.cpp_info.set_property(\"cmake_find_mode\", \"none\")\n                self.cpp_info.set_property(\"cmake_file_name\", \"Qt5\")\n        \"\"\")\n\n    cmake = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(MyHello NONE)\n\n        add_library(qt INTERFACE)\n        install(TARGETS qt EXPORT Qt5Config)\n        export(TARGETS qt\n            NAMESPACE qt::\n            FILE \"${CMAKE_CURRENT_BINARY_DIR}/Qt5Config.cmake\"\n        )\n        install(EXPORT Qt5Config\n            DESTINATION \"qt/cmake\"\n            NAMESPACE qt::\n        )\n        \"\"\")\n    c.save({\"conanfile.py\": qt,\n            \"CMakeLists.txt\": cmake})\n    c.run(\"create .\")\n\n    karchive = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n\n        class pkgRecipe(ConanFile):\n            name = \"karchive\"\n            version = \"0.1\"\n            package_type = \"static-library\"\n\n            requires = \"qt/0.1\"\n        \"\"\")\n\n    c.save({\"conanfile.py\": karchive}, clean_first=True)\n    c.run(\"create .\")\n\n    consumer_cmake = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(MyHello NONE)\n\n        find_package(karchive CONFIG REQUIRED)\n        \"\"\")\n\n    consumer = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n\n        class pkgRecipe(ConanFile):\n            package_type = \"static-library\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"CMakeToolchain\", \"CMakeDeps\"\n\n            def requirements(self):\n                self.requires(\"karchive/0.1\")\n                self.requires(\"qt/0.1\")\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n        \"\"\")\n\n    c.save({\"conanfile.py\": consumer,\n            \"CMakeLists.txt\": consumer_cmake}, clean_first=True)\n    c.run(\"build .\")\n    assert \"Conan: Target declared 'karchive::karchive'\" in c.out\n    # And it doesn't fail to find transitive qt\n\n\ndef test_cmake_find_none_relocation():\n    c = TestClient(default_server_user=True)\n    c.run(\"new cmake_lib -d name=pkg -d version=0.1\")\n    conanfile = c.load(\"conanfile.py\")\n    conanfile = conanfile + '        self.cpp_info.set_property(\"cmake_find_mode\", \"none\")'\n    conanfile = conanfile + '\\n        self.cpp_info.builddirs = [\"pkg/cmake\"]'\n\n    cmake_export = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(MyHello CXX)\n\n        add_library(pkg src/pkg.cpp)\n        target_include_directories(pkg PUBLIC\n          $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>\n          $<INSTALL_INTERFACE:include>\n        )\n        set_target_properties(pkg PROPERTIES PUBLIC_HEADER \"include/pkg.h\")\n\n        install(TARGETS pkg EXPORT pkgConfig)\n        export(TARGETS pkg\n            NAMESPACE pkg::\n            FILE \"${CMAKE_CURRENT_BINARY_DIR}/pkgConfig.cmake\"\n        )\n        install(EXPORT pkgConfig\n            DESTINATION \"pkg/cmake\"\n            NAMESPACE pkg::\n        )\n        \"\"\")\n\n    c.save({\"conanfile.py\": conanfile,\n            \"CMakeLists.txt\": cmake_export})\n\n    c.run(\"create . \")\n    c.run(\"upload * -r=default -c\")\n    c.run(\"remove * -c\")\n\n    c2 = TestClient(servers=c.servers)\n    c2.run(\"new cmake_exe -d name=myapp -d version=0.1 -d requires=pkg/0.1\")\n    c2.run('build .')\n    # Now it builds correctly without failing, because package is relocatable\n\n\n@pytest.mark.tool(\"ninja\")\n# It is IMPORTANT to do cmake-3.27 AFTER ninja, otherwise CI injects another cmake\n@pytest.mark.tool(\"cmake\", \"3.27\")\ndef test_cmake_find_none_relocation_multi():\n    # What happens for multi-config\n    c = TestClient(default_server_user=True)\n    c.run(\"new cmake_lib -d name=pkg -d version=0.1\")\n    conanfile = textwrap.dedent(\"\"\"\n        import os, textwrap\n        from conan import ConanFile\n        from conan.tools.files import save, load\n        from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout, CMakeDeps\n\n        class pkgRecipe(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            package_type = \"library\"\n\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            options = {\"shared\": [True, False], \"fPIC\": [True, False]}\n            default_options = {\"shared\": False, \"fPIC\": True}\n\n            # Sources are located in the same place as this recipe, copy them to the recipe\n            exports_sources = \"CMakeLists.txt\", \"src/*\", \"include/*\"\n            implements = [\"auto_shared_fpic\"]\n\n            generators = \"CMakeToolchain\", \"CMakeDeps\"\n\n            def layout(self):\n                cmake_layout(self)\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n\n            def package(self):\n                cmake = CMake(self)\n                cmake.install()\n                p = os.path.join(self.package_folder, \"pkg\", \"cmake\", \"pkgConfig.cmake\")\n                new_config = textwrap.dedent('''\n                    # Create imported target pkg::pkg\n                    add_library(pkg::pkg STATIC IMPORTED)\n\n                    if(NOT DEFINED CONAN_pkg_DIR_MULTI)\n                        get_filename_component(CONAN_pkg_DIR_MULTI \"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n                    endif()\n                    foreach(_IMPORT_PREFIX ${CONAN_pkg_DIR_MULTI})\n                        get_filename_component(_IMPORT_PREFIX \"${_IMPORT_PREFIX}\" PATH)\n                        get_filename_component(_IMPORT_PREFIX \"${_IMPORT_PREFIX}\" PATH)\n\n                        set_target_properties(pkg::pkg PROPERTIES\n                          INTERFACE_INCLUDE_DIRECTORIES \"${_IMPORT_PREFIX}/include\"\n                        )\n\n                        # Load information for each installed configuration.\n                        file(GLOB CONFIG_FILES \"${_IMPORT_PREFIX}/pkg/cmake/pkgConfig-*.cmake\")\n                        foreach(f ${CONFIG_FILES})\n                          include(${f})\n                        endforeach()\n                    endforeach()\n                    ''')\n                save(self, p, new_config)\n\n            def package_info(self):\n                self.cpp_info.libs = [\"pkg\"]\n                self.cpp_info.set_property(\"cmake_find_mode\", \"none\")\n                self.cpp_info.builddirs = [\"pkg/cmake\"]\n        \"\"\")\n\n    cmake_export = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(MyHello CXX)\n\n        add_library(pkg src/pkg.cpp)\n        target_include_directories(pkg PUBLIC\n          $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>\n          $<INSTALL_INTERFACE:include>\n        )\n        set_target_properties(pkg PROPERTIES PUBLIC_HEADER \"include/pkg.h\")\n\n        install(TARGETS pkg EXPORT pkgConfig)\n        export(TARGETS pkg\n            NAMESPACE pkg::\n            FILE \"${CMAKE_CURRENT_BINARY_DIR}/pkgConfig.cmake\"\n        )\n        install(EXPORT pkgConfig\n            DESTINATION \"pkg/cmake\"\n            NAMESPACE pkg::\n        )\n        \"\"\")\n\n    c.save({\"conanfile.py\": conanfile,\n            \"CMakeLists.txt\": cmake_export})\n\n    c.run(\"create .\")\n    c.run(\"create . -s build_type=Debug\")\n    c.run(\"upload * -r=default -c\")\n    c.run(\"remove * -c\")\n\n    c2 = TestClient(servers=c.servers)\n    c2.run(\"new cmake_exe -d name=myapp -d version=0.1 -d requires=pkg/0.1\")\n    env = r\".\\build\\generators\\conanbuild.bat &&\" if platform.system() == \"Windows\" else \"\"\n    conf = ('-c tools.cmake.cmaketoolchain:generator=\"Ninja Multi-Config\" '\n            '-c tools.cmake.cmakedeps:new=will_break_next')\n    c2.run(f'install . {conf}')\n    c2.run(f'install . {conf} -s build_type=Debug')\n    c2.run_command(f\"{env} cmake --preset conan-default\")\n    c2.run_command(f\"{env} cmake --build --preset conan-release\")\n    c2.run_command(f\"{env} cmake --build --preset conan-debug\")\n"
  },
  {
    "path": "test/functional/toolchains/cmake/test_cmake_multi.py",
    "content": "import os\nimport platform\nimport textwrap\n\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_multi_cmake():\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout\n        import os\n\n        class multiRecipe(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n            exports_sources = (\"cmake_one/CMakeLists.txt\", \"cmake_two/CMakeLists.txt\",\n                               \"src_one/*\", \"src_two/*\")\n\n            def layout(self):\n                cmake_layout(self)\n\n            def generate(self):\n                tc = CMakeToolchain(self)\n                tc.generate()\n\n            def build_one(self):\n                cmake = CMake(self)\n                cmake.configure(build_script_folder=\"cmake_one\", subfolder=\"one\")\n                cmake.build(subfolder=\"one\")\n\n            def build_two(self):\n                cmake = CMake(self)\n                cmake.configure(build_script_folder=\"cmake_two\", subfolder=\"two\")\n                cmake.build(subfolder=\"two\")\n\n            def build(self):\n                self.build_one()\n                self.build_two()\n\n            def package(self):\n                cmake = CMake(self)\n                cmake.install(subfolder=\"two\")\n\n            def package_info(self):\n                self.cpp_info.libs = [\"hello_two\"]\n                self.cpp_info.includedirs = ['two/include']\n                self.cpp_info.libdirs = ['two/lib']\n        \"\"\")\n\n    hello_cpp = textwrap.dedent(\"\"\"\n        #include <iostream>\n        #include \"hello_{name}.h\"\n\n        void hello_{name}() {{\n            std::cout << \"Hello, World {name}!\" << std::endl;\n        }}\n        \"\"\")\n\n    hello_h = textwrap.dedent(\"\"\"\n        #pragma once\n        void hello_{name}();\n        \"\"\")\n\n    cmakelist = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(hello_{name} LANGUAGES CXX)\n\n        add_library(hello_{name} ../src_{name}/hello_{name}.cpp)\n        target_include_directories(hello_{name} PUBLIC ../src_{name})\n\n        set_target_properties(hello_{name} PROPERTIES PUBLIC_HEADER \"../src_{name}/hello_{name}.h\")\n        install(TARGETS hello_{name})\n        \"\"\")\n\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile,\n                 \"cmake_one/CMakeLists.txt\": cmakelist.format(name=\"one\"),\n                 \"cmake_two/CMakeLists.txt\": cmakelist.format(name=\"two\"),\n                 \"src_one/hello_one.h\": hello_h.format(name=\"one\"),\n                 \"src_one/hello_one.cpp\": hello_cpp.format(name=\"one\"),\n                 \"src_two/hello_two.h\": hello_h.format(name=\"two\"),\n                 \"src_two/hello_two.cpp\": hello_cpp.format(name=\"two\")})\n\n    client.run(\"create . --name=multi --version=0.1\")\n    ext = '.a' if platform.system() != \"Windows\" else '.lib'\n    prefix = 'lib' if platform.system() != \"Windows\" else ''\n\n    assert \"multi/0.1: package(): Packaged 1 '.h' file: hello_two.h\" in client.out\n    assert f\"multi/0.1: package(): Packaged 1 '{ext}' file: {prefix}hello_two{ext}\" in client.out\n    package_folder = client.created_layout().package()\n    assert not os.path.exists(os.path.join(package_folder, \"one\", \"include\", \"hello_one.h\"))\n    assert not os.path.exists(os.path.join(package_folder, \"one\", \"lib\", f\"{prefix}hello_one{ext}\"))\n    assert os.path.exists(os.path.join(package_folder, \"two\", \"include\", \"hello_two.h\"))\n    assert os.path.exists(os.path.join(package_folder, \"two\", \"lib\", f\"{prefix}hello_two{ext}\"))\n"
  },
  {
    "path": "test/functional/toolchains/cmake/test_cmake_toolchain.py",
    "content": "import json\nimport os\nimport platform\nimport re\nimport textwrap\n\nimport pytest\n\nfrom conan.tools.microsoft.visual import vcvars_command\nfrom conan.test.assets.cmake import gen_cmakelists\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import save\nfrom test.conftest import tools_locations\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Only for windows\")\n@pytest.mark.parametrize(\"compiler, version, update, runtime\",\n                         [(\"msvc\", \"192\", None, \"dynamic\"),\n                          (\"msvc\", \"192\", \"6\", \"static\"),\n                          (\"msvc\", \"192\", \"8\", \"static\")])\ndef test_cmake_toolchain_win_toolset(compiler, version, update, runtime):\n    client = TestClient(path_with_spaces=False)\n    settings = {\"compiler\": compiler,\n                \"compiler.version\": version,\n                \"compiler.update\": update,\n                \"compiler.cppstd\": \"17\",\n                \"compiler.runtime\": runtime,\n                \"build_type\": \"Release\",\n                \"arch\": \"x86_64\"}\n\n    # Build the profile according to the settings provided\n    settings = \" \".join('-s %s=\"%s\"' % (k, v) for k, v in settings.items() if v)\n\n    conanfile = GenConanfile().with_settings(\"os\", \"compiler\", \"build_type\", \"arch\").\\\n        with_generator(\"CMakeToolchain\")\n\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"install . {}\".format(settings))\n    toolchain = client.load(\"conan_toolchain.cmake\")\n    value = \"v14{}\".format(version[-1])\n    if update is not None:  # Fullversion\n        value += f\",version=14.{version[-1]}{update}\"\n    assert 'set(CMAKE_GENERATOR_TOOLSET \"{}\" CACHE STRING \"\" FORCE)'.format(value) in toolchain\n\n\ndef test_cmake_toolchain_user_toolchain():\n    client = TestClient(path_with_spaces=False)\n    conanfile = GenConanfile().with_settings(\"os\", \"compiler\", \"build_type\", \"arch\").\\\n        with_generator(\"CMakeToolchain\")\n    client.save_home({\"global.conf\": \"tools.cmake.cmaketoolchain:user_toolchain+=mytoolchain.cmake\"})\n\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"install .\")\n    toolchain = client.load(\"conan_toolchain.cmake\")\n    assert 'include(\"mytoolchain.cmake\")' in toolchain\n\n\ndef test_cmake_toolchain_user_toolchain_from_dep():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import copy\n        class Pkg(ConanFile):\n            exports_sources = \"*\"\n            def package(self):\n                copy(self, \"*\", self.build_folder, self.package_folder)\n            def package_info(self):\n                f = os.path.join(self.package_folder, \"mytoolchain.cmake\")\n                self.conf_info.append(\"tools.cmake.cmaketoolchain:user_toolchain\", f)\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile,\n                 \"mytoolchain.cmake\": 'message(STATUS \"mytoolchain.cmake !!!running!!!\")'})\n    client.run(\"create . --name=toolchain --version=0.1\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            exports_sources = \"CMakeLists.txt\"\n            build_requires = \"toolchain/0.1\"\n            generators = \"CMakeToolchain\"\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n        \"\"\")\n\n    client.save({\"conanfile.py\": conanfile,\n                 \"CMakeLists.txt\": gen_cmakelists()}, clean_first=True)\n    client.run(\"create . --name=pkg --version=0.1\")\n    assert \"mytoolchain.cmake !!!running!!!\" in client.out\n\n\ndef test_cmake_toolchain_without_build_type():\n    # If \"build_type\" is not defined, toolchain will still be generated, it will not crash\n    # Main effect is CMAKE_MSVC_RUNTIME_LIBRARY not being defined\n    client = TestClient(path_with_spaces=False)\n    conanfile = GenConanfile().with_settings(\"os\", \"compiler\", \"arch\").\\\n        with_generator(\"CMakeToolchain\")\n\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"install .\")\n    toolchain = client.load(\"conan_toolchain.cmake\")\n    assert \"CMAKE_MSVC_RUNTIME_LIBRARY\" not in toolchain\n    assert \"CMAKE_BUILD_TYPE\" not in toolchain\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Only on Windows with msvc\")\n@pytest.mark.tool(\"cmake\")\ndef test_cmake_toolchain_cmake_vs_debugger_environment():\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_package_type(\"shared-library\")\n                                                           .with_settings(\"build_type\")})\n    client.run(\"create . -s build_type=Release\")\n    client.run(\"create . -s build_type=Debug\")\n    client.run(\"create . -s build_type=MinSizeRel\")\n\n    client.run(\"install --require=pkg/1.0 -s build_type=Debug -g CMakeToolchain --format=json\")\n    debug_graph = json.loads(client.stdout)\n    debug_bindir = debug_graph['graph']['nodes']['1']['cpp_info']['root']['bindirs'][0]\n    debug_bindir = debug_bindir.replace('\\\\', '/')\n\n    toolchain = client.load(\"conan_toolchain.cmake\")\n    debugger_environment = f\"PATH=$<$<CONFIG:Debug>:{debug_bindir}>;%PATH%\"\n    assert debugger_environment in toolchain\n\n    client.run(\"install --require=pkg/1.0 -s build_type=Release -g CMakeToolchain --format=json\")\n    release_graph = json.loads(client.stdout)\n    release_bindir = release_graph['graph']['nodes']['1']['cpp_info']['root']['bindirs'][0]\n    release_bindir = release_bindir.replace('\\\\', '/')\n\n    toolchain = client.load(\"conan_toolchain.cmake\")\n    debugger_environment = f\"PATH=$<$<CONFIG:Debug>:{debug_bindir}>\" \\\n                           f\"$<$<CONFIG:Release>:{release_bindir}>;%PATH%\"\n    assert debugger_environment in toolchain\n\n    client.run(\"install --require=pkg/1.0 -s build_type=MinSizeRel -g CMakeToolchain --format=json\")\n    minsizerel_graph = json.loads(client.stdout)\n    minsizerel_bindir = minsizerel_graph['graph']['nodes']['1']['cpp_info']['root']['bindirs'][0]\n    minsizerel_bindir = minsizerel_bindir.replace('\\\\', '/')\n\n    toolchain = client.load(\"conan_toolchain.cmake\")\n    debugger_environment = f\"PATH=$<$<CONFIG:Debug>:{debug_bindir}>\" \\\n                           f\"$<$<CONFIG:Release>:{release_bindir}>\" \\\n                           f\"$<$<CONFIG:MinSizeRel>:{minsizerel_bindir}>;%PATH%\"\n    assert debugger_environment in toolchain\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_cmake_toolchain_cmake_vs_debugger_environment_not_needed():\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_package_type(\"shared-library\")\n                                                           .with_settings(\"build_type\")})\n    client.run(\"create . -s build_type=Release\")\n\n    cmake_generator = \"\" if platform.system() != \"Windows\" else \"-c tools.cmake.cmaketoolchain:generator=Ninja\"\n    client.run(f\"install --require=pkg/1.0 -s build_type=Release -g CMakeToolchain {cmake_generator}\")\n    toolchain = client.load(\"conan_toolchain.cmake\")\n    assert \"CMAKE_VS_DEBUGGER_ENVIRONMENT\" not in toolchain\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_cmake_toolchain_multiple_user_toolchain():\n    \"\"\" A consumer consuming two packages that declare:\n            self.conf_info[\"tools.cmake.cmaketoolchain:user_toolchain\"]\n        The consumer wants to use apply both toolchains in the CMakeToolchain.\n        There are two ways to customize the CMakeToolchain (parametrized):\n                1. Altering the context of the block (with_context = True)\n                2. Using the t.blocks[\"user_toolchain\"].user_toolchains = [] (with_context = False)\n    \"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import copy\n        class Pkg(ConanFile):\n            exports_sources = \"*\"\n            def package(self):\n                copy(self, \"*\", self.source_folder, self.package_folder)\n            def package_info(self):\n                f = os.path.join(self.package_folder, \"mytoolchain.cmake\")\n                self.conf_info.append(\"tools.cmake.cmaketoolchain:user_toolchain\", f)\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile,\n                 \"mytoolchain.cmake\": 'message(STATUS \"mytoolchain1.cmake !!!running!!!\")'})\n    client.run(\"create . --name=toolchain1 --version=0.1\")\n    client.save({\"conanfile.py\": conanfile,\n                 \"mytoolchain.cmake\": 'message(STATUS \"mytoolchain2.cmake !!!running!!!\")'})\n    client.run(\"create . --name=toolchain2 --version=0.1\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake, CMakeToolchain\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            exports_sources = \"CMakeLists.txt\"\n            tool_requires = \"toolchain1/0.1\", \"toolchain2/0.1\"\n            generators = \"CMakeToolchain\"\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n        \"\"\")\n\n    client.save({\"conanfile.py\": conanfile,\n                 \"CMakeLists.txt\": gen_cmakelists()}, clean_first=True)\n    client.run(\"create . --name=pkg --version=0.1\")\n    assert \"mytoolchain1.cmake !!!running!!!\" in client.out\n    assert \"mytoolchain2.cmake !!!running!!!\" in client.out\n    assert \"CMake Warning\" not in client.out\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_cmaketoolchain_no_warnings():\n    \"\"\"Make sure uninitialized variables do not cause any warnings, passing -Werror=dev\n    and --warn-uninitialized, calling \"cmake\" with conan_toolchain.cmake used to fail\n    \"\"\"\n    # Issue https://github.com/conan-io/conan/issues/10288\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Conan(ConanFile):\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            generators = \"CMakeToolchain\", \"CMakeDeps\"\n            requires = \"dep/0.1\"\n        \"\"\")\n    consumer = textwrap.dedent(\"\"\"\n       cmake_minimum_required(VERSION 3.15)\n       project(MyHello NONE)\n\n       find_package(dep CONFIG REQUIRED)\n       \"\"\")\n    client.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\"),\n                 \"conanfile.py\": conanfile,\n                 \"CMakeLists.txt\": consumer})\n\n    client.run(\"create dep\")\n    client.run(\"install .\")\n    build_type = \"-DCMAKE_BUILD_TYPE=Release\" if platform.system() != \"Windows\" else \"\"\n    client.run_command(\"cmake -Werror=dev --warn-uninitialized . {}\"\n                       \" -DCMAKE_TOOLCHAIN_FILE=./conan_toolchain.cmake\".format(build_type))\n    assert \"Using Conan toolchain\" in client.out\n    # The real test is that there are no errors, it returns successfully\n\n\ndef test_install_output_directories():\n    \"\"\"\n    If we change the libdirs of the cpp.package, as we are doing cmake.install, the output directory\n    for the libraries is changed\n    \"\"\"\n    client = TestClient()\n    client.run(\"new cmake_lib -d name=zlib -d version=1.2.11\")\n    # Edit the cpp.package.libdirs and check if the library is placed anywhere else\n    cf = client.load(\"conanfile.py\")\n    cf = cf.replace(\"cmake_layout(self)\",\n                    'cmake_layout(self)\\n        self.cpp.package.libdirs = [\"mylibs\"]')\n    client.save({\"conanfile.py\": cf})\n    client.run(\"create . -tf=\")\n    layout = client.created_layout()\n    p_folder = layout.package()\n    assert os.path.exists(os.path.join(p_folder, \"mylibs\"))\n    assert not os.path.exists(os.path.join(p_folder, \"lib\"))\n\n    b_folder = layout.build()\n    if platform.system() != \"Windows\":\n        gen_folder = os.path.join(b_folder, \"build\", \"Release\", \"generators\")\n    else:\n        gen_folder = os.path.join(b_folder, \"build\", \"generators\")\n\n    toolchain = client.load(os.path.join(gen_folder, \"conan_toolchain.cmake\"))\n    assert 'set(CMAKE_INSTALL_LIBDIR \"mylibs\")' in toolchain\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_cmake_toolchain_definitions_complex_strings():\n    # https://github.com/conan-io/conan/issues/11043\n    client = TestClient(path_with_spaces=False)\n    profile = textwrap.dedent(r'''\n        include(default)\n        [conf]\n        tools.build:defines+=[\"escape=partially \\\"escaped\\\"\"]\n        tools.build:defines+=[\"spaces=me you\"]\n        tools.build:defines+=[\"foobar=bazbuz\"]\n        tools.build:defines+=[\"answer=42\"]\n    ''')\n\n    conanfile = textwrap.dedent(r'''\n        from conan import ConanFile\n        from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout\n\n        class Test(ConanFile):\n            exports_sources = \"CMakeLists.txt\", \"src/*\"\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n\n            def generate(self):\n                tc = CMakeToolchain(self)\n                tc.preprocessor_definitions[\"escape2\"] = \"partially \\\"escaped\\\"\"\n                tc.preprocessor_definitions[\"spaces2\"] = \"me you\"\n                tc.preprocessor_definitions[\"foobar2\"] = \"bazbuz\"\n                tc.preprocessor_definitions[\"answer2\"] = 42\n                tc.preprocessor_definitions[\"NOVALUE_DEF\"] = None\n                tc.preprocessor_definitions.release[\"escape_release\"] = \"release partially \\\"escaped\\\"\"\n                tc.preprocessor_definitions.release[\"spaces_release\"] = \"release me you\"\n                tc.preprocessor_definitions.release[\"foobar_release\"] = \"release bazbuz\"\n                tc.preprocessor_definitions.release[\"answer_release\"] = 42\n                tc.preprocessor_definitions.release[\"NOVALUE_DEF_RELEASE\"] = None\n\n                tc.preprocessor_definitions.debug[\"escape_debug\"] = \"debug partially \\\"escaped\\\"\"\n                tc.preprocessor_definitions.debug[\"spaces_debug\"] = \"debug me you\"\n                tc.preprocessor_definitions.debug[\"foobar_debug\"] = \"debug bazbuz\"\n                tc.preprocessor_definitions.debug[\"answer_debug\"] = 21\n                tc.generate()\n\n            def layout(self):\n                cmake_layout(self)\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n        ''')\n\n    main = textwrap.dedent(\"\"\"\n        #include <stdio.h>\n        #define STR(x)   #x\n        #define SHOW_DEFINE(x) printf(\"%s=%s\", #x, STR(x))\n        int main(int argc, char *argv[]) {\n            SHOW_DEFINE(escape);\n            SHOW_DEFINE(spaces);\n            SHOW_DEFINE(foobar);\n            SHOW_DEFINE(answer);\n            SHOW_DEFINE(escape2);\n            SHOW_DEFINE(spaces2);\n            SHOW_DEFINE(foobar2);\n            SHOW_DEFINE(answer2);\n            #ifdef NDEBUG\n            SHOW_DEFINE(escape_release);\n            SHOW_DEFINE(spaces_release);\n            SHOW_DEFINE(foobar_release);\n            SHOW_DEFINE(answer_release);\n            #else\n            SHOW_DEFINE(escape_debug);\n            SHOW_DEFINE(spaces_debug);\n            SHOW_DEFINE(foobar_debug);\n            SHOW_DEFINE(answer_debug);\n            #endif\n            #ifdef NOVALUE_DEF\n            printf(\"NO VALUE!!!!\");\n            #endif\n            #ifdef NOVALUE_DEF_RELEASE\n            printf(\"NO VALUE RELEASE!!!!\");\n            #endif\n            return 0;\n        }\n        \"\"\")\n\n    cmakelists = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.15)\n        project(Test CXX)\n        set(CMAKE_CXX_STANDARD 11)\n        add_executable(example src/main.cpp)\n        \"\"\")\n\n    client.save({\"conanfile.py\": conanfile, \"profile\": profile, \"src/main.cpp\": main,\n                 \"CMakeLists.txt\": cmakelists}, clean_first=True)\n    client.run(\"install . -pr=./profile\")\n    client.run(\"build . -pr=./profile\")\n    exe = \"build/Release/example\" if platform.system() != \"Windows\" else r\"build\\Release\\example.exe\"\n    client.run_command(exe)\n    assert 'escape=partially \"escaped\"' in client.out\n    assert 'spaces=me you' in client.out\n    assert 'foobar=bazbuz' in client.out\n    assert 'answer=42' in client.out\n    assert 'escape2=partially \"escaped\"' in client.out\n    assert 'spaces2=me you' in client.out\n    assert 'foobar2=bazbuz' in client.out\n    assert 'answer2=42' in client.out\n    assert 'escape_release=release partially \"escaped\"' in client.out\n    assert 'spaces_release=release me you' in client.out\n    assert 'foobar_release=release bazbuz' in client.out\n    assert 'answer_release=42' in client.out\n    assert \"NO VALUE!!!!\" in client.out\n    assert \"NO VALUE RELEASE!!!!\" in client.out\n\n    client.run(\"install . -pr=./profile -s build_type=Debug\")\n    client.run(\"build . -pr=./profile -s build_type=Debug\")\n    exe = \"build/Debug/example\" if platform.system() != \"Windows\" else r\"build\\Debug\\example.exe\"\n\n    client.run_command(exe)\n    assert 'escape_debug=debug partially \"escaped\"' in client.out\n    assert 'spaces_debug=debug me you' in client.out\n    assert 'foobar_debug=debug bazbuz' in client.out\n    assert 'answer_debug=21' in client.out\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Only for windows\")\ndef test_cmake_toolchain_runtime_types():\n    # everything works with the default cmake_minimum_required version 3.15 in the template\n    client = TestClient(path_with_spaces=False)\n    client.run(\"new cmake_lib -d name=hello -d version=0.1\")\n    client.run(\"install . -s compiler.runtime=static -s build_type=Debug\")\n    client.run(\"build . -s compiler.runtime=static -s build_type=Debug\")\n\n    vcvars = vcvars_command(version=\"15\", architecture=\"x64\")\n    lib = os.path.join(client.current_folder, \"build\", \"Debug\", \"hello.lib\")\n    dumpbind_cmd = '{} && dumpbin /directives \"{}\"'.format(vcvars, lib)\n    client.run_command(dumpbind_cmd)\n    assert \"LIBCMTD\" in client.out\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Only for windows\")\ndef test_cmake_toolchain_runtime_types_cmake_older_than_3_15():\n    client = TestClient(path_with_spaces=False)\n    # Setting an older cmake_minimum_required in the CMakeLists fails, will link\n    # against the default debug runtime (MDd->MSVCRTD), not against MTd->LIBCMTD\n    client.run(\"new cmake_lib -d name=hello -d version=0.1\")\n    cmake = client.load(\"CMakeLists.txt\")\n    cmake2 = cmake.replace('cmake_minimum_required(VERSION 3.15)',\n                           'cmake_minimum_required(VERSION 3.1)')\n    assert cmake != cmake2\n    client.save({\"CMakeLists.txt\": cmake2})\n\n    client.run(\"install . -s compiler.runtime=static -s build_type=Debug\")\n    client.run(\"build . -s compiler.runtime=static -s build_type=Debug\")\n\n    vcvars = vcvars_command(version=\"15\", architecture=\"x64\")\n    lib = os.path.join(client.current_folder, \"build\", \"Debug\", \"hello.lib\")\n    dumpbind_cmd = '{} && dumpbin /directives \"{}\"'.format(vcvars, lib)\n    client.run_command(dumpbind_cmd)\n    assert \"LIBCMTD\" in client.out\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Only for windows\")\nclass TestWinSDKVersion:\n\n    @pytest.mark.tool(\"cmake\", \"3.23\")\n    @pytest.mark.tool(\"visual_studio\", \"17\")\n    def test_cmake_toolchain_winsdk_version(self):\n        # This test passes also with CMake 3.28, as long as cmake_minimum_required(VERSION 3.27)\n        # is not defined\n        client = TestClient(path_with_spaces=False)\n        client.run(\"new cmake_lib -d name=hello -d version=0.1\")\n        cmake = client.load(\"CMakeLists.txt\")\n        cmake += 'message(STATUS \"CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION = ' \\\n                 '${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}\")'\n        client.save({\"CMakeLists.txt\": cmake})\n        client.run(\"create . -s arch=x86_64 -s compiler.version=194 \"\n                   \"-c tools.microsoft:winsdk_version=10.0\")\n        assert \"CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION = 10.0\" in client.out\n        assert \"Conan toolchain: CMAKE_GENERATOR_PLATFORM=x64\" in client.out\n        assert \"Conan toolchain: CMAKE_GENERATOR_PLATFORM=x64,version\" not in client.out\n\n    @pytest.mark.tool(\"cmake\", \"3.27\")\n    @pytest.mark.tool(\"visual_studio\", \"17\")\n    def test_cmake_toolchain_winsdk_version2(self):\n        # https://github.com/conan-io/conan/issues/15372\n        client = TestClient(path_with_spaces=False)\n        client.run(\"new cmake_lib -d name=hello -d version=0.1\")\n        cmake = client.load(\"CMakeLists.txt\")\n        cmake = cmake.replace(\"cmake_minimum_required(VERSION 3.15)\",\n                              \"cmake_minimum_required(VERSION 3.27)\")\n        cmake += 'message(STATUS \"CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION = ' \\\n                 '${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}\")'\n        client.save({\"CMakeLists.txt\": cmake})\n        client.run(\"create . -s arch=x86_64 -s compiler.version=194 \"\n                   \"-c tools.microsoft:winsdk_version=10.0 \"\n                   '-c tools.cmake.cmaketoolchain:generator=\"Visual Studio 17\"')\n        assert \"CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION = 10.0\" in client.out\n        assert \"Conan toolchain: CMAKE_GENERATOR_PLATFORM=x64,version=10.0\" in client.out\n\n\n@pytest.mark.tool(\"cmake\", \"3.23\")\ndef test_cmake_layout_missing_option():\n    client = TestClient(path_with_spaces=False)\n\n    client.run(\"new cmake_exe -d name=hello -d version=0.1\")\n    settings_layout = '-c tools.cmake.cmake_layout:build_folder_vars=\\'[\"options.missing\"]\\' ' \\\n                      '-c tools.cmake.cmaketoolchain:generator=Ninja'\n    client.run(\"install . {}\".format(settings_layout))\n    assert os.path.exists(os.path.join(client.current_folder, \"build\", \"Release\", \"generators\"))\n\n\n@pytest.mark.tool(\"cmake\", \"3.23\")\ndef test_cmake_layout_missing_setting():\n    client = TestClient(path_with_spaces=False)\n    client.run(\"new cmake_exe -d name=hello -d version=0.1\")\n    settings_layout = '-c tools.cmake.cmake_layout:build_folder_vars=\\'[\"settings.missing\"]\\' ' \\\n                      '-c tools.cmake.cmaketoolchain:generator=Ninja'\n    client.run(\"install . {}\".format(settings_layout))\n    assert os.path.exists(os.path.join(client.current_folder, \"build\", \"Release\", \"generators\"))\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_cmaketoolchain_sysroot():\n    client = TestClient(path_with_spaces=False)\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout\n\n        class AppConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            exports_sources = \"CMakeLists.txt\"\n\n            def generate(self):\n                tc = CMakeToolchain(self)\n                {}\n                tc.generate()\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n        \"\"\")\n\n    cmakelist = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(app NONE)\n        message(\"sysroot: '${CMAKE_SYSROOT}'\")\n        message(\"osx_sysroot: '${CMAKE_OSX_SYSROOT}'\")\n        \"\"\")\n\n    client.save({\n        \"conanfile.py\": conanfile.format(\"\"),\n        \"CMakeLists.txt\": cmakelist\n    })\n\n    fake_sysroot = client.current_folder\n    output_fake_sysroot = fake_sysroot.replace(\"\\\\\", \"/\") if platform.system() == \"Windows\" else fake_sysroot\n    client.run(\"create . --name=app --version=1.0 -c tools.build:sysroot='{}'\".format(fake_sysroot))\n    assert \"sysroot: '{}'\".format(output_fake_sysroot) in client.out\n\n    # set in a block instead of using conf\n    set_sysroot_in_block = 'tc.blocks[\"generic_system\"].values[\"cmake_sysroot\"] = \"{}\"'.format(output_fake_sysroot)\n    client.save({\n        \"conanfile.py\": conanfile.format(set_sysroot_in_block),\n    })\n    client.run(\"create . --name=app --version=1.0\")\n    assert \"sysroot: '{}'\".format(output_fake_sysroot) in client.out\n\n\ndef test_cmake_layout_not_forbidden_build_type():\n    client = TestClient(path_with_spaces=False)\n    client.run(\"new cmake_exe -d name=hello -d version=0.1\")\n    settings_layout = '-c tools.cmake.cmake_layout:build_folder_vars=' \\\n                      '\\'[\"options.missing\", \"settings.build_type\"]\\''\n    client.run(\"install . {}\".format(settings_layout))\n    assert os.path.exists(os.path.join(client.current_folder,\n                                       \"build/release/generators/conan_toolchain.cmake\"))\n\n\ndef test_resdirs_cmake_install():\n    \"\"\"If resdirs is declared, the CMAKE_INSTALL_DATAROOTDIR folder is set\"\"\"\n\n    client = TestClient(path_with_spaces=False)\n\n    conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout\n\n            class AppConan(ConanFile):\n                settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n                exports_sources = \"CMakeLists.txt\", \"my_license\"\n                name = \"foo\"\n                version = \"1.0\"\n\n                def generate(self):\n                    tc = CMakeToolchain(self)\n                    tc.generate()\n\n                def layout(self):\n                    self.cpp.package.resdirs = [\"res\"]\n\n                def build(self):\n                    cmake = CMake(self)\n                    cmake.configure()\n                    cmake.build()\n\n                def package(self):\n                    cmake = CMake(self)\n                    cmake.install()\n            \"\"\")\n\n    cmake = \"\"\"\n    cmake_minimum_required(VERSION 3.15)\n    project(foo NONE)\n    if(NOT CMAKE_INSTALL_DATAROOTDIR)\n        message(FATAL_ERROR \"Cannot install stuff\")\n    endif()\n    install(FILES my_license DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/licenses)\n    \"\"\"\n\n    client.save({\"conanfile.py\": conanfile, \"CMakeLists.txt\": cmake, \"my_license\": \"MIT\"})\n    client.run(\"create .\")\n    assert \"/res/licenses/my_license\" in client.out\n    assert \"Packaged 1 file: my_license\" in client.out\n\n\ndef test_resdirs_none_cmake_install():\n    \"\"\"If no resdirs are declared, the CMAKE_INSTALL_DATAROOTDIR folder is not set\"\"\"\n\n    client = TestClient(path_with_spaces=False)\n\n    conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout\n\n            class AppConan(ConanFile):\n                settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n                exports_sources = \"CMakeLists.txt\", \"my_license\"\n                name = \"foo\"\n                version = \"1.0\"\n\n                def generate(self):\n                    tc = CMakeToolchain(self)\n                    tc.generate()\n\n                def build(self):\n                    cmake = CMake(self)\n                    cmake.configure()\n                    cmake.build()\n\n                def package(self):\n                    cmake = CMake(self)\n                    cmake.install()\n            \"\"\")\n\n    cmake = \"\"\"\n    cmake_minimum_required(VERSION 3.15)\n    project(foo NONE)\n    if(NOT CMAKE_INSTALL_DATAROOTDIR)\n        message(FATAL_ERROR \"Cannot install stuff\")\n    endif()\n    \"\"\"\n\n    client.save({\"conanfile.py\": conanfile, \"CMakeLists.txt\": cmake, \"my_license\": \"MIT\"})\n    client.run(\"create .\", assert_error=True)\n    assert \"Cannot install stuff\" in client.out\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_cmake_toolchain_vars_when_option_declared():\n    t = TestClient()\n\n    cmakelists = textwrap.dedent(\"\"\"\n    cmake_minimum_required(VERSION 2.8) # <---- set this to an old version for old policies\n    cmake_policy(SET CMP0091 NEW) # <-- Needed on Windows\n    project(mylib CXX)\n\n    message(\"CMake version: ${CMAKE_VERSION}\")\n\n    # Set the options AFTER the call to project, that is, after toolchain is loaded\n    option(BUILD_SHARED_LIBS \"\" ON)\n    option(CMAKE_POSITION_INDEPENDENT_CODE \"\" OFF)\n\n    add_library(mylib src/mylib.cpp)\n    target_include_directories(mylib PUBLIC include)\n\n    get_target_property(MYLIB_TARGET_TYPE mylib TYPE)\n    get_target_property(MYLIB_PIC mylib POSITION_INDEPENDENT_CODE)\n    message(\"mylib target type: ${MYLIB_TARGET_TYPE}\")\n    message(\"MYLIB_PIC value: ${MYLIB_PIC}\")\n    if(MYLIB_PIC)\n        #Note: the value is \"True\"/\"False\" if set by cmake,\n        #       and \"ON\"/\"OFF\" if set by Conan\n        message(\"mylib position independent code: ON\")\n    else()\n        message(\"mylib position independent code: OFF\")\n    endif()\n\n    set_target_properties(mylib PROPERTIES PUBLIC_HEADER \"include/mylib.h\")\n    install(TARGETS mylib)\n    \"\"\")\n\n    t.run(\"new cmake_lib -d name=mylib -d version=1.0\")\n    t.save({\"CMakeLists.txt\": cmakelists})\n\n    # The generated toolchain should set `BUILD_SHARED_LIBS` to `OFF`,\n    # and `CMAKE_POSITION_INDEPENDENT_CODE` to `ON` and the calls to\n    # `option()` in the CMakeLists.txt should respect the existing values.\n    # Note: on *WINDOWS* `fPIC` is not an option for this recipe, so it's invalid\n    #       to pass it to Conan, in which case the value in CMakeLists.txt\n    #       takes precedence.\n    fpic_option = \"-o mylib/*:fPIC=True\" if platform.system() != \"Windows\" else \"\"\n    fpic_cmake_value = \"ON\" if platform.system() != \"Windows\" else \"OFF\"\n    t.run(f\"create . -o mylib/*:shared=False {fpic_option} --test-folder=\")\n    assert \"mylib target type: STATIC_LIBRARY\" in t.out\n    assert f\"mylib position independent code: {fpic_cmake_value}\" in t.out\n\n    # When building manually, ensure the value passed by the toolchain overrides the ones in\n    # the CMakeLists\n    fpic_option = \"-o mylib/*:fPIC=False\" if platform.system() != \"Windows\" else \"\"\n    t.run(f\"install . -o mylib/*:shared=False {fpic_option}\")\n    folder = \"build/generators\" if platform.system() == \"Windows\" else \"build/Release/generators\"\n    t.run_command(f\"cmake -S . -B build/ -DCMAKE_TOOLCHAIN_FILE={folder}/conan_toolchain.cmake\")\n    assert \"mylib target type: STATIC_LIBRARY\" in t.out\n    assert f\"mylib position independent code: OFF\" in t.out\n\n    # Note: from this point forward, the CMakeCache is already initialised.\n    # When explicitly overriding `CMAKE_POSITION_INDEPENDENT_CODE` via command line, ensure\n    # this takes precedence to the value defined by the toolchain\n    t.run_command(\"cmake -S . -B build/ -DCMAKE_POSITION_INDEPENDENT_CODE=ON\")\n    assert \"mylib target type: STATIC_LIBRARY\" in t.out\n    assert \"mylib position independent code: ON\" in t.out\n\n    t.run_command(\"cmake -S . -B build/ -DBUILD_SHARED_LIBS=ON\")\n    assert \"mylib target type: SHARED_LIBRARY\" in t.out\n    assert \"mylib position independent code: ON\" in t.out\n\n\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.parametrize(\"single_profile\", [True, False])\ndef test_find_program_for_tool_requires(single_profile):\n    \"\"\"Test that the same reference can be both a tool_requires and a regular requires,\n    and that find_program (executables) and find_package (libraries) find the correct ones\n    when cross building.\n    \"\"\"\n\n    client = TestClient()\n\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n\n        from conan import ConanFile\n        from conan.tools.files import copy\n        class TestConan(ConanFile):\n            name = \"foobar\"\n            version = \"1.0\"\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            exports_sources = \"*\"\n            def layout(self):\n                pass\n            def package(self):\n                copy(self, pattern=\"lib*\", src=self.build_folder, dst=os.path.join(self.package_folder, \"lib\"))\n                copy(self, pattern=\"*bin\", src=self.build_folder, dst=os.path.join(self.package_folder, \"bin\"))\n    \"\"\")\n\n    host_profile = textwrap.dedent(\"\"\"\n    [settings]\n        os=Linux\n        arch=armv8\n        compiler=gcc\n        compiler.version=12\n        compiler.libcxx=libstdc++11\n        build_type=Release\n    \"\"\")\n\n    build_profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=Linux\n        arch=x86_64\n        compiler=gcc\n        compiler.version=12\n        compiler.libcxx=libstdc++11\n        build_type=Release\n    \"\"\")\n\n    client.save({\"conanfile.py\": conanfile,\n                 \"libfoo.so\": \"\",\n                 \"foobin\": \"\",\n                 \"host_profile\": host_profile,\n                 \"build_profile\": build_profile\n                 })\n\n    client.run(\"create . -pr:b build_profile -pr:h build_profile\")\n    build_context_package_folder = re.search(r\"Package folder ([\\w\\W]+).conan2([\\w\\W]+)\", str(client.out)).group(2).strip()\n    build_context_package_folder = build_context_package_folder.replace(\"\\\\\", \"/\")\n    client.run(\"create . -pr:b build_profile -pr:h host_profile\")\n    host_context_package_folder = re.search(r\"Package folder ([\\w\\W]+).conan2([\\w\\W]+)\", str(client.out)).group(2).strip()\n    host_context_package_folder = host_context_package_folder.replace(\"\\\\\", \"/\")\n\n    conanfile_consumer = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import cmake_layout\n        class PkgConan(ConanFile):\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n\n            def layout(self):\n                cmake_layout(self)\n\n            def requirements(self):\n                self.requires(\"foobar/1.0\")\n\n            def build_requirements(self):\n               self.tool_requires(\"foobar/1.0\")\n    \"\"\")\n\n    cmakelists_consumer = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(Hello LANGUAGES NONE)\n        find_package(foobar CONFIG REQUIRED)\n        find_program(FOOBIN_EXECUTABLE foobin)\n        message(\"foobin executable: ${FOOBIN_EXECUTABLE}\")\n        message(\"foobar include dir: ${foobar_INCLUDE_DIR}\")\n        if(NOT FOOBIN_EXECUTABLE)\n          message(FATAL_ERROR \"FOOBIN executable not found\")\n        endif()\n    \"\"\")\n\n    client.save({\n        \"conanfile_consumer.py\": conanfile_consumer,\n        \"CMakeLists.txt\": cmakelists_consumer,\n        \"host_profile\": host_profile,\n        \"build_profile\": build_profile}, clean_first=True)\n\n    client.run(\"install conanfile_consumer.py -g CMakeToolchain -g CMakeDeps -pr:b build_profile -pr:h host_profile\")\n\n    with client.chdir(\"build\"):\n        client.run_command(\"cmake .. -DCMAKE_TOOLCHAIN_FILE=Release/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release\")\n        # Verify binary executable is found from build context package,\n        # and library comes from host context package\n        assert f\"{build_context_package_folder}/bin/foobin\" in client.out\n        assert f\"{host_context_package_folder}/include\" in client.out\n\n\n@pytest.mark.tool(\"pkg_config\")\ndef test_cmaketoolchain_and_pkg_config_path():\n    \"\"\"\n    Lightweight test which is loading a dependency as a *.pc file through\n    CMake thanks to pkg_check_modules macro.\n    It's working because PKG_CONFIG_PATH env variable is being loaded automatically\n    by the CMakeToolchain generator.\n    \"\"\"\n    client = TestClient()\n    dep = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    class DepConan(ConanFile):\n        name = \"dep\"\n        version = \"1.0\"\n        def package_info(self):\n            self.cpp_info.libs = [\"dep\"]\n    \"\"\")\n    pkg = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    from conan.tools.cmake import CMake, cmake_layout\n    class HelloConan(ConanFile):\n        name = \"pkg\"\n        version = \"1.0\"\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n        generators = \"PkgConfigDeps\", \"CMakeToolchain\"\n        exports_sources = \"CMakeLists.txt\"\n\n        def requirements(self):\n            self.requires(\"dep/1.0\")\n\n        def layout(self):\n            cmake_layout(self)\n\n        def build(self):\n            cmake = CMake(self)\n            cmake.configure()\n            cmake.build()\n    \"\"\")\n    cmakelists = textwrap.dedent(\"\"\"\n    cmake_minimum_required(VERSION 3.15)\n    project(pkg NONE)\n\n    find_package(PkgConfig REQUIRED)\n    # We should have PKG_CONFIG_PATH created in the current environment\n    pkg_check_modules(DEP REQUIRED IMPORTED_TARGET dep)\n    \"\"\")\n    client.save({\n        \"dep/conanfile.py\": dep,\n        \"pkg/conanfile.py\": pkg,\n        \"pkg/CMakeLists.txt\": cmakelists\n    })\n    client.run(\"create dep/conanfile.py\")\n    client.run(\"create pkg/conanfile.py\")\n    assert \"Found dep, version 1.0\" in client.out\n\n\ndef test_cmaketoolchain_conf_from_tool_require():\n    # https://github.com/conan-io/conan/issues/13914\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Conan(ConanFile):\n            name = \"toolchain\"\n            version = \"1.0\"\n\n            def package_info(self):\n                self.conf_info.define(\"tools.cmake.cmaketoolchain:system_name\", \"GENERIC-POTATO\")\n                self.conf_info.define(\"tools.cmake.cmaketoolchain:system_processor\", \"ARM-POTATO\")\n                self.conf_info.define(\"tools.build.cross_building:can_run\", False)\n                self.conf_info.define(\"tools.build:compiler_executables\", {\n                    \"c\": \"arm-none-eabi-gcc\",\n                    \"cpp\": \"arm-none-eabi-g++\",\n                    \"asm\": \"arm-none-eabi-as\",\n                })\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile,\n            \"test_package/conanfile.py\": GenConanfile().with_test(\"pass\")\n                                                       .with_tool_requires(\"toolchain/1.0\")\n                                                       .with_generator(\"CMakeToolchain\")})\n    c.run(\"create .\")\n    toolchain = c.load(\"test_package/conan_toolchain.cmake\")\n    assert \"set(CMAKE_SYSTEM_NAME GENERIC-POTATO)\" in toolchain\n    assert \"set(CMAKE_SYSTEM_PROCESSOR ARM-POTATO)\" in toolchain\n\n\ndef test_inject_user_toolchain():\n    client = TestClient()\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n\n        class AppConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            exports_sources = \"CMakeLists.txt\"\n            name = \"foo\"\n            version = \"1.0\"\n            generators = \"CMakeToolchain\"\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n        \"\"\")\n\n    cmake = \"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(foo LANGUAGES NONE)\n        message(STATUS \"MYVAR1 ${MY_USER_VAR1}!!\")\n    \"\"\"\n    profile = textwrap.dedent(\"\"\"\n        include(default)\n        [conf]\n        tools.cmake.cmaketoolchain:user_toolchain+={{profile_dir}}/myvars.cmake\"\"\")\n    save(os.path.join(client.paths.profiles_path, \"myprofile\"), profile)\n    save(os.path.join(client.paths.profiles_path, \"myvars.cmake\"), 'set(MY_USER_VAR1 \"MYVALUE1\")')\n    client.save({\"conanfile.py\": conanfile,\n                 \"CMakeLists.txt\": cmake})\n    client.run(\"build . -pr=myprofile\")\n    assert \"-- MYVAR1 MYVALUE1!!\" in client.out\n\n    # Now test with the global.conf\n    global_conf = 'tools.cmake.cmaketoolchain:user_toolchain=' \\\n                  '[\"{{conan_home_folder}}/my.cmake\"]'\n    client.save_home({\"global.conf\": global_conf})\n    save(os.path.join(client.cache_folder, \"my.cmake\"), 'message(STATUS \"IT WORKS!!!!\")')\n    client.run(\"build .\")\n    # The toolchain is found and can be used\n    assert \"IT WORKS!!!!\" in client.out\n\n\ndef test_no_build_type():\n    client = TestClient()\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake, CMakeToolchain\n\n        class AppConan(ConanFile):\n            name = \"pkg\"\n            version = \"1.0\"\n            settings = \"os\", \"compiler\", \"arch\"\n            exports_sources = \"CMakeLists.txt\"\n\n            def layout(self):\n                self.folders.build = \"build\"\n\n            def generate(self):\n                tc = CMakeToolchain(self)\n                if not tc.is_multi_configuration:\n                    tc.cache_variables[\"CMAKE_BUILD_TYPE\"] = \"Release\"\n                tc.generate()\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                build_type = \"Release\" if cmake.is_multi_configuration else None\n                cmake.build(build_type=build_type)\n\n            def package(self):\n                cmake = CMake(self)\n                build_type = \"Release\" if cmake.is_multi_configuration else None\n                cmake.install(build_type=build_type)\n        \"\"\")\n\n    cmake = \"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(pkg LANGUAGES NONE)\n    \"\"\"\n\n    client.save({\"conanfile.py\": conanfile,\n                 \"CMakeLists.txt\": cmake})\n    client.run(\"create .\")\n    assert \"Don't specify 'build_type' at build time\" not in client.out\n\n\n@pytest.mark.tool(\"cmake\", \"3.19\")\ndef test_redirect_stdout():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n    import os\n    from io import StringIO\n    from conan import ConanFile\n    from conan.tools.cmake import CMake, CMakeToolchain\n    from conan.tools.cmake import cmake_layout\n\n    class Pkg(ConanFile):\n        name = \"foo\"\n        version = \"1.0\"\n        settings = \"os\", \"arch\", \"build_type\", \"compiler\"\n        generators = \"CMakeToolchain\"\n        exports_sources = \"CMakeLists.txt\", \"main.cpp\"\n\n        def build(self):\n            cmake = CMake(self)\n\n            config_stdout, config_stderr = StringIO(), StringIO()\n            cmake.configure(stdout=config_stdout, stderr=config_stderr)\n            self.output.info(f\"Configure stdout: '{config_stdout.getvalue()}'\")\n            self.output.info(f\"Configure stderr: '{config_stderr.getvalue()}'\")\n\n            build_stdout, build_stderr = StringIO(), StringIO()\n            cmake.build(stdout=build_stdout, stderr=build_stderr)\n            self.output.info(f\"Build stdout: '{build_stdout.getvalue()}'\")\n            self.output.info(f\"Build stderr: '{build_stderr.getvalue()}'\")\n\n            test_stdout, test_stderr = StringIO(), StringIO()\n            cmake.test(stdout=test_stdout, stderr=test_stderr)\n            self.output.info(f\"Test stdout: '{test_stdout.getvalue()}'\")\n            self.output.info(f\"Test stderr: '{test_stderr.getvalue()}'\")\n\n        def package(self):\n            cmake = CMake(self)\n            install_stdout, install_stderr = StringIO(), StringIO()\n            cmake.install(stdout=install_stdout, stderr=install_stderr)\n            self.output.info(f\"Install stdout: '{install_stdout.getvalue()}'\")\n            self.output.info(f\"Install stderr: '{install_stderr.getvalue()}'\")\n\n\n    \"\"\")\n    client.save({\"conanfile.py\": conanfile,\n                 \"CMakeLists.txt\": 'project(foo)\\nadd_executable(mylib main.cpp)\\ninclude(CTest)',\n                 \"main.cpp\": \"int main() {return 0;}\"})\n    client.run(\"create .\")\n\n    # Ensure the output is not unexpectedly empty\n    assert re.search(\"Configure stdout: '[^']\", client.out)\n    assert re.search(\"Configure stderr: '[^']\", client.out)\n\n    assert re.search(\"Build stdout: '[^']\", client.out)\n    assert re.search(\"Build stderr: ''\", client.out)\n\n    assert re.search(\"Test stdout: '[^']\", client.out)\n\n    # Empty on Windows\n    if platform.system() == \"Windows\":\n        assert re.search(\"Test stderr: ''\", client.out)\n    else:\n        assert re.search(\"Test stderr: '[^']\", client.out)\n\n    if platform.system() == \"Windows\":\n        assert re.search(\"Install stdout: ''\", client.out)\n    else:\n        assert re.search(\"Install stdout: '[^']\", client.out)\n    assert re.search(\"Install stderr: ''\", client.out)\n\n\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"neeed multi-config\")\ndef test_cmake_toolchain_cxxflags_multi_config():\n    c = TestClient()\n    profile_release = textwrap.dedent(r\"\"\"\n        include(default)\n        [conf]\n        tools.build:defines=[\"conan_test_answer=42\", \"conan_test_other=24\"]\n        tools.build:cxxflags=[\"/Zc:__cplusplus\"]\n        \"\"\")\n    profile_debug = textwrap.dedent(r\"\"\"\n        include(default)\n        [settings]\n        build_type=Debug\n        [conf]\n        tools.build:defines=[\"conan_test_answer=123\"]\n        tools.build:cxxflags=[\"/W4\"]\n        \"\"\")\n\n    conanfile = textwrap.dedent(r'''\n        from conan import ConanFile\n        from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout\n\n        class Test(ConanFile):\n            exports_sources = \"CMakeLists.txt\", \"src/*\"\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            generators = \"CMakeToolchain\"\n\n            def layout(self):\n                cmake_layout(self)\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n        ''')\n\n    main = textwrap.dedent(r\"\"\"\n        #include <iostream>\n        #include <stdio.h>\n\n        #define STR(x)   #x\n        #define SHOW_DEFINE(x) printf(\"DEFINE %s=%s!\\n\", #x, STR(x))\n\n        int main() {\n            SHOW_DEFINE(conan_test_answer);\n            #ifdef conan_test_other\n            SHOW_DEFINE(conan_test_other);\n            #endif\n            char a = 123L;  // to trigger warnings\n\n            #if __cplusplus\n            std::cout << \"CPLUSPLUS: __cplusplus\" << __cplusplus<< \"\\n\";\n            #endif\n        }\n        \"\"\")\n\n    cmakelists = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.15)\n        project(Test CXX)\n        add_executable(example src/main.cpp)\n        \"\"\")\n\n    c.save({\"conanfile.py\": conanfile,\n            \"profile_release\": profile_release,\n            \"profile_debug\": profile_debug,\n            \"src/main.cpp\": main,\n            \"CMakeLists.txt\": cmakelists}, clean_first=True)\n    c.run(\"install . -pr=./profile_release\")\n    c.run(\"install . -pr=./profile_debug\")\n\n    with c.chdir(\"build\"):\n        c.run_command(\"cmake .. -DCMAKE_TOOLCHAIN_FILE=generators/conan_toolchain.cmake\")\n        c.run_command(\"cmake --build . --config Release\")\n        assert \"warning C4189\" not in c.out\n        c.run_command(\"cmake --build . --config Debug\")\n        assert \"warning C4189\" in c.out\n\n    c.run_command(r\"build\\Release\\example.exe\")\n    assert 'DEFINE conan_test_answer=42!' in c.out\n    assert 'DEFINE conan_test_other=24!' in c.out\n    assert \"CPLUSPLUS: __cplusplus20\" in c.out\n\n    c.run_command(r\"build\\Debug\\example.exe\")\n    assert 'DEFINE conan_test_answer=123' in c.out\n    assert 'other=' not in c.out\n    assert \"CPLUSPLUS: __cplusplus19\" in c.out\n\n\n@pytest.mark.tool(\"ninja\")\n@pytest.mark.tool(\"cmake\", \"3.23\")\ndef test_cmake_toolchain_ninja_multi_config():\n    c = TestClient()\n    profile_release = textwrap.dedent(r\"\"\"\n        include(default)\n        [conf]\n        tools.cmake.cmaketoolchain:generator=Ninja Multi-Config\n        tools.build:defines=[\"conan_test_answer=42\", \"conan_test_other=24\"]\n        \"\"\")\n    profile_debug = textwrap.dedent(r\"\"\"\n        include(default)\n        [settings]\n        build_type=Debug\n        [conf]\n        tools.cmake.cmaketoolchain:generator=Ninja Multi-Config\n        tools.build:defines=[\"conan_test_answer=123\"]\n        \"\"\")\n    profile_relwithdebinfo = textwrap.dedent(r\"\"\"\n        include(default)\n        [settings]\n        build_type=RelWithDebInfo\n        [conf]\n        tools.cmake.cmaketoolchain:generator=Ninja Multi-Config\n        tools.build:defines=[\"conan_test_answer=456\", \"conan_test_other=abc\", 'conan_test_complex=\"1 2\"']\n        \"\"\")\n\n    conanfile = textwrap.dedent(r'''\n        from conan import ConanFile\n        from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout\n\n        class Test(ConanFile):\n            exports_sources = \"CMakeLists.txt\", \"src/*\"\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            generators = \"CMakeToolchain\"\n\n            def layout(self):\n                cmake_layout(self)\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n        ''')\n\n    main = textwrap.dedent(r\"\"\"\n        #include <iostream>\n        #include <stdio.h>\n\n        #define STR(x)   #x\n        #define SHOW_DEFINE(x) printf(\"DEFINE %s=%s!\\n\", #x, STR(x))\n\n        int main() {\n            SHOW_DEFINE(conan_test_answer);\n            #ifdef conan_test_other\n            SHOW_DEFINE(conan_test_other);\n            #endif\n            #ifdef conan_test_complex\n            SHOW_DEFINE(conan_test_complex);\n            #endif\n        }\n        \"\"\")\n\n    cmakelists = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.15)\n        project(Test CXX)\n        add_executable(example src/main.cpp)\n        \"\"\")\n\n    c.save({\"conanfile.py\": conanfile,\n            \"profile_release\": profile_release,\n            \"profile_debug\": profile_debug,\n            \"profile_relwithdebinfo\": profile_relwithdebinfo,\n            \"src/main.cpp\": main,\n            \"CMakeLists.txt\": cmakelists})\n    c.run(\"install . -pr=./profile_release\")\n    c.run(\"install . -pr=./profile_debug\")\n    c.run(\"install . -pr=./profile_relwithdebinfo\")\n\n    with c.chdir(\"build\"):\n        env = r\".\\generators\\conanbuild.bat &&\" if platform.system() == \"Windows\" else \"\"\n        c.run_command(f\"{env} cmake .. -G \\\"Ninja Multi-Config\\\" \"\n                      \"-DCMAKE_TOOLCHAIN_FILE=generators/conan_toolchain.cmake\")\n        c.run_command(f\"{env} cmake --build . --config Release\")\n        c.run_command(f\"{env} cmake --build . --config Debug\")\n        c.run_command(f\"{env} cmake --build . --config RelWithDebInfo\")\n\n    c.run_command(os.sep.join([\".\", \"build\", \"Release\", \"example\"]))\n    assert 'DEFINE conan_test_answer=42!' in c.out\n    assert 'DEFINE conan_test_other=24!' in c.out\n    assert 'complex=' not in c.out\n\n    c.run_command(os.sep.join([\".\", \"build\", \"Debug\", \"example\"]))\n    assert 'DEFINE conan_test_answer=123' in c.out\n    assert 'other=' not in c.out\n    assert 'complex=' not in c.out\n\n    c.run_command(os.sep.join([\".\", \"build\", \"RelWithDebInfo\", \"example\"]))\n    assert 'DEFINE conan_test_answer=456!' in c.out\n    assert 'DEFINE conan_test_other=abc!' in c.out\n    assert 'DEFINE conan_test_complex=\"1 2\"!' in c.out\n\n\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only needs to run once, no need for extra platforms\")\ndef test_cxx_version_not_overriden_if_hardcoded():\n    \"\"\"Any C++ standard set in the CMakeLists.txt will have priority even if the\n    compiler.cppstd is set in the profile\"\"\"\n    tc = TestClient()\n    tc.run(\"new cmake_exe -dname=foo -dversion=1.0\")\n\n    cml_contents = tc.load(\"CMakeLists.txt\")\n    cml_contents = cml_contents.replace(\"project(foo CXX)\\n\", \"project(foo CXX)\\nset(CMAKE_CXX_STANDARD 17)\\n\")\n    tc.save({\"CMakeLists.txt\": cml_contents})\n\n    # The compiler.cppstd will not override the CXX_STANDARD variable\n    tc.run(\"create . -s=compiler.cppstd=11\")\n    assert \"Conan toolchain: C++ Standard 11 with extensions OFF\" in tc.out\n    assert \"Warning: Standard CMAKE_CXX_STANDARD value defined in conan_toolchain.cmake to 11 has been modified to 17\" in tc.out\n\n    # Even though Conan warns, the compiled code is C++17\n    assert \"foo/1.0: __cplusplus2017\" in tc.out\n\n    tc.run(\"create . -s=compiler.cppstd=17\")\n    assert \"Conan toolchain: C++ Standard 17 with extensions OFF\" in tc.out\n    assert \"Warning: Standard CMAKE_CXX_STANDARD value defined in conan_toolchain.cmake to 17 has been modified to 17\" not in tc.out\n\n\n@pytest.mark.tool(\"cmake\", \"3.23\")  # Android complains if <3.19\n@pytest.mark.tool(\"android_ndk\")\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"NDK only installed on MAC\")\ndef test_cmake_toolchain_crossbuild_set_cmake_compiler():\n    # To reproduce https://github.com/conan-io/conan/issues/16960\n    # the issue happens when you set CMAKE_CXX_COMPILER and CMAKE_C_COMPILER as cache variables\n    # and then cross-build\n    c = TestClient()\n\n    ndk_path = tools_locations[\"android_ndk\"][\"system\"][\"path\"][platform.system()]\n    bin_path = ndk_path + (\n        \"/toolchains/llvm/prebuilt/darwin-x86_64/bin\" if platform.machine() == \"x86_64\" else\n        \"/toolchains/llvm/prebuilt/darwin-arm64/bin\"\n    )\n\n    android = textwrap.dedent(f\"\"\"\n       [settings]\n       os=Android\n       os.api_level=23\n       arch=x86_64\n       compiler=clang\n       compiler.version=12\n       compiler.libcxx=c++_shared\n       build_type=Release\n       [conf]\n       tools.android:ndk_path={ndk_path}\n       tools.build:compiler_executables = {{\"c\": \"{bin_path}/x86_64-linux-android23-clang\", \"cpp\": \"{bin_path}/x86_64-linux-android23-clang++\"}}\n       \"\"\")\n\n    conanfile = textwrap.dedent(f\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout\n        from conan.tools.build import check_min_cppstd\n        class SDKConan(ConanFile):\n            name = \"sdk\"\n            version = \"1.0\"\n            generators = \"CMakeDeps\", \"VirtualBuildEnv\"\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            exports_sources = \"CMakeLists.txt\"\n            def layout(self):\n                cmake_layout(self)\n            def generate(self):\n                tc = CMakeToolchain(self)\n                tc.cache_variables[\"SDK_VERSION\"] = str(self.version)\n                tc.generate()\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n    \"\"\")\n\n    cmake = textwrap.dedent(f\"\"\"\n        cmake_minimum_required(VERSION 3.23)\n        project(sdk VERSION ${{SDK_VERSION}}.0 LANGUAGES NONE)\n        message(\"sdk: ${{SDK_VERSION}}.0\")\n    \"\"\")\n\n    c.save({\"android\": android,\n            \"conanfile.py\": conanfile,\n            \"CMakeLists.txt\": cmake})\n    # first run works ok\n    c.run('build . --profile:host=android')\n    assert 'sdk: 1.0.0' in c.out\n    # in second run CMake says that you have changed variables that require your cache to be deleted.\n    # and deletes the cache and fails\n    c.run('build . --profile:host=android')\n    assert 'VERSION \".0\" format invalid.' not in c.out\n    assert 'sdk: 1.0.0' in c.out\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_cmake_toolchain_language_c():\n    client = TestClient()\n\n    conanfile = textwrap.dedent(r\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout\n\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            generators = \"CMakeToolchain\"\n            languages = \"C\"\n\n            def layout(self):\n                cmake_layout(self)\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n        \"\"\")\n\n    cmakelists = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(pkg NONE)\n        \"\"\")\n\n    client.save(\n        {\n            \"conanfile.py\": conanfile,\n            \"CMakeLists.txt\": cmakelists,\n        },\n        clean_first=True,\n    )\n\n    if platform.system() == \"Windows\":\n        # compiler.version=191 is already the default now\n        client.run(\"build . -s compiler.cstd=11 -s compiler.version=191\", assert_error=True)\n        assert \"The provided compiler.cstd=11 is not supported by msvc 191. Supported values are: []\" \\\n               in client.out\n    else:\n        client.run(\"build . -s compiler.cppstd=11\")\n        # It doesn't fail\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Only for windows\")\n@pytest.mark.tool(\"cmake\")\ndef test_cmaketoolchain_check_function_exists():\n    \"\"\"\n    covers the problematic check_function_exists() CMake DISCOURAGED check, that can fail\n    for Release configuration, due to CMake issues. This was broken when we tried to\n    add the automatic CMAKE_TRY_COMPILE_CONFIGURATION in release cases, as CheckFunctionExists.c\n    is optimized away or fails to compile in Release, but works in Debug.\n    This test is here to capture this legacy and problematic use case NOT to recommended this\n    as a good practice, rather then opposite, DONT DO IT\n    \"\"\"\n\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake, CMakeToolchain\n        class Conan(ConanFile):\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            def generate(self):\n                tc = CMakeToolchain(self)\n                # This gets back to older default behavior\n                # tc.blocks[\"try_compile\"].values[\"config\"] = None\n                tc.generate()\n            def build(self):\n                CMake(self).configure()\n        \"\"\")\n    consumer = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(MyHello C)\n        include(CheckFunctionExists)\n        check_function_exists(pow HAVE_POW)\n        if(NOT HAVE_POW)\n            message(FATAL_ERROR \"Not math!!!!!\")\n        endif()\n       \"\"\")\n    c.save({\"conanfile.py\": conanfile,\n            \"CMakeLists.txt\": consumer})\n\n    c.run(\"build . \")  # Release breaks the check\n    assert \"Looking for pow - found\" in c.out\n    # And it no longer crashes\n\n\n@pytest.mark.skipif(platform.system() != \"Linux\", reason=\"Linker scripts in Linux only\")\ndef test_cmake_linker_scripts():\n    conanfile = textwrap.dedent(\"\"\"\n       from conan import ConanFile\n       from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout\n\n       class Test(ConanFile):\n           exports_sources = \"CMakeLists.txt\", \"src/*\"\n           settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n           generators = \"CMakeToolchain\"\n\n           def layout(self):\n               cmake_layout(self)\n\n           def build(self):\n               cmake = CMake(self)\n               cmake.configure()\n               cmake.build()\n       \"\"\")\n\n    main = \"int main() {}\"\n\n    cmakelists = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.15)\n        project(Test CXX)\n        add_executable(example main.cpp)\n        \"\"\")\n    profile = textwrap.dedent(\"\"\"\n       include(default)\n       [conf]\n       tools.build:linker_scripts=['{{profile_dir}}/mylinkscript.ld']\n       \"\"\")\n\n    c = TestClient()\n    c.save({\"conanfile.py\": conanfile,\n            \"CMakeLists.txt\": cmakelists,\n            \"main.cpp\": main,\n            \"mylinkscript.ld\": \"\",\n            \"profile\": profile})\n    c.run('build . -pr=profile', assert_error=True)\n    # This error means the linker script was fonud and loaded, it failed because empty\n    assert \"PHDR segment not covered by LOAD segment\" in c.out\n\n\ndef test_cmake_toolchain_verbosity_propagation():\n    t = TestClient(light=True)\n    t.save({\"conanfile.py\": GenConanfile(\"mylib\", \"1.0\")})\n    t.run(\"create .\")\n    t.run(\"install --requires=mylib/1.0 -g CMakeToolchain\")\n    toolchain = t.load(\"conan_toolchain.cmake\")\n    assert 'set(CMAKE_VERBOSE_MAKEFILE' not in toolchain\n    assert 'set(CMAKE_MESSAGE_LOG_LEVEL' not in toolchain\n\n    t.run(\"install --requires=mylib/1.0 -g CMakeToolchain -c tools.build:verbosity=verbose \"\n          \"-c tools.compilation:verbosity=verbose\")\n    toolchain = t.load(\"conan_toolchain.cmake\")\n    assert 'set(CMAKE_VERBOSE_MAKEFILE \"ON\"' in toolchain\n    assert 'set(CMAKE_MESSAGE_LOG_LEVEL \"VERBOSE\"' in toolchain\n\n    t.run(\"install --requires=mylib/1.0 -g CMakeToolchain -c tools.build:verbosity=quiet \"\n          \"-c tools.compilation:verbosity=quiet\")\n    toolchain = t.load(\"conan_toolchain.cmake\")\n    assert 'set(CMAKE_MESSAGE_LOG_LEVEL \"ERROR\"' in toolchain\n\n    # Extra variables have preference\n    t.run(\"install --requires=mylib/1.0 -g CMakeToolchain -c tools.compilation:verbosity=quiet \"\n          \"-c tools.cmake.cmaketoolchain:extra_variables=\\\"{'CMAKE_MESSAGE_LOG_LEVEL': 'WARNING'}\\\"\")\n    toolchain = t.load(\"conan_toolchain.cmake\")\n    # assert 'set(CMAKE_VERBOSE_MAKEFILE \"OFF\"' in toolchain\n    assert 'set(CMAKE_MESSAGE_LOG_LEVEL \"WARNING\"' in toolchain\n"
  },
  {
    "path": "test/functional/toolchains/cmake/test_cmake_toolchain_m1.py",
    "content": "import textwrap\nimport platform\n\n\nimport pytest\n\nfrom conan.test.assets.cmake import gen_cmakelists\nfrom conan.test.assets.sources import gen_function_cpp\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only OSX\")\n@pytest.mark.parametrize(\"op_system\", [\"Macos\", \"iOS\"])\n@pytest.mark.tool(\"cmake\")\ndef test_m1(op_system):\n    os_version = \"os.version=12.0\" if op_system == \"iOS\" else \"\"\n    os_sdk = \"\" if op_system == \"Macos\" else \"os.sdk=iphoneos\"\n    profile = textwrap.dedent(\"\"\"\n        include(default)\n        [settings]\n        os={}\n        {}\n        {}\n        arch=armv8\n    \"\"\".format(op_system, os_sdk, os_version))\n\n    client = TestClient(path_with_spaces=False)\n    client.save({\"m1\": profile}, clean_first=True)\n    client.run(\"new cmake_lib -d name=hello -d version=0.1\")\n    client.run(\"create . --profile:build=default --profile:host=m1 -tf=\\\"\\\"\")\n\n    main = gen_function_cpp(name=\"main\", includes=[\"hello\"], calls=[\"hello\"])\n    custom_content = 'message(\"CMAKE_SYSTEM_NAME: ${CMAKE_SYSTEM_NAME}\") \\n' \\\n                     'message(\"CMAKE_SYSTEM_PROCESSOR: ${CMAKE_SYSTEM_PROCESSOR}\") \\n'\n    cmakelists = gen_cmakelists(find_package=[\"hello\"], appname=\"main\", appsources=[\"main.cpp\"],\n                                custom_content=custom_content)\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake, cmake_layout\n\n        class TestConan(ConanFile):\n            requires = \"hello/0.1\"\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            exports_sources = \"CMakeLists.txt\", \"main.cpp\"\n            generators = \"CMakeDeps\", \"CMakeToolchain\"\n\n            def layout(self):\n                cmake_layout(self)\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n        \"\"\")\n\n    client.save({\"conanfile.py\": conanfile,\n                 \"CMakeLists.txt\": cmakelists,\n                 \"main.cpp\": main,\n                 \"m1\": profile}, clean_first=True)\n    client.run(\"build . --profile:build=default --profile:host=m1\")\n    system_name = 'Darwin' if op_system == 'Macos' else 'iOS'\n    assert \"CMAKE_SYSTEM_NAME: {}\".format(system_name) in client.out\n    assert \"CMAKE_SYSTEM_PROCESSOR: arm64\" in client.out\n    main_path = \"./build/Release/main.app/main\" if op_system == \"iOS\" \\\n        else \"./build/Release/main\"\n    client.run_command(\"lipo -info {}\".format(main_path))\n    assert \"Non-fat file\" in client.out\n    assert \"is architecture: arm64\" in client.out\n    client.run_command(f\"vtool -show-build {main_path}\")\n\n    if op_system == \"Macos\":\n        assert \"platform MACOS\"\n    elif op_system == \"iOS\":\n        assert \"platform IOS\"\n        assert \"minos 12.0\"\n"
  },
  {
    "path": "test/functional/toolchains/cmake/test_cmake_toolchain_presets.py",
    "content": "import json\nimport os\nimport platform\nimport textwrap\n\nimport pytest\n\nfrom conan.internal.util.files import load, rmdir\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient\nfrom conan.tools.cmake.presets import load_cmake_presets\n\n\n@pytest.mark.tool(\"cmake\", \"3.23\")\ndef test_cmake_presets_multiple_settings_single_config():\n    client = TestClient(path_with_spaces=False)\n    client.run(\"new cmake_exe -d name=hello -d version=0.1\")\n    settings_layout = '-c tools.cmake.cmake_layout:build_folder_vars=' \\\n                      '\\'[\"settings.compiler\", \"settings.compiler.version\", ' \\\n                      '   \"settings.compiler.cppstd\"]\\''\n\n    user_presets_path = os.path.join(client.current_folder, \"CMakeUserPresets.json\")\n\n    # Check that all generated names are expected, both in the layout and in the Presets\n    settings = \"-s compiler=apple-clang -s compiler.libcxx=libc++ \" \\\n               \"-s compiler.version=12.0 -s compiler.cppstd=gnu17\"\n    client.run(\"install . {} {}\".format(settings, settings_layout))\n    assert os.path.exists(os.path.join(client.current_folder, \"build\", \"apple-clang-12.0-gnu17\",\n                                       \"Release\", \"generators\"))\n    assert os.path.exists(user_presets_path)\n    user_presets = json.loads(load(user_presets_path))\n    assert len(user_presets[\"include\"]) == 1\n    presets = json.loads(client.load(user_presets[\"include\"][0]))\n    assert len(presets[\"configurePresets\"]) == 1\n    assert len(presets[\"buildPresets\"]) == 1\n    assert len(presets[\"testPresets\"]) == 1\n    assert presets[\"configurePresets\"][0][\"name\"] == \"conan-apple-clang-12.0-gnu17-release\"\n    assert presets[\"buildPresets\"][0][\"name\"] == \"conan-apple-clang-12.0-gnu17-release\"\n    assert presets[\"buildPresets\"][0][\"configurePreset\"] == \"conan-apple-clang-12.0-gnu17-release\"\n    assert presets[\"testPresets\"][0][\"name\"] == \"conan-apple-clang-12.0-gnu17-release\"\n    assert presets[\"testPresets\"][0][\"configurePreset\"] == \"conan-apple-clang-12.0-gnu17-release\"\n\n    # If we create the \"Debug\" one, it will be appended\n    client.run(\"install . {} -s build_type=Debug {}\".format(settings, settings_layout))\n    assert os.path.exists(os.path.join(client.current_folder, \"build\", \"apple-clang-12.0-gnu17\",\n                                       \"Release\", \"generators\"))\n    assert os.path.exists(user_presets_path)\n    user_presets = json.loads(load(user_presets_path))\n    assert len(user_presets[\"include\"]) == 2\n    presets = json.loads(client.load(user_presets[\"include\"][0]))\n    assert len(presets[\"configurePresets\"]) == 1\n    assert len(presets[\"buildPresets\"]) == 1\n    assert len(presets[\"testPresets\"]) == 1\n    assert presets[\"configurePresets\"][0][\"name\"] == \"conan-apple-clang-12.0-gnu17-release\"\n    assert presets[\"buildPresets\"][0][\"name\"] == \"conan-apple-clang-12.0-gnu17-release\"\n    assert presets[\"buildPresets\"][0][\"configurePreset\"] == \"conan-apple-clang-12.0-gnu17-release\"\n    assert presets[\"testPresets\"][0][\"name\"] == \"conan-apple-clang-12.0-gnu17-release\"\n    assert presets[\"testPresets\"][0][\"configurePreset\"] == \"conan-apple-clang-12.0-gnu17-release\"\n\n    presets = json.loads(client.load(user_presets[\"include\"][1]))\n    assert len(presets[\"configurePresets\"]) == 1\n    assert len(presets[\"buildPresets\"]) == 1\n    assert len(presets[\"testPresets\"]) == 1\n    assert presets[\"configurePresets\"][0][\"name\"] == \"conan-apple-clang-12.0-gnu17-debug\"\n    assert presets[\"buildPresets\"][0][\"name\"] == \"conan-apple-clang-12.0-gnu17-debug\"\n    assert presets[\"buildPresets\"][0][\"configurePreset\"] == \"conan-apple-clang-12.0-gnu17-debug\"\n    assert presets[\"testPresets\"][0][\"name\"] == \"conan-apple-clang-12.0-gnu17-debug\"\n    assert presets[\"testPresets\"][0][\"configurePreset\"] == \"conan-apple-clang-12.0-gnu17-debug\"\n\n    # But If we change, for example, the cppstd and the compiler version, the toolchain\n    # and presets will be different, but it will be appended to the UserPresets.json\n    settings = \"-s compiler=apple-clang -s compiler.libcxx=libc++ \" \\\n               \"-s compiler.version=13 -s compiler.cppstd=gnu20\"\n    client.run(\"install . {} {}\".format(settings, settings_layout))\n    assert os.path.exists(os.path.join(client.current_folder, \"build\", \"apple-clang-13-gnu20\",\n                                       \"Release\", \"generators\"))\n    assert os.path.exists(user_presets_path)\n    user_presets = json.loads(load(user_presets_path))\n    # The [0] is the apple-clang 12 the [1] is the apple-clang 13\n    assert len(user_presets[\"include\"]) == 3\n    presets = json.loads(client.load(user_presets[\"include\"][2]))\n    assert len(presets[\"configurePresets\"]) == 1\n    assert len(presets[\"buildPresets\"]) == 1\n    assert len(presets[\"testPresets\"]) == 1\n    assert presets[\"configurePresets\"][0][\"name\"] == \"conan-apple-clang-13-gnu20-release\"\n    assert presets[\"buildPresets\"][0][\"name\"] == \"conan-apple-clang-13-gnu20-release\"\n    assert presets[\"buildPresets\"][0][\"configurePreset\"] == \"conan-apple-clang-13-gnu20-release\"\n    assert presets[\"testPresets\"][0][\"name\"] == \"conan-apple-clang-13-gnu20-release\"\n    assert presets[\"testPresets\"][0][\"configurePreset\"] == \"conan-apple-clang-13-gnu20-release\"\n\n    # We can build with cmake manually\n    if platform.system() == \"Darwin\":\n        client.run_command(\"cmake . --preset conan-apple-clang-12.0-gnu17-release\")\n        client.run_command(\"cmake --build --preset conan-apple-clang-12.0-gnu17-release\")\n        client.run_command(\"ctest --preset conan-apple-clang-12.0-gnu17-release\")\n        client.run_command(\"./build/apple-clang-12.0-gnu17/Release/hello\")\n        assert \"Hello World Release!\" in client.out\n        assert \"__cplusplus2017\" in client.out\n\n        client.run_command(\"cmake . --preset conan-apple-clang-12.0-gnu17-debug\")\n        client.run_command(\"cmake --build --preset conan-apple-clang-12.0-gnu17-debug\")\n        client.run_command(\"ctest --preset conan-apple-clang-12.0-gnu17-debug\")\n        client.run_command(\"./build/apple-clang-12.0-gnu17/Debug/hello\")\n        assert \"Hello World Debug!\" in client.out\n        assert \"__cplusplus2017\" in client.out\n\n        client.run_command(\"cmake . --preset conan-apple-clang-13-gnu20-release\")\n        client.run_command(\"cmake --build --preset conan-apple-clang-13-gnu20-release\")\n        client.run_command(\"ctest --preset conan-apple-clang-13-gnu20-release\")\n        client.run_command(\"./build/apple-clang-13-gnu20/Release/hello\")\n        assert \"Hello World Release!\" in client.out\n        assert \"__cplusplus2020\" in client.out\n\n\n@pytest.mark.parametrize(\"multiconfig\", [True, False])\ndef test_cmake_presets_duplicated_install(multiconfig):\n    # https://github.com/conan-io/conan/issues/11409\n    \"\"\"Only failed when using a multiconfig generator\"\"\"\n    client = TestClient(path_with_spaces=False)\n    client.run(\"new cmake_exe -d name=hello -d version=0.1\")\n    settings = '-s compiler=gcc -s compiler.version=5 -s compiler.libcxx=libstdc++11 ' \\\n               '-c tools.cmake.cmake_layout:build_folder_vars=' \\\n               '\\'[\"settings.compiler\", \"settings.compiler.version\"]\\' '\n    if multiconfig:\n        settings += '-c tools.cmake.cmaketoolchain:generator=\"Multi-Config\"'\n    client.run(\"install . {}\".format(settings))\n    client.run(\"install . {}\".format(settings))\n    if multiconfig:\n        presets_path = os.path.join(client.current_folder, \"build\", \"gcc-5\", \"generators\",\n                                    \"CMakePresets.json\")\n    else:\n        presets_path = os.path.join(client.current_folder, \"build\", \"gcc-5\", \"Release\", \"generators\",\n                                    \"CMakePresets.json\")\n    assert os.path.exists(presets_path)\n    contents = json.loads(load(presets_path))\n    assert len(contents[\"buildPresets\"]) == 1\n    assert len(contents[\"testPresets\"]) == 1\n\n\ndef test_remove_missing_presets():\n    # https://github.com/conan-io/conan/issues/11413\n    client = TestClient(path_with_spaces=False)\n    client.run(\"new cmake_exe -d name=hello -d version=0.1\")\n    settings = '-s compiler=gcc -s compiler.version=5 -s compiler.libcxx=libstdc++11 ' \\\n               '-c tools.cmake.cmake_layout:build_folder_vars=' \\\n               '\\'[\"settings.compiler\", \"settings.compiler.version\"]\\' '\n    client.run(\"install . {}\".format(settings))\n    client.run(\"install . {} -s compiler.version=6\".format(settings))\n\n    presets_path_5 = os.path.join(client.current_folder, \"build\", \"gcc-5\")\n    assert os.path.exists(presets_path_5)\n\n    presets_path_6 = os.path.join(client.current_folder, \"build\", \"gcc-6\")\n    assert os.path.exists(presets_path_6)\n\n    rmdir(presets_path_5)\n\n    # If we generate another configuration, the missing one (removed) for gcc-5 is not included\n    client.run(\"install . {} -s compiler.version=11\".format(settings))\n\n    user_presets_path = os.path.join(client.current_folder, \"CMakeUserPresets.json\")\n    assert os.path.exists(user_presets_path)\n\n    contents = json.loads(load(user_presets_path))\n    assert len(contents[\"include\"]) == 2\n    assert \"gcc-6\" in contents[\"include\"][0]\n    assert \"gcc-11\" in contents[\"include\"][1]\n\n\n@pytest.mark.tool(\"cmake\", \"3.23\")\ndef test_cmake_presets_options_single_config():\n    client = TestClient(path_with_spaces=False)\n    client.run(\"new cmake_lib -d name=hello -d version=0.1\")\n    conf_layout = '-c tools.cmake.cmake_layout:build_folder_vars=\\'[\"settings.compiler\",' \\\n                  '\"settings.build_type\", \"options.shared\"]\\''\n\n    default_compiler = {\"Darwin\": \"apple-clang\",\n                        \"Windows\": \"msvc\",\n                        \"Linux\": \"gcc\"}.get(platform.system())\n\n    for shared in (True, False):\n        client.run(\"install . {} -o shared={}\".format(conf_layout, shared))\n        shared_str = \"shared\" if shared else \"static\"\n        assert os.path.exists(os.path.join(client.current_folder,\n                                           \"build\", f\"{default_compiler}-release-{shared_str}\",\n                                           \"generators\"))\n\n    client.run(\"install . {}\".format(conf_layout))\n    assert os.path.exists(os.path.join(client.current_folder,\n                                       \"build\", \"{}-release-static\".format(default_compiler),\n                                       \"generators\"))\n\n    user_presets_path = os.path.join(client.current_folder, \"CMakeUserPresets.json\")\n    assert os.path.exists(user_presets_path)\n\n    # We can build with cmake manually\n    if platform.system() == \"Darwin\":\n        for shared in (True, False):\n            shared_str = \"shared\" if shared else \"static\"\n            client.run_command(f\"cmake . --preset conan-apple-clang-release-{shared_str}\")\n            client.run_command(f\"cmake --build --preset conan-apple-clang-release-{shared_str}\")\n            client.run_command(f\"ctest --preset conan-apple-clang-release-{shared_str}\")\n            the_lib = \"libhello.a\" if not shared else \"libhello.dylib\"\n            path = os.path.join(client.current_folder,\n                                \"build\", \"apple-clang-release-{}\".format(shared_str), the_lib)\n            assert os.path.exists(path)\n\n\n@pytest.mark.tool(\"cmake\", \"3.23\")\ndef test_cmake_presets_with_conanfile_txt():\n    c = TestClient()\n\n    c.run(\"new cmake_exe -d name=foo -d version=1.0\")\n    os.unlink(os.path.join(c.current_folder, \"conanfile.py\"))\n    c.save({\"conanfile.txt\": textwrap.dedent(\"\"\"\n        [generators]\n        CMakeToolchain\n\n        [layout]\n        cmake_layout\n        \"\"\")})\n\n    c.run(\"install .\")\n    c.run(\"install . -s build_type=Debug\")\n\n    if platform.system() != \"Windows\":\n        c.run_command(\"cmake --preset conan-debug\")\n        c.run_command(\"cmake --build --preset conan-debug\")\n        c.run_command(\"ctest --preset conan-debug\")\n        c.run_command(\"./build/Debug/foo\")\n    else:\n        c.run_command(\"cmake --preset conan-default\")\n        # this second called used to fail\n        # https://github.com/conan-io/conan/issues/13792, CMake ignoring toolchain architecture\n        # and toolset\n        c.run_command(\"cmake --preset conan-default\")\n        c.run_command(\"cmake --build --preset conan-debug\")\n        c.run_command(\"ctest --preset conan-debug\")\n        c.run_command(\"build\\\\Debug\\\\foo\")\n\n    assert \"Hello World Debug!\" in c.out\n\n    if platform.system() != \"Windows\":\n        c.run_command(\"cmake --preset conan-release\")\n        c.run_command(\"cmake --build --preset conan-release\")\n        c.run_command(\"ctest --preset conan-release\")\n        c.run_command(\"./build/Release/foo\")\n    else:\n        c.run_command(\"cmake --build --preset conan-release\")\n        c.run_command(\"ctest --preset conan-release\")\n        c.run_command(\"build\\\\Release\\\\foo\")\n\n    assert \"Hello World Release!\" in c.out\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Needs windows\")\n@pytest.mark.tool(\"ninja\")\n@pytest.mark.tool(\"cmake\", \"3.23\")\ndef test_cmake_presets_with_conanfile_txt_ninja():\n    c = TestClient()\n\n    c.run(\"new cmake_exe -d name=foo -d version=1.0\")\n    os.unlink(os.path.join(c.current_folder, \"conanfile.py\"))\n    c.save({\"conanfile.txt\": textwrap.dedent(\"\"\"\n        [generators]\n        CMakeToolchain\n\n        [layout]\n        cmake_layout\n        \"\"\")})\n\n    conf = \"-c tools.cmake.cmaketoolchain:generator=Ninja\"\n    c.run(f\"install . {conf}\")\n    c.run(f\"install . -s build_type=Debug {conf}\")\n\n    c.run_command(\"build\\\\Release\\\\generators\\\\conanbuild.bat && cmake --preset conan-release\")\n    c.run_command(\"build\\\\Release\\\\generators\\\\conanbuild.bat && cmake --preset conan-release\")\n    c.run_command(\"build\\\\Release\\\\generators\\\\conanbuild.bat \"\n                  \"&& cmake --build --preset conan-release\")\n    c.run_command(\"build\\\\Release\\\\generators\\\\conanbuild.bat && ctest --preset conan-release\")\n    c.run_command(\"build\\\\Release\\\\foo\")\n\n    assert \"Hello World Release!\" in c.out\n\n\ndef test_cmake_toolchain_custom_toolchain():\n    client = TestClient(path_with_spaces=False)\n    conanfile = GenConanfile().with_settings(\"os\", \"compiler\", \"build_type\", \"arch\").\\\n        with_generator(\"CMakeToolchain\")\n    client.save_home({\"global.conf\": \"tools.cmake.cmaketoolchain:toolchain_file=mytoolchain.cmake\"})\n\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"install .\")\n    assert not os.path.exists(os.path.join(client.current_folder, \"conan_toolchain.cmake\"))\n    presets = load_cmake_presets(client.current_folder)\n    assert \"mytoolchain.cmake\" in presets[\"configurePresets\"][0][\"toolchainFile\"]\n    assert \"binaryDir\" in presets[\"configurePresets\"][0]\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\",\n                    reason=\"Single config test, Linux CI still without 3.23\")\n@pytest.mark.tool(\"cmake\", \"3.23\")\n@pytest.mark.parametrize(\"existing_user_presets\", [None, \"user_provided\", \"conan_generated\"])\ndef test_cmake_user_presets_load(existing_user_presets):\n    \"\"\"\n    Test if the CMakeUserPresets.cmake is generated and use CMake to use it to verify the right\n    syntax of generated CMakeUserPresets.cmake and CMakePresets.cmake. If the user already provided\n    a CMakeUserPresets.cmake, leave the file untouched, and only generate or modify the file if\n    the `conan` object exists in the `vendor` field.\n    \"\"\"\n    t = TestClient()\n    t.run(\"new -d name=mylib -d version=1.0 -f cmake_lib\")\n    t.run(\"create . -s:h build_type=Release\")\n    t.run(\"create . -s:h build_type=Debug\")\n\n    consumer = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import cmake_layout\n\n        class Consumer(ConanFile):\n\n            settings = \"build_type\", \"os\", \"arch\", \"compiler\"\n            requires = \"mylib/1.0\"\n            generators = \"CMakeToolchain\", \"CMakeDeps\"\n\n            def layout(self):\n                cmake_layout(self)\n\n    \"\"\")\n\n    cmakelist = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.1)\n        project(PackageTest NONE)\n        find_package(mylib REQUIRED CONFIG)\n        \"\"\")\n\n    user_presets = None\n    if existing_user_presets == \"user_provided\":\n        user_presets = \"{}\"\n    elif existing_user_presets == \"conan_generated\":\n        user_presets = '{ \"vendor\": {\"conan\": {} } }'\n\n    files_to_save = {\"conanfile.py\": consumer, \"CMakeLists.txt\": cmakelist}\n\n    if user_presets:\n        files_to_save['CMakeUserPresets.json'] = user_presets\n    t.save(files_to_save, clean_first=True)\n    t.run(\"install . -s:h build_type=Debug -g CMakeToolchain\")\n    t.run(\"install . -s:h build_type=Release -g CMakeToolchain\")\n\n    user_presets_path = os.path.join(t.current_folder, \"CMakeUserPresets.json\")\n    assert os.path.exists(user_presets_path)\n\n    user_presets_data = json.loads(load(user_presets_path))\n    if existing_user_presets == \"user_provided\":\n        assert not user_presets_data\n    else:\n        assert \"include\" in user_presets_data.keys()\n\n    if existing_user_presets is None:\n        t.run_command(\"cmake . --preset conan-release\")\n        assert 'CMAKE_BUILD_TYPE=\"Release\"' in t.out\n        t.run_command(\"cmake . --preset conan-debug\")\n        assert 'CMAKE_BUILD_TYPE=\"Debug\"' in t.out\n\n\n@pytest.mark.tool(\"cmake\", \"3.23\")\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Needs windows\")\ndef test_cmake_presets_multiple_settings_multi_config():\n    client = TestClient(path_with_spaces=False)\n    client.run(\"new cmake_exe -d name=hello -d version=0.1\")\n    settings_layout = '-c tools.cmake.cmake_layout:build_folder_vars=' \\\n                      '\\'[\"settings.compiler.runtime\", \"settings.compiler.cppstd\"]\\''\n\n    user_presets_path = os.path.join(client.current_folder, \"CMakeUserPresets.json\")\n\n    # Check that all generated names are expected, both in the layout and in the Presets\n    settings = \"-s compiler=msvc -s compiler.version=191 -s compiler.runtime=dynamic \" \\\n               \"-s compiler.cppstd=14\"\n    client.run(\"install . {} {}\".format(settings, settings_layout))\n    assert os.path.exists(os.path.join(client.current_folder, \"build\", \"dynamic-14\", \"generators\"))\n    assert os.path.exists(user_presets_path)\n    user_presets = json.loads(load(user_presets_path))\n    assert len(user_presets[\"include\"]) == 1\n    presets = json.loads(client.load(user_presets[\"include\"][0]))\n    assert len(presets[\"configurePresets\"]) == 1\n    assert len(presets[\"buildPresets\"]) == 1\n    assert len(presets[\"testPresets\"]) == 1\n    assert presets[\"configurePresets\"][0][\"name\"] == \"conan-dynamic-14\"\n    assert presets[\"buildPresets\"][0][\"name\"] == \"conan-dynamic-14-release\"\n    assert presets[\"buildPresets\"][0][\"configurePreset\"] == \"conan-dynamic-14\"\n    assert presets[\"testPresets\"][0][\"name\"] == \"conan-dynamic-14-release\"\n    assert presets[\"testPresets\"][0][\"configurePreset\"] == \"conan-dynamic-14\"\n\n    # If we create the \"Debug\" one, it has the same toolchain and preset file, that is\n    # always multiconfig\n    client.run(\"install . {} -s build_type=Debug {}\".format(settings, settings_layout))\n    assert os.path.exists(os.path.join(client.current_folder, \"build\", \"dynamic-14\", \"generators\"))\n    assert os.path.exists(user_presets_path)\n    user_presets = json.loads(load(user_presets_path))\n    assert len(user_presets[\"include\"]) == 1\n    presets = json.loads(client.load(user_presets[\"include\"][0]))\n    assert len(presets[\"configurePresets\"]) == 1\n    assert len(presets[\"buildPresets\"]) == 2\n    assert len(presets[\"testPresets\"]) == 2\n    assert presets[\"configurePresets\"][0][\"name\"] == \"conan-dynamic-14\"\n    assert presets[\"buildPresets\"][0][\"name\"] == \"conan-dynamic-14-release\"\n    assert presets[\"buildPresets\"][1][\"name\"] == \"conan-dynamic-14-debug\"\n    assert presets[\"buildPresets\"][0][\"configurePreset\"] == \"conan-dynamic-14\"\n    assert presets[\"buildPresets\"][1][\"configurePreset\"] == \"conan-dynamic-14\"\n    assert presets[\"testPresets\"][0][\"name\"] == \"conan-dynamic-14-release\"\n    assert presets[\"testPresets\"][1][\"name\"] == \"conan-dynamic-14-debug\"\n    assert presets[\"testPresets\"][0][\"configurePreset\"] == \"conan-dynamic-14\"\n    assert presets[\"testPresets\"][1][\"configurePreset\"] == \"conan-dynamic-14\"\n\n    # But If we change, for example, the cppstd and the compiler version, the toolchain\n    # and presets will be different, but it will be appended to the UserPresets.json\n    settings = \"-s compiler=msvc -s compiler.version=191 -s compiler.runtime=static \" \\\n               \"-s compiler.cppstd=17\"\n    client.run(\"install . {} {}\".format(settings, settings_layout))\n    assert os.path.exists(os.path.join(client.current_folder, \"build\", \"static-17\", \"generators\"))\n    assert os.path.exists(user_presets_path)\n    user_presets = json.loads(load(user_presets_path))\n    # The [0] is the msvc dynamic/14 the [1] is the static/17\n    assert len(user_presets[\"include\"]) == 2\n    presets = json.loads(client.load(user_presets[\"include\"][1]))\n    assert len(presets[\"configurePresets\"]) == 1\n    assert len(presets[\"buildPresets\"]) == 1\n    assert len(presets[\"testPresets\"]) == 1\n    assert presets[\"configurePresets\"][0][\"name\"] == \"conan-static-17\"\n    assert presets[\"buildPresets\"][0][\"name\"] == \"conan-static-17-release\"\n    assert presets[\"buildPresets\"][0][\"configurePreset\"] == \"conan-static-17\"\n    assert presets[\"testPresets\"][0][\"name\"] == \"conan-static-17-release\"\n    assert presets[\"testPresets\"][0][\"configurePreset\"] == \"conan-static-17\"\n\n    # We can build with cmake manually\n    client.run_command(\"cmake . --preset conan-dynamic-14\")\n\n    client.run_command(\"cmake --build --preset conan-dynamic-14-release\")\n    client.run_command(\"ctest --preset conan-dynamic-14-release\")\n    client.run_command(\"build\\\\dynamic-14\\\\Release\\\\hello\")\n    assert \"Hello World Release!\" in client.out\n    assert \"MSVC_LANG2014\" in client.out\n\n    client.run_command(\"cmake --build --preset conan-dynamic-14-debug\")\n    client.run_command(\"ctest --preset conan-dynamic-14-debug\")\n    client.run_command(\"build\\\\dynamic-14\\\\Debug\\\\hello\")\n    assert \"Hello World Debug!\" in client.out\n    assert \"MSVC_LANG2014\" in client.out\n\n    client.run_command(\"cmake . --preset conan-static-17\")\n\n    client.run_command(\"cmake --build --preset conan-static-17-release\")\n    client.run_command(\"ctest --preset conan-static-17-release\")\n    client.run_command(\"build\\\\static-17\\\\Release\\\\hello\")\n    assert \"Hello World Release!\" in client.out\n    assert \"MSVC_LANG2017\" in client.out\n\n\n@pytest.mark.tool(\"cmake\", \"3.23\")\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Needs windows\")\n# Test both with a local folder and an absolute folder\n@pytest.mark.parametrize(\"build\", [\"mybuild\", \"temp\"])\ndef test_cmake_presets_build_folder(build):\n    client = TestClient(path_with_spaces=False)\n    client.run(\"new cmake_exe -d name=hello -d version=0.1\")\n\n    build = temp_folder() if build == \"temp\" else build\n    settings_layout = f' -c tools.cmake.cmake_layout:build_folder=\"{build}\" '\\\n                      '-c tools.cmake.cmake_layout:build_folder_vars=' \\\n                      '\\'[\"settings.compiler.runtime\", \"settings.compiler.cppstd\"]\\''\n    # But If we change, for example, the cppstd and the compiler version, the toolchain\n    # and presets will be different, but it will be appended to the UserPresets.json\n    settings = \"-s compiler=msvc -s compiler.version=191 -s compiler.runtime=static \" \\\n               \"-s compiler.cppstd=17\"\n    client.run(\"install . {} {}\".format(settings, settings_layout))\n    assert os.path.exists(os.path.join(client.current_folder, build, \"static-17\", \"generators\"))\n\n    client.run_command(\"cmake . --preset conan-static-17\")\n    client.run_command(\"cmake --build --preset conan-static-17-release\")\n    client.run_command(\"ctest --preset conan-static-17-release\")\n    client.run_command(f\"{build}\\\\static-17\\\\Release\\\\hello\")\n    assert \"Hello World Release!\" in client.out\n    assert \"MSVC_LANG2017\" in client.out\n\n\n@pytest.mark.tool(\"cmake\", \"3.23\")\nclass TestEnvironmentInPresets:\n    @pytest.fixture(scope=\"class\")\n    def _init_client(self):\n        c = TestClient()\n        tool = textwrap.dedent(r\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.files import chdir, save\n            class Tool(ConanFile):\n                version = \"0.1\"\n                settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n                def package(self):\n                    with chdir(self, self.package_folder):\n                        v = f\"{{self.name}}/{{self.version}}\"\n                        save(self, f\"bin/{{self.name}}.bat\", f\"@echo off\\necho running: {{v}}\")\n                        save(self, f\"bin/{{self.name}}.sh\", f\"echo running: {{v}}\")\n                        os.chmod(f\"bin/{{self.name}}.sh\", 0o777)\n                def package_info(self):\n                    self.buildenv_info.define(\"MY_BUILD_VAR\", \"MY_BUILDVAR_VALUE\")\n                    {}\n            \"\"\")\n\n        consumer = textwrap.dedent(\"\"\"\n            [tool_requires]\n            mytool/0.1\n            [test_requires]\n            mytesttool/0.1\n            [layout]\n            cmake_layout\n        \"\"\")\n\n        test_env = textwrap.dedent(\"\"\"\n            #include <cstdlib>\n            int main() {\n                return std::getenv(\"MY_RUNVAR\") ? 0 : 1;\n            }\n        \"\"\")\n\n        cmakelists = textwrap.dedent(\"\"\"\n            set(CMAKE_CXX_COMPILER_WORKS 1)\n            set(CMAKE_CXX_ABI_COMPILED 1)\n            cmake_minimum_required(VERSION 3.15)\n            project(MyProject CXX)\n\n            if(WIN32)\n                set(MYTOOL_SCRIPT \"mytool.bat\")\n            else()\n                set(MYTOOL_SCRIPT \"mytool.sh\")\n            endif()\n\n            add_custom_target(run_mytool COMMAND ${MYTOOL_SCRIPT})\n\n            function(check_and_report_variable var_name)\n                set(var_value $ENV{${var_name}})\n                if (var_value)\n                    message(\"${var_name}:${var_value}\")\n                else()\n                    message(\"${var_name} NOT FOUND\")\n                endif()\n            endfunction()\n\n            check_and_report_variable(\"MY_BUILD_VAR\")\n            check_and_report_variable(\"MY_RUNVAR\")\n            check_and_report_variable(\"MY_ENV_VAR\")\n\n            enable_testing()\n            add_executable(test_env test_env.cpp)\n            add_test(NAME TestRunEnv COMMAND test_env)\n        \"\"\")\n\n        c.save({\"tool.py\": tool.format(\"\"),\n                \"test_tool.py\":\n                    tool.format('self.runenv_info.define(\"MY_RUNVAR\", \"MY_RUNVAR_VALUE\")'),\n                \"conanfile.txt\": consumer,\n                \"CMakeLists.txt\": cmakelists,\n                \"test_env.cpp\": test_env})\n\n        c.run(\"create tool.py --name=mytool\")\n\n        c.run(\"create test_tool.py --name=mytesttool\")\n        c.run(\"create test_tool.py --name=mytesttool -s build_type=Debug\")\n\n        yield c\n\n    def test_add_env_to_presets(self, _init_client):\n        c = _init_client\n\n        # do a first conan install with env disabled just to test that the conf works\n        c.run(\"install . -g CMakeToolchain -g CMakeDeps \"\n              \"-c tools.cmake.cmaketoolchain:presets_environment=disabled\")\n\n        presets_path = os.path.join(\"build\", \"Release\", \"generators\", \"CMakePresets.json\") \\\n            if platform.system() != \"Windows\" else os.path.join(\"build\", \"generators\",\n                                                                \"CMakePresets.json\")\n        presets = json.loads(c.load(presets_path))\n\n        assert presets[\"configurePresets\"][0].get(\"env\") is None\n\n        c.run(\"install . -g CMakeToolchain -g CMakeDeps\")\n        c.run(\"install . -g CMakeToolchain -g CMakeDeps -s:h build_type=Debug\")\n\n        # test that the buildenv is correctly injected to configure and build steps\n        # that the runenv is not injected to configure, but it is when running tests\n\n        preset = \"conan-default\" if platform.system() == \"Windows\" else \"conan-release\"\n\n        c.run_command(f\"cmake --preset {preset}\")\n        assert \"MY_BUILD_VAR:MY_BUILDVAR_VALUE\" in c.out\n        assert \"MY_RUNVAR NOT FOUND\" in c.out\n        c.run_command(\"cmake --build --preset conan-release --target run_mytool --target test_env\")\n        assert \"running: mytool/0.1\" in c.out\n\n        c.run_command(\"ctest --preset conan-release\")\n        assert \"tests passed\" in c.out\n\n        if platform.system() != \"Windows\":\n            c.run_command(\"cmake --preset conan-debug\")\n            assert \"MY_BUILD_VAR:MY_BUILDVAR_VALUE\" in c.out\n            assert \"MY_RUNVAR NOT FOUND\" in c.out\n\n        c.run_command(\"cmake --build --preset conan-debug --target run_mytool --target test_env\")\n        assert \"running: mytool/0.1\" in c.out\n\n        c.run_command(\"ctest --preset conan-debug\")\n        assert \"tests passed\" in c.out\n\n    def test_add_generate_env_to_presets(self, _init_client):\n        c = _init_client\n\n        consumer = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.cmake import cmake_layout, CMakeToolchain, CMakeDeps\n            from conan.tools.env import VirtualBuildEnv, VirtualRunEnv, Environment\n\n            class mypkgRecipe(ConanFile):\n                name = \"mypkg\"\n                version = \"1.0\"\n                settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n                tool_requires = \"mytool/0.1\"\n                test_requires = \"mytesttool/0.1\"\n                def layout(self):\n                    cmake_layout(self)\n\n                def generate(self):\n\n                    buildenv = VirtualBuildEnv(self)\n                    buildenv.environment().define(\"MY_BUILD_VAR\", \"MY_BUILDVAR_VALUE_OVERRIDEN\")\n                    buildenv.generate()\n\n                    runenv = VirtualRunEnv(self)\n                    runenv.environment().define(\"MY_RUN_VAR\", \"MY_RUNVAR_SET_IN_GENERATE\")\n                    runenv.generate()\n\n                    env = Environment()\n                    env.define(\"MY_ENV_VAR\", \"MY_ENV_VAR_VALUE\")\n                    env = env.vars(self)\n                    env.save_script(\"other_env\")\n\n                    deps = CMakeDeps(self)\n                    deps.generate()\n                    tc = CMakeToolchain(self)\n                    tc.presets_build_environment = buildenv.environment().compose_env(env)\n                    tc.presets_run_environment = runenv.environment()\n                    tc.generate()\n        \"\"\")\n\n        test_env = textwrap.dedent(\"\"\"\n            #include <string>\n            int main() {\n                return std::string(std::getenv(\"MY_RUNVAR\"))==\"MY_RUNVAR_SET_IN_GENERATE\";\n            }\n        \"\"\")\n\n        c.save({\"conanfile.py\": consumer,\n                \"test_env.cpp\": test_env})\n\n        c.run(\"install conanfile.py\")\n\n        preset = \"conan-default\" if platform.system() == \"Windows\" else \"conan-release\"\n\n        c.run_command(f\"cmake --preset {preset}\")\n        assert \"MY_BUILD_VAR:MY_BUILDVAR_VALUE_OVERRIDEN\" in c.out\n        assert \"MY_ENV_VAR:MY_ENV_VAR_VALUE\" in c.out\n\n        c.run_command(\"cmake --build --preset conan-release --target run_mytool --target test_env\")\n        assert \"running: mytool/0.1\" in c.out\n\n        c.run_command(f\"ctest --preset conan-release\")\n        assert \"tests passed\" in c.out\n"
  },
  {
    "path": "test/functional/toolchains/cmake/test_cmake_toolchain_win_clang.py",
    "content": "import platform\nimport re\nimport tempfile\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.cmake import gen_cmakelists\nfrom conan.test.assets.sources import gen_function_cpp, gen_function_c\nfrom test.conftest import tools_locations\nfrom test.functional.utils import check_vs_runtime, check_exe_run\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.fixture\ndef client():\n    # IMPORTANT: This cannot use the default tests location, if in Windows, it can be another unit\n    # like F and Visual WONT FIND ClangCL\n    t = tempfile.mkdtemp(suffix='conans')\n    c = TestClient(cache_folder=t)\n    clang_profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=Windows\n        arch=x86_64\n        build_type=Release\n        compiler=clang\n        compiler.version=18\n        compiler.cppstd=14\n        [conf]\n        tools.build:compiler_executables={\"cpp\": \"clang++\", \"c\": \"clang\", \"rc\": \"clang\"}\n        \"\"\")\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.cmake import CMake, cmake_layout\n\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            exports_sources = \"*\"\n            generators = \"CMakeToolchain\"\n\n            def layout(self):\n                cmake_layout(self)\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n                cmd = os.path.join(self.cpp.build.bindirs[0], \"my_app\")\n                self.run(cmd)\n\n            def package(self):\n                cmake = CMake(self)\n                cmake.install()\n\n            def package_info(self):\n                cmd = os.path.join(self.package_folder, \"bin\", \"my_app\")\n                self.output.info(\"MYCMD={}!\".format(os.path.abspath(cmd)))\n        \"\"\")\n    clangpath = tools_locations[\"clang\"][\"20\"][\"path\"][\"Windows\"]\n    llvm_clang_path = textwrap.dedent(f\"\"\"\n                      [buildenv]\n                      PATH=+(path){clangpath}\n                      \"\"\")\n    c.save({\"conanfile.py\": conanfile,\n            \"clang\": clang_profile,\n            \"clang_path\": llvm_clang_path,\n            \"CMakeLists.txt\": gen_cmakelists(appname=\"my_app\", appsources=[\"src/main.cpp\"],\n                                             install=True),\n            \"src/main.cpp\": gen_function_cpp(name=\"main\")})\n    return c\n\n\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.tool(\"clang\", \"20\")\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"requires Win\")\nclass TestLLVMClang:\n    \"\"\" External LLVM/clang, with different CMake generators\n    This links always with the VS runtime, it is built-in\n    \"\"\"\n\n    @pytest.mark.tool(\"mingw64\")\n    @pytest.mark.tool(\"visual_studio\", \"17\")\n    @pytest.mark.parametrize(\"runtime\", [\"static\", \"dynamic\"])\n    def test_clang_mingw(self, client, runtime):\n        \"\"\" compiling with an LLVM-clang installed, which uses by default the\n        VS runtime\n        \"\"\"\n        client.run(\"create . --name=pkg --version=0.1 -pr=clang -pr=clang_path \"\n                   \"-s compiler.runtime_version=v144 \"\n                   \"-s compiler.runtime={}\".format(runtime))\n        # clang compilations in Windows will use MinGW Makefiles by default\n        assert 'cmake -G \"MinGW Makefiles\"' in client.out\n        assert \"GNU-like command-line\" in client.out\n        assert \"main __clang_major__20\" in client.out\n        assert \"main _MSC_VER194\" in client.out\n        assert \"main _MSVC_LANG2014\" in client.out\n        assert \"main _M_X64 defined\" in client.out\n        assert \"main __x86_64__ defined\" in client.out\n\n        check_exe_run(client.out, \"main\", \"clang\", None, \"Release\", \"x86_64\", \"14\")\n        cmd = re.search(r\"MYCMD=(.*)!\", str(client.out)).group(1)\n        cmd = cmd + \".exe\"\n        static_runtime = (runtime == \"static\")\n        check_vs_runtime(cmd, client, \"17\", build_type=\"Release\", static_runtime=static_runtime)\n\n    @pytest.mark.tool(\"ninja\")\n    @pytest.mark.tool(\"visual_studio\", \"17\")\n    @pytest.mark.parametrize(\"generator\", [\"Ninja\", \"NMake Makefiles\"])\n    def test_clang_cmake_ninja_nmake(self, client, generator):\n        client.run(\"create . --name=pkg --version=0.1 -pr=clang  -pr=clang_path \"\n                   \"-s compiler.runtime=dynamic -s compiler.runtime_version=v144 \"\n                   '-c tools.cmake.cmaketoolchain:generator=\"{}\"'.format(generator))\n\n        assert 'cmake -G \"{}\"'.format(generator) in client.out\n        assert \"GNU-like command-line\" in client.out\n        assert \"main __clang_major__20\" in client.out\n        assert \"main _MSC_VER194\" in client.out\n        assert \"main _MSVC_LANG2014\" in client.out\n        assert \"main _M_X64 defined\" in client.out\n        assert \"main __x86_64__ defined\" in client.out\n        cmd = re.search(r\"MYCMD=(.*)!\", str(client.out)).group(1)\n        cmd = cmd + \".exe\"\n        check_vs_runtime(cmd, client, \"17\", build_type=\"Release\", static_runtime=False)\n\n    @pytest.mark.tool(\"ninja\")\n    @pytest.mark.tool(\"visual_studio\", \"17\")\n    def test_clang_cmake_ninja_clang_cl(self, client):\n        pr = textwrap.dedent(\"\"\"\\\n            [conf]\n            tools.build:compiler_executables={\"cpp\": \"clang-cl\", \"c\": \"clang-cl\", \"rc\": \"clang\"}\n            \"\"\")\n        client.save({\"comp_exes\": pr})\n\n        client.run(\"create . --name=pkg --version=0.1 -pr=clang -pr=clang_path -pr=comp_exes \"\n                   \"-s compiler.runtime=dynamic -s compiler.runtime_version=v144 \"\n                   '-c tools.cmake.cmaketoolchain:generator=\"Ninja\"')\n\n        assert 'cmake -G \"Ninja\"' in client.out\n        assert \"MSVC-like command-line\" in client.out\n        assert \"main __clang_major__20\" in client.out\n        assert \"main _MSC_VER194\" in client.out\n        assert \"main _MSVC_LANG2014\" in client.out\n        assert \"main _M_X64 defined\" in client.out\n        assert \"main __x86_64__ defined\" in client.out\n        cmd = re.search(r\"MYCMD=(.*)!\", str(client.out)).group(1)\n        cmd = cmd + \".exe\"\n        check_vs_runtime(cmd, client, \"17\", build_type=\"Release\", static_runtime=False)\n\n    @pytest.mark.tool(\"ninja\")\n    @pytest.mark.tool(\"visual_studio\", \"17\")\n    def test_clang_cmake_runtime_version(self, client):\n        generator = \"Ninja\"\n        # Make sure that normal CMakeLists with verify=False works\n        client.save({\"CMakeLists.txt\": gen_cmakelists(verify=False, appname=\"my_app\",\n                                                      appsources=[\"src/main.cpp\"], install=True)})\n        client.run(\"create . --name=pkg --version=0.1 -pr=clang -pr=clang_path \"\n                   \"-s compiler.runtime=dynamic \"\n                   \"-s compiler.cppstd=17 -s compiler.runtime_version=v144 \"\n                   '-c tools.cmake.cmaketoolchain:generator=\"{}\"'.format(generator))\n\n        assert 'cmake -G \"{}\"'.format(generator) in client.out\n        assert \"GNU-like command-line\" in client.out\n        assert \"main __clang_major__20\" in client.out\n        # Check this! Clang compiler in Windows is reporting MSC_VER and MSVC_LANG!\n        assert \"main _MSC_VER194\" in client.out\n        assert \"main _MSVC_LANG2017\" in client.out\n        assert \"main _M_X64 defined\" in client.out\n        assert \"main __x86_64__ defined\" in client.out\n        cmd = re.search(r\"MYCMD=(.*)!\", str(client.out)).group(1)\n        cmd = cmd + \".exe\"\n        check_vs_runtime(cmd, client, \"17\", build_type=\"Release\", static_runtime=False)\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"requires Win\")\nclass TestVSClangCL:\n    \"\"\"\n    This is also LLVM/Clang, but distributed with the VS installation\n    \"\"\"\n    @pytest.mark.tool(\"cmake\", \"3.27\")\n    @pytest.mark.tool(\"visual_studio\", \"17\")\n    def test_clang_visual_studio_generator(self, client):\n        \"\"\" This is using the embedded ClangCL compiler, not the external one\"\"\"\n        generator = \"Visual Studio 17\"\n        client.run(\"create . --name=pkg --version=0.1 -pr=clang -s compiler.runtime=dynamic \"\n                   \"-s compiler.cppstd=17 -s compiler.runtime_version=v144 \"\n                   '-c tools.cmake.cmaketoolchain:generator=\"{}\"'.format(generator))\n        assert 'cmake -G \"{}\"'.format(generator) in client.out\n        assert \"MSVC-like command-line\" in client.out\n        assert \"main __clang_major__19\" in client.out  # The one inside VS is clang 19\n        # Check this! Clang compiler in Windows is reporting MSC_VER and MSVC_LANG!\n        # CI forced the installation of 19.38, seems to prevail there\n        assert \"main _MSC_VER19\" in client.out\n        assert \"main _MSVC_LANG2017\" in client.out\n        assert \"main _M_X64 defined\" in client.out\n        assert \"main __x86_64__ defined\" in client.out\n        assert \"-m64\" not in client.out\n        cmd = re.search(r\"MYCMD=(.*)!\", str(client.out)).group(1)\n        cmd = cmd + \".exe\"\n        check_vs_runtime(cmd, client, \"17\", build_type=\"Release\", static_runtime=False)\n\n\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"requires Win\")\nclass TestMsysClang:\n    @pytest.mark.tool(\"msys2_clang64\")\n    def test_msys2_clang(self, client):\n        \"\"\" Using the msys2 clang64 subsystem\n        We are not really injecting the msys2 root with make, so using\n        MinGW Makefiles\n        \"\"\"\n        client.run('create . --name=pkg --version=0.1 -pr=clang -s os.subsystem=msys2 '\n                   '-s compiler.libcxx=libc++ '\n                   '-c tools.cmake.cmaketoolchain:generator=\"MinGW Makefiles\"')\n        # clang compilations in Windows will use MinGW Makefiles by default\n        assert 'cmake -G \"MinGW Makefiles\"' in client.out\n        # TODO: Version is still not controlled\n        assert \"main __clang_major__21\" in client.out\n        # Not using libstdc++\n        assert \"_GLIBCXX_USE_CXX11_ABI\" not in client.out\n        assert \"main __cplusplus2014\" in client.out\n        assert \"main __GNUC__\" in client.out\n        assert \"main __MINGW32__1\" in client.out\n        assert \"main __MINGW64__1\" in client.out\n        assert \"main _MSC_\" not in client.out\n        assert \"main _MSVC_\" not in client.out\n        assert \"main _M_X64 defined\" in client.out\n        assert \"main __x86_64__ defined\" in client.out\n\n        cmd = re.search(r\"MYCMD=(.*)!\", str(client.out)).group(1)\n        cmd = cmd + \".exe\"\n        check_vs_runtime(cmd, client, \"17\", build_type=\"Release\",\n                         static_runtime=False, subsystem=\"clang64\")\n\n    @pytest.mark.tool(\"msys2_mingw64_clang64\")\n    def test_msys2_clang_mingw(self, client):\n        \"\"\" compiling with the clang INSIDE mingw, which uses the\n        MinGW runtime, not the MSVC one\n        For 32 bits, it doesn't seem possible to install the toolchain\n        For 64 bits require \"pacman -S mingw-w64-x86-clang++\"\n        \"\"\"\n        # TODO: This should probably go to the ``os.subsystem=ming64\" but lets do it in other PR\n        client.run('create . --name=pkg --version=0.1 -pr=clang '\n                   '-s compiler.libcxx=libstdc++')\n        # clang compilations in Windows will use MinGW Makefiles by default\n        assert 'cmake -G \"MinGW Makefiles\"' in client.out\n        # TODO: Version is still not controlled\n        assert \"main __clang_major__21\" in client.out\n        assert \"main _GLIBCXX_USE_CXX11_ABI 0\" in client.out\n        assert \"main __cplusplus2014\" in client.out\n        assert \"main __GNUC__\" in client.out\n        assert \"main __MINGW32__1\" in client.out\n        assert \"main __MINGW64__1\" in client.out\n        assert \"main _MSC_\" not in client.out\n        assert \"main _MSVC_\" not in client.out\n        assert \"main _M_X64 defined\" in client.out\n        assert \"main __x86_64__ defined\" in client.out\n\n        cmd = re.search(r\"MYCMD=(.*)!\", str(client.out)).group(1)\n        cmd = cmd + \".exe\"\n        check_vs_runtime(cmd, client, \"17\", build_type=\"Release\",\n                         static_runtime=False, subsystem=\"mingw64\")\n\n    @pytest.mark.tool(\"msys2_clang64\")\n    def test_clang_pure_c(self, client):\n        \"\"\" compiling with the clang INSIDE mingw, which uses the\n        MinGW runtime, not the MSVC one\n        For 32 bits, it doesn't seem possible to install the toolchain\n        For 64 bits require \"pacman -S mingw-w64-x86-clang++\"\n        \"\"\"\n        client.save({\"CMakeLists.txt\": gen_cmakelists(verify=False, language=\"C\", appname=\"my_app\",\n                                                      appsources=[\"src/main.c\"], install=True),\n                     \"src/main.c\": gen_function_c(name=\"main\")})\n        client.run(f\"create . --name=pkg --version=0.1 -pr=clang\")\n        # clang compilations in Windows will use MinGW Makefiles by default\n        assert 'cmake -G \"MinGW Makefiles\"' in client.out\n        assert \"main __clang_major__21\" in client.out\n        assert \"GLIBCXX\" not in client.out\n        assert \"cplusplus\" not in client.out\n        assert \"main __GNUC__\" in client.out\n        assert \"main __MINGW32__1\" in client.out\n        assert \"main __MINGW64__1\" in client.out\n        assert \"main _MSC_\" not in client.out\n        assert \"main _MSVC_\" not in client.out\n        assert \"main _M_X64 defined\" in client.out\n        assert \"main __x86_64__ defined\" in client.out\n\n        cmd = re.search(r\"MYCMD=(.*)!\", str(client.out)).group(1)\n        cmd = cmd + \".exe\"\n        # static_runtime equivalent to C, for checking, no dep on libc++\n        check_vs_runtime(cmd, client, \"17\", build_type=\"Release\", static_runtime=True,\n                         subsystem=\"clang64\")\n\n\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.tool(\"ninja\")\n@pytest.mark.tool(\"clang\", \"20\")\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"requires Win\")\ndef test_error_clang_cmake_ninja_custom_cxx(client):\n    clang_profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=Windows\n        arch=x86_64\n        build_type=Release\n        compiler=clang\n        compiler.version=20\n        [buildenv]\n        CXX=/no/exist/clang++\n        \"\"\")\n    client.save({\"clang\":     clang_profile})\n    client.run(\"create . --name=pkg --version=0.1 -pr=clang \"\n               \"-c tools.cmake.cmaketoolchain:generator=Ninja\", assert_error=True)\n    assert 'Could not find compiler' in client.out\n    assert '/no/exist/clang++' in client.out\n"
  },
  {
    "path": "test/functional/toolchains/cmake/test_cmake_toolchain_xcode_flags.py",
    "content": "import textwrap\nimport platform\nimport os\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\n\ndef _add_message_status_flags(client):\n    cmakelists_path = os.path.join(client.current_folder, \"CMakeLists.txt\")\n    with open(cmakelists_path, \"a\") as cmakelists_file:\n        cmakelists_file.write('message(STATUS \"CONAN_C_FLAGS: ${CONAN_C_FLAGS}\")\\n')\n        cmakelists_file.write('message(STATUS \"CONAN_CXX_FLAGS: ${CONAN_CXX_FLAGS}\")\\n')\n        cmakelists_file.write('message(STATUS \"CONAN_OBJC_FLAGS: ${CONAN_OBJC_FLAGS}\")\\n')\n        cmakelists_file.write('message(STATUS \"CONAN_OBJCXX_FLAGS: ${CONAN_OBJCXX_FLAGS}\")\\n')\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only OSX\")\n@pytest.mark.parametrize(\"op_system,os_version,sdk,arch\", [\n    (\"watchOS\", \"8.1\", \"watchos\", \"armv7k\"),\n    (\"tvOS\", \"13.2\", \"appletvos\", \"armv8\")\n])\ndef test_cmake_apple_bitcode_arc_and_visibility_flags_enabled(op_system, os_version, sdk, arch):\n    profile = textwrap.dedent(\"\"\"\n        include(default)\n        [settings]\n        os={}\n        os.version={}\n        os.sdk={}\n        arch={}\n        [conf]\n        tools.apple:enable_arc=True\n        tools.apple:enable_visibility=True\n    \"\"\".format(op_system, os_version, sdk, arch))\n\n    client = TestClient(path_with_spaces=False)\n    client.save({\"host\": profile}, clean_first=True)\n    client.run(\"new -d name=hello -d version=0.1 cmake_lib\")\n    _add_message_status_flags(client)\n    client.run(\"install . --profile:build=default --profile:host=host\")\n    toolchain = client.load(os.path.join(\"build\", \"Release\", \"generators\", \"conan_toolchain.cmake\"))\n    # arc\n    assert 'set(FOBJC_ARC \"-fobjc-arc\")' in toolchain\n    assert 'set(CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC \"YES\")' in toolchain\n    # visibility\n    assert 'set(CMAKE_XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN \"NO\")' in toolchain\n    assert 'set(VISIBILITY \"-fvisibility=default\")' in toolchain\n\n    client.run(\"create . --profile:build=default --profile:host=host -tf=\")\n    # flags\n    assert \"-- CONAN_C_FLAGS:   -fvisibility=default\" in client.out\n    assert \"-- CONAN_CXX_FLAGS:   -fvisibility=default\" in client.out\n    assert \"-- CONAN_OBJC_FLAGS:   -fvisibility=default -fobjc-arc\" in client.out\n    assert \"-- CONAN_OBJCXX_FLAGS:   -fvisibility=default -fobjc-arc\" in client.out\n    assert \"[100%] Built target hello\" in client.out\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only OSX\")\n@pytest.mark.tool(\"cmake\", \"3.19\")\n@pytest.mark.parametrize(\"op_system,os_version,sdk,arch\", [\n    (\"watchOS\", \"8.1\", \"watchos\", \"armv7k\"),\n    (\"tvOS\", \"13.2\", \"appletvos\", \"armv8\")\n])\ndef test_cmake_apple_bitcode_arc_and_visibility_flags_enabled_and_xcode_generator(op_system, os_version, sdk, arch):\n    \"\"\"\n    Testing when all the Bitcode, ARC and Visibility are enabled, and Xcode as generator.\n\n    Note: When using CMake and Xcode as generator, the C/CXX flags do not need to be appended.\n    \"\"\"\n    profile = textwrap.dedent(\"\"\"\n        include(default)\n        [settings]\n        os={}\n        os.version={}\n        os.sdk={}\n        arch={}\n        [conf]\n        tools.apple:enable_bitcode=True\n        tools.apple:enable_arc=True\n        tools.apple:enable_visibility=True\n    \"\"\".format(op_system, os_version, sdk, arch))\n\n    client = TestClient(path_with_spaces=False)\n    client.save({\"host\": profile}, clean_first=True)\n    client.run(\"new -d name=hello -d version=0.1 cmake_lib\")\n    _add_message_status_flags(client)\n    client.run(\"create . --profile:build=default --profile:host=host -tf=\\\"\\\" \"\n               \"-c tools.cmake.cmaketoolchain:generator=Xcode\")\n    assert \"** BUILD SUCCEEDED **\" in client.out\n    # flags are not appended when Xcode generator is used\n    for line in str(client.out).splitlines():\n        if \"CONAN_C_FLAGS:\" in line:\n            assert \"-- CONAN_C_FLAGS:\" == line.strip()\n        if \"CONAN_CXX_FLAGS:\" in line:\n            assert \"-- CONAN_CXX_FLAGS:  -stdlib=libc++\" == line.strip()\n            break\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only OSX\")\n@pytest.mark.parametrize(\"op_system,os_version,sdk,arch\", [\n    (\"watchOS\", \"8.1\", \"watchos\", \"armv7k\"),\n    (\"tvOS\", \"13.2\", \"appletvos\", \"armv8\")\n])\ndef test_cmake_apple_bitcode_arc_and_visibility_flags_disabled(op_system, os_version, sdk, arch):\n    profile = textwrap.dedent(\"\"\"\n        include(default)\n        [settings]\n        os={}\n        os.version={}\n        os.sdk={}\n        arch={}\n        [conf]\n        tools.apple:enable_bitcode=False\n        tools.apple:enable_arc=False\n        tools.apple:enable_visibility=False\n    \"\"\".format(op_system, os_version, sdk, arch))\n\n    client = TestClient(path_with_spaces=False)\n    client.save({\"host\": profile}, clean_first=True)\n    client.run(\"new -d name=hello -d version=0.1 cmake_lib\")\n    _add_message_status_flags(client)\n    client.run(\"install . --profile:build=default --profile:host=host\")\n    toolchain = client.load(os.path.join(\"build\", \"Release\", \"generators\", \"conan_toolchain.cmake\"))\n    # bitcode\n    assert 'set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE \"NO\")' in toolchain\n    assert 'set(CMAKE_XCODE_ATTRIBUTE_BITCODE_GENERATION_MODE \"bitcode\")' not in toolchain\n    assert 'set(BITCODE \"-fembed-bitcode\")' not in toolchain\n    # arc\n    assert 'set(FOBJC_ARC \"-fno-objc-arc\")' in toolchain\n    assert 'set(CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC \"NO\")' in toolchain\n    # visibility\n    assert 'set(CMAKE_XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN \"YES\")' in toolchain\n    assert 'set(VISIBILITY \"-fvisibility=hidden -fvisibility-inlines-hidden\")' in toolchain\n\n    client.run(\"create . --profile:build=default --profile:host=host -tf=\\\"\\\"\")\n    # flags\n    assert \"-- CONAN_C_FLAGS:   -fvisibility=hidden -fvisibility-inlines-hidden\" in client.out\n    assert \"-- CONAN_CXX_FLAGS:   -fvisibility=hidden -fvisibility-inlines-hidden\" in client.out\n    assert \"-- CONAN_OBJC_FLAGS:   -fvisibility=hidden -fvisibility-inlines-hidden -fno-objc-arc\" in client.out\n    assert \"-- CONAN_OBJCXX_FLAGS:   -fvisibility=hidden -fvisibility-inlines-hidden -fno-objc-arc\" in client.out\n    assert \"[100%] Built target hello\" in client.out\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only OSX\")\n@pytest.mark.parametrize(\"op_system,os_version,sdk,arch\", [\n    (\"watchOS\", \"8.1\", \"watchos\", \"armv7k\"),\n    (\"tvOS\", \"13.2\", \"appletvos\", \"armv8\")\n])\ndef test_cmake_apple_bitcode_arc_and_visibility_flags_are_none(op_system, os_version, sdk, arch):\n    \"\"\"\n    Testing what happens when any of the Bitcode, ARC or Visibility configurations are not defined.\n    \"\"\"\n    profile = textwrap.dedent(\"\"\"\n        include(default)\n        [settings]\n        os={}\n        os.version={}\n        os.sdk={}\n        arch={}\n    \"\"\".format(op_system, os_version, sdk, arch))\n\n    client = TestClient(path_with_spaces=False)\n    client.save({\"host\": profile}, clean_first=True)\n    client.run(\"new -d name=hello -d version=0.1 cmake_lib\")\n    _add_message_status_flags(client)\n    client.run(\"install . --profile:build=default --profile:host=host\")\n    toolchain = client.load(os.path.join(\"build\", \"Release\", \"generators\", \"conan_toolchain.cmake\"))\n    # bitcode\n    assert 'set(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE \"NO\")' not in toolchain\n    assert 'set(CMAKE_XCODE_ATTRIBUTE_BITCODE_GENERATION_MODE \"bitcode\")' not in toolchain\n    assert 'set(BITCODE \"-fembed-bitcode\")' not in toolchain\n    # arc\n    assert 'set(FOBJC_ARC \"-' not in toolchain\n    assert 'set(CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC' not in toolchain\n    # visibility\n    assert 'set(CMAKE_XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN' not in toolchain\n    assert 'set(VISIBILITY \"-' not in toolchain\n\n    client.run(\"create . --profile:build=default --profile:host=host -tf=\\\"\\\"\")\n    # flags are not appended\n    for flag in [\"-fembed-bitcode\", \"-fno-objc-arc\", \"-fobjc-arc\", \"-fvisibility\"]:\n        assert flag not in client.out\n    assert \"[100%] Built target hello\" in client.out\n"
  },
  {
    "path": "test/functional/toolchains/cmake/test_cmake_transitive_rpath.py",
    "content": "import platform\nimport textwrap\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.skipif(platform.system() != \"Linux\",\n                    reason=\"Linux/gcc required for -rpath/-rpath-link testing\")\n@pytest.mark.tool(\"cmake\", \"3.27\")\n@pytest.mark.parametrize(\"use_cmake_config_deps\", [True, False])\ndef test_cmake_sysroot_transitive_rpath(use_cmake_config_deps):\n    c = TestClient()\n\n    extra_profile = textwrap.dedent(\"\"\"\n        [conf]\n        tools.build:sysroot=/path/to/nowhere\n    \"\"\")\n\n    # Avoid using any C or C++ standard functionality, so that we can \"redirect\" the sysroot\n    # to an empty or non-existing directory\n    foo_h = textwrap.dedent(\"\"\"\n        #pragma once\n        int foo(int x, int y);\n    \"\"\")\n    foo_cpp = textwrap.dedent(\"\"\"\n        #include \"foo.h\"\n        int foo(int x, int y) {\n            return x + y;\n        }\n    \"\"\")\n    foo_test = textwrap.dedent(\"\"\"\n        #include \"foo.h\"\n        int main() { return foo(2, 3) == 5 ? 0 : 1; }\n    \"\"\")\n    bar_h = textwrap.dedent(\"\"\"\n        #pragma once\n        int bar(int x, int y);\n    \"\"\")\n    bar_cpp = textwrap.dedent(\"\"\"\n        #include \"bar.h\"\n        #include \"foo.h\"\n        int bar(int x, int y) {\n            return foo(x, y) * 2;\n        }\n    \"\"\")\n    bar_test = textwrap.dedent(\"\"\"\n        #include \"bar.h\"\n        int main() { return bar(2, 3) == 10 ? 0 : 1; }\n    \"\"\")\n\n    c.save({\"extra_profile\": extra_profile})\n    extra_conf = \"-c tools.cmake.cmakedeps:new=will_break_next\" if use_cmake_config_deps else \"\"\n    if not use_cmake_config_deps:\n        # CMakeConfigDeps does not fail, so nothing extra is needed\n        # this is only needed to cover the case of CMakeDeps\n        extra_conf += \" -c tools.build:add_rpath_link=True\"\n    with c.chdir(\"foo\"):\n        c.run(\"new cmake_lib -d name=foo -d version=0.1\")\n        c.save({\"include/foo.h\": foo_h,\n                \"src/foo.cpp\": foo_cpp,\n                \"test_package/src/example.cpp\": foo_test})\n        c.run(f\"create . -o '*:shared=True' -pr=default -pr=../extra_profile {extra_conf}\")\n\n    with c.chdir(\"bar\"):\n        c.run(\"new cmake_lib -d name=bar -d version=0.1 -d requires=foo/0.1\")\n        c.save({\"include/bar.h\": bar_h,\n                \"src/bar.cpp\": bar_cpp,\n                \"test_package/src/example.cpp\": bar_test})\n        # skip test package, which fails with CMakeToolchain+CMakeDeps\n        c.run(f\"create . -o '*:shared=True' -tf= -pr=default -pr=../extra_profile {extra_conf}\")\n    with c.chdir(\"app\"):\n        c.run(\"new cmake_exe -d name=app -d version=0.1 -d requires=bar/0.1\")\n        c.save({\"src/main.cpp\": bar_test,\n                \"src/app.cpp\": \"\"})\n        c.run(f\"create . -o '*:shared=True' -pr=default -pr=../extra_profile {extra_conf}\")\n\n\n@pytest.mark.skipif(platform.system() != \"Linux\",\n                    reason=\"Linux/gcc required for -rpath/-rpath-link testing\")\n@pytest.mark.tool(\"cmake\", \"3.27\")\n@pytest.mark.parametrize(\"use_cmake_config_deps\", [True, False])\ndef test_cmake_transitive_rpath_private_internal(use_cmake_config_deps):\n    c = TestClient()\n\n    foo_h = textwrap.dedent(\"\"\"\n        #pragma once\n        int foo(int x, int y);\n    \"\"\")\n    foo_cpp = textwrap.dedent(\"\"\"\n        #include \"foo.h\"\n        int foo(int x, int y) {\n            return x + y;\n        }\n    \"\"\")\n    bar_h = textwrap.dedent(\"\"\"\n        #pragma once\n        int bar(int x, int y);\n    \"\"\")\n    bar_cpp = textwrap.dedent(\"\"\"\n        #include \"bar.h\"\n        #include \"foo.h\"\n        int bar(int x, int y) {\n            return foo(x, y) * 2;\n        }\n    \"\"\")\n\n    foobar_cmakelists = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(foobar CXX)\n\n        add_library(foo src/foo.cpp)\n        target_include_directories(foo PUBLIC include)\n        set_target_properties(foo PROPERTIES PUBLIC_HEADER \"include/foo.h\")\n\n        add_library(bar src/bar.cpp)\n        target_include_directories(bar PUBLIC include)\n        set_target_properties(bar PROPERTIES PUBLIC_HEADER \"include/bar.h\")\n        target_link_libraries(bar PRIVATE foo)\n\n        install(TARGETS foo bar)\n    \"\"\")\n\n    cmake_deps_gen = \"CMakeConfigDeps\" if use_cmake_config_deps else \"CMakeDeps\"\n    foobar_conanfile = textwrap.dedent(f\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake, cmake_layout\n\n\n        class foobarRecipe(ConanFile):\n            name = \"foobar\"\n            version = \"1.0\"\n            package_type = \"library\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            options = {{\"shared\": [True, False]}}\n            default_options = {{\"shared\": True}}\n\n            exports_sources = \"CMakeLists.txt\", \"src/*\", \"include/*\"\n\n            generators = \"{cmake_deps_gen}\", \"CMakeToolchain\"\n\n            def layout(self):\n                cmake_layout(self)\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n\n            def package(self):\n                cmake = CMake(self)\n                cmake.install()\n\n            def package_info(self):\n                self.cpp_info.components[\"foo\"].libs = [\"foo\"]\n                self.cpp_info.components[\"bar\"].libs = [\"bar\"]\n                self.cpp_info.components[\"bar\"].requires = [\"foo\"]\n    \"\"\")\n\n    consumer_conanfile = textwrap.dedent(f\"\"\"\n            from conan import ConanFile\n            from conan.tools.cmake import CMake, cmake_layout\n\n            class consumerRecipe(ConanFile):\n                name = \"consumer\"\n                version = \"1.0\"\n                package_type = \"library\"\n                settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n                options = {{\"shared\": [True, False]}}\n                default_options = {{\"shared\": True}}\n                generators = \"{cmake_deps_gen}\", \"CMakeToolchain\"\n                exports_sources = \"CMakeLists.txt\", \"src/*\", \"include/*\"\n\n                def layout(self):\n                    cmake_layout(self)\n\n                def requirements(self):\n                    self.requires(\"foobar/1.0\")\n\n                def build(self):\n                    cmake = CMake(self)\n                    cmake.configure()\n                    cmake.build()\n\n                def package(self):\n                    cmake = CMake(self)\n                    cmake.install()\n\n                def package_info(self):\n                    self.cpp_info.libs = [\"consumer\"]\n    \"\"\")\n\n    consumer_cmakelists = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(consumer CXX)\n\n        find_package(foobar CONFIG REQUIRED)\n\n        add_library(consumer src/consumer.cpp)\n        target_include_directories(consumer PUBLIC include)\n        target_link_libraries(consumer PRIVATE ${foobar_LIBRARIES}) # foobar_LIBRARIES is foobar::foobar\n        set_target_properties(consumer PROPERTIES PUBLIC_HEADER \"include/consumer.h\")\n        install(TARGETS consumer)\n\n        add_executable(my_app src/my_app.cpp)\n        target_link_libraries(my_app PRIVATE consumer)\n    \"\"\")\n\n    consumer_cpp = textwrap.dedent(\"\"\"\n    #include \"consumer.h\"\n    #include \"bar.h\"\n    int consumer(int x, int y) {return bar(x, y) * 2;}\n    \"\"\")\n\n    consumer_h = textwrap.dedent(\"\"\"\n    #pragma once\n    int consumer(int x, int y);\n    \"\"\")\n\n    my_app_cpp = textwrap.dedent(\"\"\"\n    #include \"consumer.h\"\n    int main() { return consumer(2, 3) == 20 ? 0 : 1; }\n    \"\"\")\n\n    extra_conf = \"-c tools.build:add_rpath_link=True\"  # removing this should break the test\n\n    with c.chdir(\"foobar\"):\n        c.save({\"include/foo.h\": foo_h,\n                \"include/bar.h\": bar_h,\n                \"src/foo.cpp\": foo_cpp,\n                \"src/bar.cpp\": bar_cpp,\n                \"CMakeLists.txt\": foobar_cmakelists,\n                \"conanfile.py\": foobar_conanfile})\n        c.run(f\"create . {extra_conf} \")\n\n    with c.chdir(\"consumer\"):\n        c.save({\"src/consumer.cpp\": consumer_cpp,\n                \"include/consumer.h\": consumer_h,\n                \"src/my_app.cpp\": my_app_cpp,\n                \"CMakeLists.txt\": consumer_cmakelists,\n                \"conanfile.py\": consumer_conanfile})\n        c.run(f\"create . {extra_conf}\")\n"
  },
  {
    "path": "test/functional/toolchains/cmake/test_cmaketoolchain_paths.py",
    "content": "import platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\nios10_armv8_settings = \"-s os=iOS -s os.sdk=iphoneos -s os.version=10.0 -s arch=armv8\"\n\n\nclass _FindRootPathModes(object):\n    def __init__(self, package=None, library=None, framework=None, include=None, program=None):\n        self.package = package\n        self.library = library\n        self.framework = framework\n        self.include = include\n        self.program = program\n\n\nfind_root_path_modes_default = _FindRootPathModes()\nfind_root_path_modes_cross_build = _FindRootPathModes(\n    package=\"ONLY\",\n    library=\"ONLY\",\n    framework=\"ONLY\",\n    include=\"ONLY\",\n    program=\"NEVER\",\n)\n\n\ndef _cmake_command_toolchain(find_root_path_modes):\n    build_type = \"-DCMAKE_BUILD_TYPE=Release\" if platform.system() != \"Windows\" else \"\"\n    cmake_command = \"cmake .. -DCMAKE_TOOLCHAIN_FILE=../conan_toolchain.cmake {}\".format(build_type)\n    if find_root_path_modes.package:\n        cmake_command += \" -DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE={}\".format(find_root_path_modes.package)\n    if find_root_path_modes.library:\n        cmake_command += \" -DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY={}\".format(find_root_path_modes.library)\n    if find_root_path_modes.framework:\n        cmake_command += \" -DCMAKE_FIND_ROOT_PATH_MODE_FRAMEWORK={}\".format(find_root_path_modes.framework)\n    if find_root_path_modes.include:\n        cmake_command += \" -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE={}\".format(find_root_path_modes.include)\n    if find_root_path_modes.program:\n        cmake_command += \" -DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM={}\".format(find_root_path_modes.program)\n    return cmake_command\n\n\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.parametrize(\"package\", [\"hello\", \"zlib\"])\n@pytest.mark.parametrize(\"find_package\", [\"module\", \"config\"])\n@pytest.mark.parametrize(\n    \"settings\",\n    [\n        \"\",\n        pytest.param(\n            ios10_armv8_settings,\n            marks=pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"OSX only\"),\n        ),\n    ],\n)\n@pytest.mark.parametrize(\n    \"find_root_path_modes\", [find_root_path_modes_default, find_root_path_modes_cross_build],\n)\ndef test_cmaketoolchain_path_find_package(package, find_package, settings, find_root_path_modes):\n    \"\"\"Test with user \"Hello\" and also ZLIB one, to check that package ZLIB\n    has priority over the CMake system one\n    \"\"\"\n    client = TestClient()\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import copy\n        class TestConan(ConanFile):\n            exports_sources = \"*\"\n            def layout(self):\n                pass\n            def package(self):\n                copy(self, \"*\", self.source_folder, self.package_folder)\n            def package_info(self):\n                self.cpp_info.builddirs.append(\"cmake\")\n        \"\"\")\n    find = textwrap.dedent(\"\"\"\n        SET({package}_FOUND 1)\n        MESSAGE(\"HELLO FROM THE {package} FIND PACKAGE!\")\n        \"\"\").format(package=package)\n\n    filename = \"{}Config.cmake\" if find_package == \"config\" else \"Find{}.cmake\"\n    filename = filename.format(package)\n    client.save({\"conanfile.py\": conanfile, \"cmake/{}\".format(filename): find})\n    client.run(\"create . --name={} --version=0.1 {}\".format(package, settings))\n\n    consumer = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(MyHello NONE)\n        find_package({package} REQUIRED)\n        \"\"\").format(package=package)\n\n    client.save({\"CMakeLists.txt\": consumer}, clean_first=True)\n    client.run(\"install --requires={}/0.1 -g CMakeToolchain {}\".format(package, settings))\n\n    with client.chdir(\"build\"):\n        client.run_command(_cmake_command_toolchain(find_root_path_modes))\n    assert \"Conan: Target declared\" not in client.out\n    assert \"HELLO FROM THE {package} FIND PACKAGE!\".format(package=package) in client.out\n\n    # If using the CMakeDeps generator, the in-package .cmake will be ignored\n    # But it is still possible to include(owncmake)\n    client.run(\"install --requires={}/0.1 -g CMakeToolchain -g CMakeDeps {}\".format(package, settings))\n    with client.chdir(\"build2\"):  # A clean folder, not the previous one, CMake cache doesnt affect\n        client.run_command(_cmake_command_toolchain(find_root_path_modes))\n    assert \"Conan: Target declared '{package}::{package}'\".format(package=package) in client.out\n    assert \"HELLO FROM THE {package} FIND PACKAGE!\".format(package=package) not in client.out\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_cmaketoolchain_path_find_package_editable():\n    \"\"\" make sure a package in editable mode that contains a xxxConfig.cmake file can find that\n    file in the user folder\n    \"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import cmake_layout\n        class TestConan(ConanFile):\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            exports_sources = \"*\"\n            def layout(self):\n                cmake_layout(self)\n                self.cpp.source.builddirs = [\"cmake\"]\n            def package(self):\n                self.copy(pattern=\"*\")\n            def package_info(self):\n                self.cpp_info.builddirs.append(\"cmake\")\n        \"\"\")\n    find = textwrap.dedent(\"\"\"\n        SET(hello_FOUND 1)\n        MESSAGE(\"HELLO FROM THE hello FIND PACKAGE!\")\n        \"\"\")\n\n    consumer = textwrap.dedent(\"\"\"\\\n        cmake_minimum_required(VERSION 3.15)\n        project(MyHello NONE)\n        find_package(hello REQUIRED)\n        \"\"\")\n    client.save({\"dep/conanfile.py\": conanfile,\n                 \"dep/cmake/helloConfig.cmake\": find,\n                 \"consumer/conanfile.txt\": \"[requires]\\nhello/0.1\\n[generators]\\nCMakeToolchain\",\n                 \"consumer/CMakeLists.txt\": consumer})\n    with client.chdir(\"dep\"):\n        client.run(\"install .\")\n        client.run(\"editable add . --name=hello --version=0.1\")\n\n    with client.chdir(\"consumer\"):\n        client.run(\"install .\")\n\n        with client.chdir(\"build\"):\n            build_type = \"-DCMAKE_BUILD_TYPE=Release\" if platform.system() != \"Windows\" else \"\"\n            cmake_command = \"cmake .. -DCMAKE_TOOLCHAIN_FILE=../conan_toolchain.cmake {}\".format(\n                build_type)\n            client.run_command(cmake_command)\n        assert \"Conan: Target declared\" not in client.out\n        assert \"HELLO FROM THE hello FIND PACKAGE!\" in client.out\n\n\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.parametrize(\n    \"settings\",\n    [\n        \"\",\n        pytest.param(\n            ios10_armv8_settings,\n            marks=pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"OSX only\"),\n        ),\n    ],\n)\n@pytest.mark.parametrize(\n    \"find_root_path_modes\", [find_root_path_modes_default, find_root_path_modes_cross_build],\n)\n@pytest.mark.parametrize(\n    \"builddir\", [\"os.path.join('hello', 'cmake')\", \"self.package_folder\", '\".\"'],\n)\ndef test_cmaketoolchain_path_find_package_real_config(settings, find_root_path_modes, builddir):\n    client = TestClient()\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n        import os\n        class TestConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            exports_sources = \"*\"\n            generators = \"CMakeToolchain\"\n\n            def layout(self):\n                pass\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n\n            def package(self):\n                cmake = CMake(self)\n                cmake.install()\n\n            def package_info(self):\n                self.cpp_info.builddirs.append({})\n        \"\"\".format(builddir))\n    cmake = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(MyHello NONE)\n\n        add_library(hello INTERFACE)\n        install(TARGETS hello EXPORT helloConfig)\n        export(TARGETS hello\n            NAMESPACE hello::\n            FILE \"${CMAKE_CURRENT_BINARY_DIR}/helloConfig.cmake\"\n        )\n        install(EXPORT helloConfig\n            DESTINATION \"hello/cmake\"\n            NAMESPACE hello::\n        )\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile,\n                 \"CMakeLists.txt\": cmake})\n    client.run(\"create . --name=hello --version=0.1 {}\".format(settings))\n\n    consumer = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(MyHello NONE)\n\n        find_package(hello REQUIRED)\n        \"\"\")\n\n    client.save({\"CMakeLists.txt\": consumer}, clean_first=True)\n    client.run(\"install --requires=hello/0.1 -g CMakeToolchain {}\".format(settings))\n\n    with client.chdir(\"build\"):\n        client.run_command(_cmake_command_toolchain(find_root_path_modes))\n    # If it didn't fail, it found the helloConfig.cmake\n    assert \"Conan: Target declared\" not in client.out\n\n    # If using the CMakeDeps generator, the in-package .cmake will be ignored\n    # But it is still possible to include(owncmake)\n    client.run(\"install --requires=hello/0.1 -g CMakeToolchain -g CMakeDeps {}\".format(settings))\n\n    with client.chdir(\"build2\"):  # A clean folder, not the previous one, CMake cache doesnt affect\n        client.run_command(_cmake_command_toolchain(find_root_path_modes))\n    assert \"Conan: Target declared 'hello::hello'\" in client.out\n\n\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.parametrize(\"require_type\", [\"requires\", \"tool_requires\"])\n@pytest.mark.parametrize(\n    \"settings\",\n    [\n        \"\",\n        pytest.param(\n            ios10_armv8_settings,\n            marks=pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"OSX only\"),\n        ),\n    ],\n)\n@pytest.mark.parametrize(\n    \"find_root_path_modes\", [find_root_path_modes_default, find_root_path_modes_cross_build],\n)\ndef test_cmaketoolchain_path_include_cmake_modules(require_type, settings, find_root_path_modes):\n    \"\"\"Test that cmake module files in builddirs of requires and tool_requires\n    are accessible with include() in consumer CMakeLists\n    \"\"\"\n    client = TestClient()\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import copy\n        class TestConan(ConanFile):\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            exports_sources = \"*\"\n            def layout(self):\n                pass\n            def package(self):\n                copy(self, \"*\", self.source_folder, self.package_folder)\n            def package_info(self):\n                self.cpp_info.builddirs.append(\"cmake\")\n    \"\"\")\n    myowncmake = 'MESSAGE(\"MYOWNCMAKE FROM hello!\")'\n    client.save({\"conanfile.py\": conanfile, \"cmake/myowncmake.cmake\": myowncmake})\n    br_flag = \"--build-require\" if require_type != \"requires\" else \"\"\n    client.run(\"create . --name=hello --version=0.1 {} {}\".format(settings, br_flag))\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class PkgConan(ConanFile):\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            {require_type} = \"hello/0.1\"\n    \"\"\".format(require_type=require_type))\n    consumer = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(MyHello NONE)\n        include(myowncmake)\n    \"\"\")\n    client.save({\"conanfile.py\": conanfile, \"CMakeLists.txt\": consumer}, clean_first=True)\n    client.run(\"install . --name=pkg --version=0.1 -g CMakeToolchain {}\".format(settings))\n    with client.chdir(\"build\"):\n        client.run_command(_cmake_command_toolchain(find_root_path_modes))\n    assert \"MYOWNCMAKE FROM hello!\" in client.out\n\n\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.parametrize(\n    \"settings\",\n    [\n        \"\",\n        pytest.param(\n            ios10_armv8_settings,\n            marks=pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"OSX only\"),\n        ),\n    ],\n)\n@pytest.mark.parametrize(\n    \"find_root_path_modes\", [find_root_path_modes_default, find_root_path_modes_cross_build],\n)\ndef test_cmaketoolchain_path_find_file_find_path(settings, find_root_path_modes):\n    \"\"\"Test that headers in includedirs of requires can be found with\n    find_file() and find_path() in consumer CMakeLists\n    \"\"\"\n    client = TestClient()\n\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import copy\n        class TestConan(ConanFile):\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            exports_sources = \"*\"\n            def layout(self):\n                pass\n            def package(self):\n                copy(self, \"*.h\", self.source_folder, os.path.join(self.package_folder, \"include\"))\n    \"\"\")\n    client.save({\"conanfile.py\": conanfile, \"hello.h\": \"\"})\n    client.run(\"create . --name=hello --version=0.1 {}\".format(settings))\n\n    consumer = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(MyHello NONE)\n        find_file(HELLOFILE hello.h)\n        if(HELLOFILE)\n            message(\"Found file hello.h\")\n        endif()\n        find_path(HELLODIR hello.h)\n        if(HELLODIR)\n            message(\"Found path of hello.h\")\n        endif()\n    \"\"\")\n    client.save({\"CMakeLists.txt\": consumer}, clean_first=True)\n    client.run(\"install --requires hello/0.1 -g CMakeToolchain {}\".format(settings))\n    with client.chdir(\"build\"):\n        client.run_command(_cmake_command_toolchain(find_root_path_modes))\n    assert \"Found file hello.h\" in client.out\n    assert \"Found path of hello.h\" in client.out\n\n\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.parametrize(\n    \"settings\",\n    [\n        \"\",\n        pytest.param(\n            ios10_armv8_settings,\n            marks=pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"OSX only\"),\n        ),\n    ],\n)\n@pytest.mark.parametrize(\n    \"find_root_path_modes\", [find_root_path_modes_default, find_root_path_modes_cross_build],\n)\ndef test_cmaketoolchain_path_find_library(settings, find_root_path_modes):\n    \"\"\"Test that libraries in libdirs of requires can be found with\n    find_library() in consumer CMakeLists\n    \"\"\"\n    client = TestClient()\n\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import copy\n        class TestConan(ConanFile):\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            exports_sources = \"*\"\n            def layout(self):\n                pass\n            def package(self):\n                copy(self, \"*\", self.source_folder, dst=os.path.join(self.package_folder, \"lib\"))\n    \"\"\")\n    client.save({\"conanfile.py\": conanfile, \"libhello.a\": \"\", \"hello.lib\": \"\"})\n    client.run(\"create . --name=hello_host --version=0.1 {}\".format(settings))\n\n    host_folder = client.created_layout().base_folder\n    host_folder_hash = host_folder.replace(\"\\\\\", \"/\").split(\"/\")[-1]\n\n    client.run(\"create . --name=hello_build --version=0.1 --build-require\")\n\n    build_folder = client.created_layout().base_folder\n    build_folder_hash = build_folder.replace(\"\\\\\", \"/\").split(\"/\")[-1]\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class PkgConan(ConanFile):\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            requires = \"hello_host/0.1\"\n            tool_requires = \"hello_build/0.1\"\n    \"\"\")\n    consumer = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(MyHello NONE)\n        find_library(HELLOLIB hello)\n        if(HELLOLIB)\n            message(\"Found hello lib: ${HELLOLIB}\")\n        endif()\n    \"\"\")\n    client.save({\"conanfile.py\": conanfile, \"CMakeLists.txt\": consumer}, clean_first=True)\n    client.run(\"install . --name=pkg --version=0.1 -g CMakeToolchain {}\".format(settings))\n    with client.chdir(\"build\"):\n        client.run_command(_cmake_command_toolchain(find_root_path_modes))\n    assert \"Found hello lib\" in client.out\n    # The hash of the cache folder\n    assert build_folder_hash != host_folder_hash\n    assert host_folder_hash in client.out\n    assert build_folder_hash not in client.out\n\n\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.parametrize(\n    \"settings\",\n    [\n        \"\",\n        pytest.param(\n            ios10_armv8_settings,\n            marks=pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"OSX only\"),\n        ),\n    ],\n)\n@pytest.mark.parametrize(\n    \"find_root_path_modes\", [find_root_path_modes_default, find_root_path_modes_cross_build],\n)\ndef test_cmaketoolchain_path_find_program(settings, find_root_path_modes):\n    \"\"\"Test that executables in bindirs of tool_requires can be found with\n    find_program() in consumer CMakeLists.\n    \"\"\"\n    client = TestClient()\n\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan.tools.files import copy\n        from conan import ConanFile\n        class TestConan(ConanFile):\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            exports_sources = \"*\"\n            def layout(self):\n                pass\n            def package(self):\n                copy(self, \"*\", self.source_folder, os.path.join(self.package_folder, \"bin\"))\n    \"\"\")\n    client.save({\"conanfile.py\": conanfile, \"hello\": \"\", \"hello.exe\": \"\"})\n\n    client.run(\"create . --name=hello_host --version=0.1 {}\".format(settings))\n    host_folder = client.created_layout().base_folder\n    host_folder_hash = host_folder.replace(\"\\\\\", \"/\").split(\"/\")[-1]\n    client.run(\"create . --name=hello_build --version=0.1 --build-require\")\n    build_folder = client.created_layout().base_folder\n    build_folder_hash = build_folder.replace(\"\\\\\", \"/\").split(\"/\")[-1]\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class PkgConan(ConanFile):\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            requires = \"hello_host/0.1\"\n            tool_requires = \"hello_build/0.1\"\n    \"\"\")\n    consumer = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(MyHello NONE)\n        find_program(HELLOPROG hello)\n        if(HELLOPROG)\n            message(\"Found hello prog: ${HELLOPROG}\")\n        endif()\n    \"\"\")\n    client.save({\"conanfile.py\": conanfile, \"CMakeLists.txt\": consumer}, clean_first=True)\n    client.run(\"install . --name=pkg --version=0.1 -g CMakeToolchain {}\".format(settings))\n    with client.chdir(\"build\"):\n        client.run_command(_cmake_command_toolchain(find_root_path_modes))\n    assert \"Found hello prog\" in client.out\n    assert host_folder_hash not in client.out\n    assert build_folder_hash in client.out\n"
  },
  {
    "path": "test/functional/toolchains/cmake/test_cps.py",
    "content": "import os\nimport platform\nimport shutil\nimport textwrap\n\nimport pytest\n\nfrom conan.internal.api.new.cmake_lib import test_conanfile_v2\nfrom conan.test.assets.sources import gen_function_h, gen_function_cpp\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.tool(\"cmake\", \"4.2\")\n@pytest.mark.parametrize(\"shared\", [False, True])\ndef test_cps(shared):\n    c = TestClient()\n    c.run(\"new cmake_lib\")\n    conanfile = textwrap.dedent(\"\"\"\\\n        from conan import ConanFile\n        from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout\n        from conan.cps import CPS\n        import glob\n\n        class mypkgRecipe(ConanFile):\n            name = \"mypkg\"\n            version = \"0.1\"\n            package_type = \"library\"\n\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            options = {\"shared\": [True, False], \"fPIC\": [True, False]}\n            default_options = {\"shared\": False, \"fPIC\": True}\n\n            exports_sources = \"CMakeLists.txt\", \"src/*\", \"include/*\"\n            implements = [\"auto_shared_fpic\"]\n            generators = \"CMakeToolchain\"\n\n            def layout(self):\n                cmake_layout(self)\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n\n            def package(self):\n                cmake = CMake(self)\n                cmake.install()\n\n            def package_info(self):\n                file_loc = glob.glob(\"**/mypkg.cps\", recursive=True)\n                self.cpp_info = CPS.load(file_loc[0]).to_conan()\n        \"\"\")\n\n    cmake = textwrap.dedent(\"\"\"\\\n        cmake_minimum_required(VERSION 4.2)\n        project(mypkg CXX)\n\n        set(CMAKE_EXPERIMENTAL_EXPORT_PACKAGE_INFO \"b80be207-778e-46ba-8080-b23bba22639e\")\n\n        add_library(mypkg src/mypkg.cpp)\n        target_include_directories(mypkg PUBLIC\n                    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>\n                    $<INSTALL_INTERFACE:include>)\n\n        target_compile_definitions(mypkg PUBLIC FOO BAR=42)\n\n        set_target_properties(mypkg PROPERTIES PUBLIC_HEADER \"include/mypkg.h\")\n        install(TARGETS mypkg EXPORT mypkg)\n\n        install(PACKAGE_INFO mypkg EXPORT mypkg)\n        \"\"\")\n\n    # First, try with the standard mypkg-config.cmake consumption\n    c.save({\"conanfile.py\": conanfile,\n            \"CMakeLists.txt\": cmake})\n\n    shared_arg = \"-o &:shared=True\" if shared else \"\"\n    c.run(f\"create {shared_arg}\")\n    assert \"mypkg/0.1: Hello World Release!\" in c.out\n\n    # Lets consume directly with CPS\n    test_cmake = textwrap.dedent(\"\"\"\\\n        cmake_minimum_required(VERSION 4.2)\n        project(PackageTest CXX)\n\n        set(CMAKE_EXPERIMENTAL_FIND_CPS_PACKAGES e82e467b-f997-4464-8ace-b00808fff261)\n\n        find_package(mypkg CONFIG REQUIRED)\n\n        add_executable(example src/example.cpp)\n        target_link_libraries(example mypkg::mypkg)\n        \"\"\")\n    test_conanfile = textwrap.dedent(\"\"\"\\\n        import os\n\n        from conan import ConanFile\n        from conan.tools.cmake import CMake, cmake_layout, CMakeToolchain, CMakeConfigDeps\n        from conan.tools.build import can_run\n\n\n        class TestConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n            def requirements(self):\n                self.requires(self.tested_reference_str)\n\n            def generate(self):\n                self.output.info(f\"Dep defines: {self.dependencies[self.tested_reference_str].cpp_info.defines}\")\n                deps = CMakeConfigDeps(self)\n                deps.set_property(\"mypkg\", \"cmake_find_mode\", \"none\")\n                deps.generate()\n                tc = CMakeToolchain(self)\n                tc.generate()\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n\n            def layout(self):\n                cmake_layout(self)\n\n            def test(self):\n                if can_run(self):\n                    cmd = os.path.join(self.cpp.build.bindir, \"example\")\n                    self.run(cmd, env=\"conanrun\")\n            \"\"\")\n    shutil.rmtree(os.path.join(c.current_folder, \"test_package\", \"build\"))\n    example_cpp = c.load(os.path.join(\"test_package\", \"src\", \"example.cpp\"))\n    example_cpp = example_cpp.replace(\"#include <string>\", '#include <string>\\n#include <iostream>')\n    example_cpp = example_cpp.replace(\"mypkg();\", 'mypkg();\\nstd::cout << \"BAR: \" << BAR << std::endl;')\n    c.save({\"test_package/conanfile.py\": test_conanfile,\n            \"test_package/CMakeLists.txt\": test_cmake,\n            \"test_package/src/example.cpp\": example_cpp})\n    c.run(f\"create {shared_arg} --build=never\")\n    assert \"mypkg/0.1: Hello World Release!\" in c.out\n    assert \"Dep defines: ['BAR=42', 'FOO']\" in c.out\n    assert \"BAR: 42\" in c.out\n\n\n@pytest.mark.tool(\"cmake\", \"4.2\")\n@pytest.mark.parametrize(\"shared\", [False, True])\ndef test_cps_components(shared):\n    c = TestClient()\n    c.run(\"new cmake_lib\")\n    conanfile = textwrap.dedent(\"\"\"\\\n        from conan import ConanFile\n        from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout\n        from conan.cps import CPS\n        import glob\n\n        class mypkgRecipe(ConanFile):\n            name = \"mypkg\"\n            version = \"0.1\"\n            package_type = \"library\"\n\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            options = {\"shared\": [True, False], \"fPIC\": [True, False]}\n            default_options = {\"shared\": False, \"fPIC\": True}\n\n            exports_sources = \"CMakeLists.txt\", \"src/*\", \"include/*\"\n            implements = [\"auto_shared_fpic\"]\n            generators = \"CMakeToolchain\"\n\n            def layout(self):\n                cmake_layout(self)\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n\n            def package(self):\n                cmake = CMake(self)\n                cmake.install()\n\n            def package_info(self):\n                file_loc = glob.glob(\"**/mypkg.cps\", recursive=True)\n                cps_data = CPS.load(file_loc[0])\n                # Convert CPS to cpp_info with components\n                self.cpp_info = cps_data.to_conan()\n        \"\"\")\n\n    cmake = textwrap.dedent(\"\"\"\\\n        cmake_minimum_required(VERSION 4.2)\n        project(mypkg CXX)\n\n        set(CMAKE_EXPERIMENTAL_EXPORT_PACKAGE_INFO \"b80be207-778e-46ba-8080-b23bba22639e\")\n\n        # First library: core\n        add_library(mypkg_core src/mypkg_core.cpp)\n        target_include_directories(mypkg_core PUBLIC\n                    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>\n                    $<INSTALL_INTERFACE:include>)\n        set_target_properties(mypkg_core PROPERTIES PUBLIC_HEADER \"include/mypkg_core.h\")\n\n        # Second library: utils (independent from core)\n        add_library(mypkg_utils src/mypkg_utils.cpp)\n        target_include_directories(mypkg_utils PUBLIC\n                    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>\n                    $<INSTALL_INTERFACE:include>)\n        set_target_properties(mypkg_utils PROPERTIES PUBLIC_HEADER \"include/mypkg_utils.h\")\n\n        install(TARGETS mypkg_core mypkg_utils EXPORT mypkg)\n\n        install(PACKAGE_INFO mypkg EXPORT mypkg)\n        \"\"\")\n\n    # Create source files for both libraries\n    core_cpp = gen_function_cpp(name=\"mypkg_core\")\n    core_h = gen_function_h(name=\"mypkg_core\")\n    utils_cpp = gen_function_cpp(name=\"mypkg_utils\")\n    utils_h = gen_function_h(name=\"mypkg_utils\")\n\n    # Create test_package files for the two components\n    test_package_cmake = textwrap.dedent(\"\"\"\\\n        cmake_minimum_required(VERSION 3.15)\n        project(PackageTest CXX)\n\n        set(CMAKE_EXPERIMENTAL_FIND_CPS_PACKAGES e82e467b-f997-4464-8ace-b00808fff261)\n\n        find_package(mypkg CONFIG REQUIRED)\n\n        add_executable(example src/example.cpp)\n        target_link_libraries(example mypkg::mypkg_core mypkg::mypkg_utils)\n        \"\"\")\n\n    test_package_example = textwrap.dedent(\"\"\"\\\n        #include \"mypkg_core.h\"\n        #include \"mypkg_utils.h\"\n\n        int main() {\n            mypkg_core();\n            mypkg_utils();\n            return 0;\n        }\n        \"\"\")\n\n    # First, try with the standard mypkg-config.cmake consumption\n    c.save({\"conanfile.py\": conanfile,\n            \"CMakeLists.txt\": cmake,\n            \"src/mypkg_core.cpp\": core_cpp,\n            \"include/mypkg_core.h\": core_h,\n            \"src/mypkg_utils.cpp\": utils_cpp,\n            \"include/mypkg_utils.h\": utils_h,\n            \"test_package/CMakeLists.txt\": test_package_cmake,\n            \"test_package/src/example.cpp\": test_package_example})\n\n    shared_arg = \"-o &:shared=True\" if shared else \"\"\n    c.run(f\"create {shared_arg}\")\n    assert \"mypkg_core: Release!\" in c.out\n    assert \"mypkg_utils: Release!\" in c.out\n\n    test_conanfile = textwrap.dedent(\"\"\"\\\n        import os\n\n        from conan import ConanFile\n        from conan.tools.cmake import CMake, cmake_layout, CMakeToolchain, CMakeConfigDeps\n        from conan.tools.build import can_run\n\n\n        class TestConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n            def requirements(self):\n                self.requires(self.tested_reference_str)\n\n            def generate(self):\n                deps = CMakeConfigDeps(self)\n                deps.set_property(\"mypkg\", \"cmake_find_mode\", \"none\")\n                deps.generate()\n                tc = CMakeToolchain(self)\n                tc.generate()\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n\n            def layout(self):\n                cmake_layout(self)\n\n            def test(self):\n                if can_run(self):\n                    cmd = os.path.join(self.cpp.build.bindir, \"example\")\n                    self.run(cmd, env=\"conanrun\")\n            \"\"\")\n    shutil.rmtree(os.path.join(c.current_folder, \"test_package\", \"build\"))\n    c.save({\"test_package/conanfile.py\": test_conanfile})\n    c.run(f\"create {shared_arg} --build=never\")\n    assert \"mypkg_core: Release!\" in c.out\n    assert \"mypkg_utils: Release!\" in c.out\n\n\n@pytest.mark.tool(\"cmake\", \"4.2\")\n@pytest.mark.parametrize(\"kind\", [\"static_public\", \"static_private\", \"shared_private\"])\ndef test_cps_components_requires(kind):\n    if kind == \"shared_private\" and platform.system() == \"Linux\":\n        pytest.skip(\"CPS still doesn't support this case\")\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\\\n        from conan import ConanFile\n        from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout\n        from conan.cps import CPS\n        import glob\n\n        class Recipe(ConanFile):\n            name = \"{name}\"\n            version = \"0.1\"\n            package_type = \"library\"\n\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            options = {{\"shared\": [True, False], \"fPIC\": [True, False]}}\n            default_options = {{\"shared\": False, \"fPIC\": True}}\n\n            exports_sources = \"CMakeLists.txt\", \"src/*\", \"include/*\"\n            implements = [\"auto_shared_fpic\"]\n            generators = \"CMakeToolchain\", \"CMakeConfigDeps\"\n\n            def requirements(self):\n                {requires}\n                pass\n\n            def layout(self):\n                cmake_layout(self)\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n\n            def package(self):\n                cmake = CMake(self)\n                cmake.install()\n\n            def package_info(self):\n                file_loc = glob.glob(\"**/{name}.cps\", recursive=True)\n                cps_data = CPS.load(file_loc[0])\n                # Convert CPS to cpp_info with components\n                self.cpp_info = cps_data.to_conan()\n        \"\"\")\n\n    lib_type = \"PUBLIC\" if \"public\" in kind else \"PRIVATE\"\n    cmake = textwrap.dedent(\"\"\"\\\n        cmake_minimum_required(VERSION 4.2)\n        project({name} CXX)\n\n        set(CMAKE_EXPERIMENTAL_EXPORT_PACKAGE_INFO \"b80be207-778e-46ba-8080-b23bba22639e\")\n\n        {find}\n        # First library: core\n        add_library({name}_core src/{name}_core.cpp)\n        target_include_directories({name}_core PUBLIC\n                    $<BUILD_INTERFACE:${{CMAKE_CURRENT_SOURCE_DIR}}/include>\n                    $<INSTALL_INTERFACE:include/core>)\n        set_target_properties({name}_core PROPERTIES PUBLIC_HEADER \"include/{name}_core.h\")\n        {deps}\n\n        # Second library: utils (independent from core)\n        add_library({name}_utils src/{name}_utils.cpp)\n\n        target_include_directories({name}_utils PUBLIC\n                    $<BUILD_INTERFACE:${{CMAKE_CURRENT_SOURCE_DIR}}/include>\n                    $<INSTALL_INTERFACE:include/utils>)\n        set_target_properties({name}_utils PROPERTIES PUBLIC_HEADER \"include/{name}_utils.h\")\n\n        target_link_libraries({name}_utils {lib_type} {name}_core)\n\n        install(TARGETS {name}_core EXPORT {name}\n                PUBLIC_HEADER DESTINATION ${{CMAKE_INSTALL_INCLUDEDIR}}/core)\n        install(TARGETS {name}_utils EXPORT {name}\n                PUBLIC_HEADER DESTINATION ${{CMAKE_INSTALL_INCLUDEDIR}}/utils)\n\n        install(PACKAGE_INFO {name} EXPORT {name})\n        \"\"\")\n\n    # Create source files for both libraries\n    core_cpp = gen_function_cpp(name=\"liba_core\")\n    core_h = gen_function_h(name=\"liba_core\")\n    utils_cpp = gen_function_cpp(name=\"liba_utils\", includes=[\"liba_core\"],\n                                 calls=[\"liba_core\"])\n    if \"public\" in kind:\n        utils_h = gen_function_h(name=\"liba_utils\", includes=[\"liba_core\"])\n    else:\n        utils_h = gen_function_h(name=\"liba_utils\")\n\n    # Create test_package files for the two components\n    test_package_cmake = textwrap.dedent(\"\"\"\\\n        cmake_minimum_required(VERSION 3.15)\n        project(PackageTest CXX)\n\n        set(CMAKE_EXPERIMENTAL_FIND_CPS_PACKAGES e82e467b-f997-4464-8ace-b00808fff261)\n\n        find_package({name} CONFIG REQUIRED)\n\n        add_executable(example src/example.cpp)\n        target_link_libraries(example {name}::{name}_utils)\n        \"\"\")\n\n    test_package_example = textwrap.dedent(\"\"\"\\\n        #include \"{name}_utils.h\"\n\n        int main() {{\n            {name}_utils();\n            return 0;\n        }}\n        \"\"\")\n    test_conanfile = test_conanfile_v2.replace(\"{{package_name}}\", \"\")\n    test_conanfile = test_conanfile.replace(\"CMakeDeps\", \"CMakeConfigDeps\")\n    # First, try with the standard liba-config.cmake consumption\n    c.save({\"conanfile.py\": conanfile.format(name=\"liba\", requires=\"\"),\n            \"CMakeLists.txt\": cmake.format(name=\"liba\", lib_type=lib_type, deps=\"\", find=\"\"),\n            \"src/liba_core.cpp\": core_cpp,\n            \"include/liba_core.h\": core_h,\n            \"src/liba_utils.cpp\": utils_cpp,\n            \"include/liba_utils.h\": utils_h,\n            \"test_package/conanfile.py\": test_conanfile,\n            \"test_package/CMakeLists.txt\": test_package_cmake.format(name=\"liba\"),\n            \"test_package/src/example.cpp\": test_package_example.format(name=\"liba\")})\n\n    shared_arg = \"-o *:shared=True\" if \"shared\" in kind else \"\"\n    c.run(f\"create {shared_arg}\")\n    assert \"liba_core: Release!\" in c.out\n    assert \"liba_utils: Release!\" in c.out\n\n    test_conanfile_cps = textwrap.dedent(\"\"\"\\\n        import os\n\n        from conan import ConanFile\n        from conan.tools.cmake import CMake, cmake_layout, CMakeToolchain, CMakeConfigDeps\n        from conan.tools.build import can_run\n\n\n        class TestConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n            def requirements(self):\n                self.requires(self.tested_reference_str)\n\n            def generate(self):\n                deps = CMakeConfigDeps(self)\n                deps.set_property(\"liba\", \"cmake_find_mode\", \"none\")\n                deps.set_property(\"libb\", \"cmake_find_mode\", \"none\")\n                deps.generate()\n                tc = CMakeToolchain(self)\n                tc.generate()\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n\n            def layout(self):\n                cmake_layout(self)\n\n            def test(self):\n                if can_run(self):\n                    cmd = os.path.join(self.cpp.build.bindir, \"example\")\n                    self.run(cmd, env=\"conanrun\")\n            \"\"\")\n    shutil.rmtree(os.path.join(c.current_folder, \"test_package\", \"build\"))\n    c.save({\"test_package/conanfile.py\": test_conanfile_cps})\n    c.run(f\"create {shared_arg} --build=never\")\n    assert \"liba_core: Release!\" in c.out\n    assert \"liba_utils: Release!\" in c.out\n\n    # Now a second level\n    core_cpp = gen_function_cpp(name=\"libb_core\", includes=[\"liba_utils\"], calls=[\"liba_utils\"])\n    if \"public\" in kind:\n        core_h = gen_function_h(name=\"libb_core\", includes=[\"liba_utils\"])\n    else:\n        core_h = gen_function_h(name=\"libb_core\")\n    utils_cpp = gen_function_cpp(name=\"libb_utils\", includes=[\"libb_core\"],\n                                 calls=[\"libb_core\"])\n    if \"public\" in kind:\n        utils_h = gen_function_h(name=\"libb_utils\", includes=[\"libb_core\"])\n    else:\n        utils_h = gen_function_h(name=\"libb_utils\")\n\n    deps = f'target_link_libraries(libb_core {lib_type} liba::liba_utils)'\n    find = f'find_package(liba CONFIG REQUIRED)'\n    transitive_headers = \"public\" in kind\n    requires = f'self.requires(\"liba/0.1\", transitive_headers={transitive_headers})'\n    c.save({\"conanfile.py\": conanfile.format(name=\"libb\", requires=requires),\n            \"CMakeLists.txt\": cmake.format(name=\"libb\", lib_type=lib_type, deps=deps, find=find),\n            \"src/libb_core.cpp\": core_cpp,\n            \"include/libb_core.h\": core_h,\n            \"src/libb_utils.cpp\": utils_cpp,\n            \"include/libb_utils.h\": utils_h,\n            \"test_package/conanfile.py\": test_conanfile,\n            \"test_package/CMakeLists.txt\": test_package_cmake.format(name=\"libb\"),\n            \"test_package/src/example.cpp\": test_package_example.format(name=\"libb\")},\n           clean_first=True)\n\n    c.run(f\"create {shared_arg}\")\n    assert \"libb_core: Release!\" in c.out\n    assert \"libb_utils: Release!\" in c.out\n    assert \"liba_core: Release!\" in c.out\n    assert \"liba_utils: Release!\" in c.out\n\n    c.save({\"test_package/conanfile.py\": test_conanfile_cps})\n    c.run(f\"create {shared_arg} --build=never\")\n    assert \"libb_core: Release!\" in c.out\n    assert \"libb_utils: Release!\" in c.out\n    assert \"liba_core: Release!\" in c.out\n    assert \"liba_utils: Release!\" in c.out\n\n\n@pytest.mark.skip(reason=\"Just to report to CMake upstream, and CPS feature request\")\n@pytest.mark.tool(\"cmake\", \"4.2\")\ndef test_pure_cmake_shared():\n    c = TestClient()\n\n    cmake = textwrap.dedent(\"\"\"\\\n        cmake_minimum_required(VERSION 4.2)\n        project(myproj CXX)\n\n        set(CMAKE_EXPERIMENTAL_EXPORT_PACKAGE_INFO \"b80be207-778e-46ba-8080-b23bba22639e\")\n\n        # First library: core\n        add_library(mypkg_core src/mypkg_core.cpp)\n        target_include_directories(mypkg_core PUBLIC\n                    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>\n                    $<INSTALL_INTERFACE:include/core>)\n        set_target_properties(mypkg_core PROPERTIES PUBLIC_HEADER \"include/mypkg_core.h\")\n\n        # Second library: utils\n        add_library(mypkg_utils src/mypkg_utils.cpp)\n\n        target_include_directories(mypkg_utils PUBLIC\n                    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>\n                    $<INSTALL_INTERFACE:include/utils>)\n        set_target_properties(mypkg_utils PROPERTIES PUBLIC_HEADER \"include/mypkg_utils.h\")\n\n        target_link_libraries(mypkg_utils PRIVATE mypkg_core)\n\n        install(TARGETS mypkg_core EXPORT mypkg\n                PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/core)\n        install(TARGETS mypkg_utils EXPORT mypkg\n                PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/utils)\n\n        install(PACKAGE_INFO mypkg EXPORT mypkg)\n        \"\"\")\n\n    # Create source files for both libraries\n    core_cpp = gen_function_cpp(name=\"mypkg_core\")\n    core_h = gen_function_h(name=\"mypkg_core\")\n    utils_cpp = gen_function_cpp(name=\"mypkg_utils\", includes=[\"mypkg_core\"],\n                                 calls=[\"mypkg_core\"])\n    utils_h = gen_function_h(name=\"mypkg_utils\")\n\n    # First, try with the standard mypkg-config.cmake consumption\n    c.save({\"CMakeLists.txt\": cmake,\n            \"src/mypkg_core.cpp\": core_cpp,\n            \"include/mypkg_core.h\": core_h,\n            \"src/mypkg_utils.cpp\": utils_cpp,\n            \"include/mypkg_utils.h\": utils_h})\n\n    c.run_command(f\"cmake . -DBUILD_SHARED_LIBS=ON\")\n    print(c.out)\n    c.run_command(\"cmake --build . --config Release\")\n    print(c.out)\n    c.run_command(\"cmake --install . --config Release --prefix=mypkginstall\")\n    print(c.out)\n    cps = c.load(\"mypkginstall/cps/mypkg.cps\")\n    print(cps)\n    cps_release = c.load(\"mypkginstall/cps/mypkg@release.cps\")\n    print(cps_release)\n\n\n@pytest.mark.tool(\"cmake\", \"4.2\")\ndef test_cps_name_mapping():\n    c = TestClient()\n    c.run(\"new cmake_lib\")\n    conanfile = textwrap.dedent(\"\"\"\\\n        from conan import ConanFile\n        from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout\n        from conan.cps import CPS\n        import glob\n\n        class mypkgRecipe(ConanFile):\n            name = \"mypkg\"\n            version = \"0.1\"\n            package_type = \"library\"\n\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            options = {\"shared\": [True, False], \"fPIC\": [True, False]}\n            default_options = {\"shared\": False, \"fPIC\": True}\n\n            exports_sources = \"CMakeLists.txt\", \"src/*\", \"include/*\"\n            implements = [\"auto_shared_fpic\"]\n            generators = \"CMakeToolchain\"\n\n            def layout(self):\n                cmake_layout(self)\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n\n            def package(self):\n                cmake = CMake(self)\n                cmake.install()\n\n            def package_info(self):\n                file_loc = glob.glob(\"**/potato.cps\", recursive=True)\n                self.cpp_info = CPS.load(file_loc[0]).to_conan()\n        \"\"\")\n\n    cmake = textwrap.dedent(\"\"\"\\\n        cmake_minimum_required(VERSION 4.2)\n        project(mypkg CXX)\n\n        set(CMAKE_EXPERIMENTAL_EXPORT_PACKAGE_INFO \"b80be207-778e-46ba-8080-b23bba22639e\")\n\n        add_library(mypkg src/mypkg.cpp)\n        target_include_directories(mypkg PUBLIC\n                    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>\n                    $<INSTALL_INTERFACE:include>)\n\n        target_compile_definitions(mypkg PUBLIC FOO BAR=42)\n\n        set_target_properties(mypkg PROPERTIES PUBLIC_HEADER \"include/mypkg.h\")\n        install(TARGETS mypkg EXPORT mypkg)\n\n        install(PACKAGE_INFO potato EXPORT mypkg)\n        \"\"\")\n\n    # First, try with the standard mypkg-config.cmake consumption\n    test_package_cmakelists = c.load(\"test_package/CMakeLists.txt\")\n    # The target and the file name use the CPS name, not the package name\n    test_package_cmakelists = test_package_cmakelists.replace(\"find_package(mypkg\", \"find_package(potato\")\n    test_package_cmakelists = test_package_cmakelists.replace(\"mypkg::mypkg\", \"potato::mypkg\")\n    test_package_cmakelists = test_package_cmakelists.replace(\"CMakeDeps\", \"CMakeConfigDeps\")\n    c.save({\"conanfile.py\": conanfile,\n            \"CMakeLists.txt\": cmake,\n            \"test_package/CMakeLists.txt\": test_package_cmakelists})\n\n    c.run(f\"create\")\n    assert \"mypkg/0.1: Hello World Release!\" in c.out\n\n    # Lets consume directly with CPS\n    test_cmake = textwrap.dedent(\"\"\"\\\n        cmake_minimum_required(VERSION 4.2)\n        project(PackageTest CXX)\n\n        set(CMAKE_EXPERIMENTAL_FIND_CPS_PACKAGES e82e467b-f997-4464-8ace-b00808fff261)\n\n        find_package(potato CONFIG REQUIRED)\n\n        add_executable(example src/example.cpp)\n        target_link_libraries(example potato::mypkg)\n        \"\"\")\n    test_conanfile = textwrap.dedent(\"\"\"\\\n        import os\n\n        from conan import ConanFile\n        from conan.tools.cmake import CMake, cmake_layout, CMakeToolchain, CMakeConfigDeps\n        from conan.tools.build import can_run\n\n\n        class TestConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n            def requirements(self):\n                self.requires(self.tested_reference_str)\n\n            def generate(self):\n                self.output.info(f\"Dep defines: {self.dependencies[self.tested_reference_str].cpp_info.defines}\")\n                deps = CMakeConfigDeps(self)\n                deps.set_property(\"mypkg\", \"cmake_find_mode\", \"none\")\n                deps.generate()\n                tc = CMakeToolchain(self)\n                tc.generate()\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n\n            def layout(self):\n                cmake_layout(self)\n\n            def test(self):\n                if can_run(self):\n                    cmd = os.path.join(self.cpp.build.bindir, \"example\")\n                    self.run(cmd, env=\"conanrun\")\n            \"\"\")\n    shutil.rmtree(os.path.join(c.current_folder, \"test_package\", \"build\"))\n    c.save({\"test_package/conanfile.py\": test_conanfile,\n            \"test_package/CMakeLists.txt\": test_cmake})\n    c.run(f\"create --build=never\")\n    assert \"mypkg/0.1: Hello World Release!\" in c.out\n"
  },
  {
    "path": "test/functional/toolchains/cmake/test_ninja.py",
    "content": "import os\nimport textwrap\nimport platform\nimport pytest\n\nfrom conan.tools.cmake import CMakeToolchain\nfrom conan.tools.cmake.presets import load_cmake_presets\nfrom conan.test.assets.cmake import gen_cmakelists\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.assets.sources import gen_function_h, gen_function_cpp\nfrom test.functional.utils import check_vs_runtime, check_exe_run\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.fixture\ndef client():\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.cmake import CMake, CMakeToolchain\n\n        class Library(ConanFile):\n            name = \"hello\"\n            version = \"1.0\"\n            settings = 'os', 'arch', 'compiler', 'build_type'\n            exports_sources = 'hello.h', '*.cpp', 'CMakeLists.txt'\n            options = {'shared': [True, False]}\n            default_options = {'shared': False}\n\n            def generate(self):\n                tc = CMakeToolchain(self, generator=\"Ninja\")\n                tc.generate()\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n                self.run(os.sep.join([\".\", \"myapp\"]))\n\n            def package(self):\n                cmake = CMake(self)\n                cmake.install()\n        \"\"\")\n\n    test_client = TestClient(path_with_spaces=False)\n    test_client.save({'conanfile.py': conanfile,\n                      \"CMakeLists.txt\": gen_cmakelists(libsources=[\"hello.cpp\"],\n                                                       appsources=[\"main.cpp\"],\n                                                       install=True),\n                      \"hello.h\": gen_function_h(name=\"hello\"),\n                      \"hello.cpp\": gen_function_cpp(name=\"hello\", includes=[\"hello\"]),\n                      \"main.cpp\": gen_function_cpp(name=\"main\", includes=[\"hello\"],\n                                                   calls=[\"hello\"])})\n    return test_client\n\n\n@pytest.mark.skipif(platform.system() != \"Linux\", reason=\"Only Linux\")\n@pytest.mark.parametrize(\"build_type,shared\", [(\"Release\", False), (\"Debug\", True)])\n@pytest.mark.tool(\"ninja\")\ndef test_locally_build_linux(build_type, shared, client):\n    settings = f\"-s os=Linux -s arch=x86_64 -s build_type={build_type} -o hello/*:shared={shared}\"\n    client.run(\"install . {}\".format(settings))\n    client.run_command('cmake . -G \"Ninja\" -DCMAKE_TOOLCHAIN_FILE={} -DCMAKE_BUILD_TYPE={}'\n                       .format(CMakeToolchain.filename, build_type))\n\n    client.run_command('ninja')\n    if shared:\n        assert \"Linking CXX shared library libmylibrary.so\" in client.out\n    else:\n        assert \"Linking CXX static library libmylibrary.a\" in client.out\n\n    client.run_command(\"./myapp\")\n    check_exe_run(client.out, [\"main\", \"hello\"], \"gcc\", None, build_type, \"x86_64\", cppstd=None)\n\n    # create should also work\n    client.run(\"create . --name=hello --version=1.0 {}\".format(settings))\n    assert 'cmake -G \"Ninja\"' in client.out\n    assert \"main: {}!\".format(build_type) in client.out\n    client.run(f\"install --requires=hello/1.0@ --deployer=full_deploy -of=mydeploy {settings}\")\n    deploy_path = os.path.join(client.current_folder, \"mydeploy\", \"full_deploy\", \"host\", \"hello\", \"1.0\",\n                               build_type, \"x86_64\")\n    client.run_command(f\"LD_LIBRARY_PATH='{deploy_path}/lib' {deploy_path}/bin/myapp\")\n    check_exe_run(client.out, [\"main\", \"hello\"], \"gcc\", None, build_type, \"x86_64\", cppstd=None)\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Only windows\")\n@pytest.mark.parametrize(\"build_type,shared\", [(\"Release\", False), (\"Debug\", True)])\n@pytest.mark.tool(\"visual_studio\", \"15\")\n@pytest.mark.tool(\"ninja\")\ndef test_locally_build_msvc(build_type, shared, client):\n    msvc_version = \"15\"\n    settings = \"-s build_type={} -o hello/*:shared={}\".format(build_type, shared)\n    client.run(\"install . {}\".format(settings))\n\n    client.run_command('conanvcvars.bat && cmake . -G \"Ninja\" '\n                       '-DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake '\n                       '-DCMAKE_BUILD_TYPE={}'.format(build_type))\n\n    client.run_command(\"conanvcvars.bat && ninja\")\n\n    libname = \"mylibrary.dll\" if shared else \"mylibrary.lib\"\n    assert libname in client.out\n\n    client.run_command(\"myapp.exe\")\n    # TODO: Need full msvc version check\n    check_exe_run(client.out, [\"main\", \"hello\"], \"msvc\", \"19\", build_type, \"x86_64\", cppstd=\"14\")\n    check_vs_runtime(\"myapp.exe\", client, msvc_version, build_type, architecture=\"amd64\")\n    check_vs_runtime(libname, client, msvc_version, build_type, architecture=\"amd64\")\n\n    # create should also work\n    client.run(\"create . --name=hello --version=1.0 {}\".format(settings))\n    assert 'cmake -G \"Ninja\"' in client.out\n    assert \"main: {}!\".format(build_type) in client.out\n    client.run(f\"install --requires=hello/1.0@ --deployer=full_deploy -of=mydeploy {settings}\")\n    client.run_command(fr\"mydeploy\\full_deploy\\host\\hello\\1.0\\{build_type}\\x86_64\\bin\\myapp.exe\")\n    check_exe_run(client.out, [\"main\", \"hello\"], \"msvc\", \"19\", build_type, \"x86_64\", cppstd=\"14\")\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Only windows\")\n@pytest.mark.tool(\"ninja\")\ndef test_locally_build_msvc_toolset(client):\n    msvc_version = \"15\"\n    profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=Windows\n        compiler=msvc\n        compiler.version=191\n        compiler.runtime=dynamic\n        compiler.cppstd=14\n        build_type=Release\n        arch=x86_64\n        [conf]\n        tools.cmake.cmaketoolchain:generator=Ninja\n        tools.microsoft.msbuild:vs_version = 15\n        \"\"\")\n    client.save({\"profile\": profile})\n    client.run(\"install . -pr=profile\")\n\n    client.run_command('conanvcvars.bat && cmake . -G \"Ninja\" '\n                       '-DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake '\n                       '-DCMAKE_BUILD_TYPE=Release')\n\n    client.run_command(\"conanvcvars.bat && ninja\")\n\n    client.run_command(\"myapp.exe\")\n\n    # Checking that compiler is indeed version 19.0, not 19.1-default of VS15\n    check_exe_run(client.out, [\"main\", \"hello\"], \"msvc\", \"191\", \"Release\", \"x86_64\", cppstd=\"14\")\n    check_vs_runtime(\"myapp.exe\", client, msvc_version, \"Release\", architecture=\"amd64\")\n    check_vs_runtime(\"mylibrary.lib\", client, msvc_version, \"Release\", architecture=\"amd64\")\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Only windows\")\n@pytest.mark.parametrize(\"build_type,shared\", [(\"Release\", False), (\"Debug\", True)])\n@pytest.mark.tool(\"mingw64\")\n@pytest.mark.tool(\"ninja\")\ndef test_locally_build_gcc(build_type, shared, client):\n    # FIXME: Note the gcc version is still incorrect\n    gcc = (\"-s os=Windows -s compiler=gcc -s compiler.version=4.9 -s compiler.libcxx=libstdc++ \"\n           \"-s arch=x86_64 -s build_type={}\".format(build_type))\n\n    client.run(\"install . {} -o hello/*:shared={}\".format(gcc, shared))\n\n    client.run_command('cmake . -G \"Ninja\" '\n                       '-DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake '\n                       '-DCMAKE_BUILD_TYPE={}'.format(build_type))\n\n    libname = \"mylibrary.dll\" if shared else \"libmylibrary.a\"\n    client.run_command(\"ninja\")\n    assert libname in client.out\n\n    client.run_command(\"myapp.exe\")\n    # TODO: Need full gcc version check\n    check_exe_run(client.out, [\"main\", \"hello\"], \"gcc\", None, build_type, \"x86_64\", cppstd=None,\n                  subsystem=\"mingw64\")\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Requires apple-clang\")\n@pytest.mark.parametrize(\"build_type,shared\", [(\"Release\", False), (\"Debug\", True)])\n@pytest.mark.tool(\"ninja\")\ndef test_locally_build_macos(build_type, shared, client):\n    client.run('install . -s os=Macos -s arch=x86_64 -s build_type={} -o hello/*:shared={}'\n               .format(build_type, shared))\n    client.run_command('cmake . -G\"Ninja\" -DCMAKE_TOOLCHAIN_FILE={} -DCMAKE_BUILD_TYPE={}'\n                       .format(CMakeToolchain.filename, build_type))\n\n    client.run_command('ninja')\n    if shared:\n        assert \"Linking CXX shared library libmylibrary.dylib\" in client.out\n    else:\n        assert \"Linking CXX static library libmylibrary.a\" in client.out\n\n    command_str = 'DYLD_LIBRARY_PATH=\"%s\" ./myapp' % client.current_folder\n    client.run_command(command_str)\n    check_exe_run(client.out, [\"main\", \"hello\"], \"apple-clang\", None, build_type, \"x86_64\",\n                  cppstd=None)\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Only windows\")\n@pytest.mark.tool(\"visual_studio\")\ndef test_ninja_conf():\n    conanfile = GenConanfile().with_generator(\"CMakeToolchain\").with_settings(\"os\", \"compiler\",\n                                                                              \"build_type\", \"arch\")\n    profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=Windows\n        compiler=msvc\n        compiler.version=191\n        compiler.runtime=dynamic\n        compiler.cppstd=14\n        build_type=Release\n        arch=x86_64\n        [conf]\n        tools.cmake.cmaketoolchain:generator=Ninja\n        \"\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile,\n                 \"profile\": profile})\n    client.run(\"install . -pr=profile\")\n    presets = load_cmake_presets(client.current_folder)\n    generator = presets[\"configurePresets\"][0][\"generator\"]\n\n    assert generator == \"Ninja\"\n    vcvars = client.load(\"conanvcvars.bat\")\n    assert \"2017\" in vcvars\n\n    # toolchain cannot define the CMAKE_GENERATOR_TOOLSET for Ninja\n    cmake = client.load(\"conan_toolchain.cmake\")\n    assert \"CMAKE_GENERATOR_TOOLSET\" not in cmake\n"
  },
  {
    "path": "test/functional/toolchains/cmake/test_presets_inherit.py",
    "content": "import json\nimport os\nimport platform\nimport textwrap\nfrom shutil import rmtree\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\n# Shared CMakePresets.json for tests that use user_presets_path + ConanPresets.json\n_CMAKE_PRESETS_FILE = textwrap.dedent(\"\"\"\n    {\n      \"version\": 4,\n      \"include\": [\"./ConanPresets.json\"],\n      \"configurePresets\": [\n        {\"name\": \"default\", \"displayName\": \"multi config\", \"inherits\": \"conan-default\"},\n        {\"name\": \"release\", \"displayName\": \"release single config\", \"inherits\": \"conan-release\"},\n        {\"name\": \"debug\", \"displayName\": \"debug single config\", \"inherits\": \"conan-debug\"}\n      ],\n      \"buildPresets\": [\n        {\"name\": \"multi-release\", \"configurePreset\": \"default\", \"configuration\": \"Release\", \"inherits\": \"conan-release\"},\n        {\"name\": \"multi-debug\", \"configurePreset\": \"default\", \"configuration\": \"Debug\", \"inherits\": \"conan-debug\"},\n        {\"name\": \"release\", \"configurePreset\": \"release\", \"configuration\": \"Release\", \"inherits\": \"conan-release\"},\n        {\"name\": \"debug\", \"configurePreset\": \"debug\", \"configuration\": \"Debug\", \"inherits\": \"conan-debug\"}\n      ]\n    }\n\"\"\")\n\n\ndef _client_with_user_presets():\n    \"\"\"TestClient with cmake_exe, user_presets_path and standard CMakePresets.json.\"\"\"\n    c = TestClient()\n    c.run(\"new cmake_exe -d name=foo -d version=1.0\")\n    conanfile = c.load(\"conanfile.py\")\n    conanfile = conanfile.replace(\n        \"tc = CMakeToolchain(self)\",\n        \"tc = CMakeToolchain(self)\\n        tc.user_presets_path = 'ConanPresets.json'\",\n    )\n    c.save({\"conanfile.py\": conanfile, \"CMakePresets.json\": _CMAKE_PRESETS_FILE})\n    return c\n\n\n@pytest.mark.tool(\"cmake\", \"3.23\")\ndef test_cmake_presets_with_user_presets_file():\n    \"\"\" Test the integration of the generated one with a user root CMakePresets.json\n    \"\"\"\n    c = TestClient()\n    c.run(\"new cmake_exe -d name=foo -d version=1.0\")\n    conanfile = c.load(\"conanfile.py\")\n    conanfile = conanfile.replace(\"tc = CMakeToolchain(self)\",\n                                  \"tc = CMakeToolchain(self)\\n\"\n                                  \"        tc.user_presets_path = 'ConanPresets.json'\\n\"\n                                  \"        tc.presets_prefix = 'conan'\\n\")\n    c.save({\"conanfile.py\": conanfile,\n            \"CMakePresets.json\": _CMAKE_PRESETS_FILE})\n\n    c.run(f\"install . \")\n    c.run(f\"install . -s build_type=Debug\")\n\n    if platform.system() != \"Windows\":\n        c.run_command(\"cmake --preset debug\")\n        c.run_command(\"cmake --build --preset debug\")\n        c.run_command(\"./build/Debug/foo\")\n    else:\n        c.run_command(\"cmake --preset default\")\n        c.run_command(\"cmake --build --preset multi-debug\")\n        c.run_command(\"build\\\\Debug\\\\foo\")\n\n    assert \"Hello World Debug!\" in c.out\n\n    if platform.system() != \"Windows\":\n        c.run_command(\"cmake --preset release\")\n        c.run_command(\"cmake --build --preset release\")\n        c.run_command(\"./build/Release/foo\")\n    else:\n        c.run_command(\"cmake --build --preset multi-release\")\n        c.run_command(\"build\\\\Release\\\\foo\")\n\n    assert \"Hello World Release!\" in c.out\n\n\n@pytest.mark.tool(\"cmake\", \"3.23\")\ndef test_cmake_presets_build_preset_stub_needs_configure_preset():\n    \"\"\"Reproduce issue #19180: buildPresets stubs in ConanPresets.json must include\n    'configurePreset' field for cmake --list-presets to succeed (single-config generators).\n    \"\"\"\n    c = _client_with_user_presets()\n    c.run(\"install .\")\n\n    conan_presets = json.loads(c.load(\"ConanPresets.json\"))\n    for stub in conan_presets.get(\"buildPresets\", []):\n        assert \"configurePreset\" in stub\n\n    c.run_command(\"cmake --list-presets\")\n    assert \"Invalid preset\" not in c.out, f\"cmake --list-presets failed: {c.out}\"\n\n\n@pytest.mark.tool(\"cmake\", \"3.23\")\ndef test_cmake_presets_stubs_restored_after_build_folder_deleted():\n    \"\"\"Reproduce issue #19173: after deleting build/ and reinstalling one config,\n    ConanPresets.json must still contain stubs for presets inherited by user (e.g. conan-release)\n    so cmake --list-presets does not fail.\n    \"\"\"\n    c = _client_with_user_presets()\n    c.run(\"install . -s build_type=Debug\")\n    c.run(\"install . -s build_type=Release\")\n\n    rmtree(os.path.join(c.current_folder, \"build\"))\n    c.run(\"install . -s build_type=Debug\")\n\n    conan_presets = json.loads(c.load(\"ConanPresets.json\"))\n    stub_names = {s[\"name\"] for s in conan_presets.get(\"configurePresets\", [])}\n    assert \"conan-release\" in stub_names\n\n    c.run_command(\"cmake --list-presets\")\n    assert \"Invalid preset\" not in c.out, f\"cmake --list-presets failed: {c.out}\"\n"
  },
  {
    "path": "test/functional/toolchains/cmake/test_shared_cmake.py",
    "content": "import os.path\nimport platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.utils.mocks import ConanFileMock\nfrom conan.tools.env.environment import environment_wrap_command\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import rmdir\n\n\n@pytest.fixture(scope=\"module\")\ndef transitive_shared_client():\n    # TODO: Reuse fixtures\n    client = TestClient(default_server_user=True)\n    client.run(\"new cmake_lib -d name=hello -d version=0.1\")\n    client.run(\"create . -o hello/*:shared=True -tf=\")\n    client.save({}, clean_first=True)\n    client.run(\"new cmake_lib -d name=chat -d version=0.1 -d requires=hello/0.1\")\n    client.run(\"create . -o chat/*:shared=True -o hello/*:shared=True -tf=\")\n\n    client.save({}, clean_first=True)\n    client.run(\"new cmake_exe -d name=app -d version=0.1 -d requires=chat/0.1\")\n    client.run(\"create . -o chat/*:shared=True -o hello/*:shared=True -tf=\")\n    client.run(\"upload * -c -r default\")\n    client.run(\"remove * -c\")\n    return client\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_other_client_can_execute(transitive_shared_client):\n    _check_install_run(transitive_shared_client)\n\n\ndef _check_install_run(client):\n    client = TestClient(servers=client.servers)\n    client.run(\"install --requires=app/0.1@ -o chat*:shared=True -o hello/*:shared=True \"\n               \"-g VirtualRunEnv\")\n    # This only finds \"app\" executable because the \"app/0.1\" is declaring package_type=\"application\"\n    # otherwise, run=None and nothing can tell us if the conanrunenv should have the PATH.\n    command = environment_wrap_command(ConanFileMock(), \"conanrun\", client.current_folder, \"app\")\n\n    client.run_command(command)\n    assert \"app/0.1: Hello World Release!\" in client.out\n    assert \"chat/0.1: Hello World Release!\" in client.out\n    assert \"hello/0.1: Hello World Release!\" in client.out\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_other_client_can_link_cmake(transitive_shared_client):\n    client = transitive_shared_client\n    # https://github.com/conan-io/conan/issues/13000\n    # This failed, because of rpath link in Linux\n    client = TestClient(servers=client.servers, inputs=[\"admin\", \"password\"])\n    client.run(\"new cmake_exe -d name=app -d version=0.1 -d requires=chat/0.1\")\n    client.run(\"create . -o chat/*:shared=True -o hello/*:shared=True -tf=\")\n\n    # check exe also keep running\n    client.run(\"upload * -c -r default\")\n    client.run(\"remove * -c\")\n    _check_install_run(transitive_shared_client)\n\n\n# FIXME: Move to the correct Meson space\n@pytest.mark.tool(\"meson\")\n@pytest.mark.tool(\"ninja\")\n@pytest.mark.tool(\"pkg_config\")\ndef test_other_client_can_link_meson(transitive_shared_client):\n    client = transitive_shared_client\n    # https://github.com/conan-io/conan/issues/13000\n    # This failed, because of rpath link in Linux\n    client = TestClient(servers=client.servers, inputs=[\"admin\", \"password\"], path_with_spaces=False)\n    client.run(\"new meson_exe -d name=app -d version=0.1 -d requires=chat/0.1\")\n    client.run(\"create . -o chat/*:shared=True -o hello/*:shared=True\")\n    # TODO Check that static builds too\n    # client.run(\"create . --build=missing\")\n\n\n# FIXME: Move to the correct Meson space\n@pytest.mark.tool(\"autotools\")\n@pytest.mark.skipif(platform.system() == \"Windows\", reason=\"Autotools needed\")\ndef test_other_client_can_link_autotools(transitive_shared_client):\n    client = transitive_shared_client\n    # https://github.com/conan-io/conan/issues/13000\n    # This failed, because of rpath link in Linux\n    client = TestClient(servers=client.servers, inputs=[\"admin\", \"password\"], path_with_spaces=False)\n    client.run(\"new autotools_exe -d name=app -d version=0.1 -d requires=chat/0.1\")\n    client.run(\"create . -o chat/*:shared=True -o hello/*:shared=True\")\n    # TODO Check that static builds too\n    # client.run(\"create . --build=missing\")\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_shared_cmake_toolchain_components():\n    \"\"\" the same as above, but with components.\n    \"\"\"\n    client = TestClient(default_server_user=True)\n\n    client.run(\"new cmake_lib -d name=hello -d version=0.1\")\n    conanfile = client.load(\"conanfile.py\")\n    conanfile2 = conanfile.replace('self.cpp_info.libs = [\"hello\"]',\n                                   'self.cpp_info.components[\"hi\"].libs = [\"hello\"]')\n    assert conanfile != conanfile2\n    client.save({\"conanfile.py\": conanfile2})\n    client.run(\"create . -o hello/*:shared=True -tf=\")\n    # Chat\n    client.save({}, clean_first=True)\n    client.run(\"new cmake_lib -d name=chat -d version=0.1 -d requires=hello/0.1\")\n    conanfile = client.load(\"conanfile.py\")\n    conanfile2 = conanfile.replace('self.cpp_info.libs = [\"chat\"]',\n                                   'self.cpp_info.components[\"talk\"].libs = [\"chat\"]\\n'\n                                   '        self.cpp_info.components[\"talk\"].requires=[\"hello::hi\"]')\n    assert conanfile != conanfile2\n    client.save({\"conanfile.py\": conanfile2})\n    client.run(\"create . -o chat/*:shared=True -o hello/*:shared=True -tf=\")\n\n    # App\n    client.save({}, clean_first=True)\n    client.run(\"new cmake_exe -d name=app -d version=0.1 -d requires=chat/0.1\")\n    cmakelist = client.load(\"CMakeLists.txt\")\n    cmakelist2 = cmakelist.replace('target_link_libraries(app PRIVATE chat::chat)',\n                                   'target_link_libraries(app PRIVATE chat::talk)')\n    assert cmakelist != cmakelist2\n    client.save({\"CMakeLists.txt\": cmakelist2})\n    client.run(\"create . -o chat/*:shared=True -o hello/*:shared=True -tf=\")\n    client.run(\"upload * -c -r default\")\n    client.run(\"remove * -c\")\n\n    client = TestClient(servers=client.servers)\n    client.run(\"install --requires=app/0.1@ -o chat*:shared=True -o hello/*:shared=True\")\n    # This only finds \"app\" executable because the \"app/0.1\" is declaring package_type=\"application\"\n    # otherwise, run=None and nothing can tell us if the conanrunenv should have the PATH.\n    command = environment_wrap_command(ConanFileMock(), \"conanrun\", client.current_folder, \"app\")\n\n    client.run_command(command)\n    assert \"app/0.1 test_package\" in client.out\n    assert \"app/0.1: Hello World Release!\" in client.out\n    assert \"chat/0.1: Hello World Release!\" in client.out\n    assert \"hello/0.1: Hello World Release!\" in client.out\n\n    # https://github.com/conan-io/conan/issues/13000\n    # This failed, because of rpath link in Linux\n    client = TestClient(servers=client.servers, inputs=[\"admin\", \"password\"])\n    client.run(\"new cmake_exe -d name=app -d version=0.1 -d requires=chat/0.1\")\n    client.run(\"create . -o chat/*:shared=True -o hello/*:shared=True\")\n    client.run(\"upload * -c -r default\")\n    client.run(\"remove * -c\")\n\n    client = TestClient(servers=client.servers)\n    client.run(\"install --requires=app/0.1@ -o chat*:shared=True -o hello/*:shared=True\")\n    # This only finds \"app\" executable because the \"app/0.1\" is declaring package_type=\"application\"\n    # otherwise, run=None and nothing can tell us if the conanrunenv should have the PATH.\n    command = environment_wrap_command(ConanFileMock(), \"conanrun\", client.current_folder, \"app\")\n\n    client.run_command(command)\n    assert \"app/0.1: Hello World Release!\" in client.out\n    assert \"chat/0.1: Hello World Release!\" in client.out\n    assert \"hello/0.1: Hello World Release!\" in client.out\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_shared_cmake_toolchain_test_package():\n    # TODO: This is already tested in other places\n    client = TestClient()\n    client.run(\"new cmake_lib -d name=hello -d version=0.1\")\n    client.run(\"create . -o hello/*:shared=True\")\n    assert \"hello/0.1: Hello World Release!\" in client.out\n    assert \"hello/0.1 test_package\" in client.out\n\n\n@pytest.fixture()\ndef test_client_shared():\n    client = TestClient()\n    client.run(\"new -d name=hello -d version=0.1 cmake_lib\")\n    test_conanfile = textwrap.dedent(\"\"\"\n                import os\n                from conan import ConanFile\n                from conan.tools.cmake import CMake, cmake_layout\n                from conan.tools.files import copy\n\n                class Pkg(ConanFile):\n                    settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n                    generators = \"CMakeToolchain\", \"CMakeDeps\"\n\n                    def requirements(self):\n                        self.requires(self.tested_reference_str)\n\n                    def layout(self):\n                        cmake_layout(self)\n\n                    def build(self):\n                        cmake = CMake(self)\n                        cmake.configure()\n                        cmake.build()\n\n                    def generate(self):\n                        for dep in self.dependencies.values():\n                            copy(self, \"*.dylib\", dep.cpp_info.libdirs[0], self.build_folder)\n                            copy(self, \"*.dll\", dep.cpp_info.libdirs[0], self.build_folder)\n\n                    def test(self):\n                        cmd = os.path.join(self.cpp.build.bindirs[0], \"example\")\n                        # This is working without runenv because CMake is puting an internal rpath\n                        # to the executable pointing to the dylib of hello, internally is doing something\n                        # like: install_name_tool -add_rpath /path/to/hello/lib/libhello.dylib test\n                        self.run(cmd)\n                \"\"\")\n    files = {\"test_package/conanfile.py\": test_conanfile}\n\n    client.save(files)\n    client.run(\"create . -o hello*:shared=True\")\n    assert \"Hello World Release!\" in client.out\n\n    # We can run the exe from the test package directory also, without environment\n    # because there is an internal RPATH in the exe with an abs path to the \"hello\"\n    build_folder = client.created_test_build_folder(\"hello/0.1\")\n    exe_folder = os.path.join(\"test_package\", build_folder)\n    client.test_exe_folder = exe_folder\n    assert os.path.exists(os.path.join(client.current_folder, exe_folder, \"example\"))\n    client.run_command(os.path.join(exe_folder, \"example\"))\n\n    # We try to remove the hello package and run again the executable from the test package,\n    # this time it should fail, it doesn't find the shared library\n    client.run(\"remove '*' -c\")\n    client.run_command(os.path.join(exe_folder, \"example\"), assert_error=True)\n    return client\n\n\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only OSX\")\ndef test_shared_same_dir_using_tool(test_client_shared):\n    \"\"\"\n    If we build an executable in Mac and we want it to locate the shared libraries in the same\n    directory, we have different alternatives, here we use the \"install_name_tool\"\n    \"\"\"\n    exe_folder = test_client_shared.test_exe_folder\n    # Alternative 1, add the \".\" to the rpaths so the @rpath from the exe can be replaced with \".\"\n    test_client_shared.current_folder = os.path.join(test_client_shared.current_folder, exe_folder)\n    test_client_shared.run_command(\"install_name_tool -add_rpath '.' example\")\n    test_client_shared.run_command(\"./{}\".format(\"example\"))\n\n\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only OSX\")\ndef test_shared_same_dir_using_cmake(test_client_shared):\n    \"\"\"\n        If we build an executable in Mac and we want it to locate the shared libraries in the same\n        directory, we have different alternatives, here we use CMake to adjust CMAKE_INSTALL_RPATH\n        to @executable_path so the exe knows that can replace @rpath with the current dir\n    \"\"\"\n\n    # Alternative 2, set the rpath in cmake\n    # Only viable when installing with cmake\n    cmake = \"\"\"\n    set(CMAKE_CXX_COMPILER_WORKS 1)\n    set(CMAKE_CXX_ABI_COMPILED 1)\n    set(CMAKE_C_COMPILER_WORKS 1)\n    set(CMAKE_C_ABI_COMPILED 1)\n    cmake_minimum_required(VERSION 3.15)\n    project(project CXX)\n\n    set(CMAKE_INSTALL_RPATH \"@executable_path\")\n\n    find_package(hello)\n    add_executable(test  src/example.cpp )\n    target_link_libraries(test  hello::hello)\n    # Hardcoded installation path to keep the exe in the same place in the tests\n    install(TARGETS test DESTINATION \"bin\")\n    \"\"\"\n    # Same test conanfile but calling cmake.install()\n    cf = textwrap.dedent(\"\"\"\n                import os\n                from conan import ConanFile\n                from conan.tools.files import copy\n                from conan.tools.cmake import CMake, cmake_layout\n\n                class Pkg(ConanFile):\n                    settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n                    generators = \"CMakeToolchain\", \"CMakeDeps\"\n\n                    def generate(self):\n                        # The exe is installed by cmake at test_package/bin\n                        dest = os.path.join(self.recipe_folder, \"bin\")\n                        for dep in self.dependencies.values():\n                            copy(self, \"*.dylib\", dep.cpp_info.libdirs[0], dest)\n\n                    def requirements(self):\n                        self.requires(self.tested_reference_str)\n\n                    def layout(self):\n                        cmake_layout(self)\n\n                    def build(self):\n                        cmake = CMake(self)\n                        cmake.configure()\n                        cmake.build()\n                        cmake.install()\n\n                    def test(self):\n                        cmd = os.path.join(self.cpp.build.bindirs[0], \"test\")\n                        # This is working without runenv because CMake is puting an internal rpath\n                        # to the executable pointing to the dylib of hello, internally is doing something\n                        # like: install_name_tool -add_rpath /path/to/hello/lib/libhello.dylib test\n                        self.run(cmd)\n                \"\"\")\n    test_client_shared.save({\"test_package/CMakeLists.txt\": cmake, \"test_package/conanfile.py\": cf})\n    test_client_shared.run(\"create . -o hello*:shared=True\")\n    test_client_shared.run(\"remove '*' -c\")\n    exe_folder = os.path.join(\"test_package\", \"bin\")\n    test_client_shared.run_command(os.path.join(exe_folder, \"test\"))\n\n\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only OSX\")\ndef test_shared_same_dir_using_env_var_current_dir(test_client_shared):\n    \"\"\"\n        If we build an executable in Mac and we want it to locate the shared libraries in the same\n        directory, we have different alternatives, here we set DYLD_LIBRARY_PATH before calling\n        the executable but running in current dir\n    \"\"\"\n\n    # Alternative 3, FAILING IN CI, set DYLD_LIBRARY_PATH in the current dir\n    exe_folder = test_client_shared.test_exe_folder\n    rmdir(os.path.join(test_client_shared.current_folder, exe_folder))\n    test_client_shared.run(\"create . -o hello*:shared=True\")\n    test_client_shared.run(\"remove '*' -c\")\n    test_client_shared.current_folder = os.path.join(test_client_shared.current_folder, exe_folder)\n    test_client_shared.run_command(\"DYLD_LIBRARY_PATH=$(pwd) ./example\")\n    test_client_shared.run_command(\"DYLD_LIBRARY_PATH=. ./example\")\n    # This assert is not working in CI, only locally\n    # test_client_shared.run_command(\"DYLD_LIBRARY_PATH=@executable_path ./test\")\n"
  },
  {
    "path": "test/functional/toolchains/cmake/test_transitive_build_scripts.py",
    "content": "import textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_transitive_build_scripts():\n    c = TestClient()\n    scriptsa = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import copy\n        class ScriptsA(ConanFile):\n            name = \"scriptsa\"\n            version = \"0.1\"\n            package_type = \"build-scripts\"\n            exports_sources = \"*.cmake\"\n            def package(self):\n                copy(self, \"*.cmake\", src=self.source_folder, dst=self.package_folder)\n            def package_info(self):\n                self.cpp_info.builddirs = [\".\"]\n            \"\"\")\n    scriptsa_cmake = textwrap.dedent(\"\"\"\n        function(myfunctionA)\n            message(STATUS \"MYFUNCTION CMAKE A: Hello world A!!!\")\n        endfunction()\n    \"\"\")\n    scriptsb = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import copy\n        class ScriptsA(ConanFile):\n            name = \"scriptsb\"\n            version = \"0.1\"\n            package_type = \"build-scripts\"\n            exports_sources = \"*.cmake\"\n            def requirements(self):\n                self.requires(\"scriptsa/0.1\", run=True, visible=True)\n            def package(self):\n                copy(self, \"*.cmake\", src=self.source_folder, dst=self.package_folder)\n            def package_info(self):\n                self.cpp_info.builddirs = [\".\"]\n            \"\"\")\n    scriptsb_cmake = textwrap.dedent(\"\"\"\n        find_package(scriptsa)\n        function(myfunctionB)\n            message(STATUS \"MYFUNCTION CMAKE B: Hello world B!!!\")\n            myfunctionA()\n        endfunction()\n        \"\"\")\n    app = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n\n        class App(ConanFile):\n            package_type = \"application\"\n            generators = \"CMakeToolchain\"\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n\n            def build_requirements(self):\n                self.tool_requires(\"scriptsb/0.1\")\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n        \"\"\")\n    app_cmake = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(App LANGUAGES NONE)\n        find_package(scriptsb)\n        myfunctionB()\n    \"\"\")\n    c.save({\"scriptsa/conanfile.py\": scriptsa,\n            \"scriptsa/Findscriptsa.cmake\": scriptsa_cmake,\n            \"scriptsb/conanfile.py\": scriptsb,\n            \"scriptsb/Findscriptsb.cmake\": scriptsb_cmake,\n            \"app/conanfile.py\": app,\n            \"app/CMakeLists.txt\": app_cmake})\n\n    c.run(\"create scriptsa\")\n    c.run(\"create scriptsb\")\n    c.run(\"build app\")\n\n    assert \"MYFUNCTION CMAKE B: Hello world B!!!\" in c.out\n    assert \"MYFUNCTION CMAKE A: Hello world A!!!\" in c.out\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_reuse_macro_from_dep():\n    \"\"\"\n    A simple cmake script can be added from a regular requires, without even a ``find_package()``\n    https://github.com/conan-io/conan/issues/14013\n    \"\"\"\n    c = TestClient()\n    pkg = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import copy\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            package_type = \"static-library\"\n            exports_sources = \"*.cmake\"\n            def package(self):\n                copy(self, \"*.cmake\", src=self.source_folder, dst=self.package_folder)\n            def package_info(self):\n                self.cpp_info.builddirs = [\".\"]\n            \"\"\")\n    pkg_macros = textwrap.dedent(\"\"\"\n        function(pkg_macro)\n            message(STATUS \"PKG MACRO WORKING!!!\")\n        endfunction()\n    \"\"\")\n    app = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n\n        class App(ConanFile):\n            package_type = \"application\"\n            generators = \"CMakeToolchain\"\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n\n            def requirements(self):\n                self.requires(\"pkg/0.1\")\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n        \"\"\")\n    app_cmake = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.15)\n        project(App LANGUAGES NONE)\n\n        include(Macros)\n        pkg_macro()\n    \"\"\")\n    c.save({\"pkg/conanfile.py\": pkg,\n            \"pkg/Macros.cmake\": pkg_macros,\n            \"app/conanfile.py\": app,\n            \"app/CMakeLists.txt\": app_cmake})\n\n    c.run(\"create pkg\")\n    c.run(\"build app\")\n\n    assert \"PKG MACRO WORKING!!!\" in c.out\n\n"
  },
  {
    "path": "test/functional/toolchains/cmake/test_universal_binaries.py",
    "content": "import os\nimport platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import rmdir\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only OSX\")\n@pytest.mark.tool(\"cmake\", \"3.23\")\ndef test_create_universal_binary():\n    client = TestClient()\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake, cmake_layout\n        class mylibraryRecipe(ConanFile):\n            package_type = \"library\"\n            generators = \"CMakeToolchain\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            options = {\"shared\": [True, False], \"fPIC\": [True, False]}\n            default_options = {\"shared\": False, \"fPIC\": True}\n            exports_sources = \"CMakeLists.txt\", \"src/*\", \"include/*\"\n\n            def layout(self):\n                cmake_layout(self)\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n                self.run(\"lipo -info libmylibrary.a\")\n\n            def package(self):\n                cmake = CMake(self)\n                cmake.install()\n\n            def package_info(self):\n                self.cpp_info.libs = [\"mylibrary\"]\n    \"\"\")\n\n    test_conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.cmake import CMake, cmake_layout\n        from conan.tools.build import can_run\n\n        class mylibraryTestConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"CMakeDeps\", \"CMakeToolchain\"\n\n            def requirements(self):\n                self.requires(self.tested_reference_str)\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n\n            def layout(self):\n                cmake_layout(self)\n\n            def test(self):\n                exe = os.path.join(self.cpp.build.bindir, \"example\")\n                self.run(f\"lipo {exe} -info\", env=\"conanrun\")\n            \"\"\")\n\n    client.run(\"new cmake_lib -d name=mylibrary -d version=1.0\")\n    client.save({\"conanfile.py\": conanfile, \"test_package/conanfile.py\": test_conanfile})\n\n    client.run('create . --name=mylibrary --version=1.0 '\n               '-s=\"arch=armv8|armv8.3|x86_64\" --build=missing -tf=\"\"')\n\n    assert \"libmylibrary.a are: x86_64 arm64 arm64e\" in client.out\n\n    client.run('test test_package mylibrary/1.0 -s=\"arch=armv8|armv8.3|x86_64\"')\n\n    assert \"example are: x86_64 arm64 arm64e\" in client.out\n\n    client.run('new cmake_exe -d name=foo -d version=1.0 -d requires=mylibrary/1.0 --force')\n\n    client.run('install . -s=\"arch=armv8|armv8.3|x86_64\"')\n\n    client.run_command(\"cmake --preset conan-release\")\n    client.run_command(\"cmake --build --preset conan-release\")\n    client.run_command(\"lipo -info ./build/Release/foo\")\n\n    assert \"foo are: x86_64 arm64 arm64e\" in client.out\n\n    rmdir(os.path.join(client.current_folder, \"build\"))\n\n    client.run('install . -s=\"arch=armv8|armv8.3|x86_64\" '\n               '-c tools.cmake.cmake_layout:build_folder_vars=\\'[\"settings.arch\"]\\'')\n\n    client.run_command(\"cmake --preset \\\"conan-armv8_armv8.3_x86_64-release\\\" \")\n    client.run_command(\"cmake --build --preset \\\"conan-armv8_armv8.3_x86_64-release\\\" \")\n    client.run_command(\"lipo -info './build/armv8_armv8.3_x86_64/Release/foo'\")\n\n    assert \"foo are: x86_64 arm64 arm64e\" in client.out\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only OSX\")\n@pytest.mark.tool(\"cmake\", \"3.23\")\ndef test_create_universal_binary_ninja():\n    client = TestClient()\n\n    client.run(\"new cmake_lib -d name=mylibrary -d version=1.0\")\n\n    client.run('export .')\n\n    conanfile = textwrap.dedent(\"\"\"\n        [requires]\n        mylibrary/1.0\n        [generators]\n        CMakeToolchain\n        CMakeDeps\n        VirtualBuildEnv\n        VirtualRunEnv\n        \"\"\")\n\n    cmake = textwrap.dedent(\"\"\"\n        cmake_minimum_required(VERSION 3.23)\n        project(ninjatest NONE)\n\n        find_package(mylibrary CONFIG REQUIRED)\n        \"\"\")\n\n    client.save({\"conanfile.txt\": conanfile,\n                 \"CMakeLists.txt\": cmake},\n                clean_first=True)\n\n    client.run('install . -s=arch=\"armv8|x86_64\" --build=missing -of=build')\n\n    with client.chdir(\"build\"):\n        client.run_command(\"cmake .. -GNinja \"\n                           \"-DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake \"\n                           \"-DCMAKE_POLICY_DEFAULT_CMP0091=NEW \"\n                           \"-DCMAKE_BUILD_TYPE=Release\")\n\n    assert \"expected newline, got '|'\" not in client.out\n    assert \"Build files have been written to:\" in client.out\n    # test that there are no files with the \"|\" character in the build folder\n    assert not any(\"|\" in f for f in os.listdir(os.path.join(client.current_folder, \"build\")))\n"
  },
  {
    "path": "test/functional/toolchains/cmake/test_v2_cmake_template.py",
    "content": "import os\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_cmake_lib_template():\n    client = TestClient(path_with_spaces=False)\n    client.run(\"new cmake_lib -d name=hello -d version=0.1\")\n    # Local flow works\n    client.run(\"build .\")\n\n    client.run(\"export-pkg .\")\n    package_folder = client.created_layout().package()\n    assert os.path.exists(os.path.join(package_folder, \"include\", \"hello.h\"))\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_cmake_lib_template_create(matrix_client_shared_debug):\n    client = matrix_client_shared_debug\n    client.run(\"new cmake_lib -d name=matrix -d version=1.0\")\n    # Create works\n    client.run(\"create . --build=never\")\n    assert \"matrix/1.0: Hello World Release!\" in client.out\n\n    client.run(\"create . -s build_type=Debug --build=never\")\n    assert \"matrix/1.0: Hello World Debug!\" in client.out\n\n    # Create + shared works\n    client.run(\"create . -o hello/*:shared=True --build=never\")\n    assert \"matrix/1.0: Hello World Release!\" in client.out\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_cmake_exe_template():\n    client = TestClient(path_with_spaces=False)\n    client.run(\"new cmake_exe -d name=greet -d version=0.1\")\n    # Local flow works\n    client.run(\"build .\")\n\n    # Create works\n    client.run(\"create .\")\n    assert \"greet/0.1: Hello World Release!\" in client.out\n\n    client.run(\"create . -s build_type=Debug\")\n    assert \"greet/0.1: Hello World Debug!\" in client.out\n"
  },
  {
    "path": "test/functional/toolchains/emscripten/__init__.py",
    "content": ""
  },
  {
    "path": "test/functional/toolchains/emscripten/test_emcc.py",
    "content": "# Test suite to check conan capabilities for cross compiling to web assembly and asmjs\nimport textwrap\nimport os\nimport platform\nfrom shutil import rmtree\nimport pytest\nimport sys\n\nfrom conan.test.utils.tools import TestClient\n\nEMCC_MIN_PYTHON_VERSION = (3, 8)\n\nbase_emscripten_profile = textwrap.dedent(\n    \"\"\"\n    [settings]\n    build_type=Release\n    compiler=emcc\n    compiler.cppstd=17\n    compiler.libcxx=libc++\n    compiler.version=4.0.10\n    os=Emscripten\n\n    [conf]\n    tools.build:exelinkflags=['-sALLOW_MEMORY_GROWTH=1']\n    tools.build:sharedlinkflags=['-sALLOW_MEMORY_GROWTH=1']\n\n    # Define the emcc executable paths\n    tools.build:compiler_executables={'c':'emcc', 'cpp':'em++'}\n\n    # Set Ninja as default generator as it is faster and will sove issues on Windows\n    tools.cmake.cmaketoolchain:generator=Ninja\n    # Verbosity to see emcc invocations\n    tools.compilation:verbosity=verbose\n    # Distinguish between architectures\n    tools.cmake.cmake_layout:build_folder_vars=['settings.build_type', 'settings.arch']\n\n    [buildenv]\n    AR=emar\n    NM=emnm\n    RANLIB=emranlib\n    STRIP=emstrip\n\"\"\"\n)\n\nwasm32_profile = textwrap.dedent(\n    \"\"\"\n    include(base_emscripten_profile)\n    [settings]\n    arch=wasm\n\n    [conf]\n    tools.build:exelinkflags+=['-sMAXIMUM_MEMORY=4GB', '-sINITIAL_MEMORY=64MB']\n    tools.build:sharedlinkflags+=['-sMAXIMUM_MEMORY=4GB', '-sINITIAL_MEMORY=64MB']\n    \"\"\"\n)\n\nwasm_64_profile = textwrap.dedent(\n    \"\"\"\n    include(base_emscripten_profile)\n    [settings]\n    arch=wasm64\n    [conf]\n    tools.build:exelinkflags+=['-sMAXIMUM_MEMORY=16GB', '-sINITIAL_MEMORY=16GB']\n    tools.build:sharedlinkflags+=['-sMAXIMUM_MEMORY=16GB', '-sINITIAL_MEMORY=16GB']\n    \"\"\"\n)\n\n\nasmjs_profile = textwrap.dedent(\n    \"\"\"\n    include(base_emscripten_profile)\n    [settings]\n    arch=asm.js\n\n    [conf]\n    tools.build:exelinkflags+=['-sMAXIMUM_MEMORY=2GB', '-sINITIAL_MEMORY=64MB']\n    tools.build:sharedlinkflags+=['-sMAXIMUM_MEMORY=2GB', '-sINITIAL_MEMORY=64MB']\n    \"\"\"\n)\n\n\n@pytest.mark.slow\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.tool(\"emcc\")\n@pytest.mark.tool(\"node\")\n@pytest.mark.skipif(sys.version_info < EMCC_MIN_PYTHON_VERSION, reason = \"emcc requires Python 3.8 or higher\")\n@pytest.mark.skipif(platform.system() == \"Windows\", reason = \"Emscripten not installed in Windows\")\ndef test_cmake_emscripten():\n    client = TestClient()\n\n    client.run(\"new cmake_exe -d name=hello -d version=0.1\")\n    client.save({\"wasm32\": wasm32_profile, \"asmjs\": asmjs_profile, \"base_emscripten_profile\": base_emscripten_profile,})\n\n    client.run(\"build . -pr:h=wasm32\")\n    assert \"Conan toolchain: Defining libcxx as C++ flags: -stdlib=libc++\" in client.out\n    assert os.path.exists(os.path.join(client.current_folder, \"build/release-wasm\" , \"hello.wasm\"))\n\n    # Run JavaScript generated code which uses .wasm file\n    client.run_command(\"node ./build/release-wasm/hello\")\n    assert \"Hello World Release!\" in client.out\n\n    client.run(\"build . -pr:h=asmjs\")\n    assert \"WASM=0\" in client.out\n    # No wasm should have been generated for asm.js architecture\n    assert not os.path.exists(os.path.join(client.current_folder, \"build/release-asm.js\" , \"hello.wasm\"))\n    client.run_command(\"node ./build/release-asm.js/hello\")\n    assert \"Hello World Release!\" in client.out\n\n\n@pytest.mark.slow\n@pytest.mark.tool(\"meson\")\n@pytest.mark.tool(\"emcc\")\n@pytest.mark.tool(\"node\")\n@pytest.mark.skipif(sys.version_info < EMCC_MIN_PYTHON_VERSION, reason = \"emcc requires Python 3.8 or higher\")\n@pytest.mark.skipif(platform.system() == \"Windows\", reason = \"Emscripten not installed in Windows\")\ndef test_meson_emscripten():\n    client = TestClient()\n    client.run(\"new meson_exe -d name=hello -d version=0.1\")\n\n    client.save({\"wasm32\": wasm32_profile, \"wasm64\": wasm_64_profile, \"asmjs\": asmjs_profile, \"base_emscripten_profile\": base_emscripten_profile,})\n    client.run(\"build . -pr:h=wasm64\")\n    assert \"C++ compiler for the host machine: em++\" in client.out\n    assert \"C++ linker for the host machine: em++ ld.wasm\" in client.out\n    assert \"Host machine cpu family: wasm64\" in client.out\n    assert os.path.exists(os.path.join(client.current_folder, \"build\", \"hello.wasm\"))\n    # wasm64 only supported since node v23 so only run in MacOS where it is available\n    if platform.system() == \"Darwin\":\n        client.run_command(\"node ./build/hello\")\n        assert \"Hello World Release!\" in client.out\n\n    rmtree(os.path.join(client.current_folder, \"build\"))\n    client.run(\"build . -pr:h=asmjs\")\n    assert \"C++ compiler for the host machine: em++\" in client.out\n    assert \"C++ linker for the host machine: em++ ld.wasm\" in client.out\n    assert \"Host machine cpu family: asm.js\" in client.out\n    assert \"WASM=0\" in client.out\n\n    assert not os.path.exists(os.path.join(client.current_folder, \"build\", \"hello.wasm\"))\n    client.run_command(\"node ./build/hello\")\n    assert \"Hello World Release!\" in client.out\n\n\n@pytest.mark.slow\n@pytest.mark.tool(\"autotools\")\n@pytest.mark.tool(\"emcc\")\n@pytest.mark.tool(\"node\")\n@pytest.mark.skipif(sys.version_info < EMCC_MIN_PYTHON_VERSION, reason = \"emcc requires Python 3.8 or higher\")\n@pytest.mark.skipif(platform.system() == \"Windows\", reason = \"Emscripten not installed in Windows\")\ndef test_autotools_emscripten():\n    client = TestClient(path_with_spaces=False)\n    client.run(\"new autotools_exe -d name=hello -d version=0.1\")\n    client.save({\"wasm32\": wasm32_profile, \"asmjs\": asmjs_profile, \"base_emscripten_profile\": base_emscripten_profile,})\n    client.run(\"build . -pr:h=wasm32\")\n    assert \"checking for wasm32-local-emscripten-ranlib... emranlib\" in client.out\n    assert \"checking for wasm32-local-emscripten-gcc... emcc\" in client.out\n    assert \"checking for wasm32-local-emscripten-ar... emar\" in client.out\n    assert \"checking the archiver (emar) interface... ar\" in client.out\n    assert \"checking for wasm32-local-emscripten-strip... emstrip\" in client.out\n\n    assert os.path.exists(os.path.join(client.current_folder, \"build-release\", \"src\", \"hello.wasm\"))\n    # Run JavaScript generated code which uses .wasm file\n    client.run_command(\"node ./build-release/src/hello\")\n    assert \"Hello World Release!\" in client.out\n\n    rmtree(os.path.join(client.current_folder, \"build-release\"))\n    client.run(\"build . -pr:h=asmjs\")\n    assert \"WASM=0\" in client.out\n    # No wasm should have been generated for asm.js architecture\n    assert not os.path.exists(os.path.join(client.current_folder, \"build-release\", \"hello.wasm\"))\n    client.run_command(\"node ./build-release/src/hello\")\n    assert \"Hello World Release!\" in client.out\n\n\n@pytest.mark.slow\n@pytest.mark.tool(\"premake\")\n@pytest.mark.tool(\"emcc\")\n@pytest.mark.tool(\"node\")\n@pytest.mark.skipif(sys.version_info < EMCC_MIN_PYTHON_VERSION, reason = \"emcc requires Python 3.8 or higher\")\n@pytest.mark.skipif(platform.system() != \"Linux\", reason = \"Premake only installed in linux\")\ndef test_premake_emscripten():\n    client = TestClient()\n    client.run(\"new premake_exe -d name=hello -d version=0.1\")\n    client.save({\"wasm32\": wasm32_profile, \"asmjs\": asmjs_profile, \"base_emscripten_profile\": base_emscripten_profile,})\n    client.run(\"build . -pr:h=wasm32\")\n    assert \"gmake --arch=wasm32\" in client.out\n    assert os.path.exists(os.path.join(client.current_folder, \"build-release\", \"bin\", \"hello.wasm\"))\n    # Run JavaScript generated code which uses .wasm file\n    client.run_command(\"node ./build-release/bin/hello\")\n    assert \"Hello World Release!\" in client.out\n    rmtree(os.path.join(client.current_folder, \"build-release\"))\n\n    client.run(\"build . -pr:h=asmjs\")\n    assert \"WASM=0\" in client.out\n    # No wasm should have been generated for asm.js architecture\n    assert not os.path.exists(os.path.join(client.current_folder, \"build-release\", \"bin\", \"hello.wasm\"))\n    client.run_command(\"node ./build-release/bin/hello\")\n    assert \"Hello World Release!\" in client.out\n\n# TODO: test_bazel_emscripten(): need WIP new bazel toolchain\n# TODO: test_msbuild_emscripten(): give support to msbuild\n"
  },
  {
    "path": "test/functional/toolchains/env/__init__.py",
    "content": ""
  },
  {
    "path": "test/functional/toolchains/env/test_complete.py",
    "content": "import textwrap\n\nimport pytest\n\nfrom conan.test.assets.sources import gen_function_cpp\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_cmake_virtualenv(matrix_client):\n    client = matrix_client\n\n    cmakewrapper = textwrap.dedent(r\"\"\"\n        from conan import ConanFile\n        import os\n        from conan.tools.files import save, chdir\n        class Pkg(ConanFile):\n            def package(self):\n                with chdir(self, self.package_folder):\n                    save(self, \"cmake.bat\", \"@echo off\\necho MYCMAKE WRAPPER!!\\ncmake.exe %*\")\n                    save(self, \"cmake.sh\", 'echo MYCMAKE WRAPPER!!\\ncmake \"$@\"')\n                    os.chmod(\"cmake.sh\", 0o777)\n\n            def package_info(self):\n                # Custom buildenv not defined by cpp_info\n                self.buildenv_info.prepend_path(\"PATH\", self.package_folder)\n            \"\"\")\n    consumer = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n        class App(ConanFile):\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            exports_sources = \"CMakeLists.txt\", \"main.cpp\"\n            requires = \"matrix/1.0\"\n            build_requires = \"cmakewrapper/0.1\"\n            generators = \"CMakeDeps\", \"CMakeToolchain\", \"VirtualBuildEnv\"\n\n            def build(self):\n                cmake = CMake(self)\n                if self.settings.os != \"Windows\":\n                    cmake._cmake_program = \"cmake.sh\"  # VERY DIRTY HACK\n                cmake.configure()\n                cmake.build()\n        \"\"\")\n\n    cmakelists = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.15)\n        project(MyApp CXX)\n\n        find_package(matrix)\n        add_executable(app main.cpp)\n        target_link_libraries(app matrix::matrix)\n        \"\"\")\n\n    client.save({\"cmakewrapper/conanfile.py\": cmakewrapper,\n                 \"consumer/conanfile.py\": consumer,\n                 \"consumer/main.cpp\": gen_function_cpp(name=\"main\", includes=[\"matrix\"],\n                                                       calls=[\"matrix\"]),\n                 \"consumer/CMakeLists.txt\": cmakelists},\n                clean_first=True)\n\n    client.run(\"create cmakewrapper --name=cmakewrapper --version=0.1\")\n    client.run(\"create consumer --name=consumer --version=0.1\")\n    assert \"MYCMAKE WRAPPER!!\" in client.out\n    assert \"consumer/0.1: Created package\" in client.out\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_complete():\n    client = TestClient()\n    client.run(\"new cmake_lib -d name=myopenssl -d version=1.0\")\n    client.run(\"create . -o myopenssl/*:shared=True\")\n    client.run(\"create . -o myopenssl/*:shared=True -s build_type=Debug\")\n\n    mycmake_main = gen_function_cpp(name=\"main\", msg=\"mycmake\",\n                                    includes=[\"myopenssl\"], calls=[\"myopenssl\"])\n    mycmake_conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n        from conan.tools.files import copy\n        class App(ConanFile):\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            requires = \"myopenssl/1.0\"\n            default_options = {\"myopenssl:shared\": True}\n            generators = \"CMakeDeps\", \"CMakeToolchain\", \"VirtualBuildEnv\"\n            exports_sources = \"*\"\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n\n            def package(self):\n                src = str(self.settings.build_type) if self.settings.os == \"Windows\" else \"\"\n                copy(self, \"mycmake*\", os.path.join(self.source_folder, src),\n                     os.path.join(self.package_folder, \"bin\"))\n\n            def package_info(self):\n                self.cpp_info.bindirs = [\"bin\"]\n        \"\"\")\n    mycmake_cmakelists = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.15)\n        project(MyCmake CXX)\n\n        find_package(myopenssl REQUIRED)\n        add_executable(mycmake main.cpp)\n        target_link_libraries(mycmake PRIVATE myopenssl::myopenssl)\n        \"\"\")\n    client.save({\"conanfile.py\": mycmake_conanfile,\n                 \"CMakeLists.txt\": mycmake_cmakelists,\n                 \"main.cpp\": mycmake_main}, clean_first=True)\n    client.run(\"create . --name=mycmake --version=1.0\", assert_error=True)\n    assert \"The usage of package names `myopenssl:shared` in options is deprecated, \" \\\n           \"use a pattern like `myopenssl/*:shared` instead\" in client.out\n\n    client.run(\"create . --name=mycmake --version=1.0 -o=:shared=True\", assert_error=True)\n    assert \"Invalid empty package\" in client.out\n\n    # Fix the default options and repeat the create\n    fixed_cf = mycmake_conanfile.replace('default_options = {\"myopenssl:shared\": True}',\n                                         'default_options = {\"myopenssl*:shared\": True}')\n    client.save({\"conanfile.py\": fixed_cf})\n    client.run(\"create . --name=mycmake --version=1.0\")\n\n    mylib = textwrap.dedent(r\"\"\"\n        from conan import ConanFile\n        import os\n        from conan.tools.cmake import CMake\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            build_requires = \"mycmake/1.0\"\n            requires = \"myopenssl/1.0\"\n            default_options = {\"myopenssl/*:shared\": True}\n            exports_sources = \"CMakeLists.txt\", \"main.cpp\"\n            generators = \"CMakeDeps\", \"CMakeToolchain\"\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n                self.run(\"mycmake\")\n                self.output.info(\"RUNNING MYAPP\")\n                if self.settings.os == \"Windows\":\n                    self.run(os.sep.join([\".\", str(self.settings.build_type), \"myapp\"]),\n                             env=\"conanrun\")\n                else:\n                    self.run(os.sep.join([\".\", \"myapp\"]), env=[\"conanrun\"])\n            \"\"\")\n\n    cmakelists = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.15)\n        project(MyApp CXX)\n\n        find_package(myopenssl)\n        add_executable(myapp main.cpp)\n        target_link_libraries(myapp myopenssl::myopenssl)\n        \"\"\")\n\n    client.save({\"conanfile.py\": mylib,\n                 \"main.cpp\": gen_function_cpp(name=\"main\", msg=\"myapp\", includes=[\"myopenssl\"],\n                                              calls=[\"myopenssl\"]),\n                 \"CMakeLists.txt\": cmakelists},\n                clean_first=True)\n\n    client.run(\"create . --name=myapp --version=0.1 -s:b build_type=Release -s:h build_type=Debug\")\n    first, last = str(client.out).split(\"RUNNING MYAPP\")\n    assert \"mycmake: Release!\" in first\n    assert \"myopenssl/1.0: Hello World Release!\" in first\n\n    assert \"myapp: Debug!\" in last\n    assert \"myopenssl/1.0: Hello World Debug!\" in last\n"
  },
  {
    "path": "test/functional/toolchains/env/test_virtualenv_powershell.py",
    "content": "import os\nimport platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.cmake import gen_cmakelists\nfrom conan.test.assets.sources import gen_function_cpp\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.mocks import ConanFileMock\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient\nfrom conan.tools.env.environment import environment_wrap_command\n\n\n@pytest.fixture\ndef client():\n    # We use special characters and spaces, to check everything works\n    # https://github.com/conan-io/conan/issues/12648\n    # FIXME: This path still fails the creation of the deactivation script\n    cache_folder = os.path.join(temp_folder(), \"[sub] folder\")\n    client = TestClient(cache_folder)\n    conanfile = str(GenConanfile(\"pkg\", \"0.1\"))\n    conanfile += \"\"\"\n\n    def package_info(self):\n        self.buildenv_info.define_path(\"MYPATH1\", \"c:/path/to/ar\")\n        self.runenv_info.define(\"MYVAR1\", 'some nice content\\\" with quotes')\n    \"\"\"\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create .\")\n    client.save_home({\"global.conf\": \"tools.env.virtualenv:powershell=powershell.exe\\n\"})\n    return client\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows powershell\")\ndef test_virtualenv(client):\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n\n        class ConanFileToolsTest(ConanFile):\n            name = \"app\"\n            version = \"0.1\"\n            requires = \"pkg/0.1\"\n\n            def build(self):\n                self.output.info(\"----------BUILD----------------\")\n                self.run(\"set\")\n                self.output.info(\"----------RUN----------------\")\n                self.run(\"set\", env=\"conanrun\")\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"install . -s:b os=Windows -s:h os=Windows\")\n\n    assert not os.path.exists(os.path.join(client.current_folder, \"conanbuildenv.sh\"))\n    assert not os.path.exists(os.path.join(client.current_folder, \"conanbuildenv.bat\"))\n    assert not os.path.exists(os.path.join(client.current_folder, \"conanrunenv.sh\"))\n    assert not os.path.exists(os.path.join(client.current_folder, \"conanrunenv.bat\"))\n    with open(os.path.join(client.current_folder, \"conanbuildenv.ps1\"), \"r\", encoding=\"utf-16\") as f:\n        buildenv = f.read()\n    assert '$env:MYPATH1=\"c:/path/to/ar\"' in buildenv\n    build = client.load(\"conanbuild.ps1\")\n    assert \"conanbuildenv.ps1\" in build\n\n    with open(os.path.join(client.current_folder, \"conanrunenv.ps1\"), \"r\", encoding=\"utf-16\") as f:\n        run_contents = f.read()\n    assert '$env:MYVAR1=\"some nice content`\" with quotes\"' in run_contents\n\n    client.run(\"create .\")\n    assert \"MYPATH1=c:/path/to/ar\" in client.out\n    assert 'MYVAR1=some nice content\" with quotes' in client.out\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows powershell\")\n@pytest.mark.parametrize(\"powershell\", [True, \"powershell.exe\", \"pwsh\"])\ndef test_virtualenv_test_package(powershell):\n    \"\"\" The test_package could crash if not cleaning correctly the test_package\n    output folder. This will still crassh if the layout is not creating different build folders\n    https://github.com/conan-io/conan/issues/12764\n    \"\"\"\n    client = TestClient()\n    test_package = textwrap.dedent(r\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import save\n        class Test(ConanFile):\n            def requirements(self):\n                self.requires(self.tested_reference_str)\n            def generate(self):\n                # Emulates vcvars.bat behavior\n                save(self, \"myenv.bat\", \"echo MYENV!!!\\nset MYVC_CUSTOMVAR1=PATATA1\")\n                self.env_scripts.setdefault(\"build\", []).append(\"myenv.bat\")\n                save(self, \"myps.ps1\", \"echo MYPS1!!!!\\n$env:MYVC_CUSTOMVAR2=\\\"PATATA2\\\"\")\n                self.env_scripts.setdefault(\"build\", []).append(\"myps.ps1\")\n            def layout(self):\n                self.folders.build = \"mybuild\"\n                self.folders.generators = \"mybuild\"\n            def test(self):\n                self.run('mkdir \"hello world\"')\n                self.run(\"dir\")\n                self.run('cd \"hello world\"')\n                self.run(\"set MYVC_CUSTOMVAR1\")\n                self.run(\"set MYVC_CUSTOMVAR2\")\n            \"\"\")\n    client.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\"),\n                 \"test_package/conanfile.py\": test_package})\n    client.run(\"create .\")\n    assert \"hello world\" in client.out\n    assert \"MYENV!!!\" in client.out\n    assert \"MYPS1!!!!\" in client.out\n    assert \"MYVC_CUSTOMVAR1=PATATA1\" in client.out\n    assert \"MYVC_CUSTOMVAR2=PATATA2\" in client.out\n    # This was crashing because the .ps1 of test_package was not being cleaned\n    client.run(f\"create . -c tools.env.virtualenv:powershell={powershell}\")\n    assert \"hello world\" in client.out\n    assert \"MYENV!!!\" in client.out\n    assert \"MYPS1!!!!\" in client.out\n    assert \"MYVC_CUSTOMVAR1=PATATA1\" in client.out\n    assert \"MYVC_CUSTOMVAR2=PATATA2\" in client.out\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows powershell\")\n@pytest.mark.parametrize(\"powershell\", [True, \"powershell.exe\", \"pwsh\"])\ndef test_vcvars(powershell):\n    client = TestClient()\n    conanfile = textwrap.dedent(r\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake, cmake_layout, CMakeToolchain, CMakeDeps\n        from conan.tools.env import VirtualBuildEnv\n\n        class Conan(ConanFile):\n           settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n           generators = 'CMakeDeps', 'CMakeToolchain'\n\n           def layout(self):\n              cmake_layout(self)\n\n           def build(self):\n              cmake = CMake(self)\n              cmake.configure()\n              cmake.build()\n    \"\"\")\n    hello_cpp = gen_function_cpp(name=\"main\")\n    cmakelists = gen_cmakelists(appname=\"hello\", appsources=[\"hello.cpp\"])\n    client.save({\"conanfile.py\": conanfile, \"hello.cpp\": hello_cpp, \"CMakeLists.txt\": cmakelists})\n    powershell_exe = \"powershell.exe\" if powershell == \"powershell\" else \"pwsh\"\n    client.run(f\"build . -c tools.env.virtualenv:powershell={powershell} -c tools.cmake.cmaketoolchain:generator=Ninja\")\n    client.run_command(rf'{powershell_exe} -Command \".\\build\\Release\\generators\\conanbuild.ps1; dir env:\"')\n    #check the conanbuid.ps1 activation message\n    assert \"conanvcvars.ps1: Activated environment\" in client.out\n    #check that the new env variables are set\n    assert \"VSCMD_ARG_VCVARS_VER\" in client.out\n\n    client.run_command(rf'{powershell_exe} -Command \".\\build\\Release\\generators\\conanvcvars.ps1\"')\n    assert client.out.strip() == \"conanvcvars.ps1: Activated environment\"\n\n    conanbuild = client.load(r\".\\build\\Release\\generators\\conanbuild.ps1\")\n    vcvars_ps1 = client.load(r\".\\build\\Release\\generators\\conanvcvars.ps1\")\n    #check that the conanvcvars.ps1 is being added to the conanbuild.ps1\n    assert \"conanvcvars.ps1\" in conanbuild\n    #check that the conanvcvars.ps1 is setting the environment\n    assert \"conanvcvars.bat&set\" in vcvars_ps1\n\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Test for powershell\")\n@pytest.mark.parametrize(\"powershell\", [True, \"powershell.exe\", \"pwsh\", \"powershell.exe -NoProfile\", \"pwsh -NoProfile\"])\ndef test_concatenate_build_and_run_env(powershell):\n    # this tests that if we have both build and run env, they are concatenated correctly when using\n    # powershell\n    client = TestClient(path_with_spaces=True)\n    compiler_bat = \"@echo off\\necho MYTOOL {}!!\\n\"\n    conanfile = textwrap.dedent(\"\"\"\\\n        import os\n        from conan import ConanFile\n        from conan.tools.files import copy\n        class Pkg(ConanFile):\n            exports_sources = \"*\"\n            package_type = \"application\"\n            def package(self):\n                copy(self, \"*\", self.build_folder, os.path.join(self.package_folder, \"bin\"))\n        \"\"\")\n\n    num_deps = 2\n    for i in range(num_deps):\n        client.save({\"conanfile.py\": conanfile,\n                     \"mycompiler{}.bat\".format(i): compiler_bat.format(i)})\n        client.run(\"create . --name=pkg{} --version=0.1\".format(i))\n\n    conanfile = textwrap.dedent(\"\"\"\\\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            settings = \"os\"\n            tool_requires = \"pkg0/0.1\"\n            requires = \"pkg1/0.1\"\n            generators = \"VirtualBuildEnv\", \"VirtualRunEnv\"\n        \"\"\")\n\n    client.save({\"conanfile.py\": conanfile}, clean_first=True)\n    client.run(f'install . -c tools.env.virtualenv:powershell=\"{powershell}\"')\n    conanfile = ConanFileMock()\n    conanfile.conf.define(\"tools.env.virtualenv:powershell\", powershell)\n    cmd = environment_wrap_command(conanfile,[\"conanrunenv\", \"conanbuildenv\"],\n                                   client.current_folder,\"mycompiler0.bat\")\n    client.run_command(cmd)\n    assert \"MYTOOL 0!!\" in client.out\n\n    cmd = environment_wrap_command(conanfile,[\"conanrunenv\", \"conanbuildenv\"],\n                                   client.current_folder,\"mycompiler1.bat\")\n    client.run_command(cmd)\n    assert \"MYTOOL 1!!\" in client.out\n\n\n@pytest.mark.parametrize(\"powershell\", [None, True, False])\ndef test_powershell_deprecated_message(powershell):\n    client = TestClient(light=True)\n    conanfile = textwrap.dedent(\"\"\"\\\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            settings = \"os\"\n            name = \"pkg\"\n            version = \"0.1\"\n        \"\"\")\n\n    client.save({\"conanfile.py\": conanfile})\n    powershell_arg = f'-c tools.env.virtualenv:powershell={powershell}' if powershell is not None else \"\"\n    client.run(f'install . {powershell_arg}')\n    # only show message if the value is set to False or True if not set do not show message\n    if powershell is not None:\n        assert \"Boolean values for 'tools.env.virtualenv:powershell' are deprecated\" in client.out\n    else:\n        assert \"Boolean values for 'tools.env.virtualenv:powershell' are deprecated\" not in client.out\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Test for powershell\")\n@pytest.mark.parametrize(\"powershell\", [True, \"pwsh\", \"powershell.exe\"])\ndef test_powershell_quoting(powershell):\n    client = TestClient(path_with_spaces=False)\n    conanfile = textwrap.dedent(\"\"\"\\\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            settings = \"os\"\n            name = \"pkg\"\n            version = \"0.1\"\n            def build(self):\n                self.run('python -c \"print(\\\\'Hello World\\\\')\"', scope=\"build\")\n        \"\"\")\n\n    client.save({\"conanfile.py\": conanfile})\n    client.run(f'create . -c tools.env.virtualenv:powershell={powershell}')\n    assert \"Hello World\" in client.out\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows\")\ndef test_verbosity_flag():\n    tc = TestClient()\n    tc.run(\"new cmake_lib -d name=pkg -d version=1.0\")\n    tc.run('create . -tf=\"\" -c tools.build:verbosity=verbose '\n           '-c tools.env.virtualenv:powershell=powershell.exe')\n\n    assert \"/verbosity:Detailed\" in tc.out\n    assert \"-verbosity:Detailed\" not in tc.out\n"
  },
  {
    "path": "test/functional/toolchains/gnu/__init__.py",
    "content": ""
  },
  {
    "path": "test/functional/toolchains/gnu/autotools/__init__.py",
    "content": ""
  },
  {
    "path": "test/functional/toolchains/gnu/autotools/test_android.py",
    "content": "import os\nimport platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\nfrom test.conftest import tools_locations\n\n\n@pytest.mark.parametrize(\"arch, expected_arch\", [('armv8', 'aarch64'),\n                                                 ('armv7', 'arm'),\n                                                 ('x86', 'i386'),\n                                                 ('x86_64', 'x86_64')\n                                                 ])\n@pytest.mark.tool(\"android_ndk\")\n@pytest.mark.tool(\"autotools\")\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"NDK only installed on MAC\")\ndef test_android_autotools_toolchain_cross_compiling(arch, expected_arch):\n    profile_host = textwrap.dedent(\"\"\"\n    include(default)\n\n    [settings]\n    os = Android\n    os.api_level = 21\n    arch = {arch}\n\n    [conf]\n    tools.android:ndk_path={ndk_path}\n    \"\"\")\n    ndk_path = tools_locations[\"android_ndk\"][\"system\"][\"path\"][platform.system()]\n    profile_host = profile_host.format(\n        arch=arch,\n        ndk_path=ndk_path\n    )\n\n    client = TestClient(path_with_spaces=False)\n    client.run(\"new autotools_lib -d name=hello -d version=1.0\")\n    client.save({\"profile_host\": profile_host})\n    client.run(\"build . --profile:build=default --profile:host=profile_host\")\n    libhello = os.path.join(\"build-release\", \"src\", \".libs\", \"libhello.a\")\n    # Check binaries architecture\n    client.run_command('objdump -f \"%s\"' % libhello)\n    assert \"architecture: %s\" % expected_arch in client.out\n"
  },
  {
    "path": "test/functional/toolchains/gnu/autotools/test_apple_toolchain.py",
    "content": "import os\nimport platform\nimport textwrap\n\nimport pytest\n\nfrom conan.tools.apple.apple import _to_apple_arch\nfrom conan.test.assets.autotools import gen_makefile\nfrom conan.test.assets.sources import gen_function_h, gen_function_cpp\nfrom conan.test.utils.tools import TestClient\n\nmakefile = gen_makefile(apps=[\"app\"], libs=[\"hello\"])\n\nconanfile_py = textwrap.dedent(\"\"\"\n    from conan import ConanFile, tools\n    from conan.tools.gnu import Autotools\n\n    class App(ConanFile):\n        settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n        options = {\"shared\": [True, False], \"fPIC\": [True, False]}\n        default_options = {\"shared\": False, \"fPIC\": True}\n        generators = \"AutotoolsToolchain\"\n\n        def config_options(self):\n            if self.settings.os == \"Windows\":\n                self.options.rm_safe(\"fPIC\")\n\n        def configure(self):\n            if self.options.shared:\n                self.options.rm_safe(\"fPIC\")\n\n        def build(self):\n            env_build = Autotools(self)\n            env_build.make()\n    \"\"\")\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only OSX\")\n@pytest.mark.parametrize(\"config\", [(\"x86_64\", \"Macos\", \"10.14\", None),\n                                    (\"armv8\", \"iOS\", \"10.0\", \"iphoneos\"),\n                                    (\"x86_64\", \"iOS\", \"10.0\", \"iphonesimulator\"),\n                                    (\"armv8\", \"Macos\", \"10.14\", None)  # M1\n                                    ])\ndef test_makefile_arch(config):\n    arch, os_, os_version, os_sdk = config\n\n    profile = textwrap.dedent(\"\"\"\n                include(default)\n                [settings]\n                os = {os}\n                {os_sdk}\n                os.version = {os_version}\n                arch = {arch}\n                \"\"\").format(os=os_, arch=arch,\n                            os_version=os_version, os_sdk=\"os.sdk = \" + os_sdk if os_sdk else \"\")\n\n    t = TestClient()\n    hello_h = gen_function_h(name=\"hello\")\n    hello_cpp = gen_function_cpp(name=\"hello\")\n    main_cpp = gen_function_cpp(name=\"main\", includes=[\"hello\"], calls=[\"hello\"])\n\n    t.save({\"Makefile\": makefile,\n            \"hello.h\": hello_h,\n            \"hello.cpp\": hello_cpp,\n            \"app.cpp\": main_cpp,\n            \"conanfile.py\": conanfile_py,\n            \"profile\": profile})\n\n    t.run(\"install . --profile:host=profile --profile:build=default\")\n    t.run(\"build . --profile:host=profile --profile:build=default\")\n\n    libhello = os.path.join(t.current_folder, \"libhello.a\")\n    app = os.path.join(t.current_folder, \"app\")\n    assert os.path.isfile(libhello)\n    assert os.path.isfile(app)\n\n    expected_arch = _to_apple_arch(arch)\n\n    t.run_command('lipo -info \"%s\"' % libhello)\n    assert \"architecture: %s\" % expected_arch in t.out\n\n    t.run_command('lipo -info \"%s\"' % app)\n    assert \"architecture: %s\" % expected_arch in t.out\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only OSX\")\n@pytest.mark.parametrize(\"arch\", [\"x86_64\", \"armv8\"])\ndef test_catalyst(arch):\n    profile = textwrap.dedent(\"\"\"\n        include(default)\n        [settings]\n        os = Macos\n        os.version = 14.6\n        os.subsystem = catalyst\n        os.subsystem.ios_version = 16.1\n        arch = {arch}\n        [buildenv]\n        DEVELOPER_DIR=/Applications/Xcode_16.0.app/Contents/Developer\n        \"\"\").format(arch=arch)\n\n    t = TestClient()\n    hello_h = gen_function_h(name=\"hello\")\n    hello_cpp = gen_function_cpp(name=\"hello\")\n    main_cpp = textwrap.dedent(\"\"\"\n        #include \"hello.h\"\n        #include <TargetConditionals.h>\n        #include <iostream>\n\n        int main()\n        {\n        #if TARGET_OS_MACCATALYST\n            std::cout << \"running catalyst \" << __IPHONE_OS_VERSION_MIN_REQUIRED << std::endl;\n        #else\n            #error \"not building for Apple Catalyst\"\n        #endif\n        }\n        \"\"\")\n\n    t.save({\"Makefile\": makefile,\n            \"hello.h\": hello_h,\n            \"hello.cpp\": hello_cpp,\n            \"app.cpp\": main_cpp,\n            \"conanfile.py\": conanfile_py,\n            \"profile\": profile})\n\n    t.run(\"install . --profile:host=profile --profile:build=default\")\n    t.run(\"build . --profile:host=profile --profile:build=default\")\n\n    libhello = os.path.join(t.current_folder, \"libhello.a\")\n    app = os.path.join(t.current_folder, \"app\")\n    assert os.path.isfile(libhello)\n    assert os.path.isfile(app)\n\n    expected_arch = _to_apple_arch(arch)\n\n    t.run_command('lipo -info \"%s\"' % libhello)\n    assert \"architecture: %s\" % expected_arch in t.out\n\n    t.run_command('lipo -info \"%s\"' % app)\n    assert \"architecture: %s\" % expected_arch in t.out\n\n    #FIXME: recover when ci is fixed for M2\n    #t.run_command('\"%s\"' % app)\n    #assert \"running catalyst 160100\" in t.out\n"
  },
  {
    "path": "test/functional/toolchains/gnu/autotools/test_basic.py",
    "content": "import os\nimport platform\nimport textwrap\nimport time\nimport re\n\nimport pytest\n\nfrom conan.test.utils.mocks import ConanFileMock\nfrom conan.tools.env.environment import environment_wrap_command\nfrom conan.test.assets.autotools import gen_makefile_am, gen_configure_ac, gen_makefile\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.assets.sources import gen_function_cpp\nfrom test.functional.utils import check_exe_run, check_vs_runtime\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.skipif(platform.system() not in [\"Linux\", \"Darwin\"], reason=\"Requires Autotools\")\n@pytest.mark.tool(\"autotools\")\ndef test_autotools(matrix_client_nospace):\n    client = matrix_client_nospace\n\n    main = gen_function_cpp(name=\"main\", includes=[\"matrix\"], calls=[\"matrix\"])\n    makefile_am = gen_makefile_am(main=\"main\", main_srcs=\"main.cpp\")\n    configure_ac = gen_configure_ac()\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.gnu import Autotools\n\n        class TestConan(ConanFile):\n            requires = \"matrix/1.0\"\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            exports_sources = \"configure.ac\", \"Makefile.am\", \"main.cpp\"\n            generators = \"AutotoolsDeps\", \"AutotoolsToolchain\"\n\n            def build(self):\n                self.run(\"aclocal\")\n                self.run(\"autoconf\")\n                self.run(\"automake --add-missing --foreign\")\n                autotools = Autotools(self)\n                autotools.configure()\n                autotools.make()\n        \"\"\")\n\n    client.save({\"conanfile.py\": conanfile,\n                 \"configure.ac\": configure_ac,\n                 \"Makefile.am\": makefile_am,\n                 \"main.cpp\": main}, clean_first=True)\n\n    client.run(\"build .\")\n    client.run_command(\"./main\")\n    cxx11_abi = 1 if platform.system() == \"Linux\" else None\n    compiler = \"gcc\" if platform.system() == \"Linux\" else \"apple-clang\"\n    host_arch = client.get_default_host_profile().settings['arch']\n    check_exe_run(client.out, \"main\", compiler, None, \"Release\", host_arch, None, cxx11_abi=cxx11_abi)\n    assert \"matrix/1.0: Hello World Release!\" in client.out\n\n\ndef build_windows_subsystem(profile, make_program, subsystem):\n    \"\"\" The AutotoolsDeps can be used also in pure Makefiles, if the makefiles follow\n    the Autotools conventions\n\n    This doesn't run in bash at all, not win_bash, pure Windows terminal\n    \"\"\"\n    # FIXME: cygwin in CI (my local machine works) seems broken for path with spaces\n    client = TestClient(path_with_spaces=False)\n    client.run(\"new cmake_lib -d name=hello -d version=0.1\")\n    # TODO: Test Windows subsystems in CMake, at least msys is broken\n    os.rename(os.path.join(client.current_folder, \"test_package\"),\n              os.path.join(client.current_folder, \"test_package2\"))\n    client.save({\"profile\": profile})\n    client.run(\"create . --profile=profile\")\n\n    main = gen_function_cpp(name=\"main\", includes=[\"hello\"], calls=[\"hello\"])\n    makefile = gen_makefile(apps=[\"app\"])\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.gnu import AutotoolsToolchain, Autotools, AutotoolsDeps\n\n        class TestConan(ConanFile):\n            requires = \"hello/0.1\"\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            exports_sources = \"Makefile\"\n            generators = \"AutotoolsDeps\", \"AutotoolsToolchain\"\n\n            def build(self):\n                autotools = Autotools(self)\n                autotools.make()\n        \"\"\")\n    client.save({\"app.cpp\": main,\n                 \"Makefile\": makefile,\n                 \"conanfile.py\": conanfile,\n                 \"profile\": profile}, clean_first=True)\n\n    client.run(\"install . --profile=profile\")\n    cmd = environment_wrap_command(ConanFileMock(), [\"conanbuildenv\",\n                                    \"conanautotoolstoolchain\",\n                                    \"conanautotoolsdeps\"], client.current_folder, make_program)\n    client.run_command(cmd)\n    client.run_command(\"app\")\n    # TODO: fill compiler version when ready\n    check_exe_run(client.out, \"main\", \"gcc\", None, \"Release\", \"x86_64\", None, subsystem=subsystem)\n    assert \"hello/0.1: Hello World Release!\" in client.out\n    check_vs_runtime(\"app.exe\", client, vs_version=\"15\", build_type=\"Release\", architecture=\"amd64\",\n                     static_runtime=False, subsystem=subsystem)\n\n    client.save({\"app.cpp\": gen_function_cpp(name=\"main\", msg=\"main2\",\n                                             includes=[\"hello\"], calls=[\"hello\"])})\n    # Make sure it is newer\n    t = time.time() + 1\n    os.utime(os.path.join(client.current_folder, \"app.cpp\"), (t, t))\n\n    client.run(\"build . --profile=profile\")\n    client.run_command(\"app\")\n    # TODO: fill compiler version when ready\n    check_exe_run(client.out, \"main2\", \"gcc\", None, \"Release\", \"x86_64\", None, cxx11_abi=0,\n                  subsystem=subsystem)\n    assert \"hello/0.1: Hello World Release!\" in client.out\n    return client.out\n\n\n@pytest.mark.tool(\"cygwin\")\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Needs windows\")\ndef test_autotoolsdeps_cygwin():\n    # TODO: This test seems broken locally, need to really verify is passing in CI\n    gcc = textwrap.dedent(\"\"\"\n        [settings]\n        os=Windows\n        os.subsystem=cygwin\n        compiler=gcc\n        compiler.version=4.9\n        compiler.libcxx=libstdc++\n        arch=x86_64\n        build_type=Release\n        \"\"\")\n    build_windows_subsystem(gcc, make_program=\"make\", subsystem=\"cygwin\")\n\n\n@pytest.mark.tool(\"mingw64\")\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Needs windows\")\ndef test_autotoolsdeps_mingw_msys():\n    # FIXME: Missing subsystem to model mingw libstdc++\n    gcc = textwrap.dedent(\"\"\"\n        [settings]\n        os=Windows\n        compiler=gcc\n        compiler.version=4.9\n        compiler.libcxx=libstdc++\n        arch=x86_64\n        build_type=Release\n        \"\"\")\n    build_windows_subsystem(gcc, make_program=\"mingw32-make\", subsystem=\"mingw64\")\n\n\n@pytest.mark.tool(\"msys2\")\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Needs windows\")\n# If we use the cmake inside msys2, it fails, so better force our own cmake\n@pytest.mark.tool(\"cmake\", \"3.19\")\ndef test_autotoolsdeps_msys():\n    gcc = textwrap.dedent(\"\"\"\n        [settings]\n        os=Windows\n        os.subsystem=msys2\n        compiler=gcc\n        compiler.version=4.9\n        compiler.libcxx=libstdc++\n        arch=x86_64\n        build_type=Release\n        \"\"\")\n    build_windows_subsystem(gcc, make_program=\"make\", subsystem=\"msys2\")\n\n\n@pytest.mark.skipif(platform.system() not in [\"Linux\", \"Darwin\"], reason=\"Requires Autotools\")\n@pytest.mark.tool(\"autotools\")\ndef test_install_output_directories(matrix_client_nospace):\n    \"\"\"\n    If we change the libdirs of the cpp.package, as we are doing cmake.install, the output directory\n    for the libraries is changed\n    \"\"\"\n    client = matrix_client_nospace\n    consumer_conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.gnu import Autotools\n\n        class TestConan(ConanFile):\n            requires = \"matrix/1.0\"\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            exports_sources = \"configure.ac\", \"Makefile.am\", \"main.cpp\", \"consumer.h\"\n            generators = \"AutotoolsDeps\", \"AutotoolsToolchain\"\n\n            def layout(self):\n                self.folders.build = \".\"\n                self.cpp.package.bindirs = [\"mybin\"]\n\n            def build(self):\n                self.run(\"aclocal\")\n                self.run(\"autoconf\")\n                self.run(\"automake --add-missing --foreign\")\n                autotools = Autotools(self)\n                autotools.configure()\n                autotools.make()\n                autotools.install()\n    \"\"\")\n\n    main = gen_function_cpp(name=\"main\", includes=[\"matrix\"], calls=[\"matrix\"])\n    makefile_am = gen_makefile_am(main=\"main\", main_srcs=\"main.cpp\")\n    configure_ac = gen_configure_ac()\n    client.save({\"conanfile.py\": consumer_conanfile,\n                 \"configure.ac\": configure_ac,\n                 \"Makefile.am\": makefile_am,\n                 \"main.cpp\": main}, clean_first=True)\n    client.run(\"create . --name=zlib --version=1.2.11\")\n    p_folder = client.created_layout().package()\n    assert os.path.exists(os.path.join(p_folder, \"mybin\", \"main\"))\n    assert not os.path.exists(os.path.join(p_folder, \"bin\"))\n\n\n@pytest.mark.skipif(platform.system() not in [\"Linux\", \"Darwin\"], reason=\"Requires Autotools\")\n@pytest.mark.tool(\"autotools\")\ndef test_autotools_with_pkgconfigdeps():\n    client = TestClient(path_with_spaces=False)\n    client.run(\"new cmake_lib -d name=hello -d version=1.0\")\n    client.run(\"create .\")\n\n    consumer_conanfile = textwrap.dedent(\"\"\"\n        [requires]\n        hello/1.0\n        [generators]\n        AutotoolsToolchain\n        PkgConfigDeps\n    \"\"\")\n    client.save({\"conanfile.txt\": consumer_conanfile}, clean_first=True)\n    client.run(\"install .\")\n\n    client.run_command(\". ./conanautotoolstoolchain.sh && \"\n                       \"pkg-config --cflags hello && \"\n                       \"pkg-config --libs-only-l hello && \"\n                       \"pkg-config --libs-only-L --libs-only-other hello\")\n\n    assert re.search(\"I.*/p/include\", str(client.out))\n    assert \"-lhello\" in client.out\n    assert re.search(\"L.*/p/lib\", str(client.out))\n\n\n@pytest.mark.skipif(platform.system() not in [\"Linux\", \"Darwin\"], reason=\"Requires Autotools\")\n@pytest.mark.tool(\"autotools\")\ndef test_autotools_option_checking():\n    # https://github.com/conan-io/conan/issues/11265\n    client = TestClient(path_with_spaces=False)\n    client.run(\"new autotools_lib -d name=mylib -d version=1.0\")\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n\n        from conan import ConanFile\n        from conan.tools.gnu import AutotoolsToolchain, Autotools\n        from conan.tools.layout import basic_layout\n        from conan.tools.build import cross_building\n\n\n        class MylibTestConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"AutotoolsDeps\"\n\n            def requirements(self):\n                self.requires(self.tested_reference_str)\n\n            def generate(self):\n                at_toolchain = AutotoolsToolchain(self)\n                # we override the default shared/static flags here\n                at_toolchain.configure_args = ['--enable-option-checking=fatal']\n                at_toolchain.generate()\n\n            def build(self):\n                autotools = Autotools(self)\n                autotools.autoreconf()\n                autotools.configure()\n                autotools.make()\n\n            def layout(self):\n                basic_layout(self)\n\n            def test(self):\n                if not cross_building(self):\n                    cmd = os.path.join(self.cpp.build.bindirs[0], \"main\")\n                    self.run(cmd, env=\"conanrun\")\n            \"\"\")\n\n    client.save({\"test_package/conanfile.py\": conanfile})\n    client.run(\"create . -tf=\\\"\\\"\")\n\n    # check that the shared flags are not added to the exe's configure, making it fail\n    client.run(\"test test_package mylib/1.0@\")\n    assert \"configure: error: unrecognized options: --disable-shared, --enable-static, --with-pic\" \\\n           not in client.out\n\n\n@pytest.mark.skipif(platform.system() not in [\"Linux\", \"Darwin\"], reason=\"Requires Autotools\")\n@pytest.mark.tool(\"autotools\")\ndef test_autotools_arguments_override():\n    client = TestClient(path_with_spaces=False)\n    client.run(\"new autotools_lib -d name=mylib -d version=1.0\")\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n\n        from conan import ConanFile\n        from conan.tools.gnu import AutotoolsToolchain, Autotools\n        from conan.tools.layout import basic_layout\n\n\n        class MyLibConan(ConanFile):\n            name = \"mylib\"\n            version = \"1.0\"\n\n            # Binary configuration\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n            exports_sources = \"configure.ac\", \"Makefile.am\", \"src/*\"\n\n            def config_options(self):\n                if self.settings.os == \"Windows\":\n                    self.options.rm_safe(\"fPIC\")\n\n            def layout(self):\n                basic_layout(self)\n\n            def generate(self):\n                at_toolchain = AutotoolsToolchain(self)\n                at_toolchain.configure_args = ['--disable-shared']\n                at_toolchain.make_args = ['--warn-undefined-variables']\n                at_toolchain.autoreconf_args = ['--verbose']\n                at_toolchain.generate()\n\n            def build(self):\n                autotools = Autotools(self)\n                autotools.autoreconf(args=['--install'])\n                autotools.configure(args=['--prefix=/', '--libdir=${prefix}/customlibfolder',\n                                          '--includedir=${prefix}/customincludefolder',\n                                          '--pdfdir=${prefix}/res'])\n                autotools.make(args=['--keep-going'])\n\n            def package(self):\n                autotools = Autotools(self)\n                autotools.install(args=['DESTDIR={}/somefolder'.format(self.package_folder)])\n\n            def package_info(self):\n                self.cpp_info.libs = [\"mylib\"]\n                self.cpp_info.libdirs = [\"somefolder/customlibfolder\"]\n                self.cpp_info.includedirs = [\"somefolder/customincludefolder\"]\n        \"\"\")\n\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . -tf=\\\"\\\"\")\n\n    # autoreconf args --force that is default should not be there\n    assert \"--force\" not in client.out\n    assert \"--install\" in client.out\n\n    # we override the default DESTDIR in the install\n    assert re.search(\"^.*make install .*DESTDIR=(.*)/somefolder.*$\", str(client.out), re.MULTILINE)\n\n    # we did override the default install args\n    for arg in ['--bindir=${prefix}/bin', '--sbindir=${prefix}/bin',\n                '--libdir=${prefix}/lib', '--includedir=${prefix}/include',\n                '--oldincludedir=${prefix}/include', '--datarootdir=${prefix}/res']:\n        assert arg not in client.out\n\n    # and use our custom arguments\n    for arg in ['--prefix=/', '--libdir=${prefix}/customlibfolder',\n                '--includedir=${prefix}/customincludefolder', '--pdfdir=${prefix}/res']:\n        assert arg in client.out\n\n    # check the other arguments we set are there\n    assert \"--disable-shared\" in client.out\n    assert \"--warn-undefined-variables\" in client.out\n    assert \"--verbose\" in client.out\n    assert \"--keep-going\" in client.out\n\n    client.run(\"test test_package mylib/1.0@\")\n    assert \"mylib/1.0: Hello World Release!\" in client.out\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Only MSVC\")\ndef test_msvc_extra_flag():\n    profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=Windows\n        compiler=msvc\n        compiler.version=193\n        compiler.runtime=dynamic\n        arch=x86_64\n        build_type=Release\n        \"\"\")\n    client = TestClient()\n    conanfile = GenConanfile().with_settings(\"os\", \"arch\", \"compiler\", \"build_type\")\\\n        .with_generator(\"AutotoolsToolchain\")\n    client.save({\"conanfile.py\": conanfile,\n                \"profile\": profile})\n    client.run(\"install . --profile:build=profile --profile:host=profile\")\n    toolchain = client.load(\"conanautotoolstoolchain{}\".format('.bat'))\n    assert 'set \"CXXFLAGS=%CXXFLAGS% -MD -O2 -Ob2 -FS\"' in toolchain\n    assert 'set \"CFLAGS=%CFLAGS% -MD -O2 -Ob2 -FS\"' in toolchain\n\n    # now verify not duplicated\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.gnu import AutotoolsToolchain\n        class Pkg(ConanFile):\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            def generate(self):\n                tc = AutotoolsToolchain(self)\n                tc.extra_cxxflags.append(\"-FS\")\n                tc.extra_cflags.append(\"-FS\")\n                tc.generate()\n                \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"install . --profile:build=profile --profile:host=profile\")\n    toolchain = client.load(\"conanautotoolstoolchain{}\".format('.bat'))\n    assert 'set \"CXXFLAGS=%CXXFLAGS% -MD -O2 -Ob2 -FS\"' in toolchain\n    assert 'set \"CFLAGS=%CFLAGS% -MD -O2 -Ob2 -FS\"' in toolchain\n"
  },
  {
    "path": "test/functional/toolchains/gnu/autotools/test_crossbuild_triplet.py",
    "content": "import platform\nimport pytest\nimport textwrap\n\nfrom conan.test.utils.tools import TestClient\n\n@pytest.mark.skipif(platform.system() not in  [\"Darwin\", \"Linux\"], reason=\"Autotools on Linux or macOS\")\ndef test_crossbuild_triplet_from_conf():\n\n    settings_yml = textwrap.dedent(\"\"\"\n        os:\n            Linux:\n            Windows:\n        arch: [x86_64, hexagon]\n        compiler:\n            gcc:\n                version: [\"10\", \"11\"]\n                libcxx: [libstdc++11]\n        build_type: [None, Debug, Release]\n        \"\"\")\n\n    host_profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=Linux\n        arch=hexagon\n        compiler=gcc\n        compiler.version=10\n        compiler.libcxx=libstdc++11\n        build_type=Release\n        [conf]\n        tools.gnu:host_triplet=hexagon-acme-linux-gnu\n    \"\"\")\n\n    build_profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=Linux\n        arch=x86_64\n        compiler=gcc\n        compiler.version=11\n        compiler.libcxx=libstdc++11\n        build_type=Release\n    \"\"\")\n\n    client = TestClient(path_with_spaces=False)\n    client.save({client.paths.settings_path: settings_yml})\n    client.save({\"host_profile\": host_profile})\n    client.save({\"build_profile\": build_profile})\n\n    client.run(\"new autotools_lib -d name=hello -d version=0.1\")\n    client.run(\"create . --profile:build=build_profile --profile:host=host_profile -tf=\\\"\\\"\")\n\n    assert \"--host=hexagon-acme-linux-gnu\" in client.out\n    assert \"checking host system type... hexagon-acme-linux-gnu\" in client.out\n"
  },
  {
    "path": "test/functional/toolchains/gnu/autotools/test_ios.py",
    "content": "import platform\nimport textwrap\n\nimport pytest\n\nfrom conan.tools.build import load_toolchain_args\nfrom conan.test.assets.autotools import gen_makefile_am, gen_configure_ac\nfrom conan.test.assets.sources import gen_function_cpp\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Requires Xcode\")\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.tool(\"autotools\")\ndef test_ios():\n    profile = textwrap.dedent(\"\"\"\n        include(default)\n        [settings]\n        os=iOS\n        os.sdk=iphoneos\n        os.version=12.0\n        arch=armv8\n        \"\"\")\n\n    client = TestClient(path_with_spaces=False)\n    client.save({\"ios-armv8\": profile}, clean_first=True)\n    client.run(\"new cmake_lib -d name=hello -d version=0.1\")\n    client.run(\"create . --profile:build=default --profile:host=ios-armv8 -tf=\\\"\\\"\")\n\n    main = gen_function_cpp(name=\"main\", includes=[\"hello\"], calls=[\"hello\"])\n    makefile_am = gen_makefile_am(main=\"main\", main_srcs=\"main.cpp\")\n    configure_ac = gen_configure_ac()\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.gnu import Autotools\n\n        class TestConan(ConanFile):\n            requires = \"hello/0.1\"\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            exports_sources = \"configure.ac\", \"Makefile.am\", \"main.cpp\"\n            generators = \"AutotoolsToolchain\", \"AutotoolsDeps\"\n\n            def layout(self):\n                self.cpp.package.resdirs = [\"res\"]\n\n            def build(self):\n                autotools = Autotools(self)\n                autotools.autoreconf()\n                autotools.configure()\n                autotools.make()\n\n        \"\"\")\n\n    client.save({\"conanfile.py\": conanfile,\n                 \"configure.ac\": configure_ac,\n                 \"Makefile.am\": makefile_am,\n                 \"main.cpp\": main,\n                 \"ios-armv8\": profile}, clean_first=True)\n    client.run(\"build . --profile:build=default --profile:host=ios-armv8\")\n    client.run_command(\"lipo -info main\")\n    assert \"Non-fat file: main is architecture: arm64\" in client.out\n\n    client.run_command(\"vtool -show-build main\")\n    assert \"platform IOS\" in client.out\n    assert \"minos 12.0\" in client.out\n\n    conanbuild = load_toolchain_args(client.current_folder)\n    configure_args = conanbuild[\"configure_args\"]\n    make_args = conanbuild[\"make_args\"]\n    autoreconf_args = conanbuild[\"autoreconf_args\"]\n    build_arch = client.api.profiles.get_profile([client.api.profiles.get_default_build()]).settings['arch']\n    build_arch = \"aarch64\" if build_arch == \"armv8\" else build_arch\n    assert configure_args == \"--prefix=/ '--bindir=${prefix}/bin' '--sbindir=${prefix}/bin' \" \\\n                             \"'--libdir=${prefix}/lib' '--includedir=${prefix}/include' \" \\\n                             \"'--oldincludedir=${prefix}/include' '--datarootdir=${prefix}/res' \" \\\n                             f\"--host=aarch64-apple-ios --build={build_arch}-apple-darwin\"\n    assert make_args == \"\"\n    assert autoreconf_args == \"--force --install\"\n"
  },
  {
    "path": "test/functional/toolchains/gnu/autotools/test_win_bash.py",
    "content": "import platform\nimport textwrap\nimport os\n\nimport pytest\n\nfrom conan.test.assets.autotools import gen_makefile_am, gen_configure_ac, gen_makefile\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.assets.sources import gen_function_cpp\nfrom test.conftest import tools_locations\nfrom test.functional.utils import check_exe_run, check_vs_runtime\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows\")\n@pytest.mark.tool(\"msys2\")\ndef test_autotools_bash_complete():\n    client = TestClient(path_with_spaces=False)\n    profile_win = textwrap.dedent(f\"\"\"\n        include(default)\n        [conf]\n        tools.microsoft.bash:subsystem=msys2\n        tools.microsoft.bash:path=bash\n        \"\"\")\n\n    main = gen_function_cpp(name=\"main\")\n    # The autotools support for \"cl\" compiler (VS) is very limited, linking with deps doesn't\n    # work but building a simple app do\n    makefile_am = gen_makefile_am(main=\"main\", main_srcs=\"main.cpp\")\n    configure_ac = gen_configure_ac()\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.gnu import Autotools\n\n        class TestConan(ConanFile):\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            exports_sources = \"configure.ac\", \"Makefile.am\", \"main.cpp\"\n            generators = \"AutotoolsToolchain\"\n            win_bash = True\n\n            def build(self):\n                # These commands will run in bash activating first the vcvars and\n                # then inside the bash activating the\n                self.run(\"aclocal\")\n                self.run(\"autoconf\")\n                self.run(\"automake --add-missing --foreign\")\n                autotools = Autotools(self)\n                autotools.configure()\n                autotools.make()\n                autotools.install()\n        \"\"\")\n\n    client.save({\"conanfile.py\": conanfile,\n                 \"configure.ac\": configure_ac,\n                 \"Makefile.am\": makefile_am,\n                 \"main.cpp\": main,\n                 \"profile_win\": profile_win})\n    client.run(\"build . -pr=profile_win\")\n    client.run_command(\"main.exe\")\n    check_exe_run(client.out, \"main\", \"msvc\", None, \"Release\", \"x86_64\", None)\n\n    bat_contents = client.load(\"conanbuild.bat\")\n    assert \"conanvcvars.bat\" in bat_contents\n\n\n@pytest.mark.slow\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows\")\n@pytest.mark.tool(\"msys2\")\n@pytest.mark.tool(\"clang\", \"20\")\n@pytest.mark.parametrize(\"frontend\", (\"clang\", \"clang-cl\"))\n@pytest.mark.parametrize(\"runtime\", (\"static\", \"dynamic\"))\n@pytest.mark.parametrize(\"build_type\", (\"Debug\", \"Release\"))\ndef test_autotools_bash_complete_clang(frontend, runtime, build_type):\n    client = TestClient(path_with_spaces=False)\n    # Problem is that msys2 also has clang in the path, so we need to make it explicit\n    clangpath = tools_locations[\"clang\"][\"20\"][\"path\"][\"Windows\"]\n    # compilers\n    c, cpp = (\"clang\", \"clang++\") if frontend == \"clang\" else (\"clang-cl\", \"clang-cl\")\n    comps = f'{{\"cpp\":\"{cpp}\", \"c\":\"{c}\", \"rc\":\"{c}\"}}'\n    profile_win = textwrap.dedent(f\"\"\"\n        [settings]\n        os=Windows\n        arch=x86_64\n        build_type={build_type}\n        compiler=clang\n        compiler.version=20\n        compiler.cppstd=14\n        compiler.runtime_version=v144\n        compiler.runtime={runtime}\n\n        [conf]\n        tools.build:compiler_executables={comps}\n        tools.microsoft.bash:subsystem=msys2\n        tools.microsoft.bash:path=bash\n        tools.compilation:verbosity=verbose\n\n        [buildenv]\n        PATH=+(path){clangpath}\n        \"\"\")\n\n    main = gen_function_cpp(name=\"main\")\n    # The autotools support for \"cl\" compiler (VS) is very limited, linking with deps doesn't\n    # work but building a simple app do\n    makefile_am = gen_makefile_am(main=\"main\", main_srcs=\"main.cpp\")\n    configure_ac = gen_configure_ac()\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.gnu import Autotools\n\n        class TestConan(ConanFile):\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            exports_sources = \"configure.ac\", \"Makefile.am\", \"main.cpp\"\n            generators = \"AutotoolsToolchain\"\n            win_bash = True\n\n            def build(self):\n                # These commands will run in bash activating first the vcvars and\n                # then inside the bash activating the\n                self.run(\"aclocal\")\n                self.run(\"autoconf\")\n                self.run(\"automake --add-missing --foreign\")\n                autotools = Autotools(self)\n                autotools.configure()\n                autotools.make()\n                autotools.install()\n        \"\"\")\n\n    client.save({\"conanfile.py\": conanfile,\n                 \"configure.ac\": configure_ac,\n                 \"Makefile.am\": makefile_am,\n                 \"main.cpp\": main,\n                 \"profile_win\": profile_win})\n    client.run(\"build . -pr=profile_win\")\n    client.run_command(\"main.exe\")\n    assert \"__GNUC__\" not in client.out\n    assert \"main __clang_major__20\" in client.out\n    check_exe_run(client.out, \"main\", \"clang\", None, build_type, \"x86_64\", None)\n\n    bat_contents = client.load(\"conanbuild.bat\")\n    assert \"conanvcvars.bat\" in bat_contents\n\n    static_runtime = runtime == \"static\"\n    check_vs_runtime(\"main.exe\", client, \"17\", build_type=build_type, static_runtime=static_runtime)\n\n\n@pytest.mark.parametrize(\"scope\", [\"build\", \"run\"])\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows\")\ndef test_add_msys2_path_automatically(scope):\n    \"\"\" Check that commands like ar, autoconf, etc, that are in the /usr/bin folder together\n    with the bash.exe, can be automaticallly used when running in windows bash, without user\n    extra addition to [buildenv] of that msys64/usr/bin path\n\n    # https://github.com/conan-io/conan/issues/12110\n    \"\"\"\n    client = TestClient(path_with_spaces=False)\n    bash_path = None\n    try:\n        bash_path = tools_locations[\"msys2\"][\"system\"][\"path\"][\"Windows\"] + \"/bash.exe\"\n    except KeyError:\n        pytest.skip(\"msys2 path not defined\")\n\n    client.save_home({\"global.conf\": textwrap.dedent(\"\"\"\n            tools.microsoft.bash:subsystem=msys2\n            tools.microsoft.bash:path={}\n            \"\"\".format(bash_path))})\n\n    conanfile = textwrap.dedent(f\"\"\"\n        from conan import ConanFile\n\n        class HelloConan(ConanFile):\n            name = \"hello\"\n            version = \"0.1\"\n\n            def configure(self):\n                if \"{scope}\" == \"build\":\n                    self.win_bash = True\n                else:\n                    self.win_bash_run = True\n\n            def build(self):\n                self.run(\"ar -h\", scope=\"{scope}\")\n                \"\"\")\n\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"build .\")\n    assert \"ar.exe\" in client.out\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows\")\ndef test_conf_inherited_in_test_package():\n    client = TestClient()\n    bash_path = None\n    try:\n        bash_path = tools_locations[\"msys2\"][\"system\"][\"path\"][\"Windows\"] + \"/bash.exe\"\n    except KeyError:\n        pytest.skip(\"msys2 path not defined\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Recipe(ConanFile):\n            name=\"msys2\"\n            version=\"1.0\"\n\n            def package_info(self):\n                self.conf_info.define(\"tools.microsoft.bash:subsystem\", \"msys2\")\n                self.conf_info.define(\"tools.microsoft.bash:path\", r\"{}\")\n    \"\"\".format(bash_path))\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create .\")\n\n    conanfile = GenConanfile(\"consumer\", \"1.0\")\n    test_package = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Recipe(ConanFile):\n            name=\"test\"\n            version=\"1.0\"\n            win_bash = True\n\n            def build_requirements(self):\n                self.tool_requires(self.tested_reference_str)\n                self.tool_requires(\"msys2/1.0\")\n\n            def build(self):\n                self.output.warning(self.conf.get(\"tools.microsoft.bash:subsystem\"))\n                self.run(\"aclocal --version\")\n\n            def test(self):\n                pass\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile, \"test_package/conanfile.py\": test_package})\n    client.run(\"create . -s:b os=Windows -s:h os=Windows\")\n    assert \"are needed to run commands in a Windows subsystem\" not in client.out\n    assert \"aclocal (GNU automake)\" in client.out\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows\")\n@pytest.mark.tool(\"msys2\")\ndef test_msys2_and_msbuild():\n    \"\"\" Check that msbuild can be executed in msys2 environment\n\n    # https://github.com/conan-io/conan/issues/15627\n    \"\"\"\n    client = TestClient(path_with_spaces=False)\n    profile_win = textwrap.dedent(f\"\"\"\n        include(default)\n        [conf]\n        tools.microsoft.bash:subsystem=msys2\n        tools.microsoft.bash:path=bash\n        \"\"\")\n\n    main = gen_function_cpp(name=\"main\")\n    # The autotools support for \"cl\" compiler (VS) is very limited, linking with deps doesn't\n    # work but building a simple app do\n    makefile_am = gen_makefile_am(main=\"main\", main_srcs=\"main.cpp\")\n    configure_ac = gen_configure_ac()\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.gnu import Autotools\n        from conan.tools.microsoft import MSBuild\n\n        class TestConan(ConanFile):\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            exports_sources = \"configure.ac\", \"Makefile.am\", \"main.cpp\", \"MyProject.vcxproj\"\n            generators = \"AutotoolsToolchain\"\n            win_bash = True\n\n            def build(self):\n                # These commands will run in bash activating first the vcvars and\n                # then inside the bash activating the\n                self.run(\"aclocal\")\n                self.run(\"autoconf\")\n                self.run(\"automake --add-missing --foreign\")\n                autotools = Autotools(self)\n                autotools.configure()\n                autotools.make()\n                autotools.install()\n                msbuild = MSBuild(self)\n                msbuild.build(\"MyProject.vcxproj\")\n        \"\"\")\n\n    # A minimal project is sufficient - here just copy the application file to another directory\n    my_vcxproj = r\"\"\"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n        <Project DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n        <ItemGroup Label=\"ProjectConfigurations\">\n        <ProjectConfiguration Include=\"Debug|Win32\">\n          <Configuration>Debug</Configuration>\n          <Platform>Win32</Platform>\n        </ProjectConfiguration>\n        <ProjectConfiguration Include=\"Release|Win32\">\n          <Configuration>Release</Configuration>\n          <Platform>Win32</Platform>\n        </ProjectConfiguration>\n        <ProjectConfiguration Include=\"Debug|x64\">\n          <Configuration>Debug</Configuration>\n          <Platform>x64</Platform>\n        </ProjectConfiguration>\n        <ProjectConfiguration Include=\"Release|x64\">\n          <Configuration>Release</Configuration>\n          <Platform>x64</Platform>\n        </ProjectConfiguration>\n      </ItemGroup>\n      <PropertyGroup Label=\"Globals\">\n        <ProjectGuid>{B58316C0-C78A-4E9B-AE8F-5D6368CE3840}</ProjectGuid>\n        <Keyword>Win32Proj</Keyword>\n      </PropertyGroup>\n      <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n      <PropertyGroup>\n        <ConfigurationType>Application</ConfigurationType>\n        <PlatformToolset>v141</PlatformToolset>\n      </PropertyGroup>\n      <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n      <ImportGroup Label=\"PropertySheets\">\n        <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" />\n      </ImportGroup>\n      <PropertyGroup>\n        <OutDir>$(ProjectDir)msbuild_out</OutDir>\n      </PropertyGroup>\n      <ItemDefinitionGroup>\n      </ItemDefinitionGroup>\n      <ItemGroup>\n        <Content Include=\"$(ProjectDir)main.exe\">\n          <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>\n        </Content>\n      </ItemGroup>\n      <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n    </Project>\n    \"\"\"\n\n    client.save({\"conanfile.py\": conanfile,\n                 \"configure.ac\": configure_ac,\n                 \"Makefile.am\": makefile_am,\n                 \"main.cpp\": main,\n                 \"profile_win\": profile_win,\n                 \"MyProject.vcxproj\": my_vcxproj})\n    client.run(\"build . -pr=profile_win\")\n    # Run application in msbuild output directory\n    client.run_command(os.path.join(\"msbuild_out\", \"main.exe\"))\n    check_exe_run(client.out, \"main\", \"msvc\", None, \"Release\", \"x86_64\", None)\n\n    bat_contents = client.load(\"conanbuild.bat\")\n    assert \"conanvcvars.bat\" in bat_contents\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows\")\ndef test_autotools_support_custom_make():\n    \"\"\" Check that the conf setting `tools.gnu:make_program` works when set with\n    windows native paths. For example, when set programatically by a package\n    \"\"\"\n    client = TestClient(path_with_spaces=False)\n    bash_path = None\n    make_path = None\n    try:\n        bash_path = tools_locations[\"msys2\"][\"system\"][\"path\"][\"Windows\"] + \"/bash.exe\"\n        make_path = tools_locations[\"msys2\"][\"system\"][\"path\"][\"Windows\"] + \"/make.exe\"\n    except KeyError:\n        pytest.skip(\"msys2 path not defined\")\n    if not os.path.exists(make_path):\n        pytest.skip(\"msys2 make not installed\")\n\n    make_path = make_path.replace(\"/\", \"\\\\\")\n    assert os.path.exists(make_path)\n\n    profile = textwrap.dedent(f\"\"\"\n        include(default)\n\n        [conf]\n        tools.microsoft.bash:subsystem=msys2\n        tools.microsoft.bash:path={bash_path}\n        tools.gnu:make_program={make_path}\n        tools.build:compiler_executables={{\"c\": \"cl\", \"cpp\": \"cl\"}}\n        \"\"\")\n\n    # The autotools support for \"cl\" compiler (VS) is very limited, linking with deps doesn't\n    # work but building a simple app do\n    makefile = gen_makefile()\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.gnu import Autotools\n\n        class TestConan(ConanFile):\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            generators = \"AutotoolsToolchain\"\n            win_bash = True\n\n            def build(self):\n                # These commands will run in bash activating first the vcvars and\n                # then inside the bash activating the\n                autotools = Autotools(self)\n                autotools.make()\n        \"\"\")\n\n    client.save({\"conanfile.py\": conanfile,\n                 \"Makefile\": makefile,\n                 \"profile\": profile})\n    client.run(\"build . -pr=profile\")\n    # This used to crash, because ``make_program`` was not unix_path\n    assert \"conanfile.py: Calling build()\" in client.out\n"
  },
  {
    "path": "test/functional/toolchains/gnu/test_gnutoolchain_android.py",
    "content": "import os\nimport platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.utils.mocks import ConanFileMock\nfrom conan.test.utils.tools import TestClient\nfrom conan.tools.files import replace_in_file\nfrom test.conftest import tools_locations\n\n\n@pytest.mark.parametrize(\"arch, expected_arch\", [('armv8', 'aarch64'),\n                                                 ('armv7', 'arm'),\n                                                 ('x86', 'i386'),\n                                                 ('x86_64', 'x86_64')\n                                                 ])\n@pytest.mark.tool(\"android_ndk\")\n@pytest.mark.tool(\"autotools\")\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"NDK only installed on MAC\")\ndef test_android_gnutoolchain_cross_compiling(arch, expected_arch):\n    profile_host = textwrap.dedent(\"\"\"\n    include(default)\n\n    [settings]\n    os = Android\n    os.api_level = 21\n    arch = {arch}\n\n    [conf]\n    tools.android:ndk_path={ndk_path}\n    \"\"\")\n    ndk_path = tools_locations[\"android_ndk\"][\"system\"][\"path\"][platform.system()]\n    profile_host = profile_host.format(\n        arch=arch,\n        ndk_path=ndk_path\n    )\n\n    client = TestClient(path_with_spaces=False)\n    # FIXME: Change this when we have gnu_lib as template in the new command\n    client.run(\"new autotools_lib -d name=hello -d version=1.0\")\n    replace_in_file(ConanFileMock(), os.path.join(client.current_folder, \"conanfile.py\"),\n                    \"AutotoolsToolchain\", \"GnuToolchain\")\n    client.save({\"profile_host\": profile_host})\n    client.run(\"build . --profile:build=default --profile:host=profile_host\")\n    libhello = os.path.join(\"build-release\", \"src\", \".libs\", \"libhello.a\")\n    # Check binaries architecture\n    client.run_command('objdump -f \"%s\"' % libhello)\n    assert \"architecture: %s\" % expected_arch in client.out\n"
  },
  {
    "path": "test/functional/toolchains/gnu/test_gnutoolchain_apple.py",
    "content": "import os\nimport platform\nimport textwrap\n\nimport pytest\n\nfrom conan.tools.apple.apple import _to_apple_arch\nfrom conan.test.assets.autotools import gen_makefile\nfrom conan.test.assets.sources import gen_function_h, gen_function_cpp\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only OSX\")\n@pytest.mark.parametrize(\"config\", [(\"x86_64\", \"Macos\", \"10.14\", None),\n                                    (\"armv8\", \"iOS\", \"10.0\", \"iphoneos\"),\n                                    (\"x86_64\", \"iOS\", \"10.0\", \"iphonesimulator\"),\n                                    (\"armv8\", \"Macos\", \"10.14\", None)  # M1\n                                    ])\ndef test_makefile_arch(config):\n    makefile = gen_makefile(apps=[\"app\"], libs=[\"hello\"])\n    conanfile_py = textwrap.dedent(\"\"\"\n        from conan import ConanFile, tools\n        from conan.tools.gnu import Autotools\n\n        class App(ConanFile):\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            options = {\"shared\": [True, False], \"fPIC\": [True, False]}\n            default_options = {\"shared\": False, \"fPIC\": True}\n            generators = \"GnuToolchain\"\n\n            def config_options(self):\n                if self.settings.os == \"Windows\":\n                    self.options.rm_safe(\"fPIC\")\n\n            def configure(self):\n                if self.options.shared:\n                    self.options.rm_safe(\"fPIC\")\n\n            def build(self):\n                env_build = Autotools(self)\n                env_build.make()\n    \"\"\")\n    arch, os_, os_version, os_sdk = config\n    profile = textwrap.dedent(\"\"\"\n                include(default)\n                [settings]\n                os = {os}\n                {os_sdk}\n                os.version = {os_version}\n                arch = {arch}\n                \"\"\").format(os=os_, arch=arch,\n                            os_version=os_version, os_sdk=\"os.sdk = \" + os_sdk if os_sdk else \"\")\n\n    t = TestClient()\n    hello_h = gen_function_h(name=\"hello\")\n    hello_cpp = gen_function_cpp(name=\"hello\")\n    main_cpp = gen_function_cpp(name=\"main\", includes=[\"hello\"], calls=[\"hello\"])\n\n    t.save({\"Makefile\": makefile,\n            \"hello.h\": hello_h,\n            \"hello.cpp\": hello_cpp,\n            \"app.cpp\": main_cpp,\n            \"conanfile.py\": conanfile_py,\n            \"profile\": profile})\n\n    t.run(\"install . --profile:host=profile --profile:build=default\")\n    t.run(\"build . --profile:host=profile --profile:build=default\")\n\n    libhello = os.path.join(t.current_folder, \"libhello.a\")\n    app = os.path.join(t.current_folder, \"app\")\n    assert os.path.isfile(libhello)\n    assert os.path.isfile(app)\n\n    expected_arch = _to_apple_arch(arch)\n    t.run_command('lipo -info \"%s\"' % libhello)\n    assert \"architecture: %s\" % expected_arch in t.out\n\n    t.run_command('lipo -info \"%s\"' % app)\n    assert \"architecture: %s\" % expected_arch in t.out\n"
  },
  {
    "path": "test/functional/toolchains/gnu/test_makedeps.py",
    "content": "import textwrap\n\nimport platform\nimport pytest\n\nfrom conan.test.assets.autotools import gen_makefile\nfrom conan.test.assets.sources import gen_function_cpp, gen_function_h\nfrom conan.test.utils.tools import TestClient\nfrom conan.tools.gnu.makedeps import CONAN_MAKEFILE_FILENAME\n\n\n@pytest.mark.tool(\"make\" if platform.system() != \"Windows\" else \"msys2\")\ndef test_make_deps_definitions_escape():\n    \"\"\"\n    MakeDeps has to escape the definitions properly.\n    \"\"\"\n    client = TestClient(path_with_spaces=False)\n    conanfile = textwrap.dedent(r'''\n        from conan import ConanFile\n        class HelloLib(ConanFile):\n            def package_info(self):\n                self.cpp_info.defines.append(\"USER_CONFIG=\\\"user_config.h\\\"\")\n                self.cpp_info.defines.append('OTHER=\"other.h\"')\n                self.cpp_info.cflags.append(\"flag1=\\\"my flag1\\\"\")\n                self.cpp_info.cxxflags.append('flag2=\"my flag2\"')\n        ''')\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"export . --name=hello --version=0.1.0\")\n    client.run(\"install --requires=hello/0.1.0 --build=missing -g MakeDeps\")\n    client.run_command(f\"make --print-data-base -f {CONAN_MAKEFILE_FILENAME}\", assert_error=True)\n    assert r'CONAN_CXXFLAGS_HELLO = flag2=\\\"my flag2\\\"' in client.out\n    assert r'CONAN_CFLAGS_HELLO = flag1=\\\"my flag1\\\"' in client.out\n    assert r'CONAN_DEFINES_HELLO = $(CONAN_DEFINE_FLAG)USER_CONFIG=\"user_config.h\" $(CONAN_DEFINE_FLAG)OTHER=\"other.h\"' in client.out\n\n\ndef test_makedeps_with_tool_requires():\n    \"\"\"\n    MakeDeps has to create any test requires to be declared on the recipe.\n    \"\"\"\n    conanfile = textwrap.dedent(r'''\n        from conan import ConanFile\n        class HelloLib(ConanFile):\n            def package_info(self):\n                self.cpp_info.libs = [self.name]\n        ''')\n    client = TestClient(path_with_spaces=False)\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=hello --version=0.1.0\")\n    client.run(\"create . --name=test --version=0.1.0\")\n    client.run(\"create . --name=tool --version=0.1.0\")\n    # Create library having build and test requires\n    conanfile = textwrap.dedent(r'''\n        from conan import ConanFile\n        class HelloLib(ConanFile):\n            def build_requirements(self):\n                self.test_requires('hello/0.1.0')\n                self.test_requires('test/0.1.0')\n                self.tool_requires('tool/0.1.0')\n        ''')\n    client.save({\"conanfile.py\": conanfile}, clean_first=True)\n    client.run(\"install . -g MakeDeps\")\n    content = client.load(CONAN_MAKEFILE_FILENAME)\n    assert \"CONAN_NAME_TEST\" in content\n    assert \"CONAN_NAME_HELLO\" in content\n    assert \"CONAN_NAME_TOOL\" not in content\n\n\n@pytest.mark.tool(\"make\" if platform.system() != \"Windows\" else \"msys2\")\ndef test_makedeps_with_makefile_build():\n    \"\"\"\n    Build a small application using MakeDeps generator and with components\n    \"\"\"\n    client = TestClient(path_with_spaces=False)\n    with client.chdir(\"lib\"):\n        client.save({\"Makefile\": gen_makefile(libs=[\"hello\"]),\n                    \"hello.cpp\": gen_function_cpp(name=\"hello\", includes=[\"hello\"], calls=[\"hello\"]),\n                    \"hello.h\": gen_function_h(name=\"hello\"),\n                    \"conanfile.py\": textwrap.dedent(r'''\n                    from conan import ConanFile\n                    from conan.tools.gnu import Autotools\n                    from conan.tools.files import copy\n                    import os\n                    class PackageConan(ConanFile):\n                        exports_sources = (\"Makefile\", \"hello.cpp\", \"hello.h\")\n                        settings = \"os\", \"arch\", \"compiler\"\n\n                        def configure(self):\n                            self.win_bash = self.settings.os == \"Windows\"\n\n                        def build(self):\n                            self.run(\"make -f Makefile\")\n\n                        def package(self):\n                            copy(self, \"libhello.a\", src=self.build_folder, dst=os.path.join(self.package_folder, \"lib\"))\n                            copy(self, \"hello.h\", src=self.source_folder, dst=os.path.join(self.package_folder, \"include\"))\n\n                        def package_info(self):\n                            self.cpp_info.components[\"qux\"].includedirs = [\"include\"]\n                            self.cpp_info.components[\"baz\"].libs = [\"hello\"]\n                            self.cpp_info.components[\"baz\"].defines = [\"FOOBAR=1\"]\n                    ''')\n                     })\n        client.run('create . --name=hello --version=0.1.0 -c tools.microsoft.bash:subsystem=msys2 -c tools.microsoft.bash:path=bash')\n    with client.chdir(\"global\"):\n        # Consume from global variables\n        client.run(\"install --requires=hello/0.1.0 -pr:b=default -pr:h=default -g MakeDeps -of build\")\n        client.save({\"Makefile\": textwrap.dedent('''\n            include build/conandeps.mk\n            CXXFLAGS            += $(CONAN_CXXFLAGS)\n            CPPFLAGS            += $(addprefix -I, $(CONAN_INCLUDE_DIRS))\n            CPPFLAGS            += $(addprefix -D, $(CONAN_DEFINES))\n            LDFLAGS             += $(addprefix -L, $(CONAN_LIB_DIRS))\n            LDLIBS              += $(addprefix -l, $(CONAN_LIBS))\n            EXELINKFLAGS        += $(CONAN_EXELINKFLAGS)\n\n            all:\n            \\t$(CXX) main.cpp $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) $(LDLIBS) $(EXELINKFLAGS) -o main\n            '''),\n            \"main.cpp\": gen_function_cpp(name=\"main\", includes=[\"hello\"], calls=[\"hello\"]),\n            })\n        client.run_command(\"make -f Makefile\")\n    with client.chdir(\"components\"):\n        # Consume from components\n        client.run(\"install --requires=hello/0.1.0 -pr:b=default -pr:h=default -g MakeDeps -of build\")\n        client.save({\"Makefile\": textwrap.dedent('''\n            include build/conandeps.mk\n            CXXFLAGS            += $(CONAN_CXXFLAGS)\n            CPPFLAGS            += $(addprefix -I, $(CONAN_INCLUDE_DIRS_HELLO_QUX))\n            CPPFLAGS            += $(addprefix -D, $(CONAN_DEFINES) $(CONAN_DEFINES_HELLO_BAZ))\n            LDFLAGS             += $(addprefix -L, $(CONAN_LIB_DIRS_HELLO_BAZ))\n            LDLIBS              += $(addprefix -l, $(CONAN_LIBS_HELLO_BAZ))\n            EXELINKFLAGS        += $(CONAN_EXELINKFLAGS)\n\n            all:\n            \\t$(CXX) main.cpp $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) $(LDLIBS) $(EXELINKFLAGS) -o main\n            '''),\n            \"main.cpp\": gen_function_cpp(name=\"main\", includes=[\"hello\"], calls=[\"hello\"]),\n            })\n        client.run_command(\"make -f Makefile\")\n"
  },
  {
    "path": "test/functional/toolchains/gnu/test_pkg_config.py",
    "content": "import platform\nimport textwrap\n\nimport pytest\n\nfrom test.conftest import tools_locations\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.tool(\"pkg_config\")\nclass TestPkgConfig:\n    \"\"\" This test uses the pkg_config in the system\n    \"\"\"\n    def test_negative(self):\n        c = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.gnu import PkgConfig\n\n            class Pkg(ConanFile):\n                def generate(self):\n                    pkg_config = PkgConfig(self, \"something_that_not_exist\")\n                    pkg_config.libs\n                \"\"\")\n        c.save({\"conanfile.py\": conanfile})\n        c.run(\"install .\", assert_error=True)\n        assert \"PkgConfig failed. Command: pkg-config --libs-only-l something_that_not_exist \" \\\n               \"--print-errors\" in c.out\n        assert \"Package something_that_not_exist was not found\" in c.out\n\n    def test_pc(self):\n        c = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.gnu import PkgConfig\n            from conan.tools import CppInfo\n\n            class Pkg(ConanFile):\n                def generate(self):\n                    pkg_config = PkgConfig(self, \"libastral\", pkg_config_path=\".\")\n                    self.output.info(f\"PROVIDES: {pkg_config.provides}\")\n                    self.output.info(f\"VERSION: {pkg_config.version}\")\n                    self.output.info(f\"VARIABLES: {pkg_config.variables['prefix']}\")\n\n                    cpp_info = CppInfo(self)\n                    pkg_config.fill_cpp_info(cpp_info, is_system=False, system_libs=[\"m\"])\n\n                    assert cpp_info.includedirs == ['/usr/local/include/libastral']\n                    assert cpp_info.defines == ['_USE_LIBASTRAL']\n                    assert cpp_info.libs == ['astral']\n                    assert cpp_info.system_libs == ['m']\n                    assert cpp_info.libdirs == ['/usr/local/lib/libastral']\n                    assert cpp_info.sharedlinkflags == ['-Wl,--whole-archive']\n            \"\"\")\n        libastral_pc = textwrap.dedent(\"\"\"\\\n            PC FILE EXAMPLE:\n\n            prefix=/usr/local\n            exec_prefix=${prefix}\n            libdir=${exec_prefix}/lib\n            includedir=${prefix}/include\n\n            Name: libastral\n            Description: Interface library for Astral data flows\n            Version: 6.6.6\n            Libs: -L${libdir}/libastral -lastral -lm -Wl,--whole-archive\n            Cflags: -I${includedir}/libastral -D_USE_LIBASTRAL\n            \"\"\")\n        c.save({\"conanfile.py\": conanfile,\n                \"libastral.pc\": libastral_pc})\n        c.run(\"install .\")\n        assert \"conanfile.py: PROVIDES: libastral = 6.6.6\" in c.out\n        assert \"conanfile.py: VERSION: 6.6.6\" in c.out\n        assert \"conanfile.py: VARIABLES: /usr/local\" in c.out\n\n\ndef test_pkg_config_round_tripe_cpp_info():\n    \"\"\" test that serialize and deserialize CppInfo works\n    \"\"\"\n    try:\n        version = tools_locations[\"pkg_config\"][\"default\"]\n        exe = tools_locations[\"pkg_config\"][\"exe\"]\n        os_ = platform.system()\n        pkg_config_path = tools_locations[\"pkg_config\"][version][\"path\"][os_] + \"/\" + exe\n    except KeyError:\n        pytest.skip(\"pkg-config path not defined\")\n        return\n\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.gnu import PkgConfig\n        from conan.tools import CppInfo\n\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            exports_sources = \"*.pc\"\n\n            def package(self):\n                pkg_config = PkgConfig(self, \"libastral\", pkg_config_path=\".\")\n                cpp_info = CppInfo(self)\n                pkg_config.fill_cpp_info(cpp_info, is_system=False, system_libs=[\"m\"])\n                cpp_info.save(os.path.join(self.package_folder, \"cpp_info.json\"))\n\n            def package_info(self):\n                self.cpp_info = CppInfo(self).load(\"cpp_info.json\")\n        \"\"\")\n    prefix = \"C:\" if platform.system() == \"Windows\" else \"\"\n    libastral_pc = textwrap.dedent(\"\"\"\\\n        PC FILE EXAMPLE:\n\n        prefix=%s/usr/local\n        exec_prefix=${prefix}\n        libdir=${exec_prefix}/lib\n        includedir=${prefix}/include\n\n        Name: libastral\n        Description: Interface library for Astral data flows\n        Version: 6.6.6\n        Libs: -L${libdir}/libastral -lastral -lm -Wl,--whole-archive\n        Cflags: -I${includedir}/libastral -D_USE_LIBASTRAL\n        \"\"\" % prefix)\n    c.save({\"conanfile.py\": conanfile,\n            \"libastral.pc\": libastral_pc,\n            \"profile\": f\"[conf]\\ntools.gnu:pkg_config={pkg_config_path}\"})\n    c.run(\"export .\")\n    c.run(\"install --requires=pkg/0.1 -pr=profile -g CMakeDeps --build=missing\")\n    pkg_data = c.load(\"pkg-none-data.cmake\")\n    assert 'set(pkg_DEFINITIONS_NONE \"-D_USE_LIBASTRAL\")' in pkg_data\n    assert 'set(pkg_SHARED_LINK_FLAGS_NONE \"-Wl,--whole-archive\")' in pkg_data\n    assert 'set(pkg_COMPILE_DEFINITIONS_NONE \"_USE_LIBASTRAL\")' in pkg_data\n    assert 'set(pkg_LIBS_NONE astral)' in pkg_data\n    assert 'set(pkg_SYSTEM_LIBS_NONE m)' in pkg_data\n    # paths\n    assert f'set(pkg_INCLUDE_DIRS_NONE \"{prefix}/usr/local/include/libastral\")' in pkg_data\n    assert f'set(pkg_LIB_DIRS_NONE \"{prefix}/usr/local/lib/libastral\")' in pkg_data\n"
  },
  {
    "path": "test/functional/toolchains/gnu/test_pkgconfigdeps.py",
    "content": "import platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.skipif(platform.system() == \"Windows\", reason=\"Needs pkg-config\")\n@pytest.mark.tool(\"pkg_config\")\ndef test_pkgconfigdeps_definitions_escape():\n    client = TestClient(path_with_spaces=False)\n    conanfile = textwrap.dedent(r'''\n        from conan import ConanFile\n        class HelloLib(ConanFile):\n            def package_info(self):\n                self.cpp_info.defines.append(\"USER_CONFIG=\\\"user_config.h\\\"\")\n                self.cpp_info.defines.append('OTHER=\"other.h\"')\n                self.cpp_info.cflags.append(\"flag1=\\\"my flag1\\\"\")\n                self.cpp_info.cxxflags.append('flag2=\"my flag2\"')\n        ''')\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"export . --name=hello --version=1.0\")\n    client.save({\"conanfile.txt\": \"[requires]\\nhello/1.0\\n\"}, clean_first=True)\n    client.run(\"install . --build=missing -g PkgConfigDeps\")\n    client.run_command(\"PKG_CONFIG_PATH=$(pwd) pkg-config --cflags hello\")\n    assert r'flag2=\\\"my flag2\\\" flag1=\\\"my flag1\\\" ' \\\n           r'-DUSER_CONFIG=\\\"user_config.h\\\" -DOTHER=\\\"other.h\\\"' in client.out\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_pkgconfigdeps_with_test_requires():\n    \"\"\"\n    PkgConfigDeps has to create any test requires declared on the recipe.\n\n    Related issue: https://github.com/conan-io/conan/issues/11376\n    \"\"\"\n    client = TestClient()\n    client.save({\"app/conanfile.py\": GenConanfile(\"app\", \"1.0\"),\n                 \"test/conanfile.py\": GenConanfile(\"test\", \"1.0\")})\n    client.run(\"create app\")\n    client.run(\"create test\")\n    # Create library having build and test requires\n    conanfile = textwrap.dedent(r'''\n        from conan import ConanFile\n        class HelloLib(ConanFile):\n            def build_requirements(self):\n                self.test_requires('app/1.0')\n                self.test_requires('test/1.0')\n        ''')\n    client.save({\"conanfile.py\": conanfile}, clean_first=True)\n    client.run(\"install . -g PkgConfigDeps\")\n    assert \"Description: Conan package: test\" in client.load(\"test.pc\")\n    assert \"Description: Conan package: app\" in client.load(\"app.pc\")\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"It makes sense only for Windows\")\n@pytest.mark.tool(\"meson\")  # https://github.com/mesonbuild/meson/pull/11649 is part of Meson 1.1.0\n@pytest.mark.tool(\"pkg_config\")\ndef test_pkgconfigdeps_bindir_and_meson():\n    \"\"\"\n    This test checks that the field bindir introduced by PkgConfigDeps is useful for Windows\n    OS and shared=True where all the DLL's files are located by default there.\n\n    Basically, Meson (version >= 1.1.0) reads from the *.pc files the bindir variable if exists, and\n    uses that variable to link with if SHARED libraries.\n\n    Issue: https://github.com/conan-io/conan/issues/13532\n    \"\"\"\n    client = TestClient()\n    client.run(\"new meson_lib -d name=hello -d version=1.0\")\n    client.run(\"create . -tf \\\"\\\" -o *:shared=True\")\n    test_meson_build = textwrap.dedent(\"\"\"\n    project('Testhello', 'cpp')\n    hello = dependency('hello', version : '>=1.0')\n    example = executable('example', 'src/example.cpp', dependencies: hello)\n    test('./src/example', example)\n    \"\"\")\n    test_conanfile = textwrap.dedent(\"\"\"\n    import os\n    from conan import ConanFile\n    from conan.tools.build import can_run\n    from conan.tools.meson import Meson\n    from conan.tools.layout import basic_layout\n\n    class helloTestConan(ConanFile):\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n        generators = \"PkgConfigDeps\", \"MesonToolchain\"\n        options = {\"shared\": [True, False], \"fPIC\": [True, False]}\n        default_options = {\"shared\": True, \"fPIC\": True}\n\n        def requirements(self):\n            self.requires(\"hello/1.0\")\n\n        def build(self):\n            meson = Meson(self)\n            meson.configure()\n            meson.build()\n\n        def layout(self):\n            basic_layout(self)\n    \"\"\")\n    client.save({\n        \"test_package/conanfile.py\": test_conanfile,\n        \"test_package/meson.build\": test_meson_build\n    })\n    client.run(\"build test_package/conanfile.py -o *:shared=True\")\n    # Important: Only Meson >= 1.1.0 brings this capability\n    # Executing directly \"meson test\" fails if the bindir field does not exist\n    client.run_command(\"meson test -C test_package/build-release\")\n    assert \"1/1 ./src/example OK\"\n\n\ndef test_pkgconfigdeps_component_matches_package_name():\n    client = TestClient(path_with_spaces=False)\n    # Create library having build and test requires\n    conanfile = textwrap.dedent(r'''\n        from conan import ConanFile\n        class MyLib(ConanFile):\n            name = \"hello\"\n            version = \"0.1\"\n            def package_info(self):\n                self.cpp_info.components[\"mycomponent\"].set_property(\"pkg_config_name\", \"hello\")\n        ''')\n    client.save({\"conanfile.py\": conanfile}, clean_first=True)\n    client.run(\"export-pkg .\")\n    client.run(\"install --requires=hello/0.1 -g PkgConfigDeps\")\n    content = client.load(\"hello.pc\")\n    assert \"Conan component: hello\" in content\n"
  },
  {
    "path": "test/functional/toolchains/gnu/test_pkgconfigdeps_autotools.py",
    "content": "import platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.tool(\"pkg_config\")\n@pytest.mark.tool(\"autotools\")\n@pytest.mark.skipif(platform.system() == \"Windows\", reason=\"Needs pkg-config\")\ndef test_pkgconfigdeps_and_autotools():\n    \"\"\"\n    This test aims to show how to use PkgConfigDeps and AutotoolsToolchain.\n\n    In this case, the test_package is using PkgConfigDeps and AutotoolsToolchain to use\n    the created pkg/1.0 package. It's important to make a full compilation to ensure that\n    the test main.cpp is using correctly the flags passed via pkg.pc file.\n\n    Issue related: https://github.com/conan-io/conan/issues/11867\n    \"\"\"\n    client = TestClient(path_with_spaces=False)\n    conanfile_pkg = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    from conan.tools.gnu import Autotools\n    from conan.tools.layout import basic_layout\n    from conan.tools.apple import fix_apple_shared_install_name\n\n\n    class PkgConan(ConanFile):\n        name = \"pkg\"\n        version = \"1.0\"\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n        options = {\"shared\": [True, False], \"fPIC\": [True, False]}\n        default_options = {\"shared\": False, \"fPIC\": True}\n        exports_sources = \"configure.ac\", \"Makefile.am\", \"src/*\"\n        generators = \"AutotoolsToolchain\"\n\n        def layout(self):\n            basic_layout(self)\n\n        def build(self):\n            autotools = Autotools(self)\n            autotools.autoreconf()\n            autotools.configure()\n            autotools.make()\n\n        def package(self):\n            autotools = Autotools(self)\n            autotools.install()\n            fix_apple_shared_install_name(self)\n\n        def package_info(self):\n            self.cpp_info.libs = [\"pkg\"]\n            # Add non-existing frameworkdirs to check that it's not failing because of this\n            self.cpp_info.frameworkdirs = [\"/my/framework/file1\", \"/my/framework/file2\"]\n    \"\"\")\n    conanfile_test = textwrap.dedent(\"\"\"\n    import os\n    from conan import ConanFile\n    from conan.tools.gnu import Autotools\n    from conan.tools.layout import basic_layout\n    from conan.tools.build import cross_building\n    class PkgTestConan(ConanFile):\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n        generators = \"PkgConfigDeps\", \"AutotoolsToolchain\"\n\n        def requirements(self):\n            self.requires(self.tested_reference_str)\n\n        def build(self):\n            autotools = Autotools(self)\n            autotools.autoreconf()\n            autotools.configure()\n            autotools.make()\n\n        def layout(self):\n            basic_layout(self)\n\n        def test(self):\n            if not cross_building(self):\n                cmd = os.path.join(self.cpp.build.bindirs[0], \"main\")\n                self.run(cmd, env=\"conanrun\")\n    \"\"\")\n    configure_test = textwrap.dedent(\"\"\"\n    AC_INIT([main], [1.0], [])\n    AM_INIT_AUTOMAKE([-Wall -Werror foreign])\n    AC_PROG_CXX\n    PKG_PROG_PKG_CONFIG\n    PKG_CHECK_MODULES([pkg], [pkg >= 1.0])\n    AC_CONFIG_FILES([Makefile])\n    AC_OUTPUT\n    \"\"\")\n    makefile_test = textwrap.dedent(\"\"\"\n    bin_PROGRAMS = main\n    main_SOURCES = main.cpp\n    AM_CXXFLAGS = $(pkg_CFLAGS)\n    main_LDADD = $(pkg_LIBS)\n    \"\"\")\n    client.run(\"new autotools_lib -d name=pkg -d version=1.0\")\n    client.save({\"conanfile.py\": conanfile_pkg,\n                 \"test_package/conanfile.py\": conanfile_test,\n                 \"test_package/configure.ac\": configure_test,\n                 \"test_package/Makefile.am\": makefile_test,\n                 })\n    # client.run(\"new autotools_lib -d name=pkg -d version=1.0\")\n    client.run(\"create .\")\n    if platform.system() == \"Darwin\":\n        # Checking that frameworkdirs appear all together instead of \"-F /whatever/f1\"\n        # Issue: https://github.com/conan-io/conan/issues/11867\n        assert '-F/my/framework/file1' in client.out\n        assert '-F/my/framework/file2' in client.out\n"
  },
  {
    "path": "test/functional/toolchains/gnu/test_universal_binaries.py",
    "content": "import platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only OSX\")\ndef test_gnutoolchain_universal_binary():\n    client = TestClient(path_with_spaces=False)\n\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.gnu import GnuToolchain, Autotools\n        from conan.tools.layout import basic_layout\n\n        class mylibraryRecipe(ConanFile):\n            name = \"mylibrary\"\n            version = \"1.0\"\n            package_type = \"library\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            options = {\"shared\": [True, False], \"fPIC\": [True, False]}\n            default_options = {\"shared\": False, \"fPIC\": True}\n\n            exports_sources = \"configure.ac\", \"Makefile.am\", \"src/*\"\n\n            def config_options(self):\n                if self.settings.os == \"Windows\":\n                    self.options.rm_safe(\"fPIC\")\n\n            def configure(self):\n                if self.options.shared:\n                    self.options.rm_safe(\"fPIC\")\n\n            def layout(self):\n                basic_layout(self)\n\n            def generate(self):\n                gnu_toolchain = GnuToolchain(self)\n                gnu_toolchain.generate()\n\n            def build(self):\n                autotools = Autotools(self)\n                autotools.autoreconf()\n                autotools.configure()\n                autotools.make()\n\n            def package(self):\n                autotools = Autotools(self)\n                autotools.install()\n                self.run(f\"lipo -info {os.path.join(self.package_folder, 'lib', 'libmylibrary.a')}\")\n\n            def package_info(self):\n                self.cpp_info.libs = [\"mylibrary\"]\n\n    \"\"\")\n\n    client.run('new autotools_lib -d name=mylibrary -d version=0.1')\n\n    client.save({\"conanfile.py\": conanfile})\n\n    client.run('create . -s=\"arch=armv8|x86_64\" -tf=\"\"')\n\n    assert \"libmylibrary.a are: x86_64 arm64\" in client.out\n"
  },
  {
    "path": "test/functional/toolchains/gnu/test_v2_autotools_template.py",
    "content": "import platform\nimport os\nimport shutil\nimport textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.skipif(platform.system() not in [\"Linux\", \"Darwin\"], reason=\"Requires Autotools\")\n@pytest.mark.tool(\"autotools\")\ndef test_autotools_lib_template():\n    client = TestClient(path_with_spaces=False)\n    client.run(\"new autotools_lib -d name=hello -d version=0.1\")\n\n    # Local flow works\n    client.run(\"install .\")\n    client.run(\"build .\")\n\n    client.run(\"export-pkg .\")\n    pkg_layout = client.created_layout()\n    package_folder = pkg_layout.package()\n    assert os.path.exists(os.path.join(package_folder, \"include\", \"hello.h\"))\n    assert os.path.exists(os.path.join(package_folder, \"lib\", \"libhello.a\"))\n\n    # Local flow for shared library works\n    client.save({}, clean_first=True)\n    client.run(\"new autotools_lib -d name=hello -d version=0.1\")\n    client.run(\"install . -o hello/*:shared=True\")\n    client.run(\"build . -o hello/*:shared=True\")\n    client.run(\"export-pkg . -o hello/*:shared=True\")\n    pkg_layout = client.created_layout()\n    package_folder = pkg_layout.package()\n\n    if platform.system() == \"Darwin\":\n        # Ensure that install name of dylib is patched\n        client.run_command(f\"otool -L {package_folder}/lib/libhello.0.dylib\")\n        assert \"@rpath/libhello.0.dylib\" in client.out\n    elif platform.system() == \"Linux\":\n        assert os.path.exists(os.path.join(package_folder, \"lib\", \"libhello.so.0\"))\n\n    # Create works\n    client.run(\"create .\")\n    assert \"hello/0.1: Hello World Release!\" in client.out\n\n    client.run(\"create . -s build_type=Debug\")\n    assert \"hello/0.1: Hello World Debug!\" in client.out\n\n    # Create + shared works\n    client.save({}, clean_first=True)\n    client.run(\"new autotools_lib -d name=hello -d version=0.1\")\n    client.run(\"create . -o hello/*:shared=True\")\n    build_folder = client.created_test_build_folder(\"hello/0.1\")\n    assert \"hello/0.1: Hello World Release!\" in client.out\n    if platform.system() == \"Darwin\":\n        client.run_command(f\"otool -l test_package/{build_folder}/main\")\n        assert \"@rpath/libhello.0.dylib\" in client.out\n    else:\n        client.run_command(f\"ldd test_package/{build_folder}/main\")\n        assert \"libhello.so.0\" in client.out\n\n\n@pytest.mark.skipif(platform.system() not in [\"Linux\", \"Darwin\"], reason=\"Requires Autotools\")\n@pytest.mark.tool(\"autotools\")\ndef test_autotools_exe_template():\n    client = TestClient(path_with_spaces=False)\n    client.run(\"new autotools_exe -d name=greet -d version=0.1\")\n    # Local flow works\n    client.run(\"install .\")\n    client.run(\"build .\")\n\n    # Create works\n    client.run(\"create .\")\n    # check that for exe's we don't add any static/shared flag\n    for flag in [\"--enable-static\", \"--disable-static\", \"--disable-shared\", \"--with-pic\"]:\n        assert flag not in client.out\n    assert \"greet/0.1: Hello World Release!\" in client.out\n\n    client.run(\"create . -s build_type=Debug\")\n    for flag in [\"--enable-static\", \"--disable-static\", \"--disable-shared\", \"--with-pic\"]:\n        assert flag not in client.out\n    assert \"greet/0.1: Hello World Debug!\" in client.out\n\n\n@pytest.mark.skipif(platform.system() not in [\"Darwin\"], reason=\"Requires Autotools\")\n@pytest.mark.tool(\"autotools\")\ndef test_autotools_relocatable_libs_darwin():\n    client = TestClient(path_with_spaces=False)\n    client.run(\"new autotools_lib -d name=hello -d version=0.1\")\n    client.run(\"create . -o hello/*:shared=True\")\n\n    build_folder = client.created_test_build_folder(\"hello/0.1\")\n    pkg_layout = client.created_layout()\n    package_folder = pkg_layout.package()\n\n    dylib = os.path.join(package_folder, \"lib\", \"libhello.0.dylib\")\n    if platform.system() == \"Darwin\":\n        client.run_command(\"otool -l {}\".format(dylib))\n        assert \"@rpath/libhello.0.dylib\" in client.out\n        client.run_command(\"otool -l {}\".format(f\"test_package/{build_folder}/main\"))\n        assert package_folder in client.out\n\n    # will work because rpath set\n    client.run_command(f\"test_package/{build_folder}/main\")\n    assert \"hello/0.1: Hello World Release!\" in client.out\n\n    # move to another location so that the path set in the rpath does not exist\n    # then the execution should fail\n    shutil.move(os.path.join(package_folder, \"lib\"), os.path.join(client.current_folder, \"tempfolder\"))\n    # will fail because rpath does not exist\n    client.run_command(f\"test_package/{build_folder}/main\", assert_error=True)\n    assert \"Library not loaded: @rpath/libhello.0.dylib\" in str(client.out).replace(\"'\", \"\")\n\n    # Use DYLD_LIBRARY_PATH and should run\n    client.run_command(\"DYLD_LIBRARY_PATH={} test_package/{}/main\".format(os.path.join(client.current_folder, \"tempfolder\"),\n                                                                          build_folder))\n    assert \"hello/0.1: Hello World Release!\" in client.out\n\n\n# FIXME: investigate this test\n@pytest.mark.skipif(platform.system() not in [\"Darwin\"], reason=\"Requires Autotools\")\n@pytest.mark.tool(\"autotools\")\n@pytest.mark.xfail(reason=\"This test is failing for newer MacOS versions, but used to pass in the ci\")\ndef test_autotools_relocatable_libs_darwin_downloaded():\n    client = TestClient(default_server_user=True, path_with_spaces=False)\n    client2 = TestClient(servers=client.servers, path_with_spaces=False)\n    assert client2.cache_folder != client.cache_folder\n    client.run(\"new autotools_lib -d name=hello -d version=0.1\")\n    client.run(\"create . -o hello/*:shared=True -tf=\\\"\\\"\")\n    client.run(\"upload hello/0.1 -c -r default\")\n    client.run(\"remove * -c\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.gnu import Autotools\n        from conan.tools.layout import basic_layout\n\n        class GreetConan(ConanFile):\n            name = \"greet\"\n            version = \"1.0\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            exports_sources = \"configure.ac\", \"Makefile.am\", \"main.cpp\"\n            generators = \"AutotoolsDeps\", \"AutotoolsToolchain\", \"VirtualRunEnv\"\n\n            def requirements(self):\n                self.requires(\"hello/0.1\")\n\n            def layout(self):\n                basic_layout(self)\n\n            def build(self):\n                autotools = Autotools(self)\n                autotools.autoreconf()\n                autotools.configure()\n                autotools.make()\n        \"\"\")\n\n    main = textwrap.dedent(\"\"\"\n        #include \"hello.h\"\n        int main() { hello(); }\n        \"\"\")\n\n    makefileam = textwrap.dedent(\"\"\"\n        bin_PROGRAMS = greet\n        greet_SOURCES = main.cpp\n        \"\"\")\n\n    configureac = textwrap.dedent(\"\"\"\n        AC_INIT([greet], [1.0], [])\n        AM_INIT_AUTOMAKE([-Wall -Werror foreign])\n        AC_PROG_CXX\n        AM_PROG_AR\n        LT_INIT\n        AC_CONFIG_FILES([Makefile])\n        AC_OUTPUT\n        \"\"\")\n\n    client2.save({\"conanfile.py\": conanfile,\n                  \"main.cpp\": main,\n                  \"makefile.am\": makefileam,\n                  \"configure.ac\": configureac})\n\n    client2.run(\"install . -o hello/*:shared=True -r default\")\n    client2.run(\"build . -o hello/*:shared=True -r default\")\n    # for some reason this is failing for newer macos\n    # although -Wl,-rpath -Wl, if passed to set the rpath when building\n    # it fails with LC_RPATH's not found\n    client2.run_command(\"build-release/greet\")\n    # activating the environment should not be needed as the rpath is set when linking greet\n    #client2.run_command(\". build-release/conan/conanrun.sh && build-release/greet\")\n    assert \"Hello World Release!\" in client2.out\n\n\n@pytest.mark.skipif(platform.system() not in [\"Darwin\"], reason=\"Only affects apple platforms\")\n@pytest.mark.tool(\"autotools\")\ndef test_autotools_fix_shared_libs():\n    \"\"\"\n    From comments in: https://github.com/conan-io/conan/pull/11365\n\n    Case 1:\n    libopencv_core.3.4.17.dylib\n    libopencv_core.3.4.dylib (symlink) -> libopencv_core.3.4.17.dylib\n    libopencv_core.dylib (symlink) -> libopencv_core.3.4.dylib\n\n    Install name in libopencv_core.3.4.17.dylib is libopencv_core.3.4.dylib NOT the dylib name\n    So we have to add the rpath to that.\n\n    Case 2:\n    libopencv_core.dylib\n    libopencv_imgproc.dylib\n\n    libopencv_imgproc.dylib depends on libopencv_core.dylib and declares that dependency not using the\n    @rpath, we have to make sure that we patch the dependencies in the dylibs using install_name_tool -change\n\n    Let's create a Conan package with two libraries: bye and hello (bye depends on hello)\n    and recreate this whole situation to check that we are correctly fixing the dylibs\n    \"\"\"\n    client = TestClient(path_with_spaces=False)\n    client.run(\"new autotools_lib -d name=hello -d version=0.1\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n\n        from conan import ConanFile\n        from conan.tools.files import save\n        from conan.tools.gnu import AutotoolsToolchain, Autotools\n        from conan.tools.layout import basic_layout\n        from conan.tools.apple import fix_apple_shared_install_name\n\n\n        class HelloConan(ConanFile):\n            name = \"hello\"\n            version = \"0.1\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            options = {\"shared\": [True, False], \"fPIC\": [True, False]}\n            default_options = {\"shared\": False, \"fPIC\": True}\n            exports_sources = \"configure.ac\", \"Makefile.am\", \"src/*\"\n\n            def layout(self):\n                basic_layout(self)\n\n            def generate(self):\n                at_toolchain = AutotoolsToolchain(self)\n                at_toolchain.generate()\n\n            def build(self):\n                autotools = Autotools(self)\n                autotools.autoreconf()\n                autotools.configure()\n                autotools.make()\n\n            def package(self):\n                autotools = Autotools(self)\n                autotools.install()\n                # before fixing the names we try to reproduce the two cases explained\n                # in the test that dylib name and install name are not the same\n                self.run(\"install_name_tool {} -id /lib/libbye.dylib\".format(os.path.join(self.package_folder,\n                                                                                          \"lib\", \"libbye.0.dylib\")))\n                # also change that in the libbye dependencies\n                self.run(\"install_name_tool {} -change /lib/libhello.0.dylib /lib/libhello.dylib\".format(os.path.join(self.package_folder,\n                                                                                                         \"lib\", \"libbye.0.dylib\")))\n                self.run(\"install_name_tool {} -id /lib/libhello.dylib\".format(os.path.join(self.package_folder,\n                                                                                            \"lib\",\"libhello.0.dylib\")))\n                # https://github.com/conan-io/conan/issues/12727\n                save(self, os.path.join(self.package_folder, \"bin\", \"subfolder\", \"testfile\"), \"foobar\")\n                save(self, os.path.join(self.package_folder, \"lib\", \"subfolder\", \"randomfile\"), \"foobar\")\n\n                fix_apple_shared_install_name(self)\n\n            def package_info(self):\n                self.cpp_info.libs = [\"hello\", \"bye\"]\n    \"\"\")\n\n    bye_cpp = textwrap.dedent(\"\"\"\n        #include <iostream>\n        #include \"hello.h\"\n        #include \"bye.h\"\n        void bye(){\n            hello();\n            std::cout << \"Bye, bye!\" << std::endl;\n        }\n    \"\"\")\n\n    bye_h = textwrap.dedent(\"\"\"\n        #pragma once\n        void bye();\n    \"\"\")\n\n    makefile_am = textwrap.dedent(\"\"\"\n        lib_LTLIBRARIES = libhello.la libbye.la\n\n        libhello_la_SOURCES = hello.cpp hello.h\n        libhello_la_HEADERS = hello.h\n        libhello_ladir = $(includedir)\n\n        libbye_la_SOURCES = bye.cpp bye.h\n        libbye_la_HEADERS = bye.h\n        libbye_ladir = $(includedir)\n        libbye_la_LIBADD = libhello.la\n\n        bin_PROGRAMS = main\n        main_SOURCES = main.cpp\n        main_LDADD = libhello.la libbye.la\n    \"\"\")\n\n    test_src = textwrap.dedent(\"\"\"\n        #include \"bye.h\"\n        int main() { bye(); }\n    \"\"\")\n\n    client.save({\n        \"src/makefile.am\": makefile_am,\n        \"src/bye.cpp\": bye_cpp,\n        \"src/bye.h\": bye_h,\n        \"src/main.cpp\": test_src,\n        \"test_package/main.cpp\": test_src,\n        \"conanfile.py\": conanfile,\n    })\n\n    client.run(\"create . -o hello/*:shared=True -tf=\\\"\\\"\")\n\n    package_folder = client.created_layout().package()\n\n    # install name fixed\n    client.run_command(\"otool -D {}\".format(os.path.join(package_folder, \"lib\", \"libhello.0.dylib\")))\n    assert \"@rpath/libhello.dylib\" in client.out\n    client.run_command(\"otool -D {}\".format(os.path.join(package_folder, \"lib\", \"libbye.0.dylib\")))\n    assert \"@rpath/libbye.dylib\" in client.out\n\n    # dependencies fixed\n    client.run_command(\"otool -L {}\".format(os.path.join(package_folder, \"lib\", \"libbye.0.dylib\")))\n    assert \"/lib/libhello.dylib (compatibility version 1.0.0, current version 1.0.0)\" not in client.out\n    assert \"/lib/libbye.dylib (compatibility version 1.0.0, current version 1.0.0)\" not in client.out\n    assert \"@rpath/libhello.dylib (compatibility version 1.0.0, current version 1.0.0)\" in client.out\n    assert \"@rpath/libbye.dylib (compatibility version 1.0.0, current version 1.0.0)\" in client.out\n\n    # app rpath fixed in executable\n    exe_path = os.path.join(package_folder, \"bin\", \"main\")\n    client.run_command(\"otool -L {}\".format(exe_path))\n    assert \"@rpath/libhello.dylib\" in client.out\n    client.run_command(exe_path)\n    assert \"Bye, bye!\" in client.out\n\n    # Running the test-package also works\n    client.run(\"test test_package hello/0.1@ -o hello/*:shared=True\")\n    assert \"Bye, bye!\" in client.out\n\n\n@pytest.mark.slow\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Using msys2\")\n@pytest.mark.tool(\"msys2\")\nclass TestAutotoolsTemplateWindows:\n    def test_msys2_autotools_windows(self):\n        c = TestClient(path_with_spaces=False)\n        c.run(\"new autotools_lib -d name=hello -d version=1.0\")\n        # TODO: Can we reduce the configuration? maybe path=bash can be defaulted?\n        msys2 = textwrap.dedent(\"\"\"\n            include(default)\n            [conf]\n            tools.microsoft.bash:subsystem=msys2\n            tools.microsoft.bash:path=bash\n            \"\"\")\n        c.save({\"msys2\": msys2})\n        # FIXME: Need to deactivate test_package because AutotoolsDeps doesn't work in Win\n        c.run(\"create . -pr=msys2 -tf=\")\n        # This will not crash\n        assert \"conanvcvars.bat: Activating environment\" in c.out\n        assert \"hello/1.0: package(): Packaged 1 '.lib' file: hello.lib\" in c.out\n\n    def test_msys2_autotools_exe_windows(self):\n        c = TestClient(path_with_spaces=False)\n        c.run(\"new autotools_exe -d name=hello -d version=1.0\")\n        msys2 = textwrap.dedent(\"\"\"\n            include(default)\n            [conf]\n            tools.microsoft.bash:subsystem=msys2\n            tools.microsoft.bash:path=bash\n            \"\"\")\n        c.save({\"msys2\": msys2})\n        c.run(\"create . -pr=msys2\")\n        assert \"hello/1.0: _MSC_VER19\" in c.out\n"
  },
  {
    "path": "test/functional/toolchains/google/__init__.py",
    "content": ""
  },
  {
    "path": "test/functional/toolchains/google/test_bazel.py",
    "content": "import platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.fixture(scope=\"module\")\ndef bazel_output_root_dir():\n    return temp_folder(path_with_spaces=False).replace(\"\\\\\", \"/\")\n\n\n@pytest.fixture(scope=\"module\")\ndef bazelrc():\n    return textwrap.dedent(\"\"\"\n        build:Debug -c dbg --copt=-g\n        build:Release -c opt\n        build:RelWithDebInfo -c opt --copt=-O3 --copt=-DNDEBUG\n        build:MinSizeRel  -c opt --copt=-Os --copt=-DNDEBUG\n        build --color=yes\n        build:withTimeStamps --show_timestamps\n        \"\"\")\n\n\n@pytest.fixture(scope=\"module\")\ndef base_profile():\n    return textwrap.dedent(\"\"\"\n        include(default)\n        [settings]\n        build_type={build_type}\n\n        [conf]\n        tools.google.bazel:bazelrc_path=[\"{curdir}/mybazelrc\"]\n        tools.google.bazel:configs=[\"{build_type}\", \"withTimeStamps\"]\n        \"\"\")\n\n\n@pytest.mark.slow\n@pytest.mark.parametrize(\"build_type\", [\"Debug\", \"Release\", \"RelWithDebInfo\", \"MinSizeRel\"])\n@pytest.mark.tool(\"bazel\", \"6.x\")\ndef test_basic_exe_6x(bazelrc, build_type, base_profile, bazel_output_root_dir):\n    client = TestClient(path_with_spaces=False)\n    client.run(f\"new bazel_exe -d name=myapp -d version=1.0 -d output_root_dir={bazel_output_root_dir}\")\n    # The build:<config> define several configurations that can be activated by passing\n    # the bazel config with tools.google.bazel:configs\n    client.save({\"mybazelrc\": bazelrc})\n    profile = base_profile.format(build_type=build_type,\n                                  curdir=client.current_folder.replace(\"\\\\\", \"/\"))\n    client.save({\"my_profile\": profile})\n    client.run(\"create . --profile=./my_profile\")\n    if build_type != \"Debug\":\n        assert \"myapp/1.0: Hello World Release!\" in client.out\n    else:\n        assert \"myapp/1.0: Hello World Debug!\" in client.out\n\n\n@pytest.mark.slow\n@pytest.mark.parametrize(\"build_type\", [\"Debug\", \"Release\", \"RelWithDebInfo\", \"MinSizeRel\"])\n@pytest.mark.tool(\"bazel\", \"7.x\")\ndef test_basic_exe(bazelrc, build_type, base_profile, bazel_output_root_dir):\n    client = TestClient(path_with_spaces=False)\n    client.run(f\"new bazel_7_exe -d name=myapp -d version=1.0 -d output_root_dir={bazel_output_root_dir}\")\n    # The build:<config> define several configurations that can be activated by passing\n    # the bazel config with tools.google.bazel:configs\n    client.save({\"mybazelrc\": bazelrc})\n    profile = base_profile.format(build_type=build_type,\n                                  curdir=client.current_folder.replace(\"\\\\\", \"/\"))\n    client.save({\"my_profile\": profile})\n    client.run(\"create . --profile=./my_profile\")\n    if build_type != \"Debug\":\n        assert \"myapp/1.0: Hello World Release!\" in client.out\n    else:\n        assert \"myapp/1.0: Hello World Debug!\" in client.out\n\n\n@pytest.mark.slow\n@pytest.mark.tool(\"bazel\", \"8.x\")\ndef test_basic_lib(bazelrc, base_profile, bazel_output_root_dir):\n    \"\"\"\n    Issue related: https://github.com/conan-io/conan/issues/17438\n    \"\"\"\n    client = TestClient(path_with_spaces=False)\n    client.run(f\"new bazel_7_lib -d name=mylib -d version=1.0 -d output_root_dir={bazel_output_root_dir}\")\n    client.run(\"create .\")\n    assert \"mylib/1.0: Hello World Release!\" in client.out\n\n@pytest.mark.slow\n@pytest.mark.parametrize(\"shared\", [False, True])\n@pytest.mark.tool(\"bazel\", \"6.x\")\ndef test_transitive_libs_consuming_6x(shared, bazel_output_root_dir):\n    \"\"\"\n    Testing the next dependencies structure for shared/static libs\n\n    /.\n    |- myfirstlib/\n         |- conanfile.py\n         |- WORKSPACE\n         |- main/\n            |- BUILD\n            |- myfirstlib.cpp\n            |- myfirstlib.h\n    |- mysecondlib/  (requires myfirstlib)\n         |- conanfile.py\n         |- WORKSPACE\n         |- main/\n            |- BUILD\n            |- mysecondlib.cpp\n            |- mysecondlib.h\n         |- test_package/\n            |- WORKSPACE\n            |- conanfile.py\n            |- main\n                |- example.cpp\n                |- BUILD\n    \"\"\"\n    client = TestClient(path_with_spaces=False)\n    # A regular library made with Bazel\n    with client.chdir(\"myfirstlib\"):\n        client.run(f\"new bazel_lib -d name=myfirstlib -d version=1.2.11 -d output_root_dir={bazel_output_root_dir}\")\n        conanfile = client.load(\"conanfile.py\")\n        conanfile += \"\"\"\n        self.cpp_info.defines.append(\"MY_DEFINE=\\\\\"MY_VALUE\\\\\"\")\n        self.cpp_info.defines.append(\"MY_OTHER_DEFINE=2\")\n        if self.settings.os != \"Windows\":\n            self.cpp_info.system_libs.append(\"m\")\n        else:\n            self.cpp_info.system_libs.append(\"ws2_32\")\n        \"\"\"\n        client.save({\"conanfile.py\": conanfile})\n        client.run(f\"create . -o '*:shared={shared}' -tf ''\")  # skipping tests\n\n    with client.chdir(\"mysecondlib\"):\n        # We prepare a consumer with Bazel (library mysecondlib using myfirstlib)\n        # and a test_package with an example executable\n        os_ = platform.system()\n        client.run(f\"new bazel_lib -d name=mysecondlib -d version=1.0 -d output_root_dir={bazel_output_root_dir}\")\n        conanfile = client.load(\"conanfile.py\")\n        conanfile = conanfile.replace('generators = \"BazelToolchain\"',\n                                      'generators = \"BazelToolchain\", \"BazelDeps\"\\n'\n                                      '    requires = \"myfirstlib/1.2.11\"')\n        workspace = textwrap.dedent(\"\"\"\n        load(\"@//conan:dependencies.bzl\", \"load_conan_dependencies\")\n        load_conan_dependencies()\n        \"\"\")\n        bazel_build_linux = textwrap.dedent(\"\"\"\\\n        cc_library(\n            name = \"mysecondlib\",\n            srcs = [\"mysecondlib.cpp\"],\n            hdrs = [\"mysecondlib.h\"],\n            deps = [ \"@myfirstlib//:myfirstlib\" ]\n        )\n        \"\"\")\n        bazel_build = textwrap.dedent(\"\"\"\\\n        cc_library(\n            name = \"mysecondlib\",\n            srcs = [\"mysecondlib.cpp\"],\n            hdrs = [\"mysecondlib.h\"],\n            deps = [ \"@myfirstlib//:myfirstlib\" ]\n        )\n\n        cc_shared_library(\n            name = \"mysecondlib_shared\",\n            shared_lib_name = \"libmysecondlib_shared.{}\",\n            deps = [\":mysecondlib\"],\n        )\n        \"\"\".format(\"dylib\" if os_ == \"Darwin\" else \"dll\"))\n        mysecondlib_cpp = textwrap.dedent(\"\"\"\n        #include <iostream>\n        #include \"mysecondlib.h\"\n        #include \"myfirstlib.h\"\n        #include <cmath>\n\n        void mysecondlib(){\n            std::cout << \"mysecondlib() First define \" << MY_DEFINE << \" and other define \" << MY_OTHER_DEFINE << std::endl;\n            myfirstlib();\n            // This comes from the systemlibs declared in the myfirstlib\n            sqrt(25);\n        }\n        void mysecondlib_print_vector(const std::vector<std::string> &strings) {\n            for(std::vector<std::string>::const_iterator it = strings.begin(); it != strings.end(); ++it) {\n                std::cout << \"mysecondlib/1.0 \" << *it << std::endl;\n            }\n        }\n        \"\"\")\n        mysecondlib_cpp_win = textwrap.dedent(\"\"\"\n        #include <iostream>\n        #include \"mysecondlib.h\"\n        #include \"myfirstlib.h\"\n        #include <WinSock2.h>\n\n        void mysecondlib(){\n            SOCKET foo; // From the system library\n            std::cout << \"mysecondlib() First define \" << MY_DEFINE << \" and other define \" << MY_OTHER_DEFINE << std::endl;\n            myfirstlib();\n        }\n        void mysecondlib_print_vector(const std::vector<std::string> &strings) {\n            for(std::vector<std::string>::const_iterator it = strings.begin(); it != strings.end(); ++it) {\n                std::cout << \"mysecondlib/1.0 \" << *it << std::endl;\n            }\n        }\n        \"\"\")\n        # Overwriting files\n        client.save({\"conanfile.py\": conanfile,\n                     \"WORKSPACE\": workspace,\n                     \"main/BUILD\": bazel_build_linux if os_ == \"Linux\" else bazel_build,\n                     \"main/mysecondlib.cpp\": mysecondlib_cpp if os_ != \"Windows\" else mysecondlib_cpp_win,\n                     })\n\n        client.run(f\"create . -o '*:shared={shared}'\")\n        assert \"mysecondlib() First define MY_VALUE and other define 2\" in client.out\n        assert \"myfirstlib/1.2.11: Hello World Release!\"\n\n\n@pytest.mark.slow\n@pytest.mark.parametrize(\"shared\", [False, True])\n@pytest.mark.tool(\"bazel\", \"7.x\")\n@pytest.mark.skipif(platform.system() == \"Linux\",\n                    reason=\"Conan CI fails (likely related to parallel \"\n                           \"tests running??). Skipping it for now!\")\ndef test_transitive_libs_consuming_7x(shared, bazel_output_root_dir):\n    \"\"\"\n    Testing the next dependencies structure for shared/static libs\n\n    /.\n    |- myfirstlib/\n         |- conanfile.py\n         |- MODULE.bazel\n         |- main/\n            |- BUILD\n            |- myfirstlib.cpp\n            |- myfirstlib.h\n    |- mysecondlib/  (requires myfirstlib)\n         |- conanfile.py\n         |- MODULE.bazel\n         |- main/\n            |- BUILD\n            |- mysecondlib.cpp\n            |- mysecondlib.h\n         |- test_package/\n            |- MODULE.bazel\n            |- conanfile.py\n            |- main\n                |- example.cpp\n                |- BUILD\n    \"\"\"\n    client = TestClient(path_with_spaces=False)\n    # A regular library made with Bazel\n    with client.chdir(\"myfirstlib\"):\n        client.run(f\"new bazel_7_lib -d name=myfirstlib -d version=1.2.11 -d output_root_dir={bazel_output_root_dir}\")\n        conanfile = client.load(\"conanfile.py\")\n        conanfile += \"\"\"\n        self.cpp_info.defines.append(\"MY_DEFINE=\\\\\"MY_VALUE\\\\\"\")\n        self.cpp_info.defines.append(\"MY_OTHER_DEFINE=2\")\n        if self.settings.os != \"Windows\":\n            self.cpp_info.system_libs.append(\"m\")\n        else:\n            self.cpp_info.system_libs.append(\"ws2_32\")\n        # Issue: https://github.com/conan-io/conan/issues/18748\n        from conan.tools.apple.apple import is_apple_os\n        if is_apple_os(self):\n            self.cpp_info.frameworks = [\"CoreFoundation\"]\n        \"\"\"\n        client.save({\"conanfile.py\": conanfile})\n        client.run(f\"create . -o '*:shared={shared}' -tf ''\")  # skipping tests\n\n    with client.chdir(\"mysecondlib\"):\n        # We prepare a consumer with Bazel (library mysecondlib using myfirstlib)\n        # and a test_package with an example executable\n        os_ = platform.system()\n        client.run(f\"new bazel_7_lib -d name=mysecondlib -d version=1.0 -d output_root_dir={bazel_output_root_dir}\")\n        conanfile = client.load(\"conanfile.py\")\n        conanfile = conanfile.replace('generators = \"BazelToolchain\"',\n                                      'generators = \"BazelToolchain\", \"BazelDeps\"\\n'\n                                      '    requires = \"myfirstlib/1.2.11\"')\n        workspace = textwrap.dedent(\"\"\"\n        load_conan_dependencies = use_extension(\"//conan:conan_deps_module_extension.bzl\", \"conan_extension\")\n        use_repo(load_conan_dependencies, \"myfirstlib\")\n        \"\"\")\n        bazel_build_linux = textwrap.dedent(\"\"\"\\\n        cc_library(\n            name = \"mysecondlib\",\n            srcs = [\"mysecondlib.cpp\"],\n            hdrs = [\"mysecondlib.h\"],\n            deps = [ \"@myfirstlib//:myfirstlib\" ]\n        )\n        \"\"\")\n        bazel_build = textwrap.dedent(\"\"\"\\\n        cc_library(\n            name = \"mysecondlib\",\n            srcs = [\"mysecondlib.cpp\"],\n            hdrs = [\"mysecondlib.h\"],\n            deps = [ \"@myfirstlib//:myfirstlib\" ]\n        )\n\n        cc_shared_library(\n            name = \"mysecondlib_shared\",\n            shared_lib_name = \"libmysecondlib_shared.{}\",\n            deps = [\":mysecondlib\"],\n        )\n        \"\"\".format(\"dylib\" if os_ == \"Darwin\" else \"dll\"))\n        mysecondlib_cpp = textwrap.dedent(\"\"\"\n        #include <iostream>\n        #include \"mysecondlib.h\"\n        #include \"myfirstlib.h\"\n        #include <cmath>\n\n        void mysecondlib(){\n            std::cout << \"mysecondlib() First define \" << MY_DEFINE << \" and other define \" << MY_OTHER_DEFINE << std::endl;\n            myfirstlib();\n            // This comes from the systemlibs declared in the myfirstlib\n            sqrt(25);\n        }\n        void mysecondlib_print_vector(const std::vector<std::string> &strings) {\n            for(std::vector<std::string>::const_iterator it = strings.begin(); it != strings.end(); ++it) {\n                std::cout << \"mysecondlib/1.0 \" << *it << std::endl;\n            }\n        }\n        \"\"\")\n        mysecondlib_cpp_win = textwrap.dedent(\"\"\"\n        #include <iostream>\n        #include \"mysecondlib.h\"\n        #include \"myfirstlib.h\"\n        #include <WinSock2.h>\n\n        void mysecondlib(){\n            SOCKET foo; // From the system library\n            std::cout << \"mysecondlib() First define \" << MY_DEFINE << \" and other define \" << MY_OTHER_DEFINE << std::endl;\n            myfirstlib();\n        }\n        void mysecondlib_print_vector(const std::vector<std::string> &strings) {\n            for(std::vector<std::string>::const_iterator it = strings.begin(); it != strings.end(); ++it) {\n                std::cout << \"mysecondlib/1.0 \" << *it << std::endl;\n            }\n        }\n        \"\"\")\n        # Overwriting files\n        client.save({\"conanfile.py\": conanfile,\n                     \"MODULE.bazel\": workspace,\n                     \"main/BUILD\": bazel_build_linux if os_ == \"Linux\" else bazel_build,\n                     \"main/mysecondlib.cpp\": mysecondlib_cpp if os_ != \"Windows\" else mysecondlib_cpp_win,\n                     })\n\n        client.run(f\"create . -o '*:shared={shared}'\")\n        assert \"mysecondlib() First define MY_VALUE and other define 2\" in client.out\n        assert \"myfirstlib/1.2.11: Hello World Release!\"\n\n\n@pytest.mark.slow\n@pytest.mark.tool(\"bazel\", \"8.x\")\ndef test_empty_bazel_query():\n    \"\"\"\n    Test that following a simple steps using the BazelDeps and running\n    a global `bazel query //...` runs OK (bazel >= 8.0)\n\n    Issue related: https://github.com/conan-io/conan/issues/18743\n    \"\"\"\n    zlib = GenConanfile(\"zlib\", \"0.1\")\n    consumer = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    from conan.tools.google import BazelDeps, bazel_layout\n\n    class App(ConanFile):\n        settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n        requires = \"zlib/0.1\"\n\n        def layout(self):\n            bazel_layout(self)\n\n        def generate(self):\n            bz = BazelDeps(self)\n            bz.generate()\n    \"\"\")\n    module = textwrap.dedent(\"\"\"\\\n    load_conan_dependencies = use_extension(\"//conan:conan_deps_module_extension.bzl\", \"conan_extension\")\n    use_repo(load_conan_dependencies, \"zlib\")\n    \"\"\")\n    client = TestClient()\n    client.save({\n        \"zlib/conanfile.py\": zlib,\n        \"consumer/conanfile.py\": consumer,\n        \"consumer/MODULE.bazel\": module,\n    })\n    client.run(\"create zlib\")\n    client.run(\"install consumer\")\n    with client.chdir(\"consumer\"):\n        client.run_command(\"bazel query //...\")\n    assert \"//conan/zlib:zlib\" in client.out\n    assert \"//conan/zlib:zlib_binaries\" in client.out\n"
  },
  {
    "path": "test/functional/toolchains/google/test_bazeltoolchain_cross_compilation.py",
    "content": "import os\nimport platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.sources import gen_function_cpp, gen_function_h\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.slow\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only for Darwin\")\n@pytest.mark.tool(\"bazel\", \"6.x\")  # not working for Bazel 7.x\ndef test_bazel_simple_cross_compilation():\n    profile = textwrap.dedent(\"\"\"\n    [settings]\n    arch=x86_64\n    build_type=Release\n    compiler=apple-clang\n    compiler.cppstd=gnu17\n    compiler.libcxx=libc++\n    compiler.version=13.0\n    os=Macos\n    \"\"\")\n    profile_host = textwrap.dedent(\"\"\"\n    [settings]\n    arch=armv8\n    build_type=Release\n    compiler=apple-clang\n    compiler.cppstd=gnu17\n    compiler.libcxx=libc++\n    compiler.version=13.0\n    os=Macos\n    \"\"\")\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    from conan.tools.google import Bazel, bazel_layout\n\n    class MyappConan(ConanFile):\n        name = \"myapp\"\n        version = \"1.0\"\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n        generators = \"BazelToolchain\"\n\n        def config_options(self):\n            if self.settings.os == \"Windows\":\n                del self.options.fPIC\n\n        def layout(self):\n            bazel_layout(self)\n\n        def build(self):\n            bazel = Bazel(self)\n            bazel.build()\n    \"\"\")\n    BUILD = textwrap.dedent(\"\"\"\n    cc_library(\n        name = \"myapp\",\n        srcs = [\"myapp.cpp\"],\n        hdrs = [\"myapp.h\"],\n    )\n    \"\"\")\n    client = TestClient(path_with_spaces=False)\n    bazel_root_dir = temp_folder(path_with_spaces=False).replace(\"\\\\\", \"/\")\n    client.save({\n        \"profile\": profile,\n        \"profile_host\": profile_host,\n        \"conanfile.py\": conanfile,\n        \"WORKSPACE\": \"\",\n        \".bazelrc\": f\"startup --output_user_root={bazel_root_dir}\",\n        \"main/BUILD\": BUILD,\n        \"main/myapp.cpp\": gen_function_cpp(name=\"myapp\"),\n        \"main/myapp.h\": gen_function_h(name=\"myapp\"),\n\n    })\n    client.run(\"build . -pr:h profile_host -pr:b profile\")\n    libmyapp = os.path.join(client.current_folder, \"bazel-bin\", \"main\", \"libmyapp.a\")\n    client.run_command(f'otool -hv {libmyapp}')\n    assert \"ARM64\" in client.out\n"
  },
  {
    "path": "test/functional/toolchains/intel/__init__.py",
    "content": ""
  },
  {
    "path": "test/functional/toolchains/intel/test_intel_cc.py",
    "content": "import pytest\nimport platform\nimport textwrap\n\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.tool(\"intel_oneapi\")\n@pytest.mark.xfail(reason=\"Intel oneAPI Toolkit is not installed on CI yet\")\n@pytest.mark.skipif(platform.system() != \"Linux\", reason=\"Only for Linux\")\nclass TestIntelCC:\n    \"\"\"Tests for Intel oneAPI C++/DPC++ compilers\"\"\"\n\n    def test_intel_oneapi_and_dpcpp(self):\n        client = TestClient()\n        # Let's create a default hello/0.1 example\n        client.run(\"new cmake_lib -d name=hello -d version=0.1\")\n        intel_profile = textwrap.dedent(\"\"\"\n            [settings]\n            os=Linux\n            arch=x86_64\n            compiler=intel-cc\n            compiler.mode=dpcpp\n            compiler.version=2021.3\n            compiler.libcxx=libstdc++\n            build_type=Release\n            [env]\n            CC=dpcpp\n            CXX=dpcpp\n        \"\"\")\n        client.save({\"intel_profile\": intel_profile})\n        # Build in the cache\n        client.run('create . --profile:build=intel_profile --profile:host=intel_profile')\n        assert \":: initializing oneAPI environment ...\" in client.out\n        assert \":: oneAPI environment initialized ::\" in client.out\n        assert \"Check for working CXX compiler: /opt/intel/oneapi/compiler/2021.3.0\" \\\n               \"/linux/bin/dpcpp -- works\" in client.out\n        assert \"hello/0.1: Package \" \\\n               \"'5d42bcd2e9be3378ed0c2f2928fe6dc9ea1b0922' created\" in client.out\n        # TODO:\n        #  self.t.run_command(exe)\n        #  self.assertIn(\"main __INTEL_COMPILER1910\", self.t.out)\n"
  },
  {
    "path": "test/functional/toolchains/intel/test_using_msbuild.py",
    "content": "import os\nimport platform\nimport pytest\nimport textwrap\n\nfrom conan.tools.microsoft.visual import vcvars_command\nfrom conan.test.assets.sources import gen_function_cpp\nfrom ..microsoft.test_msbuild import sln_file, myapp_vcxproj\n\nconanfile_py = textwrap.dedent(\"\"\"\n    from conan import ConanFile, MSBuild, MSBuildToolchain\n\n    class App(ConanFile):\n        settings = 'os', 'arch', 'compiler', 'build_type'\n        exports_sources = \"MyProject.sln\", \"MyApp/MyApp.vcxproj\", \"MyApp/MyApp.cpp\"\n        requires = \"hello/0.1\"\n\n        def generate(self):\n            tc = MSBuildToolchain(self)\n            tc.generate()\n\n        def build(self):\n            msbuild = MSBuild(self)\n            msbuild.build(\"MyProject.sln\")\n\"\"\")\n\n\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.tool(\"msbuild\")\n@pytest.mark.tool(\"icc\")\n@pytest.mark.xfail(reason=\"Intel compiler not installed yet on CI\")\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"msbuild requires Windows\")\nclass MSBuildIntelTestCase:\n    def test_use_msbuild_toolchain(self):\n        self.t.save({'profile': self.profile})\n        self.t.run(\"new hello/0.1 -s\")\n        self.t.run(\"create . --name=hello --version=0.1 -pr:h=profile\")\n\n        app = gen_function_cpp(name=\"main\", includes=[\"hello\"], calls=[\"hello\"])\n\n        # Prepare the actual consumer package\n        self.t.save({\"conanfile.py\": conanfile_py,\n                     \"MyProject.sln\": sln_file,\n                     \"MyApp/MyApp.vcxproj\": myapp_vcxproj,\n                     \"MyApp/MyApp.cpp\": app,\n                     'profile': self.profile},\n                    clean_first=True)\n\n        # Build in the cache\n        self.t.run(\"install . -pr:h=profile -of=conan\")\n\n        self.assertIn(\"conanfile.py: MSBuildToolchain created conan_toolchain_release_x64.props\",\n                      self.t.out)\n\n        self.t.run(\"build . -bf=conan\")\n        self.assertIn(\"Visual Studio 2017\", self.t.out)\n        self.assertIn(\"[vcvarsall.bat] Environment initialized for: 'x64'\", self.t.out)\n\n        exe = \"x64\\\\Release\\\\MyApp.exe\"\n        self.t.run_command(exe)\n        self.assertIn(\"main __INTEL_COMPILER1910\", self.t.out)\n\n        vcvars = vcvars_command(version=\"15\", architecture=\"x64\")\n        dumpbind_cmd = '%s && dumpbin /dependents \"%s\"' % (vcvars, exe)\n        self.t.run_command(dumpbind_cmd)\n        self.assertIn(\"KERNEL32.dll\", self.t.out)\n\n        # Build locally\n        os.unlink(os.path.join(self.t.current_folder, exe))\n\n        cmd = vcvars + ' && msbuild \"MyProject.sln\" /p:Configuration=Release ' \\\n                       '/p:Platform=x64 /p:PlatformToolset=\"Intel C++ Compiler 19.1\"'\n\n        self.t.run_command(cmd)\n        self.assertIn(\"Visual Studio 2017\", self.t.out)\n        self.assertIn(\"[vcvarsall.bat] Environment initialized for: 'x64'\", self.t.out)\n\n        self.t.run_command(exe)\n        self.assertIn(\"main __INTEL_COMPILER1910\", self.t.out)\n\n        self.t.run_command(dumpbind_cmd)\n        self.assertIn(\"KERNEL32.dll\", self.t.out)\n"
  },
  {
    "path": "test/functional/toolchains/ios/__init__.py",
    "content": ""
  },
  {
    "path": "test/functional/toolchains/ios/_utils.py",
    "content": "import textwrap\n\nlib_h = textwrap.dedent(\"\"\"\n    #pragma once\n    #include <string>\n    class HelloLib {\n    public:\n        void hello(const std::string& name);\n    };\n\"\"\")\n\nlib_cpp = textwrap.dedent(\"\"\"\n    #include \"hello.h\"\n    #include <iostream>\n    using namespace std;\n    void HelloLib::hello(const std::string& name) {\n        #ifdef DEBUG\n        std::cout << \"Hello \" << name << \" Debug!\" <<std::endl;\n        #else\n        std::cout << \"Hello \" << name << \" Release!\" <<std::endl;\n        #endif\n    }\n\"\"\")\n\ncmakelists = textwrap.dedent(\"\"\"\n    cmake_minimum_required(VERSION 3.1)\n    project(MyHello CXX)\n    set(SOURCES\n      hello.cpp\n   )\n    set(HEADERS\n        hello.h\n    )\n    add_library (hello ${SOURCES} ${HEADERS})\n    set_target_properties(hello PROPERTIES PUBLIC_HEADER \"${HEADERS}\")\n    install(TARGETS hello\n        RUNTIME DESTINATION bin\n        LIBRARY DESTINATION lib\n        ARCHIVE DESTINATION lib\n        PUBLIC_HEADER DESTINATION include\n    )\n\"\"\")\n\n\ndef create_library(client):\n    client.save({\n        'hello.h': lib_h,\n        'hello.cpp': lib_cpp,\n        'CMakeLists.txt': cmakelists\n    })\n"
  },
  {
    "path": "test/functional/toolchains/ios/test_using_cmake.py",
    "content": "import platform\nimport textwrap\n\nimport pytest\n\nfrom conan.tools.cmake import CMakeToolchain\nfrom conan.test.utils.tools import TestClient\nfrom ._utils import create_library\n\n\n@pytest.mark.slow\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Requires XCode\")\n@pytest.mark.tool(\"cmake\", \"3.19\")\ndef test_xcode_ios_generator():\n    \"\"\" Simplest approach:\n        https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling-for-ios-tvos-or-watchos\n    \"\"\"\n    t = TestClient()\n    create_library(t)\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake, CMakeToolchain\n\n        class Library(ConanFile):\n            name = 'hello'\n            version = '1.0'\n            settings = 'os', 'arch', 'compiler', 'build_type'\n            exports_sources = 'hello.h', 'hello.cpp', 'CMakeLists.txt'\n            options = {'shared': [True, False]}\n            default_options = {'shared': False}\n\n            def generate(self):\n                tc = CMakeToolchain(self, generator=\"Xcode\")\n                tc.generate()\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n                self.run(\"lipo -info Release-iphoneos/libhello.a\")\n\n            def package(self):\n                cmake = CMake(self)\n                cmake.install()\n        \"\"\")\n\n    ios_profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=iOS\n        os.sdk=iphoneos\n        os.version=12.0\n        arch=armv8\n        compiler=apple-clang\n        compiler.version=12.0\n        compiler.libcxx=libc++\n        build_type=Release\n        \"\"\")\n\n    t.save({'conanfile.py': conanfile,\n            \"ios_profile\": ios_profile})\n\n    # Build in the cache\n    t.run('create . --profile:build=default --profile:host=ios_profile')\n    assert \"Non-fat file: Release-iphoneos/libhello.a is architecture: arm64\" in t.out\n\n    # Build locally\n    t.run('install . --profile:host=ios_profile --profile:build=default')\n    t.run_command('cmake . -G\"Xcode\" -DCMAKE_TOOLCHAIN_FILE={}'.format(CMakeToolchain.filename))\n    t.run_command('cmake --build . --config Release')\n    t.run_command(\"lipo -info Release-iphoneos/libhello.a\")\n    assert \"Non-fat file: Release-iphoneos/libhello.a is architecture: arm64\" in t.out\n"
  },
  {
    "path": "test/functional/toolchains/meson/__init__.py",
    "content": ""
  },
  {
    "path": "test/functional/toolchains/meson/_base.py",
    "content": "import platform\n\n\ndef check_binary(t):\n    # FIXME: Some values are hardcoded to match the CI setup\n    host_arch = t.get_default_host_profile().settings['arch']\n    arch_macro = {\n        \"gcc\": {\"armv8\": \"__aarch64__\", \"x86_64\": \"__x86_64__\"},\n        \"msvc\": {\"armv8\": \"_M_ARM64\", \"x86_64\": \"_M_X64\"}\n    }\n    if platform.system() == \"Darwin\":\n        assert f\"main {arch_macro['gcc'][host_arch]} defined\" in t.out\n        assert \"main __apple_build_version__\" in t.out\n        assert \"main __clang_major__17\" in t.out\n        # TODO: check why __clang_minor__ seems to be not defined in XCode 12\n        # commented while migrating to XCode12 CI\n        # assert (\"main __clang_minor__0\" in t.out\n    elif platform.system() == \"Windows\":\n        assert f\"main {arch_macro['msvc'][host_arch]} defined\" in t.out\n        assert \"main _MSC_VER19\" in t.out\n        assert \"main _MSVC_LANG2014\" in t.out\n    elif platform.system() == \"Linux\":\n        assert f\"main {arch_macro['gcc'][host_arch]} defined\" in t.out\n        assert \"main __GNUC__9\" in t.out\n"
  },
  {
    "path": "test/functional/toolchains/meson/test_backend.py",
    "content": "import os\nimport platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.sources import gen_function_cpp\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.tool(\"meson\")\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"requires Windows\")\ndef test_cross_x86():\n    conanfile_py = textwrap.dedent(\"\"\"\n        from conan import ConanFile, tools\n        from conan.tools.meson import Meson, MesonToolchain\n\n\n        class App(ConanFile):\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            options = {\"shared\": [True, False], \"fPIC\": [True, False]}\n            default_options = {\"shared\": False, \"fPIC\": True}\n\n            def config_options(self):\n                if self.settings.os == \"Windows\":\n                    self.options.rm_safe(\"fPIC\")\n\n            def configure(self):\n                if self.options.shared:\n                    self.options.rm_safe(\"fPIC\")\n\n            def layout(self):\n                self.folders.build = \"build\"\n\n            def generate(self):\n                tc = MesonToolchain(self, backend='vs')\n                tc.generate()\n\n            def build(self):\n                meson = Meson(self)\n                meson.configure()\n                meson.build()\n        \"\"\")\n    meson_build = textwrap.dedent(\"\"\"\n        project('tutorial', 'cpp')\n        executable('demo', 'main.cpp')\n        \"\"\")\n    main_cpp = gen_function_cpp(name=\"main\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile_py,\n                 \"meson.build\": meson_build,\n                 \"main.cpp\": main_cpp})\n    client.run(\"install .\")\n    content = client.load(\"conan_meson_native.ini\")\n    assert \"backend = 'vs'\" in content\n    client.run(\"build .\")\n    assert \"Auto detected Visual Studio backend\" in client.out\n    client.run_command(os.path.join(\"build\", \"demo\"))\n\n    assert \"main _M_X64 defined\" in client.out\n    assert \"main _MSC_VER19\" in client.out\n    assert \"main _MSVC_LANG2014\" in client.out\n"
  },
  {
    "path": "test/functional/toolchains/meson/test_cross_compilation.py",
    "content": "import os\nimport platform\nimport tempfile\nimport textwrap\nimport pytest\n\nfrom conan.tools.apple.apple import _to_apple_arch, XCRun\nfrom conan.test.assets.sources import gen_function_cpp, gen_function_h\nfrom test.conftest import tools_locations\nfrom conan.test.utils.mocks import ConanFileMock\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.runners import conan_run\n\n_conanfile_py = textwrap.dedent(\"\"\"\nfrom conan import ConanFile\nfrom conan.tools.meson import Meson, MesonToolchain\n\n\nclass App(ConanFile):\n    settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n    options = {\"shared\": [True, False], \"fPIC\": [True, False]}\n    default_options = {\"shared\": False, \"fPIC\": True}\n\n    def layout(self):\n        self.folders.build = \"build\"\n\n    def config_options(self):\n        if self.settings.os == \"Windows\":\n            self.options.rm_safe(\"fPIC\")\n\n    def configure(self):\n        if self.options.shared:\n            self.options.rm_safe(\"fPIC\")\n\n    def generate(self):\n        tc = MesonToolchain(self)\n        tc.generate()\n\n    def build(self):\n        meson = Meson(self)\n        meson.configure()\n        meson.build()\n\"\"\")\n\n_meson_build = textwrap.dedent(\"\"\"\nproject('tutorial', 'cpp')\nadd_global_arguments('-DSTRING_DEFINITION=\"' + get_option('STRING_DEFINITION') + '\"',\n                     language : 'cpp')\nhello = library('hello', 'hello.cpp')\nexecutable('demo', 'main.cpp', link_with: hello)\n\"\"\")\n\n_meson_options_txt = textwrap.dedent(\"\"\"\noption('STRING_DEFINITION', type : 'string', description : 'a string option')\n\"\"\")\n\n\n@pytest.mark.tool(\"meson\")\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"requires Xcode\")\n@pytest.mark.parametrize(\"arch, os_, os_version, os_sdk\", [\n    ('armv8', 'iOS', '17.1', 'iphoneos'),\n    ('x86_64', 'iOS', '10.0', 'iphonesimulator'),\n    ('armv8' if platform.machine() == \"x86_64\" else \"x86_64\", 'Macos', None, None),\n    ('armv8' if platform.machine() == \"x86_64\" else \"x86_64\", 'Macos', '10.11', None),\n    ('armv8', 'visionOS', '1.0', 'xros'),\n    ('armv8', 'visionOS', '1.0', 'xrsimulator')\n])\ndef test_apple_meson_toolchain_cross_compiling(arch, os_, os_version, os_sdk):\n    profile = textwrap.dedent(\"\"\"\n    [settings]\n    os = {os}\n    {os_version}\n    {os_sdk}\n    arch = {arch}\n    compiler = apple-clang\n    compiler.version = 12.0\n    compiler.libcxx = libc++\n    \"\"\")\n\n    hello_h = gen_function_h(name=\"hello\")\n    hello_cpp = gen_function_cpp(name=\"hello\", preprocessor=[\"STRING_DEFINITION\"])\n    app = gen_function_cpp(name=\"main\", includes=[\"hello\"], calls=[\"hello\"])\n    profile = profile.format(\n        os=os_,\n        os_version=f\"os.version={os_version}\" if os_version else \"\",\n        os_sdk=\"os.sdk = \" + os_sdk if os_sdk else \"\",\n        arch=arch)\n\n    t = TestClient()\n    t.save({\"conanfile.py\": _conanfile_py,\n            \"meson.build\": _meson_build,\n            \"meson_options.txt\": _meson_options_txt,\n            \"hello.h\": hello_h,\n            \"hello.cpp\": hello_cpp,\n            \"main.cpp\": app,\n            \"profile_host\": profile})\n\n    t.run(\"build . --profile:build=default --profile:host=profile_host\")\n\n    libhello = os.path.join(t.current_folder, \"build\", \"libhello.a\")\n    assert os.path.isfile(libhello) is True\n    demo = os.path.join(t.current_folder, \"build\", \"demo\")\n    assert os.path.isfile(demo) is True\n\n    conanfile = ConanFileMock({}, runner=conan_run)\n    xcrun = XCRun(conanfile, os_sdk)\n    lipo = xcrun.find('lipo')\n\n    t.run_command('\"%s\" -info \"%s\"' % (lipo, libhello))\n    assert \"architecture: %s\" % _to_apple_arch(arch) in t.out\n\n    t.run_command('\"%s\" -info \"%s\"' % (lipo, demo))\n    assert \"architecture: %s\" % _to_apple_arch(arch) in t.out\n\n    if os_ == \"iOS\":\n        # only check for iOS because one of the macos build variants is usually native\n        content = t.load(\"conan_meson_cross.ini\")\n        assert \"needs_exe_wrapper = true\" in content\n    elif os_ == \"Macos\" and not os_version:\n        content = t.load(\"conan_meson_cross.ini\")\n        assert \"'-mmacosx-version-min=\" not in content\n    elif os_ == \"Macos\" and os_version:\n        # Issue related: https://github.com/conan-io/conan/issues/15459\n        content = t.load(\"conan_meson_cross.ini\")\n        assert f\"'-mmacosx-version-min={os_version}'\" in content\n\n\n@pytest.mark.tool(\"ninja\")\n@pytest.mark.tool(\"meson\")\n# for Linux, build for x86 will require a multilib compiler\n# for macOS, build for x86 is no longer supported by modern Xcode\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"requires Windows\")\ndef test_windows_cross_compiling_x86():\n    meson_build = textwrap.dedent(\"\"\"\n        project('tutorial', 'cpp')\n        executable('demo', 'main.cpp')\n        \"\"\")\n    main_cpp = gen_function_cpp(name=\"main\")\n    profile_x86 = textwrap.dedent(\"\"\"\n        include(default)\n        [settings]\n        arch=x86\n        \"\"\")\n\n    client = TestClient()\n    client.save({\"conanfile.py\": _conanfile_py,\n                 \"meson.build\": meson_build,\n                 \"main.cpp\": main_cpp,\n                 \"x86\": profile_x86})\n    profile_str = \"--profile:build=default --profile:host=x86\"\n    client.run(\"build . %s\" % profile_str)\n    client.run_command(os.path.join(\"build\", \"demo\"))\n    assert \"main _M_IX86 defined\" in client.out\n    assert \"main _MSC_VER19\" in client.out\n    assert \"main _MSVC_LANG2014\" in client.out\n\n\n@pytest.mark.parametrize(\"arch, expected_arch\", [('armv8', 'aarch64'),\n                                                 ('armv7', 'arm'),\n                                                 ('x86', 'i386'),\n                                                 ('x86_64', 'x86_64')])\n@pytest.mark.tool(\"meson\")\n@pytest.mark.tool(\"android_ndk\")\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Android NDK only tested in MacOS for now\")\ndef test_android_meson_toolchain_cross_compiling(arch, expected_arch):\n    profile_host = textwrap.dedent(\"\"\"\n    include(default)\n\n    [settings]\n    os = Android\n    os.api_level = 21\n    arch = {arch}\n\n    [conf]\n    tools.android:ndk_path={ndk_path}\n    \"\"\")\n    hello_h = gen_function_h(name=\"hello\")\n    hello_cpp = gen_function_cpp(name=\"hello\", preprocessor=[\"STRING_DEFINITION\"])\n    app = gen_function_cpp(name=\"main\", includes=[\"hello\"], calls=[\"hello\"])\n    ndk_path = tools_locations[\"android_ndk\"][\"system\"][\"path\"][platform.system()]\n    profile_host = profile_host.format(\n        arch=arch,\n        ndk_path=ndk_path\n    )\n\n    client = TestClient()\n    client.save({\"conanfile.py\": _conanfile_py,\n                 \"meson.build\": _meson_build,\n                 \"meson_options.txt\": _meson_options_txt,\n                 \"hello.h\": hello_h,\n                 \"hello.cpp\": hello_cpp,\n                 \"main.cpp\": app,\n                 \"profile_host\": profile_host})\n\n    client.run(\"build . --profile:build=default --profile:host=profile_host\")\n    content = client.load(os.path.join(\"conan_meson_cross.ini\"))\n    assert \"needs_exe_wrapper = true\" in content\n    assert \"Target machine cpu family: {}\".format(expected_arch if expected_arch != \"i386\" else \"x86\") in client.out\n    assert \"Target machine cpu: {}\".format(arch) in client.out\n    libhello_name = \"libhello.a\" if platform.system() != \"Windows\" else \"libhello.lib\"\n    libhello = os.path.join(client.current_folder, \"build\", libhello_name)\n    demo = os.path.join(client.current_folder, \"build\", \"demo\")\n    assert os.path.isfile(libhello)\n    assert os.path.isfile(demo)\n\n    # Check binaries architecture\n    if platform.system() == \"Darwin\":\n        client.run_command('objdump -f \"%s\"' % libhello)\n        assert \"architecture: %s\" % expected_arch in client.out\n\n\n@pytest.mark.tool(\"ninja\")\n@pytest.mark.tool(\"pkg_config\")\n@pytest.mark.tool(\"meson\")  # so it easily works in Windows too\n@pytest.mark.tool(\"android_ndk\")\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"NDK only installed on MAC\")\ndef test_use_meson_toolchain():\n    # TODO: Very similar to test in test_use_cmake_toolchain, refactor/restructure tests\n    # Overriding the default folders, so they are in the same unit drive in Windows\n    # otherwise AndroidNDK FAILS to build, it needs using the same unit drive\n    c = TestClient(cache_folder=tempfile.mkdtemp(),\n                   current_folder=tempfile.mkdtemp())\n    c.run(\"new meson_lib -d name=hello -d version=0.1\")\n    ndk_path = tools_locations[\"android_ndk\"][\"system\"][\"path\"][platform.system()]\n    pkgconf = tools_locations[\"pkg_config\"]\n    pkgconf_path = pkgconf[pkgconf[\"default\"]][\"path\"].get(platform.system()) + f'/pkg-config'\n    android = textwrap.dedent(f\"\"\"\n       [settings]\n       os=Android\n       os.api_level=23\n       arch=x86_64\n       compiler=clang\n       compiler.version=12\n       compiler.libcxx=c++_shared\n       build_type=Release\n       [conf]\n       tools.android:ndk_path={ndk_path}\n       tools.cmake.cmaketoolchain:generator=Ninja\n       tools.gnu:pkg_config={pkgconf_path}\n       \"\"\")\n    c.save({\"android\": android})\n    c.run('create . --profile:host=android')\n    assert \"hello/0.1 (test package): Running test()\" in c.out\n\n    # Build locally\n    c.run('build . --profile:host=android')\n    assert \"conanfile.py (hello/0.1): Calling build()\" in c.out\n\n\n@pytest.mark.tool(\"meson\")\n@pytest.mark.tool(\"ninja\")\n@pytest.mark.skipif(platform.system() != \"Linux\", reason=\"Linker scripts in Linux only\")\ndef test_linker_script():\n    # https://github.com/conan-io/conan/issues/18535\n    conanfile_py = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    from conan.tools.meson import Meson\n    from conan.tools.files import load\n\n    class App(ConanFile):\n        settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n        generators = \"MesonToolchain\"\n\n        def layout(self):\n            self.folders.build = \"build\"\n\n        def build(self):\n            meson = Meson(self)\n            try:\n                meson.configure()\n            finally:\n                errors = load(self, \"meson-logs/meson-log.txt\")\n                self.output.info(errors)\n    \"\"\")\n    meson_build = textwrap.dedent(\"\"\"\n        project('tutorial', 'cpp')\n        executable('demo', 'main.cpp')\n        \"\"\")\n    main_cpp = gen_function_cpp(name=\"main\")\n    profile = textwrap.dedent(\"\"\"\n        include(default)\n        [conf]\n        tools.build:linker_scripts=['{{profile_dir}}/mylinkscript.ld']\n        \"\"\")\n    c = TestClient()\n    c.save({\"conanfile.py\": conanfile_py,\n            \"meson.build\": meson_build,\n            \"main.cpp\": main_cpp,\n            \"mylinkscript.ld\": \"\",\n            \"profile\": profile})\n    c.run('build . -pr=profile', assert_error=True)\n    # This error means the linker script was fonud and loaded, it failed because empty\n    assert \"PHDR segment not covered by LOAD segment\" in c.out\n"
  },
  {
    "path": "test/functional/toolchains/meson/test_install.py",
    "content": "import os\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.sources import gen_function_cpp, gen_function_h\nfrom conan.test.utils.tools import TestClient\nfrom test.functional.toolchains.meson._base import check_binary\n\n\nclass TestMesonInstall:\n    _conanfile_py = textwrap.dedent(\"\"\"\n        import os\n        import shutil\n        from conan import ConanFile\n        from conan.tools.meson import Meson, MesonToolchain\n\n\n        class App(ConanFile):\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            options = {\"shared\": [True, False], \"fPIC\": [True, False]}\n            default_options = {\"shared\": False, \"fPIC\": True}\n            exports_sources = \"meson.build\", \"hello.cpp\", \"hello.h\"\n\n            def config_options(self):\n                if self.settings.os == \"Windows\":\n                    self.options.rm_safe(\"fPIC\")\n\n            def configure(self):\n                if self.options.shared:\n                    self.options.rm_safe(\"fPIC\")\n\n            def layout(self):\n                self.folders.build = \"build\"\n\n            def generate(self):\n                tc = MesonToolchain(self)\n                tc.generate()\n\n            def build(self):\n                meson = Meson(self)\n                meson.configure()\n                meson.build()\n\n            def package(self):\n                meson = Meson(self)\n                meson.install()\n\n                # https://mesonbuild.com/FAQ.html#why-does-building-my-project-with-msvc-output-static-libraries-called-libfooa\n                if self.settings.compiler == 'msvc' and not self.options.shared:\n                    shutil.move(os.path.join(self.package_folder, \"lib\", \"libhello.a\"),\n                                os.path.join(self.package_folder, \"lib\", \"hello.lib\"))\n\n            def package_info(self):\n                self.cpp_info.libs = ['hello']\n        \"\"\")\n\n    _meson_build = textwrap.dedent(\"\"\"\n        project('tutorial', 'cpp')\n        library('hello', 'hello.cpp', install: true)\n        install_headers('hello.h')\n        \"\"\")\n\n    _test_package_conanfile_py = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.cmake import CMake, cmake_layout\n        from conan.tools.build import cross_building\n\n        class TestConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"CMakeToolchain\", \"CMakeDeps\"\n\n            def requirements(self):\n                self.requires(self.tested_reference_str)\n\n            def layout(self):\n                cmake_layout(self)\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n\n            def test(self):\n                if not cross_building(self):\n                    cmd = os.path.join(self.cpp.build.bindirs[0], \"test_package\")\n                    self.run(cmd, env=[\"conanrunenv\"])\n        \"\"\")\n\n    _test_package_cmake_lists = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.1)\n        project(test_package CXX)\n\n        add_executable(${PROJECT_NAME} src/test_package.cpp)\n        find_package(hello CONFIG REQUIRED)\n        target_link_libraries(${PROJECT_NAME} hello::hello)\n        \"\"\")\n\n    @pytest.mark.tool(\"ninja\")\n    @pytest.mark.tool(\"meson\")\n    @pytest.mark.tool(\"cmake\")\n    def test_install(self):\n        t = TestClient()\n        hello_cpp = gen_function_cpp(name=\"hello\")\n        hello_h = gen_function_h(name=\"hello\")\n        test_package_cpp = gen_function_cpp(name=\"main\", includes=[\"hello\"], calls=[\"hello\"])\n\n        t.save({\"conanfile.py\": self._conanfile_py,\n                \"meson.build\": self._meson_build,\n                \"hello.cpp\": hello_cpp,\n                \"hello.h\": hello_h,\n                os.path.join(\"test_package\", \"conanfile.py\"): self._test_package_conanfile_py,\n                os.path.join(\"test_package\", \"CMakeLists.txt\"): self._test_package_cmake_lists,\n                os.path.join(\"test_package\", \"src\", \"test_package.cpp\"): test_package_cpp})\n\n        t.run(\"create . --name=hello --version=0.1 -c tools.compilation:verbosity=verbose\")\n        assert \"--verbose\" in t.out\n        check_binary(t)\n"
  },
  {
    "path": "test/functional/toolchains/meson/test_meson.py",
    "content": "import os\nimport platform\nimport re\nimport sys\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.sources import gen_function_cpp, gen_function_h\nfrom conan.test.utils.tools import TestClient\nfrom conan.api.model import RecipeReference\nfrom test.functional.toolchains.meson._base import check_binary\n\n\n@pytest.mark.tool(\"ninja\")\n@pytest.mark.tool(\"meson\")\nclass TestMesonToolchain:\n\n    def test_definition_of_global_options(self):\n        t = TestClient()\n        conanfile_py = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.meson import Meson, MesonToolchain\n\n\n        class App(ConanFile):\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            options = {{\"shared\": [True, False], \"fPIC\": [True, False], \"msg\": [\"ANY\"]}}\n            default_options = {{\"shared\": False, \"fPIC\": True, \"msg\": \"Hi everyone!\"}}\n\n            def config_options(self):\n                if self.settings.os == \"Windows\":\n                    self.options.rm_safe(\"fPIC\")\n\n            def configure(self):\n                if self.options.shared:\n                    self.options.rm_safe(\"fPIC\")\n\n            def layout(self):\n                self.folders.generators = 'build/gen_folder'\n                self.folders.build = \"build\"\n\n            def generate(self):\n                tc = MesonToolchain(self)\n                tc.project_options[\"STRING_DEFINITION\"] = \"Text\"\n                tc.project_options[\"TRUE_DEFINITION\"] = True\n                tc.project_options[\"FALSE_DEFINITION\"] = False\n                tc.project_options[\"INT_DEFINITION\"] = 42\n                tc.project_options[\"ARRAY_DEFINITION\"] = [\"Text1\", \"Text2\"]\n                # Meson converts True/False into true/false boolean values\n                tc.project_options[\"DYNAMIC\"] = self.options.shared\n                # This one will fail because HELLO_MSG = Hi everyone is an invalid value\n                # The good one should be HELLO_MSG = \"Hi everyone\"\n                tc.project_options[\"HELLO_MSG\"] = {msg}\n                tc.generate()\n\n            def build(self):\n                meson = Meson(self)\n                meson.configure()\n                meson.build(target='hello')\n                meson.build(target='demo')\n        \"\"\")\n\n        meson_options_txt = textwrap.dedent(\"\"\"\n        option('STRING_DEFINITION', type : 'string', description : 'a string option')\n        option('INT_DEFINITION', type : 'integer', description : 'an integer option', value: 0)\n        option('FALSE_DEFINITION', type : 'boolean', description : 'a boolean option (false)')\n        option('TRUE_DEFINITION', type : 'boolean', description : 'a boolean option (true)')\n        option('ARRAY_DEFINITION', type : 'array', description : 'an array option')\n        option('HELLO_MSG', type : 'string', description : 'message to print')\n        option('DYNAMIC', type : 'boolean', description : 'shared to true or false')\n        \"\"\")\n\n        meson_build = textwrap.dedent(\"\"\"\n        project('tutorial', 'cpp')\n        add_global_arguments('-DSTRING_DEFINITION=\"' + get_option('STRING_DEFINITION') + '\"',\n                             language : 'cpp')\n        add_global_arguments('-DHELLO_MSG=\"' + get_option('HELLO_MSG') + '\"', language : 'cpp')\n        hello = library('hello', 'hello.cpp')\n        executable('demo', 'main.cpp', link_with: hello)\n        \"\"\")\n\n        hello_h = gen_function_h(name=\"hello\")\n        hello_cpp = gen_function_cpp(name=\"hello\", preprocessor=[\"STRING_DEFINITION\"])\n        app = gen_function_cpp(name=\"main\", includes=[\"hello\"], calls=[\"hello\"])\n\n        # Issue related: https://github.com/conan-io/conan/issues/14453\n        # At first, let's add a raw option to see that it fails\n        t.save({\"conanfile.py\": conanfile_py.format(msg=\"self.options.msg\"),\n                \"meson.build\": meson_build,\n                \"meson_options.txt\": meson_options_txt,\n                \"hello.h\": hello_h,\n                \"hello.cpp\": hello_cpp,\n                \"main.cpp\": app})\n        t.run(\"build .\", assert_error=True)\n        # Using directly the options, the result is -> HELLO_MSG = Hi everyone, which is incorrect\n        assert \"WARN: deprecated: Please, do not use a Conan option value directly. \" \\\n               \"Convert 'options.shared' into\" in t.out\n        assert \"WARN: deprecated: Please, do not use a Conan option value directly. \" \\\n               \"Convert 'options.msg' into\" in t.out\n        assert \"Malformed value\" in t.out\n        # Let's transform the Conan option into other allowed data type to solve the issue\n        t.save({\"conanfile.py\": conanfile_py.format(msg=\"str(self.options.msg)\")})\n        t.run(\"build .\")\n        content = t.load(os.path.join(\"build\", \"gen_folder\", \"conan_meson_native.ini\"))\n        assert \"[project options]\" in content\n        assert \"STRING_DEFINITION = 'Text'\" in content\n        assert \"TRUE_DEFINITION = true\" in content\n        assert \"FALSE_DEFINITION = false\" in content\n        assert \"DYNAMIC = False\" in content  # Meson transforms correctly this value into bool\n        assert \"HELLO_MSG = 'Hi everyone!'\" in content\n        assert \"INT_DEFINITION = 42\" in content\n        assert \"ARRAY_DEFINITION = ['Text1', 'Text2']\" in content\n        assert \"[built-in options]\" in content\n        assert \"buildtype = 'release'\" in content\n\n        t.run_command(os.path.join(\"build\", \"demo\"))\n        assert \"hello: Release!\" in t.out\n        assert \"STRING_DEFINITION: Text\" in t.out\n        assert \"[properties]\" in content\n        assert \"needs_exe_wrapper\" not in content\n\n        check_binary(t)\n\n    def test_meson_default_dirs(self):\n        t = TestClient()\n        t.run(\"new meson_exe -d name=hello -d version=1.0\")\n        # t.run(\"new meson_exe -d name=hello -d version=1.0 -m meson_exe\")\n\n        meson_build = textwrap.dedent(\"\"\"\n        project('tutorial', 'cpp')\n        # Creating specific library\n        hello = library('hello', 'src/hello.cpp', install: true)\n        # Creating specific executable\n        executable('demo', 'src/main.cpp', link_with: hello, install: true)\n        # Creating specific data in src/ (they're going to be exported)\n        install_data(['src/file1.txt', 'src/file2.txt'])\n        \"\"\")\n        conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.meson import Meson\n        class HelloConan(ConanFile):\n            name = \"hello\"\n            version = \"1.0\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            exports_sources = \"meson.build\", \"src/*\"\n            generators = \"MesonToolchain\"\n            package_type = \"application\"\n\n            def layout(self):\n                self.folders.build = \"build\"\n                # Only adding \"res\" to resdirs\n                self.cpp.package.resdirs = [\"res\"]\n\n            def build(self):\n                meson = Meson(self)\n                meson.configure()\n                meson.build()\n\n            def package(self):\n                meson = Meson(self)\n                meson.install()\n        \"\"\")\n        test_conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.build import cross_building\n        class HelloTestConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n            def requirements(self):\n                self.requires(self.tested_reference_str)\n\n            def test(self):\n                if not cross_building(self):\n                    self.run(\"demo\", env=\"conanrun\")\n        \"\"\")\n        # Replace meson.build, conanfile.py and test_package/conanfile.py\n        t.save({\"meson.build\": meson_build,\n                \"conanfile.py\": conanfile,\n                \"test_package/conanfile.py\": test_conanfile,\n                \"src/file1.txt\": \"\", \"src/file2.txt\": \"\"})\n        t.run(\"create . -c tools.build:verbosity=quiet -c tools.compilation:verbosity=verbose\")\n        # Check verbosity control\n        assert \"unrecognized arguments\" not in t.out\n        assert re.search(\"meson compile .*? --verbose\", t.out)\n        assert re.search(\"meson install .*? --quiet\", t.out)\n\n        # Check if all the files are in the final directories\n        ref = RecipeReference.loads(\"hello/1.0\")\n        pref = t.get_latest_package_reference(ref)\n        package_folder = t.get_latest_pkg_layout(pref).package()\n        if platform.system() == \"Windows\":\n            assert os.path.exists(os.path.join(package_folder, \"lib\", \"hello.lib\"))\n            assert os.path.exists(os.path.join(package_folder, \"bin\", \"hello.dll\"))\n            assert os.path.exists(os.path.join(package_folder, \"bin\", \"demo.exe\"))\n        else:\n            ext = \"dylib\" if platform.system() == \"Darwin\" else \"so\"\n            assert os.path.exists(os.path.join(package_folder, \"bin\", \"demo\"))\n            assert os.path.exists(os.path.join(package_folder, \"lib\", \"libhello.\" + ext))\n        # res/tutorial -> tutorial is being added automatically by Meson\n        assert os.path.exists(os.path.join(package_folder, \"res\", \"tutorial\", \"file1.txt\"))\n        assert os.path.exists(os.path.join(package_folder, \"res\", \"tutorial\", \"file2.txt\"))\n\n\n@pytest.mark.tool(\"meson\")\n@pytest.mark.skipif(sys.version_info.minor < 8, reason=\"Latest Meson versions needs Python >= 3.8\")\ndef test_meson_and_additional_machine_files_composition():\n    \"\"\"\n    Testing when users wants to append their own meson machine files and override/complement some\n    sections from Conan file ones.\n\n    See more information in Meson web page: https://mesonbuild.com/Machine-files.html\n\n    In this test, we're overriding only the Meson section ``[binaries]`` for instance.\n    \"\"\"\n    profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=Windows\n        arch=x86_64\n        compiler=gcc\n        compiler.version=9\n        compiler.cppstd=17\n        compiler.libcxx=libstdc++11\n        build_type=Release\n\n        [conf]\n        tools.meson.mesontoolchain:extra_machine_files=[\"myfilename.ini\"]\n   \"\"\")\n    myfilename = textwrap.dedent(\"\"\"\n    [project options]\n    my_option = 'fake-option'\n    \"\"\")\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    from conan.tools.meson import Meson\n    class Pkg(ConanFile):\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n        generators = \"MesonToolchain\"\n        def build(self):\n            meson = Meson(self)\n            meson.configure()\n            meson.build()\n    \"\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile,\n                 \"build/myfilename.ini\": myfilename,\n                 \"meson.build\": \"project('tutorial', 'cpp')\",  # dummy one\n                 \"profile\": profile})\n\n    client.run(\"install . -pr:h=profile -pr:b=profile\")\n    client.run(\"build . -pr:h=profile -pr:b=profile\", assert_error=True)\n    # Checking the order of the appended user file (the order matters)\n    match = re.search(r\"meson setup --native-file .* --native-file \\\"myfilename\\.ini\\\"\", client.out)\n    assert match\n\n\n@pytest.mark.tool(\"ninja\")\n@pytest.mark.tool(\"meson\")\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Only for Windows\")\n@pytest.mark.skipif(sys.version_info.minor < 8, reason=\"Latest Meson versions needs Python >= 3.8\")\ndef test_meson_using_prefix_path_in_application():\n    \"\"\"\n    Issue related https://github.com/conan-io/conan/issues/14213\n    \"\"\"\n    meson_build = textwrap.dedent(\"\"\"\n    project('myhello ', 'c')\n    executable('myhello', 'src/main.c', install: true)\n\n    prefix_dir = get_option('prefix')\n    cfg_var = configuration_data()\n    cfg_var.set_quoted('MYHELLO_PREFIX', prefix_dir)\n\n    config_file = configure_file(\n        configuration: cfg_var,\n        output: 'config.h'\n    )\n    \"\"\")\n    main_c = textwrap.dedent(\"\"\"\n    #include <config.h>\n\n    int main(void) {\n        return 0;\n    }\n\n    char *issue_func() {\n        return (MYHELLO_PREFIX);\n    }\n    \"\"\")\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    from conan.tools.meson import Meson\n    from conan.tools.layout import basic_layout\n\n    class myhelloConan(ConanFile):\n        name = \"demo\"\n        version = \"0.1\"\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n        exports_sources = \"meson.build\", \"*.c\"\n        package_type = \"application\"\n        generators = \"MesonToolchain\"\n\n        def layout(self):\n            basic_layout(self)\n\n        def build(self):\n            meson = Meson(self)\n            meson.configure()\n            meson.build()\n    \"\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile,\n                 \"src/main.c\": main_c,\n                 \"meson.build\": meson_build})\n    client.run(\"build .\")\n    assert \"unrecognized character escape sequence\" not in str(client.out)  # if Visual\n    assert \"unknown escape sequence\" not in str(client.out)  # if mingw\n"
  },
  {
    "path": "test/functional/toolchains/meson/test_meson_and_gnu_deps_flags.py",
    "content": "import os\nimport platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestMesonToolchainAndGnuFlags:\n\n    @pytest.mark.tool(\"ninja\")\n    @pytest.mark.tool(\"meson\")\n    @pytest.mark.tool(\"pkg_config\")\n    def test_mesondeps_flags_are_being_appended_and_not_replacing_toolchain_ones(self):\n        \"\"\"\n        Test PkgConfigDeps and MesonToolchain are keeping all the flags/definitions defined\n        from both generators and nothing is being messed up.\n        \"\"\"\n        client = TestClient(path_with_spaces=False)\n        if platform.system() == \"Windows\":\n            deps_flags = '\"/GA\", \"/analyze:quiet\"'\n            flags = '\"/Wall\", \"/W4\"'\n        else:\n            deps_flags = '\"-Wpedantic\", \"-Werror\"'\n            flags = '\"-Wall\", \"-finline-functions\"'\n        # Dependency - hello/0.1\n        conanfile_py = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class HelloConan(ConanFile):\n            name = \"hello\"\n            version = \"0.1\"\n\n            def package_info(self):\n                self.cpp_info.cxxflags = [{}]\n                self.cpp_info.defines = ['DEF1=one_string', 'DEF2=other_string']\n        \"\"\".format(deps_flags))\n        client.save({\"conanfile.py\": conanfile_py})\n        client.run(\"create .\")\n        # Dependency - other/0.1\n        conanfile_py = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class OtherConan(ConanFile):\n            name = \"other\"\n            version = \"0.1\"\n\n            def package_info(self):\n                self.cpp_info.defines = ['DEF3=simple_string']\n        \"\"\")\n        client.save({\"conanfile.py\": conanfile_py}, clean_first=True)\n        client.run(\"create .\")\n\n        # Consumer using PkgConfigDeps and MesonToolchain\n        conanfile_py = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.meson import Meson, MesonToolchain\n        from conan.tools.gnu import PkgConfigDeps\n\n        class App(ConanFile):\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            requires = \"hello/0.1\", \"other/0.1\"\n\n            def layout(self):\n                self.folders.build = \"build\"\n\n            def generate(self):\n                deps = PkgConfigDeps(self)\n                deps.generate()\n                tc = MesonToolchain(self)\n                tc.preprocessor_definitions[\"VAR\"] = \"VALUE\"\n                tc.preprocessor_definitions[\"VAR2\"] = \"VALUE2\"\n                tc.generate()\n\n            def build(self):\n                meson = Meson(self)\n                meson.configure()\n                meson.build()\n        \"\"\")\n\n        meson_build = textwrap.dedent(\"\"\"\n            project('tutorial', 'cpp')\n            cxx = meson.get_compiler('cpp')\n            hello = dependency('hello', version : '>=0.1')\n            other = dependency('other', version : '>=0.1')\n            # It's not needed to declare \"hello/0.1\" as a dependency, only interested in flags\n            executable('demo', 'main.cpp', dependencies: [hello, other])\n        \"\"\")\n\n        main = textwrap.dedent(\"\"\"\n            #include <stdio.h>\n            #define STR(x)   #x\n            #define SHOW_DEFINE(x) printf(\"%s=%s\", #x, STR(x))\n            int main(int argc, char *argv[]) {\n                SHOW_DEFINE(VAR);\n                SHOW_DEFINE(VAR2);\n                SHOW_DEFINE(DEF1);\n                SHOW_DEFINE(DEF2);\n                SHOW_DEFINE(DEF3);\n                return 0;\n            }\n        \"\"\")\n\n        client.save({\"conanfile.py\": conanfile_py,\n                     \"meson.build\": meson_build,\n                     \"main.cpp\": main},\n                    clean_first=True)\n\n        client.run(\"build . -c 'tools.build:cxxflags=[%s]'\" % flags)\n        assert \"WARN: deprecated: Use 'extra_defines' attribute for compiler preprocessor \" \\\n               \"definitions instead of 'preprocessor_definitions'\" in client.out\n\n        app_name = \"demo.exe\" if platform.system() == \"Windows\" else \"demo\"\n        client.run_command(os.path.join(\"build\", app_name))\n        assert 'VAR=\"VALUE' in client.out\n        assert 'VAR2=\"VALUE2\"' in client.out\n        assert 'DEF1=one_string' in client.out\n        assert 'DEF2=other_string' in client.out\n        assert 'DEF3=simple_string' in client.out\n"
  },
  {
    "path": "test/functional/toolchains/meson/test_meson_and_objc.py",
    "content": "import os\nimport platform\nimport textwrap\n\nimport pytest\n\nfrom conan.tools.apple.apple import _to_apple_arch, XCRun\nfrom conan.test.utils.mocks import ConanFileMock\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.runners import conan_run\n\n_conanfile_py = textwrap.dedent(\"\"\"\nfrom conan import ConanFile\nfrom conan.tools.meson import Meson, MesonToolchain\n\n\nclass App(ConanFile):\n    settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n    options = {\"shared\": [True, False], \"fPIC\": [True, False]}\n    default_options = {\"shared\": False, \"fPIC\": True}\n\n    def layout(self):\n        self.folders.build = \"build\"\n\n    def config_options(self):\n        if self.settings.os == \"Windows\":\n            self.options.rm_safe(\"fPIC\")\n\n    def configure(self):\n        if self.options.shared:\n            self.options.rm_safe(\"fPIC\")\n\n    def generate(self):\n        tc = MesonToolchain(self)\n        tc.generate()\n\n    def build(self):\n        meson = Meson(self)\n        meson.configure()\n        meson.build()\n\"\"\")\n\n_meson_build_objc = textwrap.dedent(\"\"\"\nproject('tutorial', 'objc')\nexecutable('demo', 'main.m', link_args: ['-framework', 'Foundation'])\n\"\"\")\n\n\n@pytest.mark.tool(\"meson\")\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"requires Xcode\")\ndef test_apple_meson_toolchain_native_compilation_objective_c():\n    t = TestClient()\n    arch = t.get_default_host_profile().settings['arch']\n    profile = textwrap.dedent(f\"\"\"\n    [settings]\n    os = Macos\n    arch = {arch}\n    compiler = apple-clang\n    compiler.version = 12.0\n    compiler.libcxx = libc++\n    \"\"\")\n    app = textwrap.dedent(\"\"\"\n    #import <Foundation/Foundation.h>\n\n    int main(int argc, const char * argv[]) {\n        @autoreleasepool {\n            // insert code here...\n            NSLog(@\"Hello, World!\");\n        }\n        return 0;\n    }\n    \"\"\")\n    t.save({\"conanfile.py\": _conanfile_py,\n            \"meson.build\": _meson_build_objc,\n            \"main.m\": app,\n            \"macos_pr\": profile})\n\n    t.run(\"build . -pr macos_pr\")\n    t.run_command(\"./demo\", cwd=os.path.join(t.current_folder, \"build\"))\n    assert \"Hello, World!\" in t.out\n\n\n@pytest.mark.parametrize(\"arch, os_, os_version, sdk\", [\n    ('armv8', 'iOS', '10.0', 'iphoneos'),\n    ('x86_64', 'iOS', '10.0', 'iphonesimulator'),\n    ('armv8', 'Macos', '11.0', None)  # Apple Silicon\n])\n@pytest.mark.tool(\"meson\")\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"requires Xcode\")\ndef test_apple_meson_toolchain_cross_compiling_and_objective_c(arch, os_, os_version, sdk):\n    profile = textwrap.dedent(\"\"\"\n    include(default)\n\n    [settings]\n    os = {os}\n    os.version = {os_version}\n    {os_sdk}\n    arch = {arch}\n    compiler = apple-clang\n    compiler.version = 12.0\n    compiler.libcxx = libc++\n    \"\"\")\n\n    app = textwrap.dedent(\"\"\"\n    #import <Foundation/Foundation.h>\n\n    int main(int argc, const char * argv[]) {\n        @autoreleasepool {\n            // insert code here...\n            NSLog(@\"Hello, World!\");\n        }\n        return 0;\n    }\n    \"\"\")\n    profile = profile.format(\n        os=os_,\n        os_version=os_version,\n        os_sdk=f'os.sdk = {sdk}' if sdk else '',\n        arch=arch)\n\n    t = TestClient()\n    t.save({\"conanfile.py\": _conanfile_py,\n            \"meson.build\": _meson_build_objc,\n            \"main.m\": app,\n            \"profile_host\": profile})\n\n    t.run(\"build . --profile:build=default --profile:host=profile_host\")\n    assert \"Objective-C compiler for the host machine: clang\" in t.out\n\n    demo = os.path.join(t.current_folder, \"build\", \"demo\")\n    assert os.path.isfile(demo) is True\n\n    conanfile = ConanFileMock({}, runner=conan_run)\n    xcrun = XCRun(conanfile, sdk)\n    lipo = xcrun.find('lipo')\n    t.run_command('\"%s\" -info \"%s\"' % (lipo, demo))\n    assert \"architecture: %s\" % _to_apple_arch(arch) in t.out\n"
  },
  {
    "path": "test/functional/toolchains/meson/test_meson_native_attribute.py",
    "content": "import os\nimport platform\nimport textwrap\n\nimport pytest\n\nfrom conan.tools.apple.apple import _to_apple_arch, XCRun\nfrom conan.test.assets.sources import gen_function_cpp, gen_function_h\nfrom conan.test.utils.mocks import ConanFileMock\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.runners import conan_run\n\n\n@pytest.mark.tool(\"meson\")\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"requires OSX\")\ndef test_apple_meson_toolchain_cross_compiling():\n    arch_host = 'armv8' if platform.machine() == \"x86_64\" else \"x86_64\"\n    arch_build = 'armv8' if platform.machine() != \"x86_64\" else \"x86_64\"\n    profile = textwrap.dedent(f\"\"\"\n    [settings]\n    os = Macos\n    arch = {arch_host}\n    compiler = apple-clang\n    compiler.version = 13.0\n    compiler.libcxx = libc++\n    \"\"\")\n    profile_build = textwrap.dedent(f\"\"\"\n    [settings]\n    os = Macos\n    arch = {arch_build}\n    compiler = apple-clang\n    compiler.version = 13.0\n    compiler.libcxx = libc++\n    \"\"\")\n    conanfile_py = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    from conan.tools.meson import Meson, MesonToolchain\n    from conan.tools.build import cross_building\n\n    class App(ConanFile):\n        settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n        options = {\"shared\": [True, False], \"fPIC\": [True, False]}\n        default_options = {\"shared\": False, \"fPIC\": True}\n\n        def layout(self):\n            self.folders.build = \"build\"\n\n        def config_options(self):\n            if self.settings.os == \"Windows\":\n                self.options.rm_safe(\"fPIC\")\n\n        def configure(self):\n            if self.options.shared:\n                self.options.rm_safe(\"fPIC\")\n\n        def generate(self):\n            tc = MesonToolchain(self)\n            tc.generate()\n            # Forcing to create the native context too\n            if cross_building(self):\n                tc = MesonToolchain(self, native=True)\n                tc.generate()\n\n        def build(self):\n            meson = Meson(self)\n            meson.configure()\n            meson.build()\n    \"\"\")\n    meson_build = textwrap.dedent(\"\"\"\n    project('tutorial', 'cpp')\n    hello = library('hello', 'hello.cpp')\n    # Even cross-building the library, we want to create an executable using only the native context\n    executable('mygen', 'mygen.cpp', native: true)\n    \"\"\")\n    my_gen_cpp = gen_function_cpp(name=\"main\")\n    hello_h = gen_function_h(name=\"hello\")\n    hello_cpp = gen_function_cpp(name=\"hello\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile_py,\n                 \"meson.build\": meson_build,\n                 \"hello.h\": hello_h,\n                 \"hello.cpp\": hello_cpp,\n                 \"mygen.cpp\": my_gen_cpp,\n                 \"profile_host\": profile,\n                 \"profile_build\": profile_build})\n    client.run(\"build . --profile:build=profile_build --profile:host=profile_host\")\n    libhello = os.path.join(client.current_folder, \"build\", \"libhello.a\")\n    assert os.path.isfile(libhello) is True\n    # Now, ensuring that we can run the mygen executable\n    mygen = os.path.join(client.current_folder, \"build\", \"mygen\")\n    client.run_command(f\"'{mygen}'\")\n    assert \"Release!\" in client.out\n    # Extra check for lib arch\n    conanfile = ConanFileMock({}, runner=conan_run)\n    xcrun = XCRun(conanfile)\n    lipo = xcrun.find('lipo')\n    client.run_command('\"%s\" -info \"%s\"' % (lipo, libhello))\n    assert \"architecture: %s\" % _to_apple_arch(arch_host) in client.out\n"
  },
  {
    "path": "test/functional/toolchains/meson/test_meson_transitive_rpath_sysroot.py",
    "content": "import platform\nimport textwrap\n\nimport pytest\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.tool(\"ninja\")\n@pytest.mark.tool(\"meson\")\n@pytest.mark.tool(\"pkg_config\")\n@pytest.mark.skipif(platform.system() != \"Linux\", reason=\"Linux/gcc required for -rpath/-rpath-link testing\")\ndef test_meson_sysroot_transitive_rpath():\n    c = TestClient()\n\n    extra_profile = textwrap.dedent(\"\"\"\n        [conf]\n        tools.build:sysroot=/path/to/nowhere\n        tools.build:add_rpath_link=True\n    \"\"\")\n\n    foobar_h = textwrap.dedent(\"\"\"\n        #pragma once\n        int foobar(int x, int y);\n    \"\"\")\n\n    foobar_cpp = textwrap.dedent(\"\"\"\n        #include \"foobar.h\"\n        int foobar(int x, int y) {\n            return x + y;\n        }\n    \"\"\")\n\n    test_package_cpp = textwrap.dedent(\"\"\"\n        #include \"foobar.h\"\n        int main() { return foobar(2, 3) == 5 ? 0 : 1; }\n    \"\"\")\n\n    consumer_meson_build = textwrap.dedent(\"\"\"\n        project('consumer ', 'cpp')\n        cxx = meson.get_compiler('cpp')\n        #add_project_link_arguments('--sysroot=/path/to/nowhere', language: 'cpp')\n        foobar = dependency('foobar', required: true)\n        consumer_lib = library('consumer', 'src/consumer.cpp', install: true, dependencies: foobar)\n        executable('consumer_app', 'src/main.cpp', install: true, link_with: consumer_lib)\n    \"\"\")\n\n    consumer_consumer_h = textwrap.dedent(\"\"\"\n        #pragma once\n        int consumer(int x, int y);\n    \"\"\")\n\n    consumer_consumer_cpp = textwrap.dedent(\"\"\"\n        #include \"consumer.h\"\n        #include \"foobar.h\"\n        int consumer(int x, int y) {\n            return foobar(x, y) * 2;\n        }\n    \"\"\")\n\n    consumer_main_cpp = textwrap.dedent(\"\"\"\n        #include \"consumer.h\"\n        int main() { return consumer(2, 3) == 10 ? 0 : 1; }\n    \"\"\")\n\n    c.save({\"extra_profile\": extra_profile})\n    with c.chdir(\"foobar\"):\n        c.run(\"new cmake_lib -d name=foobar -d version=1.0\")\n        c.save({\"include/foobar.h\": foobar_h,\n                \"src/foobar.cpp\": foobar_cpp,\n                \"test_package/src/example.cpp\": test_package_cpp,})\n        \n        c.run(f'create . -o \"*:shared=True\" -pr=default -pr=../extra_profile')\n\n    with c.chdir(\"consumer\"):\n        c.run(f'new meson_lib -d name=consumer -d version=1.0 -d requires=foobar/1.0')\n        c.save({\"src/consumer.cpp\": consumer_consumer_cpp,\n                \"src/main.cpp\": consumer_main_cpp,\n                \"src/consumer.h\": consumer_consumer_h,\n                \"meson.build\": consumer_meson_build})\n        c.run(f'create . -o \"*:shared=True\" -tf= -pr=default -pr=../extra_profile')\n"
  },
  {
    "path": "test/functional/toolchains/meson/test_pkg_config_reuse.py",
    "content": "import os\n\nimport pytest\nimport textwrap\n\nfrom conan.test.assets.sources import gen_function_cpp\nfrom conan.test.utils.tools import TestClient\nfrom test.functional.toolchains.meson._base import check_binary\n\n\n@pytest.mark.tool(\"ninja\")\n@pytest.mark.tool(\"meson\")\n@pytest.mark.tool(\"pkg_config\")\nclass TestMesonPkgConfig:\n    _conanfile_py = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    from conan.tools.meson import Meson, MesonToolchain\n\n\n    class App(ConanFile):\n        settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n        generators = \"PkgConfigDeps\"\n        requires = \"hello/0.1\"\n\n        def layout(self):\n            self.folders.build = \"build\"\n\n        def generate(self):\n            tc = MesonToolchain(self)\n            tc.generate()\n\n        def build(self):\n            meson = Meson(self)\n            meson.configure()\n            meson.build()\n    \"\"\")\n\n    _meson_build = textwrap.dedent(\"\"\"\n    project('tutorial', 'cpp')\n    hello = dependency('hello', version : '>=0.1')\n    executable('demo', 'main.cpp', dependencies: hello)\n    \"\"\")\n\n    def test_reuse(self):\n        t = TestClient()\n        t.run(\"new cmake_lib -d name=hello -d version=0.1\")\n        t.run(\"create . -tf=\\\"\\\"\")\n\n        app = gen_function_cpp(name=\"main\", includes=[\"hello\"], calls=[\"hello\"])\n        # Prepare the actual consumer package\n        t.save({\"conanfile.py\": self._conanfile_py,\n                \"meson.build\": self._meson_build,\n                \"main.cpp\": app},\n               clean_first=True)\n\n        # Build in the cache\n        t.run(\"build .\")\n        t.run_command(os.path.join(\"build\", \"demo\"))\n\n        assert \"Hello World Release!\" in t.out\n\n        check_binary(t)\n"
  },
  {
    "path": "test/functional/toolchains/meson/test_preprocessor_definitions.py",
    "content": "import os\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.sources import gen_function_cpp, gen_function_h\nfrom conan.test.utils.tools import TestClient\nfrom test.functional.toolchains.meson._base import check_binary\n\n\nclass TestMesonPreprocessorDefinitionsTest:\n    _conanfile_py = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    from conan.tools.meson import Meson, MesonToolchain\n\n\n    class App(ConanFile):\n        settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n        options = {\"shared\": [True, False], \"fPIC\": [True, False]}\n        default_options = {\"shared\": False, \"fPIC\": True}\n\n        def config_options(self):\n            if self.settings.os == \"Windows\":\n                del self.options.fPIC\n\n        def layout(self):\n            self.folders.build = \"build\"\n\n        def generate(self):\n            tc = MesonToolchain(self)\n            tc.preprocessor_definitions[\"TEST_DEFINITION1\"] = \"TestPpdValue1\"\n            tc.preprocessor_definitions[\"TEST_DEFINITION2\"] = \"TestPpdValue2\"\n            tc.generate()\n\n        def build(self):\n            meson = Meson(self)\n            meson.configure()\n            meson.build()\n    \"\"\")\n\n    _meson_build = textwrap.dedent(\"\"\"\n    project('tutorial', 'cpp')\n    hello = library('hello', 'hello.cpp')\n    executable('demo', 'main.cpp', link_with: hello)\n    \"\"\")\n\n    @pytest.mark.tool(\"ninja\")\n    @pytest.mark.tool(\"meson\")\n    def test_build(self):\n        hello_h = gen_function_h(name=\"hello\")\n        hello_cpp = gen_function_cpp(name=\"hello\",\n                                     preprocessor=[\"TEST_DEFINITION1\", \"TEST_DEFINITION2\"])\n        app = gen_function_cpp(name=\"main\", includes=[\"hello\"], calls=[\"hello\"])\n\n        t = TestClient()\n        t.save({\"conanfile.py\": self._conanfile_py,\n                \"meson.build\": self._meson_build,\n                \"hello.h\": hello_h,\n                \"hello.cpp\": hello_cpp,\n                \"main.cpp\": app})\n\n        t.run(\"install .\")\n\n        content = t.load(\"conan_meson_native.ini\")\n\n        assert \"[built-in options]\" in content\n        assert \"buildtype = 'release'\" in content\n\n        t.run(\"build .\")\n        assert \"WARN: deprecated: Use 'extra_defines' attribute for compiler preprocessor \" \\\n               \"definitions instead of 'preprocessor_definitions'\" in t.out\n\n        t.run_command(os.path.join(\"build\", \"demo\"))\n        assert \"hello: Release!\" in t.out\n        assert \"TEST_DEFINITION1: TestPpdValue1\" in t.out\n        assert \"TEST_DEFINITION2: TestPpdValue2\" in t.out\n\n        check_binary(t)\n"
  },
  {
    "path": "test/functional/toolchains/meson/test_subproject.py",
    "content": "import textwrap\n\nimport pytest\n\nfrom conan.test.assets.sources import gen_function_c\nfrom conan.test.utils.tools import TestClient\n\n_conanfile_py = textwrap.dedent(\"\"\"\n    import os\n    import shutil\n    from conan import ConanFile\n    from conan.tools.meson import Meson, MesonToolchain\n\n    class App(ConanFile):\n        settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n        options = {\"shared\": [True, False], \"fPIC\": [True, False], \"use_french\": ['true', 'false']}\n        default_options = {\"shared\": False, \"fPIC\": True, \"use_french\": 'false'}\n        exports_sources = \"**\"\n\n        def config_options(self):\n            if self.settings.os == \"Windows\":\n                self.options.rm_safe(\"fPIC\")\n\n        def configure(self):\n            if self.options.shared:\n                self.options.rm_safe(\"fPIC\")\n\n        def layout(self):\n            self.folders.build = \"build\"\n\n        def generate(self):\n            tc = MesonToolchain(self)\n            tc.subproject_options[\"hello\"] = [{'french': str(self.options.use_french)}]\n            tc.generate()\n\n        def build(self):\n            meson = Meson(self)\n            meson.configure()\n            meson.build()\n\n        def package(self):\n            meson = Meson(self)\n            meson.install()\n            # https://mesonbuild.com/FAQ.html#why-does-building-my-project-with-msvc-output-static-libraries-called-libfooa\n            if self.settings.compiler == 'msvc' and not self.options.shared:\n                shutil.move(os.path.join(self.package_folder, \"lib\", \"libhello.a\"),\n                            os.path.join(self.package_folder, \"lib\", \"hello.lib\"))\n                shutil.move(os.path.join(self.package_folder, \"lib\", \"libgreeter.a\"),\n                            os.path.join(self.package_folder, \"lib\", \"greeter.lib\"))\n\n        def package_info(self):\n            self.cpp_info.components[\"hello\"].libs = ['hello']\n            self.cpp_info.components[\"greeter\"].libs = ['greeter']\n            self.cpp_info.components[\"greeter\"].requires = ['hello']\n    \"\"\")\n\n_meson_build = textwrap.dedent(\"\"\"\n    project('greeter', 'c')\n\n    hello_proj = subproject('hello')\n    hello_dep = hello_proj.get_variable('hello_dep')\n\n    inc = include_directories('include')\n    greeter = static_library('greeter',\n        'greeter.c',\n        include_directories : inc,\n        dependencies : hello_dep,\n        install : true)\n\n    install_headers('greeter.h')\n    \"\"\")\n\n_meson_subproject_build = textwrap.dedent(\"\"\"\n    project('hello', 'c')\n\n    hello_c_args = []\n        if get_option('french')\n        hello_c_args = ['-DFRENCH']\n    endif\n\n    inc = include_directories('include')\n    hello = static_library('hello',\n        'hello.c',\n        include_directories : inc,\n        c_args: hello_c_args,\n        install : true)\n\n    hello_dep = declare_dependency(include_directories : inc, link_with : hello)\n    \"\"\")\n\n_meson_subproject_options = textwrap.dedent(\"\"\"\n    option('french', type : 'boolean', value : false)\n    \"\"\")\n\n_hello_c = textwrap.dedent(\"\"\"\n    #include <stdio.h>\n\n    void hello(void) {\n    #ifdef FRENCH\n        printf(\"Le sous-projet vous salut\\\\n\");\n    #else\n        printf(\"Hello from subproject\\\\n\");\n    #endif\n    }\n    \"\"\")\n\n_greeter_c = textwrap.dedent(\"\"\"\n    #include <hello.h>\n\n    void greeter(void) {\n        hello();\n    }\n    \"\"\")\n\n_hello_h = textwrap.dedent(\"\"\"\n    #pragma once\n    void hello(void);\n    \"\"\")\n\n_greeter_h = textwrap.dedent(\"\"\"\n    #pragma once\n    void greeter(void);\n    \"\"\")\n\n_test_package_conanfile_py = textwrap.dedent(\"\"\"\n    import os\n    from conan import ConanFile\n    from conan.tools.cmake import CMake, cmake_layout\n    from conan.tools.build import cross_building\n\n    class TestConan(ConanFile):\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n        generators = \"CMakeToolchain\", \"CMakeDeps\"\n\n        def requirements(self):\n            self.requires(self.tested_reference_str)\n\n        def layout(self):\n            cmake_layout(self)\n\n        def build(self):\n            cmake = CMake(self)\n            cmake.configure()\n            cmake.build()\n\n        def test(self):\n            if not cross_building(self):\n                cmd = os.path.join(self.cpp.build.bindirs[0], \"test_package\")\n                self.run(cmd, env=[\"conanrunenv\"])\n    \"\"\")\n\n_test_package_cmake_lists = textwrap.dedent(\"\"\"\n    cmake_minimum_required(VERSION 3.1)\n    project(test_package C)\n\n    add_executable(${PROJECT_NAME} src/test_package.c)\n    find_package(greeter CONFIG REQUIRED)\n    target_link_libraries(${PROJECT_NAME} greeter::greeter)\n    \"\"\")\n\n\n@pytest.mark.tool(\"ninja\")\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.tool(\"meson\")\ndef test_subproject():\n    client = TestClient()\n    test_package_c = gen_function_c(name=\"main\", includes=[\"greeter\"], calls=[\"greeter\"])\n    client.save({\"conanfile.py\": _conanfile_py,\n                 \"meson.build\": _meson_build,\n                 \"greeter.c\": _greeter_c,\n                 \"greeter.h\": _greeter_h,\n                 \"include/greeter.h\": _greeter_h,\n                 \"subprojects/hello/include/hello.h\": _hello_h,\n                 \"subprojects/hello/hello.c\": _hello_c,\n                 \"subprojects/hello/meson.build\": _meson_subproject_build,\n                 \"subprojects/hello/meson_options.txt\": _meson_subproject_options,\n                 \"test_package/conanfile.py\": _test_package_conanfile_py,\n                 \"test_package/CMakeLists.txt\": _test_package_cmake_lists,\n                 \"test_package/src/test_package.c\": test_package_c})\n    client.run(\"create . --name=greeter --version=0.1\")\n    assert \"Hello from subproject\" in client.out\n    assert \"Le sous-projet vous salut\" not in client.out\n    # Using subproject options\n    client.run(\"create . --name=greeter --version=0.1 -o use_french='true'\")\n    assert \"Hello from subproject\" not in client.out\n    assert \"Le sous-projet vous salut\" in client.out\n"
  },
  {
    "path": "test/functional/toolchains/meson/test_test.py",
    "content": "import pytest\nimport textwrap\n\nfrom conan.test.assets.sources import gen_function_cpp\nfrom conan.test.utils.tools import TestClient\nfrom test.functional.toolchains.meson._base import check_binary\n\n\n@pytest.mark.tool(\"ninja\")\n@pytest.mark.tool(\"meson\")\n@pytest.mark.tool(\"pkg_config\")\nclass TestMeson:\n    _test_package_meson_build = textwrap.dedent(\"\"\"\n        project('test_package', 'cpp')\n        hello = dependency('hello', version : '>=0.1')\n        test_package = executable('test_package', 'test_package.cpp', dependencies: hello)\n        test('test package', test_package)\n        \"\"\")\n\n    _test_package_conanfile_py = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.meson import Meson, MesonToolchain\n\n\n        class TestConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"PkgConfigDeps\"\n\n            def requirements(self):\n                self.requires(self.tested_reference_str)\n\n            def layout(self):\n                self.folders.build = \"build\"\n\n            def generate(self):\n                tc = MesonToolchain(self)\n                tc.generate()\n\n            def build(self):\n                meson = Meson(self)\n                meson.configure()\n                meson.build()\n\n            def test(self):\n                meson = Meson(self)\n                meson.configure()\n                meson.test()\n        \"\"\")\n\n    def test_reuse(self):\n        t = TestClient()\n        t.run(\"new cmake_lib -d name=hello -d version=0.1\")\n\n        test_package_cpp = gen_function_cpp(name=\"main\", includes=[\"hello\"], calls=[\"hello\"])\n\n        t.save({\"test_package/conanfile.py\": self._test_package_conanfile_py,\n                \"test_package/meson.build\": self._test_package_meson_build,\n                \"test_package/test_package.cpp\": test_package_cpp})\n\n        t.run(\"create . --name=hello --version=0.1\")\n\n        check_binary(t)\n"
  },
  {
    "path": "test/functional/toolchains/meson/test_v2_meson_template.py",
    "content": "import os\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.tool(\"ninja\")\n@pytest.mark.tool(\"meson\")\n@pytest.mark.tool(\"pkg_config\")\ndef test_meson_lib_template():\n    # Identical to def test_cmake_lib_template(), but for Meson\n    client = TestClient(path_with_spaces=False)\n    client.run(\"new meson_lib -d name=hello -d version=0.1\")\n\n    # Local flow works\n    client.run(\"install .\")\n    client.run(\"build .\")\n    client.run(\"export-pkg . --name=hello --version=0.1\")\n    package_folder = client.created_layout().package()\n    assert os.path.exists(os.path.join(package_folder, \"include\", \"hello.h\"))\n\n    # Create works\n    client.run(\"create .\")\n    assert \"hello/0.1: Hello World Release!\" in client.out\n\n    client.run(\"create . -s build_type=Debug\")\n    assert \"hello/0.1: Hello World Debug!\" in client.out\n\n    # Create + shared works\n    client.run(\"create . -o hello/*:shared=True\")\n    assert \"hello/0.1: Hello World Release!\" in client.out\n\n\n@pytest.mark.tool(\"ninja\")\n@pytest.mark.tool(\"meson\")\ndef test_meson_exe_template():\n    client = TestClient(path_with_spaces=False)\n    client.run(\"new meson_exe -d name=greet -d version=0.1\")\n    # Local flow works\n    client.run(\"install .\")\n    client.run(\"build .\")\n\n    # Create works\n    client.run(\"create .\")\n    assert \"greet/0.1: Hello World Release!\" in client.out\n\n    client.run(\"create . -s build_type=Debug\")\n    assert \"greet/0.1: Hello World Debug!\" in client.out\n"
  },
  {
    "path": "test/functional/toolchains/microsoft/__init__.py",
    "content": ""
  },
  {
    "path": "test/functional/toolchains/microsoft/test_msbuild.py",
    "content": "import os\nimport platform\nimport textwrap\n\nimport pytest\n\nfrom conan.tools.microsoft.visual import vcvars_command\nfrom conan.internal.api.detect.detect_vs import vs_installation_path\nfrom conan.test.assets.sources import gen_function_cpp\nfrom test.functional.utils import check_vs_runtime, check_exe_run\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import rmdir\n\n\nsln_file = r\"\"\"\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio 15\nVisualStudioVersion = 15.0.28307.757\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"MyApp\", \"MyApp\\MyApp.vcxproj\", \"{B58316C0-C78A-4E9B-AE8F-5D6368CE3840}\"\nEndProject\nGlobal\n    GlobalSection(SolutionConfigurationPlatforms) = preSolution\n        Debug|x64 = Debug|x64\n        Debug|x86 = Debug|x86\n        Release|x64 = Release|x64\n        Release|x86 = Release|x86\n        Release - Shared|x64 = Release - Shared|x64\n        Release - Shared|x86 = Release - Shared|x86\n    EndGlobalSection\n    GlobalSection(ProjectConfigurationPlatforms) = postSolution\n        {B58316C0-C78A-4E9B-AE8F-5D6368CE3840}.Debug|x64.ActiveCfg = Debug|x64\n        {B58316C0-C78A-4E9B-AE8F-5D6368CE3840}.Debug|x64.Build.0 = Debug|x64\n        {B58316C0-C78A-4E9B-AE8F-5D6368CE3840}.Debug|x86.ActiveCfg = Debug|Win32\n        {B58316C0-C78A-4E9B-AE8F-5D6368CE3840}.Debug|x86.Build.0 = Debug|Win32\n        {B58316C0-C78A-4E9B-AE8F-5D6368CE3840}.Release|x64.ActiveCfg = Release|x64\n        {B58316C0-C78A-4E9B-AE8F-5D6368CE3840}.Release|x64.Build.0 = Release|x64\n        {B58316C0-C78A-4E9B-AE8F-5D6368CE3840}.Release|x86.ActiveCfg = Release|Win32\n        {B58316C0-C78A-4E9B-AE8F-5D6368CE3840}.Release|x86.Build.0 = Release|Win32\n        {B58316C0-C78A-4E9B-AE8F-5D6368CE3840}.Release - Shared|x64.ActiveCfg = Release - Shared|x64\n        {B58316C0-C78A-4E9B-AE8F-5D6368CE3840}.Release - Shared|x64.Build.0 = Release - Shared|x64\n        {B58316C0-C78A-4E9B-AE8F-5D6368CE3840}.Release - Shared|x86.ActiveCfg = Release - Shared|Win32\n        {B58316C0-C78A-4E9B-AE8F-5D6368CE3840}.Release - Shared|x86.Build.0 = Release - Shared|Win32\n    EndGlobalSection\n    GlobalSection(SolutionProperties) = preSolution\n        HideSolutionNode = FALSE\n    EndGlobalSection\n    GlobalSection(ExtensibilityGlobals) = postSolution\n        SolutionGuid = {DE6E462F-E299-4F9C-951A-F9404EB51521}\n    EndGlobalSection\nEndGlobal\n\"\"\"\n\n\nmyapp_vcxproj = r\"\"\"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"15.0\"\n          xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release - Shared|Win32\">\n      <Configuration>Release - Shared</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release - Shared|x64\">\n      <Configuration>Release - Shared</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Debug|x64\">\n      <Configuration>Debug</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|x64\">\n      <Configuration>Release</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <VCProjectVersion>15.0</VCProjectVersion>\n    <ProjectGuid>{B58316C0-C78A-4E9B-AE8F-5D6368CE3840}</ProjectGuid>\n    <Keyword>Win32Proj</Keyword>\n    <RootNamespace>MyApp</RootNamespace>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release - Shared|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v141</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release - Shared|x64'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v141</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v141</PlatformToolset>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v141</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v141</PlatformToolset>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v141</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <!-- Very IMPORTANT this should go BEFORE the Microsoft.Cpp.props.\n  If it goes after, the Toolset definition is ignored -->\n  <ImportGroup Label=\"PropertySheets\">\n    <Import Project=\"..\\conan\\conan_hello.props\" />\n    <Import Project=\"..\\conan\\conantoolchain.props\" />\n  </ImportGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Label=\"Shared\">\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\"\n    Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\"\n    Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\"\n    Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\"\n    Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n   <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release - Shared|x64'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\"\n    Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\"\n    Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n   <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release - Shared|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\"\n    Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\"\n    Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\"\n    Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\"\n    Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\"\n    Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\"\n    Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <LinkIncremental>true</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <LinkIncremental>true</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <LinkIncremental>false</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <LinkIncremental>false</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release - Shared|Win32'\">\n    <LinkIncremental>false</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release - Shared|x64'\">\n    <LinkIncremental>false</LinkIncremental>\n  </PropertyGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <ClCompile>\n      <PrecompiledHeader>NotUsing</PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>Disabled</Optimization>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)\n      </PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release - Shared|Win32'\">\n    <ClCompile>\n      <PrecompiledHeader>NotUsing</PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>MaxSpeed</Optimization>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)\n      </PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release - Shared|x64'\">\n    <ClCompile>\n      <PrecompiledHeader>NotUsing</PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>MaxSpeed</Optimization>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <ClCompile>\n      <PrecompiledHeader>NotUsing</PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>Disabled</Optimization>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <ClCompile>\n      <PrecompiledHeader>NotUsing</PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>MaxSpeed</Optimization>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)\n      </PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <ClCompile>\n      <PrecompiledHeader>NotUsing</PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>MaxSpeed</Optimization>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <ClCompile Include=\"MyApp.cpp\" />\n  </ItemGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n</Project>\n\"\"\"\n\n\n@pytest.mark.tool(\"visual_studio\", \"15\")\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Only for windows\")\ndef test_msvc_runtime_flag_vs2017():\n    check_msvc_runtime_flag(\"191\")\n\n\n@pytest.mark.tool(\"visual_studio\", \"17\")\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Only for windows\")\ndef test_msvc_runtime_flag_vs2022():\n    check_msvc_runtime_flag(\"193\")\n\n\ndef check_msvc_runtime_flag(msvc_version):\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n       from conan import ConanFile\n       from conan.tools.microsoft import msvc_runtime_flag\n       class App(ConanFile):\n           settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n\n           def generate(self):\n               self.output.info(\"MSVC FLAG={}!!\".format(msvc_runtime_flag(self)))\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run('install . -s compiler=msvc -s compiler.version={vs_version} '\n               '-s compiler.runtime=dynamic'.format(vs_version=msvc_version))\n    assert \"MSVC FLAG=MD!!\" in client.out\n    client.run('install . -s compiler=msvc -s compiler.version={msvc_version} '\n               '-s compiler.runtime=static '\n               '-s compiler.runtime_type=Debug '\n               '-s compiler.cppstd=14'.format(msvc_version=msvc_version))\n    assert \"MSVC FLAG=MTd!!\" in client.out\n    client.run('install . -s compiler=msvc -s compiler.version={msvc_version} '\n               '-s compiler.runtime=dynamic '\n               '-s compiler.cppstd=14'.format(msvc_version=msvc_version))\n    assert \"MSVC FLAG=MD!!\" in client.out\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Only for windows\")\n@pytest.mark.tool(\"visual_studio\")\nclass TestWin:\n    # FIXME: This test needs to be parameterized correctly for different VS versions\n\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.microsoft import MSBuildToolchain, MSBuild, MSBuildDeps\n        from conan.tools.files import copy\n        class App(ConanFile):\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            requires = \"hello/0.1\"\n            options = {\"shared\": [True, False]}\n            default_options = {\"shared\": False}\n\n            def layout(self):\n                self.folders.generators = \"conan\"\n                self.folders.build = \".\"\n\n            def generate(self):\n                tc = MSBuildToolchain(self)\n                gen = MSBuildDeps(self)\n                shared_option = self.dependencies[\"hello\"].options.get_safe(\"shared\")\n                if shared_option and self.settings.build_type == \"Release\":\n                    tc.configuration = \"Release - Shared\"\n                    gen.configuration = \"Release - Shared\"\n\n                tc.preprocessor_definitions[\"DEFINITIONS_BOTH\"] = '\"True\"'\n                tc.preprocessor_definitions[\"DEFINITIONS_BOTH2\"] = 'DEFINITIONS_BOTH'\n                tc.preprocessor_definitions[\"DEFINITIONS_BOTH_INT\"] = 123\n                if self.settings.build_type == \"Debug\":\n                    tc.preprocessor_definitions[\"DEFINITIONS_CONFIG\"] = '\"Debug\"'\n                    tc.preprocessor_definitions[\"DEFINITIONS_CONFIG_INT\"] = 234\n                else:\n                    tc.preprocessor_definitions[\"DEFINITIONS_CONFIG\"] = '\"Release\"'\n                    tc.preprocessor_definitions[\"DEFINITIONS_CONFIG_INT\"] = 456\n                tc.preprocessor_definitions[\"DEFINITIONS_CONFIG2\"] = 'DEFINITIONS_CONFIG'\n\n                tc.generate()\n                gen.generate()\n\n                shared_option = self.dependencies[\"hello\"].options.get_safe(\"shared\")\n                if shared_option and self.settings.build_type == \"Release\":\n                    configuration = \"Release - Shared\"\n                    if self.settings.arch == \"x86_64\":\n                        dst = \"x64/%s\" % configuration\n                    else:\n                        dst = configuration\n                else:\n                    configuration = self.settings.build_type\n                    dst = \"%s/%s\" % (self.settings.arch, configuration)\n\n                src = os.path.join(self.dependencies[\"hello\"].package_folder, \"bin\")\n                dst = os.path.join(self.build_folder, dst)\n                copy(self, \"*.dll\", src, dst, keep_path=False)\n\n            def build(self):\n                msbuild = MSBuild(self)\n                msbuild.build(\"MyProject.sln\")\n        \"\"\")\n    app = gen_function_cpp(name=\"main\", includes=[\"hello\"], calls=[\"hello\"],\n                           preprocessor=[\"DEFINITIONS_BOTH\", \"DEFINITIONS_BOTH2\",\n                                         \"DEFINITIONS_BOTH_INT\", \"DEFINITIONS_CONFIG\",\n                                         \"DEFINITIONS_CONFIG2\", \"DEFINITIONS_CONFIG_INT\"])\n\n    @staticmethod\n    def _run_app(client, arch, build_type, shared=None):\n        if build_type == \"Release\" and shared:\n            configuration = \"Release - Shared\"\n        else:\n            configuration = build_type\n\n        if arch == \"x86\":\n            command_str = \"%s\\\\MyApp.exe\" % configuration\n        else:\n            command_str = \"x64\\\\%s\\\\MyApp.exe\" % configuration\n        client.run_command(command_str)\n\n    @pytest.mark.tool(\"cmake\")\n    @pytest.mark.tool(\"visual_studio\", \"15\")\n    @pytest.mark.parametrize(\"compiler,version,runtime,cppstd\",\n                             [(\"msvc\", \"191\", \"static\", \"17\"),\n                              # (\"msvc\", \"190\", \"static\", \"14\")\n                              ])\n    def test_toolchain_win_vs2017(self, compiler, version, runtime, cppstd):\n        self.check_toolchain_win(compiler, version, runtime, cppstd, ide_version=15)\n\n    @pytest.mark.tool(\"cmake\", \"3.23\")\n    @pytest.mark.tool(\"visual_studio\", \"17\")\n    @pytest.mark.parametrize(\"compiler,version,runtime,cppstd\",\n                             [(\"msvc\", \"193\", \"static\", \"17\")])\n    def test_toolchain_win_vs2022(self, compiler, version, runtime, cppstd):\n        self.check_toolchain_win(compiler, version, runtime, cppstd, ide_version=17)\n\n    def check_toolchain_win(self, compiler, version, runtime, cppstd, ide_version):\n        client = TestClient(path_with_spaces=False)\n        settings = [(\"compiler\", compiler),\n                    (\"compiler.version\", version),\n                    (\"compiler.cppstd\", cppstd),\n                    (\"compiler.runtime\", runtime),\n                    (\"build_type\", \"Release\"),\n                    (\"arch\", \"x86\")]\n\n        profile = textwrap.dedent(\"\"\"\n            [settings]\n            os=Windows\n\n            [conf]\n            tools.microsoft.msbuild:vs_version={vs_version}\n            \"\"\".format(vs_version=ide_version))\n        client.save({\"myprofile\": profile})\n        # Build the profile according to the settings provided\n        settings_h = \" \".join('-s:h %s=\"%s\"' % (k, v) for k, v in settings if v)\n        settings_b = \" \".join('-s:b %s=\"%s\"' % (k, v) for k, v in settings if v)\n\n        client.run(\"new cmake_lib -d name=hello -d version=0.1\")\n        client.run(f\"create . {settings_h} -c tools.microsoft.msbuild:vs_version={ide_version} -c tools.build:verbosity=verbose -c tools.compilation:verbosity=verbose\")\n\n        assert \"MSBUILD : error MSB1001: Unknown switch\" not in client.out\n        assert \"-verbosity:Detailed\" in client.out\n\n        # Prepare the actual consumer package\n        client.save({\"conanfile.py\": self.conanfile,\n                     \"MyProject.sln\": sln_file,\n                     \"MyApp/MyApp.vcxproj\": myapp_vcxproj,\n                     \"MyApp/MyApp.cpp\": self.app,\n                     \"myprofile\": profile},\n                    clean_first=True)\n\n        # Run the configure corresponding to this test case\n        client.run(\"build . %s %s -pr:h=myprofile \" % (settings_h, settings_b))\n        assert \"conanfile.py: MSBuildToolchain created conantoolchain_release_win32.props\" in client.out\n        assert f\"conanvcvars.bat: Activating environment Visual Studio {ide_version}\" in client.out\n        assert \"[vcvarsall.bat] Environment initialized for: 'x86'\" in client.out\n\n        self._run_app(client, \"x86\", \"Release\")\n        assert \"Hello World Release\" in client.out\n        check_exe_run(client.out, \"main\", \"msvc\", version, \"Release\", \"x86\", cppstd,\n                      {\"DEFINITIONS_BOTH\": 'True',\n                       \"DEFINITIONS_BOTH2\": \"True\",\n                       \"DEFINITIONS_BOTH_INT\": \"123\",\n                       \"DEFINITIONS_CONFIG\": 'Release',\n                       \"DEFINITIONS_CONFIG2\": 'Release',\n                       \"DEFINITIONS_CONFIG_INT\": \"456\"})\n        static_runtime = True if runtime == \"static\" or \"MT\" in runtime else False\n        check_vs_runtime(\"Release/MyApp.exe\", client, ide_version, build_type=\"Release\",\n                         static_runtime=static_runtime)\n\n    @pytest.mark.tool(\"cmake\", \"3.23\")\n    @pytest.mark.tool(\"visual_studio\", \"17\")\n    def test_toolchain_win_debug(self):\n        client = TestClient(path_with_spaces=False)\n        settings = [(\"compiler\",  \"msvc\"),\n                    (\"compiler.version\",  \"193\"),\n                    (\"compiler.runtime\",  \"dynamic\"),\n                    (\"build_type\",  \"Debug\"),\n                    (\"arch\",  \"x86_64\")]\n\n        # Build the profile according to the settings provided\n        settings = \" \".join('-s %s=\"%s\"' % (k, v) for k, v in settings if v)\n\n        client.run(\"new cmake_lib -d name=hello -d version=0.1\")\n        client.run(\"create . %s -tf=\\\"\\\"\" % (settings,))\n\n        # Prepare the actual consumer package\n        client.save({\"conanfile.py\": self.conanfile,\n                     \"MyProject.sln\": sln_file,\n                     \"MyApp/MyApp.vcxproj\": myapp_vcxproj,\n                     \"MyApp/MyApp.cpp\": self.app},\n                    clean_first=True)\n\n        # Run the configure corresponding to this test case\n        client.run(\"build . %s\" % (settings, ))\n        assert \"conanfile.py: MSBuildToolchain created conantoolchain_debug_x64.props\" in client.out\n        assert f\"conanvcvars.bat: Activating environment Visual Studio 17\" in client.out\n        assert \"[vcvarsall.bat] Environment initialized for: 'x64'\" in client.out\n        self._run_app(client, \"x64\", \"Debug\")\n        assert \"Hello World Debug\" in client.out\n        check_exe_run(client.out, \"main\", \"msvc\", \"19\", \"Debug\", \"x86_64\", \"14\",\n                      {\"DEFINITIONS_BOTH\": 'True',\n                       \"DEFINITIONS_BOTH2\": \"True\",\n                       \"DEFINITIONS_BOTH_INT\": \"123\",\n                       \"DEFINITIONS_CONFIG\": 'Debug',\n                       \"DEFINITIONS_CONFIG2\": 'Debug',\n                       \"DEFINITIONS_CONFIG_INT\": \"234\"})\n        check_vs_runtime(\"x64/Debug/MyApp.exe\", client, \"17\", build_type=\"Debug\")\n\n    @pytest.mark.tool(\"cmake\", \"3.23\")\n    @pytest.mark.tool(\"visual_studio\", \"17\")\n    def test_toolchain_win_multi(self):\n        ide_version = \"17\"\n        client = TestClient(path_with_spaces=False)\n\n        settings = [(\"compiler\", \"msvc\"),\n                    (\"compiler.version\", \"193\"),\n                    (\"compiler.cppstd\", \"17\"),\n                    (\"compiler.runtime\", \"static\")]\n\n        settings = \" \".join('-s %s=\"%s\"' % (k, v) for k, v in settings if v)\n        client.run(\"new cmake_lib -d name=hello -d version=0.1\")\n        configs = [(\"Release\", \"x86\", True), (\"Release\", \"x86_64\", True),\n                   (\"Debug\", \"x86\", False), (\"Debug\", \"x86_64\", False)]\n        for build_type, arch, shared in configs:\n            # Build the profile according to the settings provided\n            # TODO: It is a bit ugly to remove manually\n            build_test_folder = os.path.join(client.current_folder, \"test_package\", \"build\")\n            rmdir(build_test_folder)\n            runtime = \"static\"\n            client.run(\"create . --name=hello --version=0.1 %s -s build_type=%s -s arch=%s -s compiler.runtime=%s \"\n                       \" -o hello/*:shared=%s\" % (settings, build_type, arch, runtime, shared))\n\n        # Prepare the actual consumer package\n        client.save({\"conanfile.py\": self.conanfile,\n                     \"MyProject.sln\": sln_file,\n                     \"MyApp/MyApp.vcxproj\": myapp_vcxproj,\n                     \"MyApp/MyApp.cpp\": self.app},\n                    clean_first=True)\n\n        # Run the configure corresponding to this test case\n        for build_type, arch, shared in configs:\n            runtime = \"static\"\n            client.run(\"install . %s -s build_type=%s -s arch=%s -s compiler.runtime=%s\"\n                       \" -o hello/*:shared=%s\" % (settings, build_type, arch, runtime, shared))\n\n        vs_path = vs_installation_path(ide_version)\n        vcvars_path = os.path.join(vs_path, \"VC/Auxiliary/Build/vcvarsall.bat\")\n\n        for build_type, arch, shared in configs:\n            platform_arch = \"x86\" if arch == \"x86\" else \"x64\"\n            if build_type == \"Release\" and shared:\n                configuration = \"Release - Shared\"\n            else:\n                configuration = build_type\n\n            # The \"conan build\" command is not good enough, cannot do the switch between configs\n            cmd = ('set \"VSCMD_START_DIR=%%CD%%\" && '\n                   '\"%s\" x64 && msbuild \"MyProject.sln\" /p:Configuration=\"%s\" '\n                   '/p:Platform=%s ' % (vcvars_path, configuration, platform_arch))\n            client.run_command(cmd)\n            assert \"[vcvarsall.bat] Environment initialized for: 'x64'\" in client.out\n\n            self._run_app(client, arch, build_type, shared)\n            check_exe_run(client.out, \"main\", \"msvc\", \"19\", build_type, arch, \"17\",\n                          {\"DEFINITIONS_BOTH\": \"True\",\n                           \"DEFINITIONS_CONFIG\": build_type})\n\n            if arch == \"x86\":\n                command_str = \"%s\\\\MyApp.exe\" % configuration\n            else:\n                command_str = \"x64\\\\%s\\\\MyApp.exe\" % configuration\n            vcvars = vcvars_command(version=ide_version, architecture=\"amd64\")\n            cmd = ('%s && dumpbin /dependents \"%s\"' % (vcvars, command_str))\n            client.run_command(cmd)\n            if shared:\n                assert \"hello.dll\" in client.out\n            else:\n                assert \"hello.dll\" not in client.out\n            assert \"KERNEL32.dll\" in client.out\n"
  },
  {
    "path": "test/functional/toolchains/microsoft/test_msbuilddeps.py",
    "content": "import os\nimport platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.assets.sources import gen_function_cpp, gen_function_h\nfrom conan.test.assets.visual_project_files import get_vs_project_files\nfrom conan.test.utils.tools import TestClient, NO_SETTINGS_PACKAGE_ID\n\n\nsln_file = r\"\"\"\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio 15\nVisualStudioVersion = 15.0.28307.757\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"MyProject\", \"MyProject\\MyProject.vcxproj\", \"{6F392A05-B151-490C-9505-B2A49720C4D9}\"\nEndProject\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"MyApp\", \"MyApp\\MyApp.vcxproj\", \"{B58316C0-C78A-4E9B-AE8F-5D6368CE3840}\"\nEndProject\nGlobal\n    GlobalSection(SolutionConfigurationPlatforms) = preSolution\n        Debug|x64 = Debug|x64\n        Debug|x86 = Debug|x86\n        Release|x64 = Release|x64\n        Release|x86 = Release|x86\n    EndGlobalSection\n    GlobalSection(ProjectConfigurationPlatforms) = postSolution\n        {6F392A05-B151-490C-9505-B2A49720C4D9}.Debug|x64.ActiveCfg = Debug|x64\n        {6F392A05-B151-490C-9505-B2A49720C4D9}.Debug|x64.Build.0 = Debug|x64\n        {6F392A05-B151-490C-9505-B2A49720C4D9}.Debug|x86.ActiveCfg = Debug|Win32\n        {6F392A05-B151-490C-9505-B2A49720C4D9}.Debug|x86.Build.0 = Debug|Win32\n        {6F392A05-B151-490C-9505-B2A49720C4D9}.Release|x64.ActiveCfg = Release|x64\n        {6F392A05-B151-490C-9505-B2A49720C4D9}.Release|x64.Build.0 = Release|x64\n        {6F392A05-B151-490C-9505-B2A49720C4D9}.Release|x86.ActiveCfg = Release|Win32\n        {6F392A05-B151-490C-9505-B2A49720C4D9}.Release|x86.Build.0 = Release|Win32\n        {B58316C0-C78A-4E9B-AE8F-5D6368CE3840}.Debug|x64.ActiveCfg = Debug|x64\n        {B58316C0-C78A-4E9B-AE8F-5D6368CE3840}.Debug|x64.Build.0 = Debug|x64\n        {B58316C0-C78A-4E9B-AE8F-5D6368CE3840}.Debug|x86.ActiveCfg = Debug|Win32\n        {B58316C0-C78A-4E9B-AE8F-5D6368CE3840}.Debug|x86.Build.0 = Debug|Win32\n        {B58316C0-C78A-4E9B-AE8F-5D6368CE3840}.Release|x64.ActiveCfg = Release|x64\n        {B58316C0-C78A-4E9B-AE8F-5D6368CE3840}.Release|x64.Build.0 = Release|x64\n        {B58316C0-C78A-4E9B-AE8F-5D6368CE3840}.Release|x86.ActiveCfg = Release|Win32\n        {B58316C0-C78A-4E9B-AE8F-5D6368CE3840}.Release|x86.Build.0 = Release|Win32\n    EndGlobalSection\n    GlobalSection(SolutionProperties) = preSolution\n        HideSolutionNode = FALSE\n    EndGlobalSection\n    GlobalSection(ExtensibilityGlobals) = postSolution\n        SolutionGuid = {DE6E462F-E299-4F9C-951A-F9404EB51521}\n    EndGlobalSection\nEndGlobal\n\"\"\"\n\nmyproject_vcxproj = r\"\"\"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"15.0\"\n       xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Debug|x64\">\n      <Configuration>Debug</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|x64\">\n      <Configuration>Release</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <VCProjectVersion>15.0</VCProjectVersion>\n    <ProjectGuid>{6F392A05-B151-490C-9505-B2A49720C4D9}</ProjectGuid>\n    <Keyword>Win32Proj</Keyword>\n    <RootNamespace>MyProject</RootNamespace>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v141</PlatformToolset>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v141</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v141</PlatformToolset>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v141</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Label=\"Shared\">\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\">\n    <Import Project=\"..\\conan_hello3.props\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\"\n    Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\"\n    Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\"\n    Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\"\n    Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\"\n    Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\"\n    Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\"\n    Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\"\n    Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <LinkIncremental>true</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <LinkIncremental>true</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <LinkIncremental>false</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <LinkIncremental>false</LinkIncremental>\n  </PropertyGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <ClCompile>\n      <PrecompiledHeader>NotUsing</PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>Disabled</Optimization>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)\n      </PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <ClCompile>\n      <PrecompiledHeader>NotUsing</PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>Disabled</Optimization>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <ClCompile>\n      <PrecompiledHeader>NotUsing</PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>MaxSpeed</Optimization>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)\n      </PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <ClCompile>\n      <PrecompiledHeader>NotUsing</PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>MaxSpeed</Optimization>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <ClCompile Include=\"MyProject.cpp\" />\n  </ItemGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n</Project>\n\"\"\"\n\n\nmyapp_vcxproj = r\"\"\"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"15.0\"\n          xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Debug|x64\">\n      <Configuration>Debug</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|x64\">\n      <Configuration>Release</Configuration>\n      <Platform>x64</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <VCProjectVersion>15.0</VCProjectVersion>\n    <ProjectGuid>{B58316C0-C78A-4E9B-AE8F-5D6368CE3840}</ProjectGuid>\n    <Keyword>Win32Proj</Keyword>\n    <RootNamespace>MyApp</RootNamespace>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v141</PlatformToolset>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v141</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v141</PlatformToolset>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v141</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>Unicode</CharacterSet>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Label=\"Shared\">\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\">\n    <Import Project=\"..\\conan_hello1.props\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\"\n    Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\"\n    Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\"\n    Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\"\n    Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\"\n    Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\"\n    Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\"\n    Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\"\n    Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <LinkIncremental>true</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <LinkIncremental>true</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <LinkIncremental>false</LinkIncremental>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <LinkIncremental>false</LinkIncremental>\n  </PropertyGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <ClCompile>\n      <PrecompiledHeader>NotUsing</PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>Disabled</Optimization>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)\n      </PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|x64'\">\n    <ClCompile>\n      <PrecompiledHeader>NotUsing</PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>Disabled</Optimization>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <ClCompile>\n      <PrecompiledHeader>NotUsing</PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>MaxSpeed</Optimization>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)\n      </PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\">\n    <ClCompile>\n      <PrecompiledHeader>NotUsing</PrecompiledHeader>\n      <WarningLevel>Level3</WarningLevel>\n      <Optimization>MaxSpeed</Optimization>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n    </Link>\n  </ItemDefinitionGroup>\n  <ItemGroup>\n    <ClCompile Include=\"MyApp.cpp\" />\n  </ItemGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n</Project>\n\"\"\"\n\n\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.tool(\"visual_studio\")\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires MSBuild\")\ndef test_msbuild_generator():\n    client = TestClient()\n    client.run(\"new cmake_lib -d name=hello0 -d version=1.0\")\n    client.run(\"create . -tf=\")\n    client.save({}, clean_first=True)\n    client.run(\"new cmake_lib -d name=hello3 -d version=1.0\")\n    client.run(\"create . -tf=\")\n    client.save({}, clean_first=True)\n    client.run(\"new cmake_lib -d name=hello1 -d version=1.0 -d requires=hello0/1.0\")\n    client.run(\"create . -tf=\")\n    client.save({}, clean_first=True)\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.microsoft import MSBuild\n        class HelloConan(ConanFile):\n            settings = \"os\", \"build_type\", \"compiler\", \"arch\"\n            requires = \"hello1/1.0\", \"hello3/1.0\"\n            generators = \"MSBuildDeps\", \"MSBuildToolchain\"\n            def build(self):\n                msbuild = MSBuild(self)\n                msbuild.build(\"MyProject.sln\")\n        \"\"\")\n    myapp_cpp = gen_function_cpp(name=\"main\", msg=\"MyApp\",\n                                 includes=[\"hello1\"], calls=[\"hello1\"])\n    myproject_cpp = gen_function_cpp(name=\"main\", msg=\"MyProject\", includes=[\"hello3\"],\n                                     calls=[\"hello3\"])\n    files = {\"MyProject.sln\": sln_file,\n             \"MyProject/MyProject.vcxproj\": myproject_vcxproj,\n             \"MyProject/MyProject.cpp\": myproject_cpp,\n             \"MyApp/MyApp.vcxproj\": myapp_vcxproj,\n             \"MyApp/MyApp.cpp\": myapp_cpp,\n             \"conanfile.py\": conanfile}\n\n    client.save(files, clean_first=True)\n    client.run(\"install .\")\n    client.run(\"build .\")\n    assert \"warning MSB4011\" not in client.out\n    client.run_command(r\"x64\\Release\\MyProject.exe\")\n    assert \"MyProject: Release!\" in client.out\n    assert \"hello3/1.0: Hello World Release!\" in client.out\n    client.run_command(r\"x64\\Release\\MyApp.exe\")\n    assert \"MyApp: Release!\" in client.out\n    assert \"hello0/1.0: Hello World Release!\" in client.out\n    assert \"hello1/1.0: Hello World Release\" in client.out\n\n\n@pytest.mark.tool(\"visual_studio\")\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires MSBuild\")\ndef test_install_reference_gcc():\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"create . --name=pkg --version=1.0\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            generators = \"MSBuildDeps\"\n            requires = \"pkg/1.0\"\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n\n    client.run('install . -s os=Windows -s compiler=msvc '\n               '-s compiler.version=194 -s compiler.runtime=dynamic')\n    assert \"conanfile.py: Generator 'MSBuildDeps' calling 'generate()'\" in client.out\n    props = client.load(\"conan_pkg_release_x64.props\")\n    assert '<?xml version=\"1.0\" encoding=\"utf-8\"?>' in props\n    # This will overwrite the existing one, cause configuration and arch is the same\n    client.run(\"install . -s os=Linux -s compiler=gcc -s compiler.version=5.2 '\"\n               \"'-s compiler.libcxx=libstdc++\")\n    assert \"conanfile.py: Generator 'MSBuildDeps' calling 'generate()'\" in client.out\n    pkg_props = client.load(\"conan_pkg.props\")\n    assert 'Project=\"conan_pkg_release_x64.props\"' in pkg_props\n\n\n@pytest.mark.tool(\"visual_studio\")\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires MSBuild\")\ndef test_custom_configuration():\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"create . --name=pkg --version=1.0\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.microsoft import MSBuildDeps\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            requires = \"pkg/1.0\"\n            def generate(self):\n                ms = MSBuildDeps(self)\n                ms.configuration = \"My\"+str(self.settings.build_type)\n                ms.platform = \"My\"+str(self.settings.arch)\n                ms.generate()\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n\n    client.run('install . -s os=Windows -s compiler=msvc '\n               '-s compiler.version=194 -s compiler.runtime=dynamic')\n    props = client.load(\"conan_pkg_myrelease_myx86_64.props\")\n    assert '<?xml version=\"1.0\" encoding=\"utf-8\"?>' in props\n    client.run('install . -s os=Windows -s compiler=msvc '\n               '-s compiler.version=194 -s compiler.runtime=dynamic -s arch=x86 '\n               '-s build_type=Debug')\n    props = client.load(\"conan_pkg_mydebug_myx86.props\")\n    assert '<?xml version=\"1.0\" encoding=\"utf-8\"?>' in props\n    props = client.load(\"conan_pkg.props\")\n    assert \"conan_pkg_myrelease_myx86_64.props\" in props\n    assert \"conan_pkg_mydebug_myx86.props\" in props\n\n\ndef test_custom_configuration_errors():\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"create . --name=pkg --version=1.0\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.microsoft import MSBuildDeps\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            requires = \"pkg/1.0\"\n            def generate(self):\n                ms = MSBuildDeps(self)\n                ms.configuration = None\n                ms.generate()\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n\n    client.run('install . -s os=Windows -s compiler=msvc'\n               ' -s compiler.version=194 -s compiler.runtime=dynamic', assert_error=True)\n    assert \"MSBuildDeps.configuration is None, it should have a value\" in client.out\n    client.save({\"conanfile.py\": conanfile.replace(\"configuration\", \"platform\")})\n\n    client.run('install . -s os=Windows -s compiler=msvc'\n               ' -s compiler.version=194 -s compiler.runtime=dynamic', assert_error=True)\n    assert \"MSBuildDeps.platform is None, it should have a value\" in client.out\n\n\n@pytest.mark.tool(\"visual_studio\")\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires MSBuild\")\ndef test_install_transitive():\n    # https://github.com/conan-io/conan/issues/8065\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"create . --name=pkga --version=1.0\")\n    client.save({\"conanfile.py\": GenConanfile().with_requires(\"pkga/1.0\")})\n    client.run(\"create . --name=pkgb --version=1.0\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.microsoft import MSBuild\n        class HelloConan(ConanFile):\n            settings = \"os\", \"build_type\", \"compiler\", \"arch\"\n            requires = \"pkgb/1.0@\", \"pkga/1.0\"\n            generators = \"MSBuildDeps\", \"MSBuildToolchain\"\n            def build(self):\n                msbuild = MSBuild(self)\n                msbuild.build(\"MyProject.sln\")\n        \"\"\")\n    myapp_cpp = gen_function_cpp(name=\"main\", msg=\"MyApp\")\n    myproject_cpp = gen_function_cpp(name=\"main\", msg=\"MyProject\")\n    files = {\"MyProject.sln\": sln_file,\n             \"MyProject/MyProject.vcxproj\": myproject_vcxproj.replace(\"conan_hello3.props\",\n                                                                      \"conandeps.props\"),\n             \"MyProject/MyProject.cpp\": myproject_cpp,\n             \"MyApp/MyApp.vcxproj\": myapp_vcxproj.replace(\"conan_hello1.props\",\n                                                          \"conandeps.props\"),\n             \"MyApp/MyApp.cpp\": myapp_cpp,\n             \"conanfile.py\": conanfile}\n\n    client.save(files, clean_first=True)\n    client.run(\"build .\")\n    assert \"warning MSB4011\" not in client.out\n\n\ndef test_no_build_type_error():\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile(),\n                 \"profile\": \"[settings]\\nos=Windows\\ncompiler=msvc\\narch=x86_64\"})\n    client.run(\"create . --name=mypkg --version=0.1\")\n    client.run(\"install --requires=mypkg/0.1@ -g MSBuildDeps -pr=profile\", assert_error=True)\n    assert \"The 'msbuild' generator requires a 'build_type' setting value\" in client.out\n\n\ndef test_install_build_requires():\n    # https://github.com/conan-io/conan/issues/8170\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"create . --name=tool --version=1.0\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import load\n        class HelloConan(ConanFile):\n            settings = \"os\", \"build_type\", \"compiler\", \"arch\"\n            build_requires = \"tool/1.0\"\n            generators = \"MSBuildDeps\"\n\n            def build(self):\n                deps = load(self, \"conandeps.props\")\n                assert \"conan_tool.props\" not in deps\n                self.output.info(\"Conan_tools.props not in deps\")\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"install .\")\n    deps = client.load(\"conandeps.props\")\n    assert \"conan_tool.props\" not in deps\n    client.run(\"create . --name=pkg --version=0.1\")\n    assert \"Conan_tools.props not in deps\" in client.out\n\n\n@pytest.mark.tool(\"visual_studio\")\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires MSBuild\")\ndef test_install_transitive_build_requires():\n    # https://github.com/conan-io/conan/issues/8170\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"create . --name=dep --version=1.0\")\n    client.run(\"create . --name=tool_build --version=1.0\")\n    client.run(\"create . --name=tool_test --version=1.0\")\n    conanfile = GenConanfile().with_requires(\"dep/1.0\").\\\n        with_tool_requires(\"tool_build/1.0\").\\\n        with_test_requires(\"tool_test/1.0\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=pkg --version=1.0\")\n\n    client.save({\"conanfile.py\": GenConanfile().\n                with_settings(\"os\", \"compiler\", \"arch\", \"build_type\").\n                with_requires(\"pkg/1.0\")}, clean_first=True)\n    client.run(\"install . -g MSBuildDeps -pr:b=default -pr:h=default\")\n    pkg = client.load(\"conan_pkg_release_x64.props\")\n    assert \"conan_dep.props\" in pkg\n    assert \"tool_test\" not in pkg  # test requires are not there\n    assert \"tool_build\" not in pkg\n\n\n@pytest.mark.tool(\"visual_studio\")\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires MSBuild\")\ndef test_install_reference():\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"create . --name=mypkg --version=0.1\")\n    client.run(\"install --requires=mypkg/0.1@ -g MSBuildDeps\")\n    assert \"Generator 'MSBuildDeps' calling 'generate()'\" in client.out\n    # https://github.com/conan-io/conan/issues/8163\n    props = client.load(\"conan_mypkg_vars_release_x64.props\")  # default Release/x64\n    folder = props[props.find(\"<ConanmypkgRootFolder>\")+len(\"<ConanmypkgRootFolder>\")\n                   :props.find(\"</ConanmypkgRootFolder>\")]\n    assert os.path.isfile(os.path.join(folder, \"conaninfo.txt\"))\n\n\n@pytest.mark.parametrize(\"pattern,exclude_a,exclude_b\",\n                         [(\"['*']\", True, True),\n                          (\"['pkga']\", True, False),\n                          (\"['pkgb']\", False, True),\n                          (\"['pkg*']\", True, True),\n                          (\"['pkga', 'pkgb']\", True, True),\n                          (\"['*a', '*b']\", True, True),\n                          (\"['nonexist']\", False, False),\n                          ])\ndef test_exclude_code_analysis(pattern, exclude_a, exclude_b):\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"create . --name=pkga --version=1.0\")\n    client.run(\"create . --name=pkgb --version=1.0\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.microsoft import MSBuild\n\n        class HelloConan(ConanFile):\n            settings = \"os\", \"build_type\", \"compiler\", \"arch\"\n            requires = \"pkgb/1.0@\", \"pkga/1.0\"\n            generators = \"MSBuildDeps\"\n            def build(self):\n                msbuild = MSBuild(self)\n                msbuild.build(\"MyProject.sln\")\n        \"\"\")\n    profile = textwrap.dedent(\"\"\"\n        include(default)\n        [settings]\n        build_type=Release\n        arch=x86_64\n        [conf]\n        tools.microsoft.msbuilddeps:exclude_code_analysis = %s\n        \"\"\" % pattern)\n\n    client.save({\"conanfile.py\": conanfile,\n                 \"profile\": profile})\n    client.run(\"install . --profile profile\")\n    depa = client.load(\"conan_pkga_release_x64.props\")\n    depb = client.load(\"conan_pkgb_release_x64.props\")\n\n    if exclude_a:\n        inc = \"$(ConanpkgaIncludeDirectories)\"\n        ca_exclude = \"<CAExcludePath>%s;$(CAExcludePath)</CAExcludePath>\" % inc\n        assert ca_exclude in depa\n    else:\n        assert \"CAExcludePath\" not in depa\n\n    if exclude_b:\n        inc = \"$(ConanpkgbIncludeDirectories)\"\n        ca_exclude = \"<CAExcludePath>%s;$(CAExcludePath)</CAExcludePath>\" % inc\n        assert ca_exclude in depb\n    else:\n        assert \"CAExcludePath\" not in depb\n\n\n@pytest.mark.tool(\"visual_studio\", \"15\")\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires MSBuild\")\ndef test_build_vs_project_with_a_vs2017():\n    check_build_vs_project_with_a(\"191\")\n\n\n@pytest.mark.tool(\"visual_studio\", \"17\")\n@pytest.mark.tool(\"cmake\", \"3.23\")\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires MSBuild\")\ndef test_build_vs_project_with_a_vs2022():\n    check_build_vs_project_with_a(\"193\")\n\n\ndef check_build_vs_project_with_a(vs_version):\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"create . --name=updep.pkg.team --version=0.1\")\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n        from conan.tools.files import copy\n        class HelloConan(ConanFile):\n            settings = \"os\", \"build_type\", \"compiler\", \"arch\"\n            exports_sources = '*'\n            requires = \"updep.pkg.team/0.1@\"\n            generators = \"CMakeToolchain\"\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n\n            def package(self):\n                copy(self, \"*.h\", self.source_folder, os.path.join(self.package_folder, \"include\"))\n                copy(self, \"*.a\", self.build_folder, os.path.join(self.package_folder, \"lib\"),\n                     keep_path=False)\n\n            def package_info(self):\n                self.cpp_info.libs = [\"hello.a\"]\n        \"\"\")\n    hello_cpp = gen_function_cpp(name=\"hello\")\n    hello_h = gen_function_h(name=\"hello\")\n    cmake = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.15)\n        project(MyLib CXX)\n\n        set(CMAKE_STATIC_LIBRARY_SUFFIX \".a\")\n        add_library(hello hello.cpp)\n        \"\"\")\n\n    client.save({\"conanfile.py\": conanfile,\n                 \"CMakeLists.txt\": cmake,\n                 \"hello.cpp\": hello_cpp,\n                 \"hello.h\": hello_h})\n    client.run('create . --name=mydep.pkg.team --version=0.1 -s compiler=msvc'\n               ' -s compiler.version={vs_version}'.format(vs_version=vs_version))\n\n    consumer = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.microsoft import MSBuild\n\n        class HelloConan(ConanFile):\n            settings = \"os\", \"build_type\", \"compiler\", \"arch\"\n            requires = \"mydep.pkg.team/0.1@\"\n            generators = \"MSBuildDeps\", \"MSBuildToolchain\"\n            def build(self):\n                msbuild = MSBuild(self)\n                msbuild.build(\"MyProject.sln\")\n        \"\"\")\n    files = get_vs_project_files()\n    main_cpp = gen_function_cpp(name=\"main\", includes=[\"hello\"], calls=[\"hello\"])\n    files[\"MyProject/main.cpp\"] = main_cpp\n    files[\"conanfile.py\"] = consumer\n    # INJECT PROPS FILES\n    props = os.path.join(client.current_folder, \"conandeps.props\")\n    old = r'<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />'\n    new = old + f'<Import Project=\"{props}\" />'\n    files[\"MyProject/MyProject.vcxproj\"] = files[\"MyProject/MyProject.vcxproj\"].replace(old, new)\n    old = r'<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />'\n    toolchain = os.path.join(client.current_folder, \"conantoolchain.props\")\n    new = f'<Import Project=\"{toolchain}\" />' + old\n    files[\"MyProject/MyProject.vcxproj\"] = files[\"MyProject/MyProject.vcxproj\"].replace(old, new)\n\n    client.save(files, clean_first=True)\n    client.run('build . -s compiler=msvc'\n               ' -s compiler.version={vs_version}'.format(vs_version=vs_version))\n    client.run_command(r\"x64\\Release\\MyProject.exe\")\n    assert \"hello: Release!\" in client.out\n    # TODO: This doesnt' work because get_vs_project_files() don't define NDEBUG correctly\n    # assert \"main: Release!\" in client.out\n\n\n@pytest.mark.tool(\"visual_studio\", \"15\")\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires MSBuild\")\ndef test_build_vs_project_with_test_requires_vs2017():\n    check_build_vs_project_with_test_requires(\"191\")\n\n\n@pytest.mark.tool(\"visual_studio\", \"17\")\n@pytest.mark.tool(\"cmake\", \"3.23\")\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires MSBuild\")\ndef test_build_vs_project_with_test_requires_vs2022():\n    check_build_vs_project_with_test_requires(\"193\")\n\n\ndef check_build_vs_project_with_test_requires(vs_version):\n    client = TestClient()\n    client.run(\"new cmake_lib -d name=updep.pkg.team -d version=0.1\")\n    client.run(\"create .  -s compiler.version={vs_version} -tf=\".format(vs_version=vs_version))\n\n    client.save({}, clean_first=True)\n    client.run(\"new cmake_lib -d name=mydep.pkg.team -d version=0.1 -d requires=updep.pkg.team/0.1\")\n    client.run(\"create .  -s compiler.version={vs_version} -tf=\".format(vs_version=vs_version))\n\n    consumer = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.microsoft import MSBuild\n\n        class HelloConan(ConanFile):\n            settings = \"os\", \"build_type\", \"compiler\", \"arch\"\n            generators = \"MSBuildDeps\", \"MSBuildToolchain\"\n\n            def build_requirements(self):\n                self.test_requires(\"mydep.pkg.team/0.1\")\n\n            def build(self):\n                msbuild = MSBuild(self)\n                msbuild.build(\"MyProject.sln\")\n        \"\"\")\n    files = get_vs_project_files()\n    main_cpp = gen_function_cpp(name=\"main\", includes=[\"mydep.pkg.team\"], calls=[\"mydep_pkg_team\"])\n    files[\"MyProject/main.cpp\"] = main_cpp\n    files[\"conanfile.py\"] = consumer\n\n    # INJECT PROPS FILES\n    props = os.path.join(client.current_folder, \"conandeps.props\")\n    old = r'<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />'\n    new = old + f'<Import Project=\"{props}\" />'\n    files[\"MyProject/MyProject.vcxproj\"] = files[\"MyProject/MyProject.vcxproj\"].replace(old, new)\n    old = r'<Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />'\n    toolchain = os.path.join(client.current_folder, \"conantoolchain.props\")\n    new = f'<Import Project=\"{toolchain}\" />' + old\n    files[\"MyProject/MyProject.vcxproj\"] = files[\"MyProject/MyProject.vcxproj\"].replace(old, new)\n\n    client.save(files, clean_first=True)\n    client.run('build .  -s compiler.version={vs_version}'.format(vs_version=vs_version))\n    client.run_command(r\"x64\\Release\\MyProject.exe\")\n    assert \"mydep.pkg.team/0.1: Hello World Release!\" in client.out\n    assert \"updep.pkg.team/0.1: Hello World Release!\" in client.out\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires MSBuild\")\ndef test_private_transitive():\n    # https://github.com/conan-io/conan/issues/9514\n    client = TestClient()\n    client.save({\"dep/conanfile.py\": GenConanfile(),\n                 \"pkg/conanfile.py\": GenConanfile().with_requirement(\"dep/0.1\", visible=False),\n                 \"consumer/conanfile.py\": GenConanfile().with_requires(\"pkg/0.1\")\n                                                        .with_settings(\"os\", \"build_type\", \"arch\")})\n    client.run(\"create dep --name=dep --version=0.1\")\n    client.run(\"create pkg --name=pkg --version=0.1\")\n    client.run(\"install consumer -g MSBuildDeps -s arch=x86_64 -s build_type=Release -v\")\n    client.assert_listed_binary({\"dep/0.1\": (NO_SETTINGS_PACKAGE_ID, \"Skip\")})\n    deps_props = client.load(\"consumer/conandeps.props\")\n    assert \"conan_pkg.props\" in deps_props\n    assert \"dep\" not in deps_props\n\n    pkg_data_props = client.load(\"consumer/conan_pkg_release_x64.props\")\n    assert \"conan_dep.props\" not in pkg_data_props\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires MSBuild\")\ndef test_build_requires():\n    # https://github.com/conan-io/conan/issues/9545\n    client = TestClient()\n    package = \"copy(self, '*', os.path.join(self.build_folder, str(self.settings.arch)),\" \\\n              \" os.path.join(self.package_folder, 'bin'))\"\n    dep = GenConanfile().with_exports_sources(\"*\").with_settings(\"arch\").with_package(package)\\\n        .with_import(\"import os\").with_import(\"from conan.tools.files import copy\")\n    consumer = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.microsoft import MSBuild\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            build_requires = \"dep/0.1\"\n            generators = \"MSBuildDeps\", \"MSBuildToolchain\"\n            def build(self):\n                msbuild = MSBuild(self)\n                msbuild.build(\"hello.sln\")\n            \"\"\")\n    hello_vcxproj = textwrap.dedent(r\"\"\"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n        <Project DefaultTargets=\"Build\" ToolsVersion=\"15.0\"\n               xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n          <ItemGroup Label=\"ProjectConfigurations\">\n            <ProjectConfiguration Include=\"Release|Win32\">\n              <Configuration>Release</Configuration>\n              <Platform>Win32</Platform>\n            </ProjectConfiguration>\n            <ProjectConfiguration Include=\"Release|x64\">\n              <Configuration>Release</Configuration>\n              <Platform>x64</Platform>\n            </ProjectConfiguration>\n          </ItemGroup>\n          <PropertyGroup Label=\"Globals\">\n            <VCProjectVersion>15.0</VCProjectVersion>\n            <ProjectGuid>{6F392A05-B151-490C-9505-B2A49720C4D9}</ProjectGuid>\n            <Keyword>Win32Proj</Keyword>\n            <RootNamespace>MyProject</RootNamespace>\n          </PropertyGroup>\n          <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n\n          <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\"\n                         Label=\"Configuration\">\n            <ConfigurationType>Application</ConfigurationType>\n            <UseDebugLibraries>false</UseDebugLibraries>\n            <PlatformToolset>v141</PlatformToolset>\n            <WholeProgramOptimization>true</WholeProgramOptimization>\n            <CharacterSet>Unicode</CharacterSet>\n          </PropertyGroup>\n          <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|x64'\"\n                         Label=\"Configuration\">\n            <ConfigurationType>Application</ConfigurationType>\n            <UseDebugLibraries>false</UseDebugLibraries>\n            <PlatformToolset>v141</PlatformToolset>\n            <WholeProgramOptimization>true</WholeProgramOptimization>\n            <CharacterSet>Unicode</CharacterSet>\n          </PropertyGroup>\n\n          <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n\n          <ImportGroup Label=\"PropertySheets\">\n            <Import Project=\"..\\conandeps.props\" />\n          </ImportGroup>\n\n          <PropertyGroup Label=\"UserMacros\" />\n\n            <ItemGroup>\n            <CustomBuild Include=\"data.proto\">\n              <FileType>Document</FileType>\n              <Outputs>data.proto.h</Outputs>\n              <Command>dep1tool</Command>\n            </CustomBuild>\n          </ItemGroup>\n          <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n          <ImportGroup Label=\"ExtensionTargets\">\n          </ImportGroup>\n        </Project>\"\"\")\n\n    hello_sln = textwrap.dedent(r\"\"\"\n        Microsoft Visual Studio Solution File, Format Version 12.00\n        # Visual Studio 15\n        VisualStudioVersion = 15.0.28307.757\n        MinimumVisualStudioVersion = 10.0.40219.1\n        Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"MyProject\", \"MyProject\\MyProject.vcxproj\", \"{6F392A05-B151-490C-9505-B2A49720C4D9}\"\n        EndProject\n        Global\n            GlobalSection(SolutionConfigurationPlatforms) = preSolution\n                Release|x64 = Release|x64\n                Release|x86 = Release|x86\n            EndGlobalSection\n            GlobalSection(ProjectConfigurationPlatforms) = postSolution\n                {6F392A05-B151-490C-9505-B2A49720C4D9}.Release|x64.ActiveCfg = Release|x64\n                {6F392A05-B151-490C-9505-B2A49720C4D9}.Release|x64.Build.0 = Release|x64\n                {6F392A05-B151-490C-9505-B2A49720C4D9}.Release|x86.ActiveCfg = Release|Win32\n                {6F392A05-B151-490C-9505-B2A49720C4D9}.Release|x86.Build.0 = Release|Win32\n            EndGlobalSection\n            GlobalSection(SolutionProperties) = preSolution\n                HideSolutionNode = FALSE\n            EndGlobalSection\n            GlobalSection(ExtensibilityGlobals) = postSolution\n                SolutionGuid = {DE6E462F-E299-4F9C-951A-F9404EB51521}\n            EndGlobalSection\n        EndGlobal\n        \"\"\")\n    client.save({\"dep/conanfile.py\": dep,\n                 \"dep/x86/dep1tool.bat\": \"@echo Invoking 32bit dep_1 build tool\",\n                 \"dep/x86_64/dep1tool.bat\": \"@echo Invoking 64bit dep_1 build tool\",\n                 \"consumer/conanfile.py\": consumer,\n                 \"consumer/hello.sln\": hello_sln,\n                 \"consumer/MyProject/MyProject.vcxproj\": hello_vcxproj,\n                 \"consumer/MyProject/data.proto\": \"dataproto\"})\n    client.run(\"create dep --name=dep --version=0.1 -s arch=x86\")\n    client.run(\"create dep --name=dep --version=0.1 -s arch=x86_64\")\n    with client.chdir(\"consumer\"):\n        client.run('build . -s compiler=msvc -s compiler.version=191 '\n                   \" -s arch=x86_64 -s build_type=Release\")\n        client.assert_listed_binary({\"dep/0.1\": (\"62e589af96a19807968167026d906e63ed4de1f5\",\n                                                 \"Cache\")}, build=True)\n        deps_props = client.load(\"conandeps.props\")\n        assert \"conan_dep_build.props\" in deps_props\n        assert \"Invoking 64bit dep_1 build tool\" in client.out\n\n        client.run('build . -s compiler=msvc -s compiler.version=191 '\n                   \" -s:b arch=x86 -s build_type=Release\")\n        assert \"Invoking 32bit dep_1 build tool\" in client.out\n\n        # Make sure it works with 2 profiles too\n        client.run('install . -s compiler=msvc -s compiler.version=191 '\n                   \" -s arch=x86_64 -s build_type=Release -s:b os=Windows -s:h os=Windows\")\n        client.run(\"build .\")\n        assert \"Invoking 64bit dep_1 build tool\" in client.out\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires MSBuild\")\ndef test_build_requires_transitives():\n    \"\"\" The tool-requires should not bring transitive dependencies, they will conflict and\n    are useless for linking\n    \"\"\"\n    # https://github.com/conan-io/conan/issues/10222\n    c = TestClient()\n    c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\").with_package_type(\"shared-library\"),\n            \"tool/conanfile.py\": GenConanfile(\"tool\", \"0.1\").with_requires(\"dep/0.1\"),\n            \"consumer/conanfile.py\":\n                GenConanfile().with_settings(\"os\", \"compiler\", \"build_type\", \"arch\")\n                              .with_build_requires(\"tool/0.1\")})\n    c.run(\"create dep\")\n    c.run(\"create tool\")\n    c.run(\"install consumer -g MSBuildDeps -of=.\")\n    tool = c.load(\"conan_tool_build_release_x64.props\")\n    assert \"conan_dep_build.props\" in tool\n    assert \"conan_dep.props\" not in tool\n    tool_vars = c.load(\"conan_tool_build_vars_release_x64.props\")\n    assert \"<Conantool_buildRootFolder>\" in tool_vars\n"
  },
  {
    "path": "test/functional/toolchains/microsoft/test_msbuilddeps_components.py",
    "content": "import platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.sources import gen_function_cpp\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows\")\ndef test_msbuild_deps_components():\n    # TODO: Duplicated from xcodedeps_components\n    client = TestClient()\n\n    client.run(\"new cmake_lib -d name=tcp -d version=1.0\")\n    client.run(\"create . -tf=\\\"\\\"\")\n\n    header = textwrap.dedent(\"\"\"\n        #pragma once\n        void {name}();\n        \"\"\")\n\n    source = textwrap.dedent(\"\"\"\n        #include <iostream>\n        #include \"{name}.h\"\n        {include}\n\n        void {name}(){{\n            {call}\n            #ifdef NDEBUG\n            std::cout << \"{name}/1.0: Hello World Release!\" << std::endl;\n            #else\n            std::cout << \"{name}/1.0: Hello World Debug!\" << std::endl;\n            #endif\n        }}\n        \"\"\")\n\n    cmakelists = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.15)\n        project(myproject CXX)\n\n        find_package(tcp REQUIRED CONFIG)\n\n        add_library(core src/core.cpp include/core.h)\n        add_library(client src/client.cpp include/client.h)\n        add_library(server src/server.cpp include/server.h)\n\n        target_include_directories(core PUBLIC include)\n        target_include_directories(client PUBLIC include)\n        target_include_directories(server PUBLIC include)\n\n        set_target_properties(core PROPERTIES PUBLIC_HEADER \"include/core.h\")\n        set_target_properties(client PROPERTIES PUBLIC_HEADER \"include/client.h\")\n        set_target_properties(server PROPERTIES PUBLIC_HEADER \"include/server.h\")\n\n        target_link_libraries(client core tcp::tcp)\n        target_link_libraries(server core tcp::tcp)\n\n        install(TARGETS core client server)\n        \"\"\")\n\n    conanfile_py = textwrap.dedent(\"\"\"\n        import os\n\n        from conan import ConanFile\n        from conan.tools.cmake import CMake, cmake_layout\n\n\n        class LibConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            exports_sources = \"CMakeLists.txt\", \"src/*\", \"include/*\"\n            {requires}\n            generators = \"CMakeToolchain\", \"CMakeDeps\"\n\n            def layout(self):\n                cmake_layout(self)\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure()\n                cmake.build()\n\n            def package(self):\n                cmake = CMake(self)\n                cmake.install()\n            {package_info}\n        \"\"\")\n\n    network_pi = \"\"\"\n    def package_info(self):\n        self.cpp_info.components[\"core\"].libs = [\"core\"]\n        self.cpp_info.components[\"core\"].includedirs.append(\"include\")\n        self.cpp_info.components[\"core\"].libdirs.append(\"lib\")\n\n        self.cpp_info.components[\"client\"].libs = [\"client\"]\n        self.cpp_info.components[\"client\"].includedirs.append(\"include\")\n        self.cpp_info.components[\"client\"].libdirs.append(\"lib\")\n        self.cpp_info.components[\"client\"].requires.extend([\"core\", \"tcp::tcp\"])\n\n        self.cpp_info.components[\"server\"].libs = [\"server\"]\n        self.cpp_info.components[\"server\"].includedirs.append(\"include\")\n        self.cpp_info.components[\"server\"].libdirs.append(\"lib\")\n        self.cpp_info.components[\"server\"].requires.extend([\"core\", \"tcp::tcp\"])\n    \"\"\"\n\n    client.save({\n        \"include/core.h\": header.format(name=\"core\"),\n        \"include/server.h\": header.format(name=\"server\"),\n        \"include/client.h\": header.format(name=\"client\"),\n        \"src/core.cpp\": source.format(name=\"core\", include=\"\", call=\"\"),\n        \"src/server.cpp\": source.format(name=\"server\",\n                                        include='#include \"core.h\"\\n#include \"tcp.h\"',\n                                        call=\"core(); tcp();\"),\n        \"src/client.cpp\": source.format(name=\"client\", include='#include \"core.h\"\\n#include \"tcp.h\"',\n                                        call=\"core(); tcp();\"),\n        \"conanfile.py\": conanfile_py.format(requires='requires= \"tcp/1.0\"', package_info=network_pi),\n        \"CMakeLists.txt\": cmakelists,\n    }, clean_first=True)\n\n    client.run(\"create . --name=network --version=1.0\")\n\n    chat_pi = \"\"\"\n    def package_info(self):\n        self.cpp_info.libs = [\"chat\"]\n        self.cpp_info.includedirs.append(\"include\")\n        self.cpp_info.libdirs.append(\"lib\")\n        self.cpp_info.requires.append(\"network::client\")\n    \"\"\"\n\n    cmakelists_chat = textwrap.dedent(\"\"\"\n        set(CMAKE_CXX_COMPILER_WORKS 1)\n        set(CMAKE_CXX_ABI_COMPILED 1)\n        cmake_minimum_required(VERSION 3.15)\n        project(chat CXX)\n        find_package(network REQUIRED CONFIG)\n        add_library(chat src/chat.cpp include/chat.h)\n        target_include_directories(chat PUBLIC include)\n        set_target_properties(chat PROPERTIES PUBLIC_HEADER \"include/chat.h\")\n        target_link_libraries(chat network::client)\n        install(TARGETS chat)\n        \"\"\")\n\n    client.save({\n        \"include/chat.h\": header.format(name=\"chat\"),\n        \"src/chat.cpp\": source.format(name=\"chat\", include='#include \"client.h\"', call=\"client();\"),\n        \"conanfile.py\": conanfile_py.format(requires='requires= \"network/1.0\"',\n                                            package_info=chat_pi),\n        \"CMakeLists.txt\": cmakelists_chat,\n    }, clean_first=True)\n\n    client.run(\"create . --name=chat --version=1.0\")\n\n    client.run(\"new msbuild_exe -d name=greet -d version=0.1 -f\")\n    conanfile = client.load(\"conanfile.py\").replace(\"settings = \",\n                                                    'requires=\"chat/1.0\"\\n'\n                                                    '    generators = \"MSBuildDeps\"\\n'\n                                                    '    settings = ')\n    vcproj = client.load(\"greet.vcxproj\")\n    vcproj2 = vcproj.replace(r'<Import Project=\"conan\\conantoolchain.props\" />',\n                             r\"\"\"<Import Project=\"conan\\conantoolchain.props\" />\n                               <Import Project=\"conan\\conandeps.props\" />\n                             \"\"\")\n    assert vcproj2 != vcproj\n    client.save({\"conanfile.py\": conanfile,\n                 \"src/greet.cpp\": gen_function_cpp(name=\"main\", includes=[\"chat\"],\n                                                   calls=[\"chat\"]),\n                 \"greet.vcxproj\": vcproj2})\n    client.run(\"create .\")\n    assert \"main: Release!\" in client.out\n    assert \"core/1.0: Hello World Release!\" in client.out\n    assert \"tcp/1.0: Hello World Release!\" in client.out\n    assert \"client/1.0: Hello World Release!\" in client.out\n    assert \"chat/1.0: Hello World Release!\" in client.out\n    assert \"server/1.0\" not in client.out\n"
  },
  {
    "path": "test/functional/toolchains/microsoft/test_msbuilddeps_traits.py",
    "content": "import os\nimport platform\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires MSBuild\")\ndef test_transitive_headers_not_public(transitive_libraries):\n    c = transitive_libraries\n    c.save({\"conanfile.py\": GenConanfile().with_settings(\"build_type\", \"arch\")\n                                          .with_generator(\"MSBuildDeps\").with_requires(\"engine/1.0\")},\n           clean_first=True)\n\n    c.run(\"install .\")\n    matrix_data = c.load(\"conan_matrix_vars_release_x64.props\")\n    assert \"<ConanmatrixIncludeDirectories></ConanmatrixIncludeDirectories>\" in matrix_data\n    assert \"<ConanmatrixLibraryDirectories>$(ConanmatrixRootFolder)/lib;\" \\\n           \"</ConanmatrixLibraryDirectories>\" in matrix_data\n    assert \"<ConanmatrixLibraries>matrix.lib;</ConanmatrixLibraries>\" in matrix_data\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires MSBuild\")\ndef test_shared_requires_static(transitive_libraries):\n    c = transitive_libraries\n    c.save({\"conanfile.py\": GenConanfile().with_settings(\"build_type\", \"arch\")\n           .with_generator(\"MSBuildDeps\").with_requires(\"engine/1.0\")},\n           clean_first=True)\n\n    c.run(\"install . -o engine*:shared=True\")\n    assert not os.path.exists(os.path.join(c.current_folder, \"conan_matrix_vars_release_x64.props\"))\n    engine_data = c.load(\"conan_engine_release_x64.props\")\n    # No dependency to matrix, it has been skipped as unnecessary\n    assert \"conan_matrix.props\" not in engine_data\n"
  },
  {
    "path": "test/functional/toolchains/microsoft/test_msbuildtoolchain.py",
    "content": "import platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows\")\ndef test_msbuildtoolchain_props_with_extra_flags():\n    \"\"\"\n    Real test which is injecting some compiler/linker options and other dummy defines and\n    checking that they are being processed somehow.\n\n    Expected result: everything was built successfully.\n    \"\"\"\n    profile = textwrap.dedent(\"\"\"\\\n    include(default)\n\n    [conf]\n    tools.build:cxxflags=[\"/analyze:quiet\"]\n    tools.build:cflags+=[\"/doc\"]\n    tools.build:sharedlinkflags+=[\"/VERBOSE:UNUSEDLIBS\"]\n    tools.build:exelinkflags+=[\"/PDB:mypdbfile\"]\n    tools.build:defines+=[\"DEF1\", \"DEF2\"]\n    \"\"\")\n    client = TestClient(path_with_spaces=False)\n    client.run(\"new msbuild_exe -d name=hello -d version=0.1\")\n    client.save({\"myprofile\": profile})\n    #  conantoolchain.props is already imported in the msbuild_exe tempalte\n    client.run(\"create . -pr myprofile -tf=\")\n    assert \"/analyze:quiet /doc src/hello.cpp\" in client.out\n    assert r\"/VERBOSE:UNUSEDLIBS /PDB:mypdbfile x64\\Release\\hello.obj\" in client.out\n    assert \"/D DEF1 /D DEF2\" in client.out\n    assert \"Build succeeded.\" in client.out\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows\")\ndef test_msbuildtoolchain_winsdk_version():\n    \"\"\"\n    Configure sdk_version\n    \"\"\"\n    client = TestClient(path_with_spaces=False)\n    client.run(\"new msbuild_lib -d name=hello -d version=0.1\")\n    #  conantoolchain.props is already imported in the msbuild_exe tempalte\n    client.run(\"create . -s arch=x86_64 -s compiler.version=193 \"\n               \"-c tools.microsoft:winsdk_version=10.0\")\n    # I have verified also opening VS IDE that the setting is correctly configured\n    # because the test always run over vcvars that already activates it\n    assert \"amd64 - winsdk_version=10.0 - vcvars_ver=14.3\" in client.out\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows\")\ndef test_msbuildtoolchain_compiler_update():\n    # It only works for update=8, because 19.38 is the compiler in Github actions!\n    client = TestClient(path_with_spaces=False)\n    client.run(\"new msbuild_lib -d name=hello -d version=0.1\")\n    #  conantoolchain.props is already imported in the msbuild_exe tempalte\n    client.run(\"create . -s arch=x86_64 -s compiler.version=193 -s compiler.update=8\")\n    # I have verified also opening VS IDE that the setting is correctly configured\n    # because the test always run over vcvars that already activates it\n    assert \"amd64 - winsdk_version=None - vcvars_ver=14.38\" in client.out\n    assert \"hello/0.1: _MSC_VER1938\" in client.out\n\n\n@pytest.mark.tool(\"visual_studio\")\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Only for windows\")\nclass TestTxtCommandLineMSBuild:\n\n    def test_declarative(self):\n        conanfile = textwrap.dedent(\"\"\"\n            [generators]\n            MSBuildToolchain\n            \"\"\")\n        client = TestClient()\n        client.save({\"conanfile.txt\": conanfile})\n        client.run(\"install .\")\n        self._check(client)\n\n    @staticmethod\n    def _check(client):\n        assert \"conanfile.txt: Generator 'MSBuildToolchain' calling 'generate()'\" in client.out\n        toolchain = client.load(\"conantoolchain.props\")\n        assert \"<?xml version\" in toolchain\n\n    def test_command_line(self):\n        client = TestClient()\n        client.save({\"conanfile.txt\": \"\"})\n        client.run(\"install . -g MSBuildToolchain\")\n        self._check(client)\n"
  },
  {
    "path": "test/functional/toolchains/microsoft/test_v2_msbuild_template.py",
    "content": "import os\nimport platform\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows\")\ndef test_msbuild_lib_template():\n    client = TestClient()\n    client.run(\"new msbuild_lib -d name=hello -d version=0.1\")\n    # Local flow works\n    client.run(\"install .\")\n    client.run(\"build .\")\n\n    assert os.path.isfile(os.path.join(client.current_folder, \"x64\", \"Release\", \"hello.lib\"))\n    client.run(\"export-pkg .\")\n    package_folder = client.created_layout().package()\n    assert os.path.exists(os.path.join(package_folder, \"include\", \"hello.h\"))\n    assert os.path.exists(os.path.join(package_folder, \"lib\", \"hello.lib\"))\n\n    # Create works\n    client.run(\"create .\")\n    assert \"hello/0.1: Hello World Release!\" in client.out\n    assert \"hello/0.1: _MSC_VER191\" in client.out\n\n    client.run(\"create . -s build_type=Debug\")\n    assert \"hello/0.1: Hello World Debug!\" in client.out\n\n    # FIXME: Create + shared DOESNT work fine, the proj is hardcoded to static\n    # client.run(\"create . -o hello:shared=True\")\n    # assert \"hello/0.1: Hello World Release!\" in client.out\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows\")\n@pytest.mark.tool(\"visual_studio\", \"17\")\ndef test_msbuild_lib_2022():\n    # The template .vcxproj are MSBuildTools=15, so it won't work with older versions\n    # 2022 Must have installed the v141 toolset too\n    client = TestClient(path_with_spaces=False)\n    client.run(\"new msbuild_lib -d name=hello -d version=0.1\")\n\n    # Create works\n    client.run(\"create . -s compiler.version=191 -c tools.microsoft.msbuild:vs_version=17\")\n    assert \"hello/0.1: Hello World Release!\" in client.out\n    # This is the default compiler.version=191 in conftest\n    assert \"Activating environment Visual Studio 17\" in client.out\n    assert \"hello/0.1: _MSC_VER191\" in client.out\n\n    # Create works\n    client.run(\"create . -s compiler.version=193\")\n    assert \"hello/0.1: Hello World Release!\" in client.out\n    assert \"Activating environment Visual Studio 17\" in client.out\n    assert \"hello/0.1: _MSC_VER193\" in client.out\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows\")\ndef test_msbuild_exe_template():\n    client = TestClient(path_with_spaces=False)\n    client.run(\"new msbuild_exe -d name=greet -d version=0.1\")\n    # Local flow works\n    client.run(\"install .\")\n    client.run(\"build .\")\n\n    # Create works\n    client.run(\"create .\")\n    assert \"greet/0.1: Hello World Release!\" in client.out\n\n    client.run(\"create . -s build_type=Debug\")\n    assert \"greet/0.1: Hello World Debug!\" in client.out\n"
  },
  {
    "path": "test/functional/toolchains/microsoft/test_vcvars.py",
    "content": "import platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows\")\n@pytest.mark.tool(\"visual_studio\", \"17\")\ndef test_deactivate_vcvars_message():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class TestConan(ConanFile):\n                generators = \"VCVars\"\n                settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run('install . -s compiler.version=194')\n    client.run_command(r'conanbuild.bat')\n    assert \"[vcvarsall.bat] Environment initialized\" in client.out\n    client.run_command(r'deactivate_conanvcvars.bat')\n    assert \"vcvars env cannot be deactivated\" in client.out\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows Powershell\")\ndef test_deactivate_vcvars_with_powershell():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n                from conan import ConanFile\n                class TestConan(ConanFile):\n                    generators = \"VCVars\"\n                    settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run('install . -c tools.env.virtualenv:powershell=True')\n    client.run_command(r'powershell.exe \".\\conanbuild.ps1\"')\n    assert \"conanvcvars.ps1: Activated environment\" in client.out\n    client.run_command(r'powershell.exe \".\\deactivate_conanvcvars.ps1\"')\n    assert \"vcvars env cannot be deactivated\" in client.out\n"
  },
  {
    "path": "test/functional/toolchains/qbs/__init__.py",
    "content": ""
  },
  {
    "path": "test/functional/toolchains/qbs/test_qbs.py",
    "content": "import os\nimport platform\n\nimport pytest\nimport textwrap\n\nfrom conan.internal.api.new.cmake_lib import source_cpp, source_h\nfrom conan.internal.api.new.qbs_lib import qbs_lib_file\nfrom conan.test.utils.tools import TestClient\nfrom jinja2 import Template\n\n\ndef gen_file(template, **context):\n    t = Template(template)\n    return t.render(**context)\n\n\n@pytest.mark.parametrize('shared', [False, True])\n@pytest.mark.skipif(platform.system() != \"Linux\", reason=\"QBS only for Linux now\")\n@pytest.mark.tool(\"qbs\")\ndef test_api_qbs_create_lib(shared):\n    client = TestClient()\n    client.run(\"new qbs_lib -d name=hello -d version=1.0\")\n    client.run(\"create . -o:h &:shared={shared}\".format(shared=shared))\n    assert \"compiling hello.cpp\" in client.out\n\n\n@pytest.mark.skipif(platform.system() != \"Linux\", reason=\"QBS only for Linux now\")\n@pytest.mark.tool(\"qbs\")\ndef test_qbs_all_products():\n    client = TestClient()\n\n    context = {\n        \"name\": \"hello\",\n        \"version\": \"2.0\",\n        \"package_name\": \"hello\"\n    }\n\n    conanfile = textwrap.dedent('''\n    import os\n\n    from conan import ConanFile\n    from conan.tools.qbs import Qbs\n\n    class Recipe(ConanFile):\n        name = \"hello\"\n        version = \"1.0\"\n\n        exports_sources = \"*.cpp\", \"*.h\", \"*.qbs\"\n        settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n\n        def build(self):\n            qbs = Qbs(self)\n            qbs.resolve()\n            qbs.build_all()\n        ''')\n\n    client.save({\n        \"conanfile.py\": conanfile,\n        \"hello.cpp\": gen_file(source_cpp, **context),\n        \"hello.h\": gen_file(source_h, **context),\n        \"hello.qbs\": gen_file(qbs_lib_file, **context),\n    }, clean_first=True)\n\n    client.run(\"create .\")\n    assert \"--all-products\" in client.out\n\n\n@pytest.mark.skipif(platform.system() != \"Linux\", reason=\"QBS only for Linux now\")\n@pytest.mark.tool(\"qbs\")\ndef test_qbs_specific_products():\n    client = TestClient()\n\n    context = {\n        \"name\": \"hello\",\n        \"version\": \"2.0\",\n        \"package_name\": \"hello\"\n    }\n\n    conanfile = textwrap.dedent('''\n    import os\n\n    from conan import ConanFile\n    from conan.tools.qbs import Qbs\n\n    class Recipe(ConanFile):\n        name = \"hello\"\n        version = \"1.0\"\n\n        exports_sources = \"*.cpp\", \"*.h\", \"*.qbs\"\n        settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n\n        def build(self):\n            qbs = Qbs(self)\n            qbs.resolve()\n            qbs.build(products=[\"hello\", \"hello\"])\n        ''')\n\n    client.save({\n        \"conanfile.py\": conanfile,\n        \"hello.cpp\": gen_file(source_cpp, **context),\n        \"hello.h\": gen_file(source_h, **context),\n        \"hello.qbs\": gen_file(qbs_lib_file, **context),\n    }, clean_first=True)\n\n    client.run(\"create .\")\n    assert \"--products hello,hello\" in client.out\n\n\n@pytest.mark.skipif(platform.system() != \"Linux\", reason=\"QBS only for Linux now\")\n@pytest.mark.tool(\"qbs\")\ndef test_qbs_multiple_configurations():\n    client = TestClient()\n\n    context = {\n        \"name\": \"hello\",\n        \"version\": \"2.0\",\n        \"package_name\": \"hello\"\n    }\n\n    conanfile = textwrap.dedent('''\n    import os\n\n    from conan import ConanFile\n    from conan.tools.qbs import Qbs\n\n    class Recipe(ConanFile):\n        name = \"hello\"\n        version = \"1.0\"\n\n        exports_sources = \"*.cpp\", \"*.h\", \"*.qbs\"\n        settings = \"os\", \"compiler\", \"arch\"\n\n        def build(self):\n            qbs = Qbs(self)\n            qbs.add_configuration(\"release\", {\"qbs.debugInformation\": False})\n            qbs.add_configuration(\"debug\", {\"qbs.debugInformation\": True})\n            qbs.resolve()\n            qbs.build()\n        ''')\n\n    client.save({\n        \"conanfile.py\": conanfile,\n        \"hello.cpp\": gen_file(source_cpp, **context),\n        \"hello.h\": gen_file(source_h, **context),\n        \"hello.qbs\": gen_file(qbs_lib_file, **context),\n    }, clean_first=True)\n\n    client.run(\"create .\")\n    build_folder = client.created_layout().build()\n    assert os.path.exists(os.path.join(build_folder, \"release\"))\n    assert os.path.exists(os.path.join(build_folder, \"debug\"))\n"
  },
  {
    "path": "test/functional/toolchains/qbs/test_qbsdeps.py",
    "content": "import platform\n\nimport pytest\n\nimport textwrap\n\nfrom conan.test.assets.sources import gen_function_cpp\nfrom conan.test.utils.tools import TestClient\nfrom jinja2 import Template\n\n\ndef gen_qbs_application(**context):\n    qbsfile = textwrap.dedent('''\n        CppApplication {\n            files: [{% for s in files %} \"{{s}}\", {% endfor %}]\n            {% for d in deps %}\n            Depends {\n                name: \"{{d}}\"\n            }\n            {% endfor %}\n            qbsModuleProviders: [\"conan\"]\n        }\n    ''')\n\n    t = Template(qbsfile)\n    return t.render(**context)\n\n\n@pytest.mark.skipif(platform.system() != \"Linux\", reason=\"QBS only for Linux now\")\n@pytest.mark.tool(\"qbs\")\ndef test_qbsdeps_with_test_requires_header_only():\n    client = TestClient()\n    with client.chdir(\"lib\"):\n        conanfile = textwrap.dedent('''\n            from conan import ConanFile\n            from conan.tools.files import copy\n            import os\n            class Recipe(ConanFile):\n                exports_sources = (\"hello.h\")\n                version = '0.1.0'\n                name = 'hello'\n                def package(self):\n                    copy(self,\n                         \"hello.h\",\n                         src=self.source_folder,\n                         dst=os.path.join(self.package_folder, \"include\"))\n        ''')\n        header = textwrap.dedent('''\n            #pragma once\n            inline int hello() { return 0; }\n        ''')\n        client.save({\n            'conanfile.py': conanfile,\n            'hello.h': header\n        })\n        client.run('create .')\n\n    conanfile = textwrap.dedent('''\n        from conan import ConanFile\n        class Recipe(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"QbsDeps\"\n            def requirements(self):\n                self.requires('hello/0.1.0')\n        ''')\n    client.save({\n        \"conanfile.py\": conanfile,\n        \"main.cpp\": gen_function_cpp(name=\"main\", includes=[\"hello\"], calls=[\"hello\"]),\n        \"app.qbs\": gen_qbs_application(files=[\"main.cpp\"], deps=[\"hello\"]),\n    }, clean_first=True)\n    client.run(\"install .\")\n    client.run_command(\"qbs build moduleProviders.conan.installDirectory:.\")\n\n\n@pytest.mark.skipif(platform.system() != \"Linux\", reason=\"QBS only for Linux now\")\n@pytest.mark.tool(\"qbs\")\ndef test_qbsdeps_with_test_requires_lib():\n    client = TestClient()\n    with client.chdir(\"lib\"):\n        client.run(\"new qbs_lib -d name=hello -d version=1.0\")\n        client.run(\"create . -tf=\\\"\\\"\")\n\n    conanfile = textwrap.dedent('''\n        from conan import ConanFile\n        class Recipe(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"QbsDeps\"\n            def requirements(self):\n                self.requires('hello/1.0')\n        ''')\n    client.save({\n        \"conanfile.py\": conanfile,\n        \"main.cpp\": gen_function_cpp(name=\"main\", includes=[\"hello\"], calls=[\"hello\"]),\n        \"app.qbs\": gen_qbs_application(files=[\"main.cpp\"], deps=[\"hello\"]),\n    }, clean_first=True)\n    client.run(\"install .\")\n    client.run_command(\"qbs build moduleProviders.conan.installDirectory:.\")\n\n\n@pytest.mark.skipif(platform.system() != \"Linux\", reason=\"QBS only for Linux now\")\n@pytest.mark.tool(\"qbs\")\ndef test_qbsdeps_with_qbs_toolchain():\n    client = TestClient()\n    with client.chdir(\"lib\"):\n        client.run(\"new qbs_lib -d name=hello -d version=1.0\")\n        client.run(\"create . -tf=\\\"\\\"\")\n\n    conanfile = textwrap.dedent('''\n        from conan import ConanFile\n        from conan.tools.qbs import Qbs\n\n        class Recipe(ConanFile):\n            name = \"app\"\n            version = \"1.2\"\n            exports_sources = \"*.cpp\", \"*.h\", \"*.qbs\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"QbsDeps\"\n\n            def requirements(self):\n                self.requires(\"hello/1.0\")\n\n            def layout(self):\n                self.folders.generators = \"generators\"\n\n            def build(self):\n                qbs = Qbs(self)\n                qbs.resolve()\n                qbs.build()\n\n            def install(self):\n                qbs = Qbs(self)\n                qbs.install()\n        ''')\n    client.save({\n        \"conanfile.py\": conanfile,\n        \"main.cpp\": gen_function_cpp(name=\"main\", includes=[\"hello\"], calls=[\"hello\"]),\n        \"app.qbs\": gen_qbs_application(files=[\"main.cpp\"], deps=[\"hello\"]),\n    }, clean_first=True)\n    client.run(\"create .\")\n"
  },
  {
    "path": "test/functional/toolchains/qbs/test_qbsprofile.py",
    "content": "import platform\nimport textwrap\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\nfrom conan.test.assets.sources import gen_function_cpp\n\n\n@pytest.mark.skipif(platform.system() != \"Linux\", reason=\"QBS only for Linux now\")\n@pytest.mark.tool(\"qbs\")\ndef test_qbsprofile():\n    client = TestClient()\n\n    conanfile = textwrap.dedent('''\n        from conan import ConanFile\n        from conan.tools.qbs import Qbs\n\n        class Recipe(ConanFile):\n            name = \"app\"\n            version = \"1.2\"\n            exports_sources = \"*.cpp\", \"*.h\", \"*.qbs\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"QbsProfile\"\n\n            def layout(self):\n                self.folders.generators = \"generators\"\n\n            def build(self):\n                qbs = Qbs(self)\n                qbs.resolve()\n                qbs.build()\n\n            def package(self):\n                qbs = Qbs(self)\n                qbs.install()\n        ''')\n\n    qbsfile = textwrap.dedent('''\n        CppApplication {\n            files: [\"main.cpp\"]\n        }\n    ''')\n\n    client.save({\n        \"conanfile.py\": conanfile,\n        \"main.cpp\": gen_function_cpp(name=\"main\"),\n        \"app.qbs\": qbsfile,\n    }, clean_first=True)\n    client.run(\"create .\")\n\n    assert \"qbs resolve --settings-dir\" in client.out\n    assert \"qbs build --settings-dir\" in client.out\n    assert \"qbs install --settings-dir\" in client.out\n"
  },
  {
    "path": "test/functional/toolchains/qbs/test_qbsprofile_gen.py",
    "content": "import os\nimport platform\nimport textwrap\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import load\n\n\ndef exe_suffix():\n    return '.exe' if platform.system() == 'Windows' else ''\n\n\nCOMPILER_MAP = {\n    'gcc': ('gcc', 'g++'),\n    'clang': ('clang', 'clang++')\n}\n\ncompiler_path = \"C:/opt/bin\" if platform.system() == 'Windows' else \"/opt/bin\"\n\n\n@pytest.mark.parametrize('compiler, version, system', [\n    ('gcc', '13', 'Linux'),\n    ('clang', '15', 'Linux'),\n])\ndef test_toolchain_from_path(compiler, version, system):\n    client = TestClient()\n    path = client.current_folder\n\n    profile = textwrap.dedent(f'''\n    [settings]\n    compiler={compiler}\n    compiler.version={version}\n    compiler.libcxx=libstdc++\n    os={system}\n    [buildenv]\n    PATH={path}\n    ''')\n\n    cc, cxx = COMPILER_MAP[compiler]\n\n    conanfile = textwrap.dedent('''\n    from conan import ConanFile\n    class Recipe(ConanFile):\n        settings = \"compiler\", \"os\"\n        name = \"mylib\"\n        version = \"0.1\"\n    ''')\n\n    client.save({cc + exe_suffix(): ''})\n    client.save({cxx + exe_suffix(): ''})\n    client.save({'profile': profile})\n    client.save({'conanfile.py': conanfile})\n    client.run('install . -pr:a=profile -g QbsProfile')\n\n    settings_path = os.path.join(client.current_folder, 'qbs_settings.txt')\n    assert os.path.exists(settings_path)\n\n    settings_content = load(settings_path)\n    assert f'qbs.toolchainType:{compiler}' in settings_content\n    toolchain_path = client.current_folder.replace('\\\\', '/')\n    assert f'cpp.toolchainInstallPath:{toolchain_path}' in settings_content\n    assert f'cpp.compilerName:{cxx}' in settings_content\n    assert f'cpp.cCompilerName:{cc}' in settings_content\n    assert f'cpp.cxxCompilerName:{cxx}' in settings_content\n\n\n@pytest.mark.parametrize('compiler, version, system, cc, cxx', [\n    ('gcc', '13', 'Linux', 'gcc', 'g++'),\n    ('clang', '15', 'Linux', 'clang', 'clang++'),\n])\ndef test_toolchain_from_conf(compiler, version, system, cc, cxx):\n    profile = textwrap.dedent(f'''\n    [settings]\n    compiler={compiler}\n    compiler.version={version}\n    compiler.libcxx=libstdc++\n    os={system}\n    [conf]\n    tools.build:compiler_executables ={{\"c\": \"{compiler_path}/{cc}\", \"cpp\": \"{compiler_path}/{cxx}\"}}\n    ''')\n\n    conanfile = textwrap.dedent('''\n    from conan import ConanFile\n    class Recipe(ConanFile):\n        settings = \"compiler\", \"os\"\n        name = \"mylib\"\n        version = \"0.1\"\n    ''')\n\n    client = TestClient()\n    client.save({'profile': profile})\n    client.save({'conanfile.py': conanfile})\n    client.run('install . -pr:a=profile -g QbsProfile')\n\n    settings_path = os.path.join(client.current_folder, 'qbs_settings.txt')\n    assert os.path.exists(settings_path)\n\n    settings_content = load(settings_path)\n    assert f'qbs.toolchainType:{compiler}' in settings_content\n    assert f'cpp.toolchainInstallPath:{compiler_path}' in settings_content\n    assert f'cpp.compilerName:{cxx}' in settings_content\n    assert f'cpp.cCompilerName:{cc}' in settings_content\n    assert f'cpp.cxxCompilerName:{cxx}' in settings_content\n\n\n@pytest.mark.parametrize('compiler, version, system, cc, cxx', [\n    ('gcc', '13', 'Linux', 'gcc', 'g++'),\n    ('clang', '15', 'Linux', 'clang', 'clang++'),\n])\ndef test_toolchain_from_env(compiler, version, system, cc, cxx):\n    profile = textwrap.dedent(f'''\n    [settings]\n    compiler={compiler}\n    compiler.version={version}\n    compiler.libcxx=libstdc++\n    os={system}\n    [buildenv]\n    CC={compiler_path}/{cc}\n    CXX={compiler_path}/{cxx}\n    ''')\n\n    conanfile = textwrap.dedent('''\n    from conan import ConanFile\n    class Recipe(ConanFile):\n        settings = \"compiler\", \"os\"\n        name = \"mylib\"\n        version = \"0.1\"\n    ''')\n\n    client = TestClient()\n    client.save({'profile': profile})\n    client.save({'conanfile.py': conanfile})\n    client.run('install . -pr:a=profile -g QbsProfile')\n\n    settings_path = os.path.join(client.current_folder, 'qbs_settings.txt')\n    assert os.path.exists(settings_path)\n\n    settings_content = load(settings_path)\n    assert f'qbs.toolchainType:{compiler}' in settings_content\n    assert f'cpp.toolchainInstallPath:{compiler_path}' in settings_content\n    assert f'cpp.compilerName:{cxx}' in settings_content\n    assert f'cpp.cCompilerName:{cc}' in settings_content\n    assert f'cpp.cxxCompilerName:{cxx}' in settings_content\n\n\n@pytest.mark.parametrize('system, compiler, version, build_type, arch, cppstd', [\n    ('Linux', 'gcc', '13', 'Release', 'x86_64', '17'),\n    ('Linux', 'gcc', '13', 'Debug', 'x86_64', '14'),\n    ('Linux', 'gcc', '13', 'Debug', 'x86', '20'),\n    ('Linux', 'gcc', '13', 'Release', 'avr', '11'),\n])\ndef test_options_from_settings(system, compiler, version, build_type, arch, cppstd):\n    client = TestClient()\n\n    cc, cxx = COMPILER_MAP[compiler]\n\n    profile = textwrap.dedent(f'''\n    [settings]\n    arch={arch}\n    build_type={build_type}\n    compiler={compiler}\n    compiler.version={version}\n    compiler.libcxx=libstdc++\n    compiler.cppstd={cppstd}\n    os={system}\n    [conf]\n    tools.build:compiler_executables ={{\"c\": \"{compiler_path}/{cc}\", \"cpp\": \"{compiler_path}/{cxx}\"}}\n    ''')\n\n    conanfile = textwrap.dedent('''\n    from conan import ConanFile\n    class Recipe(ConanFile):\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n        name = \"mylib\"\n        version = \"0.1\"\n    ''')\n\n    client.save({'profile': profile})\n    client.save({'conanfile.py': conanfile})\n    client.run('install . -pr:a=profile -g QbsProfile')\n\n    settings_path = os.path.join(client.current_folder, 'qbs_settings.txt')\n    assert os.path.exists(settings_path)\n    settings_content = load(settings_path)\n\n    assert f'qbs.architecture:{arch}' in settings_content\n    build_variant = build_type.lower()\n    assert f'qbs.buildVariant:{build_variant}' in settings_content\n    target_platform = system.lower()\n    assert f'qbs.targetPlatform:{target_platform}' in settings_content\n    assert 'cpp.cxxLanguageVersion:c++' + cppstd in settings_content\n    # TODO: cpp.runtimeLibrary (MSVC only)\n\n\ndef test_options_from_conf():\n    client = TestClient()\n\n    profile = textwrap.dedent(f'''\n    [settings]\n    arch=x86_64\n    build_type=Release\n    compiler=gcc\n    compiler.version=13\n    compiler.libcxx=libstdc++\n    compiler.cppstd=17\n    os=Linux\n    [conf]\n    tools.build:compiler_executables ={{\"c\": \"{compiler_path}/gcc\", \"cpp\": \"{compiler_path}/g++\"}}\n    tools.build:cflags=['-Dfoo', '-Dbar']\n    tools.build:cxxflags=['-Dfoo', '-Dbaz']\n    tools.build:sharedlinkflags=['-s']\n    tools.build:exelinkflags=['-Wl,-s']\n    ''')\n\n    conanfile = textwrap.dedent('''\n    from conan import ConanFile\n    class Recipe(ConanFile):\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n        name = \"mylib\"\n        version = \"0.1\"\n    ''')\n\n    client.save({'profile': profile})\n    client.save({'conanfile.py': conanfile})\n    client.run('install . -pr:a=profile -g QbsProfile')\n\n    settings_path = os.path.join(client.current_folder, 'qbs_settings.txt')\n    assert os.path.exists(settings_path)\n    settings_content = load(settings_path)\n\n    assert \"cpp.cFlags:['-Dfoo', '-Dbar']\" in settings_content\n    assert \"cpp.cxxFlags:['-Dfoo', '-Dbaz']\" in settings_content\n    assert \"cpp.linkerFlags:['-s']\" in settings_content\n    assert \"cpp.driverLinkerFlags:['-s']\" in settings_content\n\n\ndef test_options_extra():\n    client = TestClient()\n\n    profile = textwrap.dedent(f'''\n    [settings]\n    arch=x86_64\n    build_type=Release\n    compiler=gcc\n    compiler.version=13\n    compiler.libcxx=libstdc++\n    compiler.cppstd=17\n    os=Linux\n    [conf]\n    tools.build:compiler_executables ={{\"c\": \"{compiler_path}/gcc\", \"cpp\": \"{compiler_path}/g++\"}}\n    ''')\n\n    conanfile = textwrap.dedent('''\n    from conan import ConanFile\n    from conan.tools.qbs import QbsProfile\n    class Recipe(ConanFile):\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n        name = \"mylib\"\n        version = \"0.1\"\n\n        def generate(self):\n            profile = QbsProfile(self)\n            profile.extra_cflags=['-Dfoo', '-Dbar']\n            profile.extra_cxxflags=['-Dfoo', '-Dbaz']\n            profile.extra_defines=['FOO', 'QUX']\n            profile.extra_sharedlinkflags=['-s']\n            profile.extra_exelinkflags=['-Wl,-s']\n            profile.generate()\n    ''')\n\n    client.save({'profile': profile})\n    client.save({'conanfile.py': conanfile})\n    client.run('install . -pr:a=profile')\n\n    settings_path = os.path.join(client.current_folder, 'qbs_settings.txt')\n    assert os.path.exists(settings_path)\n    settings_content = load(settings_path)\n\n    assert \"cpp.cFlags:['-Dfoo', '-Dbar']\" in settings_content\n    assert \"cpp.cxxFlags:['-Dfoo', '-Dbaz']\" in settings_content\n    assert \"cpp.defines:['FOO', 'QUX']\" in settings_content\n    assert \"cpp.linkerFlags:['-s']\" in settings_content\n    assert \"cpp.driverLinkerFlags:['-s']\" in settings_content\n\n\ndef test_sysroot():\n    client = TestClient()\n\n    profile = textwrap.dedent(f'''\n    [settings]\n    arch=x86_64\n    build_type=Release\n    compiler=gcc\n    compiler.version=13\n    compiler.libcxx=libstdc++\n    compiler.cppstd=17\n    os=Linux\n    [conf]\n    tools.build:compiler_executables ={{\"c\": \"{compiler_path}/gcc\", \"cpp\": \"{compiler_path}/g++\"}}\n    tools.build:sysroot=\\\\opt\\\\usr\\\\local\n    ''')\n\n    conanfile = textwrap.dedent('''\n    from conan import ConanFile\n    class Recipe(ConanFile):\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n        name = \"mylib\"\n        version = \"0.1\"\n    ''')\n\n    client.save({'profile': profile})\n    client.save({'conanfile.py': conanfile})\n    client.run('install . -pr:a=profile -g QbsProfile')\n\n    settings_path = os.path.join(client.current_folder, 'qbs_settings.txt')\n    assert os.path.exists(settings_path)\n    settings_content = load(settings_path)\n\n    assert \"qbs.sysroot:/opt/usr/local\" in settings_content\n"
  },
  {
    "path": "test/functional/toolchains/scons/__init__.py",
    "content": ""
  },
  {
    "path": "test/functional/toolchains/scons/test_sconsdeps.py",
    "content": "import platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.skipif(platform.system() != \"Linux\", reason=\"SCons functional tests\"\n                                                         \"only for Linux\")\n@pytest.mark.tool(\"scons\")\ndef test_sconsdeps():\n    client = TestClient(path_with_spaces=False)\n\n    conanfile = textwrap.dedent(\"\"\"\\\n        import os\n\n        from conan import ConanFile\n        from conan.tools.files import copy\n\n\n        class helloConan(ConanFile):\n            name = \"hello\"\n            version = \"1.0\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n            exports_sources = \"src/*\"\n\n            # TODO: check what would be the correct layout and how to interact with\n            # SCons scripts\n            def layout(self):\n                self.folders.source = \"src\"\n\n            def build(self):\n                debug_opt = '--debug-build' if self.settings.build_type == 'Debug' else ''\n                self.run(f'scons -C {self.folders.source} {debug_opt}')\n\n            def package(self):\n                copy(self, pattern=\"*.h\", dst=os.path.join(self.package_folder, \"include\"), src=os.path.join(self.source_folder),)\n                copy(self, \"*.lib\", src=self.source_folder, dst=os.path.join(self.package_folder, \"lib\"), keep_path=False)\n                copy(self, \"*.a\", src=self.source_folder, dst=os.path.join(self.package_folder, \"lib\"), keep_path=False)\n\n            def package_info(self):\n                self.cpp_info.libs = [\"hello\"]\n\n        \"\"\")\n\n    hello_cpp = textwrap.dedent(\"\"\"\\\n        #include <iostream>\n        #include \"hello.h\"\n\n        void hello(){\n            #ifdef NDEBUG\n                std::cout << \"Hello World Release!\" <<std::endl;\n            #else\n                std::cout << \"Hello World Debug!\" <<std::endl;\n            #endif\n        }\n        \"\"\")\n\n    hello_h = textwrap.dedent(\"\"\"\\\n        #pragma once\n\n        #ifdef WIN32\n          #define HELLO_EXPORT __declspec(dllexport)\n        #else\n          #define HELLO_EXPORT\n        #endif\n\n        HELLO_EXPORT void hello();\n        \"\"\")\n\n    sconscript = textwrap.dedent(\"\"\"\\\n        import sys\n\n        AddOption('--debug-build', action='store_true', help='debug build')\n\n        env = Environment(TARGET_ARCH=\"x86_64\")\n\n        is_debug = GetOption('debug_build')\n        is_release = not is_debug\n\n        if not is_debug:\n            env.Append(CPPDEFINES=\"NDEBUG\")\n\n        if is_debug:\n            env.Append(CXXFLAGS = '-g -ggdb')\n        else:\n            env.Append(CXXFLAGS = '-O2')\n            env.Append(LINKFLAGS = '-O2')\n\n        env.Library(\"hello\", \"hello.cpp\")\n        \"\"\")\n\n    sconstruct = textwrap.dedent(\"\"\"\\\n        SConscript('SConscript', variant_dir='build', duplicate = False)\n        \"\"\")\n\n    t_sconscript = textwrap.dedent(\"\"\"\\\n        import sys\n\n        AddOption('--debug-build', action='store_true', help='debug build')\n\n        env = Environment(TARGET_ARCH=\"x86_64\")\n\n        is_debug = GetOption('debug_build')\n        is_release = not is_debug\n\n        if not is_debug:\n            env.Append(CPPDEFINES=\"NDEBUG\")\n\n        if is_debug:\n            env.Append(CXXFLAGS = '-g -ggdb')\n        else:\n            env.Append(CXXFLAGS = '-O2')\n            env.Append(LINKFLAGS = '-O2')\n\n        build_path_relative_to_sconstruct = Dir('.').path\n\n        conandeps = SConscript('./SConscript_conandeps')\n\n        flags = conandeps[\"conandeps\"]\n        env.MergeFlags(flags)\n\n        env.Program(\"main\", \"main.cpp\")\n        \"\"\")\n\n    t_sconstruct = textwrap.dedent(\"\"\"\\\n        SConscript('SConscript', variant_dir='build', duplicate = False)\n        \"\"\")\n    t_conanfile = textwrap.dedent(\"\"\"\\\n        import os\n\n        from conan import ConanFile\n\n        class helloTestConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"SConsDeps\"\n\n            def requirements(self):\n                self.requires(self.tested_reference_str)\n\n            def build(self):\n                debug_opt = '--debug-build' if self.settings.build_type == 'Debug' else ''\n                self.run(f'scons {debug_opt}')\n\n            # TODO: check how to setup layout and scons\n            def layout(self):\n                self.folders.source = \".\"\n                self.folders.generators = self.folders.source\n                self.cpp.build.bindirs = [\"build\"]\n\n            def test(self):\n                cmd = os.path.join(self.cpp.build.bindirs[0], \"main\")\n                self.run(cmd, env=\"conanrun\")\n        \"\"\")\n\n    t_main_cpp = textwrap.dedent(\"\"\"\\\n        #include \"hello.h\"\n\n        int main() {\n            hello();\n        }\n        \"\"\")\n\n    client.save({\"conanfile.py\": conanfile,\n                 \"src/hello.cpp\": hello_cpp,\n                 \"src/hello.h\": hello_h,\n                 \"src/SConscript\": sconscript,\n                 \"src/SConstruct\": sconstruct,\n                 \"test_package/SConscript\": t_sconscript,\n                 \"test_package/SConstruct\": t_sconstruct,\n                 \"test_package/conanfile.py\": t_conanfile,\n                 \"test_package/main.cpp\": t_main_cpp,\n                 })\n\n    client.run(\"create .\")\n    assert \"Hello World Release!\" in client.out\n"
  },
  {
    "path": "test/functional/toolchains/test_basic.py",
    "content": "import platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestBasic:\n\n    def test_basic(self):\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.cmake import CMakeToolchain\n            class Pkg(ConanFile):\n                def generate(self):\n                    tc = CMakeToolchain(self)\n                    tc.generate()\n                \"\"\")\n        client = TestClient()\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"install .\")\n\n        assert \"conanfile.py: Calling generate()\" in client.out\n        toolchain = client.load(\"conan_toolchain.cmake\")\n        assert \"Conan automatically generated toolchain file\" in toolchain\n\n    def test_declarative(self):\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n                generators = (\"CMakeToolchain\", \"CMakeDeps\", \"MesonToolchain\")\n            \"\"\")\n        client = TestClient()\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"install .\")\n\n        assert \"conanfile.py: Generator 'CMakeToolchain' calling 'generate()'\" in client.out\n        assert \"conanfile.py: Generator 'MesonToolchain' calling 'generate()'\" in client.out\n        assert \"conanfile.py: Generator 'CMakeDeps' calling 'generate()'\" in client.out\n        toolchain = client.load(\"conan_toolchain.cmake\")\n        assert \"Conan automatically generated toolchain file\" in toolchain\n        toolchain = client.load(\"conan_meson_native.ini\")\n        assert \"[project options]\" in toolchain\n\n    @pytest.mark.tool(\"visual_studio\")\n    @pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Only for windows\")\n    def test_declarative_msbuildtoolchain(self):\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n                generators = (\"MSBuildToolchain\", )\n            \"\"\")\n        client = TestClient()\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"install .\")\n\n        assert \"conanfile.py: Generator 'MSBuildToolchain' calling 'generate()'\" in client.out\n        toolchain = client.load(\"conantoolchain.props\")\n        assert \"<?xml version\" in toolchain\n\n    def test_error_missing_settings(self):\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                generators = \"MSBuildToolchain\"\n            \"\"\")\n        client = TestClient()\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"install .\", assert_error=True)\n        assert (\"Error in generator 'MSBuildToolchain': 'settings.build_type' \"\n                \"doesn't exist\") in client.out\n\n    def test_error_missing_settings_method(self):\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.microsoft import MSBuildToolchain\n            class Pkg(ConanFile):\n                def generate(self):\n                   tc = MSBuildToolchain(self)\n                   tc.generate()\n            \"\"\")\n        client = TestClient()\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"install .\", assert_error=True)\n        assert \"ERROR: conanfile.py: Error in generate() method, line 6\" in client.out\n\n    def test_declarative_new_helper(self):\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.cmake import CMake\n            class Pkg(ConanFile):\n                generators = \"CMakeToolchain\"\n                def build(self):\n                    cmake = CMake(self)\n                    cmake.configure()\n            \"\"\")\n        client = TestClient()\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"build .\", assert_error=True)  # No CMakeLists.txt\n        assert '-DCMAKE_TOOLCHAIN_FILE=\"conan_toolchain.cmake\"' in client.out\n        assert \"ERROR: conanfile.py: Error in build() method\" in client.out\n\n    @pytest.mark.tool(\"visual_studio\")\n    @pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Only for windows\")\n    def test_toolchain_windows(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.microsoft import MSBuildToolchain\n            class Pkg(ConanFile):\n                name = \"Pkg\"\n                version = \"0.1\"\n                settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n                generators = \"MSBuildDeps\"\n\n                def generate(self):\n                    tc = MSBuildToolchain(self)\n                    tc.generate()\n        \"\"\")\n\n        client.save({\"conanfile.py\": conanfile})\n\n        client.run('install . -s os=Windows -s compiler=msvc -s compiler.version=191'\n                   ' -s compiler.runtime=dynamic')\n\n        conan_toolchain_props = client.load(\"conantoolchain.props\")\n        assert \"<ConanPackageName>Pkg</ConanPackageName>\" in conan_toolchain_props\n        assert \"<ConanPackageVersion>0.1</ConanPackageVersion>\" in conan_toolchain_props\n"
  },
  {
    "path": "test/functional/toolchains/test_nmake_toolchain.py",
    "content": "import platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.sources import gen_function_cpp\nfrom test.functional.utils import check_exe_run\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.slow\n@pytest.mark.parametrize(\n    \"compiler, version, runtime, cppstd, build_type, defines, cflags, cxxflags, sharedlinkflags, exelinkflags\",\n    [\n        (\"msvc\", \"191\", \"dynamic\", \"14\", \"Release\", [], [], [], [], []),\n        (\"msvc\", \"191\", \"dynamic\", \"14\", \"Release\",\n         [\"TEST_DEFINITION1\", \"TEST_DEFINITION2=0\", \"TEST_DEFINITION3=\", \"TEST_DEFINITION4=TestPpdValue4\",\n          \"TEST_DEFINITION5=__declspec(dllexport)\", \"TEST_DEFINITION6=foo bar\"],\n         [\"/GL\"], [\"/GL\"], [\"/LTCG\"], [\"/LTCG\"]),\n        (\"msvc\", \"191\", \"static\", \"17\", \"Debug\", [], [], [], [], []),\n    ],\n)\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Only for windows\")\ndef test_toolchain_nmake(compiler, version, runtime, cppstd, build_type,\n                         defines, cflags, cxxflags, sharedlinkflags, exelinkflags):\n    client = TestClient(path_with_spaces=False)\n    settings = {\"compiler\": compiler,\n                \"compiler.version\": version,\n                \"compiler.cppstd\": cppstd,\n                \"compiler.runtime\": runtime,\n                \"build_type\": build_type,\n                \"arch\": \"x86_64\"}\n\n    serialize_array = lambda arr: \"[{}]\".format(\",\".join([f\"'{v}'\" for v in arr]))\n    conf = {\n        \"tools.build:defines\": serialize_array(defines) if defines else \"\",\n        \"tools.build:cflags\": serialize_array(cflags) if cflags else \"\",\n        \"tools.build:cxxflags\": serialize_array(cxxflags) if cxxflags else \"\",\n        \"tools.build:sharedlinkflags\": serialize_array(sharedlinkflags) if sharedlinkflags else \"\",\n        \"tools.build:exelinkflags\": serialize_array(exelinkflags) if exelinkflags else \"\",\n    }\n\n    # Build the profile according to the settings provided\n    settings = \" \".join('-s %s=\"%s\"' % (k, v) for k, v in settings.items() if v)\n\n    client.run(\"new cmake_lib -d name=dep -d version=1.0\")\n    conf = \" \".join(f'-c {k}=\"{v}\"' for k, v in conf.items() if v)\n    client.run(f'create . -tf=\\\"\\\" {settings} {conf}'\n               f' -c tools.cmake.cmaketoolchain:generator=\"Visual Studio 15\"')\n\n    # Rearrange defines to macro / value dict\n    conf_preprocessors = {}\n    for define in defines:\n        if \"=\" in define:\n            key, value = define.split(\"=\", 1)\n            # gen_function_cpp doesn't properly handle empty macros\n            if value:\n                conf_preprocessors[key] = value\n        else:\n            conf_preprocessors[define] = \"1\"\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            requires = \"dep/1.0\"\n            generators = \"NMakeToolchain\", \"NMakeDeps\"\n\n            def build(self):\n                self.run(f\"nmake /f makefile\")\n            \"\"\")\n    makefile = textwrap.dedent(\"\"\"\\\n        all: simple.exe\n\n        .cpp.obj:\n          $(CPP) $*.cpp\n\n        simple.exe: simple.obj\n          $(CPP) simple.obj\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile,\n                 \"makefile\": makefile,\n                 \"simple.cpp\": gen_function_cpp(name=\"main\", includes=[\"dep\"], calls=[\"dep\"],\n                                                preprocessor=conf_preprocessors.keys())},\n                clean_first=True)\n    client.run(f\"build . {settings} {conf}\")\n    client.run_command(\"simple.exe\")\n    assert \"dep/1.0\" in client.out\n    check_exe_run(client.out, \"main\", \"msvc\", version, build_type, \"x86_64\", cppstd,\n                  conf_preprocessors)\n\n\n@pytest.mark.slow\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows\")\n@pytest.mark.tool(\"cmake\", \"3.23\")\n# This test uses clang inside Visual Studio, not managed by mark.tool\n@pytest.mark.tool(\"visual_studio\")\ndef test_toolchain_nmake_clang():\n    cppstd = \"14\"\n    build_type = \"Debug\"\n    defines = [\"TEST_DEFINITION1\", \"TEST_DEFINITION2=0\", \"TEST_DEFINITION3=\",\n               \"TEST_DEFINITION4=TestPpdValue4\", \"TEST_DEFINITION5=__declspec(dllexport)\",\n               \"TEST_DEFINITION6=foo bar\"]\n    client = TestClient(path_with_spaces=False)\n    settings = {\"compiler\": \"clang\",\n                \"compiler.version\": \"20\",\n                \"compiler.cppstd\": \"14\",\n                \"compiler.runtime\": \"dynamic\",\n                \"build_type\": build_type,\n                \"compiler.runtime_version\": \"v144\",\n                \"arch\": \"x86_64\"}\n\n    conf = {\n        \"tools.build:defines\": \"[{}]\".format(\",\".join([f\"'{v}'\" for v in defines])),\n        \"tools.build:compiler_executables\": r'{\\\"c\\\": \\\"clang-cl\\\", \\\"cpp\\\": \\\"clang-cl\\\"}',\n        \"tools.cmake.cmaketoolchain:generator\": \"Visual Studio 17\",\n    }\n\n    # Build the profile according to the settings provided\n    settings = \" \".join('-s %s=\"%s\"' % (k, v) for k, v in settings.items() if v)\n\n    client.run(\"new cmake_lib -d name=dep -d version=1.0\")\n    conf = \" \".join(f'-c {k}=\"{v}\"' for k, v in conf.items() if v)\n    client.run(f'create . -tf=\\\"\\\" {settings} {conf}')\n\n    # Rearrange defines to macro / value dict\n    conf_preprocessors = {}\n    for define in defines:\n        if \"=\" in define:\n            key, value = define.split(\"=\", 1)\n            # gen_function_cpp doesn't properly handle empty macros\n            if value:\n                conf_preprocessors[key] = value\n        else:\n            conf_preprocessors[define] = \"1\"\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            requires = \"dep/1.0\"\n            generators = \"NMakeToolchain\", \"NMakeDeps\"\n\n            def build(self):\n                self.run(f\"nmake /f makefile\")\n            \"\"\")\n    makefile = textwrap.dedent(\"\"\"\\\n        all: simple.exe\n\n        simple.exe: simple.cpp\n          $(CPP) simple.cpp -o simple.exe\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile,\n                 \"makefile\": makefile,\n                 \"simple.cpp\": gen_function_cpp(name=\"main\", includes=[\"dep\"], calls=[\"dep\"],\n                                                preprocessor=conf_preprocessors.keys())},\n                clean_first=True)\n    client.run(f\"build . {settings} {conf}\")\n    client.run_command(\"simple.exe\")\n    assert \"dep/1.0\" in client.out\n    check_exe_run(client.out, \"main\", \"clang\", \"19.1\", build_type, \"x86_64\", cppstd,\n                  conf_preprocessors)\n"
  },
  {
    "path": "test/functional/toolchains/test_premake.py",
    "content": "import os\nimport platform\nimport textwrap\n\nfrom conan.test.assets.premake import gen_premake5\nfrom conan.test.utils.mocks import ConanFileMock\nfrom conan.tools.files.files import replace_in_file, rmdir\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\nfrom conan.test.assets.sources import gen_function_cpp\n\n\n@pytest.mark.slow\n@pytest.mark.skipif(platform.machine() not in (\"x86_64\", \"AMD64\"),\n                    reason=\"Premake Legacy generator only supports x86_64 machines\")\n@pytest.mark.tool(\"premake\")\ndef test_premake_legacy(matrix_client):\n    c = matrix_client\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.premake import Premake\n        from conan.tools.microsoft import MSBuild\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            requires = \"matrix/1.0\"\n            generators = \"PremakeDeps\", \"VCVars\"\n            def build(self):\n                p = Premake(self)\n                p.configure()\n                build_type = str(self.settings.build_type)\n                if self.settings.os == \"Windows\":\n                    msbuild = MSBuild(self)\n                    msbuild.build(\"HelloWorld.sln\")\n                else:\n                    self.run(f\"make config={build_type.lower()}_x86_64\")\n                p = os.path.join(self.build_folder, \"bin\", build_type, \"HelloWorld\")\n                self.run(f'\"{p}\"')\n        \"\"\")\n    premake = textwrap.dedent(\"\"\"\n        -- premake5.lua\n\n        include('conandeps.premake5.lua')\n\n        workspace \"HelloWorld\"\n           conan_setup()\n           configurations { \"Debug\", \"Release\" }\n           platforms { \"x86_64\" }\n\n        project \"HelloWorld\"\n           kind \"ConsoleApp\"\n           language \"C++\"\n           targetdir \"bin/%{cfg.buildcfg}\"\n\n           files { \"**.h\", \"**.cpp\" }\n\n           filter \"configurations:Debug\"\n              defines { \"DEBUG\" }\n              symbols \"On\"\n\n           filter \"configurations:Release\"\n              defines { \"NDEBUG\" }\n              optimize \"On\"\n\n           filter \"platforms:x86_64\"\n              architecture \"x86_64\"\n          \"\"\")\n    c.save({\"conanfile.py\": conanfile,\n            \"premake5.lua\": premake,\n            \"main.cpp\": gen_function_cpp(name=\"main\", includes=[\"matrix\"], calls=[\"matrix\"])})\n    c.run(\"build .\")\n    assert \"main: Release!\" in c.out\n    assert \"matrix/1.0: Hello World Release!\" in c.out\n    assert \"main _M_X64 defined\" in c.out or \"main __x86_64__ defined\" in c.out\n    c.run(\"build . -s build_type=Debug --build=missing\")\n    assert \"main: Debug!\" in c.out\n    assert \"matrix/1.0: Hello World Debug!\" in c.out\n\n\n@pytest.mark.slow\n@pytest.mark.tool(\"premake\")\ndef test_premake_new_generator():\n    c = TestClient()\n    c.run(\"new premake_lib -d name=lib -d version=0.1 -o lib\")\n    c.run(\"create lib\")\n    c.run(\"new premake_exe -d name=example -d requires=lib/0.1 -d version=1.0 -o exe\")\n    c.run(\"create exe\")\n\n    assert \"example/1.0 (test package): RUN: example\" in c.out\n    assert \"lib/0.1: Hello World Release!\" in c.out\n    assert \"example/1.0: Hello World Release!\" in c.out\n\n\n@pytest.mark.slow\n@pytest.mark.tool(\"premake\")\ndef test_premake_shared_lib():\n    c = TestClient()\n    c.run(\"new premake_lib -d name=lib -d version=0.1 -o lib\")\n    c.run(\"create lib -o '&:shared=True'\")\n    assert \"lib/0.1: package(): Packaged 1 '.so' file: liblib.so\" in c.out\n    assert \"lib/0.1: package(): Packaged 1 '.a' file: liblib.a\" not in c.out\n\n\n@pytest.mark.slow\n@pytest.mark.tool(\"premake\")\n@pytest.mark.parametrize(\"transitive_libs\", [True, False])\ndef test_premake_components(transitive_libs):\n    c = TestClient()\n    c.run(\"new premake_lib -d name=liba -d version=1.0 -o liba\")\n\n    libb_premake = gen_premake5(\n        workspace=\"Libb\",\n        includedirs=[\".\", \"libb1\", \"libb2\"],\n        projects=[\n            {\"name\": \"libb1\", \"files\": [\"libb1/*.h\", \"libb1/*.cpp\"], \"kind\": \"StaticLib\"},\n            {\"name\": \"libb2\", \"files\": [\"libb2/*.h\", \"libb2/*.cpp\"], \"kind\": \"StaticLib\",\n             \"links\": [\"libb1\"]}\n        ]\n    )\n    libb_conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import copy\n        from conan.tools.layout import basic_layout\n        from conan.tools.premake import Premake\n\n\n        class libbRecipe(ConanFile):\n            name = \"libb\"\n            version = \"1.0\"\n            package_type = \"static-library\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            exports_sources = \"premake5.lua\", \"libb1/*\", \"libb2/*\"\n            generators= \"PremakeDeps\", \"PremakeToolchain\"\n\n            def layout(self):\n                basic_layout(self)\n\n            def requirements(self):\n                self.requires(\"liba/1.0\", transitive_libs=%s)\n\n            def build(self):\n                premake = Premake(self)\n                premake.configure()\n                premake.build(workspace=\"Libb\")\n\n            def package(self):\n                for lib in (\"libb1\", \"libb2\"):\n                    copy(self, \"*.h\", os.path.join(self.source_folder, lib),\n                         os.path.join(self.package_folder, \"include\", lib))\n\n                for pattern in (\"*.lib\", \"*.a\", \"*.so*\", \"*.dylib\"):\n                    copy(self, pattern, os.path.join(self.build_folder, \"bin\"),\n                         os.path.join(self.package_folder, \"lib\"))\n                copy(self, \"*.dll\", os.path.join(self.build_folder, \"bin\"),\n                     os.path.join(self.package_folder, \"bin\"))\n\n            def package_info(self):\n                self.cpp_info.components[\"libb1\"].libs = [\"libb1\"]\n                self.cpp_info.components[\"libb1\"].requires = [\"liba::liba\"]\n\n                self.cpp_info.components[\"libb2\"].libs = [\"libb2\"]\n                self.cpp_info.components[\"libb2\"].requires = [\"libb1\"]\n    \"\"\")\n\n    libb_h = textwrap.dedent(\"\"\"\n        #pragma once\n        #include <string>\n        void libb%s();\n    \"\"\")\n\n    libb_cpp = textwrap.dedent(\"\"\"\n        #include <iostream>\n        #include \"libb%s.h\"\n        #include \"liba.h\"\n        void libb%s(){\n            liba();\n            std::cout << \"libb%s/1.0\" << std::endl;\n        }\n    \"\"\")\n\n    c.save(\n        {\n            \"libb/premake5.lua\": libb_premake,\n            \"libb/conanfile.py\": libb_conanfile % transitive_libs,\n            \"libb/libb1/libb1.h\": libb_h % \"1\",\n            \"libb/libb1/libb1.cpp\": libb_cpp % (\"1\", \"1\", \"1\"),\n            \"libb/libb2/libb2.h\": libb_h % \"2\",\n            \"libb/libb2/libb2.cpp\": libb_cpp % (\"2\", \"2\", \"2\"),\n        }\n    )\n    # Create a consumer application which depends on libb\n    c.run(\"new premake_exe -d name=consumer -d version=1.0 -o consumer -d requires=libb/1.0\")\n    # Adapt includes and usage of libb in the consumer application\n    replace_in_file(ConanFileMock(),\n                    os.path.join(c.current_folder, \"consumer\", \"src\", \"consumer.cpp\"),\n                    '#include \"libb.h\"', '#include \"libb1/libb1.h\"\\n#include \"libb2/libb2.h\"')\n    replace_in_file(ConanFileMock(),\n                    os.path.join(c.current_folder, \"consumer\", \"src\", \"consumer.cpp\"),\n                    'libb()', 'libb1();libb2()')\n\n    c.run(\"create liba\")\n    c.run(\"create libb\")\n    # If transitive_libs is false, consumer will not compile because it will not find liba\n    c.run(\"build consumer\", assert_error=not transitive_libs)\n\n\n@pytest.mark.slow\n@pytest.mark.tool(\"premake\")\ndef test_transitive_headers_not_public(transitive_libraries):\n    c = transitive_libraries\n\n    main = gen_function_cpp(name=\"main\", includes=[\"engine\"], calls=[\"engine\"])\n    premake5 = gen_premake5(\n        workspace=\"Consumer\",\n        projects=[\n            {\"name\": \"consumer\", \"files\": [\"src/main.cpp\"], \"kind\": \"ConsoleApp\"}\n        ],\n    )\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.layout import basic_layout\n        from conan.tools.premake import Premake\n\n        class ConsumerRecipe(ConanFile):\n            name = \"consumer\"\n            version = \"1.0\"\n            package_type = \"application\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            exports_sources = \"*\"\n            generators= \"PremakeDeps\", \"PremakeToolchain\"\n\n            def layout(self):\n                basic_layout(self)\n\n            def requirements(self):\n                self.requires(\"engine/1.0\")\n\n            def build(self):\n                premake = Premake(self)\n                premake.configure()\n                premake.build(workspace=\"Consumer\")\n    \"\"\")\n\n    c.save({\"src/main.cpp\": main,\n            \"premake5.lua\": premake5,\n            \"conanfile.py\": conanfile\n            })\n    # Test it builds successfully\n    c.run(\"build .\")\n\n    # Test including a transitive header: it should fail as engine does not require matrix with\n    # transitive_headers enabled\n    main = gen_function_cpp(name=\"main\", includes=[\"engine\", \"matrix\"], calls=[\"engine\"])\n    c.save({\"src/main.cpp\": main})\n    rmdir(ConanFileMock(), os.path.join(c.current_folder, \"build-release\"))\n    c.run(\"build .\", assert_error=True)\n    # Error should be about not finding matrix\n\n\n@pytest.mark.slow\n@pytest.mark.tool(\"premake\")\ndef test_premake_custom_configuration(transitive_libraries):\n    c = transitive_libraries\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.layout import basic_layout\n        from conan.tools.premake import Premake, PremakeDeps, PremakeToolchain\n\n        class ConsumerRecipe(ConanFile):\n            name = \"consumer\"\n            version = \"1.0\"\n            package_type = \"application\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            options = {\"sanitizer\": [True, False]}\n            default_options = {\"sanitizer\": False}\n            exports_sources = \"*\"\n\n            def layout(self):\n                basic_layout(self)\n\n            @property\n            def _premake_configuration(self):\n                return str(self.settings.build_type) + \"Sanitizer\" if self.options.sanitizer else \"\"\n\n            def generate(self):\n                deps = PremakeDeps(self)\n                deps.configuration = self._premake_configuration\n                deps.generate()\n                tc = PremakeToolchain(self)\n                tc.generate()\n\n            def build(self):\n                premake = Premake(self)\n                premake.configure()\n                # premake.build(workspace=\"Consumer\")\n                premake.build(workspace=\"Consumer\", configuration=self._premake_configuration)\n    \"\"\")\n\n    c.save({\"src/main.cpp\": gen_function_cpp(name=\"main\"),\n            \"premake5.lua\": gen_premake5(\n                workspace=\"Consumer\",\n                projects=[\n                    {\n                        \"name\": \"consumer\",\n                        \"files\": [\"src/main.cpp\"],\n                        \"kind\": \"ConsoleApp\",\n                    }\n                ],\n                configurations=[\"Debug\", \"Release\", \"DebugSanitizer\", \"ReleaseSanitizer\"],\n            ),\n            \"conanfile.py\": conanfile\n            })\n    # Test it builds successfully with the custom configuration\n    c.run(\"build . -o sanitizer=True\")\n"
  },
  {
    "path": "test/functional/tools/__init__.py",
    "content": ""
  },
  {
    "path": "test/functional/tools/scm/__init__.py",
    "content": ""
  },
  {
    "path": "test/functional/tools/scm/test_git.py",
    "content": "import os\nimport platform\nimport re\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.cmake import gen_cmakelists\nfrom conan.test.assets.sources import gen_function_cpp\nfrom conan.test.utils.scm import create_local_git_repo, git_add_changes_commit, git_create_bare_repo\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import rmdir, save_files, save\n\n\n@pytest.mark.tool(\"git\")\nclass TestGitBasicCapture:\n    \"\"\" base Git capture operations. They do not raise (unless errors)\n    \"\"\"\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.scm import Git\n\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n\n            def export(self):\n                git = Git(self, self.recipe_folder, excluded=[\"myfile.txt\", \"mynew.txt\", \"file with spaces.txt\"])\n                commit = git.get_commit()\n                repo_commit = git.get_commit(repository=True)\n                url = git.get_remote_url()\n                self.output.info(\"URL: {}\".format(url))\n                self.output.info(\"COMMIT: {}\".format(commit))\n                self.output.info(\"REPO_COMMIT: {}\".format(repo_commit))\n                in_remote = git.commit_in_remote(commit)\n                self.output.info(\"COMMIT IN REMOTE: {}\".format(in_remote))\n                self.output.info(\"DIRTY: {}\".format(git.is_dirty()))\n        \"\"\")\n\n    def test_capture_commit_local(self):\n        \"\"\"\n        A local repo, without remote, will have commit, but no URL\n        \"\"\"\n        c = TestClient()\n        c.save({\"conanfile.py\": self.conanfile})\n        commit = c.init_git_repo()\n        c.run(\"export .\")\n        assert \"pkg/0.1: COMMIT: {}\".format(commit) in c.out\n        assert \"pkg/0.1: URL: None\" in c.out\n        assert \"pkg/0.1: COMMIT IN REMOTE: False\" in c.out\n        assert \"pkg/0.1: DIRTY: False\" in c.out\n\n    def test_capture_remote_url(self):\n        \"\"\"\n        a cloned repo, will have a default \"origin\" remote and will manage to get URL\n        \"\"\"\n        folder = temp_folder()\n        url, commit = create_local_git_repo(files={\"conanfile.py\": self.conanfile}, folder=folder)\n\n        c = TestClient()\n        c.run_command('git clone \"{}\" myclone'.format(folder))\n        with c.chdir(\"myclone\"):\n            c.run(\"export .\")\n            assert \"pkg/0.1: COMMIT: {}\".format(commit) in c.out\n            assert \"pkg/0.1: REPO_COMMIT: {}\".format(commit) in c.out\n            assert \"pkg/0.1: URL: {}\".format(url) in c.out\n            assert \"pkg/0.1: COMMIT IN REMOTE: True\" in c.out\n            assert \"pkg/0.1: DIRTY: False\" in c.out\n\n    def test_capture_remote_pushed_commit(self):\n        \"\"\"\n        a cloned repo, after doing some new commit, no longer commit in remote, until push\n        \"\"\"\n        url = git_create_bare_repo()\n\n        c = TestClient()\n        c.run_command('git clone \"{}\" myclone'.format(url))\n        with c.chdir(\"myclone\"):\n            c.save({\"conanfile.py\": self.conanfile + \"\\n# some coment!\"})\n            new_commit = git_add_changes_commit(c.current_folder)\n\n            c.run(\"export .\")\n            assert \"pkg/0.1: COMMIT: {}\".format(new_commit) in c.out\n            assert \"pkg/0.1: URL: {}\".format(url) in c.out\n            assert \"pkg/0.1: COMMIT IN REMOTE: False\" in c.out\n            assert \"pkg/0.1: DIRTY: False\" in c.out\n            c.run_command(\"git push\")\n            c.run(\"export .\")\n            assert \"pkg/0.1: COMMIT: {}\".format(new_commit) in c.out\n            assert \"pkg/0.1: URL: {}\".format(url) in c.out\n            assert \"pkg/0.1: COMMIT IN REMOTE: True\" in c.out\n            assert \"pkg/0.1: DIRTY: False\" in c.out\n\n    def test_capture_commit_local_subfolder(self):\n        \"\"\"\n        A local repo, without remote, will have commit, but no URL, and sibling folders\n        can be dirty, no prob\n        \"\"\"\n        c = TestClient()\n        c.save({\"subfolder/conanfile.py\": self.conanfile,\n                \"other/myfile.txt\": \"content\"})\n        commit = c.init_git_repo()\n        c.save({\"other/myfile.txt\": \"change content\"})\n        c.run(\"export subfolder\")\n        assert \"pkg/0.1: COMMIT: {}\".format(commit) in c.out\n        assert \"pkg/0.1: REPO_COMMIT: {}\".format(commit) in c.out\n        assert \"pkg/0.1: URL: None\" in c.out\n        assert \"pkg/0.1: COMMIT IN REMOTE: False\" in c.out\n        assert \"pkg/0.1: DIRTY: False\" in c.out\n        commit2 = git_add_changes_commit(c.current_folder, msg=\"fix\")\n        c.run(\"export subfolder\")\n        assert \"pkg/0.1: COMMIT: {}\".format(commit) in c.out\n        assert \"pkg/0.1: REPO_COMMIT: {}\".format(commit2) in c.out\n        assert \"pkg/0.1: URL: None\" in c.out\n        assert \"pkg/0.1: COMMIT IN REMOTE: False\" in c.out\n        assert \"pkg/0.1: DIRTY: False\" in c.out\n\n    def test_git_excluded(self):\n        \"\"\"\n        A local repo, without remote, will have commit, but no URL\n        \"\"\"\n        c = TestClient()\n        c.save({\"conanfile.py\": self.conanfile,\n                \"myfile.txt\": \"\"})\n        c.init_git_repo()\n        c.run(\"export . -vvv\")\n        assert \"pkg/0.1: DIRTY: False\" in c.out\n        c.save({\"myfile.txt\": \"changed\",\n                \"mynew.txt\": \"new\",\n                \"file with spaces.txt\": \"hello\"})\n        c.run(\"export .\")\n        assert \"pkg/0.1: DIRTY: False\" in c.out\n        c.save({\"other.txt\": \"new\"})\n        c.run(\"export .\")\n        assert \"pkg/0.1: DIRTY: True\" in c.out\n\n        conf_excluded = f'core.scm:excluded+=[\"other.txt\"]'\n        save(c.paths.global_conf_path, conf_excluded)\n        c.run(\"export .\")\n        assert \"pkg/0.1: DIRTY: False\" in c.out\n\n\n@pytest.mark.tool(\"git\")\nclass TestGitCaptureSCM:\n    \"\"\" test the get_url_and_commit() high level method intended for SCM capturing\n    into conandata.yaml\n    \"\"\"\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.scm import Git\n\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n\n            def export(self):\n                git = Git(self, self.recipe_folder)\n                scm_url, scm_commit = git.get_url_and_commit()\n                self.output.info(\"SCM URL: {}\".format(scm_url))\n                self.output.info(\"SCM COMMIT: {}\".format(scm_commit))\n        \"\"\")\n\n    def test_capture_commit_local(self):\n        \"\"\"\n        A local repo, without remote, will provide its own URL to the export(),\n        and if it has local changes, it will be marked as dirty, and raise an error\n        \"\"\"\n        c = TestClient()\n        c.save({\"conanfile.py\": self.conanfile})\n        commit = c.init_git_repo()\n        c.run(\"export .\")\n        assert \"This revision will not be buildable in other computer\" in c.out\n        assert \"pkg/0.1: SCM COMMIT: {}\".format(commit) in c.out\n        assert \"pkg/0.1: SCM URL: {}\".format(c.current_folder.replace(\"\\\\\", \"/\")) in c.out\n\n        c.save({\"conanfile.py\": self.conanfile + \"\\n# something....\"})\n        c.run(\"export .\", assert_error=True)\n        assert \"Repo is dirty, cannot capture url and commit\" in c.out\n\n    def test_capture_commit_local_repository(self):\n        \"\"\"\n        same as above, but with ``get_url_and_commit(repository=True)``\n        \"\"\"\n        c = TestClient()\n        c.save({\"pkg/conanfile.py\": self.conanfile.replace(\"get_url_and_commit()\",\n                                                           \"get_url_and_commit(repository=True)\"),\n                \"somefile.txt\": \"\"})\n        commit = c.init_git_repo()\n        c.run(\"export pkg\")\n        assert \"This revision will not be buildable in other computer\" in c.out\n        assert \"pkg/0.1: SCM COMMIT: {}\".format(commit) in c.out\n        assert \"pkg/0.1: SCM URL: {}\".format(c.current_folder.replace(\"\\\\\", \"/\")) in c.out\n\n        c.save({\"somefile.txt\": \"something\"})\n        c.run(\"export pkg\", assert_error=True)\n        assert \"Repo is dirty, cannot capture url and commit\" in c.out\n\n    def test_capture_remote_url(self):\n        \"\"\"\n        a cloned repo that is expored, will report the URL of the remote\n        \"\"\"\n        folder = temp_folder()\n        url, commit = create_local_git_repo(files={\"conanfile.py\": self.conanfile}, folder=folder)\n\n        c = TestClient()\n        c.run_command('git clone \"{}\" myclone'.format(folder))\n        with c.chdir(\"myclone\"):\n            c.run(\"export .\")\n            assert \"pkg/0.1: SCM COMMIT: {}\".format(commit) in c.out\n            assert \"pkg/0.1: SCM URL: {}\".format(url) in c.out\n\n    def test_capture_remote_pushed_commit(self):\n        \"\"\"\n        a cloned repo, after doing some new commit, no longer commit in remote, until push\n        \"\"\"\n        url = git_create_bare_repo()\n\n        c = TestClient()\n        c.run_command('git clone \"{}\" myclone'.format(url))\n        with c.chdir(\"myclone\"):\n            c.save({\"conanfile.py\": self.conanfile + \"\\n# some coment!\"})\n            new_commit = git_add_changes_commit(c.current_folder)\n\n            c.run(\"export .\")\n            assert \"This revision will not be buildable in other computer\" in c.out\n            assert \"pkg/0.1: SCM COMMIT: {}\".format(new_commit) in c.out\n            # NOTE: commit not pushed yet, so locally is the current folder\n            assert \"pkg/0.1: SCM URL: {}\".format(c.current_folder.replace(\"\\\\\", \"/\")) in c.out\n            c.run_command(\"git push\")\n            c.run(\"export .\")\n            assert \"pkg/0.1: SCM COMMIT: {}\".format(new_commit) in c.out\n            assert \"pkg/0.1: SCM URL: {}\".format(url) in c.out\n\n    def test_capture_commit_modified_config(self):\n        \"\"\"\n        A clean repo with the status.branch git config set to on\n        Expected to not raise an error an return the commit and url\n        \"\"\"\n        folder = temp_folder()\n        url, commit = create_local_git_repo(files={\"conanfile.py\": self.conanfile}, folder=folder)\n        c = TestClient()\n        with c.chdir(folder):\n            c.run_command(\"git config --local status.branch true\")\n            c.run(\"export .\")\n            assert \"pkg/0.1: SCM COMMIT: {}\".format(commit) in c.out\n            assert \"pkg/0.1: SCM URL: {}\".format(url) in c.out\n\n    def test_capture_commit_modified_config_untracked(self):\n        \"\"\"\n        A dirty repo with the showUntrackedFiles git config set to off.\n        Expected to throw an exception\n        \"\"\"\n        folder = temp_folder()\n        create_local_git_repo(files={\"conanfile.py\": self.conanfile}, folder=folder)\n        c = TestClient()\n        with c.chdir(folder):\n            c.save(files={\"some_header.h\": \"now the repo is dirty\"})\n            c.run_command(\"git config --local status.showUntrackedFiles no\")\n            c.run(\"export .\", assert_error=True)\n            assert \"Repo is dirty, cannot capture url and commit\" in c.out\n\n\n@pytest.mark.tool(\"git\")\nclass TestGitBasicClone:\n    \"\"\" base Git cloning operations\n    \"\"\"\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.scm import Git\n        from conan.tools.files import load\n\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n\n            def layout(self):\n                self.folders.source = \"source\"\n\n            def source(self):\n                git = Git(self)\n                git.clone(url=\"{url}\", target=\".\")\n                git.checkout(commit=\"{commit}\")\n                self.output.info(\"MYCMAKE: {{}}\".format(load(self, \"CMakeLists.txt\")))\n                self.output.info(\"MYFILE: {{}}\".format(load(self, \"src/myfile.h\")))\n        \"\"\")\n\n    def test_clone_checkout(self):\n        folder = os.path.join(temp_folder(), \"myrepo\")\n        url, commit = create_local_git_repo(files={\"src/myfile.h\": \"myheader!\",\n                                                   \"CMakeLists.txt\": \"mycmake\"}, folder=folder)\n        # This second commit will NOT be used, as I will use the above commit in the conanfile\n        save_files(path=folder, files={\"src/myfile.h\": \"my2header2!\"})\n        git_add_changes_commit(folder=folder)\n\n        c = TestClient()\n        c.save({\"conanfile.py\": self.conanfile.format(url=url, commit=commit)})\n        c.run(\"create . -v\")\n        # Clone is not printed, it might contain tokens\n        assert 'pkg/0.1: RUN: git clone \"<hidden>\"  \".\"' in c.out\n        assert \"pkg/0.1: RUN: git checkout\" in c.out\n        assert \"pkg/0.1: MYCMAKE: mycmake\" in c.out\n        assert \"pkg/0.1: MYFILE: myheader!\" in c.out\n\n        # It also works in local flow\n        c.run(\"source .\")\n        assert \"conanfile.py (pkg/0.1): MYCMAKE: mycmake\" in c.out\n        assert \"conanfile.py (pkg/0.1): MYFILE: myheader!\" in c.out\n        assert c.load(\"source/src/myfile.h\") == \"myheader!\"\n        assert c.load(\"source/CMakeLists.txt\") == \"mycmake\"\n\n    def test_clone_url_not_hidden(self):\n        conanfile = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.scm import Git\n            from conan.tools.files import load\n\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n\n                def layout(self):\n                    self.folders.source = \"source\"\n\n                def source(self):\n                    git = Git(self)\n                    git.clone(url=\"{url}\", target=\".\", hide_url=False)\n            \"\"\")\n        folder = os.path.join(temp_folder(), \"myrepo\")\n        url, _ = create_local_git_repo(files={\"CMakeLists.txt\": \"mycmake\"}, folder=folder)\n\n        c = TestClient(light=True)\n        c.save({\"conanfile.py\": conanfile.format(url=url)})\n        c.run(\"create . -v\")\n        # Clone URL is explicitly printed\n        assert f'pkg/0.1: RUN: git clone \"{url}\"  \".\"' in c.out\n\n        # It also works in local flow\n        c.run(\"source .\")\n        assert f'conanfile.py (pkg/0.1): RUN: git clone \"{url}\"  \".\"' in c.out\n\n    def test_clone_target(self):\n        # Clone to a different target folder\n        # https://github.com/conan-io/conan/issues/14058\n        conanfile = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.scm import Git\n            from conan.tools.files import load\n\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n\n                def layout(self):\n                    self.folders.source = \"source\"\n\n                def source(self):\n                    # Alternative, first defining the folder\n                    # git = Git(self, \"target\")\n                    # git.clone(url=\"{url}\", target=\".\")\n                    # git.checkout(commit=\"{commit}\")\n\n                    git = Git(self)\n                    git.clone(url=\"{url}\", target=\"tar get\") # git clone url target\n                    git.folder = \"tar get\"                   # cd target\n                    git.checkout(commit=\"{commit}\")         # git checkout commit\n\n                    self.output.info(\"MYCMAKE: {{}}\".format(load(self, \"tar get/CMakeLists.txt\")))\n                    self.output.info(\"MYFILE: {{}}\".format(load(self, \"tar get/src/myfile.h\")))\n                \"\"\")\n        folder = os.path.join(temp_folder(), \"myrepo\")\n        url, commit = create_local_git_repo(files={\"src/myfile.h\": \"myheader!\",\n                                                   \"CMakeLists.txt\": \"mycmake\"}, folder=folder)\n        # This second commit will NOT be used, as I will use the above commit in the conanfile\n        save_files(path=folder, files={\"src/myfile.h\": \"my2header2!\"})\n        git_add_changes_commit(folder=folder)\n\n        c = TestClient()\n        c.save({\"conanfile.py\": conanfile.format(url=url, commit=commit)})\n        c.run(\"create .\")\n        assert \"pkg/0.1: MYCMAKE: mycmake\" in c.out\n        assert \"pkg/0.1: MYFILE: myheader!\" in c.out\n\n    @pytest.mark.tool(\"msys2\")\n    def test_clone_msys2_win_bash(self):\n        # To avoid regression in https://github.com/conan-io/conan/issues/14754\n        folder = os.path.join(temp_folder(), \"myrepo\")\n        url, commit = create_local_git_repo(files={\"src/myfile.h\": \"myheader!\",\n                                                   \"CMakeLists.txt\": \"mycmake\"}, folder=folder)\n\n        c = TestClient()\n        conanfile_win_bash = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.scm import Git\n            from conan.tools.files import load\n\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                win_bash = True\n\n                def layout(self):\n                    self.folders.source = \"source\"\n\n                def source(self):\n                    git = Git(self)\n                    git.clone(url=\"{url}\", target=\".\")\n                    git.checkout(commit=\"{commit}\")\n                    self.output.info(\"MYCMAKE: {{}}\".format(load(self, \"CMakeLists.txt\")))\n                    self.output.info(\"MYFILE: {{}}\".format(load(self, \"src/myfile.h\")))\n            \"\"\")\n        c.save({\"conanfile.py\": conanfile_win_bash.format(url=url, commit=commit)})\n        conf = \"-c tools.microsoft.bash:subsystem=msys2 -c tools.microsoft.bash:path=bash.exe\"\n        c.run(f\"create . {conf}\")\n        assert \"pkg/0.1: MYCMAKE: mycmake\" in c.out\n        assert \"pkg/0.1: MYFILE: myheader!\" in c.out\n\n        # It also works in local flow, not running in msys2 at all\n        c.run(f\"source .\")\n        assert \"conanfile.py (pkg/0.1): MYCMAKE: mycmake\" in c.out\n        assert \"conanfile.py (pkg/0.1): MYFILE: myheader!\" in c.out\n        assert c.load(\"source/src/myfile.h\") == \"myheader!\"\n        assert c.load(\"source/CMakeLists.txt\") == \"mycmake\"\n\n\n@pytest.mark.tool(\"git\")\nclass TestGitShallowClone:\n    \"\"\" base Git cloning operations\n    \"\"\"\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.scm import Git\n        from conan.tools.files import load\n\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n\n            def layout(self):\n                self.folders.source = \"source\"\n\n            def source(self):\n                git = Git(self)\n                git.fetch_commit(url=\"{url}\", commit=\"{commit}\")\n                self.output.info(\"MYCMAKE: {{}}\".format(load(self, \"CMakeLists.txt\")))\n                self.output.info(\"MYFILE: {{}}\".format(load(self, \"src/myfile.h\")))\n        \"\"\")\n\n    @pytest.mark.skipif(platform.system() == \"Linux\", reason=\"Git version in Linux not support it\")\n    def test_clone_checkout(self):\n        folder = os.path.join(temp_folder(), \"myrepo\")\n        url, commit = create_local_git_repo(files={\"src/myfile.h\": \"myheader!\",\n                                                   \"CMakeLists.txt\": \"mycmake\"}, folder=folder)\n        # This second commit will NOT be used, as I will use the above commit in the conanfile\n        save_files(path=folder, files={\"src/myfile.h\": \"my2header2!\"})\n        git_add_changes_commit(folder=folder)\n\n        c = TestClient()\n        c.save({\"conanfile.py\": self.conanfile.format(url=url, commit=commit)})\n        c.run(\"create . -v\")\n        assert 'pkg/0.1: RUN: git remote add origin \"<hidden>\"' in c.out\n        assert \"pkg/0.1: MYCMAKE: mycmake\" in c.out\n        assert \"pkg/0.1: MYFILE: myheader!\" in c.out\n\n        # It also works in local flow\n        c.run(\"source .\")\n        assert \"conanfile.py (pkg/0.1): MYCMAKE: mycmake\" in c.out\n        assert \"conanfile.py (pkg/0.1): MYFILE: myheader!\" in c.out\n        assert c.load(\"source/src/myfile.h\") == \"myheader!\"\n        assert c.load(\"source/CMakeLists.txt\") == \"mycmake\"\n\n    def test_clone_url_not_hidden(self):\n        conanfile = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.scm import Git\n            from conan.tools.files import load\n\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n\n                def layout(self):\n                    self.folders.source = \"source\"\n\n                def source(self):\n                    git = Git(self)\n                    git.fetch_commit(url=\"{url}\", commit=\"{commit}\", hide_url=False)\n            \"\"\")\n        folder = os.path.join(temp_folder(), \"myrepo\")\n        url, commit = create_local_git_repo(files={\"CMakeLists.txt\": \"mycmake\"}, folder=folder)\n\n        c = TestClient(light=True)\n        c.save({\"conanfile.py\": conanfile.format(url=url, commit=commit)})\n        c.run(\"create . -v\")\n        # Clone URL is explicitly printed\n        assert f'pkg/0.1: RUN: git remote add origin \"{url}\"' in c.out\n\n        # It also works in local flow\n        c.run(\"source .\")\n        assert f'conanfile.py (pkg/0.1): RUN: git remote add origin \"{url}\"' in c.out\n\n    @pytest.mark.skipif(platform.system() == \"Linux\", reason=\"Git version in Linux not support it\")\n    def test_clone_to_subfolder(self):\n        conanfile = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.scm import Git\n            from conan.tools.files import load\n\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n\n                def layout(self):\n                    self.folders.source = \"source\"\n\n                def source(self):\n                    git = Git(self, folder=\"folder\")\n                    git.fetch_commit(url=\"{url}\", commit=\"{commit}\")\n                    self.output.info(\"MYCMAKE: {{}}\".format(load(self, \"folder/CMakeLists.txt\")))\n                    self.output.info(\"MYFILE: {{}}\".format(load(self, \"folder/src/myfile.h\")))\n            \"\"\")\n        folder = os.path.join(temp_folder(), \"myrepo\")\n        url, commit = create_local_git_repo(files={\"src/myfile.h\": \"myheader!\",\n                                                   \"CMakeLists.txt\": \"mycmake\"}, folder=folder)\n        # This second commit will NOT be used, as I will use the above commit in the conanfile\n        save_files(path=folder, files={\"src/myfile.h\": \"my2header2!\"})\n        git_add_changes_commit(folder=folder)\n\n        c = TestClient()\n        c.save({\"conanfile.py\": conanfile.format(url=url, commit=commit)})\n        c.run(\"create . -v\")\n        assert \"pkg/0.1: MYCMAKE: mycmake\" in c.out\n        assert \"pkg/0.1: MYFILE: myheader!\" in c.out\n\n        # It also works in local flow\n        c.run(\"source .\")\n        assert \"conanfile.py (pkg/0.1): MYCMAKE: mycmake\" in c.out\n        assert \"conanfile.py (pkg/0.1): MYFILE: myheader!\" in c.out\n        assert c.load(\"source/folder/CMakeLists.txt\") == \"mycmake\"\n        assert c.load(\"source/folder/src/myfile.h\") == \"myheader!\"\n\nclass TestGitCloneWithArgs:\n    \"\"\" Git cloning passing additional arguments\n    \"\"\"\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.scm import Git\n        from conan.tools.files import load\n\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n\n            def layout(self):\n                self.folders.source = \"source\"\n\n            def source(self):\n                git = Git(self)\n                git.clone(url=\"{url}\", target=\".\", args={args})\n                self.output.info(\"MYCMAKE: {{}}\".format(load(self, \"CMakeLists.txt\")))\n                self.output.info(\"MYFILE: {{}}\".format(load(self, \"src/myfile.h\")))\n        \"\"\")\n\n    def test_clone_specify_branch_or_tag(self):\n        folder = os.path.join(temp_folder(), \"myrepo\")\n        url, commit = create_local_git_repo(files={\"src/myfile.h\": \"myheader!\",\n                                                   \"CMakeLists.txt\": \"mycmake\"}, folder=folder,\n                                            commits=3, branch=\"main\", tags=[\"v1.2.3\"])\n\n        c = TestClient()\n        git_args = ['--branch', 'main']\n        c.save({\"conanfile.py\": self.conanfile.format(url=url, commit=commit, args=str(git_args))})\n        c.run(\"create .\")\n        assert \"pkg/0.1: MYCMAKE: mycmake\" in c.out\n        assert \"pkg/0.1: MYFILE: myheader!\" in c.out\n\n        git_args = ['--branch', 'v1.2.3']\n        c.save({\"conanfile.py\": self.conanfile.format(url=url, commit=commit, args=str(git_args))})\n        c.run(\"create .\")\n        assert \"pkg/0.1: MYCMAKE: mycmake\" in c.out\n        assert \"pkg/0.1: MYFILE: myheader!\" in c.out\n\n    def test_clone_invalid_branch_argument(self):\n        folder = os.path.join(temp_folder(), \"myrepo\")\n        url, commit = create_local_git_repo(files={\"src/myfile.h\": \"myheader!\",\n                                                   \"CMakeLists.txt\": \"mycmake\"}, folder=folder,\n                                            commits=3, branch=\"main\", tags=[\"v1.2.3\"])\n        c = TestClient()\n        git_args = ['--branch', 'foobar']\n        c.save({\"conanfile.py\": self.conanfile.format(url=url, commit=commit, args=str(git_args))})\n        c.run(\"create .\", assert_error=True)\n        assert \"Remote branch foobar not found\" in c.out\n\n\n@pytest.mark.tool(\"git\")\nclass TestGitBasicSCMFlow:\n    \"\"\" Build the full new SCM approach:\n    - export() captures the URL and commit with get_url_and_commit(\n    - export() stores it in conandata.yml\n    - source() recovers the info from conandata.yml and clones it\n    \"\"\"\n    conanfile_full = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.scm import Git\n        from conan.tools.files import load, update_conandata\n\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n\n            def export(self):\n                git = Git(self, self.recipe_folder)\n                scm_url, scm_commit = git.get_url_and_commit()\n                update_conandata(self, {\"sources\": {\"commit\": scm_commit, \"url\": scm_url}})\n\n            def layout(self):\n                self.folders.source = \".\"\n\n            def source(self):\n                git = Git(self)\n                sources = self.conan_data[\"sources\"]\n                git.clone(url=sources[\"url\"], target=\".\")\n                git.checkout(commit=sources[\"commit\"])\n                self.output.info(\"MYCMAKE: {}\".format(load(self, \"CMakeLists.txt\")))\n                self.output.info(\"MYFILE: {}\".format(load(self, \"src/myfile.h\")))\n\n            def build(self):\n                cmake = os.path.join(self.source_folder, \"CMakeLists.txt\")\n                file_h = os.path.join(self.source_folder, \"src/myfile.h\")\n                self.output.info(\"MYCMAKE-BUILD: {}\".format(load(self, cmake)))\n                self.output.info(\"MYFILE-BUILD: {}\".format(load(self, file_h)))\n        \"\"\")\n    conanfile_scm = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.scm import Git\n        from conan.tools.files import load, trim_conandata\n\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n\n            def export(self):\n                Git(self).coordinates_to_conandata()\n                trim_conandata(self)  # to test it does not affect\n\n            def layout(self):\n                self.folders.source = \".\"\n\n            def source(self):\n                Git(self).checkout_from_conandata_coordinates()\n                self.output.info(\"MYCMAKE: {}\".format(load(self, \"CMakeLists.txt\")))\n                self.output.info(\"MYFILE: {}\".format(load(self, \"src/myfile.h\")))\n\n            def build(self):\n                cmake = os.path.join(self.source_folder, \"CMakeLists.txt\")\n                file_h = os.path.join(self.source_folder, \"src/myfile.h\")\n                self.output.info(\"MYCMAKE-BUILD: {}\".format(load(self, cmake)))\n                self.output.info(\"MYFILE-BUILD: {}\".format(load(self, file_h)))\n        \"\"\")\n\n    @pytest.mark.parametrize(\"conanfile_scm\", [False, True])\n    def test_full_scm(self, conanfile_scm):\n        conanfile = self.conanfile_scm if conanfile_scm else self.conanfile_full\n        folder = os.path.join(temp_folder(), \"myrepo\")\n        url, commit = create_local_git_repo(files={\"conanfile.py\": conanfile,\n                                                   \"src/myfile.h\": \"myheader!\",\n                                                   \"CMakeLists.txt\": \"mycmake\"}, folder=folder)\n\n        c = TestClient(default_server_user=True)\n        c.run_command('git clone \"file://{}\" .'.format(url))\n        c.run(\"create .\")\n        assert \"pkg/0.1: MYCMAKE: mycmake\" in c.out\n        assert \"pkg/0.1: MYFILE: myheader!\" in c.out\n        c.run(\"upload * -c -r=default\")\n\n        # Do a change and commit, this commit will not be used by package\n        save_files(path=folder, files={\"src/myfile.h\": \"my2header2!\"})\n        git_add_changes_commit(folder=folder)\n\n        # use another fresh client\n        c2 = TestClient(servers=c.servers)\n        c2.run(\"install --requires=pkg/0.1@ --build=pkg*\")\n        assert \"pkg/0.1: MYCMAKE: mycmake\" in c2.out\n        assert \"pkg/0.1: MYFILE: myheader!\" in c2.out\n\n        # local flow\n        c.run(\"install .\")\n        c.run(\"build .\")\n        assert \"conanfile.py (pkg/0.1): MYCMAKE-BUILD: mycmake\" in c.out\n        assert \"conanfile.py (pkg/0.1): MYFILE-BUILD: myheader!\" in c.out\n\n    @pytest.mark.parametrize(\"conanfile_scm\", [False, True])\n    def test_branch_flow(self, conanfile_scm):\n        \"\"\" Testing that when a user creates a branch, and pushes a commit,\n        the package can still be built from sources, and get_url_and_commit() captures the\n        remote URL and not the local\n        \"\"\"\n        conanfile = self.conanfile_scm if conanfile_scm else self.conanfile_full\n        url = git_create_bare_repo()\n        c = TestClient(default_server_user=True)\n        c.run_command('git clone \"file://{}\" .'.format(url))\n        c.save({\"conanfile.py\": conanfile,\n                \"src/myfile.h\": \"myheader!\",\n                \"CMakeLists.txt\": \"mycmake\"})\n        c.run_command(\"git checkout -b mybranch\")\n        git_add_changes_commit(folder=c.current_folder)\n        c.run_command(\"git push --set-upstream origin mybranch\")\n        c.run(\"create .\")\n        assert \"pkg/0.1: MYCMAKE: mycmake\" in c.out\n        assert \"pkg/0.1: MYFILE: myheader!\" in c.out\n        c.run(\"upload * -c -r=default\")\n        rmdir(c.current_folder)  # Remove current folder to make sure things are not used from here\n\n        # use another fresh client\n        c2 = TestClient(servers=c.servers)\n        c2.run(\"install --requires=pkg/0.1@ --build=pkg*\")\n        assert \"pkg/0.1: MYCMAKE: mycmake\" in c2.out\n        assert \"pkg/0.1: MYFILE: myheader!\" in c2.out\n\n    def test_fetch_commit(self):\n        \"\"\" Testing fetch commit\n        \"\"\"\n        url = git_create_bare_repo()\n        c = TestClient(default_server_user=True)\n        c.run_command('git clone \"file://{}\" .'.format(url))\n        c.save({\"conanfile.py\": self.conanfile_scm,\n                \"src/myfile.h\": \"myheader!\",\n                \"CMakeLists.txt\": \"mycmake\"})\n        c.run_command(\"git checkout -b mybranch\")\n        git_add_changes_commit(folder=c.current_folder)\n        c.run_command(\"git push --set-upstream origin mybranch\")\n        c.run(\"create .\")\n        assert \"pkg/0.1: MYCMAKE: mycmake\" in c.out\n        assert \"pkg/0.1: MYFILE: myheader!\" in c.out\n        c.run(\"upload * -c -r=default\")\n        # Create an orphan commit by removing the branch\n        c.run_command(\"git push origin --delete mybranch\")\n        rmdir(c.current_folder)  # Remove current folder to make sure things are not used from here\n\n        # use another fresh client\n        c2 = TestClient(servers=c.servers)\n        c2.run(\"install --requires=pkg/0.1@ --build=pkg*\")\n        assert \"pkg/0.1: MYCMAKE: mycmake\" in c2.out\n        assert \"pkg/0.1: MYFILE: myheader!\" in c2.out\n\n    def test_grafted_commit(self):\n        # https://github.com/conan-io/conan/issues/18295\n        folder = os.path.join(temp_folder(), \"myrepo\")\n        conanfile = textwrap.dedent(\"\"\"\\\n           from conan import ConanFile\n           from conan.tools.scm import Git\n\n           class ConanRecipe(ConanFile):\n               name = \"conan-grafted\"\n               version = \"1.2.3\"\n\n               def export(self):\n                   git = Git(self, self.recipe_folder)\n                   git.coordinates_to_conandata(repository=True)\n           \"\"\")\n        url, commit = create_local_git_repo(files={\"conanfile.py\": conanfile}, folder=folder)\n\n        c = TestClient()\n        c.save({\"README.txt\": \"my readme!\"}, path=folder)\n        c.run_command(\"git checkout -b mybranch\", cwd=folder)\n        orphan_commit = git_add_changes_commit(folder)\n        c.run_command(f\"git checkout {orphan_commit}\", cwd=folder)\n        c.run_command(\"git branch -D mybranch\", cwd=folder)\n\n        # Now the client does the clone and export\n        c.run_command(f'git clone \"file://{url}\" . ')\n        c.run_command(\"git --no-pager log --decorate\")\n        assert \"grafted\" not in c.out\n        c.run(\"export .\")\n        c.run_command(\"git --no-pager log --decorate\")\n        assert \"grafted\" not in c.out\n\n\n@pytest.mark.tool(\"git\")\nclass TestGitBasicSCMFlowSubfolder:\n    \"\"\" Same as above, but conanfile.py put in \"conan\" subfolder in the root\n    \"\"\"\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.scm import Git\n        from conan.tools.files import load, update_conandata\n\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n\n            def export(self):\n                git = Git(self, os.path.dirname(self.recipe_folder)) # PARENT!\n                scm_url, scm_commit = git.get_url_and_commit()\n                update_conandata(self, {\"sources\": {\"commit\": scm_commit, \"url\": scm_url}})\n\n            def layout(self):\n                self.folders.root = \"..\"\n                self.folders.source = \".\"\n\n            def source(self):\n                git = Git(self)\n                sources = self.conan_data[\"sources\"]\n                git.clone(url=sources[\"url\"], target=\".\")\n                git.checkout(commit=sources[\"commit\"])\n                self.output.info(\"MYCMAKE: {}\".format(load(self, \"CMakeLists.txt\")))\n                self.output.info(\"MYFILE: {}\".format(load(self, \"src/myfile.h\")))\n\n            def build(self):\n                cmake = os.path.join(self.source_folder, \"CMakeLists.txt\")\n                file_h = os.path.join(self.source_folder, \"src/myfile.h\")\n                self.output.info(\"MYCMAKE-BUILD: {}\".format(load(self, cmake)))\n                self.output.info(\"MYFILE-BUILD: {}\".format(load(self, file_h)))\n        \"\"\")\n\n    def test_full_scm(self):\n        folder = os.path.join(temp_folder(), \"myrepo\")\n        url, commit = create_local_git_repo(files={\"conan/conanfile.py\": self.conanfile,\n                                                   \"src/myfile.h\": \"myheader!\",\n                                                   \"CMakeLists.txt\": \"mycmake\"}, folder=folder)\n\n        c = TestClient(default_server_user=True)\n        c.run_command('git clone \"{}\" .'.format(url))\n        c.run(\"create conan\")\n        assert \"pkg/0.1: MYCMAKE: mycmake\" in c.out\n        assert \"pkg/0.1: MYFILE: myheader!\" in c.out\n        c.run(\"upload * -c -r=default\")\n\n        # Do a change and commit, this commit will not be used by package\n        save_files(path=folder, files={\"src/myfile.h\": \"my2header2!\"})\n        git_add_changes_commit(folder=folder)\n\n        # use another fresh client\n        c2 = TestClient(servers=c.servers)\n        c2.run(\"install --requires=pkg/0.1@ --build=pkg*\")\n        assert \"pkg/0.1: MYCMAKE: mycmake\" in c2.out\n        assert \"pkg/0.1: MYFILE: myheader!\" in c2.out\n\n        # local flow\n        c.run(\"install conan\")\n        c.run(\"build conan\")\n        assert \"conanfile.py (pkg/0.1): MYCMAKE-BUILD: mycmake\" in c.out\n        assert \"conanfile.py (pkg/0.1): MYFILE-BUILD: myheader!\" in c.out\n\n\n@pytest.mark.tool(\"git\")\nclass TestGitMonorepoSCMFlow:\n    \"\"\" Build the full new SCM approach:\n    Same as above but with a monorepo with multiple subprojects\n    \"\"\"\n    # TODO: swap_child_folder() not documented, not public usage\n    conanfile = textwrap.dedent(\"\"\"\n        import os, shutil\n        from conan import ConanFile\n        from conan.tools.scm import Git\n        from conan.tools.files import load, update_conandata, move_folder_contents\n\n        class Pkg(ConanFile):\n            name = \"{pkg}\"\n            version = \"0.1\"\n\n            {requires}\n\n            def export(self):\n                git = Git(self, self.recipe_folder)\n                scm_url, scm_commit = git.get_url_and_commit()\n                self.output.info(\"CAPTURING COMMIT: {{}}!!!\".format(scm_commit))\n                folder = os.path.basename(self.recipe_folder)\n                update_conandata(self, {{\"sources\": {{\"commit\": scm_commit, \"url\": scm_url,\n                                                      \"folder\": folder}}}})\n\n            def layout(self):\n                self.folders.source = \".\"\n\n            def source(self):\n                git = Git(self)\n                sources = self.conan_data[\"sources\"]\n                git.clone(url=sources[\"url\"], target=\".\")\n                git.checkout(commit=sources[\"commit\"])\n                move_folder_contents(self, os.path.join(self.source_folder, sources[\"folder\"]),\n                                    self.source_folder)\n\n            def build(self):\n                cmake = os.path.join(self.source_folder, \"CMakeLists.txt\")\n                file_h = os.path.join(self.source_folder, \"src/myfile.h\")\n                self.output.info(\"MYCMAKE-BUILD: {{}}\".format(load(self, cmake)))\n                self.output.info(\"MYFILE-BUILD: {{}}\".format(load(self, file_h)))\n        \"\"\")\n\n    def test_full_scm(self):\n        folder = os.path.join(temp_folder(), \"myrepo\")\n        conanfile1 = self.conanfile.format(pkg=\"pkg1\", requires=\"\")\n        conanfile2 = self.conanfile.format(pkg=\"pkg2\", requires=\"requires = 'pkg1/0.1'\")\n        url, commit = create_local_git_repo(files={\"sub1/conanfile.py\": conanfile1,\n                                                   \"sub1/src/myfile.h\": \"myheader1!\",\n                                                   \"sub1/CMakeLists.txt\": \"mycmake1!\",\n                                                   \"sub2/conanfile.py\": conanfile2,\n                                                   \"sub2/src/myfile.h\": \"myheader2!\",\n                                                   \"sub2/CMakeLists.txt\": \"mycmake2!\"\n                                                   },\n                                            folder=folder)\n\n        c = TestClient(default_server_user=True)\n        c.run_command('git clone \"{}\" .'.format(url))\n        c.run(\"create sub1\")\n        commit = re.search(r\"CAPTURING COMMIT: (\\S+)!!!\", str(c.out)).group(1)\n        assert \"pkg1/0.1: MYCMAKE-BUILD: mycmake1!\" in c.out\n        assert \"pkg1/0.1: MYFILE-BUILD: myheader1!\" in c.out\n\n        c.save({\"sub2/src/myfile.h\": \"my2header!\"})\n        git_add_changes_commit(folder=c.current_folder)\n        c.run(\"create sub2\")\n        assert \"pkg2/0.1: MYCMAKE-BUILD: mycmake2!\" in c.out\n        assert \"pkg2/0.1: MYFILE-BUILD: my2header!\" in c.out\n\n        # Exporting again sub1, gives us exactly the same revision as before\n        c.run(\"export sub1\")\n        assert \"CAPTURING COMMIT: {}\".format(commit) in c.out\n        c.run(\"upload * -c -r=default\")\n\n        # use another fresh client\n        c2 = TestClient(servers=c.servers)\n        c2.run(\"install --requires=pkg2/0.1@ --build=*\")\n        assert \"pkg1/0.1: Checkout: {}\".format(commit) in c2.out\n        assert \"pkg1/0.1: MYCMAKE-BUILD: mycmake1!\" in c2.out\n        assert \"pkg1/0.1: MYFILE-BUILD: myheader1!\" in c2.out\n        assert \"pkg2/0.1: MYCMAKE-BUILD: mycmake2!\" in c2.out\n        assert \"pkg2/0.1: MYFILE-BUILD: my2header!\" in c2.out\n\n    @pytest.mark.tool(\"cmake\")\n    def test_exports_sources_common_code_layout(self):\n        \"\"\" This is a copy of test_exports_sources_common_code_layout in test_in_subfolder.py\n        but instead of using \"exports\", trying to implement it with Git features\n        \"\"\"\n        c = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.cmake import cmake_layout, CMake\n            from conan.tools.files import load, copy, save, update_conandata, move_folder_contents\n            from conan.tools.scm import Git\n\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n                generators = \"CMakeToolchain\"\n\n                def export(self):\n                    git = Git(self)\n                    scm_url, scm_commit = git.get_url_and_commit()\n                    update_conandata(self, {\"sources\": {\"commit\": scm_commit, \"url\": scm_url}})\n\n                def layout(self):\n                    self.folders.root = \"..\"\n                    self.folders.subproject = \"pkg\"\n                    cmake_layout(self)\n\n                def source(self):\n                    git = Git(self)\n                    sources = self.conan_data[\"sources\"]\n                    git.clone(url=sources[\"url\"], target=\".\")\n                    git.checkout(commit=sources[\"commit\"])\n                    # Layout is pkg/pkg/<files> and pkg/common/<files>\n                    # Final we want is pkg/<files> and common/<files>\n                    # NOTE: This abs_path is IMPORTANT to avoid the trailing \".\"\n                    src_folder = os.path.abspath(self.source_folder)\n                    move_folder_contents(self, src_folder, os.path.dirname(src_folder))\n\n                def build(self):\n                    cmake = CMake(self)\n                    cmake.configure()\n                    cmake.build()\n                    self.run(os.path.join(self.cpp.build.bindirs[0], \"myapp\"))\n                \"\"\")\n        cmake_include = \"include(${CMAKE_CURRENT_LIST_DIR}/../common/myutils.cmake)\"\n        c.save({\"pkg/conanfile.py\": conanfile,\n                \"pkg/app.cpp\": gen_function_cpp(name=\"main\", includes=[\"../common/myheader\"],\n                                                preprocessor=[\"MYDEFINE\"]),\n                \"pkg/CMakeLists.txt\": gen_cmakelists(appsources=[\"app.cpp\"],\n                                                     custom_content=cmake_include),\n                \"common/myutils.cmake\": 'message(STATUS \"MYUTILS.CMAKE!\")',\n                \"common/myheader.h\": '#define MYDEFINE \"MYDEFINEVALUE\"'})\n        c.init_git_repo()\n\n        c.run(\"create pkg\")\n        assert \"MYUTILS.CMAKE!\" in c.out\n        assert \"main: Release!\" in c.out\n        assert \"MYDEFINE: MYDEFINEVALUE\" in c.out\n\n        # Local flow\n        c.run(\"install pkg\")\n        c.run(\"build pkg\")\n        assert \"MYUTILS.CMAKE!\" in c.out\n        assert \"main: Release!\" in c.out\n        assert \"MYDEFINE: MYDEFINEVALUE\" in c.out\n\n        c.run(\"install pkg -s build_type=Debug\")\n        c.run(\"build pkg -s build_type=Debug\")\n        assert \"MYUTILS.CMAKE!\" in c.out\n        assert \"main: Debug!\" in c.out\n        assert \"MYDEFINE: MYDEFINEVALUE\" in c.out\n\n\nclass TestConanFileSubfolder:\n    \"\"\"verify that we can have a conanfile in a subfolder\n        # https://github.com/conan-io/conan/issues/11275\n    \"\"\"\n\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.scm import Git\n        from conan.tools.files import update_conandata, load\n\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n\n            def export(self):\n                git = Git(self, os.path.dirname(self.recipe_folder))\n                url, commit = git.get_url_and_commit()\n                # We store the current url and commit in conandata.yml\n                update_conandata(self, {\"sources\": {\"commit\": commit, \"url\": url}})\n                self.output.info(\"URL: {}\".format(url))\n                self.output.info(\"COMMIT: {}\".format(commit))\n\n            def layout(self):\n                pass # self.folders.source = \"source\"\n\n            def source(self):\n                git = Git(self)\n                sources = self.conan_data[\"sources\"]\n                url = sources[\"url\"]\n                commit = sources[\"commit\"]\n                git.clone(url=url, target=\".\")\n                git.checkout(commit=commit)\n                self.output.info(\"MYCMAKE: {}\".format(load(self, \"CMakeLists.txt\")))\n                self.output.info(\"MYFILE: {}\".format(load(self, \"src/myfile.h\")))\n        \"\"\")\n\n    def test_conanfile_subfolder(self):\n        \"\"\"\n        A local repo, without remote, will have commit, but no URL\n        \"\"\"\n        c = TestClient()\n        c.save({\"conan/conanfile.py\": self.conanfile,\n                \"CMakeLists.txt\": \"mycmakelists\",\n                \"src/myfile.h\": \"myheader\"})\n        commit = c.init_git_repo()\n        c.run(\"export conan\")\n        assert \"pkg/0.1: COMMIT: {}\".format(commit) in c.out\n        assert \"pkg/0.1: URL: {}\".format(c.current_folder.replace(\"\\\\\", \"/\")) in c.out\n\n        c.run(\"create conan\")\n        assert \"pkg/0.1: MYCMAKE: mycmakelists\" in c.out\n        assert \"pkg/0.1: MYFILE: myheader\" in c.out\n\n    def test_git_run(self):\n        conanfile = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.scm import Git\n\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                def export(self):\n                    git = Git(self)\n                    self.output.info(git.run(\"--version\"))\n            \"\"\")\n\n        c = TestClient()\n        c.save({\"conan/conanfile.py\": conanfile})\n        c.init_git_repo()\n        c.run(\"export conan\")\n        assert \"pkg/0.1: git version\" in c.out\n\n\nclass TestGitIncluded:\n    def test_git_included(self):\n        conanfile = textwrap.dedent(\"\"\"\n            import os\n            import shutil\n            from conan import ConanFile\n            from conan.tools.scm import Git\n\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n\n                def export_sources(self):\n                    git = Git(self)\n                    included = git.included_files()\n                    for i in included:\n                        dst =  os.path.join(self.export_sources_folder, i)\n                        os.makedirs(os.path.dirname(dst), exist_ok=True)\n                        shutil.copy2(i, dst)\n\n                def source(self):\n                    self.output.info(\"SOURCES: {}!!\".format(sorted(os.listdir(\".\"))))\n                    self.output.info(\"SOURCES_SUB: {}!!\".format(sorted(os.listdir(\"sub\"))))\n            \"\"\")\n\n        c = TestClient()\n        c.save({\"conanfile.py\": conanfile,\n                \".gitignore\": \"*.txt\",\n                \"myfile.txt\": \"test\",\n                \"myfile.other\": \"othertest\",\n                \"sub/otherfile\": \"other\"})\n        c.init_git_repo()\n        c.run(\"create .\")\n        assert \"pkg/0.1: SOURCES: ['.gitignore', 'conanfile.py', 'myfile.other', 'sub']!!\" in c.out\n        assert \"pkg/0.1: SOURCES_SUB: ['otherfile']!!\" in c.out\n\n    def test_git_included_subfolder(self):\n        conanfile = textwrap.dedent(\"\"\"\n            import os\n            import shutil\n            from conan import ConanFile\n            from conan.tools.scm import Git\n\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n\n                def export_sources(self):\n                    git = Git(self, \"src\")\n                    included = git.included_files()\n                    for i in included:\n                        shutil.copy2(i, self.export_sources_folder)\n\n                def source(self):\n                    self.output.info(\"SOURCES: {}!!\".format(sorted(os.listdir(\".\"))))\n            \"\"\")\n\n        c = TestClient()\n        c.save({\"conanfile.py\": conanfile,\n                \".gitignore\": \"*.txt\",\n                \"somefile\": \"some\",\n                \"src/myfile.txt\": \"test\",\n                \"src/myfile.other\": \"othertest\"})\n        c.init_git_repo()\n        c.run(\"create .\")\n        assert \"pkg/0.1: SOURCES: ['myfile.other']!!\" in c.out\n\n\ndef test_capture_git_tag():\n    \"\"\"\n    A local repo, without remote, will have commit, but no URL\n    \"\"\"\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.scm import Git\n\n        class Pkg(ConanFile):\n            name = \"pkg\"\n\n            def set_version(self):\n                git = Git(self, self.recipe_folder)\n                self.version = git.run(\"describe --tags\")\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.init_git_repo()\n    c.run_command(\"git tag 1.2\")\n    c.run(\"install .\")\n    assert \"pkg/1.2\" in c.out\n    c.run(\"create .\")\n    assert \"pkg/1.2\" in c.out\n    c.run(\"install --requires=pkg/1.2\")\n    assert \"pkg/1.2\" in c.out\n\n\n@pytest.mark.tool(\"git\")\nclass TestGitShallowTagClone:\n    \"\"\"\n    When we do a shallow clone of a repo with a specific tag/branch, it doesn't\n    clone any of the git history.  When we check to see if a commit is in the\n    repo, we fallback to a git fetch if we can't verify the commit locally.\n    \"\"\"\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.scm import Git\n\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n\n            def export(self):\n                git = Git(self, self.recipe_folder)\n                commit = git.get_commit()\n                url = git.get_remote_url()\n                self.output.info(\"URL: {}\".format(url))\n                self.output.info(\"COMMIT: {}\".format(commit))\n                in_remote = git.commit_in_remote(commit)\n                self.output.info(\"COMMIT IN REMOTE: {}\".format(in_remote))\n                self.output.info(\"DIRTY: {}\".format(git.is_dirty()))\n        \"\"\")\n\n    def test_find_tag_in_remote(self):\n        \"\"\"\n        a shallow cloned repo won't have the new commit locally, but can fetch it.\n        \"\"\"\n        folder = temp_folder()\n        url, commit = create_local_git_repo(files={\"conanfile.py\": self.conanfile}, folder=folder)\n\n        c = TestClient()\n        # Create a tag\n        with c.chdir(folder):\n            c.run_command('git tag 1.0.0')\n\n        # Do a shallow clone of our tag\n        c.run_command('git clone --depth=1 --branch 1.0.0 \"{}\" myclone'.format(folder))\n        with c.chdir(\"myclone\"):\n            c.run(\"export .\")\n            assert \"pkg/0.1: COMMIT: {}\".format(commit) in c.out\n            assert \"pkg/0.1: URL: {}\".format(url) in c.out\n            assert \"pkg/0.1: COMMIT IN REMOTE: True\" in c.out\n            assert \"pkg/0.1: DIRTY: False\" in c.out\n\n    def test_detect_commit_not_in_remote(self):\n        \"\"\"\n        a shallow cloned repo won't have new commit in remote\n        \"\"\"\n        folder = temp_folder()\n        url, commit = create_local_git_repo(files={\"conanfile.py\": self.conanfile}, folder=folder)\n\n        c = TestClient()\n        # Create a tag\n        with c.chdir(folder):\n            c.run_command('git tag 1.0.0')\n\n        # Do a shallow clone of our tag\n        c.run_command('git clone --depth=1 --branch 1.0.0 \"{}\" myclone'.format(folder))\n        with c.chdir(\"myclone\"):\n            c.save({\"conanfile.py\": self.conanfile + \"\\n# some coment!\"})\n            new_commit = git_add_changes_commit(c.current_folder)\n\n            c.run(\"export .\")\n            assert \"pkg/0.1: COMMIT: {}\".format(new_commit) in c.out\n            assert \"pkg/0.1: URL: {}\".format(url) in c.out\n            assert \"pkg/0.1: COMMIT IN REMOTE: False\" in c.out\n            assert \"pkg/0.1: DIRTY: False\" in c.out\n\n\n@pytest.mark.tool(\"git\")\nclass TestGitTreelessRemote:\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.scm import Git\n        import os\n\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n\n            def layout(self):\n                self.folders.source = \"source\"\n\n            def export(self):\n                git = Git(self)\n                git.clone(url=\"{url}\", args=[\"--filter=tree:0\"], target=\"target\")\n                git.folder = \"target\"\n                cloned_url = git.run(\"remote -v\")\n                self.output.info(\"git remote: %s ===\" % cloned_url)\n                cloned_url = git.get_remote_url()\n                self.output.info(\"get_remote_url(): %s ===\" % cloned_url)\n        \"\"\")\n\n    def test_treeless_clone(self):\n        \"\"\"\n        When cloning a git repository with the `--filter=tree:0` option,\n        the Git.get_remote_url() should only the URL of the repository.\n\n        Validate the issue https://github.com/conan-io/conan/issues/18415\n        \"\"\"\n        repository = temp_folder(path_with_spaces=False)\n        url, commit = create_local_git_repo(files={\"README\": \"Lumen naturale ratum est\"},\n                                            folder=repository)\n\n        client = TestClient()\n        client.save({\"conanfile.py\": self.conanfile.format(url=url)})\n        client.run(\"export .\")\n        # We expect [tree:0] for regular git remote command. Requires Git +2.43\n        assert f\"git remote: origin\\t{url} (fetch) [tree:0]\" in client.out\n        # Then get_remote_url filters it to only the URL\n        assert f\"get_remote_url(): {url} ===\" in client.out\n\n    def test_treeless_clone_with_parenthesis(self):\n        \"\"\"\n        Windows can use C:/Program Files (x86) path, which contains parenthesis.\n        As the URL will have (fetch) or (push), get_remote_url() should be able to parse it.\n        \"\"\"\n        repository = os.path.join(temp_folder(), \"Program Files (x86)\", \"myrepo\")\n        os.makedirs(repository)\n        url, commit = create_local_git_repo(files={\"README\": \"Pacem in maribus.\"},\n                                            folder=repository)\n\n        client = TestClient()\n        client.save({\"conanfile.py\": self.conanfile.format(url=url)})\n        client.run(\"export .\")\n        assert f\"get_remote_url(): {url} ===\" in client.out\n"
  },
  {
    "path": "test/functional/tools/scm/test_git_get_commit.py",
    "content": "import os\n\nimport pytest\n\nfrom conan.tools.scm import Git\nfrom conan.test.utils.mocks import ConanFileMock\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import chdir\nfrom conan.internal.util.runners import conan_run\n\n\n@pytest.mark.tool(\"git\")\ndef test_change_branch_in_root_commit():\n    \"\"\"\n    https://github.com/conan-io/conan/issues/10971#issuecomment-1089316912\n    \"\"\"\n    c = TestClient()\n    c.save({\"root.txt\": \"\", \"subfolder/subfolder.txt\": \"\"})\n    c.run_command(\"git init .\")\n    c.run_command(\"git checkout -B master\")\n    c.run_command('git config user.name myname')\n    c.run_command('git config user.email myname@mycompany.com')\n    c.run_command(\"git add .\")\n    c.run_command('git commit -m \"initial commit\"')\n    c.run_command(\"git checkout -b change_branch\")\n    c.save({\"subfolder/subfolder.txt\": \"CHANGED\"})\n    c.run_command(\"git add .\")\n    c.run_command('git commit -m \"second commit\"')\n    c.run_command(\"git checkout master\")\n    c.run_command('git merge --no-ff change_branch -m \"Merge branch\"')\n\n    conanfile = ConanFileMock({}, runner=conan_run)\n    git = Git(conanfile, folder=c.current_folder)\n    commit_conan = git.get_commit()\n\n    c.run_command(\"git rev-parse HEAD\")\n    commit_real = str(c.out).splitlines()[0]\n    assert commit_conan == commit_real\n\n\n@pytest.mark.tool(\"git\")\ndef test_multi_folder_repo():\n    c = TestClient()\n    c.save({\"lib_a/conanfile.py\": \"\"})\n    c.run_command(\"git init .\")\n    c.run_command('git config user.name myname')\n    c.run_command('git config user.email myname@mycompany.com')\n    c.run_command(\"git add .\")\n    c.run_command('git commit -m \"lib_a commit\"')\n    c.save({\"lib_b/conanfile.py\": \"\"})\n    c.run_command(\"git add .\")\n    c.run_command('git commit -m \"lib_b commit\"')\n    c.save({\"lib_c/conanfile.py\": \"\"})\n    c.run_command(\"git add .\")\n    c.run_command('git commit -m \"lib_c commit\"')\n    c.save({\"root_change\": \"\"})\n    c.run_command(\"git add .\")\n    c.run_command('git commit -m \"root change\"')\n\n    # Git object for lib_a\n    conanfile = ConanFileMock({}, runner=conan_run)\n    git = Git(conanfile, folder=os.path.join(c.current_folder, \"lib_a\"))\n    commit_libA = git.get_commit()\n\n    git = Git(conanfile, folder=os.path.join(c.current_folder, \"lib_b\"))\n    commit_libB = git.get_commit()\n\n    git = Git(conanfile, folder=os.path.join(c.current_folder, \"lib_c\"))\n    commit_libC = git.get_commit()\n\n    git = Git(conanfile, folder=c.current_folder)\n    commit_root = git.get_commit()\n\n    # All different\n    assert len({commit_libA, commit_libB, commit_libC, commit_root}) == 4\n\n    c.run_command(\"git rev-parse HEAD\")\n    commit_real = str(c.out).splitlines()[0]\n    assert commit_root == commit_real\n\n    # New commit in A\n    c.save({\"lib_a/conanfile.py\": \"CHANGED\"})\n    c.run_command(\"git add .\")\n    c.run_command('git commit -m \"lib_a commit2\"')\n\n    # Git object for lib_a\n    git = Git(conanfile, folder=os.path.join(c.current_folder, \"lib_a\"))\n    new_commit_libA = git.get_commit()\n\n    git = Git(conanfile, folder=os.path.join(c.current_folder, \"lib_b\"))\n    new_commit_libB = git.get_commit()\n\n    git = Git(conanfile, folder=os.path.join(c.current_folder, \"lib_c\"))\n    new_commit_libC = git.get_commit()\n\n    git = Git(conanfile, folder=c.current_folder)\n    new_commit_root = git.get_commit()\n\n    assert new_commit_libA != commit_libA\n    assert new_commit_libB == commit_libB\n    assert new_commit_libC == commit_libC\n    assert new_commit_root != commit_root\n\n    c.run_command(\"git rev-parse HEAD\")\n    commit_real = str(c.out).splitlines()[0]\n    assert new_commit_root == commit_real\n\n\n@pytest.mark.tool(\"git\")\ndef test_relative_folder_repo():\n    c = TestClient()\n    c.save({\"lib_a/conanfile.py\": \"\"})\n    c.run_command(\"git init .\")\n    c.run_command('git config user.name myname')\n    c.run_command('git config user.email myname@mycompany.com')\n    c.run_command(\"git add .\")\n    c.run_command('git commit -m \"lib_a commit\"')\n    c.save({\"lib_b/conanfile.py\": \"\"})\n    c.run_command(\"git add .\")\n    c.run_command('git commit -m \"lib_b commit\"')\n    c.save({\"lib_c/conanfile.py\": \"\"})\n    c.run_command(\"git add .\")\n    c.run_command('git commit -m \"lib_c commit\"')\n    c.save({\"root_change\": \"\"})\n    c.run_command(\"git add .\")\n    c.run_command('git commit -m \"root change\"')\n\n    conanfile = ConanFileMock({}, runner=conan_run)\n    # Relative paths for folders, from the current_folder\n    with chdir(c.current_folder):\n        git = Git(conanfile, folder=\"lib_a\")\n        commit_libA = git.get_commit()\n\n        git = Git(conanfile, folder=\"lib_b\")\n        commit_libB = git.get_commit()\n\n        git = Git(conanfile, folder=\"./lib_c\")\n        commit_libC = git.get_commit()\n\n        # this is folder default, but be explicit\n        git = Git(conanfile, folder=\".\")\n        commit_root = git.get_commit()\n\n    # All different\n    assert len({commit_libA, commit_libB, commit_libC, commit_root}) == 4\n\n    # Compare to Full paths\n    git = Git(conanfile, folder=os.path.join(c.current_folder, \"lib_a\"))\n    full_commit_libA = git.get_commit()\n\n    git = Git(conanfile, folder=os.path.join(c.current_folder, \"lib_b\"))\n    full_commit_libB = git.get_commit()\n\n    git = Git(conanfile, folder=os.path.join(c.current_folder, \"lib_c\"))\n    full_commit_libC = git.get_commit()\n\n    git = Git(conanfile, folder=c.current_folder)\n    full_commit_root = git.get_commit()\n\n    assert full_commit_libA == commit_libA\n    assert full_commit_libB == commit_libB\n    assert full_commit_libC == commit_libC\n    assert full_commit_root == commit_root\n\n    # Sanity checks\n    c.run_command(\"git rev-parse HEAD\")\n    commit_real_root = str(c.out).splitlines()[0]\n    assert commit_real_root == commit_root\n\n    c.run_command(\"git rev-list -n 1 --full-history HEAD -- lib_a\")\n    commit_real_libA = str(c.out).splitlines()[0]\n    assert commit_real_libA == commit_libA\n\n\n@pytest.mark.tool(\"git\")\ndef test_submodule_repo():\n    c = TestClient()\n    c.save({\"conanfile.py\": \"\"})\n    c.run_command(\"git init .\")\n    c.run_command('git config user.name myname')\n    c.run_command('git config user.email myname@mycompany.com')\n    c.run_command(\"git add .\")\n    c.run_command('git commit -m \"Initial commit\"')\n    c.run_command('git clone . source_subfolder')\n    c.run_command('git submodule add ../ source_subfolder')\n    c.run_command('git commit -m \"submodule commit\"')\n    c.save({\"root_change\": \"\"})\n    c.run_command(\"git add .\")\n    c.run_command('git commit -m \"root change\"')\n\n    conanfile = ConanFileMock({}, runner=conan_run)\n    with chdir(c.current_folder):\n        # default case\n        git = Git(conanfile)\n        commit_root = git.get_commit()\n\n        # Relative paths\n        git = Git(conanfile, folder=\"source_subfolder\")\n        commit_relA = git.get_commit()\n\n        git = Git(conanfile, folder=\"./source_subfolder\")\n        commit_relB = git.get_commit()\n\n        # Full path\n        git = Git(conanfile, folder=os.path.join(c.current_folder, \"source_subfolder\"))\n        commit_full = git.get_commit()\n\n    assert commit_relA == commit_relB\n    assert commit_relA == commit_full\n    assert commit_root != commit_full\n\n    # This is the commit which modified the tree in the containing repo\n    # not the commit which the submodule is at\n    c.run_command(\"git rev-list HEAD -n 1 --full-history -- source_subfolder\")\n    commit_submodule = str(c.out).splitlines()[0]\n    assert commit_submodule != commit_full\n"
  },
  {
    "path": "test/functional/tools/scm/test_version.py",
    "content": "import textwrap\n\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_version():\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.scm import Version\n\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            settings = \"compiler\"\n            def configure(self):\n                v = Version(self.settings.compiler.version)\n                assert v > \"10\"\n\n                v = Version(\"1.2.3\")\n                self.output.warning(f\"The major of 1.2.3 is {v.major}\")\n                self.output.warning(f\"The minor of 1.2.3 is {v.minor}\")\n                self.output.warning(f\"The patch of 1.2.3 is {v.patch}\")\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    settings = \"-s compiler=gcc -s compiler.libcxx=libstdc++11\"\n    c.run(\"create . {} -s compiler.version=11\".format(settings))\n    assert \"The major of 1.2.3 is 1\" in c.out\n    assert \"The minor of 1.2.3 is 2\" in c.out\n    assert \"The patch of 1.2.3 is 3\" in c.out\n\n    c.run(\"create . {} -s compiler.version=9\".format(settings), assert_error=True)\n"
  },
  {
    "path": "test/functional/tools/system/__init__.py",
    "content": ""
  },
  {
    "path": "test/functional/tools/system/package_manager_test.py",
    "content": "import json\nimport platform\nimport textwrap\nfrom unittest.mock import patch, MagicMock\n\nimport pytest\n\nfrom conan.tools.system.package_manager import _SystemPackageManagerTool\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.tool(\"apt_get\")\n@pytest.mark.skipif(platform.system() != \"Linux\", reason=\"Requires apt\")\ndef test_apt_check():\n    client = TestClient()\n    client.save({\"conanfile.py\": textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.system.package_manager import Apt\n\n        class MyPkg(ConanFile):\n            settings = \"arch\", \"os\"\n            def system_requirements(self):\n                apt = Apt(self)\n                not_installed = apt.check([\"non-existing1\", \"non-existing2\"])\n                print(\"missing:\", not_installed)\n        \"\"\")})\n    client.run(\"create . --name=test --version=1.0 -s:b arch=armv8 -s:h arch=x86\")\n    assert \"missing: ['non-existing1', 'non-existing2']\" in client.out\n\n\n@pytest.mark.tool(\"apt_get\")\n@pytest.mark.skipif(platform.system() != \"Linux\", reason=\"Requires apt\")\ndef test_apt_install_substitutes():\n    client = TestClient()\n    conanfile_py = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.system.package_manager import Apt\n        class MyPkg(ConanFile):\n            settings = \"arch\", \"os\"\n            def system_requirements(self):\n                # FIXME this is needed because the ci-functional apt-get update fails\n                try:\n                    self.run(\"sudo apt-get update\")\n                except Exception:\n                    pass\n                apt = Apt(self)\n                {}\n        \"\"\")\n\n    installs = 'apt.install_substitutes([\"non-existing1\", \"non-existing2\"], [\"non-existing3\", \"non-existing4\"])'\n    client.save({\"conanfile.py\": conanfile_py.format(installs)})\n    client.run(\"create . --name=test --version=1.0 -c tools.system.package_manager:mode=install \"\n               \"-c tools.system.package_manager:sudo=True\", assert_error=True)\n    assert \"None of the installs for the package substitutes succeeded.\" in client.out\n\n    client.run_command(\"sudo apt remove nano -yy\")\n    installs = 'apt.install_substitutes([\"non-existing1\", \"non-existing2\"], [\"nano\"], [\"non-existing3\"])'\n    client.save({\"conanfile.py\": conanfile_py.format(installs)})\n    client.run(\"create . --name=test --version=1.0 -c tools.system.package_manager:mode=install \"\n               \"-c tools.system.package_manager:sudo=True\")\n    assert \"1 newly installed\" in client.out\n\n\n@pytest.mark.tool(\"apt_get\")\n@pytest.mark.skipif(platform.system() != \"Linux\", reason=\"Requires apt\")\ndef test_build_require():\n    client = TestClient()\n    client.save({\"tool_require.py\": textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.system.package_manager import Apt\n\n        class MyPkg(ConanFile):\n            settings = \"arch\", \"os\"\n            def system_requirements(self):\n                apt = Apt(self)\n                not_installed = apt.check([\"non-existing1\", \"non-existing2\"])\n                print(\"missing:\", not_installed)\n        \"\"\")})\n    client.run(\"export tool_require.py --name=tool_require --version=1.0\")\n    client.save({\"consumer.py\": textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class consumer(ConanFile):\n            settings = \"arch\", \"os\"\n            tool_requires = \"tool_require/1.0\"\n        \"\"\")})\n    client.run(\"create consumer.py --name=consumer --version=1.0 \"\n               \"-s:b arch=armv8 -s:h arch=x86 --build=missing\")\n    assert \"missing: ['non-existing1', 'non-existing2']\" in client.out\n\n\n@pytest.mark.tool(\"brew\")\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Requires brew\")\ndef test_brew_check():\n    client = TestClient()\n    client.save({\"conanfile.py\": textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.system.package_manager import Brew\n\n        class MyPkg(ConanFile):\n            settings = \"arch\"\n            def system_requirements(self):\n                brew = Brew(self)\n                not_installed = brew.check([\"non-existing1\", \"non-existing2\"])\n                print(\"missing:\", not_installed)\n        \"\"\")})\n    client.run(\"create . --name=test --version=1.0\")\n    assert \"missing: ['non-existing1', 'non-existing2']\" in client.out\n\n\n@pytest.mark.tool(\"brew\")\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Requires brew\")\n@pytest.mark.skip(reason=\"brew update takes a lot of time\")\ndef test_brew_install_check_mode():\n    client = TestClient()\n    client.save({\"conanfile.py\": textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.system.package_manager import Brew\n\n        class MyPkg(ConanFile):\n            settings = \"arch\"\n            def system_requirements(self):\n                brew = Brew(self)\n                brew.install([\"non-existing1\", \"non-existing2\"])\n        \"\"\")})\n    client.run(\"create . test/1.0@\", assert_error=True)\n    assert \"System requirements: 'non-existing1, non-existing2' are missing but \" \\\n           \"can't install because tools.system.package_manager:mode is 'check'\" in client.out\n\n\n@pytest.mark.tool(\"brew\")\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Requires brew\")\n@pytest.mark.skip(reason=\"brew update takes a lot of time\")\ndef test_brew_install_install_mode():\n    client = TestClient()\n    client.save({\"conanfile.py\": textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.system.package_manager import Brew\n\n        class MyPkg(ConanFile):\n            settings = \"arch\"\n            def system_requirements(self):\n                brew = Brew(self)\n                brew.install([\"non-existing1\", \"non-existing2\"])\n        \"\"\")})\n    client.run(\"create . test/1.0@ -c tools.system.package_manager:mode=install\", assert_error=True)\n    assert \"Error: No formulae found in taps.\" in client.out\n\n\ndef test_collect_system_requirements():\n    \"\"\" we can know the system_requires for every package because they are part of the graph,\n    this naturally execute at ``install``, but we can also prove that with ``graph info`` we can\n    for it to with the righ ``mode=collect`` mode.\n    \"\"\"\n    client = TestClient()\n    client.save({\"conanfile.py\": textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.system.package_manager import Brew, Apt\n\n        class MyPkg(ConanFile):\n            settings = \"arch\"\n            def system_requirements(self):\n                brew = Brew(self)\n                brew.install([\"brew1\", \"brew2\"])\n                apt = Apt(self)\n                apt.install([\"pkg1\", \"pkg2\"])\n        \"\"\")})\n\n    with patch.object(_SystemPackageManagerTool, '_conanfile_run', MagicMock(return_value=False)):\n        client.run(\"install . -c tools.system.package_manager:tool=apt-get --format=json\",\n                   redirect_stdout=\"graph.json\")\n    graph = json.loads(client.load(\"graph.json\"))\n    assert {\"apt-get\": {\"install\": [\"pkg1\", \"pkg2\"], \"missing\": []}} == \\\n           graph[\"graph\"][\"nodes\"][\"0\"][\"system_requires\"]\n\n    # plain report, do not check\n    client.run(\"graph info . -c tools.system.package_manager:tool=apt-get \"\n               \"-c tools.system.package_manager:mode=report --format=json\",\n               redirect_stdout=\"graph2.json\")\n    graph2 = json.loads(client.load(\"graph2.json\"))\n    # TODO: Unify format of ``graph info`` and ``install``\n    assert {\"apt-get\": {\"install\": [\"pkg1\", \"pkg2\"]}} == \\\n           graph2[\"graph\"][\"nodes\"][\"0\"][\"system_requires\"]\n\n    # Check report-installed\n    with patch.object(_SystemPackageManagerTool, '_conanfile_run', MagicMock(return_value=True)):\n        client.run(\"graph info . -c tools.system.package_manager:tool=apt-get \"\n                   \"-c tools.system.package_manager:mode=report-installed --format=json\",\n                   redirect_stdout=\"graph2.json\")\n        graph2 = json.loads(client.load(\"graph2.json\"))\n        assert {\"apt-get\": {\"install\": [\"pkg1\", \"pkg2\"],\n                            'missing': ['pkg1', 'pkg2']}} == graph2[\"graph\"][\"nodes\"][\"0\"][\"system_requires\"]\n\n    # Default \"check\" will fail, as dpkg-query not installed\n    client.run(\"graph info . -c tools.system.package_manager:tool=apt-get \"\n               \"-c tools.system.package_manager:mode=check\", assert_error=True)\n    assert \"ERROR: conanfile.py: Error in system_requirements() method, line 11\" in client.out\n"
  },
  {
    "path": "test/functional/tools/system/python_manager_test.py",
    "content": "import json\nimport sys\nimport textwrap\nimport platform\nimport pytest\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import save_files\nfrom conan.test.utils.test_files import temp_folder\n\n\ndef _create_py_hello_world(folder):\n    setup_py = textwrap.dedent(\"\"\"\n        from setuptools import setup, find_packages\n\n        setup(\n            name='hello',\n            version='0.1.0',\n            packages=find_packages(include=['hello', 'hello.*']),\n            entry_points={'console_scripts': ['hello-world = hello:hello']}\n        )\n        \"\"\")\n    hello_py = textwrap.dedent(\"\"\"\n        def hello():\n            print(\"Hello Test World!\")\n        \"\"\")\n\n    save_files(folder, {\"setup.py\": setup_py, \"hello/__init__.py\": hello_py})\n\n\ndef test_empty_pyenv():\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.system import PyEnv\n\n        class PyenvPackage(ConanFile):\n\n            def generate(self):\n                PyEnv(self).generate()\n\n            def build(self):\n                self.run(\"python -m pip list\")\n        \"\"\")\n\n    c = TestClient(path_with_spaces=False)\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"build\")\n    # Test that some Conan common deps are not in this pip list\n    assert \"requests\" not in c.out\n    assert \"colorama\" not in c.out\n    assert \"Jinja2\" not in c.out\n    assert \"PyJWT\" not in c.out\n    ext = \".bat\" if platform.system() == \"Windows\" else \".sh\"\n    script = c.load(f\"conan_pyenv{ext}\")\n    assert \"conan_pyenv\" in script\n\n\ndef test_build_py_manager():\n    pip_package_folder = temp_folder(path_with_spaces=True)\n    _create_py_hello_world(pip_package_folder)\n    pip_package_folder = pip_package_folder.replace('\\\\', '/')\n\n    conanfile_pyenv = textwrap.dedent(f\"\"\"\n        from conan import ConanFile\n        from conan.tools.system import PyEnv\n        from conan.tools.layout import basic_layout\n\n        class PyenvPackage(ConanFile):\n            def layout(self):\n                basic_layout(self)\n\n            def generate(self):\n                pyenv = PyEnv(self)\n                pyenv.install([\"{pip_package_folder}\"])\n                pyenv.generate()\n\n            def build(self):\n                self.run(\"hello-world\")\n        \"\"\")\n\n    client = TestClient(path_with_spaces=False)\n    # FIXME: the python shebang inside vitual env packages fails when using path_with_spaces\n    client.save({\"pip/conanfile.py\": conanfile_pyenv})\n    client.run(\"build pip\")\n\n    assert \"RUN: hello-world\" in client.out\n    assert \"Hello Test World!\" in client.out\n\n    client.run(\"build pip\")\n    assert \"Found existing installation: hello 0.1.0\" in client.out\n    assert \"Hello Test World!\" in client.out\n\n    client.run(\"build pip -verror\")\n    assert \"Found existing installation\" not in client.out\n\n\ndef test_install_version_range():\n    c = TestClient(path_with_spaces=False)\n\n    # TODO: Maybe we want a pip.run(\"-m pip install .\") that automatically handles python.exe path\n    conanfile_pyenv = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.system import PyEnv\n        from conan.tools.layout import basic_layout\n\n        class PyenvPackage(ConanFile):\n\n            def generate(self):\n                pyenv = PyEnv(self)\n                pyenv.install([\".\"])\n                pyenv.install([\"hello>=0.0,<1.0\"])\n                pyenv.generate()\n\n            def build(self):\n                self.run(\"hello-world\")\n        \"\"\")\n\n    # FIXME: the python shebang inside vitual env packages fails when using path_with_spaces\n    c.save({\"conanfile.py\": conanfile_pyenv})\n    _create_py_hello_world(c.current_folder)\n\n    c.run(\"build\")\n\n    assert \"RUN: hello-world\" in c.out\n    assert \"Hello Test World!\" in c.out\n\n\ndef test_create_py_manager():\n\n    pip_package_folder = temp_folder(path_with_spaces=True)\n    _create_py_hello_world(pip_package_folder)\n    pip_package_folder = pip_package_folder.replace('\\\\', '/')\n\n    conanfile_pyenv = textwrap.dedent(f\"\"\"\n        from conan import ConanFile\n        from conan.tools.system import PyEnv\n        from conan.tools.layout import basic_layout\n\n        class PyenvPackage(ConanFile):\n            name = \"pip_hello_test\"\n            version = \"0.1\"\n            build_policy = \"missing\"\n            upload_policy = \"skip\"\n\n            def layout(self):\n                basic_layout(self)\n\n            def finalize(self):\n                PyEnv(self, self.package_folder).install([\"{pip_package_folder}\"])\n\n            def package_info(self):\n                python_env_bin = PyEnv(self, self.package_folder).bin_path\n                self.buildenv_info.prepend_path(\"PATH\", python_env_bin)\n        \"\"\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Recipe(ConanFile):\n\n            def requirements(self):\n                self.tool_requires(\"pip_hello_test/0.1\")\n\n            def build(self):\n                self.run(\"hello-world\")\n        \"\"\")\n\n    client = TestClient(path_with_spaces=False)\n    # FIXME: the python shebang inside vitual env packages fails when using path_with_spaces\n    client.save({\"pip/conanfile.py\": conanfile_pyenv, \"consumer/conanfile.py\": conanfile})\n    client.run(\"create pip --version=0.1\")\n    client.run(\"build consumer\")\n\n    assert \"RUN: hello-world\" in client.out\n    assert \"Hello Test World!\" in client.out\n\n\n@pytest.mark.skipif(sys.version_info.minor < 8, reason=\"UV needs Python >= 3.8\")\ndef test_build_uv_manager():\n\n    pip_package_folder = temp_folder(path_with_spaces=True)\n    _create_py_hello_world(pip_package_folder)\n    pip_package_folder = pip_package_folder.replace('\\\\', '/')\n\n    def conanfile_pyenv(py_version):\n        return textwrap.dedent(f\"\"\"\n        from conan import ConanFile\n        from conan.tools.system import PyEnv\n        from conan.tools.layout import basic_layout\n        import platform\n        import os\n\n\n        class PyenvPackage(ConanFile):\n            name = \"pip_hello_test\"\n            version = \"0.1\"\n\n            def layout(self):\n                basic_layout(self)\n\n            def generate(self):\n                pip_env = PyEnv(self, py_version=\"{py_version}\")\n                pip_env.install([\"{pip_package_folder}\"])\n                pip_env.generate()\n                pip_env.run([\"--version\"])\n\n            def build(self):\n                self.run(\"hello-world\")\n        \"\"\")\n\n    client = TestClient(path_with_spaces=False)\n    # FIXME: the python shebang inside vitual env packages fails when using path_with_spaces\n    client.save({\"pip/conanfile.py\": conanfile_pyenv(\"3.11.6\")})\n    client.run(\"build pip/conanfile.py\")\n    assert \"Virtual environment for Python 3.11.6 created successfully using UV.\" in client.out\n    if platform.system() == \"Windows\":\n        assert \"python.exe --version\\nPython 3.11.6\" in client.out\n    else:\n        assert \"python --version\\nPython 3.11.6\" in client.out\n    assert \"RUN: hello-world\" in client.out\n    assert \"Hello Test World!\" in client.out\n\n    client.run(\"build pip/conanfile.py\")\n    assert \"Found existing installation: hello 0.1.0\" in client.out\n    assert \"RUN: hello-world\" in client.out\n    assert \"Hello Test World!\" in client.out\n\n    client.save({\"pip/conanfile.py\": conanfile_pyenv(\"3.12.3\")})\n\n    client.run(\"build pip/conanfile.py\")\n    assert \"Virtual environment for Python 3.12.3 created successfully using UV.\" in client.out\n    if platform.system() == \"Windows\":\n        assert \"python.exe --version\\nPython 3.12.3\" in client.out\n    else:\n        assert \"python --version\\nPython 3.12.3\" in client.out\n    assert \"Found existing installation: hello 0.1.0\" not in client.out\n    assert \"RUN: hello-world\" in client.out\n    assert \"Hello Test World!\" in client.out\n\n\n@pytest.mark.skipif(sys.version_info.minor < 8, reason=\"UV needs Python >= 3.8\")\ndef test_fail_build_uv_manager():\n\n    pip_package_folder = temp_folder(path_with_spaces=True)\n    _create_py_hello_world(pip_package_folder)\n    pip_package_folder = pip_package_folder.replace('\\\\', '/')\n\n    conanfile_pyenv = textwrap.dedent(f\"\"\"\n        from conan import ConanFile\n        from conan.tools.system import PyEnv\n        from conan.tools.layout import basic_layout\n        import platform\n        import os\n\n\n        class PyenvPackage(ConanFile):\n            name = \"pip_hello_test\"\n            version = \"0.1\"\n\n            def layout(self):\n                basic_layout(self)\n\n            def generate(self):\n                pip_env = PyEnv(self, py_version=\"3.11.86\")\n                pip_env.install([\"{pip_package_folder}\"])\n                pip_env.generate()\n\n            def build(self):\n                self.run(\"hello-world\")\n        \"\"\")\n\n    client = TestClient(path_with_spaces=False)\n    # FIXME: the python shebang inside vitual env packages fails when using path_with_spaces\n    client.save({\"pip/conanfile.py\": conanfile_pyenv})\n    client.run(\"build pip/conanfile.py\", assert_error=True)\n    assert \"PyEnv could not create a Python 3.11.86 virtual environment using UV\" in client.out\n\n\n@pytest.mark.skipif(sys.version_info.minor > 7, reason=\"UV needs Python 3.7 to fail\")\ndef test_fail_uv_python_version():\n\n    pip_package_folder = temp_folder(path_with_spaces=True)\n    _create_py_hello_world(pip_package_folder)\n    pip_package_folder = pip_package_folder.replace('\\\\', '/')\n\n    conanfile_pyenv = textwrap.dedent(f\"\"\"\n        from conan import ConanFile\n        from conan.tools.system import PyEnv\n        from conan.tools.layout import basic_layout\n        import platform\n        import os\n\n\n        class PyenvPackage(ConanFile):\n            name = \"pip_hello_test\"\n            version = \"0.1\"\n\n            def layout(self):\n                basic_layout(self)\n\n            def generate(self):\n                pip_env = PyEnv(self, py_version=\"3.11.86\")\n                pip_env.install([\"{pip_package_folder}\"])\n                pip_env.generate()\n\n            def build(self):\n                self.run(\"hello-world\")\n        \"\"\")\n\n    client = TestClient(path_with_spaces=False)\n    # FIXME: the python shebang inside vitual env packages fails when using path_with_spaces\n    client.save({\"pip/conanfile.py\": conanfile_pyenv})\n    client.run(\"build pip/conanfile.py\", assert_error=True)\n    assert \"needs Python >= 3.8\" in client.out\n\n\ndef test_build_deprecated_python_manager():\n    pip_package_folder = temp_folder(path_with_spaces=True)\n    _create_py_hello_world(pip_package_folder)\n    pip_package_folder = pip_package_folder.replace('\\\\', '/')\n\n    conanfile_pyenv = textwrap.dedent(f\"\"\"\n        from conan import ConanFile\n        from conan.tools.system import PipEnv\n        from conan.tools.layout import basic_layout\n\n        class PyenvPackage(ConanFile):\n            def layout(self):\n                basic_layout(self)\n\n            def generate(self):\n                pip = PipEnv(self)\n                pip.install([\"{pip_package_folder}\"])\n                pip.generate()\n\n            def build(self):\n                self.run(\"hello-world\")\n        \"\"\")\n\n    client = TestClient(path_with_spaces=False)\n    # FIXME: the python shebang inside vitual env packages fails when using path_with_spaces\n    client.save({\"pip/conanfile.py\": conanfile_pyenv})\n    client.run(\"build pip\")\n\n    assert \"WARN: deprecated: 'PipEnv()' is deprecated, use 'PyEnv()'\" in client.out\n    assert \"RUN: hello-world\" in client.out\n    assert \"Hello Test World!\" in client.out\n\n\n@pytest.mark.parametrize(\"verbosity\", [\"-verror\", \"-vstatus\"])\ndef test_pyenv_install_error_always_shown(verbosity):\n    conanfile_pyenv = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.system import PyEnv\n\n        class PyenvPackage(ConanFile):\n            def generate(self):\n                pyenv = PyEnv(self)\n                pyenv.install([\"package_does_not_exist\"])\n        \"\"\")\n\n    client = TestClient(path_with_spaces=False)\n    client.save({\"conanfile.py\": conanfile_pyenv})\n    client.run(f\"build . {verbosity}\", assert_error=True)\n    assert \"package_does_not_exist\" in client.out\n    assert \"ERROR\" in client.out\n\n\ndef test_cmake_toolchain_configure_find_python():\n    client = TestClient(path_with_spaces=False)\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMakeToolchain\n        from conan.tools.system import PyEnv\n\n        class Pkg(ConanFile):\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n\n            def generate(self):\n                pyenv = PyEnv(self)\n                pyenv.generate()\n                tc = CMakeToolchain(self)\n                tc.cache_variables[\"Python_ROOT_DIR\"] = pyenv.env_dir\n                tc.cache_variables[\"Python_EXECUTABLE\"] = pyenv.env_exe\n                tc.cache_variables[\"Python_FIND_UNVERSIONED_NAMES\"] = \"FIRST\"\n                tc.cache_variables[\"Python_FIND_STRATEGY\"] = \"LOCATION\"\n                tc.cache_variables[\"Python_FIND_VIRTUALENV\"] = \"STANDARD\"\n                tc.cache_variables[\"Python_FIND_REGISTRY\"] = \"NEVER\"\n                tc.generate()\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"install .\")\n    presets = json.loads(client.load(\"CMakePresets.json\"))\n    cv = presets[\"configurePresets\"][0][\"cacheVariables\"]\n    assert \"Python_ROOT_DIR\" in cv\n    assert \"Python_EXECUTABLE\" in cv\n    assert \"\\\\\" not in cv[\"Python_ROOT_DIR\"]\n    assert \"\\\\\" not in cv[\"Python_EXECUTABLE\"]\n    assert \"conan_pyenv\" in cv[\"Python_ROOT_DIR\"]\n    assert cv[\"Python_FIND_UNVERSIONED_NAMES\"] == \"FIRST\"\n    assert cv[\"Python_FIND_STRATEGY\"] == \"LOCATION\"\n    assert cv[\"Python_FIND_VIRTUALENV\"] == \"STANDARD\"\n    assert cv[\"Python_FIND_REGISTRY\"] == \"NEVER\"\n"
  },
  {
    "path": "test/functional/tools/test_apple_tools.py",
    "content": "import platform\nimport re\nimport textwrap\nimport os\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\nfrom conan.tools.apple.apple import XCRun\nfrom conan.test.utils.mocks import ConanFileMock, MockSettings\nfrom conan.internal.util.runners import conan_run\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Requires Xcode\")\ndef test_xcrun():\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.apple import XCRun\n\n        class HelloConan(ConanFile):\n            name = \"hello\"\n            version = \"0.1\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            def build(self):\n                sdk_path = XCRun(self).sdk_path\n                self.output.info(sdk_path)\n        \"\"\")\n    client = TestClient(path_with_spaces=False)\n    client.save({\"conanfile.py\": conanfile}, clean_first=True)\n    client.run(\"create .\")\n    assert \"MacOSX\" in client.out\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Requires OSX and xcrun tool\")\ndef test_xcrun_sdks():\n    def _common_asserts(xcrun_):\n        assert xcrun_.cc.endswith('clang')\n        assert xcrun_.cxx.endswith('clang++')\n        assert xcrun_.ar.endswith('ar')\n        assert xcrun_.ranlib.endswith('ranlib')\n        assert xcrun_.strip.endswith('strip')\n        assert xcrun_.find('lipo').endswith('lipo')\n        assert os.path.isdir(xcrun_.sdk_path)\n\n    conanfile = ConanFileMock( runner=conan_run)\n    conanfile.settings = MockSettings(\n        {\"os\": \"Macos\",\n         \"arch\": \"x86\"})\n    xcrun = XCRun(conanfile)\n    _common_asserts(xcrun)\n\n    conanfile.settings = MockSettings(\n        {\"os\": \"iOS\",\n         \"arch\": \"x86\"})\n    xcrun = XCRun(conanfile, sdk='macosx')\n    _common_asserts(xcrun)\n    # Simulator\n    assert \"iPhoneOS\" not in xcrun.sdk_path\n\n    conanfile.settings = MockSettings(\n        {\"os\": \"iOS\",\n         \"os.sdk\": \"iphoneos\",\n         \"arch\": \"armv7\"})\n    xcrun = XCRun(conanfile)\n    _common_asserts(xcrun)\n    assert \"iPhoneOS\" in xcrun.sdk_path\n\n    conanfile.settings = MockSettings(\n        {\"os\": \"watchOS\",\n         \"os.sdk\": \"watchos\",\n         \"arch\": \"armv7\"})\n    xcrun = XCRun(conanfile)\n    _common_asserts(xcrun)\n    assert \"WatchOS\" in xcrun.sdk_path\n\n    # Default one\n    conanfile.settings = MockSettings({})\n    xcrun = XCRun(conanfile)\n    _common_asserts(xcrun)\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Requires Xcode\")\ndef test_xcrun_in_tool_requires():\n    # https://github.com/conan-io/conan/issues/12260\n    client = TestClient()\n    tool = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.apple import XCRun\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n            def package_info(self):\n                xcrun = XCRun(self{})\n                self.output.info(\"sdk: %s\" % xcrun.sdk_path)\n        \"\"\")\n    client.save({\"br.py\": tool.format(\", use_settings_target=True\")})\n    client.run(\"export br.py --name=br --version=0.1\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            tool_requires = \"br/0.1\"\n        \"\"\")\n\n    profile_ios = textwrap.dedent(\"\"\"\n        include(default)\n        [settings]\n        os=iOS\n        os.version=15.5\n        os.sdk=iphoneos\n        os.sdk_version=15.5\n        arch=armv8\n    \"\"\")\n\n    client.save({\"conanfile.py\": conanfile, \"profile_ios\": profile_ios})\n    client.run(\"create . --name=pkg --version=1.0 -pr:h=./profile_ios -pr:b=default --build='*'\")\n    assert re.search(\"sdk:.*iPhoneOS\", str(client.out))\n    assert not re.search(\"sdk:.*MacOSX\", str(client.out))\n\n    client.save({\"br.py\": tool.format(\"\")})\n    client.run(\"export br.py --name=br --version=0.1\")\n    client.run(\"create . --name=pkg --version=1.0 -pr:h=./profile_ios -pr:b=default --build='*'\")\n    assert not re.search(\"sdk:.*iPhoneOS\", str(client.out))\n    assert re.search(\"sdk:.*MacOSX\", str(client.out))\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Requires Xcode\")\ndef test_xcrun_in_required_by_tool_requires():\n    \"\"\"\n    ConanCenter case, most typical, openssl builds with autotools so needs the sysroot\n    and is a require by cmake so in the build context it needs the settings_build, not\n    the settings_target, that's why the use_settings_target default is False\n    \"\"\"\n    client = TestClient()\n\n    openssl = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.apple import XCRun\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            def build(self):\n                xcrun = XCRun(self)\n                self.output.info(\"sdk for building openssl: %s\" % xcrun.sdk_path)\n        \"\"\")\n\n    consumer = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            tool_requires = \"cmake/1.0\"\n        \"\"\")\n\n    profile_ios = textwrap.dedent(\"\"\"\n        include(default)\n        [settings]\n        os=iOS\n        os.version=15.5\n        os.sdk=iphoneos\n        os.sdk_version=15.5\n        arch=armv8\n    \"\"\")\n\n    client.save({\"cmake.py\": GenConanfile(\"cmake\", \"1.0\").with_requires(\"openssl/1.0\"),\n                 \"openssl.py\": openssl,\n                 \"consumer.py\": consumer,\n                 \"profile_ios\": profile_ios})\n\n    client.run(\"export openssl.py --name=openssl --version=1.0\")\n    client.run(\"export cmake.py\")\n    client.run(\"create consumer.py --name=consumer --version=1.0 -pr:h=./profile_ios -pr:b=default --build='*'\")\n\n    assert re.search(\"sdk for building openssl:.*MacOSX\", str(client.out))\n"
  },
  {
    "path": "test/functional/tools/test_files.py",
    "content": "import os\nimport textwrap\n\nimport patch_ng\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.file_server import TestFileServer\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import save, load\n\n\nclass MockPatchset:\n    apply_args = None\n\n    def apply(self, strip=0, root=None, fuzz=False):\n        self.apply_args = (root, strip, fuzz)\n        return True\n\n\n@pytest.fixture\ndef mock_patch_ng(monkeypatch):\n    mock = MockPatchset()\n\n    def mock_fromstring(string):\n        mock.string = string\n        return mock\n\n    monkeypatch.setattr(patch_ng, \"fromfile\", lambda _: mock)\n    monkeypatch.setattr(patch_ng, \"fromstring\", mock_fromstring)\n    return mock\n\n\nclass TestConanToolFiles:\n\n    def test_imports(self):\n        conanfile = GenConanfile().with_import(\"from conan.tools.files import load, save, \"\n                                               \"mkdir, download, get, ftp_download\")\n        client = TestClient(light=True)\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"install .\")\n\n    def test_load_save_mkdir(self):\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import load, save, mkdir\n\n            class Pkg(ConanFile):\n                name = \"mypkg\"\n                version = \"1.0\"\n                def source(self):\n                    mkdir(self, \"myfolder\")\n                    save(self, \"./myfolder/myfile\", \"some_content\")\n                    assert load(self, \"./myfolder/myfile\") == \"some_content\"\n            \"\"\")\n        client = TestClient(light=True)\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"source .\")\n\n    def test_download(self):\n        client = TestClient(light=True)\n        file_server = TestFileServer()\n        client.servers[\"file_server\"] = file_server\n        save(os.path.join(file_server.store, \"myfile.txt\"), \"some content\")\n\n        profile = textwrap.dedent(\"\"\"\\\n            [conf]\n            tools.files.download:retry=1\n            tools.files.download:retry_wait=0\n            \"\"\")\n\n        conanfile = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.files import download\n\n            class Pkg(ConanFile):\n                name = \"mypkg\"\n                version = \"1.0\"\n                def source(self):\n                    download(self, \"{}/myfile.txt\", \"myfile.txt\")\n                    assert os.path.exists(\"myfile.txt\")\n            \"\"\".format(file_server.fake_url))\n\n        client.save({\"conanfile.py\": conanfile})\n        client.save({\"profile\": profile})\n        client.run(\"create . -pr=profile\")\n\n    def test_download_export_sources(self):\n        client = TestClient(light=True)\n        file_server = TestFileServer()\n        client.servers[\"file_server\"] = file_server\n        save(os.path.join(file_server.store, \"myfile.txt\"), \"some content\")\n        save(os.path.join(file_server.store, \"myfile2.txt\"), \"some content\")\n\n        conanfile = textwrap.dedent(f\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.files import download\n\n            class Pkg(ConanFile):\n                name = \"mypkg\"\n                version = \"1.0\"\n                def export(self):\n                    download(self, \"{file_server.fake_url}/myfile.txt\", \"myfile.txt\")\n                    assert os.path.exists(\"myfile.txt\")\n                def export_sources(self):\n                    download(self, \"{file_server.fake_url}/myfile2.txt\", \"myfile2.txt\")\n                    assert os.path.exists(\"myfile2.txt\")\n            \"\"\")\n\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create .\")\n\n\ndef test_patch(mock_patch_ng):\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import patch\n\n        class Pkg(ConanFile):\n            name = \"mypkg\"\n            version = \"1.0\"\n\n            def build(self):\n                patch(self, patch_file='path/to/patch-file', patch_type='security')\n        \"\"\")\n\n    client = TestClient(light=True)\n    client.save({\"conanfile.py\": conanfile})\n    client.run('create .')\n\n    # Note: This cannot exist anymore, because the path is moved when prev is computed\n    # assert os.path.exists(mock_patch_ng.apply_args[0])\n    assert mock_patch_ng.apply_args[1:] == (0, False)\n    assert 'mypkg/1.0: Apply patch (security)' in str(client.out)\n\n\n@pytest.mark.parametrize(\"no_copy_source\", [False, True])\ndef test_patch_real(no_copy_source):\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import patch, save, load\n\n        class Pkg(ConanFile):\n            name = \"mypkg\"\n            version = \"1.0\"\n            exports_sources = \"*\"\n            no_copy_source = %s\n\n            def layout(self):\n                self.folders.source = \"src\"\n                self.folders.build = \"build\"\n\n            def source(self):\n                save(self, \"myfile.h\", \"//dummy contents\")\n                patch(self, patch_file=\"patches/mypatch_h\", patch_type=\"security\")\n                self.output.info(\"SOURCE: {}\".format(load(self, \"myfile.h\")))\n\n            def build(self):\n                save(self, \"myfile.cpp\", \"//dummy contents\")\n                if self.no_copy_source:\n                    patch_file = os.path.join(self.source_folder, \"../patches/mypatch_cpp\")\n                else:\n                    patch_file = \"patches/mypatch_cpp\"\n                patch(self, patch_file=patch_file, patch_type=\"security\",\n                      base_path=self.build_folder)\n                self.output.info(\"BUILD: {}\".format(load(self, \"myfile.cpp\")))\n        \"\"\" % no_copy_source)\n\n    client = TestClient(light=True)\n    patch_contents = textwrap.dedent(\"\"\"\\\n        --- myfile.{ext}\n        +++ myfile.{ext}\n        @@ -1 +1 @@\n        -//dummy contents\n        +//smart contents\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile,\n                 \"patches/mypatch_h\": patch_contents.format(ext=\"h\"),\n                 \"patches/mypatch_cpp\": patch_contents.format(ext=\"cpp\")})\n    client.run('create .')\n    assert \"mypkg/1.0: Apply patch (security)\" in client.out\n    assert \"mypkg/1.0: SOURCE: //smart contents\" in client.out\n    assert \"mypkg/1.0: BUILD: //smart contents\" in client.out\n\n    # Test local source too\n    client.run(\"install .\")\n    client.run(\"source .\")\n    assert \"conanfile.py (mypkg/1.0): Apply patch (security)\" in client.out\n    assert \"conanfile.py (mypkg/1.0): SOURCE: //smart contents\" in client.out\n    client.run(\"build .\")\n    assert \"conanfile.py (mypkg/1.0): Apply patch (security)\" in client.out\n    assert \"conanfile.py (mypkg/1.0): BUILD: //smart contents\" in client.out\n\n\ndef test_apply_conandata_patches(mock_patch_ng):\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import apply_conandata_patches\n\n        class Pkg(ConanFile):\n            name = \"mypkg\"\n            version = \"1.11.0\"\n\n            def layout(self):\n                self.folders.source = \"source_subfolder\"\n\n            def build(self):\n                apply_conandata_patches(self)\n        \"\"\")\n    conandata_yml = textwrap.dedent(\"\"\"\n        patches:\n          \"1.11.0\":\n            - patch_file: \"patches/0001-buildflatbuffers-cmake.patch\"\n            - patch_file: \"patches/0002-implicit-copy-constructor.patch\"\n              patch_type: backport\n              patch_source: https://github.com/google/flatbuffers/pull/5650\n              patch_description: Needed to build with modern clang compilers.\n          \"1.12.0\":\n            - patch_file: \"patches/0001-buildflatbuffers-cmake.patch\"\n    \"\"\")\n\n    client = TestClient(light=True)\n    client.save({'conanfile.py': conanfile,\n                 'conandata.yml': conandata_yml})\n    client.run('create .')\n\n    assert mock_patch_ng.apply_args[0].endswith('source_subfolder')\n    assert mock_patch_ng.apply_args[1:] == (0, False)\n\n    assert 'mypkg/1.11.0: Apply patch (backport): Needed to build with modern' \\\n           ' clang compilers.' in str(client.out)\n\n    # Test local methods\n    client.run(\"install .\")\n    client.run(\"build .\")\n\n    assert 'conanfile.py (mypkg/1.11.0): Apply patch (backport): Needed to build with modern' \\\n           ' clang compilers.' in str(client.out)\n\n\ndef test_apply_conandata_patches_relative_base_path(mock_patch_ng):\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import apply_conandata_patches\n\n        class Pkg(ConanFile):\n            name = \"mypkg\"\n            version = \"1.11.0\"\n\n            def layout(self):\n                self.folders.source = \"source_subfolder\"\n\n            def build(self):\n                apply_conandata_patches(self)\n        \"\"\")\n    conandata_yml = textwrap.dedent(\"\"\"\n        patches:\n          \"1.11.0\":\n            - patch_file: \"patches/0001-buildflatbuffers-cmake.patch\"\n              base_path: \"relative_dir\"\n    \"\"\")\n\n    client = TestClient(light=True)\n    client.save({'conanfile.py': conanfile,\n                 'conandata.yml': conandata_yml})\n    client.run('create .')\n\n    assert mock_patch_ng.apply_args[0].endswith(os.path.join('source_subfolder', \"relative_dir\"))\n    assert mock_patch_ng.apply_args[1:] == (0, False)\n\n\ndef test_no_patch_file_entry():\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import apply_conandata_patches\n\n        class Pkg(ConanFile):\n            name = \"mypkg\"\n            version = \"1.11.0\"\n\n            def layout(self):\n                self.folders.source = \"source_subfolder\"\n\n            def build(self):\n                apply_conandata_patches(self)\n        \"\"\")\n    conandata_yml = textwrap.dedent(\"\"\"\n        patches:\n          \"1.11.0\":\n            - wrong_entry: \"patches/0001-buildflatbuffers-cmake.patch\"\n          \"1.12.0\":\n            - patch_file: \"patches/0001-buildflatbuffers-cmake.patch\"\n    \"\"\")\n\n    client = TestClient(light=True)\n    client.save({'conanfile.py': conanfile,\n                 'conandata.yml': conandata_yml})\n    client.run('create .', assert_error=True)\n\n    assert \"The 'conandata.yml' file needs a 'patch_file' or 'patch_string' entry for every patch\" \\\n           \" to be applied\" in str(client.out)\n\n\ndef test_patch_string_entry(mock_patch_ng):\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import apply_conandata_patches\n\n        class Pkg(ConanFile):\n            name = \"mypkg\"\n            version = \"1.11.0\"\n\n            def build(self):\n                apply_conandata_patches(self)\n        \"\"\")\n    conandata_yml = textwrap.dedent(\"\"\"\n        patches:\n          \"1.11.0\":\n            - patch_string: mock patch data\n              patch_type: string\n    \"\"\")\n\n    client = TestClient(light=True)\n    client.save({'conanfile.py': conanfile,\n                 'conandata.yml': conandata_yml})\n    client.run('create .')\n\n    # Note: This cannot exist anymore, because the path is moved when prev is computed\n    # assert os.path.exists(mock_patch_ng.apply_args[0])\n    assert mock_patch_ng.apply_args[1:] == (0, False)\n    assert 'mock patch data' == mock_patch_ng.string.decode('utf-8')\n    assert 'mypkg/1.11.0: Apply patch (string)' in str(client.out)\n\n\ndef test_relate_base_path_all_versions(mock_patch_ng):\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import apply_conandata_patches\n\n        class Pkg(ConanFile):\n            name = \"mypkg\"\n            version = \"1.0\"\n\n            def layout(self):\n                self.folders.source = \"source_subfolder\"\n\n            def build(self):\n                apply_conandata_patches(self)\n        \"\"\")\n    conandata_yml = textwrap.dedent(\"\"\"\n        patches:\n          - patch_file: \"patches/0001-buildflatbuffers-cmake.patch\"\n            base_path: \"relative_dir\"\n    \"\"\")\n\n    client = TestClient(light=True)\n    client.save({'conanfile.py': conanfile,\n                 'conandata.yml': conandata_yml})\n    client.run('create .')\n\n    assert mock_patch_ng.apply_args[0].endswith(os.path.join('source_subfolder', \"relative_dir\"))\n    assert mock_patch_ng.apply_args[1:] == (0, False)\n\n\ndef test_export_conandata_patches():\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import export_conandata_patches, load\n\n        class Pkg(ConanFile):\n            name = \"mypkg\"\n            version = \"1.0\"\n\n            def layout(self):\n                self.folders.source = \"source_subfolder\"\n\n            def export_sources(self):\n                export_conandata_patches(self)\n\n            def source(self):\n                self.output.info(load(self, os.path.join(self.export_sources_folder,\n                                                         \"patches/mypatch.patch\")))\n        \"\"\")\n    conandata_yml = textwrap.dedent(\"\"\"\n        patches:\n          - patch_file: \"patches/mypatch.patch\"\n    \"\"\")\n\n    client = TestClient(light=True)\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create .\", assert_error=True)\n    assert \"conandata.yml not defined\" in client.out\n    # Empty conandata\n    client.save({\"conandata.yml\": \"\"})\n    client.run(\"create .\", assert_error=True)\n    assert \"export_conandata_patches(): No patches defined in conandata\" in client.out\n    assert \"ERROR: mypkg/1.0: Error in source() method\" in client.out\n    # wrong patches\n    client.save({\"conandata.yml\": \"patches: 123\"})\n    client.run(\"create .\", assert_error=True)\n    assert \"conandata.yml 'patches' should be a list or a dict\" in client.out\n\n    # No patch found\n    client.save({\"conandata.yml\": conandata_yml})\n    client.run(\"create .\", assert_error=True)\n    assert \"Patch file does not exist: '\" in client.out\n\n    client.save({\"patches/mypatch.patch\": \"mypatch!!!\"})\n    client.run(\"create .\")\n    assert \"mypkg/1.0: mypatch!!!\" in client.out\n\n    conandata_yml = textwrap.dedent(\"\"\"\n        patches:\n            \"1.0\":\n                - patch_file: \"patches/mypatch.patch\"\n    \"\"\")\n    client.save({\"conandata.yml\": conandata_yml})\n    client.run(\"create .\")\n    assert \"mypkg/1.0: mypatch!!!\" in client.out\n\n\ndef test_export_conandata_patches_no_patches():\n    # Patch exists but has no contents, this used to hard crash\n    client = TestClient(light=True)\n    conandata_yml = textwrap.dedent(\"\"\"\n            patches:\n                \"1.0\":\n                    # - patch_file: \"patches/mypatch.patch\"\n        \"\"\")\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import export_conandata_patches, apply_conandata_patches\n        class Pkg(ConanFile):\n            name = \"mypkg\"\n            version = \"1.0\"\n\n            def export_sources(self):\n                export_conandata_patches(self)\n\n            def build(self):\n                apply_conandata_patches(self)\n    \"\"\")\n    client.save({\"conandata.yml\": conandata_yml, \"conanfile.py\": conanfile})\n    client.run(\"create .\")\n    assert \"No patches defined for version 1.0 in conandata.yml\" in client.out\n\n\n@pytest.mark.parametrize(\"trim\", [True, False])\ndef test_export_conandata_patches_extra_origin(trim):\n    conanfile = textwrap.dedent(f\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import export_conandata_patches, load, trim_conandata\n\n        class Pkg(ConanFile):\n            name = \"mypkg\"\n            version = \"1.0\"\n\n            def export(self):\n                if {trim}:\n                    trim_conandata(self)\n\n            def layout(self):\n                self.folders.source = \"source_subfolder\"\n\n            def export_sources(self):\n                export_conandata_patches(self)\n\n            def source(self):\n                self.output.info(load(self, os.path.join(self.export_sources_folder,\n                                                         \"patches/mypatch.patch\")))\n        \"\"\")\n    client = TestClient(light=True)\n    patches_folder = temp_folder()\n    conandata_yml = textwrap.dedent(\"\"\"\n        patches:\n            \"1.0\":\n                - patch_file: \"patches/mypatch.patch\"\n        \"\"\")\n    save(os.path.join(patches_folder, \"mypkg\", \"conandata.yml\"), conandata_yml)\n    save(os.path.join(patches_folder, \"mypkg\", \"patches\", \"mypatch.patch\"), \"mypatch!!!\")\n\n    pkg_conandata = textwrap.dedent(\"\"\"\\\n        patches:\n            \"1.1\":\n                - patch_file: \"patches/mypatch2.patch\"\n    \"\"\")\n    client.save({\"conanfile.py\": conanfile,\n                 \"conandata.yml\": pkg_conandata,\n                 \"patches/mypatch2.patch\": \"\"})\n    client.run(f'create . -cc core.sources.patch:extra_path=\"{patches_folder}\"')\n    assert \"mypkg/1.0: Applying extra patches\" in client.out\n    assert \"mypkg/1.0: mypatch!!!\" in client.out\n\n    conandata = load(client.exported_layout().conandata())\n    assert \"1.0\" in conandata\n    assert \"patch_file: patches/mypatch.patch\" in conandata\n\n    if trim:\n        assert \"1.1\" not in conandata\n    else:\n        assert \"1.1\" in conandata\n"
  },
  {
    "path": "test/functional/tools_versions_test.py",
    "content": "import platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.sources import gen_function_cpp\nfrom test.conftest import tools_locations\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestToolsCustomVersions:\n\n    @pytest.mark.tool(\"cmake\")\n    def test_default_cmake(self):\n        client = TestClient()\n        client.run_command('cmake --version')\n        default_cmake_version = tools_locations[\"cmake\"][\"default\"]\n        assert \"cmake version {}\".format(default_cmake_version) in client.out\n\n    @pytest.mark.tool(\"cmake\", \"3.19\")\n    def test_custom_cmake_3_19(self):\n        client = TestClient()\n        client.run_command('cmake --version')\n        assert \"cmake version 3.19\" in client.out\n\n    @pytest.mark.tool(\"mingw64\")\n    @pytest.mark.tool(\"cmake\", \"3.19\")\n    @pytest.mark.skipif(platform.system() != \"Windows\",\n                        reason=\"Mingw test\")\n    def test_custom_cmake_mingw64(self):\n        client = TestClient()\n        client.run_command('cmake --version')\n        assert \"cmake version 3.19\" in client.out\n        main = gen_function_cpp(name=\"main\")\n        cmakelist = textwrap.dedent(\"\"\"\n            set(CMAKE_CXX_COMPILER_WORKS 1)\n            set(CMAKE_CXX_ABI_COMPILED 1)\n            cmake_minimum_required(VERSION 3.15)\n            project(App CXX)\n            add_executable(app app.cpp)\n            \"\"\")\n        client.save({\"CMakeLists.txt\": cmakelist, \"app.cpp\": main})\n        client.run_command('cmake . -G \"MinGW Makefiles\"')\n        client.run_command(\"cmake --build .\")\n"
  },
  {
    "path": "test/functional/util/__init__.py",
    "content": ""
  },
  {
    "path": "test/functional/util/test_cmd_args_to_string.py",
    "content": "import os\nimport platform\nimport textwrap\n\nimport pytest\n\nfrom conan.tools.build import cmd_args_to_string\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import chdir\nfrom conan.internal.util.runners import detect_runner\n\n\n@pytest.fixture(scope=\"module\")\ndef application_folder():\n    \"\"\"\n    This is building a simple C app to print the received arguments and see if the obtained\n    value is the expected once it is escaped by the Conan cmd_args_to_string tool\n    \"\"\"\n    t = TestClient()\n    main = textwrap.dedent(\"\"\"\n    #include<stdio.h>\n    int main(int argc, char *argv[]){\n        int i;\n        for(i=1;i<argc;i++){\n            printf(\"%s\\\\n\",argv[i]);\n        }\n        return 0;\n    }\n    \"\"\"\n    )\n\n    cmake = textwrap.dedent(\"\"\"\n    cmake_minimum_required(VERSION 3.15)\n    project(arg_printer C)\n\n    add_executable(arg_printer main.c)\n    \"\"\")\n\n    t.save({\"CMakeLists.txt\": cmake, \"main.c\": main})\n    t.run_command(\"cmake . -DCMAKE_BUILD_TYPE=Release\")\n    if platform.system() == \"Windows\":\n        t.run_command(\"cmake --build . --config Release\")\n    else:\n        t.run_command(\"cmake --build .\")\n\n    if platform.system() == \"Windows\":\n        return os.path.join(t.current_folder, \"Release\")\n    else:\n        return t.current_folder\n\n\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.skipif(platform.system() == \"Windows\", reason=\"Unix console parsing\")\n@pytest.mark.parametrize(\"_input, output\", [\n         (['.', 'foo'], '. foo'),\n         (['.', 'foo with sp'], \". 'foo with sp'\"),\n         (['.', 'foo \"with\" sp'], \". 'foo \\\"with\\\" sp'\"),\n         (['.', '\\'foo with sp\\''], '. \\'\\'\"\\'\"\\'foo with sp\\'\"\\'\"\\'\\''),\n         (['\".\"', 'foo'], '\\'\".\"\\' foo'),\n         (['\".', 'foo'], '\\'\".\\' foo'),\n])\ndef test_unix_cases(application_folder, _input, output):\n    _input = [\"arg_printer\"] + _input\n    output = \"arg_printer {}\".format(output)\n    assert cmd_args_to_string(_input) == output\n\n    # Check calling the exe that the arguments are the same we tried to input\n    with chdir(application_folder):\n        _, cmd_parsed_output = detect_runner(\"./{}\".format(output))\n        interpreted_args = cmd_parsed_output.splitlines()\n        real_args = _input[1:]\n        assert real_args == interpreted_args\n\n\n@pytest.mark.tool(\"cmake\")\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Windows console parsing\")\n@pytest.mark.parametrize(\"_input, output\", [\n         (['.', 'foo'], '. foo'),\n         (['\".\"', '\"foo\"'], r'\\\".\\\" \\\"foo\\\"'),\n         ([r'\\\".\\\"', '\"foo\"'], r'\\\\\\\".\\\\\\\" \\\"foo\\\"'),\n         (['path with spaces/foo', 'var'], '\"path with spaces/foo\" var'),\n         ([r'c:\\path with spaces\\foo', '%var$:.'], r'\"c:\\path with spaces\\foo\" %var$:.'),\n])\ndef test_windows_cases(application_folder, _input, output):\n    from subprocess import list2cmdline\n    _input = [\"arg_printer.exe\"] + _input\n    output = \"arg_printer.exe {}\".format(output)\n    assert list2cmdline(_input) == output\n    assert cmd_args_to_string(_input) == output\n\n    # Check calling the exe that the arguments are the same we tried to input\n    with chdir(application_folder):\n        _, cmd_parsed_output = detect_runner(output)\n        interpreted_args = cmd_parsed_output.splitlines()\n        real_args = _input[1:]\n        assert real_args == interpreted_args\n"
  },
  {
    "path": "test/functional/util/tools_test.py",
    "content": "import os\nimport platform\nfrom shutil import which\n\nimport pytest\n\nfrom conan.internal.api.detect.detect_vs import vswhere\nfrom conan.errors import ConanException\nfrom conan.test.utils.env import environment_update\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Visual Studio\")\n@pytest.mark.tool(\"visual_studio\")\nclass TestVisualStudioTools:\n\n    def test_vswhere_not_found(self):\n        \"\"\"\n        Locate vswhere in PATH or in ProgramFiles\n        \"\"\"\n        # vswhere not found\n        with environment_update({\"ProgramFiles\": None, \"ProgramFiles(x86)\": None, \"PATH\": \"\"}):\n            with pytest.raises(ConanException) as e:\n                vswhere()\n            assert \"Cannot locate vswhere\" in str(e.value)\n\n    def test_vswhere_path(self):\n        # vswhere in ProgramFiles but not in PATH\n        program_files = os.environ.get(\"ProgramFiles(x86)\") or os.environ.get(\"ProgramFiles\")\n        vswhere_path = None\n        if program_files:\n            expected_path = os.path.join(program_files, \"Microsoft Visual Studio\", \"Installer\",\n                                         \"vswhere.exe\")\n            if os.path.isfile(expected_path):\n                vswhere_path = expected_path\n                with environment_update({\"PATH\": \"\"}):\n                    assert vswhere()\n\n        # vswhere in PATH but not in ProgramFiles\n        env = {\"ProgramFiles\": None, \"ProgramFiles(x86)\": None}\n        env.update({\"PATH\": os.path.dirname(vswhere_path)})\n        with environment_update(env):\n            assert vswhere()\n"
  },
  {
    "path": "test/functional/utils.py",
    "content": "from conan.tools.microsoft.visual import vcvars_command\n\n\ndef check_vs_runtime(artifact, client, vs_version, build_type, architecture=\"amd64\",\n                     static_runtime=False, subsystem=None):\n    vcvars = vcvars_command(version=vs_version, architecture=architecture)\n    normalized_path = artifact.replace(\"/\", \"\\\\\")\n    static = artifact.endswith(\".a\") or artifact.endswith(\".lib\")\n    if not static:\n        cmd = ('%s && dumpbin /nologo /dependents \"%s\"' % (vcvars, normalized_path))\n        client.run_command(cmd)\n        if subsystem:\n            assert \"KERNEL32.dll\" in client.out\n            if subsystem in (\"mingw32\", \"mingw64\"):\n                assert \"msvcrt.dll\" in client.out\n                if static_runtime:\n                    assert \"libstdc++-6.dll\" not in client.out\n                else:\n                    assert \"libstdc++-6.dll\" in client.out\n                if subsystem == \"mingw32\":\n                    if static_runtime:\n                        assert \"libgcc_s_dw2-1.dll\" not in client.out\n                    else:\n                        assert \"libgcc_s_dw2-1.dll\" in client.out\n            elif subsystem == \"msys2\":\n                assert \"msys-2.0.dll\" in client.out\n                if static_runtime:\n                    assert \"msys-stdc++-6.dll\" not in client.out\n                else:\n                    assert \"msys-stdc++-6.dll\" in client.out\n            elif subsystem == \"cygwin\":\n                assert \"cygwin1.dll\" in client.out\n                if static_runtime:\n                    assert \"cygstdc++-6.dll\" not in client.out\n                else:\n                    assert \"cygstdc++-6.dll\" in client.out\n            elif subsystem == \"ucrt64\":\n                assert \"api-ms-win-crt-\" in client.out\n                if static_runtime:\n                    assert \"libstdc++-6.dll\" not in client.out\n                else:\n                    assert \"libstdc++-6.dll\" in client.out\n            else:\n                assert subsystem == \"clang64\"\n                assert \"api-ms-win-crt-\" in client.out\n                if static_runtime:\n                    assert \"libunwind.dll\" not in client.out\n                    assert \"libc++.dll\" not in client.out\n                else:\n                    # Latest clangs from subsystems no longer depend on libunwind\n                    assert \"libunwind.dll\" not in client.out\n                    assert \"libc++.dll\" in client.out\n        elif static_runtime:\n            assert \"KERNEL32.dll\" in client.out\n            assert \"MSVC\" not in client.out\n            assert \"VCRUNTIME\" not in client.out\n        else:\n            assert \"KERNEL32.dll\" in client.out\n            if build_type == \"Debug\":\n                assert \"ucrtbased\" in client.out\n            else:\n                assert \"api-ms-win-crt-\" in client.out\n            assert vs_version in [\"15\", \"16\", \"17\", \"18\"]  # UCRT\n            debug = \"D\" if build_type == \"Debug\" else \"\"\n            assert \"MSVCP140{}.dll\".format(debug) in client.out\n            assert \"VCRUNTIME140{}.dll\".format(debug) in client.out\n\n    else:  # A static library cannot be checked the same\n        client.run_command('{} && DUMPBIN /NOLOGO /DIRECTIVES \"{}\"'.format(vcvars, artifact))\n        if build_type == \"Debug\":\n            assert \"RuntimeLibrary=MDd_DynamicDebug\" in client.out\n        else:\n            assert \"RuntimeLibrary=MD_DynamicRelease\" in client.out\n\n\ndef check_exe_run(output, names, compiler, version, build_type, arch, cppstd, definitions=None,\n                  cxx11_abi=None, subsystem=None, extra_msg=\"\"):\n    output = str(output)\n    names = names if isinstance(names, list) else [names]\n\n    for name in names:\n        if extra_msg:  # For ``conan new`` templates\n            assert \"{} {} {}\".format(name, extra_msg, build_type) in output\n        else:\n            assert \"{}: {}\".format(name, build_type) in output\n        if compiler == \"msvc\":\n            if arch == \"x86\":\n                assert \"{} _M_IX86 defined\".format(name) in output\n            elif arch == \"x86_64\":\n                assert \"{} _M_X64 defined\".format(name) in output\n            elif arch == \"armv8\":\n                assert \"{} _M_ARM64 defined\".format(name) in output\n            else:\n                assert arch is None, \"checked don't know how to validate this architecture\"\n\n            if version:\n                assert \"{} _MSC_VER{}\".format(name, version) in output\n            if cppstd:\n                assert \"{} _MSVC_LANG20{}\".format(name, cppstd) in output\n\n        elif compiler in [\"gcc\", \"clang\", \"apple-clang\"]:\n            if compiler == \"gcc\":\n                assert \"{} __GNUC__\".format(name) in output\n                assert \"clang\" not in output\n                if version:  # FIXME: At the moment, the GCC version is not controlled, will change\n                    major, minor = version.split(\".\")[0:2]\n                    assert \"{} __GNUC__{}\".format(name, major) in output\n                    assert \"{} __GNUC_MINOR__{}\".format(name, minor) in output\n            elif compiler == \"clang\":\n                assert \"{} __clang_\".format(name) in output\n                if version:\n                    major, minor = version.split(\".\")[0:2]\n                    assert \"{} __clang_major__{}\".format(name, major) in output\n                    assert \"{} __clang_minor__{}\".format(name, minor) in output\n            elif compiler == \"apple-clang\":\n                assert \"{} __apple_build_version__\".format(name) in output\n                if version:\n                    major, minor = version.split(\".\")[0:2]\n                    assert \"{} __apple_build_version__{}{}\".format(name, major, minor) in output\n            if arch == \"x86\":\n                assert \"{} __i386__ defined\".format(name) in output\n            elif arch == \"x86_64\":\n                assert \"{} __x86_64__ defined\".format(name) in output\n            elif arch == \"armv8\":\n                assert \"{} __aarch64__ defined\".format(name) in output\n            else:\n                assert arch is None, \"checked don't know how to validate this architecture\"\n\n            if cppstd:\n                cppstd_value = {\"98\": \"199711\",\n                                \"11\": \"201103\",\n                                \"14\": \"201402\",\n                                \"17\": \"201703\"}[cppstd]\n                assert \"{} __cplusplus{}\".format(name, cppstd_value) in output\n\n            if cxx11_abi is not None:\n                assert \"{} _GLIBCXX_USE_CXX11_ABI {}\".format(name, cxx11_abi) in output\n\n        if definitions:\n            for k, v in definitions.items():\n                assert \"{}: {}\".format(k, v) in output\n\n        if subsystem:\n            if subsystem == \"msys2\":\n                assert \"__MSYS__\" in output\n                assert \"__CYGWIN__\" in output\n                assert \"MINGW\" not in output\n            elif subsystem in (\"mingw32\", \"mingw64\"):\n                assert \"__MINGW32__\" in output\n                assert \"__CYGWIN__\" not in output\n                assert \"__MSYS__\" not in output\n                if subsystem == \"mingw64\":\n                    assert \"__MINGW64__\" in output\n                else:\n                    assert \"MING64\" not in output\n            elif subsystem == \"cygwin\":\n                assert \"__CYGWIN__\" in output\n                assert \"__MINGW32__\" not in output\n                assert \"__MINGW64__\" not in output\n                assert \"__MSYS__\" not in output\n            else:\n                raise Exception(\"unknown subsystem {}\".format(subsystem))\n        else:\n            assert \"CYGWIN\" not in output\n            assert \"MINGW\" not in output\n            assert \"MSYS\" not in output\n"
  },
  {
    "path": "test/functional/workspace/__init__.py",
    "content": ""
  },
  {
    "path": "test/functional/workspace/test_workspace.py",
    "content": "import os\nimport platform\nimport shutil\n\nimport pytest\n\nfrom conan.api.subapi.workspace import WorkspaceAPI\nfrom conan.test.utils.mocks import ConanFileMock\nfrom conan.test.utils.tools import TestClient\nfrom conan.tools.files import replace_in_file\n\nWorkspaceAPI.TEST_ENABLED = \"will_break_next\"\n\n\n@pytest.mark.tool(\"cmake\")\ndef test_build():\n    # This is not using the meta-project at all\n    c = TestClient()\n    c.run(\"new cmake_lib -d name=mymath\")\n    c.run(\"create . -tf=\")\n\n    c.save({}, clean_first=True)\n    c.run(\"new workspace -d requires=mymath/0.1\")\n    c.run(\"workspace build\")\n    assert \"conanfile.py (app1/0.1): Calling build()\" in c.out\n    assert \"conanfile.py (app1/0.1): Running CMake.build()\" in c.out\n    # it works without failing\n\n\n# The workspace CMake needs at least 3.25 for find_package to work\n@pytest.mark.tool(\"cmake\", \"3.27\")\ndef test_metabuild():\n    # This is using the meta-project\n    c = TestClient()\n    c.run(\"new cmake_lib -d name=mymath\")\n    c.run(\"create . -tf=\")\n\n    c.save({}, clean_first=True)\n    c.run(\"new workspace -d requires=mymath/0.1\")\n    c.run(\"workspace super-install\")\n    assert os.path.exists(os.path.join(c.current_folder, \"CMakeUserPresets.json\"))\n    build_folder = \"build/Release\" if platform.system() != \"Windows\" else \"build\"\n    assert os.path.exists(os.path.join(c.current_folder, build_folder, \"generators\"))\n    config_preset = \"conan-default\" if platform.system() == \"Windows\" else \"conan-release\"\n    c.run_command(f\"cmake --preset {config_preset}\")\n    assert \"Conan: Target declared 'mymath::mymath'\" in c.out\n    assert \"Adding project: liba\" in c.out\n    assert \"Adding project: libb\" in c.out\n    assert \"Adding project: app1\" in c.out\n    c.run_command(\"cmake --build --preset conan-release\")\n    # it doesn't fail\n\n\n# The workspace CMake needs at least 3.25 for find_package to work\n@pytest.mark.tool(\"cmake\", \"3.27\")\ndef test_new_template_and_different_folder():\n    \"\"\"\n    Issue related: https://github.com/conan-io/conan/issues/18813\n    \"\"\"\n    c = TestClient()\n    c.run(\"new workspace\")\n    shutil.move(os.path.join(c.current_folder, \"liba\"), os.path.join(c.current_folder, \"libX\"))\n    replace_in_file(ConanFileMock(), os.path.join(c.current_folder, \"conanws.yml\"),\n                    \"  - path: liba\",\n                    \"  - path: libX\")\n    c.run(\"workspace super-install\")\n    config_preset = \"conan-default\" if platform.system() == \"Windows\" else \"conan-release\"\n    c.run_command(f\"cmake --preset {config_preset}\")  # it does not fail\n    assert \"Adding project: liba\" in c.out\n    assert \"Adding project: libb\" in c.out\n    assert \"Adding project: app1\" in c.out\n\n\n# The workspace CMake needs at least 3.25 for find_package to work\n@pytest.mark.tool(\"cmake\", \"3.27\")\ndef test_super_build_different_layouts():\n    \"\"\"\n    https://github.com/conan-io/conan/issues/18875\n    \"\"\"\n    c = TestClient()\n    c.run(\"new workspace\")\n    liba_src = os.path.join(c.current_folder, \"liba\", \"mysrc\")\n    os.makedirs(liba_src)\n    shutil.move(os.path.join(c.current_folder, \"liba\", \"CMakeLists.txt\"), liba_src)\n    shutil.move(os.path.join(c.current_folder, \"liba\", \"include\"), liba_src,)\n    shutil.move(os.path.join(c.current_folder, \"liba\", \"src\"), liba_src)\n    replace_in_file(ConanFileMock(), os.path.join(c.current_folder, \"liba\", \"conanfile.py\"),\n                    \"cmake_layout(self)\",\n                    \"cmake_layout(self, src_folder='mysrc')\")\n\n    c.run(\"workspace super-install\")\n\n    config_preset = \"conan-default\" if platform.system() == \"Windows\" else \"conan-release\"\n    c.run_command(f\"cmake --preset {config_preset}\")  # it does not fail\n    assert \"Adding project: liba\" in c.out\n    assert \"Adding project: libb\" in c.out\n    assert \"Adding project: app1\" in c.out\n"
  },
  {
    "path": "test/integration/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/build_requires/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/build_requires/build_requires_test.py",
    "content": "import json\nimport os\nimport platform\nimport re\nimport textwrap\n\nimport pytest\n\nfrom conan.test.utils.mocks import ConanFileMock\nfrom conan.tools.env.environment import environment_wrap_command\nfrom conan.test.utils.tools import TestClient, GenConanfile\n\n\n@pytest.fixture()\ndef client():\n    openssl = textwrap.dedent(r\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import save, chdir\n        class Pkg(ConanFile):\n            settings = \"build_type\"\n            def package(self):\n                with chdir(self, self.package_folder):\n                    echo = \"@echo off\\necho MYOPENSSL={}!!\".format(self.settings.build_type)\n                    save(self, \"bin/myopenssl.bat\", echo)\n                    save(self, \"bin/myopenssl.sh\", echo)\n                    os.chmod(\"bin/myopenssl.sh\", 0o777)\n            \"\"\")\n\n    cmake = textwrap.dedent(r\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import save, chdir\n        class Pkg(ConanFile):\n            type = \"application\"\n            settings = \"build_type\"\n            def requirements(self):\n                self.requires(\"openssl/1.0\", run=True)\n            def package(self):\n                with chdir(self, self.package_folder):\n                    echo = \"@echo off\\necho MYCMAKE={}!!\".format(self.settings.build_type)\n                    save(self, \"mycmake.bat\", echo + \"\\ncall myopenssl.bat\")\n                    save(self, \"mycmake.sh\", echo + \"\\n myopenssl.sh\")\n                    os.chmod(\"mycmake.sh\", 0o777)\n\n            def package_info(self):\n                # Custom buildenv not defined by cpp_info\n                self.buildenv_info.prepend_path(\"PATH\", self.package_folder)\n                self.buildenv_info.define(\"MYCMAKEVAR\", \"MYCMAKEVALUE!!\")\n            \"\"\")\n\n    gtest = textwrap.dedent(r\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import save, chdir\n        class Pkg(ConanFile):\n            settings = \"build_type\"\n            def package(self):\n                with chdir(self, self.package_folder):\n                    echo = \"@echo off\\necho MYGTEST={}!!\".format(self.settings.build_type)\n                    save(self, \"bin/mygtest.bat\", echo)\n                    save(self, \"bin/mygtest.sh\", echo)\n                    os.chmod(\"bin/mygtest.sh\", 0o777)\n\n            def package_info(self):\n                self.runenv_info.define(\"MYGTESTVAR\",\n                                        \"MyGTestValue{}\".format(self.settings.build_type))\n            \"\"\")\n    client = TestClient()\n    client.save({\"cmake/conanfile.py\": cmake,\n                 \"gtest/conanfile.py\": gtest,\n                 \"openssl/conanfile.py\": openssl})\n\n    client.run(\"create openssl --name=openssl --version=1.0\")\n    client.run(\"create cmake --name=mycmake --version=1.0\")\n    client.run(\"create gtest --name=mygtest --version=1.0\")\n\n    myrunner_bat = \"@echo off\\necho MYGTESTVAR=%MYGTESTVAR%!!\\n\"\n    myrunner_sh = \"echo MYGTESTVAR=$MYGTESTVAR!!\\n\"\n    client.save({\"myrunner.bat\": myrunner_bat,\n                 \"myrunner.sh\": myrunner_sh}, clean_first=True)\n    os.chmod(os.path.join(client.current_folder, \"myrunner.sh\"), 0o777)\n    return client\n\n\ndef test_conanfile_txt(client):\n    # conanfile.txt -(br)-> cmake\n    client.save({\"conanfile.txt\": \"[tool_requires]\\nmycmake/1.0\"}, clean_first=True)\n    client.run(\"install . -s:h build_type=Debug\")\n\n    assert \"mycmake/1.0\" in client.out\n    assert \"openssl/1.0\" in client.out\n    ext = \"bat\" if platform.system() == \"Windows\" else \"sh\"  # TODO: Decide on logic .bat vs .sh\n    cmd = environment_wrap_command(ConanFileMock(), \"conanbuild\", client.current_folder, \"mycmake.{}\".format(ext))\n    client.run_command(cmd)\n\n    assert \"MYCMAKE=Release!!\" in client.out\n    assert \"MYOPENSSL=Release!!\" in client.out\n\n\ndef test_complete(client):\n    app = textwrap.dedent(\"\"\"\n        import platform\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            requires = \"openssl/1.0\"\n            build_requires = \"mycmake/1.0\"\n            settings = \"os\"\n\n            def build_requirements(self):\n                self.test_requires(\"mygtest/1.0\", run=True)\n\n            def build(self):\n                mybuild_cmd = \"mycmake.bat\" if platform.system() == \"Windows\" else \"mycmake.sh\"\n                self.run(mybuild_cmd)\n                mytest_cmd = \"mygtest.bat\" if platform.system() == \"Windows\" else \"mygtest.sh\"\n                self.run(mytest_cmd, env=\"conanrun\")\n       \"\"\")\n\n    client.save({\"conanfile.py\": app})\n    client.run(\"install . -s build_type=Debug --build=missing\")\n    # Run the BUILD environment\n    ext = \"bat\" if platform.system() == \"Windows\" else \"sh\"  # TODO: Decide on logic .bat vs .sh\n    cmd = environment_wrap_command(ConanFileMock(), \"conanbuild\", client.current_folder,\n                                   cmd=\"mycmake.{}\".format(ext))\n    client.run_command(cmd)\n    assert \"MYCMAKE=Release!!\" in client.out\n    assert \"MYOPENSSL=Release!!\" in client.out\n\n    # Run the RUN environment\n    cmd = environment_wrap_command(ConanFileMock(), \"conanrun\", client.current_folder,\n                                   cmd=\"mygtest.{ext} && .{sep}myrunner.{ext}\".format(ext=ext,\n                                                                                      sep=os.sep))\n    client.run_command(cmd)\n    assert \"MYGTEST=Debug!!\" in client.out\n    assert \"MYGTESTVAR=MyGTestValueDebug!!\" in client.out\n\n    client.run(\"build . -s:h build_type=Debug\")\n    assert \"MYCMAKE=Release!!\" in client.out\n    assert \"MYOPENSSL=Release!!\" in client.out\n    assert \"MYGTEST=Debug!!\" in client.out\n\n\ndef test_dependents_new_buildenv():\n    client = TestClient()\n    boost = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Boost(ConanFile):\n            def package_info(self):\n                self.buildenv_info.define_path(\"PATH\", \"myboostpath\")\n        \"\"\")\n    other = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Other(ConanFile):\n            def requirements(self):\n                self.requires(\"boost/1.0\")\n\n            def package_info(self):\n                self.buildenv_info.append_path(\"PATH\", \"myotherpath\")\n                self.buildenv_info.prepend_path(\"PATH\", \"myotherprepend\")\n        \"\"\")\n    consumer = textwrap.dedent(\"\"\"\n       from conan import ConanFile\n       from conan.tools.env import VirtualBuildEnv\n       import os\n       class Lib(ConanFile):\n           requires = {}\n           def generate(self):\n               build_env = VirtualBuildEnv(self).vars()\n               with build_env.apply():\n                   self.output.info(\"LIB PATH %s\" % os.getenv(\"PATH\"))\n       \"\"\")\n    client.save({\"boost/conanfile.py\": boost,\n                 \"other/conanfile.py\": other,\n                 \"consumer/conanfile.py\": consumer.format('\"boost/1.0\", \"other/1.0\"'),\n                 \"profile_define\": \"[buildenv]\\nPATH=(path)profilepath\",\n                 \"profile_append\": \"[buildenv]\\nPATH+=(path)profilepath\",\n                 \"profile_prepend\": \"[buildenv]\\nPATH=+(path)profilepath\"})\n    client.run(\"create boost --name=boost --version=1.0\")\n    client.run(\"create other --name=other --version=1.0\")\n    client.run(\"install consumer\")\n    result = os.pathsep.join([\"myotherprepend\", \"myboostpath\", \"myotherpath\"])\n    assert \"LIB PATH {}\".format(result) in client.out\n\n    # Now test if we declare in different order, still topological order should be respected\n    client.save({\"consumer/conanfile.py\": consumer.format('\"other/1.0\", \"boost/1.0\"')})\n    client.run(\"install consumer\")\n    assert \"LIB PATH {}\".format(result) in client.out\n\n    client.run(\"install consumer -pr=profile_define\")\n    assert \"LIB PATH profilepath\" in client.out\n    client.run(\"install consumer -pr=profile_append\")\n    result = os.pathsep.join([\"myotherprepend\", \"myboostpath\", \"myotherpath\", \"profilepath\"])\n    assert \"LIB PATH {}\".format(result) in client.out\n    client.run(\"install consumer -pr=profile_prepend\")\n    result = os.pathsep.join([\"profilepath\", \"myotherprepend\", \"myboostpath\", \"myotherpath\"])\n    assert \"LIB PATH {}\".format(result) in client.out\n\n\ndef test_tool_requires_conanfile_txt():\n    client = TestClient(light=True)\n    client.save({\"conanfile.py\": GenConanfile()})\n\n    build_req = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class BuildReqConan(ConanFile):\n            pass\n        \"\"\")\n\n    client.save({\"conanfile.py\": build_req})\n    client.run(\"export . --name=build_req --version=1.0 --user=test --channel=test\")\n\n    consumer = textwrap.dedent(\"\"\"\n                [tool_requires]\n                build_req/1.0@test/test\n            \"\"\")\n    client.save({\"conanfile.txt\": consumer}, clean_first=True)\n    client.run(\"install . --build=missing\")\n    assert \"build_req/1.0@test/test: Created package\" in client.out\n\n\ndef test_profile_override_conflict():\n    client = TestClient(light=True)\n\n    test = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Lib(ConanFile):\n\n            def requirements(self):\n                self.tool_requires(self.tested_reference_str)\n\n            def test(self):\n                pass\n        \"\"\")\n    client.save({\"conanfile.py\": GenConanfile(\"protoc\"),\n                 \"test_package/conanfile.py\": test,\n                 \"profile\": \"[tool_requires]\\nprotoc/0.1\"})\n    client.run(\"create . --version 0.1 -pr=profile\")\n    client.run(\"create . --version 0.2 -pr=profile\")\n    assert \"protoc/0.1: Already installed!\" in client.out\n    assert \"protoc/0.2 (test package)\" in client.out\n    assert \"WARN: The package created was 'protoc/0.1' but the reference being tested \" \\\n           \"is 'protoc/0.2'\" in client.out\n\n\ndef test_both_context_options_error():\n    # https://github.com/conan-io/conan/issues/11385\n    c = TestClient()\n    pkg = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            settings = \"arch\"\n            options = {\"neon\": [True, \"check\", False]}\n            default_options = {\"neon\": True}\n\n            def config_options(self):\n                if \"arm\" not in self.settings.arch:\n                    del self.options.neon\n            \"\"\")\n    c.save({\"pkg/conanfile.py\": pkg,\n            \"consumer/conanfile.py\": GenConanfile().with_requires(\"pkg/0.1\")\n                                                   .with_build_requires(\"pkg/0.1\")})\n    c.run(\"export pkg\")\n    c.run(\"install consumer -s:b arch=x86_64 -s:h arch=armv8 --build=missing\")\n    # This failed in Conan 1.X, but now it works\n    c.assert_listed_binary({\"pkg/0.1\": (\"a0a41a189feabff576a535d071858191b90beceb\", \"Build\")})\n    c.assert_listed_binary({\"pkg/0.1\": (\"62e589af96a19807968167026d906e63ed4de1f5\", \"Build\")},\n                           build=True)\n    assert \"Finalizing install\" in c.out\n\n\ndef test_conditional_require_context():\n    \"\"\" test that we can condition on the context to define a dependency\n    \"\"\"\n    c = TestClient(light=True)\n    pkg = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n           name = \"pkg\"\n           version = \"0.1\"\n           def requirements(self):\n               if self.context == \"host\":\n                   self.requires(\"dep/1.0\")\n           \"\"\")\n    c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"1.0\"),\n            \"consumer/conanfile.py\": pkg})\n    c.run(\"create dep\")\n    c.run(\"create consumer\")\n    c.assert_listed_require({\"dep/1.0\": \"Cache\"})\n    c.run(\"create consumer --build-require\")\n    assert \"dep/1.0\" not in c.out\n\n\nclass TestBuildTrackHost:\n\n    def test_overriden_host_but_not_build(self):\n        \"\"\"\n        Making the ``tool_requires(..., visible=True)`` works, and allows overriding, but\n        propagates the build-requirement to protobuf/protoc down the graph, and VirtualBuildEnv\n        will put ``protoc`` from it in the PATH. Not a problem in majority of cases, but not the\n        cleanest\n        \"\"\"\n        c = TestClient(light=True)\n        pkg = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class ProtoBuf(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                def requirements(self):\n                    self.requires(\"protobuf/1.0\")\n                def build_requirements(self):\n                    self.tool_requires(\"protobuf/1.0\", visible=True)\n            \"\"\")\n        c.save({\"protobuf/conanfile.py\": GenConanfile(\"protobuf\"),\n                \"pkg/conanfile.py\": pkg,\n                \"app/conanfile.py\": GenConanfile().with_requires(\"pkg/0.1\")\n                                                  .with_requirement(\"protobuf/1.1\", override=True)\n                                                  .with_build_requirement(\"protobuf/1.1\",\n                                                                          override=True)})\n        c.run(\"create protobuf --version=1.0\")\n        c.run(\"create protobuf --version=1.1\")\n        c.run(\"create pkg\")\n        c.run(\"install app\")\n        c.assert_listed_require({\"protobuf/1.1\": \"Cache\"})\n        c.assert_listed_require({\"protobuf/1.1\": \"Cache\"}, build=True)\n\n    def test_overriden_host_version(self):\n        \"\"\"\n        Make the tool_requires follow the regular require with the expression \"<host_version>\"\n        \"\"\"\n        c = TestClient(light=True)\n        pkg = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class ProtoBuf(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                def requirements(self):\n                    self.requires(\"protobuf/1.0\")\n                def build_requirements(self):\n                    self.tool_requires(\"protobuf/<host_version>\")\n            \"\"\")\n        c.save({\"protobuf/conanfile.py\": GenConanfile(\"protobuf\"),\n                \"pkg/conanfile.py\": pkg,\n                \"app/conanfile.py\": GenConanfile().with_requires(\"pkg/0.1\")\n                                                  .with_requirement(\"protobuf/1.1\", override=True)})\n        c.run(\"create protobuf --version=1.0\")\n        c.run(\"create protobuf --version=1.1\")\n        c.run(\"create pkg\")\n        c.run(\"install pkg\")  # make sure it doesn't crash\n        c.run(\"install app\")\n        c.assert_listed_require({\"protobuf/1.1\": \"Cache\"})\n        c.assert_listed_require({\"protobuf/1.1\": \"Cache\"}, build=True)\n        # verify locks work\n        c.run(\"lock create app\")\n        lock = json.loads(c.load(\"app/conan.lock\"))\n        build_requires = lock[\"build_requires\"]\n        assert len(build_requires) == 1\n        assert \"protobuf/1.1\" in build_requires[0]\n        # lock can be used\n        c.run(\"install app --lockfile=app/conan.lock\")\n        c.assert_listed_require({\"protobuf/1.1\": \"Cache\"}, build=True)\n\n    def test_overriden_host_version_version_range(self):\n        \"\"\"\n        same as above, but using version ranges instead of overrides\n        \"\"\"\n        c = TestClient(light=True)\n        pkg = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class ProtoBuf(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                def requirements(self):\n                    self.requires(\"protobuf/[*]\")\n                def build_requirements(self):\n                    self.tool_requires(\"protobuf/<host_version>\")\n            \"\"\")\n        c.save({\"protobuf/conanfile.py\": GenConanfile(\"protobuf\"),\n                \"pkg/conanfile.py\": pkg,\n                \"app/conanfile.py\": GenConanfile().with_requires(\"pkg/0.1\")})\n        c.run(\"create protobuf --version=1.0\")\n        c.run(\"create pkg\")\n        c.run(\"install pkg\")  # make sure it doesn't crash\n        c.run(\"install app\")\n        c.assert_listed_require({\"protobuf/1.0\": \"Cache\"})\n        c.assert_listed_require({\"protobuf/1.0\": \"Cache\"}, build=True)\n\n        c.run(\"create protobuf --version=1.1\")\n        c.run(\"install pkg\")  # make sure it doesn't crash\n        c.run(\"install app\")\n        c.assert_listed_require({\"protobuf/1.1\": \"Cache\"})\n        c.assert_listed_require({\"protobuf/1.1\": \"Cache\"}, build=True)\n        # verify locks work\n        c.run(\"lock create app\")\n        lock = json.loads(c.load(\"app/conan.lock\"))\n        build_requires = lock[\"build_requires\"]\n        assert len(build_requires) == 1\n        assert \"protobuf/1.1\" in build_requires[0]\n        # lock can be used\n        c.run(\"install app --lockfile=app/conan.lock\")\n        c.assert_listed_require({\"protobuf/1.1\": \"Cache\"}, build=True)\n\n    def test_track_host_error_nothost(self):\n        \"\"\"\n        if no host requirement is defined, it will be an error\n        \"\"\"\n        c = TestClient(light=True)\n        c.save({\"conanfile.py\": GenConanfile().with_build_requirement(\"protobuf/<host_version>\")})\n        c.run(\"install .\", assert_error=True)\n        assert \"ERROR:  require 'protobuf/<host_version>': \" \\\n               \"didn't find a matching host dependency\" in c.out\n\n    def test_track_host_errors_trait(self):\n        \"\"\"\n        It is not possible to make host_version visible too\n        \"\"\"\n        c = TestClient(light=True)\n        pkg = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class ProtoBuf(ConanFile):\n                name = \"protobuf\"\n                def requirements(self):\n                   self.tool_requires(\"other/<host_version>\", visible=True)\n            \"\"\")\n        c.save({\"pkg/conanfile.py\": pkg})\n        c.run(\"install pkg\", assert_error=True)\n        assert \"ERROR: protobuf/None require 'other/<host_version>': 'host_version' \" \\\n               \"can only be used for non-visible tool_requires\" in c.out\n\n    def test_track_host_error_wrong_context(self):\n        \"\"\"\n        it can only be used by tool_requires, not regular requires\n        \"\"\"\n        c = TestClient(light=True)\n        c.save({\"conanfile.py\": GenConanfile(\"pkg\").with_requirement(\"protobuf/<host_version>\")})\n        c.run(f\"install .\", assert_error=True)\n        assert \" 'host_version' can only be used for non-visible tool_requires\" in c.out\n\n    def test_host_version_test_package(self):\n        \"\"\"\n        https://github.com/conan-io/conan/issues/14704\n        \"\"\"\n        c = TestClient(light=True)\n        pkg = textwrap.dedent(\"\"\"\n                from conan import ConanFile\n                class ProtoBuf(ConanFile):\n                    name = \"pkg\"\n                    version = \"0.1\"\n                    def requirements(self):\n                        self.requires(\"protobuf/[>=1.0]\")\n                    def build_requirements(self):\n                        self.tool_requires(\"protobuf/<host_version>\")\n                \"\"\")\n        # regular requires test_package\n        c.save({\"protobuf/conanfile.py\": GenConanfile(\"protobuf\"),\n                \"pkg/conanfile.py\": pkg,\n                \"pkg/test_package/conanfile.py\": GenConanfile().with_test(\"pass\")})\n        c.run(\"create protobuf --version=1.0\")\n        c.run(f\"create pkg\")\n        # works without problem\n\n        test = textwrap.dedent(\"\"\"\n                from conan import ConanFile\n                class Test(ConanFile):\n                    def build_requirements(self):\n                        self.tool_requires(self.tested_reference_str)\n                    def test(self):\n                        pass\n                \"\"\")\n        c.save({\"pkg/test_package/conanfile.py\": test})\n        c.run(\"create protobuf --version=1.0\")\n        # This used to fail\n        c.run(f\"create pkg\")\n        c.assert_listed_binary({\"protobuf/1.0\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\",\n                                                 \"Cache\")})\n        c.assert_listed_binary({\"protobuf/1.0\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\",\n                                                 \"Cache\")}, build=True)\n\n    def test_overriden_host_version_transitive_deps(self):\n        \"\"\"\n        Make the tool_requires follow the regular require with the expression \"<host_version>\"\n        for a transitive_deps\n        \"\"\"\n        c = TestClient(light=True)\n        c.save({\"protobuf/conanfile.py\": GenConanfile(\"protobuf\"),\n                \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_requirement(\"protobuf/[>=1.0]\"),\n                \"app/conanfile.py\": GenConanfile().with_requires(\"pkg/0.1\")\n                                                  .with_tool_requirement(\"protobuf/<host_version>\")})\n        c.run(\"create protobuf --version=1.0\")\n        c.run(\"create protobuf --version=1.1\")\n        c.run(\"create pkg\")\n        c.run(\"install pkg\")  # make sure it doesn't crash\n        c.run(\"install app\")\n        c.assert_listed_require({\"protobuf/1.1\": \"Cache\"})\n        c.assert_listed_require({\"protobuf/1.1\": \"Cache\"}, build=True)\n        # verify locks work\n        c.run(\"lock create app\")\n        lock = json.loads(c.load(\"app/conan.lock\"))\n        build_requires = lock[\"build_requires\"]\n        assert len(build_requires) == 1\n        assert \"protobuf/1.1\" in build_requires[0]\n        # lock can be used\n        c.run(\"install app --lockfile=app/conan.lock\")\n        c.assert_listed_require({\"protobuf/1.1\": \"Cache\"}, build=True)\n\n    @pytest.mark.parametrize(\"host_version, assert_error, assert_msg\", [\n        (\"libgettext>\", False, \"gettext/0.2#d9f9eaeac9b6e403b271f04e04149df2\"),\n        # Error cases, just checking that we fail gracefully - no tracebacks\n        (\"libgettext\", True, \"Package 'gettext/<host_version:libgettext' not resolved\"),\n        (\":>\", True, \"app/1.0 require ':/<host_version::>': didn't find a matching host dependency\"),\n        (\">\", True, \"app/1.0 require '/<host_version:>': didn't find a matching host dependency\"),\n        (\":\", True, \" Package 'gettext/<host_version::' not resolved\"),\n        (\"\", True, \"Package 'gettext/<host_version:' not resolved: No remote defined\")\n    ])\n    def test_host_version_different_ref(self, host_version, assert_error, assert_msg):\n        tc = TestClient(light=True)\n        tc.save({\"gettext/conanfile.py\": GenConanfile(\"gettext\"),\n                 \"libgettext/conanfile.py\": GenConanfile(\"libgettext\"),\n                 \"app/conanfile.py\": GenConanfile(\"app\", \"1.0\").with_requires(\"libgettext/[>0.1]\")\n                                                   .with_tool_requirement(f\"gettext/<host_version:{host_version}\")})\n        tc.run(\"create libgettext --version=0.2\")\n        tc.run(\"create gettext --version=0.1 --build-require\")\n        tc.run(\"create gettext --version=0.2 --build-require\")\n\n        tc.run(\"create app\", assert_error=assert_error)\n        assert assert_msg in tc.out\n\n    @pytest.mark.parametrize(\"requires_tag,tool_requires_tag\", [\n        (\"\", \"\"),\n        (\"\", \"user/channel\"),\n        (\"user/channel\", \"user/channel\"),\n        (\"\", \"user/channel\"),\n        (\"auser/achannel\", \"anotheruser/anotherchannel\"),\n    ])\n    def test_overriden_host_version_user_channel(self, requires_tag, tool_requires_tag):\n        \"\"\"\n        Make the tool_requires follow the regular require with the expression \"<host_version>\"\n        \"\"\"\n        c = TestClient(light=True)\n        user_channel_reference = f\"@{requires_tag}\" if requires_tag else \"\"\n        pkg = textwrap.dedent(f\"\"\"\n            from conan import ConanFile\n            class ProtoBuf(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                def requirements(self):\n                    self.requires(\"protobuf/1.0{user_channel_reference}\")\n                def build_requirements(self):\n                    self.tool_requires(\"protobuf/<host_version>@{tool_requires_tag}\")\n            \"\"\")\n        c.save({\"protobuf/conanfile.py\": GenConanfile(\"protobuf\"),\n                \"pkg/conanfile.py\": pkg})\n        for tag in (requires_tag, tool_requires_tag):\n            if \"/\" in tag:\n                user, channel = tag.split(\"/\", 1)\n                user_channel = f\"--user={user} --channel={channel}\"\n            else:\n                user_channel = \"\"\n            c.run(f\"create protobuf --version=1.0 {user_channel}\")\n\n        c.run(\"create pkg\")\n        expected_tool_requires_tag = f\"@{tool_requires_tag}\" if tool_requires_tag else \"\"\n        c.assert_listed_require({f\"protobuf/1.0{user_channel_reference}\": \"Cache\"})\n        c.assert_listed_require({f\"protobuf/1.0{expected_tool_requires_tag}\": \"Cache\"}, build=True)\n\n    @pytest.mark.parametrize(\"shared\", [True, False])\n    def test_host_version_transitive_contexts(self, shared):\n        # app ---------------------------------------> protobuf (shared)\n        #   \\---tool-require-> grpc/<host> (shared) -> protobuf (shared)\n        #    \\--tool-require-------(host)----------------/\n        tc = TestClient(light=True)\n        tc.save({\"grpc/conanfile.py\": GenConanfile(\"grpc\", \"0.1\").with_shared_option(shared)\n                .with_requirement(\"protobuf/0.1\"),\n                 \"protobuf/conanfile.py\": GenConanfile(\"protobuf\", \"0.1\")\n                .with_shared_option(shared),\n                 \"conanfile.py\": GenConanfile(\"app\", \"0.1\").with_requires(\"protobuf/[*]\")\n                .with_tool_requirement(\"grpc/[*]\")\n                .with_tool_requirement(\"protobuf/<host_version>\")\n                 })\n        tc.run(\"export protobuf\")\n        tc.run(\"export grpc\")\n        tc.run(\"graph info .\")\n        assert \"Conflict between\" not in tc.out\n\n    @pytest.mark.parametrize(\"shared\", [True, False])\n    def test_host_version_transitive_contexts2(self, shared):\n        # app -> grpc (shared) -> protobuf (shared)\n        #  \\-----------------------/\n        #   \\---tool-require-> grpc/<host> (shared) -> protobuf (shared)\n        #    \\--tool-require-------(host)----------------/\n        tc = TestClient(light=True)\n        tc.save({\"grpc/conanfile.py\": GenConanfile(\"grpc\", \"0.1\").with_shared_option(shared)\n                .with_requirement(\"protobuf/0.1\"),\n                 \"protobuf/conanfile.py\": GenConanfile(\"protobuf\", \"0.1\")\n                .with_shared_option(shared),\n                 \"conanfile.py\": GenConanfile(\"app\", \"0.1\").with_requires(\"grpc/0.1\")\n                .with_requires(\"protobuf/[*]\")\n                .with_tool_requirement(\"grpc/<host_version>\")\n                .with_tool_requirement(\"protobuf/<host_version>\")\n                 })\n        tc.run(\"export protobuf\")\n        tc.run(\"export grpc\")\n        tc.run(\"graph info .\")\n        assert \"Conflict between\" not in tc.out\n\n    def test_host_version_transitive_contexts_orphan(self):\n        tc = TestClient(light=True)\n        tc.save({\"grpc/conanfile.py\": GenConanfile(\"grpc\", \"0.1\")\n                .with_requirement(\"protobuf/0.1\").with_shared_option(False),\n                 \"protobuf/conanfile.py\": GenConanfile(\"protobuf\", \"0.1\").with_shared_option(False),\n                 \"conanfile.py\": GenConanfile(\"app\", \"0.1\").with_requires(\"grpc/0.1\")\n                .with_requires(\"protobuf/[*]\")\n                .with_tool_requirement(\"protobuf/<host_version>\")\n                .with_tool_requirement(\"grpc/<host_version>\")})\n        tc.run(\"export protobuf\")\n        tc.run(\"export grpc\")\n        tc.run(\"graph info . -o:a=*:shared=True -f=json\", redirect_stdout=\"graph.json\")\n        data = json.loads(tc.load(\"graph.json\"))\n\n        def _assert_no_orphan(deps_graph):\n            ids = set(deps_graph[\"nodes\"].keys())\n            seen = set(deps_graph[\"root\"].keys())\n            for node in deps_graph[\"nodes\"].values():\n                seen.update(node[\"dependencies\"].keys())\n            assert not ids - seen, f\"Orphan nodes found: {ids - seen}\"\n        _assert_no_orphan(data[\"graph\"])\n\n    def test_user_channel_error(self):\n        lib = textwrap.dedent(\"\"\"\n           from conan import ConanFile\n           class LibWithToolConan(ConanFile):\n               name = \"lib_with_tool\"\n               package_type = \"static-library\"\n               settings = \"os\", \"arch\"\n               # {}\n           \"\"\")\n        c = TestClient(default_server_user=True)\n        c.save({\"conanfile.py\": lib.format(1)})\n        c.run(\"create . --version 1.0.0 --user foobar\")\n        c.save({\"conanfile.py\": lib.format(2)})\n        c.run(\"create . --version 1.1.0 --user foobar\")\n        rev1 = c.exported_recipe_revision()\n        c.save({\"conanfile.py\": lib.format(3)})\n        c.run(\"create . --version 1.1.0 --user foobar\")\n        rev2 = c.exported_recipe_revision()\n        assert rev1 != rev2\n\n        c.run(f\"upload lib_with_tool/1.1.0@foobar#{rev2} -r=default\")\n        c.run(f\"remove lib_with_tool/1.1.0@foobar#{rev2} -c\")\n\n        dep = textwrap.dedent(\"\"\"\n           from conan import ConanFile\n           class DepLibConan(ConanFile):\n               name = \"dep_lib\"\n\n               package_type = \"static-library\"\n               settings = \"os\", \"arch\"\n\n               def build_requirements(self):\n                   self.tool_requires(\"lib_with_tool/<host_version>@foobar\")\n\n               def requirements(self):\n                   self.requires(\"lib_with_tool/1.1.0@foobar\")\n           \"\"\")\n        c.save({\"conanfile.py\": dep}, clean_first=True)\n        c.run(\"create . --version=1.0.0 --user=foobar\")\n\n        conanfile = textwrap.dedent(f\"\"\"\n            [requires]\n            dep_lib/1.0.0@foobar\n            lib_with_tool/1.1.0@foobar#{rev2}\n            \"\"\")\n        c.save({\"conanfile.txt\": conanfile}, clean_first=True)\n        c.run(\"install .\")\n        # No longer produces a conflict\n\n\ndef test_build_missing_build_requires():\n    c = TestClient(light=True)\n    c.save({\"tooldep/conanfile.py\": GenConanfile(\"tooldep\", \"0.1\"),\n            \"tool/conanfile.py\": GenConanfile(\"tool\", \"0.1\").with_tool_requires(\"tooldep/0.1\"),\n            \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_tool_requires(\"tool/0.1\"),\n            \"app/conanfile.py\": GenConanfile().with_requires(\"pkg/0.1\")})\n    c.run(\"create tooldep\")\n    c.run(\"create tool\")\n    c.run(\"create pkg\")\n    c.run(\"remove tool*:* -c\")\n    c.run(\"install app\")\n    assert \"- Build\" not in c.out\n    assert re.search(r\"Skipped binaries(\\s*)tool/0.1, tooldep/0.1\", c.out)\n    c.run(\"install app --build=missing\")\n    assert \"- Build\" not in c.out\n    assert re.search(r\"Skipped binaries(\\s*)tool/0.1, tooldep/0.1\", c.out)\n\n\ndef test_requirement_in_wrong_method():\n    tc = TestClient(light=True)\n    tc.save({\"conanfile.py\": textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            def configure(self):\n                self.requires(\"foo/1.0\")\n        \"\"\")})\n    tc.run('create . -cc=\"core:warnings_as_errors=[\\'*\\']\"', assert_error=True)\n    assert (\"ERROR: deprecated: Requirements should only be added in the requirements()/\"\n            \"build_requirements() methods, not configure()/config_options(), which might \"\n            \"raise errors in the future.\") in tc.out\n\n\ndef test_transitive_build_scripts_error():\n    # https://github.com/conan-io/conan/issues/18235\n    c = TestClient(light=True)\n    meta = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Meta(ConanFile):\n            name = \"meta\"\n            version = \"0.1\"\n            package_type = \"build-scripts\"\n            def requirements(self):\n                self.requires(\"dep/0.1\")\n        \"\"\")\n    product = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Product(ConanFile):\n            name = \"product\"\n            version = \"0.1\"\n            package_type = \"build-scripts\"\n            def requirements(self):\n                self.requires(\"meta/0.1\")\n        \"\"\")\n\n    c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\"),\n            \"meta/conanfile.py\": meta,\n            \"product/conanfile.py\": product})\n    c.run(\"create dep\")\n    c.run(\"create meta\")\n    c.run(\"install product\")\n    # It doesn't crash\n\n\ndef test_transitive_build_scripts_library_error():\n    # https://github.com/conan-io/conan/issues/18856\n    c = TestClient(light=True)\n    tool = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Product(ConanFile):\n            name = \"tool\"\n            version = \"0.1\"\n            package_type = \"build-scripts\"\n            def requirements(self):\n                self.requires(\"dep/0.1\")\n        \"\"\")\n\n    c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\").with_package_type(\"static-library\"),\n            \"tool/conanfile.py\": tool})\n    c.run(\"create dep\")\n    c.run(\"create tool\")\n    # Tool-requires, not an issue\n    c.run(\"install --tool-requires=tool/0.1\")\n    # requires, it crashed with traceback, now a clear error message\n    c.run(\"install --requires=tool/0.1\", assert_error=True)\n    assert (\"ERROR: Package 'tool/0.1' with type 'build-scripts' cannot have \"\n            \"a 'static-library' dependency to 'dep/0.1'\") in c.out\n"
  },
  {
    "path": "test/integration/build_requires/profile_build_requires_test.py",
    "content": "import os\nimport platform\nimport textwrap\n\nimport pytest\n\nfrom conan.internal.paths import CONANFILE\nfrom conan.test.utils.tools import TestClient, GenConanfile\n\n\nclass TestBuildRequires:\n\n    @pytest.fixture()\n    def client(self):\n        c = TestClient()\n        tool_conanfile = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.files import copy\n\n            class tool(ConanFile):\n                name = \"tool\"\n                version = \"0.1\"\n                exports_sources = \"mytool*\"\n\n                def package(self):\n                    copy(self, \"mytool*\", self.source_folder, self.package_folder)\n\n                def package_info(self):\n                    self.buildenv_info.append_path(\"PATH\", self.package_folder)\n            \"\"\")\n        name = \"mytool.bat\" if platform.system() == \"Windows\" else \"mytool\"\n        c.save({CONANFILE: tool_conanfile,\n                name: \"echo Hello World!\"}, clean_first=True)\n        os.chmod(os.path.join(c.current_folder, name), 0o777)\n        c.run(\"export . --user=lasote --channel=stable\")\n\n        lib_conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class mylib(ConanFile):\n                name = \"mylib\"\n                version = \"0.1\"\n\n                def build(self):\n                    self.run(\"mytool\")\n            \"\"\")\n        profile = \"\"\"\n            [tool_requires]\n            tool/0.1@lasote/stable\n            nonexistingpattern*: sometool/1.2@user/channel\n            \"\"\"\n\n        profile2 = \"\"\"\n            [tool_requires]\n            tool/0.1@lasote/stable\n            nonexistingpattern*: sometool/1.2@user/channel\n            \"\"\"\n\n        test_conanfile = textwrap.dedent(\"\"\"\n           from conan import ConanFile\n\n           class Testmylib(ConanFile):\n\n               def build(self):\n                   self.run(\"mytool\")\n               def test(self):\n                   pass\n           \"\"\")\n        c.save({CONANFILE: lib_conanfile,\n                \"test_package/conanfile.py\": test_conanfile,\n                \"profile.txt\": profile,\n                \"profile2.txt\": profile2}, clean_first=True)\n        return c\n\n    def test_profile_requires(self, client):\n        \"\"\"\n        cli -(tool-requires)-> tool/0.1\n          \\\\--(requires)->mylib/0.1 -(tool_requires)->tool/0.1 (skipped)\n        \"\"\"\n        client.run(\"export . --user=lasote --channel=stable\")\n        client.run(\"install --requires=mylib/0.1@lasote/stable \"\n                   \"--profile ./profile.txt --build missing\")\n        assert \"Hello World!\" in client.out\n\n        client.run(\"install --requires=mylib/0.1@lasote/stable --profile ./profile2.txt --build='*'\")\n        assert \"Hello World!\" in client.out\n\n    def test_profile_open_requires(self, client):\n        client.run(\"build . --profile ./profile.txt --build missing\")\n        assert \"Hello World!\" in client.out\n\n    def test_build_mode_requires(self, client):\n        client.run(\"install . --profile ./profile.txt\", assert_error=True)\n        assert \"ERROR: Missing prebuilt package for 'tool/0.1@lasote/stable'\" in client.out\n        client.run(\"install . --profile ./profile.txt --build=Pythontool\", assert_error=True)\n        assert \"ERROR: Missing prebuilt package for 'tool/0.1@lasote/stable'\" in client.out\n        client.run(\"install . --profile ./profile.txt --build=tool/0.1*\")\n        assert \"tool/0.1@lasote/stable: Created package\" in client.out\n\n        # now remove packages, ensure --build=missing also creates them\n        client.run('remove \"*:*\" -c')\n        client.run(\"install . --profile ./profile.txt --build=missing\")\n        assert \"tool/0.1@lasote/stable: Created package\" in client.out\n\n    def test_profile_test_requires(self, client):\n        client.run(\"create . --profile ./profile.txt --build missing\")\n        assert 2 == str(client.out).splitlines().count(\"Hello World!\")\n\n    def test_consumer_patterns(self, client):\n        profile_patterns = \"\"\"\n            [tool_requires]\n            &: tool/0.1@lasote/stable\n            nonexistingpattern*: sometool/1.2@user/channel\n            \"\"\"\n        client.save({CONANFILE: GenConanfile(\"mylib\", \"0.1\"),\n                     \"profile.txt\": profile_patterns})\n        client.run(\"create . --profile=./profile.txt --build=missing\")\n        assert 1 == str(client.out).splitlines().count(\"Hello World!\")\n\n    def test_build_requires_options(self):\n        client = TestClient()\n        client.save({CONANFILE: GenConanfile(\"mytool\", \"0.1\")})\n        client.run(\"export . --user=lasote --channel=stable\")\n\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class mylib(ConanFile):\n                name = \"mylib\"\n                version = \"0.1\"\n                build_requires = \"mytool/0.1@lasote/stable\"\n                options = {\"coverage\": [True, False]}\n                def build(self):\n                    self.output.info(\"Coverage %s\" % self.options.coverage)\n            \"\"\")\n        client.save({CONANFILE: conanfile}, clean_first=True)\n        client.run(\"build . -o mylib*:coverage=True --build missing\")\n        client.assert_listed_require({\"mytool/0.1@lasote/stable\": \"Cache\"}, build=True)\n        assert \"conanfile.py (mylib/0.1): Coverage True\" in client.out\n\n        client.save({CONANFILE: conanfile}, clean_first=True)\n        client.run(\"build . -o coverage=True\")\n        client.assert_listed_require({\"mytool/0.1@lasote/stable\": \"Cache\"}, build=True)\n        assert \"mytool/0.1@lasote/stable: Already installed!\" in client.out\n        assert \"conanfile.py (mylib/0.1): Coverage True\" in client.out\n\n\ndef test_consumer_patterns_loop_error():\n    client = TestClient()\n\n    profile_patterns = textwrap.dedent(\"\"\"\n        include(default)\n        [tool_requires]\n        tool1/1.0\n        tool2/1.0\n        \"\"\")\n    client.save({\"tool1/conanfile.py\": GenConanfile(),\n                 \"tool2/conanfile.py\": GenConanfile().with_build_requires(\"tool1/1.0\"),\n                 \"consumer/conanfile.py\": GenConanfile(),\n                 \"profile.txt\": profile_patterns})\n\n    client.run(\"export tool1 --name=tool1 --version=1.0\")\n    client.run(\"export tool2 --name=tool2 --version=1.0\")\n    client.run(\"install consumer --build=missing -pr:b=profile.txt -pr:h=profile.txt\",\n               assert_error=True)\n    assert \"There is a cycle/loop in the graph\" in client.out\n\n    # we can fix it with the negation\n    profile_patterns = textwrap.dedent(\"\"\"\n        include(default)\n        [tool_requires]\n        tool1/1.0\n        !tool1*:tool2/1.0\n        \"\"\")\n    client.save({\"profile.txt\": profile_patterns})\n\n    client.run(\"install consumer --build=missing -pr:b=profile.txt -pr:h=profile.txt\")\n    assert \"tool1/1.0: Created package\" in client.out\n    assert \"tool2/1.0: Created package\" in client.out\n\n\ndef test_tool_requires_revision_profile():\n    # We shoul be able to explicitly [tool_require] a recipe revision in the profile\n    c = TestClient()\n    build_profile = textwrap.dedent(\"\"\"\\\n        [settings]\n        os=Linux\n        [tool_requires]\n        *:tool/0.1#2d65f1b4af1ce59028f96adbfe7ed5a2\n        \"\"\")\n    c.save({\"tool/conanfile.py\": GenConanfile(\"tool\", \"0.1\"),\n            \"cmake/conanfile.py\": GenConanfile(\"cmake\", \"0.1\"),\n            \"app/conanfile.py\": GenConanfile(\"app\", \"0.1\").with_tool_requires(\"cmake/0.1\"),\n            \"build_profile\": build_profile})\n    c.run(\"export tool\")\n    rev1 = c.exported_recipe_revision()\n    assert rev1 == \"2d65f1b4af1ce59028f96adbfe7ed5a2\"\n    # Create a new tool revision to proof that we can still require the old one\n    c.save({\"tool/conanfile.py\": GenConanfile(\"tool\", \"0.1\").with_class_attribute(\"myvar=42\")})\n    c.run(\"export tool\")\n    rev2 = c.exported_recipe_revision()\n    assert rev2 != rev1\n    c.run(\"export cmake\")\n    c.run(\"graph info app -pr:b=build_profile --build=*\")\n    assert f\"tool/0.1#{rev1}\" in c.out\n    assert rev2 not in c.out\n\n\ndef test_tool_requires_version_range_loop():\n    # https://github.com/conan-io/conan/issues/17930\n    c = TestClient(light=True)\n    build_profile = textwrap.dedent(\"\"\"\\\n        [settings]\n        os=Linux\n        [tool_requires]\n        tool/[>=1.0 <2]\n        \"\"\")\n    c.save({\"tool/conanfile.py\": GenConanfile(\"tool\", \"1.1\"),\n            \"app/conanfile.py\": GenConanfile(\"app\", \"0.1\").with_tool_requires(\"tool/1.1\"),\n            \"build_profile\": build_profile})\n    c.run(\"create tool\")\n    c.run(\"install app -pr:b=build_profile\")\n    assert \"tool/1.1\" in c.out  # It is skipped\n"
  },
  {
    "path": "test/integration/build_requires/test_build_requires_source_method.py",
    "content": "import textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestBuildEnvSource:\n    @pytest.fixture()\n    def client(self):\n        c = TestClient()\n        tool = textwrap.dedent(r\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.files import chdir, save\n\n            class Tool(ConanFile):\n                name = \"tool\"\n                version = \"0.1\"\n                def package(self):\n                    with chdir(self, self.package_folder):\n                        echo = f\"@echo off\\necho MY-TOOL! {self.name}/{self.version}!!\"\n                        save(self, \"bin/mytool.bat\", echo)\n                        save(self, \"bin/mytool.sh\", echo)\n                        os.chmod(\"bin/mytool.sh\", 0o777)\n            \"\"\")\n        c.save({\"conanfile.py\": tool})\n        c.run(\"create .\")\n        return c\n\n    def test_source_buildenv(self, client):\n        c = client\n        pkg = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            import platform\n\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                tool_requires = \"tool/0.1\"\n\n                source_buildenv = True\n\n                def source(self):\n                    cmd = \"mytool.bat\" if platform.system() == \"Windows\" else \"mytool.sh\"\n                    self.run(cmd)\n            \"\"\")\n        c.save({\"conanfile.py\": pkg})\n        c.run(\"create .\")\n        assert \"MY-TOOL! tool/0.1\" in c.out\n\n        c.run(\"install .\")  # to generate conanbuild script first, so it is available\n        c.run(\"source .\")\n        assert \"MY-TOOL! tool/0.1\" in c.out\n\n    def test_source_buildenv_layout(self, client):\n        c = client\n        pkg = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            import platform\n\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                tool_requires = \"tool/0.1\"\n                settings = \"build_type\"\n\n                source_buildenv = True\n\n                def layout(self):\n                    self.folders.source = \"mysrc\"\n                    bt = self.settings.get_safe(\"build_type\") or \"Release\"\n                    self.folders.generators = f\"mybuild{bt}\"\n\n                def source(self):\n                    cmd = \"mytool.bat\" if platform.system() == \"Windows\" else \"mytool.sh\"\n                    self.run(cmd)\n            \"\"\")\n        c.save({\"conanfile.py\": pkg})\n        c.run(\"create .\")\n        assert \"MY-TOOL! tool/0.1\" in c.out\n\n        c.run(\"install .\")  # to generate conanbuild script first, so it is available\n        # But they are in a different folder, user can copy them to source folder to make\n        # them available to source() method. This works\n        # shutil.copytree(os.path.join(c.current_folder, \"mybuild\"),\n        #                os.path.join(c.current_folder, \"mysrc\"))\n        # Another possibility is user directly calling the \"conanbuild\" script to activate\n        # The current solution defines \"generators\" to be robust for \"conan source\" command\n        # defaulting to \"Release\" config\n        c.run(\"source .\")\n        assert \"MY-TOOL! tool/0.1\" in c.out\n\n    def test_source_buildenv_cmake_layout(self, client):\n        c = client\n        pkg = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.cmake import cmake_layout\n            import platform\n\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                tool_requires = \"tool/0.1\"\n                settings = \"build_type\"\n\n                source_buildenv = True\n\n                def layout(self):\n                    cmake_layout(self)\n                    bt = self.settings.get_safe(\"build_type\") or \"Release\"\n                    self.folders.generators = os.path.join(bt, \"generators\")\n\n                def source(self):\n                    cmd = \"mytool.bat\" if platform.system() == \"Windows\" else \"mytool.sh\"\n                    self.run(cmd)\n            \"\"\")\n        c.save({\"conanfile.py\": pkg})\n        c.run(\"create .\")\n        assert \"MY-TOOL! tool/0.1\" in c.out\n\n        c.run(\"install .\")\n        c.run(\"source .\")\n        assert \"MY-TOOL! tool/0.1\" in c.out\n\n    def test_source_buildenv_default_fail(self, client):\n        c = client\n\n        pkg = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            import platform\n\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                tool_requires = \"tool/0.1\"\n\n                def source(self):\n                    cmd = \"mytool.bat\" if platform.system() == \"Windows\" else \"mytool.sh\"\n                    self.run(cmd)\n            \"\"\")\n        c.save({\"conanfile.py\": pkg})\n        c.run(\"create .\", assert_error=True)\n        assert \"ERROR: pkg/0.1: Error in source() method, line 12\" in c.out\n\n        # Local will still work, because ``install`` generates env-scripts and no layout\n        c.run(\"install .\")\n        c.run(\"source .\")\n        assert \"MY-TOOL! tool/0.1\" in c.out\n"
  },
  {
    "path": "test/integration/build_requires/test_install_test_build_require.py",
    "content": "import json\nimport platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.utils.mocks import ConanFileMock\nfrom conan.tools.env.environment import environment_wrap_command\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.fixture(scope=\"module\")\ndef client():\n    openssl = textwrap.dedent(r\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import save, chdir\n        class Pkg(ConanFile):\n            settings = \"os\"\n            package_type = \"shared-library\"\n            def package(self):\n                with chdir(self, self.package_folder):\n                    echo = \"@echo off\\necho MYOPENSSL={}!!\".format(self.settings.os)\n                    save(self, \"bin/myopenssl.bat\", echo)\n                    save(self, \"bin/myopenssl.sh\", echo)\n                    os.chmod(\"bin/myopenssl.sh\", 0o777)\n            \"\"\")\n\n    cmake = textwrap.dedent(r\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import save, chdir\n        class Pkg(ConanFile):\n            settings = \"os\"\n            requires = \"openssl/1.0\"\n            def package(self):\n                with chdir(self, self.package_folder):\n                    echo = \"@echo off\\necho MYCMAKE={}!!\".format(self.settings.os)\n                    save(self, \"mycmake.bat\", echo + \"\\ncall myopenssl.bat\")\n                    save(self, \"mycmake.sh\", echo + \"\\n myopenssl.sh\")\n                    os.chmod(\"mycmake.sh\", 0o777)\n\n            def package_info(self):\n                self.buildenv_info.append_path(\"PATH\", self.package_folder)\n            \"\"\")\n\n    client = TestClient()\n    client.save({\"tool/conanfile.py\": GenConanfile(),\n                 \"cmake/conanfile.py\": cmake,\n                 \"openssl/conanfile.py\": openssl})\n\n    client.run(\"create tool --name=tool --version=1.0\")\n    client.run(\"create openssl --name=openssl --version=1.0\")\n    client.run(\"create cmake --name=mycmake --version=1.0\")\n    return client\n\n\n@pytest.mark.parametrize(\"build_profile\", [\"\", \"-pr:b=default\"])\ndef test_build_require_test_package(build_profile, client):\n    test_cmake = textwrap.dedent(r\"\"\"\n        import os, platform, sys\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            settings = \"os\"\n\n            def requirements(self):\n                self.tool_requires(self.tested_reference_str)\n\n            def build(self):\n                mybuild_cmd = \"mycmake.bat\" if platform.system() == \"Windows\" else \"mycmake.sh\"\n                self.run(mybuild_cmd)\n\n            def test(self):\n                pass\n        \"\"\")\n\n    # Test with extra build_requires to check it doesn't interfere or get deleted\n    client.save({\"cmake/test_package/conanfile.py\": test_cmake})\n    client.run(\"create cmake --name=mycmake --version=1.0 {} --build=missing\".format(build_profile))\n\n    def check(out):\n        system = {\"Darwin\": \"Macos\"}.get(platform.system(), platform.system())\n        assert \"MYCMAKE={}!!\".format(system) in out\n        assert \"MYOPENSSL={}!!\".format(system) in out\n\n    check(client.out)\n\n    client.run(\"test cmake/test_package mycmake/1.0@ {}\".format(build_profile))\n    check(client.out)\n\n\ndef test_both_types(client):\n    # When testing same package in both contexts, the 2 profiles approach must be used\n    test_cmake = textwrap.dedent(r\"\"\"\n        import os, platform\n        from conan import ConanFile\n\n        class Pkg(ConanFile):\n            settings = \"os\"\n\n            def requirements(self):\n                self.requires(self.tested_reference_str)\n                self.build_requires(self.tested_reference_str)\n\n            def build(self):\n                mybuild_cmd = \"mycmake.bat\" if platform.system() == \"Windows\" else \"mycmake.sh\"\n                self.run(mybuild_cmd)\n\n            def test(self):\n                pass\n        \"\"\")\n\n    # Test with extra build_requires to check it doesn't interfere or get deleted\n    client.save({\"cmake/test_package/conanfile.py\": test_cmake})\n    # This must use the build-host contexts to have same dep in different contexts\n    client.run(\"create cmake --name=mycmake --version=1.0 -pr:b=default --build=missing\")\n\n    def check(out):\n        system = {\"Darwin\": \"Macos\"}.get(platform.system(), platform.system())\n        assert \"MYCMAKE={}!!\".format(system) in out\n        assert \"MYOPENSSL={}!!\".format(system) in out\n\n    check(client.out)\n\n    client.run(\"test cmake/test_package mycmake/1.0@ -pr:b=default\")\n    check(client.out)\n\n\ndef test_create_build_requires():\n    # test that I can create a package passing the build and host context and package will get both\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            settings = \"os\"\n\n            def package_info(self):\n                self.output.info(\"MYOS=%s!!!\" % self.settings.os)\n                self.output.info(\"MYTARGET={}!!!\".format(self.settings_target.os))\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=br --version=0.1  --build-require -s:h os=Linux -s:b os=Windows\")\n    client.assert_listed_binary({\"br/0.1\": (\"ebec3dc6d7f6b907b3ada0c3d3cdc83613a2b715\", \"Build\")},\n                                build=True)\n    assert \"br/0.1: MYOS=Windows!!!\" in client.out\n    assert \"br/0.1: MYTARGET=Linux!!!\" in client.out\n    assert \"br/0.1: MYOS=Linux!!!\" not in client.out\n\n\ndef test_build_require_conanfile_text(client):\n    client.save({\"conanfile.txt\": \"[tool_requires]\\nmycmake/1.0\"}, clean_first=True)\n    client.run(\"install . -g VirtualBuildEnv\")\n    ext = \".bat\" if platform.system() == \"Windows\" else \".sh\"\n    cmd = environment_wrap_command(ConanFileMock(), \"conanbuild\", client.current_folder,\n                                   f\"mycmake{ext}\")\n    client.run_command(cmd)\n    system = {\"Darwin\": \"Macos\"}.get(platform.system(), platform.system())\n    assert \"MYCMAKE={}!!\".format(system) in client.out\n    assert \"MYOPENSSL={}!!\".format(system) in client.out\n\n\ndef test_build_require_command_line_build_context(client):\n    client.run(\"install --tool-requires=mycmake/1.0@ -g VirtualBuildEnv -pr:b=default\")\n    ext = \".bat\" if platform.system() == \"Windows\" else \".sh\"\n    cmd = environment_wrap_command(ConanFileMock(), \"conanbuild\", client.current_folder,\n                                   f\"mycmake{ext}\")\n    client.run_command(cmd)\n    system = {\"Darwin\": \"Macos\"}.get(platform.system(), platform.system())\n    assert \"MYCMAKE={}!!\".format(system) in client.out\n    assert \"MYOPENSSL={}!!\".format(system) in client.out\n\n\ndef test_install_multiple_tool_requires_cli():\n    c = TestClient()\n    c.save({\"conanfile.py\": GenConanfile()})\n    c.run(\"create . --name=zlib --version=1.1\")\n    c.run(\"create . --name=cmake --version=0.1\")\n    c.run(\"create . --name=gcc --version=0.2\")\n    c.run(\"install --tool-requires=cmake/0.1 --tool-requires=gcc/0.2 --requires=zlib/1.1\")\n    c.assert_listed_require({\"cmake/0.1\": \"Cache\", \"gcc/0.2\": \"Cache\"}, build=True)\n    c.assert_listed_require({\"zlib/1.1\": \"Cache\"})\n\n\ndef test_bootstrap_other_architecture():\n    \"\"\" this is the case of libraries as ICU, that needs itself for cross-compiling\n    \"\"\"\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.build import cross_building\n\n        class Pkg(ConanFile):\n            name = \"tool\"\n            version = \"1.0\"\n            settings = \"os\"\n            def build_requirements(self):\n                if cross_building(self):\n                    self.tool_requires(\"tool/1.0\")\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    win_pkg_id = \"ebec3dc6d7f6b907b3ada0c3d3cdc83613a2b715\"\n    linux_pkg_id = \"9a4eb3c8701508aa9458b1a73d0633783ecc2270\"\n\n    c.run(\"create . -s:b os=Windows -s:h os=Windows\")\n    c.assert_listed_binary({\"tool/1.0\": (win_pkg_id, \"Build\")})\n    assert \"Build requirements\" not in c.out\n\n    # This is smart and knows how to build only the missing one \"host\" but not \"build\"\n    c.run(\"create . -s:b os=Windows -s:h os=Linux --build=missing:tool*\")\n    c.assert_listed_binary({\"tool/1.0\": (linux_pkg_id, \"Build\")})\n    c.assert_listed_binary({\"tool/1.0\": (win_pkg_id, \"Cache\")}, build=True)\n\n    # This will rebuild all\n    c.run(\"create . -s:b os=Windows -s:h os=Linux\")\n    c.assert_listed_binary({\"tool/1.0\": (linux_pkg_id, \"Build\")})\n    c.assert_listed_binary({\"tool/1.0\": (win_pkg_id, \"Build\")}, build=True)\n\n    c.run(\"graph build-order --requires=tool/1.0 -s:b os=Windows -s:h os=Linux --build=* \"\n          \"--format=json\", redirect_stdout=\"o.json\")\n    order = json.loads(c.load(\"o.json\"))\n    package1 = order[0][0][\"packages\"][0][0]\n    package2 = order[0][0][\"packages\"][1][0]\n    assert package1[\"package_id\"] == win_pkg_id\n    assert package1[\"depends\"] == []\n    assert package2[\"package_id\"] == linux_pkg_id\n    assert package2[\"depends\"] == [win_pkg_id]\n\n\ndef test_bootstrap_cc():\n    # https://github.com/conan-io/conan/issues/16758\n    cc = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class CcConanfile(ConanFile):\n            name = \"cc\"\n            version = \"1.0\"\n            options = {\"bootstrap\": [True, False]}\n            default_options = {\"bootstrap\": True}\n\n            def build_requirements(self):\n                if self.options.bootstrap:\n                    self.tool_requires(\"cc/1.0\", options={\"*:bootstrap\": False})\n        \"\"\")\n    foo = GenConanfile(\"foo\", \"1.0\").with_tool_requirement(\"cc/1.0\")\n    c = TestClient()\n    c.save({\"cc/conanfile.py\": cc,\n            \"foo/conanfile.py\": foo})\n    c.run(\"create cc --build-require\")\n    # Both are build-requires\n    c.assert_listed_binary({\"cc/1.0\": (\"826727aac60b5956d1df5121a3921f26a6984f15\", \"Build\")},\n                           build=True)\n    c.assert_listed_binary({\"cc/1.0\": (\"96ae1d965ce6f2e2256ac0cfc3a35dcd4860c389\", \"Build\")},\n                           build=True)\n    # This works fine, being able to build the 2 different binaries both bootstrapped and not\n    c.run(\"list cc/1.0:*\")\n    assert \"bootstrap: False\" in c.out\n    assert \"bootstrap: True\" in c.out\n    c.run(\"create foo\")\n    c.assert_listed_binary({\"cc/1.0\": (\"96ae1d965ce6f2e2256ac0cfc3a35dcd4860c389\", \"Cache\")},\n                           build=True)\n"
  },
  {
    "path": "test/integration/build_requires/test_relocatable_toolchain.py",
    "content": "import textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_relocatable_toolchain():\n    \"\"\" Implements the following use case:\n    - base/1.0 implements an SDK that needs to be relocated in every maching, but this package\n      contains the non relocatable part and the relocation scripts\n    - sdk/1.0 --tool_requires-> base/1.0 and implements just the relocation execution, copying\n      whatever is necessary from base, and relocating it.\n      It defines build_policy = \"missing\" and upload policy = \"skip\"\n    https://github.com/conan-io/conan/issues/5059\n    \"\"\"\n    c = TestClient(default_server_user=True)\n    base = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import save, copy\n        class Pkg(ConanFile):\n            name = \"base\"\n            version = \"1.0\"\n            settings = \"arch\"\n\n            def build(self):\n                save(self, \"sdk.txt\", f\"arch:{self.settings.arch}=>{self.settings_target.arch}\")\n\n            def package(self):\n                copy(self, \"*\", self.build_folder, self.package_folder)\n        \"\"\")\n    sdk = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import load, copy, save\n        class Pkg(ConanFile):\n            name = \"sdk\"\n            version = \"1.0\"\n            settings = \"arch\"\n            build_policy = \"missing\"\n            upload_policy = \"skip\"\n\n            def build_requirements(self):\n                self.tool_requires(\"base/1.0\")\n\n            def package(self):\n                # Whatever modification, customization, RPATHs, symlinks, etc\n                pkg_folder = self.dependencies.build[\"base\"].package_folder\n                sdk = load(self, os.path.join(pkg_folder, \"sdk.txt\"))\n                save(self, os.path.join(self.package_folder, \"sdk.txt\"), \"CUSTOM PATH: \" + sdk)\n\n            def package_info(self):\n                self.output.info(f\"SDK INFO: {load(self, 'sdk.txt')}!!!\")\n        \"\"\")\n    c.save({\"linux\": \"[settings]\\nos=Linux\\narch=x86_64\",\n            \"embedded\": \"[settings]\\narch=armv8\",\n            \"base/conanfile.py\": base,\n            \"sdk/conanfile.py\": sdk,\n            \"consumer/conanfile.py\": GenConanfile(\"app\", \"1.0\").with_tool_requires(\"sdk/1.0\")})\n    c.run(\"create base -pr:h=embedded -pr:b=linux --build-require\")\n    c.run(\"export sdk\")\n    c.run(\"install consumer -pr:h=embedded -pr:b=linux\")\n    c.assert_listed_binary({\"base/1.0\": (\"62e589af96a19807968167026d906e63ed4de1f5\", \"Cache\"),\n                            \"sdk/1.0\": (\"62e589af96a19807968167026d906e63ed4de1f5\", \"Build\")},\n                           build=True)\n    assert \"sdk/1.0: Calling package()\" in c.out\n    assert \"sdk/1.0: SDK INFO: CUSTOM PATH: arch:x86_64=>armv8!!!\" in c.out\n\n    c.run(\"install consumer -pr:h=embedded -pr:b=linux -v\")\n    c.assert_listed_binary({\"base/1.0\": (\"62e589af96a19807968167026d906e63ed4de1f5\", \"Skip\"),\n                            \"sdk/1.0\": (\"62e589af96a19807968167026d906e63ed4de1f5\", \"Cache\")},\n                           build=True)\n    assert \"sdk/1.0: Calling package()\" not in c.out\n    assert \"sdk/1.0: SDK INFO: CUSTOM PATH: arch:x86_64=>armv8!!!\" in c.out\n\n    # If I upload everything and remove:\n    c.run(\"upload * -r=default -c\")\n    c.run(\"remove * -c\")\n    c.run(\"install consumer -pr:h=embedded -pr:b=linux\")\n    c.assert_listed_binary(\n        {\"base/1.0\": (\"62e589af96a19807968167026d906e63ed4de1f5\", \"Download (default)\"),\n         \"sdk/1.0\": (\"62e589af96a19807968167026d906e63ed4de1f5\", \"Build\")},\n        build=True)\n    assert \"sdk/1.0: Calling package()\" in c.out\n    assert \"sdk/1.0: SDK INFO: CUSTOM PATH: arch:x86_64=>armv8!!!\" in c.out\n\n    # we can even remove the binary!\n    c.run(\"remove base/1.0:* -c\")\n    c.run(\"install consumer -pr:h=embedded -pr:b=linux -v\")\n    c.assert_listed_binary({\"base/1.0\": (\"62e589af96a19807968167026d906e63ed4de1f5\", \"Skip\"),\n                            \"sdk/1.0\": (\"62e589af96a19807968167026d906e63ed4de1f5\", \"Cache\")},\n                           build=True)\n    assert \"sdk/1.0: SDK INFO: CUSTOM PATH: arch:x86_64=>armv8!!!\" in c.out\n"
  },
  {
    "path": "test/integration/build_requires/test_toolchain_packages.py",
    "content": "import json\nimport textwrap\n\nfrom conan.api.model import PkgReference\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_android_ndk():\n    \"\"\" emulates the androidndk, a single package per OS-arch, that can target any\n    android architecture (not especialized binary per target)\n    \"\"\"\n    c = TestClient()\n\n    windows = textwrap.dedent(\"\"\"\\\n        [settings]\n        os=Windows\n        arch=x86_64\n        \"\"\")\n    linux = textwrap.dedent(\"\"\"\\\n        [settings]\n        os=Linux\n        arch=x86_64\n        \"\"\")\n    android = textwrap.dedent(\"\"\"\\\n        [settings]\n        os=Android\n        os.api_level=14\n        arch = armv7\n        build_type = Release\n        compiler=clang\n        compiler.version=11\n        compiler.libcxx=c++_shared\n        compiler.cppstd=14\n\n        [tool_requires]\n        androidndk/0.1\n        \"\"\")\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import save, copy\n        class Pkg(ConanFile):\n            name = \"androidndk\"\n            version = \"0.1\"\n            settings = \"os\", \"arch\"\n\n            def build(self):\n                save(self, \"bin/ndk.compiler\", f\"MYNDK-{self.settings.os}-{self.settings.arch} exe!\")\n\n            def package(self):\n                copy(self, \"*\", src=self.build_folder, dst=self.package_folder)\n\n            def package_info(self):\n                arch = self.settings_target.arch\n                self.cpp_info.libs = [f\"libndklib-{arch}\"]\n                self.buildenv_info.define(\"MY_ANDROID_ARCH\", f\"android-{arch}\")\n        \"\"\")\n    test = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import load\n        from conan.tools.env import VirtualBuildEnv\n        class Pkg(ConanFile):\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n\n            def generate(self):\n                ndk = self.dependencies.build[\"androidndk\"]\n                self.output.info(f\"NDK LIBS: {ndk.cpp_info.libs}!!!\")\n                compiler = os.path.join(ndk.package_folder, \"bin/ndk.compiler\")\n                self.output.info(load(self, compiler))\n                env = VirtualBuildEnv(self).vars()\n                self.output.info(f\"MY-VAR: {env.get('MY_ANDROID_ARCH')}\")\n\n            def test(self):\n                pass\n        \"\"\")\n\n    c.save({\"conanfile.py\": conanfile,\n            \"windows\": windows,\n            \"linux\": linux,\n            \"android\": android})\n\n    # IMPORTANT: The consumption via test_package define the relation. If not existing\n    # I need to pass --build-require\n\n    # Creating the NDK packages for Windows, Linux\n    c.run(\"create . -pr:b=windows -pr:h=android --build-require\")\n    c.assert_listed_binary({\"androidndk/0.1\": (\"522dcea5982a3f8a5b624c16477e47195da2f84f\", \"Build\")},\n                           build=True)\n    # The same NDK can be used for different architectures, this should not require a new NDK build\n    c.run(\"create . -pr:b=windows -pr:h=android -s:h arch=armv8 --build=missing  --build-require\")\n    c.assert_listed_binary({\"androidndk/0.1\": (\"522dcea5982a3f8a5b624c16477e47195da2f84f\", \"Cache\")},\n                           build=True)\n    assert \"androidndk/0.1: Already installed!\" in c.out\n    # But a different build architecture is a different NDK executable\n    c.run(\"create . -pr:b=windows -s:b arch=x86 -pr:h=android --build-require\")\n    c.assert_listed_binary({\"androidndk/0.1\": (\"c11e463c49652ba9c5adc62573ee49f966bd8417\", \"Build\")},\n                           build=True)\n    assert \"androidndk/0.1: Calling build()\" in c.out\n    # But a different build OS is a different NDK executable\n    c.run(\"create . -pr:b=linux -pr:h=android  --build-require\")\n    c.assert_listed_binary({\"androidndk/0.1\": (\"63fead0844576fc02943e16909f08fcdddd6f44b\", \"Build\")},\n                           build=True)\n    assert \"androidndk/0.1: Calling build()\" in c.out\n\n    # IMPORTANT: The consumption via test_package allows specifying the type of requires\n    # in this case: None, as this is intended to be injected via profile [tool_requires]\n    # can be tested like that\n    c.run(\"remove * -c\")\n    c.save({\"test_package/conanfile.py\": test})\n\n    # Creating the NDK packages for Windows, Linux\n    c.run(\"create . -pr:b=windows -pr:h=android --build-require\")\n    c.assert_listed_binary({\"androidndk/0.1\": (\"522dcea5982a3f8a5b624c16477e47195da2f84f\", \"Build\")},\n                           build=True)\n    assert \"androidndk/0.1 (test package): NDK LIBS: ['libndklib-armv7']!!!\" in c.out\n    assert \"androidndk/0.1 (test package): MYNDK-Windows-x86_64 exe!\" in c.out\n    assert \"androidndk/0.1 (test package): MY-VAR: android-armv7\" in c.out\n    # The same NDK can be used for different architectures, this should not require a new NDK build\n    c.run(\"create . -pr:b=windows -pr:h=android -s:h arch=armv8 --build=missing --build-require\")\n    c.assert_listed_binary({\"androidndk/0.1\": (\"522dcea5982a3f8a5b624c16477e47195da2f84f\", \"Cache\")},\n                           build=True)\n    assert \"androidndk/0.1: Already installed!\" in c.out\n    assert \"androidndk/0.1 (test package): NDK LIBS: ['libndklib-armv8']!!!\" in c.out\n    assert \"androidndk/0.1 (test package): MYNDK-Windows-x86_64 exe!\" in c.out\n    assert \"androidndk/0.1 (test package): MY-VAR: android-armv8\" in c.out\n\n    # But a different build architecture is a different NDK executable\n    c.run(\"create . -pr:b=windows -s:b arch=x86 -pr:h=android --build=missing --build-require\")\n    c.assert_listed_binary({\"androidndk/0.1\": (\"c11e463c49652ba9c5adc62573ee49f966bd8417\", \"Build\")},\n                           build=True)\n    assert \"androidndk/0.1: Calling build()\" in c.out\n    assert \"androidndk/0.1 (test package): NDK LIBS: ['libndklib-armv7']!!!\" in c.out\n    assert \"androidndk/0.1 (test package): MYNDK-Windows-x86 exe!\" in c.out\n    assert \"androidndk/0.1 (test package): MY-VAR: android-armv7\" in c.out\n\n    # But a different build OS is a different NDK executable\n    c.run(\"create . -pr:b=linux -pr:h=android --build=missing --build-require\")\n    c.assert_listed_binary({\"androidndk/0.1\": (\"63fead0844576fc02943e16909f08fcdddd6f44b\", \"Build\")},\n                           build=True)\n    assert \"androidndk/0.1: Calling build()\" in c.out\n    assert \"androidndk/0.1 (test package): NDK LIBS: ['libndklib-armv7']!!!\" in c.out\n    assert \"androidndk/0.1 (test package): MYNDK-Linux-x86_64 exe!\" in c.out\n    assert \"androidndk/0.1 (test package): MY-VAR: android-armv7\" in c.out\n\n    # Now any other package can use it\n    c.save({\"conanfile.py\": test,\n            \"windows\": windows,\n            \"linux\": linux,\n            \"android\": android}, clean_first=True)\n    c.run(\"install . -pr:b=windows -pr:h=android\")\n    c.assert_listed_binary({\"androidndk/0.1\": (\"522dcea5982a3f8a5b624c16477e47195da2f84f\", \"Cache\")},\n                           build=True)\n    assert \"conanfile.py: NDK LIBS: ['libndklib-armv7']!!!\" in c.out\n    assert \"conanfile.py: MYNDK-Windows-x86_64 exe!\" in c.out\n    # And build on the fly the NDK if not binary exists\n    c.run(\"install . -pr:b=linux -s:b arch=x86 -pr:h=android -s:h arch=armv8 --build=missing\")\n    c.assert_listed_binary({\"androidndk/0.1\": (\"f14494c6e4810a63f050d6f5f37e9776ed48d3c9\", \"Build\")},\n                           build=True)\n    assert \"conanfile.py: NDK LIBS: ['libndklib-armv8']!!!\" in c.out\n    assert \"conanfile.py: MYNDK-Linux-x86 exe!\" in c.out\n    assert \"conanfile.py: MY-VAR: android-armv8\" in c.out\n\n\ndef test_libcxx():\n    \"\"\" emulates a package for libcxx, containing only a library to link with\n    \"\"\"\n    c = TestClient()\n    macos = textwrap.dedent(\"\"\"\n        [settings]\n        os=Macos\n        arch = x86_64\n        build_type = Release\n        compiler=apple-clang\n        compiler.version=12.0\n        compiler.cppstd=14\n        compiler.libcxx=libc++\n        \"\"\")\n    ios = textwrap.dedent(\"\"\"\\\n        [settings]\n        os=iOS\n        os.version = 14.3\n        os.sdk = iphoneos\n        arch = armv7\n        build_type = Release\n        compiler=apple-clang\n        compiler.version=11.0\n        compiler.cppstd=14\n        compiler.libcxx=libc++\n\n        [tool_requires]\n        libcxx/0.1\n        \"\"\")\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import save, copy\n        class Pkg(ConanFile):\n            name = \"libcxx\"\n            version = \"0.1\"\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n\n            def build(self):\n                # HERE IT MUST USE THE SETTINGS-TARGET for CREATING THE BINARIES\n                arch = self.settings_target.arch\n                os_ = self.settings_target.os\n                phone_sdk = self.settings_target.get_safe(\"os.sdk\") or \"\"\n                save(self, f\"lib/libcxx-{arch}\", f\"libcxx{phone_sdk}-{os_}-{arch}!\")\n\n            def package(self):\n                copy(self, \"*\", src=self.build_folder, dst=self.package_folder)\n\n            def package_info(self):\n                arch = self.settings_target.arch\n                self.cpp_info.libs = [f\"libcxx-{arch}\"]\n\n            def package_id(self):\n                self.info.settings.clear()\n                self.info.settings_target = self.settings_target\n        \"\"\")\n    test = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import load\n        class Pkg(ConanFile):\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n\n            def generate(self):\n                libcxx = self.dependencies.build[\"libcxx\"]\n                libcxx_lib = libcxx.cpp_info.libs[0]\n                self.output.info(f\"LIBCXX LIBS: {libcxx_lib}!!!\")\n                libcxx_path = os.path.join(libcxx.package_folder, \"lib\", libcxx_lib)\n                self.output.info(load(self, libcxx_path))\n\n            def test(self):\n                pass\n        \"\"\")\n\n    c.save({\"conanfile.py\": conanfile,\n            \"test_package/conanfile.py\": test,\n            \"macos\": macos,\n            \"ios\": ios})\n\n    c.run(\"create . -pr:b=macos -pr:h=ios --build-require\")\n    c.assert_listed_binary({\"libcxx/0.1\": (\"cd83035dfa71d83329e31a13b54b03fd38836815\", \"Build\")},\n                           build=True)\n    assert \"libcxx/0.1 (test package): LIBCXX LIBS: libcxx-armv7!!!\" in c.out\n    assert \"libcxx/0.1 (test package): libcxxiphoneos-iOS-armv7!\" in c.out\n\n    # Same host profile should be same binary, the build profile is not factored in\n    c.run(\"create . -pr:b=macos -s:b build_type=Debug -s:b arch=armv8 -pr:h=ios \"\n          \"--build=missing --build-require\")\n    c.assert_listed_binary({\"libcxx/0.1\": (\"cd83035dfa71d83329e31a13b54b03fd38836815\", \"Cache\")},\n                           build=True)\n    assert \"libcxx/0.1 (test package): LIBCXX LIBS: libcxx-armv7!!!\" in c.out\n    assert \"libcxx/0.1 (test package): libcxxiphoneos-iOS-armv7!\" in c.out\n\n    # But every change in host, is a different binary\n    c.run(\"create . -pr:b=macos -pr:h=ios -s:h arch=armv8 --build=missing --build-require\")\n    c.assert_listed_binary({\"libcxx/0.1\": (\"af2d5e0458816f1d7e61c82315d143c20e3db2e3\", \"Build\")},\n                           build=True)\n    assert \"libcxx/0.1 (test package): LIBCXX LIBS: libcxx-armv8!!!\" in c.out\n    assert \"libcxx/0.1 (test package): libcxxiphoneos-iOS-armv8!\" in c.out\n\n    # But every change in host, is a different binary\n    c.run(\"create . -pr:b=macos -pr:h=ios -s:h arch=armv8 -s:h os.sdk=iphonesimulator \"\n          \"--build-require\")\n    c.assert_listed_binary({\"libcxx/0.1\": (\"c7e3b0fbb4fac187f59bf97e7958631b96fda2a6\", \"Build\")},\n                           build=True)\n    assert \"libcxx/0.1 (test package): LIBCXX LIBS: libcxx-armv8!!!\" in c.out\n    assert \"libcxx/0.1 (test package): libcxxiphonesimulator-iOS-armv8!\" in c.out\n\n    # Now any other package can use it\n    c.save({\"conanfile.py\": test,\n            \"macos\": macos,\n            \"ios\": ios}, clean_first=True)\n    c.run(\"install . -pr:b=macos -pr:h=ios\")\n    c.assert_listed_binary({\"libcxx/0.1\": (\"cd83035dfa71d83329e31a13b54b03fd38836815\", \"Cache\")},\n                           build=True)\n    assert \"conanfile.py: LIBCXX LIBS: libcxx-armv7!!!\" in c.out\n    assert \"conanfile.py: libcxxiphoneos-iOS-armv7!\" in c.out\n\n\ndef test_compiler_gcc():\n    \"\"\" this is testing a gcc-like cross-compiler that needs the gcc.exe binary to compile\n    and can also contain a specific libcxx for the target architecture\n    \"\"\"\n    c = TestClient()\n    # build machine\n    linux = textwrap.dedent(\"\"\"\n        [settings]\n        os=Linux\n        arch = x86_64\n        build_type = Release\n        compiler=gcc\n        compiler.version=11\n        compiler.cppstd=14\n        compiler.libcxx=libstdc++11\n        \"\"\")\n    rpi = textwrap.dedent(\"\"\"\\\n        [settings]\n        os=Linux\n        arch = armv7\n        build_type = Release\n\n        [tool_requires]\n        gcc/0.1\n        \"\"\")\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import save, copy\n        class Pkg(ConanFile):\n            name = \"gcc\"\n            version = \"0.1\"\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n\n            def build(self):\n                # HERE IT MUST USE THE SETTINGS-TARGET for CREATING THE LIBCXX\n                # BUT SETTINGS for CREATING THE GCC.EXE\n                arch = self.settings_target.arch\n                os_ = self.settings_target.os\n                save(self, f\"lib/libcxx-{arch}\", f\"libcxx-{os_}-{arch}!\")\n                save(self, \"bin/gcc\", f\"gcc-{self.settings.os}-{self.settings.arch}\")\n\n            def package(self):\n                copy(self, \"*\", src=self.build_folder, dst=self.package_folder)\n\n            def package_info(self):\n                arch = self.settings_target.arch\n                self.cpp_info.libs = [f\"libcxx-{arch}\"]\n\n            def package_id(self):\n                self.info.settings_target = self.settings_target\n        \"\"\")\n    test = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import load\n        class Pkg(ConanFile):\n            settings = \"os\", \"arch\", \"build_type\"\n\n            def generate(self):\n                gcc = self.dependencies.build[\"gcc\"]\n                libcxx_lib = gcc.cpp_info.libs[0]\n                self.output.info(f\"LIBCXX LIBS: {libcxx_lib}!!!\")\n                libcxx_path = os.path.join(gcc.package_folder, \"lib\", libcxx_lib)\n                self.output.info(load(self, libcxx_path))\n                gcc_path = os.path.join(gcc.package_folder, \"bin/gcc\")\n                self.output.info(load(self, gcc_path))\n\n            def test(self):\n                pass\n        \"\"\")\n\n    c.save({\"conanfile.py\": conanfile,\n            \"test_package/conanfile.py\": test,\n            \"linux\": linux,\n            \"rpi\": rpi})\n\n    c.run(\"create . -pr:b=linux -pr:h=rpi --build-require\")\n    c.assert_listed_binary({\"gcc/0.1\": (\"6190ea2804cd4777609ec7174ccfdee22c6318c3\", \"Build\")},\n                           build=True)\n    assert \"gcc/0.1 (test package): LIBCXX LIBS: libcxx-armv7!!!\" in c.out\n    assert \"gcc/0.1 (test package): libcxx-Linux-armv7!\" in c.out\n    assert \"gcc/0.1 (test package): gcc-Linux-x86_64\" in c.out\n\n    # Same host profile, but different build profile is a different binary\n    c.run(\"create . -pr:b=linux  -s:b os=Windows -s:b arch=armv8 -pr:h=rpi --build-require\")\n    c.assert_listed_binary({\"gcc/0.1\": (\"687fdc5f43017300a98643948869b4c5560ca82c\", \"Build\")},\n                           build=True)\n    assert \"gcc/0.1 (test package): LIBCXX LIBS: libcxx-armv7!!!\" in c.out\n    assert \"gcc/0.1 (test package): libcxx-Linux-armv7!\" in c.out\n    assert \"gcc/0.1 (test package): gcc-Windows-armv8\" in c.out\n\n    # Same build but different host is also a new binary\n    c.run(\"create . -pr:b=linux -pr:h=rpi -s:h arch=armv8 --build=missing --build-require\")\n    c.assert_listed_binary({\"gcc/0.1\": (\"0521de9a6b94083bd47474a51570a3b856b77406\", \"Build\")},\n                           build=True)\n    assert \"gcc/0.1 (test package): LIBCXX LIBS: libcxx-armv8!!!\" in c.out\n    assert \"gcc/0.1 (test package): libcxx-Linux-armv8!\" in c.out\n    assert \"gcc/0.1 (test package): gcc-Linux-x86_64\" in c.out\n    # check the list packages\n    c.run(\"list gcc/0.1:* --format=json\", redirect_stdout=\"packages.json\")\n    pkgs_json = json.loads(c.load(\"packages.json\"))\n    pref = PkgReference.loads(\"gcc/0.1#a8d725d9988de633accf410fb04cd162:\"\n                              \"6190ea2804cd4777609ec7174ccfdee22c6318c3\")\n    settings_target = {\n        \"arch\": \"armv7\",\n        \"build_type\": \"Release\",\n        \"os\": \"Linux\"\n    }\n    revision_dict = pkgs_json[\"Local Cache\"][\"gcc/0.1\"][\"revisions\"][pref.ref.revision]\n    assert settings_target == revision_dict[\"packages\"][pref.package_id][\"info\"][\"settings_target\"]\n"
  },
  {
    "path": "test/integration/cache/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/cache/backup_sources_test.py",
    "content": "import json\nimport os\nimport textwrap\nimport uuid\nfrom unittest import mock\n\nimport bottle\nimport pytest\nfrom bottle import static_file, HTTPError, request\nfrom webtest import TestApp\n\nfrom conan.internal.errors import NotFoundException\nfrom conan.errors import ConanException\nfrom conan.test.utils.file_server import TestFileServer\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import save, load, rmdir, mkdir, remove\n\n\nclass TestDownloadCacheBackupSources:\n    def test_users_download_cache_summary(self):\n        def custom_download(this, url, filepath, *args, **kwargs):  # noqa\n            assert not url.startswith(\"http://myback\")\n            save(filepath, f\"Hello, world!\")\n\n        with mock.patch(\"conan.internal.rest.file_downloader.FileDownloader.download\",\n                        custom_download):\n            client = TestClient(default_server_user=True, light=True)\n            tmp_folder = temp_folder()\n            client.save_home(\n                {\"global.conf\": f\"core.sources:download_cache={tmp_folder}\\n\"\n                                \"core.sources:download_urls=['origin', 'http://myback']\"})\n            sha256 = \"315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3\"\n            conanfile = textwrap.dedent(f\"\"\"\n                from conan import ConanFile\n                from conan.tools.files import download\n                class Pkg(ConanFile):\n                   def source(self):\n                       download(self, \"http://localhost:5000/myfile.txt\", \"myfile.txt\",\n                                sha256=\"{sha256}\")\n                \"\"\")\n            client.save({\"conanfile.py\": conanfile})\n            client.run(\"source .\")\n\n            assert 2 == len(os.listdir(os.path.join(tmp_folder, \"s\")))\n            content = json.loads(load(os.path.join(tmp_folder, \"s\", sha256 + \".json\")))\n            assert \"http://localhost:5000/myfile.txt\" in content[\"references\"][\"unknown\"]\n            assert len(content[\"references\"][\"unknown\"]) == 1\n\n            conanfile = textwrap.dedent(f\"\"\"\n                from conan import ConanFile\n                from conan.tools.files import download\n                class Pkg2(ConanFile):\n                    name = \"pkg\"\n                    version = \"1.0\"\n                    def source(self):\n                        download(self, \"http://localhost.mirror:5000/myfile.txt\", \"myfile.txt\",\n                                 sha256=\"{sha256}\")\n                \"\"\")\n            client.save({\"conanfile.py\": conanfile})\n            client.run(\"source .\")\n\n            assert 2 == len(os.listdir(os.path.join(tmp_folder, \"s\")))\n            content = json.loads(load(os.path.join(tmp_folder, \"s\", sha256 + \".json\")))\n            assert \"http://localhost.mirror:5000/myfile.txt\" in content[\"references\"][\"pkg/1.0\"]\n            assert len(content[\"references\"][\"pkg/1.0\"]) == 1\n\n            # Ensure the cache is working and we didn't break anything by modifying the summary\n            client.run(\"source .\")\n            assert \"Downloading file\" not in client.out\n\n            client.run(\"create . --user=barbarian\")\n            content = json.loads(load(os.path.join(tmp_folder, \"s\", sha256 + \".json\")))\n            assert content[\"references\"][\"pkg/1.0@barbarian\"] == \\\n                   [\"http://localhost.mirror:5000/myfile.txt\"]\n\n            client.run(\"create . --user=barbarian --channel=stable\")\n            content = json.loads(load(os.path.join(tmp_folder, \"s\", sha256 + \".json\")))\n            assert content[\"references\"][\"pkg/1.0@barbarian/stable\"] == \\\n                   [\"http://localhost.mirror:5000/myfile.txt\"]\n\n    @pytest.fixture(autouse=True)\n    def _setup(self):\n        self.client = TestClient(default_server_user=True, light=True)\n        self.file_server = TestFileServer()\n        self.client.servers[\"file_server\"] = self.file_server\n        self.download_cache_folder = temp_folder()\n\n    def test_upload_sources_backup(self):\n        http_server_base_folder_backups = os.path.join(self.file_server.store, \"backups\")\n        http_server_base_folder_internet = os.path.join(self.file_server.store, \"internet\")\n\n        save(os.path.join(http_server_base_folder_internet, \"myfile.txt\"), \"Hello, world!\")\n        save(os.path.join(self.file_server.store, \"mycompanystorage\", \"mycompanyfile.txt\"),\n             \"Business stuff\")\n        save(os.path.join(http_server_base_folder_internet, \"duplicated1.txt\"), \"I am duplicated #1\")\n        save(os.path.join(self.file_server.store, \"mycompanystorage2\", \"duplicated2.txt\"),\n             \"I am duplicated #2\")\n\n        hello_world_sha256 = \"315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3\"\n        mycompanyfile_sha256 = \"7f1d5d6ae44eb93061b0e07661bd8cbac95a7c51fa204570bf7e24d877d4a224\"\n        duplicated1_sha256 = \"744aca0436e2e355c285fa926a37997df488544589cec2260fc9db969a3c78df\"\n        duplicated2_sha256 = \"66ba2ba05211da3b0b0cb0a08f18e1d9077e7321c2be27887371ec37fade376d\"\n\n        conanfile = textwrap.dedent(f\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import download\n            class Pkg2(ConanFile):\n                name = \"pkg\"\n                version = \"1.0\"\n                def source(self):\n                    download(self, \"{self.file_server.fake_url}/internet/myfile.txt\",\n                            \"myfile.txt\",\n                             sha256=\"{hello_world_sha256}\")\n\n                    download(self, \"{self.file_server.fake_url}/mycompanystorage/mycompanyfile.txt\",\n                            \"mycompanyfile.txt\",\n                             sha256=\"{mycompanyfile_sha256}\")\n\n                    download(self, [\"{self.file_server.fake_url}/mycompanystorage/duplicated1.txt\",\n                                    \"{self.file_server.fake_url}/internet/duplicated1.txt\"],\n                            \"duplicated1.txt\",\n                            sha256=\"{duplicated1_sha256}\")\n\n                    download(self, [\"{self.file_server.fake_url}/internet/duplicated1.txt\"],\n                            \"duplicated1.txt\",\n                            sha256=\"{duplicated1_sha256}\")\n\n                    download(self, [\"{self.file_server.fake_url}/mycompanystorage/duplicated2.txt\",\n                                    \"{self.file_server.fake_url}/mycompanystorage2/duplicated2.txt\"],\n                            \"duplicated2.txt\",\n                            sha256=\"{duplicated2_sha256}\")\n\n                    download(self, \"{self.file_server.fake_url}/mycompanystorage2/duplicated2.txt\",\n                            \"duplicated2.txt\",\n                            sha256=\"{duplicated2_sha256}\")\n            \"\"\")\n\n        # Ensure that a None url is only warned about but no exception is thrown,\n        # this is possible in CI systems that substitute an env var and fail to give it a value\n        self.client.save_home(\n            {\"global.conf\": f\"core.sources:download_cache={self.download_cache_folder}\\n\"\n                            f\"core.sources:download_urls=[None, 'origin', '{self.file_server.fake_url}/backups/']\\n\"\n                            f\"core.sources:upload_url={self.file_server.fake_url}/backups/\"})\n\n        self.client.save({\"conanfile.py\": conanfile})\n        self.client.run(\"create .\", assert_error=True)\n        assert \"Trying to download sources from None backup remote\" in self.client.out\n\n        self.client.save_home(\n            {\"global.conf\": f\"core.sources:download_cache={self.download_cache_folder}\\n\"\n                            f\"core.sources:download_urls=['origin', '{self.file_server.fake_url}/backups/']\\n\"\n                            f\"core.sources:upload_url={self.file_server.fake_url}/backups/\\n\"\n                            f\"core.sources:exclude_urls=['{self.file_server.fake_url}/mycompanystorage/', \"\n                            f\"'{self.file_server.fake_url}/mycompanystorage2/']\"})\n        self.client.run(\"create .\")\n\n        self.client.run(\"upload * -c -r=default\")\n\n        # To test #15501 that it works even with extra files in the local cache\n        extra_file_path = os.path.join(self.download_cache_folder, \"s\", \"extrafile\")\n        save(extra_file_path, \"Hello, world!\")\n        self.client.run(\"upload * -c -r=default\", assert_error=True)\n        assert \"Missing metadata file for backup source\" in self.client.out\n        os.unlink(extra_file_path)\n\n        server_contents = os.listdir(http_server_base_folder_backups)\n        assert hello_world_sha256 in server_contents\n        assert hello_world_sha256 + \".json\" in server_contents\n        # Its only url is excluded, should not be there\n        assert mycompanyfile_sha256 not in server_contents\n        assert mycompanyfile_sha256 + \".json\" not in server_contents\n        # It has an excluded url, but another that is not, it should be there\n        assert duplicated1_sha256 in server_contents\n        assert duplicated1_sha256 + \".json\" in server_contents\n        # All its urls are excluded, it shoud not be there\n        assert duplicated2_sha256 not in server_contents\n        assert duplicated2_sha256 + \".json\" not in server_contents\n\n        self.client.run(\"upload * -c -r=default\")\n        assert \"already in server, skipping upload\" in self.client.out\n\n        # Clear de local cache\n        rmdir(self.download_cache_folder)\n        mkdir(self.download_cache_folder)\n        # Everything the same, but try to download from backup first\n        self.client.save_home(\n            {\"global.conf\": f\"core.sources:download_cache={self.download_cache_folder}\\n\"\n                            f\"core.sources:download_urls=['{self.file_server.fake_url}/backups/', 'origin']\\n\"\n                            f\"core.sources:upload_url={self.file_server.fake_url}/backups/\\n\"\n                            f\"core.sources:exclude_urls=['{self.file_server.fake_url}/mycompanystorage/', '{self.file_server.fake_url}/mycompanystorage2/']\"})\n        self.client.run(\"source .\")\n        assert f\"Sources for {self.file_server.fake_url}/internet/myfile.txt found in remote backup\" in self.client.out\n        assert f\"File {self.file_server.fake_url}/mycompanystorage/mycompanyfile.txt not found in {self.file_server.fake_url}/backups/\" in self.client.out\n\n        # Ensure defaults backup folder works if it's not set in global.conf\n        # (The rest is needed to exercise the rest of the code)\n        self.client.save_home(\n            {\"global.conf\": f\"core.sources:download_urls=['{self.file_server.fake_url}/backups/', 'origin']\\n\"\n                            f\"core.sources:exclude_urls=['{self.file_server.fake_url}/mycompanystorage/', '{self.file_server.fake_url}/mycompanystorage2/']\"})\n        self.client.run(\"source .\")\n        assert f\"Sources for {self.file_server.fake_url}/internet/myfile.txt found in remote backup\" in self.client.out\n        assert f\"File {self.file_server.fake_url}/mycompanystorage/mycompanyfile.txt not found in {self.file_server.fake_url}/backups/\" in self.client.out\n\n    def test_unknown_handling(self):\n        http_server_base_folder_internet = os.path.join(self.file_server.store, \"internet\")\n\n        save(os.path.join(http_server_base_folder_internet, \"myfile.txt\"), \"Hello, world!\")\n\n        sha256 = \"315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3\"\n        conanfile = textwrap.dedent(f\"\"\"\n                            from conan import ConanFile\n                            from conan.tools.files import download\n                            class Pkg2(ConanFile):\n                                name = \"pkg\"\n                                def source(self):\n                                    download(self, \"{self.file_server.fake_url}/internet/myfile.txt\",\n                                             \"myfile.txt\",\n                                             sha256=\"{sha256}\")\n                            \"\"\")\n\n        self.client.save_home(\n            {\"global.conf\": f\"core.sources:download_cache={self.download_cache_folder}\\n\"\n                            f\"core.sources:download_urls=['origin']\\n\"\n                            f\"core.sources:upload_url={self.file_server.fake_url}/backups/\"})\n\n        self.client.save({\"conanfile.py\": conanfile})\n        self.client.run(\"source .\")\n        json_path = os.path.join(self.download_cache_folder, \"s\", sha256 + \".json\")\n        contents = json.loads(load(json_path))\n        assert \"unknown\" in contents[\"references\"]\n\n        s_folder = os.path.join(self.download_cache_folder, \"s\")\n        assert len(os.listdir(s_folder)) == 2\n\n        self.client.run(\"export . --version=1.0\")\n        self.client.run(\"upload * -c -r=default\")\n        assert \"No backup sources files to upload\" in self.client.out\n\n        self.client.run(\"cache clean --backup-sources\")\n        assert len(os.listdir(s_folder)) == 0\n\n    def test_download_origin_first(self):\n        http_server_base_folder_internet = os.path.join(self.file_server.store, \"internet\")\n\n        save(os.path.join(http_server_base_folder_internet, \"myfile.txt\"), \"Hello, world!\")\n\n        sha256 = \"315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3\"\n        conanfile = textwrap.dedent(f\"\"\"\n                    from conan import ConanFile\n                    from conan.tools.files import download\n                    class Pkg2(ConanFile):\n                        name = \"pkg\"\n                        version = \"1.0\"\n                        def source(self):\n                            download(self, \"{self.file_server.fake_url}/internet/myfile.txt\", \"myfile.txt\",\n                                     sha256=\"{sha256}\")\n                    \"\"\")\n\n        self.client.save_home(\n            {\"global.conf\": f\"core.sources:download_cache={self.download_cache_folder}\\n\"\n                            f\"core.sources:download_urls=['origin', '{self.file_server.fake_url}/backup/']\\n\"\n                            f\"core.sources:upload_url={self.file_server.fake_url}/backup/\"})\n\n        self.client.save({\"conanfile.py\": conanfile})\n        self.client.run(\"create .\")\n        self.client.run(\"upload * -c -r=default\")\n\n        rmdir(self.download_cache_folder)\n\n        self.client.run(\"source .\")\n        assert f\"Sources for {self.file_server.fake_url}/internet/myfile.txt found in origin\" in self.client.out\n        self.client.run(\"source .\")\n        assert f\"Source {self.file_server.fake_url}/internet/myfile.txt retrieved from local download cache\" in self.client.out\n\n    def test_download_origin_last(self):\n        http_server_base_folder_internet = os.path.join(self.file_server.store, \"internet\")\n\n        save(os.path.join(http_server_base_folder_internet, \"myfile.txt\"), \"Hello, world!\")\n\n        sha256 = \"315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3\"\n        conanfile = textwrap.dedent(f\"\"\"\n                    from conan import ConanFile\n                    from conan.tools.files import download\n                    class Pkg2(ConanFile):\n                        name = \"pkg\"\n                        version = \"1.0\"\n                        def source(self):\n                            download(self, \"{self.file_server.fake_url}/internet/myfile.txt\", \"myfile.txt\",\n                                     sha256=\"{sha256}\")\n                    \"\"\")\n\n        self.client.save_home(\n            {\"global.conf\": f\"core.sources:download_cache={self.download_cache_folder}\\n\"\n                            f\"core.sources:download_urls=['{self.file_server.fake_url}/backup', 'origin']\\n\"\n                            f\"core.sources:upload_url={self.file_server.fake_url}/backup\"})\n\n        self.client.save({\"conanfile.py\": conanfile})\n        self.client.run(\"create . -vv\")\n        assert f\"WARN: File {self.file_server.fake_url}/internet/myfile.txt not found in {self.file_server.fake_url}/backup/\" in self.client.out\n        assert f\"Downloaded {self.file_server.fake_url}/internet/myfile.txt from {self.file_server.fake_url}/internet/myfile.txt\"\n        self.client.run(\"upload * -c -r=default\")\n\n        rmdir(self.download_cache_folder)\n\n        self.client.run(\"source .\")\n        assert f\"Sources for {self.file_server.fake_url}/internet/myfile.txt found in remote backup\" in self.client.out\n        self.client.run(\"source .\")\n        assert f\"Source {self.file_server.fake_url}/internet/myfile.txt retrieved from local download cache\" in self.client.out\n\n    def test_sources_backup_server_error_500(self):\n        conanfile = textwrap.dedent(f\"\"\"\n           from conan import ConanFile\n           from conan.tools.files import download\n           class Pkg2(ConanFile):\n               name = \"pkg\"\n               version = \"1.0\"\n               def source(self):\n                   download(self, \"{self.file_server.fake_url}/internet/myfile.txt\", \"myfile.txt\",\n                            sha256=\"unused\")\n           \"\"\")\n\n        self.client.save_home(\n            {\"global.conf\": f\"core.sources:download_cache={self.download_cache_folder}\\n\"\n                            f\"core.sources:download_urls=['{self.file_server.fake_url}/internal_error/', \"\n                            f\"'{self.file_server.fake_url}/unused/']\\n\"})\n        self.client.save({\"conanfile.py\": conanfile})\n        self.client.run(\"create .\", assert_error=True)\n        assert \"ConanException: Error 500 downloading file\" in self.client.out\n\n    def test_sources_backup_server_not_found(self):\n        conanfile = textwrap.dedent(f\"\"\"\n           from conan import ConanFile\n           from conan.tools.files import download\n           class Pkg2(ConanFile):\n               name = \"pkg\"\n               version = \"1.0\"\n               def source(self):\n                   download(self, \"{self.file_server.fake_url}/internet/myfile.txt\", \"myfile.txt\",\n                            sha256=\"unused\")\n           \"\"\")\n\n        self.client.save_home(\n            {\"global.conf\": f\"core.sources:download_cache={self.download_cache_folder}\\n\"\n                            f\"core.download:retry=0\\n\"\n                            f\"core.sources:download_urls=['error_server', 'origin']\\n\"})\n\n        self.client.save({\"conanfile.py\": conanfile})\n        self.client.run(\"create .\", assert_error=True)\n        assert \"ConanException: Error downloading file\" in self.client.out\n\n    def test_upload_sources_backup_creds_needed(self):\n        client = TestClient(default_server_user=True, light=True)\n        download_cache_folder = temp_folder()\n        http_server_base_folder_backups = temp_folder()\n        http_server_base_folder_internet = temp_folder()\n\n        save(os.path.join(http_server_base_folder_internet, \"myfile.txt\"), \"Hello, world!\")\n\n        class TestFileServer2:\n\n            def __init__(self):\n                self.fake_url = \"http://fake%s.com\" % str(uuid.uuid4()).replace(\"-\", \"\")\n                self.root_app = bottle.Bottle()\n                self.app = TestApp(self.root_app)\n                self._attach_to(self.root_app)\n\n            @staticmethod\n            def _attach_to(app):\n                def valid_auth(token):\n                    auth = request.headers.get(\"Authorization\")\n                    if auth == f\"Bearer {token}\":\n                        return\n                    return HTTPError(401, \"Authentication required\")\n\n                @app.route(\"/internet/<file>\", method=[\"GET\"])\n                def get_internet_file(file):\n                    return static_file(file, http_server_base_folder_internet)\n\n                @app.route(\"/downloader/<file>\", method=[\"GET\"])\n                def get_file(file):\n                    ret = valid_auth(\"mytoken\")\n                    return ret or static_file(file, http_server_base_folder_backups)\n\n                @app.route(\"/uploader/<file>\", method=[\"PUT\"])\n                def put_file(file):\n                    ret = valid_auth(\"myuploadtoken\")\n                    if ret:\n                        return ret\n                    dest = os.path.join(http_server_base_folder_backups, file)\n                    with open(dest, 'wb') as f:\n                        f.write(request.body.read())\n\n        http_server = TestFileServer2()\n        client.servers[\"file_server\"] = http_server\n\n        sha256 = \"315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3\"\n        conanfile = textwrap.dedent(f\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import download, load\n            class Pkg2(ConanFile):\n                name = \"pkg\"\n                version = \"1.0\"\n                def source(self):\n                    download(self, \"{http_server.fake_url}/internet/myfile.txt\", \"myfile.txt\",\n                             sha256=\"{sha256}\")\n                    self.output.info(f\"CONTENT: {{load(self, 'myfile.txt')}}\")\n            \"\"\")\n\n        client.save_home(\n            {\"global.conf\": f\"core.sources:download_cache={download_cache_folder}\\n\"\n                            f\"core.sources:download_urls=['{http_server.fake_url}/downloader/', 'origin']\\n\"\n                            f\"core.sources:upload_url={http_server.fake_url}/uploader/\"})\n\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create .\", assert_error=True)\n        assert f\"ConanException: Authentication to source backup server '{http_server.fake_url}\" \\\n               f\"/downloader/' failed\" in client.out\n        content = {\"credentials\": [\n            {\"url\": f\"{http_server.fake_url}\", \"token\": \"mytoken\"}\n        ]}\n        save(os.path.join(client.cache_folder, \"source_credentials.json\"), json.dumps(content))\n\n        client.run(\"create .\")\n        assert \"CONTENT: Hello, world!\" in client.out\n        client.run(\"upload * -c -r=default\", assert_error=True)\n        assert f\"Authentication to source backup server '{http_server.fake_url}\" \\\n               f\"/uploader/' failed\" in client.out\n        content = {\"credentials\": [\n            {\"url\": f\"{http_server.fake_url}\", \"token\": \"myuploadtoken\"}\n        ]}\n        # Now use the correct UPLOAD token\n        save(os.path.join(client.cache_folder, \"source_credentials.json\"), json.dumps(content))\n        client.run(\"upload * -c -r=default --force\")  # need --force to guarantee cached updated\n\n        server_contents = os.listdir(http_server_base_folder_backups)\n        assert sha256 in server_contents\n        assert sha256 + \".json\" in server_contents\n\n        client.run(\"upload * -c -r=default\")\n        assert \"already in server, skipping upload\" in client.out\n\n        content = {\"credentials\": [\n            {\"url\": f\"{http_server.fake_url}\", \"token\": \"mytoken\"}\n        ]}\n\n        save(os.path.join(client.cache_folder, \"source_credentials.json\"), json.dumps(content))\n        rmdir(download_cache_folder)\n\n        # Remove the \"remote\" myfile.txt so if it raises\n        # we know it tried to download the original source\n        os.remove(os.path.join(http_server_base_folder_internet, \"myfile.txt\"))\n\n        client.run(\"source .\")\n        assert f\"Sources for {http_server.fake_url}/internet/myfile.txt found in remote backup\" in client.out\n        assert \"CONTENT: Hello, world!\" in client.out\n        client.run(\"source .\")\n        assert f\"Source {http_server.fake_url}/internet/myfile.txt retrieved from local download cache\" in client.out\n        assert \"CONTENT: Hello, world!\" in client.out\n\n    def test_download_sources_multiurl(self):\n        http_server_base_folder_internet = os.path.join(self.file_server.store, \"internet\")\n        http_server_base_folder_backup = os.path.join(self.file_server.store, \"backup\")\n        http_server_base_folder_downloader = os.path.join(self.file_server.store, \"downloader\")\n\n        save(os.path.join(http_server_base_folder_internet, \"myfile.txt\"), \"Hello, world!\")\n        sha256 = \"315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3\"\n\n        conanfile = textwrap.dedent(f\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import download\n            class Pkg2(ConanFile):\n                name = \"pkg\"\n                version = \"1.0\"\n                def source(self):\n                    download(self, \"{self.file_server.fake_url}/internet/myfile.txt\", \"myfile.txt\",\n                             sha256=\"{sha256}\")\n            \"\"\")\n\n        self.client.save_home(\n            {\"global.conf\": f\"core.sources:download_cache={self.download_cache_folder}\\n\"\n                            f\"core.sources:upload_url={self.file_server.fake_url}/backup/\\n\"\n                            f\"core.sources:download_urls=['origin', '{self.file_server.fake_url}/downloader/', \"\n                            f\"'{self.file_server.fake_url}/backup/']\"})\n\n        self.client.save({\"conanfile.py\": conanfile})\n        self.client.run(\"create .\")\n        self.client.run(\"upload * -c -r=default\")\n        # We upload files to second backup,\n        # to ensure that the first one gets skipped in the list but finds in the second one\n        server_contents = os.listdir(http_server_base_folder_backup)\n        assert sha256 in server_contents\n        assert sha256 + \".json\" in server_contents\n\n        rmdir(self.download_cache_folder)\n        # Remove the \"remote\" myfile.txt so if it raises\n        # we know it tried to download the original source\n        remove(os.path.join(http_server_base_folder_internet, \"myfile.txt\"))\n\n        self.client.run(\"source .\")\n        assert f\"Sources for {self.file_server.fake_url}/internet/myfile.txt found in remote backup {self.file_server.fake_url}/backup/\" in self.client.out\n\n        # And if the first one has them, prefer it before others in the list\n        save(os.path.join(http_server_base_folder_downloader, sha256),\n             load(os.path.join(http_server_base_folder_backup, sha256)))\n        save(os.path.join(http_server_base_folder_downloader, sha256 + \".json\"),\n             load(os.path.join(http_server_base_folder_backup, sha256 + \".json\")))\n        rmdir(self.download_cache_folder)\n        self.client.run(\"source .\")\n        assert f\"Sources for {self.file_server.fake_url}/internet/myfile.txt found in remote backup {self.file_server.fake_url}/downloader/\" in self.client.out\n\n    def test_list_urls_miss(self):\n        def custom_download(this, url, *args, **kwargs):  # noqa\n            raise NotFoundException()\n\n        with mock.patch(\"conan.internal.rest.file_downloader.FileDownloader.download\",\n                        custom_download):\n            client = TestClient(default_server_user=True, light=True)\n            download_cache_folder = temp_folder()\n\n            sha256 = \"315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3\"\n\n            conanfile = textwrap.dedent(f\"\"\"\n                from conan import ConanFile\n                from conan.tools.files import download\n                class Pkg2(ConanFile):\n                    name = \"pkg\"\n                    version = \"1.0\"\n                    def source(self):\n                        download(self, \"http://fake/myfile.txt\", \"myfile.txt\", sha256=\"{sha256}\")\n                \"\"\")\n\n            client.save_home(\n                {\"global.conf\": f\"core.sources:download_cache={download_cache_folder}\\n\"\n                                f\"core.sources:download_urls=['origin', 'http://extrafake/']\\n\"})\n            client.save({\"conanfile.py\": conanfile})\n            client.run(\"source .\", assert_error=True)\n            assert \"WARN: Sources for http://fake/myfile.txt failed in 'origin'\" in client.out\n            assert \"WARN: Checking backups\" in client.out\n            assert \"NotFoundException: File http://fake/myfile.txt \" \\\n                   \"not found in ['origin', 'http://extrafake/']\" in client.out\n\n    def test_ok_when_origin_breaks_midway_list(self):\n        http_server_base_folder_backup2 = os.path.join(self.file_server.store, \"backup2\")\n\n        sha256 = \"315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3\"\n        save(os.path.join(http_server_base_folder_backup2, sha256), \"Hello, world!\")\n        save(os.path.join(http_server_base_folder_backup2, sha256 + \".json\"), '{\"references\": {}}')\n\n        conanfile = textwrap.dedent(f\"\"\"\n           from conan import ConanFile\n           from conan.tools.files import download\n           class Pkg2(ConanFile):\n               name = \"pkg\"\n               version = \"1.0\"\n               def source(self):\n                   download(self, \"{self.file_server.fake_url}/internal_error/myfile.txt\", \"myfile.txt\",\n                            sha256=\"{sha256}\")\n           \"\"\")\n\n        self.client.save_home(\n            {\"global.conf\": \"tools.files.download:retry=0\\n\"\n                            f\"core.sources:download_cache={self.download_cache_folder}\\n\"\n                            f\"core.sources:download_urls=['{self.file_server.fake_url}/empty/', \"\n                            f\"'origin', '{self.file_server.fake_url}/backup2/']\\n\"})\n\n        self.client.save({\"conanfile.py\": conanfile})\n        self.client.run(\"create .\")\n        assert f\"Sources for {self.file_server.fake_url}/internal_error/myfile.txt found in remote backup {self.file_server.fake_url}/backup2/\" in self.client.out\n\n    def test_ok_when_origin_authorization_error(self):\n        client = TestClient(default_server_user=True, light=True)\n        download_cache_folder = temp_folder()\n        http_server_base_folder_backup1 = temp_folder()\n        http_server_base_folder_backup2 = temp_folder()\n\n        sha256 = \"315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3\"\n        save(os.path.join(http_server_base_folder_backup2, sha256), \"Hello, world!\")\n        save(os.path.join(http_server_base_folder_backup2, sha256 + \".json\"), '{\"references\": {}}')\n\n        class TestFileServer2:\n\n            def __init__(self, store=None):\n                self.store = store or temp_folder(path_with_spaces=False)\n                mkdir(self.store)\n                self.fake_url = \"http://fake%s.com\" % str(uuid.uuid4()).replace(\"-\", \"\")\n                self.root_app = bottle.Bottle()\n                self.app = TestApp(self.root_app)\n                self._attach_to(self.root_app, self.store)\n\n            @staticmethod\n            def _attach_to(app, store):  # noqa\n                @app.route(\"/internet/<file>\", method=[\"GET\"])\n                def get_internet_file(file):\n                    return HTTPError(401, \"You Are Not Allowed Here\")\n\n                @app.route(\"/downloader1/<file>\", method=[\"GET\"])\n                def get_file(file):\n                    return static_file(file, http_server_base_folder_backup1)\n\n                @app.route(\"/downloader1/<file>\", method=[\"PUT\"])\n                def put_file(file):\n                    if file in os.listdir(http_server_base_folder_backup1):\n                        return HTTPError(401, \"You Are Not Allowed Here\")\n                    dest = os.path.join(http_server_base_folder_backup1, file)\n                    with open(dest, 'wb') as f:\n                        f.write(request.body.read())\n\n                @app.route(\"/downloader2/<file>\", method=[\"GET\"])\n                def get_file_2(file):\n                    return static_file(file, http_server_base_folder_backup2)\n\n        http_server = TestFileServer2()\n        client.servers[\"file_server\"] = http_server\n\n        conanfile = textwrap.dedent(f\"\"\"\n           from conan import ConanFile\n           from conan.tools.files import download\n           class Pkg2(ConanFile):\n               name = \"pkg\"\n               version = \"1.0\"\n               def source(self):\n                   download(self, \"{http_server.fake_url}/internet/myfile.txt\", \"myfile.txt\",\n                            sha256=\"{sha256}\")\n           \"\"\")\n        client.save_home({\"global.conf\": f\"core.sources:download_cache={download_cache_folder}\\n\"\n                          f\"core.sources:download_urls=['{http_server.fake_url}/downloader1/', \"\n                          f\"'origin', '{http_server.fake_url}/downloader2/']\\n\"\n                          f\"core.sources:upload_url={http_server.fake_url}/downloader1/\\n\"\n                          \"core.upload:retry=0\\ncore.download:retry=0\"})\n\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create .\")\n        assert f\"Sources for {http_server.fake_url}/internet/myfile.txt found in remote backup {http_server.fake_url}/downloader2/\" in client.out\n        # TODO: Check better message with Authentication error message\n        assert \"failed in 'origin'\" in client.out\n\n        # Now try to upload once to the first backup server. It's configured so it has write permissions but no overwrite\n        client.run(\"upload * -c -r=default\")\n        upload_server_contents = os.listdir(http_server_base_folder_backup1)\n        assert sha256 in upload_server_contents\n        assert sha256 + \".json\" in upload_server_contents\n\n        client.run(\"remove * -c -r=default\")\n\n        client.run(\"upload * -c -r=default\")\n        assert f\"Could not update summary '{sha256}.json' in backup sources server\" in client.out\n\n    def test_ok_when_origin_bad_sha256(self):\n        http_server_base_folder_internet = os.path.join(self.file_server.store, \"internet\")\n        http_server_base_folder_backup2 = os.path.join(self.file_server.store, \"backup2\")\n\n        sha256 = \"315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3\"\n        # This file's sha is not the one in the line above\n        save(os.path.join(http_server_base_folder_internet, \"myfile.txt\"), \"Bye, world!\")\n        save(os.path.join(http_server_base_folder_backup2, sha256), \"Hello, world!\")\n        save(os.path.join(http_server_base_folder_backup2, sha256 + \".json\"), '{\"references\": {}}')\n\n        conanfile = textwrap.dedent(f\"\"\"\n           from conan import ConanFile\n           from conan.tools.files import download\n           class Pkg2(ConanFile):\n               name = \"pkg\"\n               version = \"1.0\"\n               def source(self):\n                   download(self, \"{self.file_server.fake_url}/internet/myfile.txt\", \"myfile.txt\",\n                            sha256=\"{sha256}\")\n           \"\"\")\n\n        self.client.save_home(\n            {\"global.conf\": f\"core.sources:download_cache={self.download_cache_folder}\\n\"\n                            f\"core.sources:download_urls=['{self.file_server.fake_url}/backup1/', \"\n                            f\"'origin', '{self.file_server.fake_url}/backup2/']\\n\"})\n\n        self.client.save({\"conanfile.py\": conanfile})\n        self.client.run(\"create .\")\n        assert f\"Sources for {self.file_server.fake_url}/internet/myfile.txt found in remote backup {self.file_server.fake_url}/backup2/\" in self.client.out\n        assert \"sha256 hash failed for\" in self.client.out\n\n    def test_export_then_upload_workflow(self):\n        mkdir(os.path.join(self.download_cache_folder, \"s\"))\n\n        http_server_base_folder_internet = os.path.join(self.file_server.store, \"internet\")\n        http_server_base_folder_backup = os.path.join(self.file_server.store, \"backup\")\n\n        sha256 = \"315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3\"\n        save(os.path.join(http_server_base_folder_internet, \"myfile.txt\"), \"Hello, world!\")\n\n        conanfile = textwrap.dedent(f\"\"\"\n           from conan import ConanFile\n           from conan.tools.files import download\n           class Pkg2(ConanFile):\n               name = \"pkg\"\n               version = \"1.0\"\n               def source(self):\n                   download(self, \"{self.file_server.fake_url}/internet/myfile.txt\", \"myfile.txt\",\n                            sha256=\"{sha256}\")\n           \"\"\")\n\n        self.client.save_home(\n            {\"global.conf\": f\"core.sources:download_cache={self.download_cache_folder}\\n\"\n                            f\"core.sources:download_urls=['{self.file_server.fake_url}/backup/', 'origin']\\n\"\n                            f\"core.sources:upload_url={self.file_server.fake_url}/backup/\"})\n\n        self.client.save({\"conanfile.py\": conanfile})\n        self.client.run(\"export .\")\n        self.client.run(\"upload * -c -r=default\")\n        # This used to crash because we were trying to list a missing dir if only exports were made\n        assert \"[Errno 2] No such file or directory\" not in self.client.out\n        self.client.run(\"create .\")\n        self.client.run(\"upload * -c -r=default\")\n        assert sha256 in os.listdir(http_server_base_folder_backup)\n        self.client.run(\"cache clean * -bs\")\n        backups = os.listdir(os.path.join(self.download_cache_folder, \"s\"))\n        assert len(backups) == 0\n\n    def test_export_then_upload_recipe_only_workflow(self):\n        http_server_base_folder_internet = os.path.join(self.file_server.store, \"internet\")\n\n        sha256 = \"315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3\"\n        save(os.path.join(http_server_base_folder_internet, \"myfile.txt\"), \"Hello, world!\")\n\n        conanfile = textwrap.dedent(f\"\"\"\n           from conan import ConanFile\n           from conan.tools.files import download\n           class Pkg2(ConanFile):\n               name = \"pkg\"\n               version = \"1.0\"\n               def source(self):\n                   download(self, \"{self.file_server.fake_url}/internet/myfile.txt\", \"myfile.txt\",\n                            sha256=\"{sha256}\")\n           \"\"\")\n\n        self.client.save_home(\n            {\"global.conf\": f\"core.sources:download_cache={self.download_cache_folder}\\n\"\n                            f\"core.sources:download_urls=['{self.file_server.fake_url}/backup/', 'origin']\\n\"\n                            f\"core.sources:upload_url={self.file_server.fake_url}/backup/\"})\n\n        self.client.save({\"conanfile.py\": conanfile})\n        self.client.run(\"export .\")\n        exported_rev = self.client.exported_recipe_revision()\n        self.client.run(\"upload * --only-recipe -c -r=default\")\n        # This second run used to crash because we thought there would be some packages always\n        self.client.run(\"upload * --only-recipe -c -r=default\")\n        # Ensure we are testing for an already uploaded recipe\n        assert f\"Recipe 'pkg/1.0#{exported_rev}' already in server, skipping upload\" in self.client.out\n\n    @pytest.mark.parametrize(\"unknown\", [True, False])\n    def test_source_then_upload_workflow(self, unknown):\n        mkdir(os.path.join(self.download_cache_folder, \"s\"))\n\n        http_server_base_folder_internet = os.path.join(self.file_server.store, \"internet\")\n        http_server_base_folder_backup = os.path.join(self.file_server.store, \"backup\")\n\n        sha256 = \"315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3\"\n        save(os.path.join(http_server_base_folder_internet, \"myfile.txt\"), \"Hello, world!\")\n\n        conanfile = textwrap.dedent(f\"\"\"\n           from conan import ConanFile\n           from conan.tools.files import download\n           class Pkg2(ConanFile):\n               def source(self):\n                   download(self, \"{self.file_server.fake_url}/internet/myfile.txt\", \"myfile.txt\",\n                            sha256=\"{sha256}\")\n           \"\"\")\n\n        self.client.save_home(\n            {\"global.conf\": f\"core.sources:download_cache={self.download_cache_folder}\\n\"\n                            f\"core.sources:download_urls=['{self.file_server.fake_url}/backup/', 'origin']\\n\"\n                            f\"core.sources:upload_url={self.file_server.fake_url}/backup/\"})\n\n        self.client.save({\"conanfile.py\": conanfile})\n        ref_args = \"\" if unknown else \"--name foo --version 1.0\"\n        reference_key = \"unknown\" if unknown else \"foo/1.0\"\n        self.client.run(f\"source . {ref_args}\")\n        content = json.loads(load(os.path.join(self.download_cache_folder, \"s\", sha256 + \".json\")))\n        assert len(content[\"references\"][reference_key]) == 1\n\n        self.client.run(\"cache backup-upload\")\n        # This used to crash because we were trying to list a missing dir if only exports were made\n        assert \"[Errno 2] No such file or directory\" not in self.client.out\n        assert sha256 in os.listdir(http_server_base_folder_backup)\n\n    def test_backup_source_corrupted_download_handling(self):\n        http_server_base_folder_internet = os.path.join(self.file_server.store, \"internet\")\n\n        sha256 = \"315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3\"\n        save(os.path.join(http_server_base_folder_internet, \"myfile.txt\"), \"Hello, world!\")\n\n        conanfile = textwrap.dedent(f\"\"\"\n           from conan import ConanFile\n           from conan.tools.files import download\n           class Pkg2(ConanFile):\n               def source(self):\n                   download(self, \"{self.file_server.fake_url}/internet/myfile.txt\", \"myfile.txt\",\n                            sha256=\"{sha256}\")\n           \"\"\")\n\n        self.client.save_home(\n            {\"global.conf\": f\"core.sources:download_cache={self.download_cache_folder}\"})\n\n        self.client.save({\"conanfile.py\": conanfile})\n        self.client.run(\"source .\")\n\n        # Now simulate a dirty download, the file is there but the sha256 is wrong\n        save(os.path.join(self.download_cache_folder, \"s\", sha256), \"Bye bye, world!\")\n\n        # Now try to source again, it should eat it up\n        self.client.run(\"source .\")\n\n    @pytest.mark.parametrize(\"exception\", [Exception, ConanException])\n    @pytest.mark.parametrize(\"upload\", [True, False])\n    def test_backup_source_dirty_download_handle(self, exception, upload):\n        def custom_download(this, *args, **kwargs):\n            raise exception()\n\n        http_server_base_folder_internet = os.path.join(self.file_server.store, \"internet\")\n\n        sha256 = \"315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3\"\n        save(os.path.join(http_server_base_folder_internet, \"myfile.txt\"), \"Hello, world!\")\n\n        conanfile = textwrap.dedent(f\"\"\"\n           from conan import ConanFile\n           from conan.tools.files import download\n           class Pkg2(ConanFile):\n               def source(self):\n                   download(self, \"{self.file_server.fake_url}/internet/myfile.txt\", \"myfile.txt\",\n                            sha256=\"{sha256}\")\n           \"\"\")\n\n        self.client.save_home(\n            {\"global.conf\": f\"core.sources:download_cache={self.download_cache_folder}\\n\"\n                            f\"tools.files.download:retry=0\"})\n\n        self.client.save({\"conanfile.py\": conanfile})\n\n        with mock.patch(\"conan.internal.rest.file_downloader.FileDownloader._download_file\",\n                        custom_download):\n            self.client.run(\"source .\", assert_error=True)\n            # The mock does not actually download a file, let's add it for the test\n            save(os.path.join(self.download_cache_folder, \"s\", sha256), \"__corrupted download__\")\n            # Check that the dirty file was not removed.\n            # This check should go away once we refactor dirty handling\n            assert os.path.exists(os.path.join(self.download_cache_folder, \"s\", f\"{sha256}.dirty\"))\n\n        if upload:\n            self.client.run(\"cache backup-upload\")\n        else:\n            self.client.run(\"source .\")\n        assert f\"{sha256} is dirty, removing it\" in self.client.out\n\n    @pytest.mark.parametrize(\"exception\", [Exception, ConanException])\n    def test_backup_source_upload_when_dirty(self, exception):\n        def custom_download(this, *args, **kwargs):  # noqa\n            raise exception()\n\n        mkdir(os.path.join(self.download_cache_folder, \"s\"))\n        http_server_base_folder_internet = os.path.join(self.file_server.store, \"internet\")\n\n        sha256 = \"315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3\"\n        save(os.path.join(http_server_base_folder_internet, \"myfile.txt\"), \"Hello, world!\")\n\n        conanfile = textwrap.dedent(f\"\"\"\n           from conan import ConanFile\n           from conan.tools.files import download\n           class Pkg2(ConanFile):\n               def source(self):\n                   download(self, \"{self.file_server.fake_url}/internet/myfile.txt\", \"myfile.txt\",\n                            sha256=\"{sha256}\")\n           \"\"\")\n\n        self.client.save_home(\n            {\"global.conf\": f\"core.sources:download_cache={self.download_cache_folder}\\n\"\n                            \"tools.files.download:retry=0\\n\"\n                            f\"core.sources:upload_url={self.file_server.fake_url}/backup/\\n\"})\n\n        self.client.save({\"conanfile.py\": conanfile})\n        with mock.patch(\"conan.internal.rest.file_downloader.FileDownloader._download_file\",\n                        custom_download):\n            self.client.run(\"source .\", assert_error=True)\n\n        # A .dirty file was created, now try to source again,\n        # it should detect the dirty download and clean it, but not re-source it\n        self.client.run(\"export . --name=pkg2 --version=1.0\")\n        self.client.run(\"upload * -c -r=default\")\n        assert \"No backup sources files to upload\" in self.client.out\n        assert sha256 + \".dirty\" not in os.listdir(os.path.join(self.download_cache_folder, \"s\"))\n"
  },
  {
    "path": "test/integration/cache/cache2_update_test.py",
    "content": "import copy\nimport json\nimport textwrap\nfrom collections import OrderedDict\n\nimport pytest\nfrom unittest.mock import patch\n\nfrom conan.api.model import RecipeReference\nfrom conans.server.revision_list import RevisionList\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient, TestServer, NO_SETTINGS_PACKAGE_ID\n\n\nclass TestUpdateFlows:\n    @pytest.fixture(autouse=True)\n    def _setup(self):\n        self.liba = RecipeReference.loads(\"liba/1.0.0\")\n\n        servers = OrderedDict()\n        for index in range(3):\n            servers[f\"server{index}\"] = TestServer([(\"*/*@*/*\", \"*\")], [(\"*/*@*/*\", \"*\")],\n                                                   users={\"user\": \"password\"})\n\n        self.client = TestClient(servers=servers, inputs=3*[\"user\", \"password\"])\n        self.client2 = TestClient(servers=servers, inputs=3*[\"user\", \"password\"])\n        self.the_time = 0.0\n        self.server_times = {}\n\n    def _upload_ref_to_all_servers(self, ref, client):\n        # we are patching the time all these revisions uploaded to the servers\n        # will be older than the ones we create in local\n        for index in range(3):\n            self.the_time = self.the_time + 10\n            self._upload_ref_to_server(ref, f\"server{index}\", client)\n\n    def _upload_ref_to_server(self, ref, remote, client):\n        # we are patching the time all these revisions uploaded to the servers\n        # will be older than the ones we create in local\n        self.server_times[remote] = self.the_time\n        with patch.object(RevisionList, '_now', return_value=self.the_time):\n            client.run(f\"upload {ref} -r {remote} -c\")\n\n    def test_revision_fixed_version(self):\n        # NOTES:\n        # - When a revision is installed from a remote it takes the date from the remote, not\n        # updating the date to the current time\n        # - If we want to install the revision and create it with a new date use --update-date\n        # (name to be decided)\n        # - Revisions are considered inmutable: if for example we do a conan install --update of a\n        # revision that is already in the cache, but has a newer date in the remote, we will not install\n        # anything, just updating the date in the cache to the one in the remote, so if you want to\n        # get what the remote has you have to re-install you will have to remove the local\n        # package and install from server\n        # - In conan 2.X no remote means search in all remotes\n\n        # create a revision 0 in client2, client2 will have an older revision than all the servers\n        self.client2.save({\"conanfile.py\": GenConanfile(\"liba\", \"1.0.0\").with_build_msg(\"REV0\")})\n        self.client2.run(\"create .\")\n\n        # other revision created in client\n        self.client.save({\"conanfile.py\": GenConanfile(\"liba\", \"1.0.0\").with_build_msg(\"REV\")})\n        self.client.run(\"create .\")\n\n        self._upload_ref_to_all_servers(\"liba/1.0.0\", self.client)\n\n        # upload other revision 1 we create in client\n        self.client.save({\"conanfile.py\": GenConanfile(\"liba\", \"1.0.0\").with_build_msg(\"REV1\")})\n        self.client.run(\"create .\")\n\n        self._upload_ref_to_all_servers(\"liba/1.0.0\", self.client)\n\n        # NOW WE HAVE:\n        # | CLIENT      | CLIENT2    | SERVER0    | SERVER1   | SERVER2    |\n        # |-------------|------------|------------|-----------|------------|\n        # | REV1  (1020)| REV0 (1000)| REV1(40)   | REV1(50)  | REV1 (60)  |\n        # | REV   (1010)|            | REV (10)   | REV (20)  | REV  (30)  |\n        # |             |            |            |           |            |\n\n        # 1. TESTING WITHOUT SPECIFIC REVISIONS AND WITH NO REMOTES: \"conan install --requires=liba/1.0.0\"\n\n        # client2 already has a revision for this recipe, don't install anything\n        self.client2.run(\"install --requires=liba/1.0.0@\")\n        self.client2.assert_listed_require({\"liba/1.0.0\": \"Cache\"})\n        assert \"liba/1.0.0: Already installed!\" in self.client2.out\n\n        self.client.run(\"remove * -c\")\n\n        # | CLIENT      | CLIENT2    | SERVER0    | SERVER1   | SERVER2    |\n        # |-------------|------------|------------|-----------|------------|\n        # |             | REV0 (1000)| REV1(40)   | REV1(50)  | REV1 (60)  |\n        # |             |            | REV (10)   | REV (20)  | REV  (30)  |\n        # |             |            |            |           |            |\n\n        self.client.run(\"install --requires=liba/1.0.0@\")\n\n        # will not find revisions for the recipe -> search remotes by order and install the\n        # first match that is rev1 from server0\n        # --> result: install rev from server0\n        self.client.assert_listed_require({\"liba/1.0.0\": \"Downloaded (server0)\"})\n        assert f\"liba/1.0.0: Retrieving package {NO_SETTINGS_PACKAGE_ID}\" \\\n               \" from remote 'server0'\" in self.client.out\n\n        latest_rrev = self.client.cache.get_latest_recipe_revision(RecipeReference.loads(\"liba/1.0.0@\"))\n        # check that we have stored REV1 in client with the same date from the server0\n        assert latest_rrev.timestamp == self.server_times[\"server0\"]\n        assert latest_rrev.timestamp == self.server_times[\"server0\"]\n\n        # | CLIENT      | CLIENT2    | SERVER0    | SERVER1   | SERVER2    |\n        # |-------------|------------|------------|-----------|------------|\n        # |REV1 (40)    | REV0 (1000)| REV1(40)   | REV1(50)  | REV1 (60)  |\n        # |             |            | REV (10)   | REV (20)  | REV  (30)  |\n        # |             |            |            |           |            |\n\n        self.client.run(\"install --requires=liba/1.0.0@ --update\")\n        # It will first check all the remotes and\n        # will find the latest revision: REV1 from server2 we already have that\n        # revision but the date is newer\n        # --> result: do not download anything, but update REV1 date in cache\n        self.client.assert_listed_require({\"liba/1.0.0\": \"Cache (Updated date) (server2)\"})\n        assert \"liba/1.0.0: Already installed!\" in self.client.out\n\n        # now create a newer REV2 in server2 and if we do --update it should update the date\n        # to the date in server0 and associate that remote but not install anything\n\n        # we create a newer revision in client2\n        self.client2.run(\"remove * -c\")\n        self.client2.save({\"conanfile.py\": GenConanfile(\"liba\", \"1.0.0\").with_build_msg(\"REV2\")})\n        self.client2.run(\"create .\")\n\n        self.the_time = 100.0\n\n        self._upload_ref_to_server(\"liba/1.0.0\", \"server2\", self.client2)\n\n        # | CLIENT      | CLIENT2    | SERVER0    | SERVER1   | SERVER2    |\n        # |-------------|------------|------------|-----------|------------|\n        # |REV1 (60)    | REV2 (1000)| REV1(100)  | REV1(50)  | REV2 (100) |\n        # |             |            | REV (10)   | REV (20)  | REV1 (60)  |\n        # |             |            |            |           | REV  (30)  |\n\n        self.client.run(\"install --requires=liba/1.0.0@ --update\")\n        # --> result: Update date and server because server0 has a newer date\n        latest_rrev = self.client.cache.get_latest_recipe_revision(self.liba)\n        self.client.assert_listed_require({\"liba/1.0.0\": \"Updated (server2)\"})\n        assert \"liba/1.0.0: Downloaded package\" in self.client.out\n        assert latest_rrev.timestamp == self.server_times[\"server2\"]\n\n        # we create a newer revision in client\n        self.client.run(\"remove * -c\")\n        self.client.save({\"conanfile.py\": GenConanfile(\"liba\", \"1.0.0\").with_build_msg(\"REV2\")})\n        self.client.run(\"create .\")\n        self.client.run(f\"remove {latest_rrev.repr_notime()} -c -r server2\")\n\n        # | CLIENT      | CLIENT2    | SERVER0    | SERVER1   | SERVER2    |\n        # |-------------|------------|------------|-----------|------------|\n        # |REV2 (2002)  | REV2 (2000)| REV1(100)  | REV1(50)  | REV1 (60)  |\n        # |             |            | REV (10)   | REV (20)  | REV (30)   |\n        # |             |            |            |           |            |\n\n        self.client.run(\"install --requires=liba/1.0.0@\")\n        # we already have a revision for liba/1.0.0 so don't install anything\n        # --> result: don't install anything\n        assert \"liba/1.0.0: Already installed!\" in self.client.out\n\n        self.client.run(\"install --requires=liba/1.0.0@ --update\")\n        # we already have a newer revision in the client\n        # we will check all the remotes, find the latest revision\n        # this revision will be oldest than the one in the cache\n        # --> result: don't install anything\n        self.client.assert_listed_require({\"liba/1.0.0\": \"Newer\"})\n        assert \"liba/1.0.0: Already installed!\" in self.client.out\n\n        # create newer revisions in servers so that the ones from the clients are older\n        self.client.save({\"conanfile.py\": GenConanfile(\"liba\", \"1.0.0\").with_build_msg(\"REV3\")})\n        self.client.run(\"create .\")\n        rev_to_upload = self.client.cache.get_latest_recipe_revision(self.liba)\n        # the future\n        self.the_time = 3000000000.0\n        self._upload_ref_to_all_servers(repr(rev_to_upload), self.client)\n\n        # | CLIENT      | CLIENT2    | SERVER0    | SERVER1   | SERVER2    |\n        # |-------------|------------|------------|-----------|------------|\n        # | REV2 (2002) | REV2 (2000)| REV3(3010) | REV3(3020)| REV3 (3030)|\n        # |             |            | REV1(100)  | REV1(50)  | REV1 (60)  |\n        # |             |            | REV (10)   | REV (20)  | REV  (30)  |\n        # |             |            |            |           |            |\n\n        self.client2.run(\"install --requires=liba/1.0.0@ --update\")\n        # now check for newer references with --update for client2 that has an older revision\n        # when we use --update: first check all remotes (no -r argument) get latest revision\n        # check if it is in cache, if it is --> stop, if it is not --> check date and install\n        # --> result: install rev from server2\n        self.client2.assert_listed_require({\"liba/1.0.0\": \"Updated (server2)\"})\n        assert f\"liba/1.0.0: Downloaded recipe revision {rev_to_upload.revision}\" in self.client2.out\n        assert f\"liba/1.0.0: Retrieving package {NO_SETTINGS_PACKAGE_ID}\" \\\n               \" from remote 'server2'\" in self.client2.out\n\n        check_ref = RecipeReference.loads(str(rev_to_upload))  # without revision\n        rev_to_upload = self.client2.cache.get_latest_recipe_revision(check_ref)\n        assert rev_to_upload.timestamp == self.server_times[\"server2\"]\n\n        # | CLIENT      | CLIENT2    | SERVER0    | SERVER1   | SERVER2    |\n        # |-------------|------------|------------|-----------|------------|\n        # | REV2 (2000) | REV3 (3030)| REV3(3010) | REV3(3020)| REV3 (3030)|\n        # |             | REV0 (1000)| REV1(100)  | REV1(50)  | REV1 (60)  |\n        # |             |            | REV (10)   | REV (20)  | REV  (30)  |\n        # |             |            |            |           |            |\n\n        # TESTING WITH SPECIFIC REVISIONS AND WITH NO REMOTES: \"conan install --requires=liba/1.0.0#rrev\"\n        # - In conan 2.X no remote means search in all remotes\n\n        # check one revision we already have will not be installed\n        # we search for that revision in the cache, we found it\n        # --> result: don't install that\n        latest_rrev = self.client.cache.get_latest_recipe_revision(self.liba)\n        self.client.run(f\"install --requires={latest_rrev}@#{latest_rrev.revision}\")\n        self.client.assert_listed_require({\"liba/1.0.0\": \"Cache\"})\n        assert \"liba/1.0.0: Already installed!\" in self.client.out\n\n        self.client.run(\"remove * -c\")\n\n        self.client.run(\"remove '*' -c -r server0\")\n        self.client.run(\"remove '*' -c -r server1\")\n        self.client.run(\"remove '*' -c -r server2\")\n\n        # create new older revisions in servers\n        self.client.save({\"conanfile.py\": GenConanfile(\"liba\", \"1.0.0\").with_build_msg(\"REV4\")})\n        self.client.run(\"create .\")\n        server_rrev = self.client.cache.get_latest_recipe_revision(self.liba)\n        self.the_time = 0.0\n\n        self._upload_ref_to_all_servers(\"liba/1.0.0\", self.client)\n\n        self.client.run(\"remove * -c\")\n\n        # | CLIENT      | CLIENT2    | SERVER0    | SERVER1   | SERVER2    |\n        # |-------------|------------|------------|-----------|------------|\n        # |             | REV3 (3030)| REV4(10)   | REV4(20)  | REV4 (30)  |\n        # |             | REV0 (1000)|            |           |            |\n        # |             |            |            |           |            |\n\n        self.client.save({\"conanfile.py\": GenConanfile(\"liba\", \"1.0.0\").with_build_msg(\"REV5\")})\n        self.client.run(\"create .\")\n\n        # | CLIENT      | CLIENT2    | SERVER0    | SERVER1   | SERVER2    |\n        # |-------------|------------|------------|-----------|------------|\n        # | REV5 (2001) | REV3 (3030)| REV4(10)   | REV4(20)  | REV4 (30)  |\n        # |             | REV0 (1000)|            |           |            |\n        # |             |            |            |           |            |\n\n        # install REV4\n        self.client.run(f\"install --requires={server_rrev}@#{server_rrev.revision}\")\n        # have a newer different revision in the cache, but ask for an specific revision that is in\n        # the servers, will try to find that revision and install it from the first server found\n        # will not check all the remotes for the latest because we consider revisions completely\n        # immutable so all of them are the same\n        # --> result: install new revision asked, but the latest revision remains the other one,\n        # because the one installed took the date from the server and it's older\n        assert \"liba/1.0.0: Not found in local cache, looking in remotes...\" in self.client.out\n        assert \"liba/1.0.0: Checking remote: server0\" in self.client.out\n        assert \"liba/1.0.0: Checking remote: server1\" not in self.client.out\n        assert \"liba/1.0.0: Checking remote: server2\" not in self.client.out\n        server_rrev_norev = copy.copy(server_rrev)\n        server_rrev_norev.revision = None\n        latest_cache_revision = self.client.cache.get_latest_recipe_revision(server_rrev_norev)\n        assert latest_cache_revision != server_rrev\n\n        # | CLIENT      | CLIENT2    | SERVER0    | SERVER1   | SERVER2    |\n        # |-------------|------------|------------|-----------|------------|\n        # | REV5 (2001) | REV3 (3030)| REV4(10)   | REV4(20)  | REV4 (30)  |\n        # | REV4 (10)   | REV0 (1000)|            |           |            |\n        # |             |            |            |           |            |\n\n        self.client.run(f\"install --requires={server_rrev}@#{server_rrev.revision} --update\")\n        # last step without --update it took the REV4 from server0 but now\n        # we tell conan to search for newer recipes of an specific revision\n        # it will go to server2 and update the local date with the one\n        # from the remote\n        # --> result: update REV4 date to 30 but it won't be latest\n\n        latest_cache_revision = self.client.cache.get_latest_recipe_revision(server_rrev_norev)\n        assert latest_cache_revision != server_rrev\n        latest_cache_revision = self.client.cache.recipe_layout(server_rrev).reference\n\n        assert self.the_time == latest_cache_revision.timestamp\n        self.client.assert_listed_require({\"liba/1.0.0\": \"Cache (Updated date) (server2)\"})\n\n        self.client.run(\"remove * -c\")\n        self.client.run(\"remove '*' -c -r server0\")\n        self.client.run(\"remove '*' -c -r server1\")\n        self.client.run(\"remove '*' -c -r server2\")\n\n        self.client.save({\"conanfile.py\": GenConanfile(\"liba\", \"1.0.0\").with_build_msg(\"REV6\")})\n        self.client.run(\"create .\")\n        server_rrev = self.client.cache.get_latest_recipe_revision(self.liba)\n        self.the_time = 3000000020.0\n\n        self._upload_ref_to_all_servers(repr(server_rrev), self.client)\n\n        latest_server_time = self.the_time\n\n        # | CLIENT      | CLIENT2    | SERVER0    | SERVER1   | SERVER2    |\n        # |-------------|------------|------------|-----------|------------|\n        # | REV6(2002)  | REV3 (3030)| REV6(3030) |REV6(3040) | REV6(3050) |\n        # |             | REV0 (1000)|            |           |            |\n        # |             |            |            |           |            |\n\n        self.client.run(f\"install --requires={server_rrev}@#{server_rrev.revision} --update\")\n\n        # now we have the same revision with different dates in the servers and in the cache\n        # in this case, if we specify --update we will check all the remotes, if that revision\n        # has a newer date in the servers we will take that date from the server but we will not\n        # install anything, we are considering revisions fully immutable in 2.0\n        # --> results: update revision date in cache, do not install anything\n\n        latest_rrev_cache = self.client.cache.get_latest_recipe_revision(self.liba)\n        assert latest_server_time == latest_rrev_cache.timestamp\n        self.client.assert_listed_require({\"liba/1.0.0\": \"Cache (Updated date) (server2)\"})\n\n        # | CLIENT      | CLIENT2    | SERVER0    | SERVER1   | SERVER2    |\n        # |-------------|------------|------------|-----------|------------|\n        # | REV6(2002)  | REV3 (3050)| REV6(3030) |REV6(3040) | REV6(3050) |\n        # |             | REV0 (1000)|            |           |            |\n        # |             |            |            |           |            |\n\n        self.client.run(\"remove * -c\")\n\n        # | CLIENT      | CLIENT2    | SERVER0    | SERVER1   | SERVER2    |\n        # |-------------|------------|------------|-----------|------------|\n        # |             | REV3 (3050)| REV6(3030) |REV6(3040) | REV6(3050) |\n        # |             | REV0 (1000)|            |           |            |\n        # |             |            |            |           |            |\n\n        self.client.run(f\"install --requires={server_rrev}@#{server_rrev.revision} --update\")\n\n        # now we have the same revision with different dates in the servers and in the cache\n        # in this case, if we specify --update we will check all the remotes and will install\n        # the revision from the server that has the latest date\n        # --> results: install from server2\n\n        latest_rrev_cache = self.client.cache.get_latest_recipe_revision(self.liba)\n        assert latest_server_time == latest_rrev_cache.timestamp\n        self.client.assert_listed_require({\"liba/1.0.0\": \"Downloaded (server2)\"})\n\n        # | CLIENT      | CLIENT2    | SERVER0    | SERVER1   | SERVER2    |\n        # |-------------|------------|------------|-----------|------------|\n        # | REV6(3050)  | REV3 (3050)| REV6(3030) |REV6(3040) | REV6(3050) |\n        # |             | REV0 (1000)|            |           |            |\n        # |             |            |            |           |            |\n\n    def test_version_ranges(self):\n        # create a revision 0 in client2, client2 will have an older revision than all the servers\n        for minor in range(3):\n            self.client2.save({\"conanfile.py\": GenConanfile(\"liba\", f\"1.{minor}.0\").with_build_msg(\"REV0\")})\n            self.client2.run(\"create .\")\n            self.the_time = 10.0 + minor*10.0\n            self._upload_ref_to_server(f\"liba/1.{minor}.0\", f\"server{minor}\", self.client2)\n\n        self.client.save({\"conanfile.py\": GenConanfile(\"liba\", \"1.0.0\").with_build_msg(\"REV0\")})\n        self.client.run(\"create .\")\n\n        # NOW WE HAVE:\n        # | CLIENT         | CLIENT2        | SERVER0        | SERVER1        | SERVER2        |\n        # |----------------|----------------|----------------|----------------|----------------|\n        # | 1.0 REV0 (1000)| 1.0 REV0 (1000)| 1.0 REV0 (10)  | 1.1 REV0 (10)  | 1.2 REV0 (10)  |\n        # |                | 1.1 REV0 (1000)|                |                |                |\n        # |                | 1.2 REV0 (1000)|                |                |                |\n\n        self.client.run(\"install --requires=liba/[>0.9.0]@\")\n        assert \"liba/[>0.9.0]: liba/1.0.0\" in self.client.out\n        assert \"liba/1.0.0: Already installed!\" in self.client.out\n\n        self.client.run(\"remove * -c\")\n\n        # | CLIENT         | CLIENT2        | SERVER0        | SERVER1        | SERVER2        |\n        # |----------------|----------------|----------------|----------------|----------------|\n        # |                | 1.0 REV0 (1000)| 1.0 REV0 (10)  | 1.1 REV0 (20)  | 1.2 REV0 (30)  |\n        # |                | 1.1 REV0 (1000)|                |                |                |\n        # |                | 1.2 REV0 (1000)|                |                |                |\n\n        self.client.run(\"install --requires=liba/[>0.9.0]@\")\n\n        # will not find versions for the recipe in cache -> search remotes by order and install the\n        # first match that is 1.0 from server0\n        # --> result: install 1.0 from server0\n        assert \"liba/[>0.9.0]: liba/1.0.0\" in self.client.out\n        self.client.assert_listed_require({\"liba/1.0.0\": \"Downloaded (server0)\"})\n\n        latest_rrev = self.client.cache.get_latest_recipe_revision(RecipeReference.loads(\"liba/1.0.0@\"))\n        assert latest_rrev.timestamp == self.server_times[\"server0\"]\n\n        # | CLIENT         | CLIENT2        | SERVER0        | SERVER1        | SERVER2        |\n        # |----------------|----------------|----------------|----------------|----------------|\n        # | 1.0 REV0 (10)| 1.0 REV0 (1000)  | 1.0 REV0 (10)  | 1.1 REV0 (20)  | 1.2 REV0 (30)  |\n        # |                | 1.1 REV0 (1000)|                |                |                |\n        # |                | 1.2 REV0 (1000)|                |                |                |\n\n        self.client.run(\"install --requires=liba/[>1.0.0]@\")\n        # first match that is 1.1 from server1\n        # --> result: install 1.1 from server1\n        assert \"liba/[>1.0.0]: liba/1.1.0\" in self.client.out\n        self.client.assert_listed_require({\"liba/1.1.0\": \"Downloaded (server1)\"})\n\n        # | CLIENT         | CLIENT2        | SERVER0        | SERVER1        | SERVER2        |\n        # |----------------|----------------|----------------|----------------|----------------|\n        # | 1.1 REV0 (10)  | 1.0 REV0 (1000)| 1.0 REV0 (10)  | 1.1 REV0 (20)  | 1.2 REV0 (30)  |\n        # |                | 1.1 REV0 (1000)|                |                |                |\n        # |                | 1.2 REV0 (1000)|                |                |                |\n\n        self.client.run(\"install --requires=liba/[>1.0.0]@ --update\")\n        # check all servers\n        # --> result: install 1.2 from server2\n        assert \"liba/[>1.0.0]: liba/1.2.0\" in self.client.out\n        self.client.assert_listed_require({\"liba/1.2.0\": \"Downloaded (server2)\"})\n\n        # If we have multiple revisions with different names for the same version and we\n        # do a --update we are going to first resolver the version range agains server0\n        # then in the proxy we will install rev2 that is the latest\n        # | CLIENT         | CLIENT2        | SERVER0        | SERVER1        | SERVER2        |\n        # |----------------|----------------|----------------|----------------|----------------|\n        # | 1.0 REV0 (10)  |                | 1.2 REV0 (10)  | 1.2 REV1 (20)  | 1.2 REV2 (30)  |\n        # |                |                |                |                |                |\n        # |                |                |                |                |                |\n\n        self.client.run(\"remove * -c\")\n        self.client2.run(\"remove * -c\")\n\n        # now we are uploading different revisions with different dates, but the same version\n        for minor in range(3):\n            self.client2.save({\"conanfile.py\": GenConanfile(\"liba\", f\"1.2.0\").with_build_msg(f\"REV{minor}\")})\n            self.client2.run(\"create .\")\n            self.the_time = 10.0 + minor*10.0\n            self._upload_ref_to_server(f\"liba/1.2.0\", f\"server{minor}\", self.client2)\n\n        self.client.save({\"conanfile.py\": GenConanfile(\"liba\", \"1.0.0\").with_build_msg(\"REV0\")})\n        self.client.run(\"create .\")\n\n        self.client.run(\"install --requires=liba/[>1.0.0]@ --update\")\n        assert \"liba/[>1.0.0]: liba/1.2.0\" in self.client.out\n        self.client.assert_listed_require({\"liba/1.2.0\": \"Downloaded (server2)\"})\n        assert f\"liba/1.2.0: Retrieving package {NO_SETTINGS_PACKAGE_ID} \" \\\n               \"from remote 'server2' \" in self.client.out\n\n\n@pytest.mark.parametrize(\"update,result\", [\n                                           # Not a real pattern, works to support legacy syntax\n                                           [\"*\", {\"liba/1.1\": \"Downloaded (default)\",\n                                                  \"libb/1.1\": \"Downloaded (default)\"}],\n                                           [\"libc\", {\"liba/1.0\": \"Cache\",\n                                                     \"libb/1.0\": \"Cache\"}],\n                                           [\"liba\", {\"liba/1.1\": \"Downloaded (default)\",\n                                                     \"libb/1.0\": \"Cache\"}],\n                                           [\"libb\", {\"liba/1.0\": \"Cache\",\n                                                     \"libb/1.1\": \"Downloaded (default)\"}],\n                                           [\"libb/1.0\", {\"liba/1.0\": \"Cache\",\n                                                         \"libb/1.0\": \"Cache\"}],\n                                           [\"libb/1.0#7e88fd43dc3c8171b6f38f8d1b139641\",\n                                                {\"liba/1.0\": \"Cache\",\n                                                 \"libb/1.0\": \"Cache\"}],\n                                           [\"\", {\"liba/1.0\": \"Cache\",\n                                                 \"libb/1.0\": \"Cache\"}],\n                                           # Patterns not supported, only full name match\n                                           [\"lib*\", {\"liba/1.0\": \"Cache\",\n                                                     \"libb/1.0\": \"Cache\"}],\n                                           [\"liba/*\", {\"liba/1.0\": \"Cache\",\n                                                       \"libb/1.0\": \"Cache\"}],\n                                           # None only passes legacy --update without args,\n                                           # to ensure it works, it should be the same as passing *\n                                           [None, {\"liba/1.1\": \"Downloaded (default)\",\n                                                   \"libb/1.1\": \"Downloaded (default)\"}]\n                                           ])\ndef test_muliref_update_pattern(update, result):\n    tc = TestClient(light=True, default_server_user=True)\n    tc.save({\"liba/conanfile.py\": GenConanfile(\"liba\"),\n             \"libb/conanfile.py\": GenConanfile(\"libb\")})\n    tc.run(\"create liba --version=1.0\")\n    tc.run(\"create libb --version=1.0\")\n\n    tc.run(\"create liba --version=1.1\")\n    tc.run(\"create libb --version=1.1\")\n\n    tc.run(\"upload * -c -r default\")\n    tc.run('remove \"*/1.1\" -c')\n\n    update_flag = f\"--update={update}\" if update is not None else \"--update\"\n\n    tc.run(f'install --requires=\"liba/[>=1.0]\" --requires=\"libb/[>=1.0]\" -r default {update_flag}')\n\n    tc.assert_listed_require(result)\n\n\ndef test_update_remote_older_revision():\n    # https://github.com/conan-io/conan/issues/19313\n    c = TestClient(light=True, default_server_user=True)\n    zlib = textwrap.dedent(\"\"\"\n       from conan import ConanFile\n       class Zlib(ConanFile):\n           name = \"zlib\"\n           version = \"1.2.11\"\n           exports_sources = \"*\"\n        \"\"\")\n    c.save({\"conanfile.py\": zlib,\n            \"file.h\": \"//myheader\"})\n    c.run(\"export\")\n    c.run(\"upload * -r=default -c\")\n\n    c2 = TestClient(light=True, servers=c.servers)\n    c2.run(\"graph info --requires=zlib/[*]\")\n    rev1 = \"2e87959c586811f8a4eaf12a327cc042\"\n    c2.assert_listed_require({f\"zlib/1.2.11#{rev1}\": \"Downloaded (default)\"})\n\n    # Modify zlib code\n    c.save({\"file.h\": \"//myheader 2\"})\n    c.run(\"export\")\n    c.run(\"upload * -r=default -c\")\n\n    c2.run(\"graph info --requires=zlib/[*] --update\")\n    rev2 = \"934b3de03768d9030b61127d588d0a96\"\n    c2.assert_listed_require({f\"zlib/1.2.11#{rev2}\": \"Updated (default)\"})\n\n    # revert this to old, make it latestlatest\n    c.save({\"file.h\": \"//myheader\"})\n    c.run(\"export\")\n    c.run(\"remove * -r=default -c\")\n    c.run(\"upload * -r=default -c\")\n\n    c2.run(\"graph info --requires=zlib/[*] --update\")\n    assert (\"Latest from 'default' was found in \"\n            \"the cache, using it and updating its timestamp\") in c2.out\n    c2.assert_listed_require({f\"zlib/1.2.11#{rev1}\": \"Updated (default)\"})\n\n    c2.run(\"list *#* --format=json\")\n    revs = json.loads(c2.stdout)[\"Local Cache\"][\"zlib/1.2.11\"][\"revisions\"]\n    # we check that the update from the server has made rev1 the latest in the cache again\n    assert revs[rev1][\"timestamp\"] > revs[rev2][\"timestamp\"]\n"
  },
  {
    "path": "test/integration/cache/download_cache_test.py",
    "content": "import os\nimport textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.file_server import TestFileServer\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import save, set_dirty\n\n\nclass TestDownloadCache:\n\n    def test_download_skip(self):\n        \"\"\" basic proof that enabling download_cache avoids downloading things again\n        \"\"\"\n        client = TestClient(default_server_user=True)\n        # generate large random package file\n        conanfile = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.files import save\n            class Pkg(ConanFile):\n                def package(self):\n                    fileSizeInBytes = 11000000\n                    with open(os.path.join(self.package_folder, \"data.txt\"), 'wb') as fout:\n                        fout.write(os.urandom(fileSizeInBytes))\n                \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --name=mypkg --version=0.1 --user=user --channel=testing\")\n        client.run(\"upload * --confirm -r default\")\n        client.run(\"remove * -c\")\n\n        # enable cache\n        tmp_folder = temp_folder()\n        client.save_home({\"global.conf\": f\"core.download:download_cache={tmp_folder}\"})\n        client.run(\"install --requires=mypkg/0.1@user/testing\")\n        assert \"mypkg/0.1@user/testing: Downloading\" in client.out\n\n        client.run(\"remove * -c\")\n        client.run(\"install --requires=mypkg/0.1@user/testing\")\n        assert \"mypkg/0.1@user/testing: Downloading\" not in client.out\n        assert \"conan_package.tgz from download cache, instead of downloading it\" in client.out\n        # removing the config downloads things\n        client.save_home({\"global.conf\": \"\"})\n        client.run(\"remove * -c\")\n        client.run(\"install --requires=mypkg/0.1@user/testing\")\n        assert \"mypkg/0.1@user/testing: Downloading\" in client.out\n\n        client.save_home({\"global.conf\": f\"core.download:download_cache={tmp_folder}\"})\n\n        client.run(\"remove * -c\")\n        client.run(\"install --requires=mypkg/0.1@user/testing\")\n        assert \"mypkg/0.1@user/testing: Downloading\" not in client.out\n        assert \"conan_package.tgz from download cache, instead of downloading it\" in client.out\n\n    def test_dirty_download(self):\n        # https://github.com/conan-io/conan/issues/8578\n        client = TestClient(default_server_user=True)\n        tmp_folder = temp_folder()\n        client.save_home({\"global.conf\": f\"core.download:download_cache={tmp_folder}\"})\n\n        client.save({\"conanfile.py\": GenConanfile().with_package_file(\"file.txt\", \"content\")})\n        client.run(\"create . --name=pkg --version=0.1\")\n        client.run(\"upload * -c -r default\")\n        client.run(\"remove * -c\")\n        client.run(\"install --requires=pkg/0.1@\")\n\n        # Make the cache dirty\n        # The \"c\" internal folder must exist, it is the actual storage of blobs\n        cache_folder = os.path.join(tmp_folder, \"c\")\n        for f in os.listdir(cache_folder):\n            # damage the file\n            path = os.path.join(cache_folder, f)\n            assert os.path.isfile(path)\n            save(path, \"broken!\")\n            set_dirty(path)\n\n        client.run(\"remove * -c\")\n        client.run(\"install --requires=pkg/0.1@\")\n        assert \"Downloading\" in client.out\n\n        client.run(\"remove * -c\")\n        client.run(\"install --requires=pkg/0.1@\")\n        # TODO  assert \"Downloading\" not in client.out\n\n    def test_user_downloads_cached_newtools(self):\n        client = TestClient()\n        file_server = TestFileServer()\n        client.servers[\"file_server\"] = file_server\n        save(os.path.join(file_server.store, \"myfile.txt\"), \"some content\")\n        save(os.path.join(file_server.store, \"myfile2.txt\"), \"some query\")\n        save(os.path.join(file_server.store, \"myfile3.txt\"), \"some content 3\")\n\n        tmp_folder = temp_folder()\n        client.save_home({\"global.conf\": f\"core.sources:download_cache={tmp_folder}\"})\n        # badchecksums are not cached\n        conanfile = textwrap.dedent(\"\"\"\n           from conan import ConanFile\n           from conan.tools.files import download\n           class Pkg(ConanFile):\n               def source(self):\n                   download(self, \"%s/myfile.txt\", \"myfile.txt\", md5=\"kk\")\n           \"\"\" % file_server.fake_url)\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"source .\", assert_error=True)\n        assert \"ConanException: md5 hash failed for\" in client.out\n        assert \"Provided hash: kk\" in client.out\n\n        # There are 2 things in the cache, not sha256, no caching\n        assert 0 == len(os.listdir(tmp_folder))  # Nothing was cached\n\n        # This is the right checksum\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import download\n            class Pkg(ConanFile):\n                def source(self):\n                    md5 = \"9893532233caff98cd083a116b013c0b\"\n                    md5_2 = \"0dc8a17658b1c7cfa23657780742a353\"\n                    sha256 = \"bcc23055e479c1050455f5bb457088cfae3cbb2783f7579a7df9e33ea9f43429\"\n                    download(self, \"{0}/myfile.txt\", \"myfile.txt\", md5=md5)\n                    download(self, \"{0}/myfile3.txt\", \"myfile3.txt\", sha256=sha256)\n                    download(self, \"{0}/myfile.txt?q=myfile2.txt\", \"myfile2.txt\", md5=md5_2)\n            \"\"\").format(file_server.fake_url)\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"source .\")\n        assert \"some content\" in client.load(\"myfile.txt\")\n        assert \"some query\" in client.load(\"myfile2.txt\")\n        assert \"some content 3\" in client.load(\"myfile3.txt\")\n\n        # remove remote and local files\n        os.remove(os.path.join(file_server.store, \"myfile3.txt\"))\n        os.remove(os.path.join(client.current_folder, \"myfile.txt\"))\n        os.remove(os.path.join(client.current_folder, \"myfile2.txt\"))\n        os.remove(os.path.join(client.current_folder, \"myfile3.txt\"))\n        # Will use the cached one\n        client.run(\"source .\")\n        assert \"some content\" == client.load(\"myfile.txt\")\n        assert \"some query\" == client.load(\"myfile2.txt\")\n        assert \"some content 3\" in client.load(\"myfile3.txt\")\n\n        # disabling cache will make it fail\n        client.save_home({\"global.conf\": \"\"})\n        client.run(\"source .\", assert_error=True)\n        assert \"ERROR: conanfile.py: Error in source() method, line 10\" in client.out\n        assert \"Not found\" in client.out\n\n    def test_download_relative_error(self):\n        \"\"\" relative paths are not allowed\n        \"\"\"\n        c = TestClient(default_server_user=True)\n        c.save({\"conanfile.py\": GenConanfile().with_package_file(\"file.txt\", \"content\")})\n        c.run(\"create . --name=mypkg --version=0.1 --user=user --channel=testing\")\n        c.run(\"upload * --confirm -r default\")\n        c.run(\"remove * -c\")\n\n        # enable cache\n        c.save_home({\"global.conf\": f\"core.download:download_cache=mytmp_folder\"})\n        c.run(\"install --requires=mypkg/0.1@user/testing\", assert_error=True)\n        assert 'core.download:download_cache must be an absolute path' in c.out\n"
  },
  {
    "path": "test/integration/cache/rmdir_fail_test.py",
    "content": "import os\nimport platform\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient, GenConanfile\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"needs windows\")\ndef test_fail_rmdir():\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"create . --name=mypkg --version=0.1 --user=lasote --channel=testing\")\n    build_folder = client.created_layout().build()\n    f = open(os.path.join(build_folder, \"myfile\"), \"wb\")\n    f.write(b\"Hello world\")\n    client.run(\"install --requires=mypkg/0.1@lasote/testing --build=*\", assert_error=True)\n    assert \"ERROR: Couldn't remove folder\" in client.out\n"
  },
  {
    "path": "test/integration/cache/storage_path_test.py",
    "content": "import os\nimport textwrap\nfrom hashlib import sha256\n\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient, GenConanfile\n\n\ndef test_storage_path():\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile()})\n    tmp_folder = temp_folder(path_with_spaces=True)\n    client.save_home({\"global.conf\": f\"core.cache:storage_path={tmp_folder}\"})\n    client.run(\"create . --name=mypkg --version=0.1\")\n    assert f\"mypkg/0.1: Package folder {tmp_folder}\" in client.out\n    assert os.path.isfile(os.path.join(tmp_folder, \"cache.sqlite3\"))\n\n    client.run(\"cache path mypkg/0.1\")\n    assert tmp_folder in client.out\n\n\ndef test_wrong_home_error():\n    client = TestClient(light=True)\n    client.save_home({\"global.conf\": \"core.cache:storage_path=//\"})\n    client.run(\"list *\", assert_error=True)\n    assert \"Couldn't initialize storage in\" in client.out\n\n\ndef test_short_storage_path():\n    c = TestClient()\n    global_conf = textwrap.dedent(\"\"\"\\\n        {% set h = hashlib.new(\"sha256\", conan_home_folder.encode(),\n                               usedforsecurity=False).hexdigest() %}\n        core.cache:storage_path=C:/conan_{{h[:6]}}\n        \"\"\")\n    c.save_home({\"global.conf\": global_conf})\n    c.run(\"config show *\")\n    myhash = sha256()\n    myhash.update(c.cache_folder.replace(\"\\\\\", \"/\").encode())\n    myhash = myhash.hexdigest()[:6]\n    assert f\"core.cache:storage_path: C:/conan_{myhash}\" in c.out\n"
  },
  {
    "path": "test/integration/cache/test_home_special_char.py",
    "content": "import os\nimport platform\n\nimport pytest\n\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient\n\nimport textwrap\n\n_path_chars = \"päthñç$\"\n\n\n@pytest.fixture(scope=\"module\")\ndef client_with_special_chars():\n    \"\"\" the path with special characters is creating a conanbuild.bat that fails\n    \"\"\"\n    cache_folder = os.path.join(temp_folder(), _path_chars)\n    current_folder = os.path.join(temp_folder(), _path_chars)\n    c = TestClient(cache_folder, current_folder)\n\n    tool = textwrap.dedent(r\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import save, chdir\n        class Pkg(ConanFile):\n            name = \"mytool\"\n            version = \"1.0\"\n            def package(self):\n                with chdir(self, self.package_folder):\n                    echo = \"@echo off\\necho MYTOOL WORKS!!\"\n                    save(self, \"bin/mytool.bat\", echo)\n                    save(self, \"bin/mytool.sh\", echo)\n                    os.chmod(\"bin/mytool.sh\", 0o777)\n            \"\"\")\n    c.save({\"conanfile.py\": tool})\n    c.run(\"create .\")\n\n    conan_file = textwrap.dedent(\"\"\"\n        import platform\n        from conan import ConanFile\n\n        class App(ConanFile):\n            name=\"failure\"\n            version=\"0.1\"\n            settings = 'os', 'arch', 'compiler', 'build_type'\n            generators = \"VirtualBuildEnv\"\n            tool_requires = \"mytool/1.0\"\n\n            def build(self):\n                mycmd = \"mytool.bat\" if platform.system() == \"Windows\" else \"mytool.sh\"\n                self.run(mycmd)\n        \"\"\")\n    c.save({\"conanfile.py\": conan_file})\n    return c\n\n\ndef test_reuse_buildenv(client_with_special_chars):\n    c = client_with_special_chars\n    # Need the 2 profile to work correctly buildenv\n    c.run(\"create .\")\n    assert _path_chars in c.out\n    assert \"MYTOOL WORKS!!\" in c.out\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"powershell only win\")\ndef test_reuse_buildenv_powershell(client_with_special_chars):\n    c = client_with_special_chars\n    c.run(\"create . -c tools.env.virtualenv:powershell=True\")\n    assert _path_chars in c.out\n    assert \"MYTOOL WORKS!!\" in c.out\n"
  },
  {
    "path": "test/integration/cache/test_package_revisions.py",
    "content": "from unittest import mock\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\nfrom conan.test.utils.env import environment_update\n\n\ndef test_package_revision_latest():\n    # https://github.com/conan-io/conan/issues/14945\n    c = TestClient()\n    c.save({\"tool/conanfile.py\": GenConanfile(\"tool\", \"0.1\").with_package_file(\"file.txt\",\n                                                                               env_var=\"MYVAR\"),\n            \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_tool_requires(\"tool/0.1\")})\n    with environment_update({\"MYVAR\": \"MYVALUE1\"}):\n        # Just in case dates were not correctly processed\n        with mock.patch(\"conan.internal.cache.cache.revision_timestamp_now\",\n                        return_value=\"1691760295\"):\n            c.run(\"create tool\")\n    prev1 = c.created_package_revision(\"tool/0.1\")\n    with environment_update({\"MYVAR\": \"MYVALUE2\"}):\n        # Just in case dates were not correctly processed\n        with mock.patch(\"conan.internal.cache.cache.revision_timestamp_now\",\n                        return_value=\"1697442658\"):\n            c.run(\"create tool\")\n    prev2 = c.created_package_revision(\"tool/0.1\")\n\n    c.run(\"create pkg\")\n    # The latest is used\n    assert prev2 in c.out\n    assert prev1 not in c.out\n\n    c.run(\"install --requires=pkg/0.1 --build=pkg*\")\n    # The latest is used\n    assert prev2 in c.out\n    assert prev1 not in c.out\n"
  },
  {
    "path": "test/integration/cache/test_same_pref_removal.py",
    "content": "import os\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_same_pref_removal():\n    c = TestClient()\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n    c.run(\"export .\")\n    c.run(\"install --requires=pkg/0.1 --build=pkg*\")\n    layout = c.created_layout()\n    pkg_folder1 = layout.package()\n    assert os.path.exists(os.path.join(pkg_folder1, \"conanmanifest.txt\"))\n    assert os.path.exists(os.path.join(pkg_folder1, \"conaninfo.txt\"))\n    c.run(\"install --requires=pkg/0.1 --build=pkg*\")\n    layout = c.created_layout()\n    pkg_folder2 = layout.package()\n    assert pkg_folder1 == pkg_folder2\n    assert os.path.exists(os.path.join(pkg_folder1, \"conanmanifest.txt\"))\n    assert os.path.exists(os.path.join(pkg_folder1, \"conaninfo.txt\"))\n"
  },
  {
    "path": "test/integration/command/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/command/alias_test.py",
    "content": "import os\nimport textwrap\n\nfrom conan.api.model import RecipeReference\nfrom conan.internal.graph.graph_builder import DepsGraphBuilder\nfrom conan.test.utils.tools import TestClient, GenConanfile\n\nDepsGraphBuilder.ALLOW_ALIAS = True\n\n\nclass TestConanAlias:\n\n    def test_repeated_alias(self):\n        client = TestClient(light=True)\n        client.alias(\"hello/0.x@lasote/channel\",  \"hello/0.1@lasote/channel\")\n        client.alias(\"hello/0.x@lasote/channel\",  \"hello/0.2@lasote/channel\")\n        client.alias(\"hello/0.x@lasote/channel\",  \"hello/0.3@lasote/channel\")\n\n    def test_basic(self):\n        client = TestClient(light=True, default_server_user=True)\n        for i in (1, 2):\n            client.save({\"conanfile.py\": GenConanfile().with_name(\"hello\").with_version(\"0.%s\" % i)})\n            client.run(\"export . --user=lasote --channel=channel\")\n\n        client.alias(\"hello/0.x@lasote/channel\",  \"hello/0.1@lasote/channel\")\n        conanfile_chat = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class TestConan(ConanFile):\n                name = \"chat\"\n                version = \"1.0\"\n                requires = \"hello/(0.x)@lasote/channel\"\n                \"\"\")\n        client.save({\"conanfile.py\": conanfile_chat}, clean_first=True)\n        client.run(\"export . --user=lasote --channel=channel\")\n        client.save({\"conanfile.txt\": \"[requires]\\nchat/1.0@lasote/channel\"}, clean_first=True)\n\n        client.run(\"install . --build=missing\")\n        assert (\"chat/1.0@lasote/channel: WARN: legacy: Requirement 'alias' is provided in Conan 2\"\n                in client.out)\n\n        client.assert_listed_require({\"hello/0.1@lasote/channel\": \"Cache\"})\n        assert \"hello/0.x@lasote/channel: hello/0.1@lasote/channel\" in client.out\n\n        ref = RecipeReference.loads(\"chat/1.0@lasote/channel\")\n        pref = client.get_latest_package_reference(ref)\n        pkg_folder = client.get_latest_pkg_layout(pref).package()\n        conaninfo = client.load(os.path.join(pkg_folder, \"conaninfo.txt\"))\n\n        assert \"hello/0.1\" in conaninfo\n        assert \"hello/0.x\" not in conaninfo\n\n        client.run('upload \"*\" --confirm -r default')\n        client.run('remove \"*\" -c')\n\n        client.run(\"install .\")\n        assert \"'alias' is a Conan 1.X legacy\" in client.out\n        client.assert_listed_require({\"hello/0.1@lasote/channel\": \"Downloaded (default)\"})\n        assert \"hello/0.x@lasote/channel from\" not in client.out\n\n        client.alias(\"hello/0.x@lasote/channel\",  \"hello/0.2@lasote/channel\")\n        client.run(\"install . --build=missing\")\n        assert \"hello/0.2\" in client.out\n        assert \"hello/0.1\" not in client.out\n\n    def test_not_override_package(self):\n        \"\"\" Do not override a package with an alias\n\n            If we create an alias with the same name as an existing package, it will\n            override the package without any warning.\n        \"\"\"\n        t = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                description = \"{}\"\n            \"\"\")\n\n        # Create two packages\n        reference1 = \"pkga/0.1@user/testing\"\n        t.save({\"conanfile.py\": conanfile.format(reference1)})\n        t.run(\"export . --name=pkga --version=0.1 --user=user --channel=testing\")\n\n        reference2 = \"pkga/0.2@user/testing\"\n        t.save({\"conanfile.py\": conanfile.format(reference2)})\n        t.run(\"export . --name=pkga --version=0.2 --user=user --channel=testing\")\n"
  },
  {
    "path": "test/integration/command/cache/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/command/cache/test_cache_clean.py",
    "content": "import os.path\nimport re\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import save\n\n\n@pytest.mark.parametrize(\"use_pkglist\", [True, False])\ndef test_cache_clean(use_pkglist):\n    c = TestClient(default_server_user=True, light=True)\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_exports(\"*\").with_exports_sources(\"*\"),\n            \"sorces/file.txt\": \"\"})\n    c.run(\"create .\")\n    ref_layout = c.exported_layout()\n    pkg_layout = c.created_layout()\n    c.run(\"upload * -c -r=default\")  # Force creation of tgzs\n    assert os.path.exists(ref_layout.source())\n    assert os.path.exists(ref_layout.download_export())\n    assert os.path.exists(pkg_layout.build())\n    assert os.path.exists(pkg_layout.download_package())\n\n    if use_pkglist:\n        c.run(\"list *:*#* -f=json\", redirect_stdout=\"pkglist.json\")\n    arg = \"--list=pkglist.json\" if use_pkglist else \"*\"\n    c.run(f'cache clean {arg} -s -b -v')\n    assert f\"{ref_layout.reference.repr_notime()}: Cleaning recipe cache contents\" in c.out\n    assert f\"{pkg_layout.reference}: Cleaning package cache contents\" in c.out\n    assert not os.path.exists(pkg_layout.build())\n    assert not os.path.exists(ref_layout.source())\n    assert os.path.exists(ref_layout.download_export())\n    assert os.path.exists(pkg_layout.download_package())\n\n    c.run('cache clean -d')\n    assert not os.path.exists(ref_layout.download_export())\n    assert not os.path.exists(pkg_layout.download_package())\n\n    c.run(\"cache clean -bs -v\")\n    assert \"Cleaning 0 backup sources\" in c.out\n\n\ndef test_cache_clean_all():\n    c = TestClient(light=True)\n    c.save({\"pkg1/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_class_attribute(\"revision_mode='scm'\"),\n            \"pkg2/conanfile.py\": GenConanfile(\"pkg\", \"0.2\").with_package(\"error\"),\n            \"pkg3/conanfile.py\": GenConanfile(\"pkg\", \"0.3\")})\n    c.run(\"create pkg1\", assert_error=True)\n    c.run(\"create pkg2\", assert_error=True)\n    c.run(\"create pkg3\")\n    pref = c.created_package_reference(\"pkg/0.3\")\n    tmp_folder = os.path.join(c.cache_folder, \"p\", \"t\")\n    assert len(os.listdir(tmp_folder)) == 1  # Failed export was here\n    builds_folder = os.path.join(c.cache_folder, \"p\", \"b\")\n    assert len(os.listdir(builds_folder)) == 2  # both builds are here\n    c.run('cache clean')\n    assert not os.path.exists(tmp_folder)\n    assert len(os.listdir(builds_folder)) == 1  # only correct pkg/0.3 remains\n    # Check correct package removed all\n    ref_layout = c.get_latest_ref_layout(pref.ref)\n    pkg_layout = c.get_latest_pkg_layout(pref)\n    assert not os.path.exists(ref_layout.source())\n    assert not os.path.exists(ref_layout.download_export())\n    assert not os.path.exists(pkg_layout.build())\n    assert not os.path.exists(pkg_layout.download_package())\n\n    # A second clean like this used to crash\n    # as it tried to delete a folder that was not there and tripped shutils up\n    c.run('cache clean')\n    assert not os.path.exists(tmp_folder)\n\n\ndef test_cache_multiple_builds_same_prev_clean():\n    \"\"\"\n    Different consecutive builds will create exactly the same folder, for the\n    same exact prev, not leaving trailing non-referenced folders\n    \"\"\"\n    c = TestClient(light=True)\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n    c.run(\"create .\")\n    create_out = c.out\n    c.run(\"cache path pkg/0.1:da39a3ee5e6b4b0d3255bfef95601890afd80709\")\n    path1 = str(c.stdout)\n    assert path1 in create_out\n    c.run(\"create .\")\n    create_out = c.out\n    c.run(\"cache path pkg/0.1:da39a3ee5e6b4b0d3255bfef95601890afd80709\")\n    path2 = str(c.stdout)\n    assert path2 in create_out\n    assert path1 == path2\n\n    builds_folder = os.path.join(c.cache_folder, \"p\", \"b\")\n    assert len(os.listdir(builds_folder)) == 1  # only one build\n    c.run('cache clean')\n    assert len(os.listdir(builds_folder)) == 1  # one build not cleaned\n    c.run('remove * -c')\n    assert len(os.listdir(builds_folder)) == 0  # no folder remain\n\n\ndef test_cache_multiple_builds_diff_prev_clean():\n    \"\"\"\n    Different consecutive builds will create different folders, even if for the\n    same exact prev, leaving trailing non-referenced folders\n    \"\"\"\n    c = TestClient(light=True)\n    package_lines = 'save(self, os.path.join(self.package_folder, \"foo.txt\"), str(time.time()))'\n    gen = GenConanfile(\"pkg\", \"0.1\").with_package(package_lines).with_import(\"import os, time\") \\\n                                    .with_import(\"from conan.tools.files import save\")\n    c.save({\"conanfile.py\": gen})\n    c.run(\"create .\")\n    create_out = c.out\n    c.run(\"cache path pkg/0.1:da39a3ee5e6b4b0d3255bfef95601890afd80709\")\n    path1 = str(c.stdout)\n    assert path1 in create_out\n    c.run(\"create .\")\n    create_out = c.out\n    c.run(\"cache path pkg/0.1:da39a3ee5e6b4b0d3255bfef95601890afd80709\")\n    path2 = str(c.stdout)\n    assert path2 in create_out\n    assert path1 != path2\n\n    builds_folder = os.path.join(c.cache_folder, \"p\", \"b\")\n    assert len(os.listdir(builds_folder)) == 2  # both builds are here\n    c.run('cache clean')\n    assert len(os.listdir(builds_folder)) == 2  # two builds will remain, both are valid\n    c.run('remove * -c')\n    assert len(os.listdir(builds_folder)) == 0  # no folder remain\n\n\ndef test_cache_clean_custom_storage():\n    c = TestClient()\n    t = temp_folder(path_with_spaces=False)\n    save(c.paths.global_conf_path, f\"core.cache:storage_path={t}\")\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_cmake_build()})\n    c.run(\"create .\", assert_error=True)\n    build_folder = re.search(r\"pkg/0.1: Building your package in (\\S+)\", str(c.out)).group(1)\n    assert os.listdir(build_folder)\n    # now clean\n    c.run(\"cache clean\")\n    assert not os.path.exists(build_folder)\n"
  },
  {
    "path": "test/integration/command/cache/test_cache_integrity.py",
    "content": "import os\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import save\n\n\n@pytest.mark.parametrize(\"use_pkglist\", [True, False])\n@pytest.mark.parametrize(\"output_pkglist\", [True, False])\ndef test_cache_integrity(use_pkglist, output_pkglist):\n    t = TestClient(light=True)\n    t.save({\"conanfile.py\": GenConanfile()})\n    t.run(\"create . --name pkg1 --version 1.0\")\n    t.run(\"create . --name pkg2 --version=2.0\")\n    layout = t.created_layout()\n    conaninfo = os.path.join(layout.package(), \"conaninfo.txt\")\n    save(conaninfo, \"[settings]\")\n    t.run(\"create . --name pkg3 --version=3.0\")\n    layout = t.created_layout()\n    conaninfo = os.path.join(layout.package(), \"conaninfo.txt\")\n    save(conaninfo, \"[settings]\")\n    t.run(\"create . --name pkg4 --version=4.0\")\n    layout = t.created_layout()\n    conaninfo = os.path.join(layout.package(), \"conaninfo.txt\")\n    save(conaninfo, \"[settings]\")\n    t.run(\"create . --name pkg5 --version=5.0\")\n    layout = t.exported_layout()\n    save(layout.conanfile(), \"empty\")\n\n    if use_pkglist:\n        t.run(\"list *:*#* -f=json\", redirect_stdout=\"pkglist.json\")\n    arg = \"--list=pkglist.json\" if use_pkglist else \"*\"\n\n    if output_pkglist:\n        arg += \" --format=json\"\n\n    t.run(\n        f\"cache check-integrity {arg}\",\n        assert_error=True,\n        redirect_stdout=\"pkglist.json\" if output_pkglist else None,\n    )\n    assert \"pkg1/1.0#4d670581ccb765839f2239cc8dff8fbd: Integrity check: ok\" in t.out\n    assert \"pkg1/1.0#4d670581ccb765839f2239cc8dff8fbd:da39a3ee5e6b4b0d3255bfef95601890afd80709\" \\\n           \"#0ba8627bd47edc3a501e8f0eb9a79e5e: Integrity check: ok\" in t.out\n    assert \"pkg2/2.0#4d670581ccb765839f2239cc8dff8fbd:da39a3ee5e6b4b0d3255bfef95601890afd80709\" \\\n           \"#0ba8627bd47edc3a501e8f0eb9a79e5e: ERROR: \\nManifest mismatch\" in t.out\n    assert \"pkg3/3.0#4d670581ccb765839f2239cc8dff8fbd:da39a3ee5e6b4b0d3255bfef95601890afd80709\" \\\n           \"#0ba8627bd47edc3a501e8f0eb9a79e5e: ERROR: \\nManifest mismatch\" in t.out\n    assert \"pkg4/4.0#4d670581ccb765839f2239cc8dff8fbd:da39a3ee5e6b4b0d3255bfef95601890afd80709\" \\\n           \"#0ba8627bd47edc3a501e8f0eb9a79e5e: ERROR: \\nManifest mismatch\" in t.out\n    assert \"pkg5/5.0#4d670581ccb765839f2239cc8dff8fbd: ERROR: \\nManifest mismatch\" in t.out\n\n    if output_pkglist:\n        t.run(\"remove --list=pkglist.json -c\")\n    else:\n        t.run(\"remove pkg2/2.0:da39a3ee5e6b4b0d3255bfef95601890afd80709 -c\")\n        t.run(\"remove pkg3/3.0:da39a3ee5e6b4b0d3255bfef95601890afd80709 -c\")\n        t.run(\"remove pkg4/4.0:da39a3ee5e6b4b0d3255bfef95601890afd80709 -c\")\n        t.run(\"remove pkg5/5.0 -c\")\n    t.run(\"cache check-integrity *\")\n    assert \"pkg1/1.0#4d670581ccb765839f2239cc8dff8fbd: Integrity check: ok\" in t.out\n    assert \"pkg2/2.0#4d670581ccb765839f2239cc8dff8fbd: Integrity check: ok\" in t.out\n    assert \"pkg3/3.0#4d670581ccb765839f2239cc8dff8fbd: Integrity check: ok\" in t.out\n    assert \"pkg4/4.0#4d670581ccb765839f2239cc8dff8fbd: Integrity check: ok\" in t.out\n\n\n@pytest.mark.parametrize(\"output_pkglist\", [True, False])\ndef test_cache_integrity_missing_recipe_manifest(output_pkglist):\n    t = TestClient()\n    t.save({\"conanfile.py\": GenConanfile()})\n    t.run(\"create . --name pkg1 --version 1.0\")\n    t.run(\"create . --name pkg2 --version=2.0\")\n    layout = t.exported_layout()\n    manifest = os.path.join(layout.export(), \"conanmanifest.txt\")\n    os.remove(manifest)\n    t.run(\"create . --name pkg3 --version=3.0\")\n\n    if output_pkglist:\n        t.run(\"cache check-integrity * -f json\", assert_error=True, redirect_stdout=\"pkglist.json\")\n    else:\n        t.run(\"cache check-integrity *\", assert_error=True)\n    assert \"pkg1/1.0#4d670581ccb765839f2239cc8dff8fbd: Integrity check: ok\" in t.out\n    assert \"pkg2/2.0#4d670581ccb765839f2239cc8dff8fbd: ERROR: Manifest missing\" in t.out\n    assert \"pkg3/3.0#4d670581ccb765839f2239cc8dff8fbd: Integrity check: ok\" in t.out\n    assert \"ERROR: There are corrupted artifacts, check the error logs\" in t.out\n\n    t.run(f\"remove {'--list pkglist.json' if output_pkglist else 'pkg2*'}  -c\")\n    t.run(\"cache check-integrity *\")\n    assert \"pkg1/1.0#4d670581ccb765839f2239cc8dff8fbd:da39a3ee5e6b4b0d3255bfef95601890afd80709\" \\\n           \"#0ba8627bd47edc3a501e8f0eb9a79e5e: Integrity check: ok\" in t.out\n    assert \"pkg3/3.0#4d670581ccb765839f2239cc8dff8fbd: Integrity check: ok\" in t.out\n    assert \"Integrity check: ok\" in t.out\n\n\n@pytest.mark.parametrize(\"output_pkglist\", [True, False])\ndef test_cache_integrity_missing_package_manifest(output_pkglist):\n    t = TestClient()\n    t.save({\"conanfile.py\": GenConanfile()})\n    t.run(\"create . --name pkg1 --version 1.0\")\n    t.run(\"create . --name pkg2 --version=2.0\")\n    layout = t.created_layout()\n    manifest = os.path.join(layout.package(), \"conanmanifest.txt\")\n    os.remove(manifest)\n    t.run(\"create . --name pkg3 --version=3.0\")\n\n    if output_pkglist:\n        t.run(\"cache check-integrity * -f json\", assert_error=True, redirect_stdout=\"pkglist.json\")\n    else:\n        t.run(\"cache check-integrity *\", assert_error=True)\n    assert \"pkg1/1.0#4d670581ccb765839f2239cc8dff8fbd: Integrity check: ok\" in t.out\n    assert \"pkg2/2.0#4d670581ccb765839f2239cc8dff8fbd:da39a3ee5e6b4b0d3255bfef95601890afd80709\" \\\n           \"#0ba8627bd47edc3a501e8f0eb9a79e5e: ERROR: Manifest missing\" in t.out\n    assert \"pkg3/3.0#4d670581ccb765839f2239cc8dff8fbd: Integrity check: ok\" in t.out\n    assert \"ERROR: There are corrupted artifacts, check the error logs\" in t.out\n\n    t.run(f\"remove {'--list pkglist.json' if output_pkglist else 'pkg2*'}  -c\")\n    t.run(\"cache check-integrity *\")\n    assert \"pkg1/1.0#4d670581ccb765839f2239cc8dff8fbd:da39a3ee5e6b4b0d3255bfef95601890afd80709\" \\\n           \"#0ba8627bd47edc3a501e8f0eb9a79e5e: Integrity check: ok\" in t.out\n    assert \"pkg3/3.0#4d670581ccb765839f2239cc8dff8fbd: Integrity check: ok\" in t.out\n    assert \"Integrity check: ok\" in t.out\n\n\n@pytest.mark.parametrize(\"output_pkglist\", [True, False])\ndef test_cache_integrity_missing_package_conaninfo(output_pkglist):\n    t = TestClient()\n    t.save({\"conanfile.py\": GenConanfile()})\n    t.run(\"create . --name pkg1 --version 1.0\")\n    t.run(\"create . --name pkg2 --version=2.0\")\n    layout = t.created_layout()\n    conaninfo = os.path.join(layout.package(), \"conaninfo.txt\")\n    os.remove(conaninfo)\n\n    if output_pkglist:\n        t.run(\"cache check-integrity * -f json\", assert_error=True, redirect_stdout=\"pkglist.json\")\n    else:\n        t.run(\"cache check-integrity *\", assert_error=True)\n    assert \"pkg1/1.0#4d670581ccb765839f2239cc8dff8fbd: Integrity check: ok\" in t.out\n    assert \"pkg2/2.0#4d670581ccb765839f2239cc8dff8fbd:da39a3ee5e6b4b0d3255bfef95601890afd80709\" \\\n           \"#0ba8627bd47edc3a501e8f0eb9a79e5e: ERROR: \\nManifest mismatch\" in t.out\n\n    t.run(f\"remove {'--list pkglist.json' if output_pkglist else 'pkg2*'}  -c\")\n    t.run(\"cache check-integrity *\")\n    assert \"pkg1/1.0#4d670581ccb765839f2239cc8dff8fbd:da39a3ee5e6b4b0d3255bfef95601890afd80709\" \\\n           \"#0ba8627bd47edc3a501e8f0eb9a79e5e: Integrity check: ok\" in t.out\n\n\ndef test_cache_integrity_missing_package_file():\n    t = TestClient()\n    t.save({\"conanfile.py\": GenConanfile().with_package_file(\"myfile\", \"mycontents!\")})\n    t.run(\"create . --name pkg --version 1.0\")\n    layout = t.created_layout()\n    os.remove(os.path.join(layout.package(), \"myfile\"))\n\n    t.run(\"cache check-integrity *\", assert_error=True)\n    assert \"pkg/1.0#2f2609c8e5c87bf836c3fdaa6096b55d:da39a3ee5e6b4b0d3255bfef95601890afd80709\" \\\n           \"#d950d0cd76f6bba62c8add9c68d1aeb3: ERROR: \\nManifest mismatch\" in t.out\n\n\ndef test_cache_integrity_export_sources():\n    # https://github.com/conan-io/conan/issues/14840\n    t = TestClient(default_server_user=True)\n    t.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_exports_sources(\"src/*\"),\n            \"src/mysource.cpp\": \"\"})\n    t.run(\"create .\")\n    t.run(\"cache check-integrity *\")\n    assert \"pkg/0.1#ae07161b81ab07f7f1f746391668df0e: Integrity check: ok\" in t.out\n\n    # If we download, integrity should be ok\n    # (it failed before, because the manifest is not complete)\n    t.run(\"upload * -r=default -c\")\n    t.run(\"remove * -c\")\n    t.run(\"install --requires=pkg/0.1\")\n    t.run(\"cache check-integrity *\")\n    assert \"pkg/0.1#ae07161b81ab07f7f1f746391668df0e: Integrity check: ok\" in t.out\n"
  },
  {
    "path": "test/integration/command/cache/test_cache_path.py",
    "content": "import json\nimport os\nimport platform\n\nimport pytest\n\nfrom conan.api.model import RecipeReference, PkgReference\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.fixture(scope=\"module\")\ndef created_package():\n    t = TestClient(light=True)\n    t.save({\"conanfile.py\": GenConanfile()})\n    t.run(\"create . --name foo --version 1.0\")\n    recipe_layout = t.exported_layout()\n    pkg_layout = t.created_layout()\n    return t, recipe_layout, pkg_layout\n\n\ndef test_cache_path(created_package):\n    t, recipe_layout, pkg_layout = created_package\n\n    # Basic recipe paths, without specifying revision\n\n    recipe_revision = recipe_layout.reference.revision\n    pref = pkg_layout.reference\n    t.run(\"cache path foo/1.0\")\n    assert recipe_layout.export() == str(t.out).rstrip()\n    t.run(\"cache path foo/1.0#latest\")\n    assert recipe_layout.export() == str(t.out).rstrip()\n    t.run(\"cache path foo/1.0 --folder=export_source\")\n    assert recipe_layout.export_sources() == str(t.out).rstrip()\n    t.run(\"cache path foo/1.0 --folder=source\")\n    assert recipe_layout.source() == str(t.out).rstrip()\n\n    # Basic recipe paths, with revision\n    t.run(f\"cache path foo/1.0#{recipe_revision}\")\n    assert recipe_layout.export() == str(t.out).rstrip()\n    t.run(f\"cache path foo/1.0#{recipe_revision} --folder=export_source\")\n    assert recipe_layout.export_sources() == str(t.out).rstrip()\n    t.run(f\"cache path foo/1.0#{recipe_revision} --folder=source\")\n    assert recipe_layout.source() == str(t.out).rstrip()\n\n    # Basic package paths, without specifying revision\n    t.run(f\"cache path foo/1.0:{pref.package_id}\")\n    assert pkg_layout.package() == str(t.out).rstrip()\n    t.run(f\"cache path foo/1.0:{pref.package_id} --folder=build\")\n    assert pkg_layout.build() == str(t.out).rstrip()\n\n    # Basic package paths, with recipe-revision\n    t.run(f\"cache path foo/1.0#{recipe_revision}:{pref.package_id}\")\n    assert pkg_layout.package() == str(t.out).rstrip()\n    t.run(f\"cache path foo/1.0#{recipe_revision}:{pref.package_id}#latest\")\n    assert pkg_layout.package() == str(t.out).rstrip()\n    t.run(f\"cache path foo/1.0#{recipe_revision}:{pref.package_id} --folder=build\")\n    assert pkg_layout.build() == str(t.out).rstrip()\n\n    # Basic package paths, with both revisions\n    t.run(f\"cache path foo/1.0#{recipe_revision}:{pref.package_id}#{pref.revision}\")\n    assert pkg_layout.package() == str(t.out).rstrip()\n    t.run(f\"cache path foo/1.0#{recipe_revision}:{pref.package_id}#{pref.revision} --folder=build\")\n    assert pkg_layout.build() == str(t.out).rstrip()\n\n\ndef test_cache_path_exist_errors(created_package):\n    t, recipe_layout, pkg_layout = created_package\n    recipe_revision = recipe_layout.reference.revision\n    pref = pkg_layout.reference\n\n    t.run(\"cache path nonexist/1.0\", assert_error=True)\n    assert \"ERROR: Recipe 'nonexist/1.0' not found\" in t.out\n\n    t.run(\"cache path nonexist/1.0#rev\", assert_error=True)\n    assert \"ERROR: Recipe 'nonexist/1.0#rev' not found\" in t.out\n\n    t.run(\"cache path foo/1.0#rev\", assert_error=True)\n    # TODO: Improve this error message\n    assert \"ERROR: Recipe 'foo/1.0#rev' not found\" in t.out\n\n    t.run(f\"cache path foo/1.0:pid1\", assert_error=True)\n    assert f\"ERROR: 'foo/1.0#{recipe_revision}:pid1' not found in cache\" in t.out\n\n    t.run(f\"cache path foo/1.0#{recipe_revision}:pid1\", assert_error=True)\n    assert f\"ERROR: 'foo/1.0#{recipe_revision}:pid1' not found in cache\" in t.out\n\n    t.run(f\"cache path foo/1.0#{recipe_revision}:{pref.package_id}#rev2\", assert_error=True)\n    assert f\"ERROR: No entry for package 'foo/1.0#{recipe_revision}:{pref.package_id}#rev2\" in t.out\n\n\ndef test_cache_path_arg_errors():\n    t = TestClient()\n    # build, cannot obtain build without pref\n    t.run(\"cache path foo/1.0 --folder build\", assert_error=True)\n    assert \"ERROR: '--folder build' requires a valid package reference\" in t.out\n\n    # Invalid reference\n    t.run(\"cache path patata\", assert_error=True)\n    assert \"ERROR: patata is not a valid recipe reference\" in t.out\n\n    # source, cannot obtain build without pref\n    t.run(\"cache path foo/1.0:pid --folder source\", assert_error=True)\n    assert \"ERROR: '--folder source' requires a recipe reference\" in t.out\n\n\ndef test_cache_path_does_not_exist_folder():\n    client = TestClient(default_server_user=True)\n    conanfile = GenConanfile()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=mypkg --version=0.1\")\n    pref = client.created_package_reference(\"mypkg/0.1\")\n    client.run(\"upload * --confirm -r default\")\n    client.run(\"remove * -c\")\n\n    client.run(f\"install --requires mypkg/0.1\")\n    client.run(f\"cache path {pref} --folder build\", assert_error=True)\n    assert f\"ERROR: 'build' folder does not exist for the reference {pref}\" in client.out\n\n\ndef test_cache_path_output_json():\n    client = TestClient()\n    conanfile = GenConanfile(\"mypkg\", \"0.1\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"export .\")\n    layout = client.exported_layout()\n    client.run(\"cache path mypkg/0.1 --format=json\")\n    output = json.loads(client.stdout)\n    assert output == {\"cache_path\": os.path.join(layout.base_folder, \"e\")}\n\n\nclass TestCacheRef:\n\n    def test_cache_path(self, created_package):\n        t, recipe_layout, pkg_layout = created_package\n\n        t.run(f'cache ref \"{os.path.dirname(recipe_layout.export())}\"')\n        assert f\"foo/1.0#{recipe_layout.reference.revision}\" in t.out\n\n        t.run(f'cache ref \"{recipe_layout.export()}\"')\n        assert f\"foo/1.0#{recipe_layout.reference.revision}\" in t.out\n\n        t.run(f'cache ref \"{recipe_layout.source()}\"')\n        assert f\"foo/1.0#{recipe_layout.reference.revision}\" in t.out\n\n        t.run(f'cache ref \"{os.path.dirname(pkg_layout.package())}\"')\n        assert f\"foo/1.0#{recipe_layout.reference.revision}\" in t.out\n\n        t.run(f'cache ref \"{pkg_layout.build()}\"')\n        assert f\"foo/1.0#{recipe_layout.reference.revision}\" in t.out\n\n        t.run(f'cache ref \"{pkg_layout.package()}\"')\n        assert f\"foo/1.0#{recipe_layout.reference.revision}\" in t.out\n\n    def test_downloaded_paths(self):\n        t = TestClient(light=True, default_server_user=True)\n        t.save({\"conanfile.py\": GenConanfile()})\n        t.run(\"create . --name foo --version 1.0\")\n        t.run(\"upload * -c -r=default\")\n        t.run(\"remove * -c\")\n        t.run(\"install --requires=foo/1.0\")\n        ref = RecipeReference.loads(\"foo/1.0#4d670581ccb765839f2239cc8dff8fbd\")\n        pref = PkgReference(ref, \"da39a3ee5e6b4b0d3255bfef95601890afd80709\")\n        recipe_layout = t.get_latest_ref_layout(ref)\n        pkg_layout = t.get_latest_pkg_layout(pref)\n\n        t.run(f'cache ref \"{os.path.dirname(recipe_layout.export())}\"')\n        assert f\"foo/1.0#{recipe_layout.reference.revision}\" in t.out\n\n        t.run(f'cache ref \"{recipe_layout.export()}\"')\n        assert f\"foo/1.0#{recipe_layout.reference.revision}\" in t.out\n\n        t.run(f'cache ref \"{os.path.dirname(pkg_layout.package())}\"')\n        assert f\"foo/1.0#{recipe_layout.reference.revision}\" in t.out\n\n        t.run(f'cache ref \"{pkg_layout.package()}\"')\n        assert f\"foo/1.0#{recipe_layout.reference.revision}\" in t.out\n\n    def test_errors(self):\n        t = TestClient(light=True)\n        t.run('cache ref \"/some/non/existing/path\"', assert_error=True)\n        assert \"ERROR: Reference for this path not found in cache\" in t.out\n\n        if platform.system() == \"Windows\":\n            t.run(\"cache ref J:/not/path\", assert_error=True)\n            assert \"ERROR: Invalid path: J:/not/path\" in t.out\n"
  },
  {
    "path": "test/integration/command/cache/test_cache_save_restore.py",
    "content": "import json\nimport os\nimport platform\nimport shutil\nimport sys\nimport tarfile\nimport time\n\nimport pytest\n\nfrom conan.api.model import PkgReference, RecipeReference\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient, NO_SETTINGS_PACKAGE_ID\nfrom conan.internal.util.files import save, load\n\n\ndef test_cache_save_restore():\n    c = TestClient()\n    c.save({\"conanfile.py\": GenConanfile().with_settings(\"os\")})\n    c.run(\"create . --name=pkg --version=1.0 -s os=Linux\")\n    c.run(\"create . --name=pkg --version=1.1 -s os=Linux\")\n    c.run(\"create . --name=other --version=2.0 -s os=Linux\")\n    # Force the compress level just to make sure it doesn't crash\n    c.run(\"cache save pkg/*:* -cc core.gzip:compresslevel=9\")\n    cache_path = os.path.join(c.current_folder, \"conan_cache_save.tgz\")\n    assert os.path.exists(cache_path)\n    _validate_restore(cache_path)\n\n    # Lets test that the pkglist does not contain windows backslash paths to make it portable\n    with open(cache_path, mode='rb') as file_handler:\n        the_tar = tarfile.open(fileobj=file_handler)\n        fileobj = the_tar.extractfile(\"pkglist.json\")\n        pkglist = fileobj.read()\n        the_tar.close()\n\n    package_list = json.loads(pkglist)\n    assert \"\\\\\" not in package_list\n\n\ndef test_cache_save_restore_with_package_file():\n    \"\"\"If we have some sources in the root (like the CMakeLists.txt)\n    we don't declare folders.source\"\"\"\n    conan_file = GenConanfile() \\\n        .with_settings(\"os\") \\\n        .with_package_file(\"bin/file.txt\", \"content!!\")\n\n    client = TestClient()\n    client.save({\"conanfile.py\": conan_file})\n    client.run(\"create . --name=pkg --version=1.0 -s os=Linux\")\n    client.run(\"cache save pkg/*:* \")\n    cache_path = os.path.join(client.current_folder, \"conan_cache_save.tgz\")\n    assert os.path.exists(cache_path)\n\n    c2 = TestClient()\n    shutil.copy2(cache_path, c2.current_folder)\n    c2.run(\"cache restore conan_cache_save.tgz\")\n    c2.run(\"list *:*#*\")\n    assert \"pkg/1.0\" in c2.out\n    tree = _get_directory_tree(c2.base_folder)\n\n    # Restore again, expect the tree to be unchanged\n    c2.run(\"cache restore conan_cache_save.tgz\")\n    c2.run(\"list *:*#*\")\n    assert \"pkg/1.0\" in c2.out\n    tree2 = _get_directory_tree(c2.base_folder)\n\n    assert tree2 == tree\n\n\ndef test_cache_save_downloaded_restore():\n    \"\"\" what happens if we save packages downloaded from server, not\n    created\n    \"\"\"\n    c = TestClient(default_server_user=True)\n    c.save({\"conanfile.py\": GenConanfile().with_settings(\"os\")})\n    c.run(\"create . --name=pkg --version=1.0 -s os=Linux\")\n    c.run(\"create . --name=pkg --version=1.1 -s os=Linux\")\n    c.run(\"create . --name=other --version=2.0 -s os=Linux\")\n    c.run(\"upload * -r=default -c\")\n    c.run(\"remove * -c\")\n    c.run(\"download *:* -r=default --metadata=*\")\n    c.run(\"cache save pkg/*:* \")\n    cache_path = os.path.join(c.current_folder, \"conan_cache_save.tgz\")\n    assert os.path.exists(cache_path)\n\n    _validate_restore(cache_path)\n\n\ndef _get_directory_tree(base_folder):\n    tree = []\n    for d, _, fs in os.walk(base_folder):\n        rel_d = os.path.relpath(d, base_folder) if d != base_folder else \"\"\n        if rel_d:\n            tree.append(rel_d)\n        for f in fs:\n            tree.append(os.path.join(rel_d, f))\n    tree.sort()\n    return tree\n\n\ndef _validate_restore(cache_path):\n    c2 = TestClient()\n    # Create a package in the cache to check put doesn't interact badly\n    c2.save({\"conanfile.py\": GenConanfile().with_settings(\"os\")})\n    c2.run(\"create . --name=pkg2 --version=3.0 -s os=Windows\")\n    shutil.copy2(cache_path, c2.current_folder)\n    c2.run(\"cache restore conan_cache_save.tgz\")\n    c2.run(\"list *:*#*\")\n    assert \"pkg2/3.0\" in c2.out\n    assert \"pkg/1.0\" in c2.out\n    assert \"pkg/1.1\" in c2.out\n    assert \"other/2.0\" not in c2.out\n    tree = _get_directory_tree(c2.base_folder)\n\n    # Restore again, just in case\n    c2.run(\"cache restore conan_cache_save.tgz\")\n    c2.run(\"list *:*#*\")\n    assert \"pkg2/3.0\" in c2.out\n    assert \"pkg/1.0\" in c2.out\n    assert \"pkg/1.1\" in c2.out\n    assert \"other/2.0\" not in c2.out\n    tree2 = _get_directory_tree(c2.base_folder)\n    assert tree2 == tree\n\n\ndef test_cache_save_excluded_folders():\n    # https://github.com/conan-io/conan/issues/18234\n    c = TestClient(default_server_user=True)\n    c.save({\"conanfile.py\": GenConanfile().with_exports(\"*.py\").with_exports_sources(\"*.c\"),\n            \"somefile.py\": \"\",\n            \"mysrc.c\": \"\"})\n    c.run(\"create . --name=pkg --version=1.0\")\n    ref_layout = c.exported_layout()\n    pkg_layout = c.created_layout()\n    c.run(\"upload * --dry-run -r=default -c\")\n    assert os.path.exists(os.path.join(ref_layout.download_export(), \"conan_export.tgz\"))\n    assert os.path.exists(os.path.join(ref_layout.download_export(), \"conan_sources.tgz\"))\n    assert os.path.exists(os.path.join(ref_layout.source(), \"mysrc.c\"))\n    assert os.path.exists(os.path.join(pkg_layout.download_package(), \"conan_package.tgz\"))\n    assert os.path.exists(pkg_layout.build())\n\n    c.run(\"cache save *:*\")\n    cache_path = os.path.join(c.current_folder, \"conan_cache_save.tgz\")\n\n    c2 = TestClient()\n    shutil.copy2(cache_path, c2.current_folder)\n    c2.run(\"cache restore conan_cache_save.tgz\")\n\n    ref = RecipeReference.loads(\"pkg/1.0\")\n    ref_layout = c2.get_latest_ref_layout(ref)\n    pkg_layout = c2.get_latest_pkg_layout(PkgReference(ref_layout.reference, NO_SETTINGS_PACKAGE_ID))\n    assert os.path.exists(os.path.join(ref_layout.source(), \"mysrc.c\"))\n    assert not os.path.exists(os.path.join(ref_layout.download_export(), \"conan_export.tgz\"))\n    assert not os.path.exists(os.path.join(ref_layout.download_export(), \"conan_sources.tgz\"))\n    assert not os.path.exists(os.path.join(pkg_layout.download_package(), \"conan_package.tgz\"))\n    assert not os.path.exists(pkg_layout.build())\n\n    # exclude source\n    c.run(\"cache save * --no-source\")\n    c3 = TestClient()\n    shutil.copy2(cache_path, c3.current_folder)\n    c3.run(\"cache restore conan_cache_save.tgz\")\n    ref_layout = c3.get_latest_ref_layout(ref)\n    assert not os.path.exists(os.path.join(ref_layout.source(), \"mysrc.c\"))\n\n\ndef test_cache_save_restore_metadata():\n    c = TestClient()\n    c.save({\"conanfile.py\": GenConanfile().with_settings(\"os\")})\n    c.run(\"create . --name=pkg --version=1.0 -s os=Linux\")\n    pid = c.created_package_id(\"pkg/1.0\")\n    # Add some metadata\n    c.run(\"cache path pkg/1.0 --folder=metadata\")\n    metadata_path = str(c.stdout).strip()\n    myfile = os.path.join(metadata_path, \"logs\", \"mylogs.txt\")\n    save(myfile, \"mylogs!!!!\")\n    c.run(f\"cache path pkg/1.0:{pid} --folder=metadata\")\n    pkg_metadata_path = str(c.stdout).strip()\n    myfile = os.path.join(pkg_metadata_path, \"logs\", \"mybuildlogs.txt\")\n    save(myfile, \"mybuildlogs!!!!\")\n\n    c.run(\"cache save  pkg/*:* \")\n    cache_path = os.path.join(c.current_folder, \"conan_cache_save.tgz\")\n    assert os.path.exists(cache_path)\n\n    # restore and check\n    c2 = TestClient()\n    shutil.copy2(cache_path, c2.current_folder)\n    c2.run(\"cache restore conan_cache_save.tgz\")\n    c2.run(\"cache path pkg/1.0 --folder=metadata\")\n    metadata_path = str(c2.stdout).strip()\n    myfile = os.path.join(metadata_path, \"logs\", \"mylogs.txt\")\n    assert load(myfile) == \"mylogs!!!!\"\n    c2.run(f\"cache path pkg/1.0:{pid} --folder=metadata\")\n    pkg_metadata_path = str(c2.stdout).strip()\n    myfile = os.path.join(pkg_metadata_path, \"logs\", \"mybuildlogs.txt\")\n    assert load(myfile) == \"mybuildlogs!!!!\"\n\n\n# FIXME: check the timestamps of the conan cache restore\n@pytest.mark.skipif(platform.system() == \"Windows\",\n                    reason=\"Fails in windows in ci because of the low precission of the clock\")\ndef test_cache_save_restore_multiple_revisions():\n    c = TestClient()\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n    c.run(\"create .\")\n    rrev1 = c.exported_recipe_revision()\n    time.sleep(0.2)\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_class_attribute(\"var=42\")})\n    c.run(\"create .\")\n    rrev2 = c.exported_recipe_revision()\n    time.sleep(0.2)\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_class_attribute(\"var=123\")})\n    c.run(\"create .\")\n    rrev3 = c.exported_recipe_revision()\n\n    def check_ordered_revisions(client):\n        client.run(\"list *#* --format=json\")\n        revisions = json.loads(client.stdout)[\"Local Cache\"][\"pkg/0.1\"][\"revisions\"]\n        assert revisions[rrev1][\"timestamp\"] < revisions[rrev2][\"timestamp\"]\n        assert revisions[rrev2][\"timestamp\"] < revisions[rrev3][\"timestamp\"]\n\n    check_ordered_revisions(c)\n\n    c.run(\"cache save pkg/*#*:* \")\n    cache_path = os.path.join(c.current_folder, \"conan_cache_save.tgz\")\n\n    # restore and check\n    c2 = TestClient()\n    shutil.copy2(cache_path, c2.current_folder)\n    c2.run(\"cache restore conan_cache_save.tgz\")\n    check_ordered_revisions(c2)\n\n\ndef test_cache_save_restore_graph():\n    \"\"\" It is possible to save package list\n    \"\"\"\n    c = TestClient()\n    c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\"),\n            \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_requires(\"dep/0.1\")})\n    c.run(\"create dep\")\n    c.run(\"create pkg --format=json\", redirect_stdout=\"graph.json\")\n    c.run(\"list --graph=graph.json --format=json\", redirect_stdout=\"list.json\")\n    c.run(\"cache save --file=cache.tgz --list=list.json\")\n    cache_path = os.path.join(c.current_folder, \"cache.tgz\")\n    assert os.path.exists(cache_path)\n    c2 = TestClient()\n    # Create a package in the cache to check put doesn't interact badly\n    c2.save({\"conanfile.py\": GenConanfile().with_settings(\"os\")})\n    c2.run(\"create . --name=pkg2 --version=3.0 -s os=Windows\")\n    shutil.copy2(cache_path, c2.current_folder)\n    c2.run(\"cache restore cache.tgz\")\n    c2.run(\"list *:*#*\")\n    assert \"pkg/0.1\" in c2.out\n    assert \"dep/0.1\" in c2.out\n\n\ndef test_cache_save_subfolder():\n    \"\"\" It is possible to save package list in subfolder that doesn't exist\n    https://github.com/conan-io/conan/issues/15362\n    \"\"\"\n    c = TestClient()\n    c.save({\"conanfile.py\": GenConanfile(\"dep\", \"0.1\")})\n    c.run(\"export .\")\n    c.run(\"cache save * --file=subfolder/cache.tgz\")\n    assert os.path.exists(os.path.join(c.current_folder, \"subfolder\", \"cache.tgz\"))\n\n\ndef test_error_restore_not_existing():\n    c = TestClient()\n    c.run(\"cache restore potato.tgz\", assert_error=True)\n    assert \"ERROR: Restore archive doesn't exist in \" in c.out\n\n\n@pytest.mark.parametrize(\"src_store\", (False, True))\n@pytest.mark.parametrize(\"dst_store\", (False, True))\ndef test_cache_save_restore_custom_storage_path(src_store, dst_store):\n    c = TestClient()\n    if src_store:\n        tmp_folder = temp_folder()\n        c.save_home({\"global.conf\": f\"core.cache:storage_path={tmp_folder}\"})\n    c.save({\"conanfile.py\": GenConanfile()})\n    c.run(\"create . --name=pkg --version=1.0\")\n    c.run(\"cache save *:*\")\n    cache_path = os.path.join(c.current_folder, \"conan_cache_save.tgz\")\n\n    c2 = TestClient()\n    if dst_store:\n        tmp_folder = temp_folder()\n        c2.save_home({\"global.conf\": f\"core.cache:storage_path={tmp_folder}\"})\n    shutil.copy2(cache_path, c2.current_folder)\n    c2.run(\"cache restore conan_cache_save.tgz\")\n    c2.run(\"list *:*\")\n    assert \"pkg/1.0\" in c2.out\n\n\n@pytest.mark.parametrize(\"compress\", [\"gz\", \"xz\", \"zst\"])\ndef test_cache_save_restore_compressions(compress):\n    \"\"\" we accept different compressions formats\"\"\"\n    if compress == \"zst\" and sys.version_info.minor < 14:\n        pytest.skip(\"Skipping zst compression tests\")\n\n    conan_file = GenConanfile() \\\n        .with_settings(\"os\") \\\n        .with_package_file(\"bin/file.txt\", \"content!!\")\n\n    client = TestClient()\n    client.save({\"conanfile.py\": conan_file})\n    client.run(\"create . --name=pkg --version=1.0 -s os=Linux\")\n    client.run(f\"cache save pkg/*:* --file=mysave.t{compress}\")\n    if compress in (\"xz\", \"zst\"):\n        assert f\"WARN: experimental: The '{compress}' compression is experimental.\" in client.out\n    cache_path = os.path.join(client.current_folder, f\"mysave.t{compress}\")\n    assert os.path.exists(cache_path)\n\n    c2 = TestClient()\n    shutil.copy2(cache_path, c2.current_folder)\n    c2.run(f\"cache restore mysave.t{compress}\")\n    c2.run(\"list *:*#*\")\n    assert \"pkg/1.0\" in c2.out\n"
  },
  {
    "path": "test/integration/command/cache/test_cache_sign.py",
    "content": "import json\nimport textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\nPLUGIN_CONTENT = textwrap.dedent(\"\"\"\n    import os\n    from conan.internal.util.files import save  # Only for testing purposes\n\n    def sign(ref, artifacts_folder, signature_folder, **kwargs):\n        save(os.path.join(signature_folder, \"signature.sig\"), \"signed-content\")\n        return [{\n            \"method\": \"dummy-method\",\n            \"provider\": \"dummy-provider\",\n            \"sign_artifacts\": {\"signature\": \"signature.sig\"}\n        }]\n\n    def verify(ref, artifacts_folder, signature_folder, files, **kwargs):\n        pass\n\"\"\")\n\ndef test_pkg_sign_no_plugin():\n    c = TestClient()\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n    c.run(\"create .\")\n    c.run(\"cache sign *\", assert_error=True)\n    assert \"ERROR: The sign() function in the package sign plugin is not defined.\" in c.out\n    c.run(\"cache verify *\", assert_error=True)\n    assert \"ERROR: The verify() function in the package sign plugin is not defined.\" in c.out\n\n\ndef test_pkg_sign_no_plugin_functions():\n    c = TestClient()\n    c.save_home({\"extensions/plugins/sign/sign.py\": \"\"})\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n    c.run(\"create .\")\n    c.run(\"cache sign *\", assert_error=True)\n    assert \"ERROR: The sign() function in the package sign plugin is not defined.\" in c.out\n    c.run(\"cache verify *\", assert_error=True)\n    assert \"ERROR: The verify() function in the package sign plugin is not defined.\" in c.out\n\n\ndef test_pkg_sign_verify_basic():\n    c = TestClient()\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n    c.save_home({\"extensions/plugins/sign/sign.py\": PLUGIN_CONTENT})\n    c.run(\"create .\")\n    c.run(\"cache sign *\")\n    assert textwrap.dedent(\"\"\"\\\n        [Package sign] Results:\n\n        pkg/0.1\n          revisions\n            485dad6cb11e2fa99d9afbe44a57a164\n              packages\n                da39a3ee5e6b4b0d3255bfef95601890afd80709\n                  revisions\n                    0ba8627bd47edc3a501e8f0eb9a79e5e\n\n        [Package sign] Summary: OK=2, FAILED=0\"\"\") in c.out\n    c.run(\"cache sign * -f json\")\n    conanfile_dict = json.loads(c.stdout)[\"pkg/0.1\"][\"revisions\"][\"485dad6cb11e2fa99d9afbe44a57a164\"]\n    package_dict = conanfile_dict[\"packages\"][\"da39a3ee5e6b4b0d3255bfef95601890afd80709\"] \\\n                                 [\"revisions\"][\"0ba8627bd47edc3a501e8f0eb9a79e5e\"]\n    assert list(conanfile_dict[\"files\"].keys()) == [\"conanfile.py\", \"conanmanifest.txt\"]\n    assert list(package_dict[\"files\"].keys()) == [\"conan_package.tgz\", \"conaninfo.txt\",\n                                                  \"conanmanifest.txt\"]\n    c.run(\"cache verify *\")\n    assert textwrap.dedent(\"\"\"\n        [Package sign] Results:\n\n        pkg/0.1\n          revisions\n            485dad6cb11e2fa99d9afbe44a57a164\n              packages\n                da39a3ee5e6b4b0d3255bfef95601890afd80709\n                  revisions\n                    0ba8627bd47edc3a501e8f0eb9a79e5e\n\n        [Package sign] Summary: OK=2, FAILED=0\"\"\") in c.out\n    c.run(\"cache verify * -f json\")\n    conanfile_dict = json.loads(c.stdout)[\"pkg/0.1\"][\"revisions\"][\"485dad6cb11e2fa99d9afbe44a57a164\"]\n    package_dict = conanfile_dict[\"packages\"][\"da39a3ee5e6b4b0d3255bfef95601890afd80709\"] \\\n                                 [\"revisions\"][\"0ba8627bd47edc3a501e8f0eb9a79e5e\"]\n    assert list(conanfile_dict[\"files\"].keys()) == [\"conanfile.py\", \"conanmanifest.txt\"]\n    assert list(package_dict[\"files\"].keys()) == [\"conan_package.tgz\", \"conaninfo.txt\",\n                                                  \"conanmanifest.txt\"]\n\n\ndef test_pkg_sign_no_packages():\n    c = TestClient()\n    c.save_home({\"extensions/plugins/sign/sign.py\": PLUGIN_CONTENT})\n    c.run(\"cache sign other-pkg/*\", assert_error=True)\n    assert \"ERROR: No packages to process in the package list provided\" in c.out\n    c.run(\"cache verify other-pkg/*\", assert_error=True)\n    assert \"ERROR: No packages to process in the package list provided\" in c.out\n\n\ndef test_pkg_sign_exception():\n    c = TestClient()\n    signer = textwrap.dedent(r\"\"\"\n        import os\n        from conan.errors import ConanException\n        from conan.tools.files import save\n\n        def sign(ref, artifacts_folder, signature_folder, **kwargs):\n            if \"lib\" in ref.repr_notime():\n                raise ConanException(\"Error signing package\")\n            save(None, os.path.join(signature_folder, \"signature.sig\"), \"signed-content\")\n            return [{\n                \"method\": \"dummy-method\",\n                \"provider\": \"dummy-provider\",\n                \"sign_artifacts\": {\"signature\": \"signature.sig\"}\n            }]\n        \"\"\")\n    c.save_home({\"extensions/plugins/sign/sign.py\": signer})\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n    c.run(\"export .\")\n    c.save({\"conanfile.py\": GenConanfile(\"lib\", \"0.1\")})\n    c.run(\"export .\")\n    c.save({\"conanfile.py\": GenConanfile(\"package\", \"0.1\")})\n    c.run(\"export .\")\n    c.run(\"cache sign *\", assert_error=True)\n    assert textwrap.dedent(\"\"\"\\\n        [Package sign] Results:\n\n        lib/0.1\n          revisions\n            dbe307e08b1a344fef76f60c85c0c4e8\n              ERROR: Error signing package\n        package/0.1\n          revisions\n            1fd0e5bcc411dcd3ff5b16024e2d7c04\n        pkg/0.1\n          revisions\n            485dad6cb11e2fa99d9afbe44a57a164\n\n        [Package sign] Summary: OK=2, FAILED=1\"\"\") in c.out\n    # test json output\n    c.run(\"cache sign * -f json\", assert_error=True)\n    assert \"ERROR: There were some errors in the package signing process. \" \\\n           \"Please check the output.\" in c.out\n    results = json.loads(c.stdout)\n    assert results[\"lib/0.1\"][\"revisions\"][\"dbe307e08b1a344fef76f60c85c0c4e8\"][\"pkgsign_error\"] == \\\n           \"Error signing package\"\n\n\ndef test_pkg_verify_exception():\n    c = TestClient()\n    signer = textwrap.dedent(r\"\"\"\n        import os\n        from conan.internal.util.files import save  # Only for testing purposes\n        from conan.errors import ConanException\n\n\n        def sign(ref, artifacts_folder, signature_folder, **kwargs):\n            save(os.path.join(signature_folder, \"signature.sig\"), \"signed-content\")\n            return [{\n                \"method\": \"dummy-method\",\n                \"provider\": \"dummy-provider\",\n                \"sign_artifacts\": {\"signature\": \"signature.sig\"}\n            }]\n\n        def verify(ref, artifacts_folder, signature_folder, files, **kwargs):\n            if \"lib\" in ref.repr_notime():\n                raise ConanException(\"Wrong signature\")\n        \"\"\")\n    c.save_home({\"extensions/plugins/sign/sign.py\": signer})\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n    c.run(\"export .\")\n    c.save({\"conanfile.py\": GenConanfile(\"lib\", \"0.1\")})\n    c.run(\"export .\")\n    c.save({\"conanfile.py\": GenConanfile(\"package\", \"0.1\")})\n    c.run(\"export .\")\n    c.run(\"cache sign\" \" *\")  # First sign all packages to generate manifests\n    c.run(\"cache verify *\", assert_error=True)\n    assert textwrap.dedent(\"\"\"\\\n        [Package sign] Results:\n\n        lib/0.1\n          revisions\n            dbe307e08b1a344fef76f60c85c0c4e8\n              ERROR: Wrong signature\n        package/0.1\n          revisions\n            1fd0e5bcc411dcd3ff5b16024e2d7c04\n        pkg/0.1\n          revisions\n            485dad6cb11e2fa99d9afbe44a57a164\n\n        [Package sign] Summary: OK=2, FAILED=1\"\"\") in c.out\n    # test json output\n    c.run(\"cache verify * -f json\", assert_error=True)\n    assert \"ERROR: There were some errors in the package signing process. \" \\\n           \"Please check the output.\" in c.out\n    results = json.loads(c.stdout)\n    assert results[\"lib/0.1\"][\"revisions\"][\"dbe307e08b1a344fef76f60c85c0c4e8\"][\"pkgsign_error\"] == \\\n           \"Wrong signature\"\n\n\ndef test_pkg_sign_verify_pkglist():\n    c = TestClient(default_server_user=True)\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n    c.save_home({\"extensions/plugins/sign/sign.py\": PLUGIN_CONTENT})\n    c.run(\"create .\")\n    # test empty package list\n    c.run(\"list no-exist/* -f json\", redirect_stdout=\"pkglist.json\")\n    c.run(\"cache sign -l pkglist.json\", assert_error=True)\n    assert \"ERROR: No packages to process in the package list provided\" in c.out\n    c.run(\"cache verify -l pkglist.json\", assert_error=True)\n    assert \"ERROR: No packages to process in the package list provided\" in c.out\n\n    # test incomplete package list\n    c.run(\"list */* -f json\", redirect_stdout=\"pkglist.json\")\n    c.run(\"cache sign -l pkglist.json\", assert_error=True)\n    assert \"ERROR: No packages to process in the package list provided\" in c.out\n    c.run(\"cache verify -l pkglist.json\", assert_error=True)\n    assert \"ERROR: No packages to process in the package list provided\" in c.out\n\n    # test recipe latest package list\n    c.run(\"list */*#latest -f json\", redirect_stdout=\"pkglist.json\")\n    c.run(\"cache sign -l pkglist.json\")\n    expected = textwrap.dedent(\"\"\"\\\n        [Package sign] Results:\n\n        pkg/0.1\n          revisions\n            485dad6cb11e2fa99d9afbe44a57a164\n\n        [Package sign] Summary: OK=1, FAILED=0\"\"\")\n    assert expected in c.out\n    c.run(\"cache verify -l pkglist.json\")\n    assert expected in c.out\n\n    # test packages without prev package list\n    c.run(\"list */*:* -f json\", redirect_stdout=\"pkglist.json\")\n    # FIXME: list command is returning packages without package revision, so packages are not signed\n    c.run(\"cache sign -l pkglist.json\")\n    expected = textwrap.dedent(\"\"\"\\\n        [Package sign] Results:\n\n        pkg/0.1\n          revisions\n            485dad6cb11e2fa99d9afbe44a57a164\n              packages\n                da39a3ee5e6b4b0d3255bfef95601890afd80709\n\n        [Package sign] Summary: OK=1, FAILED=0\"\"\")\n    assert expected in c.out\n    c.run(\"cache verify -l pkglist.json\")\n    assert expected in c.out\n\n    # test packages with prev package list\n    c.run(\"list */*:*#latest -f json\", redirect_stdout=\"pkglist.json\")\n    c.run(\"cache sign -l pkglist.json\")\n    expected = textwrap.dedent(\"\"\"\\\n        [Package sign] Results:\n\n        pkg/0.1\n          revisions\n            485dad6cb11e2fa99d9afbe44a57a164\n              packages\n                da39a3ee5e6b4b0d3255bfef95601890afd80709\n                  revisions\n                    0ba8627bd47edc3a501e8f0eb9a79e5e\n\n        [Package sign] Summary: OK=2, FAILED=0\"\"\")\n    assert expected in c.out\n    c.run(\"cache verify -l pkglist.json\")\n    assert expected in c.out\n"
  },
  {
    "path": "test/integration/command/config_test.py",
    "content": "import json\nimport os\nimport textwrap\n\nimport pytest\n\nfrom conan.api.conan_api import ConanAPI\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.internal.model.conf import BUILT_IN_CONFS\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient\nfrom conan.test.utils.env import environment_update\n\n\ndef test_missing_subarguments():\n    \"\"\" config MUST run  with a subcommand. Otherwise, it MUST exits with error.\n    \"\"\"\n    client = TestClient()\n    client.run(\"config\", assert_error=True)\n    assert \"ERROR: Exiting with code: 2\" in client.out\n\n\nclass TestConfigHome:\n    \"\"\" The test framework cannot test the CONAN_HOME env-var because it is not using it\n    (it will break tests for maintainers that have the env-var defined)\n    \"\"\"\n    def test_config_home_default(self):\n        client = TestClient()\n        client.run(\"config home\")\n        assert f\"{client.cache_folder}\\n\" == client.stdout\n\n        client.run(\"config home --format=text\", assert_error=True)\n        # It is not possible to use --format=text explicitly\n        assert \"--format=text\" in client.out\n\n    def test_api_uses_env_var_home(self):\n        cache_folder = os.path.join(temp_folder(), \"custom\")\n        with environment_update({\"CONAN_HOME\": cache_folder}):\n            api = ConanAPI()\n            assert api.cache_folder == cache_folder\n\n\ndef test_config_list():\n    \"\"\"\n    'conan config list' shows all the built-in Conan configurations\n    \"\"\"\n    client = TestClient()\n    client.run(\"config list\")\n    for k, v in BUILT_IN_CONFS.items():\n        assert f\"{k}: {v}\" in client.out\n    client.run(\"config list --format=json\")\n    assert f\"{json.dumps(BUILT_IN_CONFS, indent=4)}\\n\" == client.stdout\n\n    client.run(\"config list cmake\")\n    assert \"tools.cmake:cmake_program: Path to CMake executable\" in client.out\n    assert \"core.download:parallel\" not in client.out\n    assert \"tools.build:verbosity\" not in client.out\n\n\ndef test_config_install():\n    tc = TestClient()\n    tc.save({'config/foo': ''})\n    # This should not fail (insecure flag exists)\n    tc.run(\"config install config --insecure\")\n    assert \"foo\" in os.listdir(tc.cache_folder)\n    # Negative test, ensure we would be catching a missing arg if it did not exist\n    tc.run(\"config install config --superinsecure\", assert_error=True)\n\n\ndef test_config_install_conanignore():\n    tc = TestClient()\n    conanignore = textwrap.dedent(\"\"\"\n    a/*  # This is a tests\n    b/c/*\n    d/*\n    tests/*\n    # Next line is commented out, so it should be ignored\n    # other_tests/*\n    !b/c/important_file\n    !b/c/important_folder/*\n    \"\"\")\n    tc.save({\n        'config_folder/.conanignore': conanignore,\n        'config_folder/a/test': '',\n        'config_folder/abracadabra': '',\n        'config_folder/b/bison': '',\n        'config_folder/b/a/test2': '',\n        'config_folder/b/c/helmet': '',\n        'config_folder/b/c/important_file': '',\n        'config_folder/b/c/important_folder/contents': '',\n        'config_folder/d/prix': '',\n        'config_folder/d/foo/bar': '',\n        'config_folder/foo': '',\n        'config_folder/tests/tester': '',\n        'config_folder/other_tests/tester2': ''\n    })\n\n    def _assert_config_exists(path):\n        assert os.path.exists(os.path.join(tc.cache_folder, path))\n\n    def _assert_config_not_exists(path):\n        assert not os.path.exists(os.path.join(tc.cache_folder, path))\n\n    tc.run('config install config_folder')\n\n    _assert_config_not_exists(\".conanignore\")\n\n    _assert_config_not_exists(\"a\")\n    _assert_config_not_exists(\"a/test\")\n\n    _assert_config_exists(\"abracadabra\")\n\n    _assert_config_exists(\"b\")\n    _assert_config_exists(\"b/bison\")\n    _assert_config_exists(\"b/a/test2\")\n    _assert_config_not_exists(\"b/c/helmet\")\n\n    _assert_config_exists(\"b/c\")\n    _assert_config_exists(\"b/c/important_file\")\n    _assert_config_exists(\"b/c/important_folder/contents\")\n\n    _assert_config_not_exists(\"d/prix\")\n    _assert_config_not_exists(\"d/foo/bar\")\n    _assert_config_not_exists(\"d\")\n\n    _assert_config_exists(\"foo\")\n\n    _assert_config_not_exists(\"tests/tester\")\n    _assert_config_exists(\"other_tests/tester2\")\n\n\ndef test_config_install_conanignore_ignore_all_allow_specific_workflow():\n    tc = TestClient()\n    conanignore = textwrap.dedent(\"\"\"\n    *\n    !important_folder/*\n    !important_file\n    # We can even include the conanignore that we skip by default!\n    !.conanignore\n    \"\"\")\n    tc.save({\n        'config_folder/.conanignore': conanignore,\n        'config_folder/a/test': '',\n        'config_folder/abracadabra': '',\n        'config_folder/important_folder/contents': '',\n        'config_folder/important_file': '',\n    })\n\n    def _assert_config_exists(path):\n        assert os.path.exists(os.path.join(tc.cache_folder, path))\n\n    def _assert_config_not_exists(path):\n        assert not os.path.exists(os.path.join(tc.cache_folder, path))\n\n    tc.run('config install config_folder')\n\n    _assert_config_exists(\".conanignore\")\n\n    _assert_config_not_exists(\"a\")\n    _assert_config_not_exists(\"abracadabra\")\n\n    _assert_config_exists(\"important_folder/contents\")\n    _assert_config_exists(\"important_file\")\n\n\n@pytest.mark.parametrize(\"has_conanignore\", [True, False])\n@pytest.mark.parametrize(\"folder\", [None, \"myfolder\", \"myfolder/subfolder\"])\ndef test_config_install_conanignore_walk_directories(has_conanignore, folder):\n    tc = TestClient(light=True)\n    if has_conanignore:\n        conanignore = \"*\"\n        tc.save({\"config_folder/.conanignore\": conanignore})\n    tc.save({\"config_folder/myfolder/subfolder/item.py\": \"\"})\n\n    folder_arg = f\"-sf {folder} -tf {folder}\" if folder else \"\"\n\n    tc.run(f\"config install config_folder {folder_arg}\")\n    if has_conanignore:\n        assert not os.path.exists(os.path.join(tc.cache_folder, \"myfolder\", \"subfolder\", \"item.py\"))\n    else:\n        assert os.path.exists(os.path.join(tc.cache_folder, \"myfolder\", \"subfolder\", \"item.py\"))\n\n\ndef test_config_show():\n    globalconf = textwrap.dedent(\"\"\"\n    tools.build:jobs=42\n    tools.files.download:retry_wait=10\n    tools.files.download:retry=7\n    core.net.http:timeout=30\n    core.net.http:max_retries=5\n    zlib/*:user.mycategory:retry=True\n    zlib/*:user.mycategory:foo=0\n    zlib/*:user.myothercategory:foo=0\n    \"\"\")\n    tc = TestClient()\n    tc.save_home({\"global.conf\": globalconf})\n    tc.run(\"config show tools.build:jobs\")\n    assert \"42\" in tc.out\n\n    tc.run(\"config show core*\")\n    assert \"core.net.http:timeout\" in tc.out\n    assert \"30\" in tc.out\n    assert \"core.net.http:max_retries\" in tc.out\n    assert \"5\" in tc.out\n\n    tc.run(\"config show *retr*\")\n    assert \"tools.files.download:retry_wait\" in tc.out\n    assert \"tools.files.download:retry\" in tc.out\n    assert \"core.net.http:max_retries\" in tc.out\n    assert \"zlib/*:user.mycategory:retry\" in tc.out\n\n    tc.run(\"config show zlib*\")\n    assert \"zlib/*:user.mycategory:retry\" in tc.out\n    assert \"zlib/*:user.mycategory:foo\" in tc.out\n    assert \"zlib/*:user.myothercategory:foo\" in tc.out\n\n    tc.run(\"config show zlib/*\")\n    assert \"zlib/*:user.mycategory:retry\" in tc.out\n    assert \"zlib/*:user.mycategory:foo\" in tc.out\n    assert \"zlib/*:user.myothercategory:foo\" in tc.out\n\n    tc.run(\"config show zlib/*:foo\")\n    assert \"zlib/*:user.mycategory:foo\" in tc.out\n    assert \"zlib/*:user.myothercategory:foo\" in tc.out\n\n\n@pytest.mark.parametrize(\"storage_path\", [None, \"p\", \"../foo\"])\ndef test_config_clean(storage_path):\n    tc = TestClient(light=True)\n    absolut_storage_path = os.path.abspath(os.path.join(tc.current_folder, storage_path)) if storage_path else os.path.join(tc.cache_folder, \"p\")\n\n    storage = f\"core.cache:storage_path={storage_path}\" if storage_path else \"\"\n    tc.save_home({\"global.conf\": f\"core.upload:retry=7\\n{storage}\",\n                  \"extensions/compatibility/mycomp.py\": \"\",\n                  \"extensions/commands/cmd_foo.py\": \"\",\n                  })\n\n    tc.run(\"profile detect --name=foo\")\n    tc.run(\"remote add bar http://fakeurl\")\n\n    tc.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n    tc.run(\"create .\")\n\n    assert os.path.exists(absolut_storage_path)\n\n    tc.run(\"config clean\")\n    tc.run(\"profile list\")\n    assert \"foo\" not in tc.out\n    tc.run(\"remote list\")\n    assert \"bar\" not in tc.out\n    tc.run(\"config show core.upload:retry\")\n    assert \"7\" not in tc.out\n    assert os.path.exists(os.path.join(tc.cache_folder, \"extensions\"))\n    assert not os.path.exists(os.path.join(tc.cache_folder, \"extensions\", \"compatibility\", \"mycomp.py\"))\n    assert os.path.exists(absolut_storage_path)\n    # This will error because the call to clean will remove the profiles\n    tc.run(\"create .\", assert_error=True)\n    # Works after regenerating them!\n    tc.run(\"profile detect\")\n    tc.run(\"create .\")\n\n\ndef test_config_reinit():\n    custom_global_conf = \"core.upload:retry=7\"\n    global_conf_folder = temp_folder()\n    with open(os.path.join(global_conf_folder, \"global.conf\"), \"w\") as f:\n        f.write(custom_global_conf)\n\n    cache_folder = temp_folder()\n    conan_api = ConanAPI(cache_folder=cache_folder)\n    assert conan_api._api_helpers.global_conf.get(\"core.upload:retry\", check_type=int) != 7\n\n    conan_api.config.install(global_conf_folder, verify_ssl=False)\n    # Already has an effect, the config installation reinitializes the config\n    assert conan_api._api_helpers.global_conf.get(\"core.upload:retry\", check_type=int) == 7\n\n\ndef test_config_reinit_core_conf():\n    tc = TestClient(light=True)\n    tc.save_home({\"extensions/commands/cmd_foo.py\": textwrap.dedent(\"\"\"\n        from conan.cli.command import conan_command\n        from conan.api.output import ConanOutput\n\n        @conan_command()\n        def foo(conan_api, parser, *args, **kwargs):\n            ''' Foo '''\n            parser.parse_args(*args)\n            ConanOutput().info(f\"Retry: {conan_api.config.get('core.upload:retry', check_type=int)}\")\n    \"\"\")})\n    tc.run(\"foo -cc core.upload:retry=7\")\n    assert \"Retry: 7\" in tc.out\n"
  },
  {
    "path": "test/integration/command/create_test.py",
    "content": "import json\nimport os\nimport re\nimport textwrap\n\nimport pytest\n\nfrom conan.api.model import RecipeReference\nfrom conan.cli.exit_codes import ERROR_GENERAL\nfrom conan.test.utils.tools import TestClient, NO_SETTINGS_PACKAGE_ID, GenConanfile\nfrom conan.internal.util.files import load\n\n\ndef test_dependencies_order_matches_requires():\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"create . --name=pkga --version=0.1 --user=user --channel=testing\")\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"create . --name=pkgb --version=0.1 --user=user --channel=testing\")\n    conanfile = textwrap.dedent(\"\"\"\n        [requires]\n        pkgb/0.1@user/testing\n        pkga/0.1@user/testing\n        \"\"\")\n    client.save({\"conanfile.txt\": conanfile}, clean_first=True)\n    client.run(\"install . -g MSBuildDeps -s build_type=Release -s arch=x86\")\n    conandeps = client.load(\"conandeps.props\")\n    assert conandeps.find(\"pkgb\") < conandeps.find(\"pkga\")\n\n\ndef test_create():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    class MyPkg(ConanFile):\n        def source(self):\n            assert(self.version==\"0.1\")\n            assert(self.name==\"pkg\")\n        def configure(self):\n            assert(self.version==\"0.1\")\n            assert(self.name==\"pkg\")\n        def requirements(self):\n            assert(self.version==\"0.1\")\n            assert(self.name==\"pkg\")\n        def build(self):\n            assert(self.version==\"0.1\")\n            assert(self.name==\"pkg\")\n        def package(self):\n            assert(self.version==\"0.1\")\n            assert(self.name==\"pkg\")\n        def package_info(self):\n            assert(self.version==\"0.1\")\n            assert(self.name==\"pkg\")\n        def system_requirements(self):\n            assert(self.version==\"0.1\")\n            assert(self.name==\"pkg\")\n            self.output.info(\"Running system requirements!!\")\n    \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create --name=pkg --version=0.1 --user=lasote --channel=testing\")\n    assert \"Profile host:\\n[settings]\" in client.out\n    assert \"pkg/0.1@lasote/testing: Generating the package\" in client.out\n    assert \"Running system requirements!!\" in client.out\n    client.run('list -c *')\n    assert \"pkg/0.1@lasote/testing\" in client.out\n\n    # Create with only user will raise an error because of no name/version\n    client.run(\"create conanfile.py --user=lasote --channel=testing\", assert_error=True)\n    assert \"ERROR: conanfile didn't specify name\" in client.out\n    # Create with user but no channel should be valid\n    client.run(\"create . --name=pkg --version=0.1 --user=lasote\")\n    assert \"pkg/0.1@lasote:\" in client.out\n\n\ndef test_error_create_name_version():\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile().with_name(\"hello\").with_version(\"1.2\")})\n    client.run(\"create . --name=hello --version=1.2 --user=lasote --channel=stable\")\n    client.run(\"create . --name=pkg\", assert_error=True)\n    assert \"ERROR: Package recipe with name pkg!=hello\" in client.out\n    client.run(\"create . --version=1.1\", assert_error=True)\n    assert \"ERROR: Package recipe with version 1.1!=1.2\" in client.out\n\n\ndef test_create_user_channel():\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile().with_name(\"pkg\").with_version(\"0.1\")})\n    client.run(\"create . --user=lasote --channel=channel\")\n    assert \"pkg/0.1@lasote/channel: Generating the package\" in client.out\n    client.run(\"list * -c\")\n    assert \"pkg/0.1@lasote/channel\" in client.out\n\n    # test default without user and channel\n    client.run(\"create . \")\n    assert \"pkg/0.1: Generating the package\" in client.out\n\n\ndef test_create_in_subfolder():\n    client = TestClient()\n    client.save({\"subfolder/conanfile.py\": GenConanfile().with_name(\"pkg\").with_version(\"0.1\")})\n    client.run(\"create subfolder --user=lasote --channel=channel\")\n    assert \"pkg/0.1@lasote/channel: Generating the package\" in client.out\n    client.run(\"list * -c\")\n    assert \"pkg/0.1@lasote/channel\" in client.out\n\n\ndef test_create_in_subfolder_with_different_name():\n    # Now with a different name\n    client = TestClient()\n    client.save({\"subfolder/Custom.py\": GenConanfile().with_name(\"pkg\").with_version(\"0.1\")})\n    client.run(\"create subfolder/Custom.py --user=lasote --channel=channel\")\n    assert \"pkg/0.1@lasote/channel: Generating the package\" in client.out\n    client.run(\"list * -c\")\n    assert \"pkg/0.1@lasote/channel\" in client.out\n\n\ndef test_create_test_package():\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile().with_name(\"pkg\").with_version(\"0.1\"),\n                 \"test_package/conanfile.py\":\n                     GenConanfile().with_test('self.output.info(\"TESTING!!!\")')})\n    client.run(\"create . --user=lasote --channel=testing\")\n    assert \"pkg/0.1@lasote/testing: Generating the package\" in client.out\n    assert \"pkg/0.1@lasote/testing (test package): TESTING!!!\" in client.out\n\n\ndef test_create_skip_test_package():\n    # Skip the test package stage if explicitly disabled with --test-folder=None\n    # https://github.com/conan-io/conan/issues/2355\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile().with_name(\"pkg\").with_version(\"0.1\"),\n                 \"test_package/conanfile.py\":\n                     GenConanfile().with_test('self.output.info(\"TESTING!!!\")')})\n    client.run(\"create . --user=lasote --channel=testing --test-folder=\\\"\\\"\")\n    assert \"pkg/0.1@lasote/testing: Generating the package\" in client.out\n    assert \"TESTING!!!\" not in client.out\n\n\ndef test_create_package_requires():\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"create . --name=dep --version=0.1 --user=user --channel=channel\")\n    client.run(\"create . --name=other --version=1.0 --user=user --channel=channel\")\n\n    conanfile = GenConanfile().with_require(\"dep/0.1@user/channel\")\n    test_conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    class MyPkg(ConanFile):\n        requires = \"other/1.0@user/channel\"\n        def requirements(self):\n            self.requires(self.tested_reference_str)\n        def build(self):\n            for r in self.requires.values():\n                self.output.info(\"build() Requires: %s\" % str(r.ref))\n            import os\n            for dep in self.dependencies.host.values():\n                self.output.info(\"build() cpp_info dep: %s\" % dep)\n\n        def test(self):\n            pass\n    \"\"\")\n\n    client.save({\"conanfile.py\": conanfile,\n                 \"test_package/conanfile.py\": test_conanfile})\n\n    client.run(\"create . --name=pkg --version=0.1 --user=lasote --channel=testing -vv\")\n\n    assert \"pkg/0.1@lasote/testing (test package): build() \" \\\n           \"Requires: other/1.0@user/channel\" in client.out\n    assert \"pkg/0.1@lasote/testing (test package): build() \" \\\n           \"Requires: pkg/0.1@lasote/testing\" in client.out\n    assert \"pkg/0.1@lasote/testing (test package): build() cpp_info dep: other\" in client.out\n    assert \"pkg/0.1@lasote/testing (test package): build() cpp_info dep: dep\" in client.out\n    assert \"pkg/0.1@lasote/testing (test package): build() cpp_info dep: pkg\" in client.out\n\n    # Check that the additional info shows up when creating pkg\n    # Graph info, package creation, and test package graph info\n    assert client.out.count(\"requires: dep/0.1@user/channel\") == 3\n\n\ndef test_package_folder_build_error():\n    \"\"\"\n    Check package folder is not created if the build step fails\n    \"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class MyPkg(ConanFile):\n\n            def build(self):\n                raise Exception(\"Build error\")\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n\n    ref = RecipeReference(\"pkg\", \"0.1\", \"danimtb\", \"testing\")\n    client.run(\"create . --name=pkg --version=0.1 --user=danimtb --channel=testing\",\n               assert_error=True)\n\n    assert \"Build error\" in client.out\n    pref = client.get_latest_package_reference(ref, NO_SETTINGS_PACKAGE_ID)\n    assert pref is None\n\n\ndef test_create_with_name_and_version():\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run('create . --name=lib --version=1.0')\n    assert \"lib/1.0: Created package revision\" in client.out\n\n\ndef test_create_with_only_user_channel():\n    \"\"\"This should be the recommended way and only from Conan 2.0\"\"\"\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile().with_name(\"lib\").with_version(\"1.0\")})\n    client.run('create . --user=user --channel=channel')\n    assert \"lib/1.0@user/channel: Created package revision\" in client.out\n\n    client.run('create . --user=user --channel=channel')\n    assert \"lib/1.0@user/channel: Created package revision\" in client.out\n\n\ndef test_requires_without_user_channel():\n    client = TestClient()\n    conanfile = textwrap.dedent('''\n        from conan import ConanFile\n\n        class HelloConan(ConanFile):\n            name = \"hellobar\"\n            version = \"0.1\"\n\n            def package_info(self):\n                self.output.warning(\"Hello, I'm hellobar\")\n        ''')\n\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create .\")\n\n    client.save({\"conanfile.py\": GenConanfile().with_require(\"hellobar/0.1\")})\n    client.run(\"create . --name=consumer --version=1.0\")\n    assert \"hellobar/0.1: WARN: Hello, I'm hellobar\" in client.out\n    assert \"consumer/1.0: Created package revision\" in client.out\n\n\ndef test_conaninfo_contents_without_user_channel():\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile().with_name(\"hello\").with_version(\"0.1\")})\n    client.run(\"create .\")\n    client.save({\"conanfile.py\": GenConanfile().with_name(\"bye\").with_version(\"0.1\")\n                .with_require(\"hello/0.1\")})\n    client.run(\"create .\")\n\n    package_folder = client.created_layout().package()\n\n    conaninfo = load(os.path.join(package_folder, \"conaninfo.txt\"))\n    # The user and channel nor None nor \"_/\" appears in the conaninfo\n    assert \"None\" not in conaninfo\n    assert \"_/\" not in conaninfo\n    assert \"/_\" not in conaninfo\n    assert \"[requires]\\nhello/0.1\\n\" in conaninfo\n\n\ndef test_components_json_output():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class MyTest(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            settings = \"build_type\"\n\n            def package_info(self):\n                self.cpp_info.components[\"pkg1\"].libs = [\"libpkg1\"]\n                self.cpp_info.components[\"pkg2\"].libs = [\"libpkg2\"]\n                self.cpp_info.components[\"pkg2\"].requires = [\"pkg1\"]\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --format=json\")\n    data = json.loads(client.stdout)\n    cpp_info_data = data[\"graph\"][\"nodes\"][\"1\"][\"cpp_info\"]\n    assert \"libpkg1\" in cpp_info_data[\"pkg1\"][\"libs\"]\n    assert cpp_info_data[\"pkg1\"][\"requires\"] == []\n    assert \"libpkg2\" in cpp_info_data[\"pkg2\"][\"libs\"]\n    assert cpp_info_data[\"pkg2\"][\"requires\"] == [\"pkg1\"]\n\n\ndef test_lockfile_input_not_specified():\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile().with_name(\"foo\").with_version(\"1.0\")})\n    client.run(\"lock create . --lockfile-out locks/conan.lock\")\n    client.run(\"create . --lockfile-out locks/conan.lock\")\n    assert \"Generated lockfile:\" in client.out\n\n\ndef test_create_build_missing():\n    \"\"\" test the --build=missing:pattern syntax\n    \"\"\"\n    c = TestClient()\n    c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"1.0\").with_settings(\"os\"),\n            \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_settings(\"os\")\n           .with_requires(\"dep/1.0\")})\n    c.run(\"create dep -s os=Windows\")\n\n    # Wrong pattern will not build it\n    c.run(\"create pkg -s os=Windows --build=missing:kk\", assert_error=True)\n    assert \"ERROR: Missing prebuilt package for 'pkg/1.0'\" in c.out\n\n    # Pattern missing * will not build it\n    c.run(\"create pkg -s os=Windows --build=missing:pkg\", assert_error=True)\n    assert \"ERROR: Missing prebuilt package for 'pkg/1.0'\" in c.out\n\n    # Correct pattern pkg* will build it\n    c.run(\"create pkg -s os=Windows --build=missing:pkg*\")\n    c.assert_listed_binary({\"pkg/1.0\": (\"90887fdbe22295dfbe41afe0a45f960c6a72b650\", \"Build\")})\n\n    # Now anything that is not an explicit --build=pkg* will avoid rebuilding\n    c.run(\"create pkg -s os=Windows --build=missing:kk\")\n    c.assert_listed_binary({\"pkg/1.0\": (\"90887fdbe22295dfbe41afe0a45f960c6a72b650\", \"Cache\")})\n    assert \"Calling build()\" not in c.out\n\n    # but dependency without binary will fail, even if right pkg* pattern\n    c.run(\"create pkg -s os=Linux --build=missing:pkg*\", assert_error=True)\n    c.assert_listed_binary({\"pkg/1.0\": (\"4c0c198b627f9af3e038af4da5e6b3ae205c2435\", \"Build\")})\n    c.assert_listed_binary({\"dep/1.0\": (\"9a4eb3c8701508aa9458b1a73d0633783ecc2270\", \"Missing\")})\n    assert \"ERROR: Missing prebuilt package for 'dep/1.0'\" in c.out\n\n    # The & placeholder also works\n    c.run(\"create pkg -s os=Linux --build=missing:&\", assert_error=True)\n    c.assert_listed_binary({\"pkg/1.0\": (\"4c0c198b627f9af3e038af4da5e6b3ae205c2435\", \"Build\")})\n    c.assert_listed_binary({\"dep/1.0\": (\"9a4eb3c8701508aa9458b1a73d0633783ecc2270\", \"Missing\")})\n    assert \"ERROR: Missing prebuilt package for 'dep/1.0'\" in c.out\n\n\ndef test_create_no_user_channel():\n    \"\"\" test the --build=pattern and --build=missing:pattern syntax to build missing packages\n     without user/channel\n    \"\"\"\n    c = TestClient()\n    c.save({\"dep/conanfile.py\": GenConanfile(),\n            \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_requires(\"dep1/0.1\", \"dep2/0.1@user\",\n                                                                         \"dep3/0.1@user/channel\")})\n    c.run(\"export dep --name=dep1 --version=0.1\")\n    c.run(\"export dep --name=dep2 --version=0.1 --user=user\")\n    c.run(\"export dep --name=dep3 --version=0.1 --user=user --channel=channel\")\n\n    # First test the ``--build=missing:pattern``\n    c.run(\"create pkg --build=missing:*@\", assert_error=True)\n    c.assert_listed_binary({\"dep1/0.1\": (NO_SETTINGS_PACKAGE_ID, \"Build\"),\n                            \"dep2/0.1\": (NO_SETTINGS_PACKAGE_ID, \"Missing\"),\n                            \"dep3/0.1\": (NO_SETTINGS_PACKAGE_ID, \"Missing\")})\n    c.run(\"create pkg --build=missing:!*@\", assert_error=True)\n    c.assert_listed_binary({\"dep1/0.1\": (NO_SETTINGS_PACKAGE_ID, \"Missing\"),\n                            \"dep2/0.1\": (NO_SETTINGS_PACKAGE_ID, \"Build\"),\n                            \"dep3/0.1\": (NO_SETTINGS_PACKAGE_ID, \"Build\")})\n\n    # Now lets make sure they exist\n    c.run(\"create pkg --build=missing\")\n\n    # Now test the --build=pattern\n    c.run(\"create pkg --build=*@\")\n    c.assert_listed_binary({\"dep1/0.1\": (NO_SETTINGS_PACKAGE_ID, \"Build\"),\n                            \"dep2/0.1\": (NO_SETTINGS_PACKAGE_ID, \"Cache\"),\n                            \"dep3/0.1\": (NO_SETTINGS_PACKAGE_ID, \"Cache\")})\n    # The --build=* needs to be said: \"build all except those that have user/channel\n    c.run(\"create pkg --build=* --build=!*@\")\n    c.assert_listed_binary({\"dep1/0.1\": (NO_SETTINGS_PACKAGE_ID, \"Cache\"),\n                            \"dep2/0.1\": (NO_SETTINGS_PACKAGE_ID, \"Build\"),\n                            \"dep3/0.1\": (NO_SETTINGS_PACKAGE_ID, \"Build\")})\n\n\ndef test_create_build_missing_negation():\n    tc = TestClient(light=True)\n    tc.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"1.0\"),\n             \"lib/conanfile.py\": GenConanfile(\"lib\", \"1.0\").with_requires(\"dep/1.0\"),\n             \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_requires(\"lib/1.0\")})\n\n    tc.run(\"export dep\")\n    tc.run(\"export lib\")\n    tc.run(\"create pkg --build=missing:~dep/*\", assert_error=True)\n\n    tc.assert_listed_binary({\"pkg/1.0\": (\"a72376edfbbdaf97c8608b5fda53cadebac46a20\", \"Build\"),\n                             \"lib/1.0\": (\"abfcc78fa8242cabcd1e3d92896aa24808c789a3\", \"Build\"),\n                             \"dep/1.0\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\", \"Missing\")})\n\n    tc.run(\"create pkg --build=missing:~dep/* --build=missing:~lib/*\",\n           assert_error=True)\n\n    tc.assert_listed_binary({\"pkg/1.0\": (\"a72376edfbbdaf97c8608b5fda53cadebac46a20\", \"Build\"),\n                             \"lib/1.0\": (\"abfcc78fa8242cabcd1e3d92896aa24808c789a3\", \"Missing\"),\n                             \"dep/1.0\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\", \"Missing\")})\n\n\ndef test_create_format_json():\n    \"\"\"\n    Tests the ``conan create . -f json`` result\n\n    The result should be something like:\n\n    {\n        'graph': {\n            'nodes': [\n                {'ref': '',  # consumer\n                 'recipe': 'Virtual',\n                 ....\n                },\n                {'ref': 'hello/0.1#18d5440ae45afc4c36139a160ac071c7',\n                 'dependencies': {'1': {'ref': 'hello/0.1', 'visible': 'True', ...}},\n                 ....\n                },\n                {'ref': 'pkg/0.2#44a1a27ac2ea1fbcf434a05c4d57388d',\n                 ....\n                }\n            ],\n            'root': {'0': 'None'}\n        }\n    }\n    \"\"\"\n    client = TestClient()\n    profile_build = textwrap.dedent(\"\"\"\\\n    [settings]\n    arch=x86_64\n    build_type=Release\n    compiler=gcc\n    compiler.libcxx=libstdc++\n    compiler.version=12\n    os=Linux\n    [conf]\n    user.first:value=\"my value\"\n    user.second:value=[\"my value\"]\n    user.second:value+=[\"other value\"]\n    [buildenv]\n    VAR1=myvalue1\n    \"\"\")\n    profile_host = textwrap.dedent(\"\"\"\\\n    [settings]\n    arch=x86\n    build_type=Debug\n    compiler=gcc\n    compiler.libcxx=libstdc++\n    compiler.version=12\n    os=Linux\n    \"\"\")\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class MyTest(ConanFile):\n            name = \"pkg\"\n            version = \"0.2\"\n            settings = \"build_type\", \"compiler\"\n            author = \"John Doe\"\n            license = \"MIT\"\n            url = \"https://foo.bar.baz\"\n            homepage = \"https://foo.bar.site\"\n            topics = \"foo\", \"bar\", \"qux\"\n            provides = \"libjpeg\", \"libjpg\"\n            deprecated = \"other-pkg\"\n            options = {\"shared\": [True, False], \"fPIC\": [True, False]}\n            default_options = {\"shared\": False, \"fPIC\": True}\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile,\n                 \"host\": profile_host, \"build\": profile_build})\n    client.run(\"create . -pr:h host -pr:b build\")\n    client.save({\"conanfile.py\": GenConanfile().with_name(\"hello\").with_version(\"0.1\")\n                .with_require(\"pkg/0.2\"),\n                 \"host\": profile_host, \"build\": profile_build}, clean_first=True)\n    client.run(\"create . -f json -pr:h host -pr:b build\")\n    info = json.loads(client.stdout)\n    nodes = info[\"graph\"]['nodes']\n    consumer_ref = 'conanfile'\n    hello_pkg_ref = 'hello/0.1#18d5440ae45afc4c36139a160ac071c7'\n    pkg_pkg_ref = 'pkg/0.2#db78b8d06a78af5c3ac56706f133098d'\n    consumer_info = hello_pkg_info = pkg_pkg_info = None\n\n    for n in nodes.values():\n        ref = n[\"ref\"]\n        if ref == consumer_ref:\n            consumer_info = n\n        elif ref == hello_pkg_ref:\n            hello_pkg_info = n\n        else:\n            assert ref == pkg_pkg_ref\n            pkg_pkg_info = n\n\n    # Consumer information\n    assert consumer_info[\"recipe\"] == \"Cli\"\n    assert consumer_info[\"package_id\"] is None\n    assert consumer_info[\"prev\"] is None\n    assert consumer_info[\"options\"] == {}\n    assert consumer_info[\"settings\"] == {'arch': 'x86', 'build_type': 'Debug', 'compiler': 'gcc',\n                                         'compiler.libcxx': 'libstdc++', 'compiler.version': '12',\n                                         'os': 'Linux'}\n    consumer_deps = {\n        '1': {'ref': 'hello/0.1', 'run': False, 'libs': True, 'skip': False,\n              'test': False, 'force': False, 'direct': True, 'build': False,\n              'transitive_headers': None, 'transitive_libs': None, 'headers': True,\n              'package_id_mode': None, 'visible': True, 'require': 'hello/0.1'},\n        '2': {'ref': 'pkg/0.2', 'run': False, 'libs': True, 'skip': False, 'test': False,\n              'force': False, 'direct': False, 'build': False, 'transitive_headers': None,\n              'transitive_libs': None, 'headers': True, 'package_id_mode': None,\n              'visible': True, 'require': 'pkg/0.2'}\n    }\n    assert consumer_info[\"dependencies\"] == consumer_deps\n    # hello/0.1 pkg information\n    assert hello_pkg_info[\"package_id\"] == \"8eba237c0fb239fcb7daa47979ab99258eaaa7d1\"\n    assert hello_pkg_info[\"prev\"] == \"d95380a07c35273509dfc36b26f6cec1\"\n    assert hello_pkg_info[\"settings\"] == {}\n    assert hello_pkg_info[\"options\"] == {}\n    hello_pkg_info_deps = {\n        \"2\": {\n            \"ref\": \"pkg/0.2\", \"run\": False, \"libs\": True, \"skip\": False, \"test\": False,\n            \"force\": False, \"direct\": True, \"build\": False, \"transitive_headers\": None,\n            \"transitive_libs\": None, \"headers\": True, \"package_id_mode\": \"semver_mode\",\n            \"visible\": True, 'require': 'pkg/0.2'\n        }\n    }\n    assert hello_pkg_info[\"dependencies\"] == hello_pkg_info_deps\n    # pkg/0.2 pkg information\n    assert pkg_pkg_info[\"package_id\"] == \"fb1439470288b15b2da269ed97b1a5f2f5d1f766\"\n    assert pkg_pkg_info[\"prev\"] == \"6949b0f89941d2a5994f9e6e4a89a331\"\n    assert pkg_pkg_info[\"author\"] == 'John Doe'\n    assert pkg_pkg_info[\"settings\"] == {'build_type': 'Debug', 'compiler': 'gcc',\n                                        'compiler.libcxx': 'libstdc++', 'compiler.version': '12'}\n    assert pkg_pkg_info[\"options\"] == {'fPIC': 'True', 'shared': 'False'}\n    assert pkg_pkg_info[\"dependencies\"] == {}\n\n\ndef test_create_format_json_and_deps_cpp_info():\n    \"\"\"\n    Tests the ``conan create . -f json`` result, but ``cpp_info`` object only.\n\n    The goal is to get something like:\n\n    ```\n    { ....\n    'cpp_info': {'cmp1': {'bindirs': None,\n                          'builddirs': None,\n                          'cflags': None,\n                          'cxxflags': None,\n                          'defines': None,\n                          'exelinkflags': None,\n                          'frameworkdirs': None,\n                          'frameworks': None,\n                          'includedirs': None,\n                          'libdirs': None,\n                          'libs': ['libcmp1'],\n                          'objects': None,\n                          'properties': {'pkg_config_aliases': ['compo1_alias'],\n                                         'pkg_config_name': 'compo1'},\n                          'dependencies': None,\n                          'resdirs': None,\n                          'sharedlinkflags': None,\n                          'srcdirs': None,\n                          'sysroot': '/another/sysroot',\n                          'system_libs': None},\n                 'root': {'bindirs': ['bin'],\n                          'builddirs': [],\n                          'cflags': ['pkg_a_c_flag'],\n                          'cxxflags': ['pkg_a_cxx_flag'],\n                          'defines': ['pkg_onedefinition',\n                                      'pkg_twodefinition'],\n                          'exelinkflags': ['pkg_exe_link_flag'],\n                          'frameworkdirs': ['framework/path/pkg'],\n                          'frameworks': ['pkg_oneframework',\n                                         'pkg_twoframework'],\n                          'includedirs': ['path/includes/pkg',\n                                          'include/path/pkg'],\n                          'libdirs': ['lib/path/pkg'],\n                          'libs': ['pkg'],\n                          'objects': None,\n                          'properties': {'pkg_config_aliases': ['pkg_alias1',\n                                                                'pkg_alias2'],\n                                         'pkg_config_name': 'pkg_other_name'},\n                          'dependencies': None,\n                          'resdirs': ['/path '\n                                      'with '\n                                      'spaces/.conan2/p/d15a235e212166d9/p/res'],\n                          'sharedlinkflags': ['pkg_shared_link_flag'],\n                          'srcdirs': None,\n                          'sysroot': '/path/to/folder/pkg',\n                          'system_libs': ['pkg_onesystemlib',\n                                          'pkg_twosystemlib']}\n    }}\n    ```\n    \"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class MyTest(ConanFile):\n            name = \"pkg\"\n            version = \"0.2\"\n\n            def package_info(self):\n                self.cpp_info.libs = [\"pkg\"]\n                self.cpp_info.includedirs = [\"path/includes/pkg\", \"other/include/path/pkg\"]\n                self.cpp_info.libdirs = [\"one/lib/path/pkg\"]\n                self.cpp_info.defines = [\"pkg_onedefinition\", \"pkg_twodefinition\"]\n                self.cpp_info.cflags = [\"pkg_a_c_flag\"]\n                self.cpp_info.cxxflags = [\"pkg_a_cxx_flag\"]\n                self.cpp_info.sharedlinkflags = [\"pkg_shared_link_flag\"]\n                self.cpp_info.exelinkflags = [\"pkg_exe_link_flag\"]\n                self.cpp_info.sysroot = \"/path/to/folder/pkg\"\n                self.cpp_info.frameworks = [\"pkg_oneframework\", \"pkg_twoframework\"]\n                self.cpp_info.system_libs = [\"pkg_onesystemlib\", \"pkg_twosystemlib\"]\n                self.cpp_info.frameworkdirs = [\"one/framework/path/pkg\"]\n                self.cpp_info.set_property(\"pkg_config_name\", \"pkg_other_name\")\n                self.cpp_info.set_property(\"pkg_config_aliases\", [\"pkg_alias1\", \"pkg_alias2\"])\n                self.cpp_info.components[\"cmp1\"].libs = [\"libcmp1\"]\n                self.cpp_info.components[\"cmp1\"].set_property(\"pkg_config_name\", \"compo1\")\n                self.cpp_info.components[\"cmp1\"].set_property(\"pkg_config_aliases\", [\"compo1_alias\"])\n                self.cpp_info.components[\"cmp1\"].sysroot = \"/another/sysroot\"\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create .\")\n    client.save({\"conanfile.py\": GenConanfile().with_name(\"hello\").with_version(\"0.1\")\n                .with_require(\"pkg/0.2\")}, clean_first=True)\n    client.run(\"create . -f json\")\n    info = json.loads(client.stdout)\n    nodes = info[\"graph\"][\"nodes\"]\n    hello_pkg_ref = 'hello/0.1#18d5440ae45afc4c36139a160ac071c7'\n    pkg_pkg_ref = 'pkg/0.2#926714b5fb0a994f47ec37e071eba1da'\n    hello_cpp_info = pkg_cpp_info = None\n    for n in nodes.values():\n        ref = n[\"ref\"]\n        if ref == hello_pkg_ref:\n            assert n['binary'] == \"Build\"\n            hello_cpp_info = n['cpp_info']\n        elif ref == pkg_pkg_ref:\n            assert n['binary'] == \"Cache\"\n            pkg_cpp_info = n['cpp_info']\n\n    assert hello_cpp_info and pkg_cpp_info\n    # hello/0.1 cpp_info\n    assert hello_cpp_info['root'][\"libs\"] is None\n    assert len(hello_cpp_info['root'][\"bindirs\"]) == 1\n    assert len(hello_cpp_info['root'][\"libdirs\"]) == 1\n    assert hello_cpp_info['root'][\"sysroot\"] is None\n    assert hello_cpp_info['root'][\"properties\"] is None\n    # pkg/0.2 cpp_info\n    # root info\n    assert pkg_cpp_info['root'][\"libs\"] == ['pkg']\n    assert len(pkg_cpp_info['root'][\"bindirs\"]) == 1\n    assert len(pkg_cpp_info['root'][\"libdirs\"]) == 1\n    assert pkg_cpp_info['root'][\"sysroot\"] == '/path/to/folder/pkg'\n    assert pkg_cpp_info['root'][\"system_libs\"] == ['pkg_onesystemlib', 'pkg_twosystemlib']\n    assert pkg_cpp_info['root']['cflags'] == ['pkg_a_c_flag']\n    assert pkg_cpp_info['root']['cxxflags'] == ['pkg_a_cxx_flag']\n    assert pkg_cpp_info['root']['defines'] == ['pkg_onedefinition', 'pkg_twodefinition']\n    assert pkg_cpp_info['root'][\"properties\"] == {'pkg_config_aliases': ['pkg_alias1', 'pkg_alias2'],\n                                                  'pkg_config_name': 'pkg_other_name'}\n    # component info\n    assert pkg_cpp_info['cmp1'][\"libs\"] == ['libcmp1']\n    assert pkg_cpp_info['cmp1'][\"bindirs\"][0].endswith(\"bin\")  # Abs path /bin\n    assert pkg_cpp_info['cmp1'][\"libdirs\"][0].endswith(\"lib\")  # Abs path /lib\n    assert pkg_cpp_info['cmp1'][\"sysroot\"] == \"/another/sysroot\"\n    assert pkg_cpp_info['cmp1'][\"properties\"] == {'pkg_config_aliases': ['compo1_alias'],\n                                                  'pkg_config_name': 'compo1'}\n\n\ndef test_default_framework_dirs():\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n\n\n    class LibConan(ConanFile):\n        name = \"lib\"\n        version = \"1.0\"\n\n        def package_info(self):\n            self.output.warning(\"FRAMEWORKS: {}\".format(self.cpp_info.frameworkdirs))\"\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create .\")\n    assert \"FRAMEWORKS: []\" in client.out\n\n\ndef test_default_framework_dirs_with_layout():\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n\n\n    class LibConan(ConanFile):\n        name = \"lib\"\n        version = \"1.0\"\n\n        def layout(self):\n            pass\n\n        def package_info(self):\n            self.output.warning(\"FRAMEWORKS: {}\".format(self.cpp_info.frameworkdirs))\"\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create .\")\n    assert \"FRAMEWORKS: []\" in client.out\n\n\ndef test_defaults_in_components():\n    \"\"\"In Conan 2, declaring or not the layout has no influence in how cpp_info behaves. It was\n       only 1.X\"\"\"\n    lib_conan_file = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n\n    class LibConan(ConanFile):\n        name = \"lib\"\n        version = \"1.0\"\n\n        def layout(self):\n            pass\n\n        def package_info(self):\n            self.cpp_info.components[\"foo\"].libs = [\"foolib\"]\n\n    \"\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": lib_conan_file})\n    client.run(\"create . \")\n\n    consumer_conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Consumer(ConanFile):\n            name = \"consumer\"\n            version = \"1.0\"\n            requires = \"lib/1.0\"\n\n            def layout(self):\n                pass\n\n            def generate(self):\n                cppinfo = self.dependencies[\"lib\"].cpp_info\n                components = cppinfo.components\n                self.output.warning(\"BINDIRS: {}\".format(cppinfo.bindirs))\n                self.output.warning(\"LIBDIRS: {}\".format(cppinfo.libdirs))\n                self.output.warning(\"INCLUDEDIRS: {}\".format(cppinfo.includedirs))\n                self.output.warning(\"RESDIRS: {}\".format(cppinfo.resdirs))\n                self.output.warning(\"FOO LIBDIRS: {}\".format(components[\"foo\"].libdirs))\n                self.output.warning(\"FOO INCLUDEDIRS: {}\".format(components[\"foo\"].includedirs))\n                self.output.warning(\"FOO RESDIRS: {}\".format(components[\"foo\"].resdirs))\n\n        \"\"\")\n\n    client.save({\"conanfile.py\": consumer_conanfile})\n    client.run(\"create . \")\n\n    # The paths are absolute and the components have defaults\n    # \".+\" Check that there is a path, not only \"lib\"\n    assert re.search(r\"BINDIRS: \\['.+bin']\", client.out)\n    assert re.search(r\"LIBDIRS: \\['.+lib']\", client.out)\n    assert re.search(r\"INCLUDEDIRS: \\['.+include']\", client.out)\n    assert \"WARN: RES DIRS: []\"\n    assert re.search(r\"WARN: FOO LIBDIRS: \\['.+lib']\", client.out)\n    assert re.search(r\"WARN: FOO INCLUDEDIRS: \\['.+include']\", client.out)\n    assert \"WARN: FOO RESDIRS: []\" in client.out\n\n    # The paths are absolute and the components have defaults\n    # \".+\" Check that there is a path, not only \"lib\"\n    assert re.search(r\"BINDIRS: \\['.+bin']\", client.out)\n    assert re.search(r\"LIBDIRS: \\['.+lib']\", client.out)\n    assert re.search(r\"INCLUDEDIRS: \\['.+include']\", client.out)\n    assert \"WARN: RES DIRS: []\"\n    assert bool(re.search(r\"WARN: FOO LIBDIRS: \\['.+lib']\", client.out))\n    assert bool(re.search(r\"WARN: FOO INCLUDEDIRS: \\['.+include']\", client.out))\n    assert \"WARN: FOO RESDIRS: []\" in client.out\n\n\ndef test_name_never():\n    \"\"\" check that a package can be named equal to a build policy --build=never,\n    because --build are now patterns\n    Close https://github.com/conan-io/conan/issues/12430\n    \"\"\"\n    c = TestClient()\n    c.save({\"conanfile.py\": GenConanfile(\"never\", \"0.1\")})\n    c.run(\"create .\")\n    assert \"never/0.1: Created package\" in c.out\n\n\ndef test_create_both_host_build_require():\n    c = TestClient()\n    c.save({\"conanfile.py\": GenConanfile(\"protobuf\", \"0.1\").with_settings(\"build_type\"),\n            \"test_package/conanfile.py\": GenConanfile().with_build_requires(\"protobuf/0.1\")\n                                                       .with_test(\"pass\")})\n    c.run(\"create . -s:b build_type=Release -s:h build_type=Debug\", assert_error=True)\n    # The main \"host\" Debug binary will be correctly build\n    c.assert_listed_binary({\"protobuf/0.1\": (\"9e186f6d94c008b544af1569d1a6368d8339efc5\", \"Build\")})\n    # But test_package will fail because of the missing \"tool_require\" in Release\n    c.assert_listed_binary({\"protobuf/0.1\": (\"efa83b160a55b033c4ea706ddb980cd708e3ba1b\", \"Missing\")},\n                           build=True, test_package=True)\n\n    c.run(\"remove * -c\")  # make sure that previous binary is removed\n    c.run(\"create . -s:b build_type=Release -s:h build_type=Debug --build-test=missing\")\n    c.assert_listed_binary({\"protobuf/0.1\": (\"9e186f6d94c008b544af1569d1a6368d8339efc5\", \"Build\")})\n    # it used to fail, now it works and builds the test_package \"tools_requires\" in Release\n    c.assert_listed_binary({\"protobuf/0.1\": (\"9e186f6d94c008b544af1569d1a6368d8339efc5\", \"Cache\")},\n                           test_package=True)\n    c.assert_listed_binary({\"protobuf/0.1\": (\"efa83b160a55b033c4ea706ddb980cd708e3ba1b\", \"Build\")},\n                           build=True, test_package=True)\n\n    # we can be more explicit about the current package only with \"missing:protobuf/*\"\n    c.run(\"remove * -c\")  # make sure that previous binary is removed\n    c.run(\"create . -s:b build_type=Release -s:h build_type=Debug --build-test=missing:protobuf/*\")\n    c.assert_listed_binary({\"protobuf/0.1\": (\"9e186f6d94c008b544af1569d1a6368d8339efc5\", \"Build\")})\n    # it used to fail, now it works and builds the test_package \"tools_requires\" in Release\n    c.assert_listed_binary({\"protobuf/0.1\": (\"efa83b160a55b033c4ea706ddb980cd708e3ba1b\", \"Build\")},\n                           build=True, test_package=True)\n\n\ndef test_python_requires_json_format():\n    \"\"\"Check python requires does not crash when calling conan create . --format=json\n    See https://github.com/conan-io/conan/issues/14577\"\"\"\n    c = TestClient()\n    c.save({\"conanfile.py\": GenConanfile(\"pyreq\", \"1.0\")\n           .with_package_type(\"python-require\")})\n    c.run(\"create . --format=json\", redirect_stdout=\"output.json\")\n    data = json.loads(load(os.path.join(c.current_folder, \"output.json\")))\n    # There's a graph and the python requires is there\n    assert len(data[\"graph\"][\"nodes\"][\"0\"][\"python_requires\"]) == 1\n\n\ndef test_python_requires_with_test_package():\n    c = TestClient()\n    # Code comes from the docs\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n\n    def mynumber():\n        return 42\n\n    class PyReq(ConanFile):\n        name = \"pyreq\"\n        version = \"1.0\"\n        package_type = \"python-require\"\n    \"\"\")\n    test_conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n\n    class Tool(ConanFile):\n        def test(self):\n            pyreq = self.python_requires[\"pyreq\"].module\n            mynumber = pyreq.mynumber()\n            self.output.info(\"{}!!!\".format(mynumber))\n    \"\"\")\n    c.save({\"conanfile.py\": conanfile, \"test_package/conanfile.py\": test_conanfile})\n    c.run(\"create .\")\n    # Ensure that creating a deps graph does not break the testing\n    assert \"pyreq/1.0 (test package): 42!!!\" in c.out\n\n\ndef test_create_test_package_only_build():\n    c = TestClient()\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\"),\n            \"test_package/conanfile.py\": GenConanfile().with_test(\"self.output.info('TEST1!!!')\"),\n            \"test_package2/conanfile.py\": GenConanfile().with_test(\"self.output.info('TEST2!!!')\")})\n    # As it doesn't exist, it builds and test it\n    c.run(\"create . -tm\")\n    assert \"Testing the package\" in c.out\n    assert \"TEST1!!!\" in c.out\n    # this will not create the binary, so it won't test it\n    c.run(\"create . --build=missing --test-missing\")\n    assert \"Testing the package\" not in c.out\n    assert \"TEST\" not in c.out\n    c.run(\"create . -tf=test_package2 -tm\")\n    assert \"Testing the package\" in c.out\n    assert \"TEST2!!!\" in c.out\n    assert \"TEST1!!!\" not in c.out\n    c.run(\"create . -tf=test_package2 --build=missing --test-missing\")\n    assert \"Testing the package\" not in c.out\n    assert \"TEST2!!!\" not in c.out\n    assert \"TEST1!!!\" not in c.out\n\n    # error\n    c.run(\"create . -tm -tf=\", assert_error=True)\n    assert '--test-folder=\"\" is incompatible with --test-missing' in c.out\n\n\ndef test_create_test_package_only_build_python_require():\n    c = TestClient()\n    test = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Tool(ConanFile):\n            python_requires = \"tested_reference_str\"\n            def test(self):\n                self.output.info(\"TEST!!!!\")\n        \"\"\")\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_package_type(\"python-require\"),\n            \"test_package/conanfile.py\": test})\n    c.run(\"create .\")\n    assert \"Testing the package\" in c.out\n    assert \"pkg/0.1 (test package): TEST!!!\" in c.out\n    c.run(\"create . -tm\")\n    assert \"Testing the package\" in c.out\n    assert \"pkg/0.1 (test package): TEST!!!\" in c.out\n    c.run(\"create . -tm --build=missing\")\n    assert \"Testing the package\" in c.out\n    assert \"pkg/0.1 (test package): TEST!!!\" in c.out\n\n\n@pytest.mark.parametrize(\"command\", [\"create\", \"install\"])\n@pytest.mark.parametrize(\"out_file\", [False, True])\ndef test_create_build_fail_generate_outfile(command, out_file):\n    c = TestClient()\n    c.save({\"pkga/conanfile.py\": GenConanfile(\"pkga\", \"0.1\"),\n            \"pkgb/conanfile.py\": GenConanfile(\"pkgb\", \"0.1\").with_requires(\"pkga/0.1\"),\n            \"pkgc/conanfile.py\": GenConanfile(\"pkgc\", \"0.1\")\n           .with_requires(\"pkgb/0.1\")\n           .with_package(\"raise Exception('myerror')\"),\n            \"pkgd/conanfile.py\": GenConanfile(\"pkgd\", \"0.1\").with_requires(\"pkgc/0.1\")\n                                                            .with_settings(\"build_type\")\n                                                            .with_generator(\"CMakeDeps\"),\n            })\n    c.run(\"export pkga\")\n    c.run(\"export pkgb\")\n    c.run(\"export pkgc\")\n    if out_file:\n        error = c.run(f\"{command} pkgd --build=missing --format=json --out-file=graph.json\",\n                      assert_error=True)\n    else:\n        error = c.run(f\"{command} pkgd --build=missing --format=json\", assert_error=True,\n                      redirect_stdout=\"graph.json\")\n    assert error == ERROR_GENERAL\n    assert \"pkgc/0.1: Error in package() method, line 8\" in c.out\n    graph = json.loads(c.load(\"graph.json\"))\n    nodeid = \"1\" if command == \"create\" else \"0\"\n    assert graph[\"graph\"][\"nodes\"][nodeid][\"name\"] == \"pkgd\"\n\n    # We can construct a package list from it\n    c.run(\"list -g=graph.json --graph-binaries=Build --format=json\")\n    pkglist = json.loads(c.stdout)\n    # not built packages don't have revisions\n    rrev = pkglist[\"Local Cache\"][\"pkgc/0.1\"][\"revisions\"][\"b7f74fa20b19f1daac67db49318b7197\"]\n    assert \"revisions\" not in rrev[\"packages\"][\"4a8d7d78a454700be1ab74b4a77fd7f36a44d122\"]\n    # built packages do have package revisions\n    rrev = pkglist[\"Local Cache\"][\"pkgb/0.1\"][\"revisions\"][\"5b1ae5e3c1f718c0fd90d4dd8d9b57fb\"]\n    assert \"revisions\" in rrev[\"packages\"][\"47a5f20ec8fb480e1c5794462089b01a3548fdc5\"]\n    rrev = pkglist[\"Local Cache\"][\"pkga/0.1\"][\"revisions\"][\"57ece23aeb368b634896004ad579767a\"]\n    assert \"revisions\" in rrev[\"packages\"][\"da39a3ee5e6b4b0d3255bfef95601890afd80709\"]\n"
  },
  {
    "path": "test/integration/command/custom_commands_test.py",
    "content": "import json\nimport os\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient\nfrom conan.test.utils.env import environment_update\n\n\nclass TestCustomCommandsErrors:\n\n    def test_import_error_custom_command(self):\n        mycommand = textwrap.dedent(\"\"\"\n            import this_doesnt_exist\n            \"\"\")\n\n        client = TestClient()\n        command_file_path = os.path.join(client.cache_folder, 'extensions',\n                                         'commands', 'cmd_mycommand.py')\n        client.save({f\"{command_file_path}\": mycommand})\n        # Call to any other command, it will fail loading the custom command\n        client.run(\"list *\")\n        assert \"ERROR: Error loading custom command 'cmd_mycommand.py': \" \\\n               \"No module named 'this_doesnt_exist'\" in client.out\n        # But it won't break the whole conan and you can still use the rest of it\n        client.run(\"config home\")\n        assert client.cache_folder in client.out\n\n    def test_import_error_custom_command_subfolder(self):\n        \"\"\"\n        used to break, this is handled differently in conan\n        \"\"\"\n        mycommand = textwrap.dedent(\"\"\"\n            import this_doesnt_exist\n            \"\"\")\n\n        client = TestClient()\n        command_file_path = os.path.join(client.cache_folder, 'extensions',\n                                         'commands', 'mycompany', 'cmd_mycommand.py')\n        client.save({f\"{command_file_path}\": mycommand})\n        # Call to any other command, it will fail loading the custom command,\n        client.run(\"list *\")\n        assert \"ERROR: Error loading custom command mycompany.cmd_mycommand\" in client.out\n        # But it won't break the whole conan and you can still use the rest of it\n        client.run(\"config home\")\n        assert client.cache_folder in client.out\n\n    def test_import_error_bad_name(self):\n        mycommand = textwrap.dedent(\"\"\"\n            from conan.cli.command import conan_command, conan_subcommand\n            @conan_command(group=\"custom commands\")\n            def mycommand(conan_api, parser, *args, **kwargs):\n                \\\"\"\" custom \\\"\"\"\n            @conan_subcommand()\n            def mysubcmd(conan_api, parser, *args, **kwargs):\n                \\\"\"\" mysubcmd \\\"\"\"\n            \"\"\")\n\n        c = TestClient()\n        c.save_home({\"extensions/commands/cmd_mycommand.py\": mycommand})\n        # Call to any other command, it will fail loading the custom command\n        c.run(\"list *\")\n        assert \"The name for the subcommand method should begin with the main command name\" in c.out\n\n\nclass TestCustomCommands:\n    def test_simple_custom_command(self):\n        mycommand = textwrap.dedent(\"\"\"\n            import json\n            import os\n\n            from conan.cli.command import conan_command\n            from conan.api.output import cli_out_write\n\n            def output_mycommand_cli(info):\n                cli_out_write(f\"Conan cache folder is: {info.get('cache_folder')}\")\n\n            def output_mycommand_json(info):\n                cli_out_write(json.dumps(info))\n\n            @conan_command(group=\"custom commands\",\n                           formatters={\"cli\": output_mycommand_cli,\n                                       \"json\": output_mycommand_json})\n            def mycommand(conan_api, parser, *args, **kwargs):\n                \\\"\"\"\n                this is my custom command, it will print the location of the cache folder\n                \\\"\"\"\n                info = {\"cache_folder\": os.path.basename(conan_api.cache_folder)}\n                return info\n            \"\"\")\n\n        client = TestClient()\n        command_file_path = os.path.join(client.cache_folder, 'extensions',\n                                         'commands', 'cmd_mycommand.py')\n        client.save({f\"{command_file_path}\": mycommand})\n        client.run(\"mycommand -f cli\")\n        foldername = os.path.basename(client.cache_folder)\n        assert f'Conan cache folder is: {foldername}' in client.out\n        client.run(\"mycommand -f json\")\n        assert f'{{\"cache_folder\": \"{foldername}\"}}' in client.out\n\n    def test_command_layer(self):\n        myhello = textwrap.dedent(\"\"\"\n            from conan.api.output import cli_out_write\n            from conan.cli.command import conan_command\n\n            @conan_command(group=\"custom commands\")\n            def hello(conan_api, parser, *args, **kwargs):\n                '''\n                My Hello doc\n                '''\n                cli_out_write(\"Hello {}!\")\n            \"\"\")\n        mybye = textwrap.dedent(\"\"\"\n            from conan.api.output import cli_out_write\n            from conan.cli.command import conan_command, conan_subcommand\n\n            @conan_command(group=\"custom commands\")\n            def bye(conan_api, parser, *args, **kwargs):\n                '''\n                My Bye doc\n                '''\n\n            @conan_subcommand()\n            def bye_say(conan_api, parser, *args, **kwargs):\n                '''\n                My bye say doc\n                '''\n                cli_out_write(\"Bye!\")\n            \"\"\")\n\n        client = TestClient()\n        layer_path = os.path.join(client.cache_folder, 'extensions', 'commands')\n        client.save({os.path.join(layer_path, 'cmd_hello.py'): myhello.format(\"world\"),\n                     os.path.join(layer_path, \"greet\", 'cmd_hello.py'): myhello.format(\"moon\"),\n                     os.path.join(layer_path, \"greet\", 'cmd_bye.py'): mybye})\n        # Test that the root \"hello\" without subfolder still works and no conflict\n        client.run(\"hello\")\n        assert \"Hello world!\" in client.out\n        client.run(\"greet:hello\")\n        assert \"Hello moon!\" in client.out\n        client.run(\"greet:bye say\")\n        assert \"Bye!\" in client.out\n        client.run(\"-h\")\n        assert \"greet:bye\" in client.out\n\n        # Ensure the prog has the full command name\n        client.run(\"hello -h\")\n        assert \"conan hello\" in client.out\n        client.run(\"greet:bye -h\")\n        assert \"conan greet:bye\" in client.out\n        client.run(\"greet:bye say -h\")\n        assert \"conan greet:bye say\" in client.out\n\n    def test_custom_command_with_subcommands(self):\n        complex_command = textwrap.dedent(\"\"\"\n            import json\n\n            from conan.cli.command import conan_command, conan_subcommand\n            from conan.api.output import cli_out_write\n\n            def output_cli(info):\n                cli_out_write(f\"{info.get('argument1')}\")\n\n            def output_json(info):\n                 cli_out_write(json.dumps(info))\n\n            @conan_subcommand(formatters={\"cli\": output_cli, \"json\": output_json})\n            def complex_sub1(conan_api, parser, subparser, *args):\n                \\\"\"\"\n                sub1 subcommand\n                \\\"\"\"\n                subparser.add_argument(\"argument1\", help=\"This is argument number 1\")\n                args = parser.parse_args(*args)\n                info = {\"argument1\": args.argument1}\n                return info\n\n            @conan_command()\n            def complex(conan_api, parser, *args, **kwargs):\n                \\\"\"\"\n                this is a command with subcommands\n                \\\"\"\"\n            \"\"\")\n\n        client = TestClient()\n        command_file_path = os.path.join(client.cache_folder, 'extensions',\n                                         'commands', 'cmd_complex.py')\n        client.save({f\"{command_file_path}\": complex_command})\n        client.run(\"complex sub1 myargument -f=cli\")\n        assert \"myargument\" in client.out\n        client.run(\"complex sub1 myargument -f json\")\n        assert f'{{\"argument1\": \"myargument\"}}' in client.out\n\n    def test_custom_command_with_subcommands_with_underscore(self):\n        complex_command = textwrap.dedent(\"\"\"\n            import json\n\n            from conan.cli.command import conan_command, conan_subcommand\n            from conan.api.output import cli_out_write\n\n            @conan_command()\n            def command_with_underscores(conan_api, parser, *args, **kwargs):\n                \\\"\"\"\n                this is a command with subcommands\n                \\\"\"\"\n\n            @conan_subcommand()\n            def command_with_underscores_subcommand_with_underscores_too(conan_api, parser, subparser, *args):\n                \\\"\"\"\n                sub1 subcommand\n                \\\"\"\"\n                subparser.add_argument(\"argument1\", help=\"This is argument number 1\")\n                args = parser.parse_args(*args)\n                cli_out_write(args.argument1)\n            \"\"\")\n\n        client = TestClient()\n        command_file_path = os.path.join(client.cache_folder, 'extensions',\n                                         'commands', 'cmd_command_with_underscores.py')\n        client.save({f\"{command_file_path}\": complex_command})\n        client.run(\"command-with-underscores subcommand-with-underscores-too myargument\")\n        assert \"myargument\" in client.out\n\n    def test_overwrite_builtin_command(self):\n        complex_command = textwrap.dedent(\"\"\"\n            import json\n\n            from conan.cli.command import conan_command\n            from conan.api.output import cli_out_write\n\n            @conan_command()\n            def install(conan_api, parser, *args, **kwargs):\n                \\\"\"\"\n                this is a command with subcommands\n                \\\"\"\"\n                cli_out_write(\"Hello world\")\n            \"\"\")\n\n        client = TestClient()\n        command_file_path = os.path.join(client.cache_folder, 'extensions',\n                                         'commands', 'myteam', 'cmd_install.py')\n        client.save({f\"{command_file_path}\": complex_command})\n        command_file_path = os.path.join(client.cache_folder, 'extensions',\n                                         'commands', 'cmd_install.py')\n        client.save({f\"{command_file_path}\": complex_command})\n        client.run(\"myteam:install\")\n        assert \"Hello world\" in client.out\n        client.run(\"install\")\n        assert \"Hello world\" in client.out\n\n    def test_custom_command_local_import(self):\n        mycode = textwrap.dedent(\"\"\"\n            from conan.api.output import cli_out_write\n\n\n            def write_output(folder):\n                cli_out_write(f\"Conan cache folder from cmd_mycode: {folder}\")\n        \"\"\")\n        mycommand = textwrap.dedent(\"\"\"\n            import os\n\n            from conan.cli.command import conan_command\n            from mycode import write_output\n\n\n            @conan_command(group=\"custom commands\")\n            def mycommand(conan_api, parser, *args, **kwargs):\n                \\\"\"\"\n                this is my custom command, it will print the location of the cache folder\n                \\\"\"\"\n                folder = os.path.basename(conan_api.cache_folder)\n                write_output(folder)\n            \"\"\")\n\n        client = TestClient()\n        mycommand_file_path = os.path.join(client.cache_folder, 'extensions',\n                                           'commands', 'danimtb', 'cmd_mycommand.py')\n        mycode_file_path = os.path.join(client.cache_folder, 'extensions',\n                                        'commands', 'danimtb', 'mycode.py')\n        client.save({\n            mycode_file_path: mycode,\n            mycommand_file_path: mycommand\n        })\n        client.run(\"danimtb:mycommand\")\n        foldername = os.path.basename(client.cache_folder)\n        assert f'Conan cache folder from cmd_mycode: {foldername}' in client.out\n\n    def test_custom_command_from_other_location(self):\n        \"\"\"\n        Tests that setting developer env variable ``_CONAN_INTERNAL_CUSTOM_COMMANDS_PATH``\n        will append that folder to the Conan custom command default location.\n        \"\"\"\n        myhello = textwrap.dedent(\"\"\"\n            from conan.api.output import cli_out_write\n            from conan.cli.command import conan_command\n\n            @conan_command(group=\"custom commands\")\n            def hello(conan_api, parser, *args, **kwargs):\n                '''\n                My Hello doc\n                '''\n                cli_out_write(\"Hello {}!\")\n            \"\"\")\n\n        client = TestClient()\n        my_local_layer_path = temp_folder(path_with_spaces=False)\n        layer_path = os.path.join(client.cache_folder, 'extensions', 'commands')\n        client.save({os.path.join(layer_path, 'cmd_hello.py'): myhello.format(\"world\")})\n        client.save({\"cmd_hello.py\": myhello.format(\"Overridden\")}, path=my_local_layer_path)\n        with environment_update({\"_CONAN_INTERNAL_CUSTOM_COMMANDS_PATH\": my_local_layer_path}):\n            client.run(\"hello\")\n            # Local commands have preference over Conan custom ones if they collide\n            assert \"Hello Overridden!\" in client.out\n        # Without the variable it only loads the default custom commands location\n        client.run(\"hello\")\n        assert \"Hello world!\" in client.out\n\n\nclass TestCommandAPI:\n    @pytest.mark.parametrize(\"argument\", ['[\"list\", \"pkg*\", \"-c\"]',\n                                          '\"list pkg* -c\"'])\n    def test_command_reuse_interface(self, argument):\n        mycommand = textwrap.dedent(f\"\"\"\n            import json\n            from conan.cli.command import conan_command\n            from conan.api.output import cli_out_write\n\n            @conan_command(group=\"custom commands\")\n            def mycommand(conan_api, parser, *args, **kwargs):\n                \\\"\"\" mycommand help \\\"\"\"\n                result = conan_api.command.run({argument})\n                cli_out_write(json.dumps(result[\"results\"], indent=2))\n            \"\"\")\n\n        c = TestClient()\n        command_file_path = os.path.join(c.cache_folder, 'extensions',\n                                         'commands', 'cmd_mycommand.py')\n        c.save({f\"{command_file_path}\": mycommand})\n        c.run(\"mycommand\", redirect_stdout=\"file.json\")\n        assert json.loads(c.load(\"file.json\")) == {\"Local Cache\": {}}\n\n    def test_command_reuse_other_custom(self):\n        cmd1 = textwrap.dedent(f\"\"\"\n            from conan.cli.command import conan_command\n            from conan.api.output import cli_out_write\n\n            @conan_command(group=\"custom commands\")\n            def mycmd1(conan_api, parser, *args, **kwargs):\n                \\\"\"\"mycommand help \\\"\"\"\n                # result = conan_api.command.run(\"\")\n                cli_out_write(\"MYCMD1!!!!!\")\n                conan_api.command.run(\"mycmd2\")\n            \"\"\")\n        cmd2 = textwrap.dedent(f\"\"\"\n            from conan.cli.command import conan_command\n            from conan.api.output import cli_out_write\n\n            @conan_command(group=\"custom commands\")\n            def mycmd2(conan_api, parser, *args, **kwargs):\n                \\\"\"\"mycommand help\\\"\"\"\n                cli_out_write(\"MYCMD2!!!!!\")\n            \"\"\")\n\n        c = TestClient()\n        cmds = os.path.join(c.cache_folder, 'extensions', 'commands')\n        c.save({os.path.join(cmds, \"cmd_mycmd1.py\"): cmd1,\n                os.path.join(cmds, \"cmd_mycmd2.py\"): cmd2})\n        c.run(\"mycmd1\")\n        assert \"MYCMD1!!!!!\" in c.out\n        assert \"MYCMD2!!!!!\" in c.out\n\n    def test_command_verbosity_leak(self):\n        mycommand = textwrap.dedent(f\"\"\"\n                    import json\n                    from conan.cli.command import conan_command\n                    from conan.api.output import ConanOutput\n\n                    @conan_command(group=\"custom commands\")\n                    def mycommand(conan_api, parser, *args, **kwargs):\n                        \\\"\"\" mycommand help \\\"\"\"\n                        parser.add_argument(\"foo\", help=\"foo\")\n                        args = parser.parse_args(*args)\n\n                        out = ConanOutput()\n                        out.title(\"This is my first title\")\n                        conan_api.command.run(\"config home\")\n                        out.title(\"This is my second title\")\n                    \"\"\")\n\n        c = TestClient()\n        command_file_path = os.path.join(c.cache_folder, 'extensions',\n                                         'commands', 'cmd_mycommand.py')\n        c.save({f\"{command_file_path}\": mycommand})\n        c.run(\"mycommand foo -vquiet\")\n        assert \"This is my first title\" not in c.out\n        assert \"This is my second title\" not in c.out\n\n    def test_command_reuse_interface_create(self):\n        mycommand = textwrap.dedent(\"\"\"\n            import json\n            from conan.cli.command import conan_command\n            from conan.cli.formatters.graph import format_graph_json\n\n            @conan_command(group=\"custom commands\", formatters={\"json\": format_graph_json})\n            def mycommand(conan_api, parser, *args, **kwargs):\n                \\\"\"\" mycommand help \\\"\"\"\n                result = conan_api.command.run([\"create\", \".\", \"--version=1.0.0\"])\n                return result\n            \"\"\")\n\n        c = TestClient()\n        command_file_path = os.path.join(c.cache_folder, 'extensions',\n                                         'commands', 'cmd_mycommand.py')\n        c.save({f\"{command_file_path}\": mycommand,\n                \"conanfile.py\": GenConanfile(\"mylib\")})\n        c.run(\"mycommand --format=json\", redirect_stdout=\"file.json\")\n        create_output = json.loads(c.load(\"file.json\"))\n        assert create_output['graph']['nodes']['1']['label'] == \"mylib/1.0.0\"\n\n    def test_subcommand_reuse_interface(self):\n        mycommand = textwrap.dedent(\"\"\"\n            import json\n            from conan.cli.command import conan_command\n            from conan.api.output import cli_out_write\n\n            @conan_command(group=\"custom commands\")\n            def mycommand(conan_api, parser, *args, **kwargs):\n                \\\"\"\" mycommand help \\\"\"\"\n                parser.add_argument(\"remote\", help=\"remote\")\n                parser.add_argument(\"url\", help=\"url\")\n                args = parser.parse_args(*args)\n                conan_api.command.run([\"remote\", \"add\", args.remote, args.url])\n                result = conan_api.command.run([\"remote\", \"list\"])\n                result = {r.name: r.url for r in result}\n                cli_out_write(json.dumps(result, indent=2))\n            \"\"\")\n\n        c = TestClient()\n        command_file_path = os.path.join(c.cache_folder, 'extensions',\n                                         'commands', 'cmd_mycommand.py')\n        c.save({f\"{command_file_path}\": mycommand})\n        c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n        c.run(\"export .\")\n        c.run(\"mycommand myremote myurl\")\n        assert json.loads(c.stdout) == {\"myremote\": \"myurl\"}\n\n\nclass TestCommandsRemoteCaching:\n    def test_remotes_cache(self):\n        complex_command = textwrap.dedent(\"\"\"\n            import json\n            from conan.cli.command import conan_command\n            from conan.api.output import ConanOutput\n\n            @conan_command()\n            def mycache(conan_api, parser, *args, **kwargs):\n                \\\"\"\" this is a command with subcommands \\\"\"\"\n\n                remotes = conan_api.remotes.list()\n                host = conan_api.profiles.get_profile([\"default\"])\n                build = conan_api.profiles.get_profile([\"default\"])\n\n                deps_graph = conan_api.graph.load_graph_requires([\"pkg/0.1\"], None, host, build,\n                                                                 None, remotes, None, None)\n                conan_api.graph.analyze_binaries(deps_graph, None, remotes=remotes)\n\n                # SECOND RUN!!!\n                # This will break if the caching is not working\n                remotes[0].url = \"broken\"\n                deps_graph = conan_api.graph.load_graph_requires([\"pkg/0.1\"], None, host, build,\n                                                                 None, remotes, None, None)\n                conan_api.graph.analyze_binaries(deps_graph, None, remotes=remotes)\n\n                # Now invalidate the cache and see how it breaks\n                try:\n                    remotes[0].invalidate_cache()\n                    deps_graph = conan_api.graph.load_graph_requires([\"pkg/0.1\"], None, host, build,\n                                                                     None, remotes, None, None)\n                    conan_api.graph.analyze_binaries(deps_graph, None, remotes=remotes)\n                except Exception as e:\n                    ConanOutput().warning(f\"Cache invalidated, as expected: {e}\")\n            \"\"\")\n\n        c = TestClient(default_server_user=True)\n        c.save_home({\"extensions/commands/cmd_mycache.py\": complex_command})\n\n        c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\"),\n                \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_require(\"dep/0.1\")})\n        c.run(\"create dep\")\n        c.run(\"create pkg\")\n        c.run(\"upload * -r=default -c\")\n        c.run(\"remove * -c\")\n        c.run(\"mycache\")\n        # Does not break unexpectedly, caching is working\n        assert \"WARN: Cache invalidated, as expected: Invalid URL 'broken\" in c.out\n\n\ndef test_custom_command_settings_access():\n    tc = TestClient()\n    mycommand = textwrap.dedent(\"\"\"\n        from conan.cli.command import conan_command\n        from conan.api.output import ConanOutput\n\n        @conan_command(group=\"custom commands\")\n        def mycommand(conan_api, parser, *args, **kwargs):\n            \\\"\"\"\n            test\n            \\\"\"\"\n            settings = conan_api.config.settings_yml\n            ConanOutput().info(f\"settings.fields: {settings.fields}\")\n            ConanOutput().info(f\"settings.possible_values(): {settings.possible_values()}\")\n            ConanOutput().info(f\"settings.compiler: {settings.compiler}\")\n            ConanOutput().info(f\"settings.compiler.possible_values(): {settings.compiler.possible_values()}\")\n        \"\"\")\n    command_file_path = os.path.join('extensions', 'commands', 'cmd_mycommand.py')\n    tc.save_home({f\"{command_file_path}\": mycommand})\n    tc.run(\"mycommand\")\n    assert \"settings.fields: ['arch', 'build_type', 'compiler', 'os']\" in tc.out\n    # No values here, but as it does not fail, the interface is working fine\n    assert \"settings.compiler: None\" in tc.out\n"
  },
  {
    "path": "test/integration/command/download/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/command/download/download_parallel_test.py",
    "content": "from conan.test.utils.tools import GenConanfile, TestClient\n\n\ndef test_basic_parallel_download():\n    client = TestClient(light=True, default_server_user=True)\n    threads = 2\n    packages = 2\n    per_package = 4\n    client.save_home({\"global.conf\": f\"core.download:parallel={threads}\"})\n    client.save({\"conanfile.py\": GenConanfile().with_option(\"myoption\", '[\"ANY\"]')})\n\n    package_ids = []\n    for i in range(packages):\n        for n in range(per_package):\n            client.run(f\"create . --name=pkg{i} --version=0.1 --user=user --channel=testing -o pkg{i}/*:myoption={n}\")\n            package_id = client.created_package_id(f\"pkg{i}/0.1@user/testing\")\n            package_ids.append((i, package_id))\n    client.run(\"upload * --confirm -r default\")\n    client.run(\"remove * -c\")\n\n    # Lets download the packages\n    client.run(\"download pkg*/0.1@user/testing#*:* -r default\")\n    assert f\"Downloading with {threads} parallel threads\" in client.out\n    for i, package_id in package_ids:\n        assert f\"pkg{i}/0.1@user/testing: Package installed {package_id}\" in client.out\n"
  },
  {
    "path": "test/integration/command/download/download_selected_packages_test.py",
    "content": "import os\n\nimport pytest\n\nfrom conan.api.model import RecipeReference\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import load\n\n\n@pytest.fixture(scope=\"module\")\ndef setup():\n    client = TestClient(default_server_user=True)\n    conanfile = GenConanfile().with_settings(\"os\", \"arch\").with_package_file(\"hellohello0.h\", \"x\")\n    client.save({\"conanfile.py\": conanfile})\n    ref = RecipeReference.loads(\"hello0/0.1@lasote/stable\")\n    client.run(\"export . --name=hello0 --version=0.1 --user=lasote --channel=stable\")\n    client.run(\"install --requires={} -s os=Windows --build missing\".format(ref))\n    client.run(\"install --requires={} -s os=Linux --build missing\".format(ref))\n    client.run(\"install --requires={} -s os=Linux -s arch=x86 --build missing\".format(ref))\n    client.run(\"upload {} -r default\".format(ref))\n    latest_rrev = client.cache.get_latest_recipe_revision(ref)\n    packages = client.cache.get_package_references(latest_rrev)\n    package_ids = [package.package_id for package in packages]\n    return client, ref, package_ids, str(conanfile)\n\n\n@pytest.mark.artifactory_ready\ndef test_download_recipe_twice(setup):\n    client, ref, package_ids, conanfile = setup\n    new_client = TestClient(servers=client.servers, inputs=[\"admin\", \"password\"])\n    new_client.run(\"download hello0/0.1@lasote/stable -r default\")\n    ref = RecipeReference.loads(\"hello0/0.1@lasote/stable\")\n\n    conanfile_path = new_client.get_latest_ref_layout(ref).conanfile()\n    assert conanfile == load(conanfile_path)\n\n    new_client.run(\"download hello0/0.1@lasote/stable -r default\")\n    assert conanfile == load(conanfile_path)\n\n    new_client.run(\"download hello0/0.1@lasote/stable -r default\")\n    assert conanfile == load(conanfile_path)\n\n\n@pytest.mark.artifactory_ready\ndef test_download_packages_twice(setup):\n    client, ref, package_ids, _ = setup\n    new_client = TestClient(servers=client.servers, inputs=[\"admin\", \"password\"])\n    expected_header_contents = \"x\"\n\n    new_client.run(\"download hello0/0.1@lasote/stable:* -r default\")\n    pref = client.get_latest_package_reference(\"hello0/0.1@lasote/stable\", package_id=package_ids[0])\n    package_folder = new_client.get_latest_pkg_layout(pref).package()\n    got_header = load(os.path.join(package_folder, \"hellohello0.h\"))\n    assert expected_header_contents == got_header\n\n    new_client.run(\"download hello0/0.1@lasote/stable:* -r default\")\n    got_header = load(os.path.join(package_folder, \"hellohello0.h\"))\n    assert expected_header_contents == got_header\n\n    new_client.run(\"download hello0/0.1@lasote/stable:* -r default\")\n    got_header = load(os.path.join(package_folder, \"hellohello0.h\"))\n    assert expected_header_contents == got_header\n"
  },
  {
    "path": "test/integration/command/download/download_test.py",
    "content": "import os\nimport textwrap\nfrom collections import OrderedDict\nfrom unittest import mock\n\nfrom conan.api.model import RecipeReference\nfrom conan.test.utils.tools import TestClient, TestServer, NO_SETTINGS_PACKAGE_ID, GenConanfile\nfrom conan.internal.util.files import load\n\n\ndef test_download_with_sources():\n    client = TestClient(default_server_user=True)\n    client.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_exports_sources(\"*\"),\n                 \"file.h\": \"myfile.h\",\n                 \"otherfile.cpp\": \"C++code\"})\n    client.run(\"export . --user=lasote --channel=stable\")\n\n    ref = RecipeReference.loads(\"pkg/0.1@lasote/stable\")\n    client.run(\"upload pkg/0.1@lasote/stable -r default\")\n    client.run(\"remove pkg/0.1@lasote/stable -c\")\n\n    client.run(\"download pkg/0.1@lasote/stable -r default\")\n    assert \"Downloading 'pkg/0.1@lasote/stable' sources\" in client.out\n    source = client.get_latest_ref_layout(ref).export_sources()\n    assert \"myfile.h\" == load(os.path.join(source, \"file.h\"))\n    assert \"C++code\" == load(os.path.join(source, \"otherfile.cpp\"))\n\n\ndef test_no_user_channel():\n    # https://github.com/conan-io/conan/issues/6009\n    client = TestClient(default_server_user=True)\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"create . --name=pkg --version=1.0\")\n    client.run(\"upload * --confirm -r default\")\n    client.run(\"remove * -c\")\n\n    client.run(\"download pkg/1.0:{} -r default\".format(NO_SETTINGS_PACKAGE_ID))\n    assert f\"Downloading package 'pkg/1.0#4d670581ccb765839f2239cc8dff8fbd:{NO_SETTINGS_PACKAGE_ID}\" in client.out\n\n    # All\n    client.run(\"remove * -c\")\n    client.run(\"download pkg/1.0#*:* -r default\")\n    assert f\"Downloading package 'pkg/1.0#4d670581ccb765839f2239cc8dff8fbd:{NO_SETTINGS_PACKAGE_ID}\" in client.out\n\n\ndef test_download_with_python_requires():\n    \"\"\" In the past,\n    when having a python_require in a different repo, it cannot be ``conan download``\n    as the download runs from a single repo.\n\n    Now, from https://github.com/conan-io/conan/issues/14260, \"conan download\" doesn't\n    really need to load conanfile, so it doesn't fail because of this.\n    \"\"\"\n    # https://github.com/conan-io/conan/issues/9548\n    servers = OrderedDict([(\"tools\", TestServer()),\n                           (\"pkgs\", TestServer())])\n    c = TestClient(servers=servers, inputs=[\"admin\", \"password\", \"admin\", \"password\"])\n\n    c.save({\"tool/conanfile.py\": GenConanfile(\"tool\", \"0.1\"),\n            \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_python_requires(\"tool/0.1\")})\n    c.run(\"export tool\")\n    c.run(\"create pkg\")\n    c.run(\"upload tool* -r tools -c\")\n    c.run(\"upload pkg* -r pkgs -c\")\n    c.run(\"remove * -c\")\n\n    c.run(\"install --requires=pkg/0.1 -r pkgs -r tools\")\n    assert \"Downloading\" in c.out\n    c.run(\"remove * -c\")\n\n    c.run(\"download pkg/0.1 -r pkgs\")\n    assert \"pkg/0.1: Downloaded package revision\" in c.out\n\n\ndef test_download_verify_ssl_conf():\n    client = TestClient()\n\n    client.save({\"conanfile.py\": textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import download\n\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"1.0\"\n\n            def source(self):\n                download(self, \"http://verify.true\", \"\", verify=True)\n                download(self, \"http://verify.false\", \"\", verify=False)\n        \"\"\")})\n\n    did_verify = {}\n\n    def custom_download(this, url, filepath, *args, **kwargs):\n        did_verify[url] = args[2]\n\n    with mock.patch(\"conan.internal.rest.file_downloader.FileDownloader.download\",\n                    custom_download):\n        client.run(\"create . -c tools.files.download:verify=True\")\n        assert did_verify[\"http://verify.true\"]\n        assert did_verify[\"http://verify.false\"]\n\n        did_verify.clear()\n        client.run(\"remove pkg/1.0 -c\")\n\n        client.run(\"create . -c tools.files.download:verify=False\")\n        assert not did_verify[\"http://verify.true\"]\n        assert not did_verify[\"http://verify.false\"]\n\n        did_verify.clear()\n        client.run(\"remove pkg/1.0 -c\")\n\n        client.run(\"create .\")\n        assert did_verify[\"http://verify.true\"]\n        assert not did_verify[\"http://verify.false\"]\n\n\ndef test_download_list_only_recipe():\n    c = TestClient(default_server_user=True)\n    c.save({\"conanfile.py\": GenConanfile(\"liba\", \"0.1\")})\n    c.run(\"create .\")\n    c.run(\"upload * -r=default -c\")\n    c.run(\"remove * -c\")\n    c.run(\"list *:* -r=default --format=json\", redirect_stdout=\"pkgs.json\")\n    c.run(\"download --list=pkgs.json --only-recipe -r=default\")\n    assert \"packages\" not in c.out\n"
  },
  {
    "path": "test/integration/command/download/test_download_patterns.py",
    "content": "import re\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\nfrom conan.test.utils.env import environment_update\n\n\n@pytest.mark.artifactory_ready\nclass TestDownloadPatterns:\n    # The fixture is very similar from TestUploadPatterns, but not worth extracting\n    @pytest.fixture(scope=\"class\")\n    def client(self):\n        \"\"\" create a few packages, with several recipe revisions, several pids, several prevs\n        \"\"\"\n        client = TestClient(default_server_user=True)\n\n        for pkg in (\"pkga\", \"pkgb\"):\n            for version in (\"1.0\", \"1.1\"):\n                for rrev in (\"rev1\", \"rev2\"):\n                    client.save({\"conanfile.py\": GenConanfile().with_settings(\"os\")\n                                .with_class_attribute(f\"potato='{rrev}'\")\n                                .with_package_file(\"file\", env_var=\"MYVAR\")})\n                    for the_os in (\"Windows\", \"Linux\"):\n                        for prev in (\"prev1\", \"prev2\"):\n                            with environment_update({\"MYVAR\": prev}):\n                                client.run(f\"create . --name={pkg} --version={version} \"\n                                           f\"-s os={the_os}\")\n        client.run(\"upload *#*:*#* -r=default -c\")\n        return client\n\n    @staticmethod\n    def assert_downloaded(pattern, result, client, only_recipe=False, query=None):\n        def ref_map(r):\n            rev1 = \"ad55a66b62acb63ffa99ea9b75c16b99\"\n            rev2 = \"127fb537a658ad6a57153a038960dc53\"\n            pid1 = \"ebec3dc6d7f6b907b3ada0c3d3cdc83613a2b715\"\n            pid2 = \"9a4eb3c8701508aa9458b1a73d0633783ecc2270\"\n            if \"Linux\" in r:\n                prev1 = \"7ce684c6109943482b9174dd089e717b\"\n                prev2 = \"772234192e8e4ba71b018d2e7c02423e\"\n            else:\n                prev1 = \"45f88f3c318bd43d1bc48a5d408a57ef\"\n                prev2 = \"c5375d1f517ecb1ed6c9532b0f4d86aa\"\n\n            r = r.replace(\"prev1\", prev1).replace(\"prev2\", prev2).replace(\"Windows\", pid1)\n            r = r.replace(\"Linux\", pid2).replace(\"rev1\", rev1).replace(\"rev2\", rev2)\n            return r\n\n        pattern = ref_map(pattern)\n        only_recipe = \"\" if not only_recipe else \"--only-recipe\"\n        query = \"\" if not query else f\"-p={query}\"\n        client.run(f\"download {pattern} -r=default {only_recipe} {query}\")\n        out = str(client.out)\n\n        downloaded_recipes = [f\"{p}/{v}#{rr}\" for p in result[0]\n                              for v in result[1]\n                              for rr in result[2]]\n        downloaded_packages = [f\"{r}:{pid}#{pr}\" for r in downloaded_recipes\n                               for pid in result[3]\n                               for pr in result[4]]\n\n        # Checks\n        skipped_recipe_count = len(re.findall(\"Skip recipe .+ download, already in cache\", out))\n        assert skipped_recipe_count == len(downloaded_recipes)\n        for recipe in downloaded_recipes:\n            recipe = ref_map(recipe)\n            existing = f\"Skip recipe {recipe} download, already in cache\" in out\n            assert existing\n        skipped_pkg_count = len(re.findall(\"Skip package .+ download, already in cache\", out))\n        assert skipped_pkg_count == len(downloaded_packages)\n        for pkg in downloaded_packages:\n            pkg = ref_map(pkg)\n            existing = f\"Skip package {pkg} download, already in cache\" in out\n            assert existing\n\n    def test_all_latest(self, client):\n        result = (\"pkga\", \"pkgb\"), (\"1.0\", \"1.1\"), (\"rev2\",), (\"Windows\", \"Linux\"), (\"prev2\",)\n        self.assert_downloaded(\"*\", result, client)\n\n    def test_all(self, client):\n        result = (\"pkga\", \"pkgb\"), (\"1.0\", \"1.1\"), (\"rev1\", \"rev2\",), (\"Windows\", \"Linux\"), \\\n                 (\"prev1\", \"prev2\")\n        self.assert_downloaded(\"*#*:*#*\", result, client)\n\n    def test_pkg(self, client):\n        result = (\"pkga\",), (\"1.0\", \"1.1\"), (\"rev2\",), (\"Windows\", \"Linux\"), (\"prev2\",)\n        self.assert_downloaded(\"pkga\", result, client)\n\n    def test_pkg_rrev(self, client):\n        result = (\"pkga\",), (\"1.0\", \"1.1\"), (\"rev1\",), (\"Windows\", \"Linux\"), (\"prev2\",)\n        self.assert_downloaded(\"pkga#rev1\", result, client)\n\n    def test_pkg_rrevs(self, client):\n        result = (\"pkga\",), (\"1.0\", \"1.1\"), (\"rev1\", \"rev2\"), (\"Windows\", \"Linux\"), (\"prev2\",)\n        self.assert_downloaded(\"pkga#*\", result, client)\n\n    def test_pkg_pid(self, client):\n        result = (\"pkga\",), (\"1.0\", \"1.1\"), (\"rev2\",), (\"Windows\",), (\"prev2\",)\n        self.assert_downloaded(\"pkga:Windows\", result, client)\n\n    def test_pkg_rrev_pid(self, client):\n        result = (\"pkga\",), (\"1.0\", \"1.1\"), (\"rev1\",), (\"Windows\",), (\"prev2\",)\n        self.assert_downloaded(\"pkga#rev1:Windows\", result, client)\n\n    def test_pkg_rrevs_pid(self, client):\n        result = (\"pkga\",), (\"1.0\", \"1.1\"), (\"rev1\", \"rev2\"), (\"Windows\",), (\"prev2\",)\n        self.assert_downloaded(\"pkga#*:Windows\", result, client)\n\n    def test_pkg_rrev_pid_prev(self, client):\n        result = (\"pkga\",), (\"1.0\", \"1.1\"), (\"rev1\",), (\"Windows\",), (\"prev1\",)\n        self.assert_downloaded(\"pkga#rev1:Windows#prev1\", result, client)\n\n    # Only recipes\n    def test_all_latest_only_recipe(self, client):\n        result = (\"pkga\", \"pkgb\"), (\"1.0\", \"1.1\"), (\"rev2\",), (), ()\n        self.assert_downloaded(\"*\", result, client, only_recipe=True)\n\n    def test_pkg_only_recipe(self, client):\n        result = (\"pkga\",), (\"1.0\", \"1.1\"), (\"rev2\",), (), ()\n        self.assert_downloaded(\"pkga\", result, client, only_recipe=True)\n\n    def test_pkg_rrev_only_recipe(self, client):\n        result = (\"pkga\",), (\"1.0\", \"1.1\"), (\"rev1\",), (), ()\n        self.assert_downloaded(\"pkga#rev1\", result, client, only_recipe=True)\n\n    def test_pkg_rrevs_only_recipe(self, client):\n        result = (\"pkga\",), (\"1.0\", \"1.1\"), (\"rev1\", \"rev2\"), (), ()\n        self.assert_downloaded(\"pkga#*\", result, client, only_recipe=True)\n\n    # Package query\n    def test_all_query(self, client):\n        result = (\"pkga\", \"pkgb\"), (\"1.0\", \"1.1\"), (\"rev2\",), (\"Windows\",), (\"prev2\",)\n        self.assert_downloaded(\"*\", result, client, query=\"os=Windows\")\n\n    def test_pkg_query(self, client):\n        result = (\"pkga\",), (\"1.0\", \"1.1\"), (\"rev2\",), (\"Windows\",), (\"prev2\",)\n        self.assert_downloaded(\"pkga\", result, client, query=\"os=Windows\")\n\n\nclass TestDownloadPatterErrors:\n\n    @pytest.fixture(scope=\"class\")\n    def client(self):\n        client = TestClient(default_server_user=True)\n        client.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n        client.run(f\"create .\")\n        client.run(\"upload *#*:*#* -r=default -c\")\n        return client\n\n    @staticmethod\n    def assert_error(pattern, error, client, only_recipe=False, query=None):\n        only_recipe = \"\" if not only_recipe else \"--only-recipe\"\n        query = \"\" if not query else f\"-p={query}\"\n        client.run(f\"download {pattern} -r=default {only_recipe} {query}\", assert_error=True)\n        assert error in client.out\n\n    def test_recipe_not_found(self, client):\n        # FIXME: This error is ugly\n        error = \"ERROR: Recipe not found: 'zlib/1.2.11@_/_'. [Remote: default]\"\n        self.assert_error(\"zlib/1.2.11\", error, client)\n\n    def test_rrev_not_found(self, client):\n        error = \"ERROR: Recipe revision 'pkg/0.1#rev1' not found\"\n        self.assert_error(\"pkg/0.1#rev1\", error, client)\n\n    def test_pid_not_found(self, client):\n        # FIXME: Ugly error, improve it\n        rrev = \"485dad6cb11e2fa99d9afbe44a57a164\"\n        error = f\"Binary package not found: 'pkg/0.1@_/_#{rrev}:pid1'. [Remote: default]\"\n        self.assert_error(f\"pkg/0.1#{rrev}:pid1\", error, client)\n\n    def test_prev_not_found(self, client):\n        rrev = \"485dad6cb11e2fa99d9afbe44a57a164\"\n        pid = \"da39a3ee5e6b4b0d3255bfef95601890afd80709\"\n        error = f\"ERROR: Package revision 'pkg/0.1#{rrev}:{pid}#prev' not found\"\n        self.assert_error(f\"pkg/0.1#{rrev}:{pid}#prev\", error, client)\n"
  },
  {
    "path": "test/integration/command/export/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/command/export/export_dirty_test.py",
    "content": "import os\nimport textwrap\n\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import load\n\n\nclass TestSourceDirty:\n    def test_keep_failing_source_folder(self):\n        # https://github.com/conan-io/conan/issues/4025\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\\\n            from conan import ConanFile\n            from conan.tools.files import save\n            class Pkg(ConanFile):\n                def source(self):\n                    save(self, \"somefile.txt\", \"hello world!!!\")\n                    raise Exception(\"boom\")\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --name=pkg --version=1.0\", assert_error=True)\n        assert \"ERROR: pkg/1.0: Error in source() method, line 6\" in client.out\n        # Check that we can debug and see the folder\n        source_file = os.path.join(client.exported_layout().source(), \"somefile.txt\")\n        assert load(source_file) == \"hello world!!!\"\n        # Without any change, the export will generate same recipe revision, reuse source folder\n        client.run(\"create . --name=pkg --version=1.0\", assert_error=True)\n        assert \"pkg/1.0: Source folder is corrupted, forcing removal\" in client.out\n        assert \"ERROR: pkg/1.0: Error in source() method, line 6\" in client.out\n\n        # The install also removes corrupted source folder before proceeding, then call source\n        client.run(\"install --requires=pkg/1.0 --build=missing\", assert_error=True)\n        assert \"pkg/1.0: WARN: Trying to remove corrupted source folder\" in client.out\n        assert \"ERROR: pkg/1.0: Error in source() method, line 6\" in client.out\n\n        # This creates a new revision that doesn't need removal, different source folder\n        client.save({\"conanfile.py\": conanfile.replace(\"source(\", \"source2(\")})\n        client.run(\"create . --name=pkg --version=1.0\")\n        assert \"corrupted, forcing removal\" not in client.out\n        # Check that it is empty\n        assert os.listdir(os.path.join(client.exported_layout().source())) == []\n"
  },
  {
    "path": "test/integration/command/export/export_path_test.py",
    "content": "import os\nimport textwrap\n\nimport pytest\n\nfrom conan.internal.model.manifest import FileTreeManifest\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.parametrize(\"relative_path\", [False, True])\ndef test_basic(relative_path):\n    client = TestClient()\n    source_folder = os.path.join(client.current_folder, \"source\")\n    files = {\"conanfile.py\": GenConanfile().with_exports(\"*\"),\n             \"main.cpp\": \"mymain\"}\n    client.save(files, path=source_folder)\n    if relative_path:\n        with client.chdir(\"current\"):\n            client.run(\"export ../source --name=hello --version=0.1 --user=lasote --channel=stable\")\n    else:\n        client.run(\"export source --name=hello --version=0.1 --user=lasote --channel=stable\")\n\n    # The result should be the same in both cases\n    ref_layoyt = client.exported_layout()\n    ref = ref_layoyt.reference\n    reg_path = ref_layoyt.export()\n    manif = FileTreeManifest.load(reg_path)\n\n    assert '%s: Exported' % str(ref) in client.out\n    assert '%s: Exported to cache folder: %s' % (str(ref), reg_path) in client.out\n\n    for name in list(files.keys()):\n        assert os.path.exists(os.path.join(reg_path, name))\n\n    expected_sums = {'conanfile.py': '7fbb7e71f5b665780ff8c407fe0b1f9e',\n                     'main.cpp': '76c0a7a9d385266e27d69d3875f6ac19'}\n    assert expected_sums == manif.file_sums\n\n\n@pytest.mark.parametrize(\"relative_path\", [False, True])\ndef test_path(relative_path):\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import copy\n        class Pkg(ConanFile):\n            def export(self):\n                copy(self, \"*\", src=os.path.join(self.recipe_folder, \"..\", \"source\"),\n                     dst=os.path.join(self.export_folder, \"source\"))\n            \"\"\")\n    if relative_path:\n        client.save({\"conan/conanfile.py\": conanfile,\n                     \"source/main.cpp\": \"mymain\"})\n        with client.chdir(\"current\"):\n            client.run(\"export ../conan --name=hello --version=0.1 --user=lasote --channel=stable\")\n    else:\n        client.save({\"current/conanfile.py\": conanfile,\n                     \"source/main.cpp\": \"mymain\"})\n        with client.chdir(\"current\"):\n            client.run(\"export --name=hello --version=0.1 --user=lasote --channel=stable\")\n    ref_layoyt = client.exported_layout()\n    reg_path = ref_layoyt.export()\n    manif = FileTreeManifest.load(reg_path)\n\n    for name in ['conanfile.py', 'conanmanifest.txt', 'source/main.cpp']:\n        assert os.path.exists(os.path.join(reg_path, name))\n\n    expected_sums = {'conanfile.py': '6cdb33126a0408bffc0ad0ada66cb061',\n                     'source/main.cpp': '76c0a7a9d385266e27d69d3875f6ac19'}\n    assert expected_sums == manif.file_sums\n"
  },
  {
    "path": "test/integration/command/export/export_sources_test.py",
    "content": "import os\nimport textwrap\n\nfrom conan.api.model import RecipeReference\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_exports():\n    \"\"\" Check that exported files go to the right folder\n    \"\"\"\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class HelloConan(ConanFile):\n            name = \"hello\"\n            version = \"0.1\"\n            exports = \"*.h\"\n        \"\"\")\n    c = TestClient(light=True)\n    c.save({\"conanfile.py\": conanfile,\n            \"hello.h\": \"hello\",\n            \"data.txt\": \"data\"})\n    c.run(\"create .\")\n    ref = RecipeReference.loads(\"hello/0.1\")\n    ref_layout = c.get_latest_ref_layout(ref)\n\n    def assert_files(folder, files):\n        assert sorted(os.listdir(folder)) == sorted(files)\n\n    assert_files(ref_layout.source(), [])\n    assert_files(ref_layout.export(), ['conanfile.py', 'conanmanifest.txt', 'hello.h'])\n    assert_files(ref_layout.export_sources(), [])\n\n\ndef test_exports_sources():\n    \"\"\" Check that exported-sources files go to the right folder AND to the source folder\n        \"\"\"\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class HelloConan(ConanFile):\n            name = \"hello\"\n            version = \"0.1\"\n            exports_sources = \"*.h\"\n        \"\"\")\n    c = TestClient(light=True)\n    c.save({\"conanfile.py\": conanfile,\n            \"hello.h\": \"hello\",\n            \"data.txt\": \"data\"})\n    c.run(\"create .\")\n    ref = RecipeReference.loads(\"hello/0.1\")\n    ref_layout = c.get_latest_ref_layout(ref)\n\n    def assert_files(folder, files):\n        assert sorted(os.listdir(folder)) == sorted(files)\n\n    assert_files(ref_layout.source(), ['hello.h'])\n    assert_files(ref_layout.export(), ['conanfile.py', 'conanmanifest.txt', ])\n    assert_files(ref_layout.export_sources(), ['hello.h'])\n\n\ndef test_test_package_copied():\n    \"\"\"The exclusion of the test_package folder have been removed so now we test that indeed is\n    exported\"\"\"\n\n    client = TestClient(light=True)\n    conanfile = GenConanfile().with_exports(\"*\").with_exports_sources(\"*\")\n    client.save({\"conanfile.py\": conanfile,\n                 \"test_package/foo.txt\": \"bar\"})\n    client.run(\"export . --name foo --version 1.0\")\n    assert \"Copied 2 '.txt' file\" in client.out\n\n\ndef test_source_changes_generate_new_revisions():\n    tc = TestClient(light=True)\n    tc.save({\"conanfile.py\": GenConanfile(\"lib\", \"1.0\").with_exports_sources(\"file.h\"),\n             \"file.h\": \"Hello World!\"})\n\n    tc.run(\"export .\")\n    exported_rev = tc.exported_recipe_revision()\n\n    tc.save({\"file.h\": \"Bye World!\"})\n    tc.run(\"export .\")\n    exported_rev_new = tc.exported_recipe_revision()\n\n    assert exported_rev != exported_rev_new\n"
  },
  {
    "path": "test/integration/command/export/export_test.py",
    "content": "import json\nimport os\nimport platform\nimport stat\nimport textwrap\n\nimport pytest\n\nfrom conan.internal.model.manifest import FileTreeManifest\nfrom conan.api.model import RecipeReference\nfrom conan.internal.paths import CONANFILE, CONAN_MANIFEST\nfrom conan.test.utils.tools import TestClient, GenConanfile\nfrom conan.internal.util.files import load, save\n\n\nclass TestExportSettings:\n\n    def test_export_without_full_reference(self):\n        client = TestClient(light=True)\n        client.save({\"conanfile.py\": GenConanfile()})\n        client.run(\"export . --user=lasote --channel=stable\", assert_error=True)\n        assert \"conanfile didn't specify name\" in client.out\n\n        client.save({\"conanfile.py\": GenConanfile(\"lib\")})\n        client.run(\"export . --user=lasote --channel=stable\", assert_error=True)\n        assert \"conanfile didn't specify version\" in client.out\n\n        client.save({\"conanfile.py\": GenConanfile()})\n        client.run(\"export . --name=lib --version=1.0 --user=lasote --channel=channel\")\n        assert \"lib/1.0@lasote/channel: Exported\" in client.out\n\n        client.save({\"conanfile.py\": GenConanfile(\"lib\", \"1.0\")})\n        client.run(\"export . --user=lasote\")\n        assert \"lib/1.0@lasote: Exporting package recipe\" in client.out\n        client.run(\"export . --channel=channel\", assert_error=True)\n        assert \"Can't specify channel 'channel' without user\" in client.out\n\n        client.save({\"conanfile.py\": GenConanfile(\"lib\", \"1.0\").with_class_attribute('channel = \"channel\"')})\n        client.run(\"export .\", assert_error=True)\n        assert \"Can't specify channel 'channel' without user\" in client.out\n\n        client.run(\"export . --user=user\")\n        assert \"Exported: lib/1.0@user/channel\" in client.out\n\n        client.save({\"conanfile.py\": GenConanfile(\"lib\", \"1.0\").with_class_attribute('user = \"user\"')})\n        client.run(\"export .\")\n        assert \"lib/1.0@user: Exported\" in client.out\n        client.run(\"export . --channel=channel\")\n        assert \"lib/1.0@user/channel: Exported\" in client.out\n\n    def test_export_read_only(self):\n        client = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class TestConan(ConanFile):\n                name = \"hello\"\n                version = \"1.2\"\n                exports = \"file1.txt\"\n                exports_sources = \"file2.txt\"\n            \"\"\")\n        client.save({CONANFILE: conanfile,\n                     \"file1.txt\": \"\",\n                     \"file2.txt\": \"\"})\n        mode1 = os.stat(os.path.join(client.current_folder, \"file1.txt\")).st_mode\n        mode2 = os.stat(os.path.join(client.current_folder, \"file2.txt\")).st_mode\n        os.chmod(os.path.join(client.current_folder, \"file1.txt\"), mode1 & ~stat.S_IWRITE)\n        os.chmod(os.path.join(client.current_folder, \"file2.txt\"), mode2 & ~stat.S_IWRITE)\n\n        client.run(\"export . --user=lasote --channel=stable\")\n\n        layout = client.exported_layout()\n        export_path = layout.export()\n        export_src_path = layout.export_sources()\n\n        assert load(os.path.join(export_path, \"file1.txt\")) == \"\"\n        assert load(os.path.join(export_src_path, \"file2.txt\")) == \"\"\n        with pytest.raises(IOError):\n            save(os.path.join(export_path, \"file1.txt\"), \"\")\n        with pytest.raises(IOError):\n            save(os.path.join(export_src_path, \"file2.txt\"), \"\")\n\n        os.chmod(os.path.join(client.current_folder, \"file1.txt\"), mode1 | stat.S_IWRITE)\n        os.chmod(os.path.join(client.current_folder, \"file2.txt\"), mode2 | stat.S_IWRITE)\n        client.save({CONANFILE: conanfile,\n                     \"file1.txt\": \"file1\",\n                     \"file2.txt\": \"file2\"})\n        client.run(\"export . --user=lasote --channel=stable\")\n\n        layout = client.exported_layout()\n        export_path = layout.export()\n        export_src_path = layout.export_sources()\n\n        assert load(os.path.join(export_path, \"file1.txt\")) == \"file1\"\n        assert load(os.path.join(export_src_path, \"file2.txt\")) == \"file2\"\n        client.run(\"install --requires=hello/1.2@lasote/stable --build=missing\")\n        assert \"hello/1.2@lasote/stable: Generating the package\" in client.out\n\n        client.save({CONANFILE: conanfile,\n                     \"file1.txt\": \"\",\n                     \"file2.txt\": \"\"})\n        os.chmod(os.path.join(client.current_folder, \"file1.txt\"), mode1 & ~stat.S_IWRITE)\n        os.chmod(os.path.join(client.current_folder, \"file2.txt\"), mode2 & ~stat.S_IWRITE)\n        client.run(\"export . --user=lasote --channel=stable\")\n\n        layout = client.exported_layout()\n        export_path = layout.export()\n        export_src_path = layout.export_sources()\n\n        assert load(os.path.join(export_path, \"file1.txt\")) == \"\"\n        assert load(os.path.join(export_src_path, \"file2.txt\")) == \"\"\n        client.run(\"install --requires=hello/1.2@lasote/stable --build=hello*\")\n        assert \"hello/1.2@lasote/stable: Generating the package\" in client.out\n\n    def test_code_parent(self):\n        # when referencing the parent, the relative folder \"sibling\" will be kept\n        base = \"\"\"\nimport os\nfrom conan import ConanFile\nfrom conan.tools.files import copy\nclass TestConan(ConanFile):\n    name = \"hello\"\n    version = \"1.2\"\n    def export(self):\n        copy(self, \"*.txt\", src=os.path.join(self.recipe_folder, \"..\"),\n             dst=self.export_folder)\n\"\"\"\n        for conanfile in (base, base.replace(\"../*.txt\", \"../sibling*\")):\n            client = TestClient(light=True)\n            client.save({\"recipe/conanfile.py\": conanfile,\n                         \"sibling/file.txt\": \"Hello World!\"})\n            client.current_folder = os.path.join(client.current_folder, \"recipe\")\n            client.run(\"export . --user=lasote --channel=stable\")\n            layout = client.exported_layout()\n            export_path = layout.export()\n            content = load(os.path.join(export_path, \"sibling/file.txt\"))\n            assert \"Hello World!\" == content\n\n    def test_code_sibling(self):\n        # if provided a path with slash, it will use as a export base\n        client = TestClient(light=True)\n        conanfile = \"\"\"\nimport os\nfrom conan import ConanFile\nfrom conan.tools.files import copy\nclass TestConan(ConanFile):\n    name = \"hello\"\n    version = \"1.2\"\n    def export(self):\n        copy(self, \"*.txt\", src=os.path.join(self.recipe_folder, \"..\", \"sibling\"),\n             dst=self.export_folder)\n\"\"\"\n        files = {\"recipe/conanfile.py\": conanfile,\n                 \"sibling/file.txt\": \"Hello World!\"}\n        client.save(files)\n        client.current_folder = os.path.join(client.current_folder, \"recipe\")\n        client.run(\"export . --user=lasote --channel=stable\")\n        layout = client.exported_layout()\n        export_path = layout.export()\n        content = load(os.path.join(export_path, \"file.txt\"))\n        assert \"Hello World!\" == content\n\n    def test_code_several_sibling(self):\n        # if provided a path with slash, it will use as a export base\n        client = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.files import copy\n            class TestConan(ConanFile):\n                name = \"hello\"\n                version = \"1.2\"\n                # exports_sources = \"../test/src/*\", \"../cpp/*\", \"../include/*\"\n                def export_sources(self):\n                    copy(self, \"*\", src=os.path.join(self.recipe_folder, \"..\", \"test\", \"src\"),\n                         dst=self.export_sources_folder)\n                    copy(self, \"*\", src=os.path.join(self.recipe_folder, \"..\", \"cpp\"),\n                         dst=self.export_sources_folder)\n                    copy(self, \"*\", src=os.path.join(self.recipe_folder, \"..\", \"include\"),\n                         dst=self.export_sources_folder)\n\n            \"\"\")\n        client.save({\"recipe/conanfile.py\": conanfile,\n                     \"test/src/file.txt\": \"Hello World!\",\n                     \"cpp/file.cpp\": \"Hello World!\",\n                     \"include/file.h\": \"Hello World!\"})\n        client.current_folder = os.path.join(client.current_folder, \"recipe\")\n        client.run(\"export . --user=lasote --channel=stable\")\n        layout = client.exported_layout()\n        export_path = layout.export_sources()\n        assert sorted(['file.txt', 'file.cpp', 'file.h']) == sorted(os.listdir(export_path))\n\n    @pytest.mark.parametrize(\"filename\", [\"myconanfile.py\", \"Conanfile.py\"])\n    def test_filename(self, filename):\n        client = TestClient(light=True)\n        client.save({filename: GenConanfile(\"hello\", \"1.2\")})\n        client.run(\"export %s --user=user --channel=stable\" % filename)\n        assert \"hello/1.2@user/stable: Exported\" in client.out\n        layout = client.exported_layout()\n        export_path = layout.export()\n        conanfile = load(os.path.join(export_path, \"conanfile.py\"))\n        assert \"name = 'hello'\" in conanfile\n        manifest = load(os.path.join(export_path, \"conanmanifest.txt\"))\n        assert 'conanfile.py: 5dc49e518e15f3889cb2e097ce4d1dff' in manifest\n\n    def test_exclude_basic(self):\n        client = TestClient(light=True)\n        conanfile = \"\"\"\nfrom conan import ConanFile\nclass TestConan(ConanFile):\n    name = \"hello\"\n    version = \"1.2\"\n    exports = \"*.txt\", \"!*file1.txt\"\n    exports_sources = \"*.cpp\", \"!*temp.cpp\"\n\"\"\"\n\n        client.save({CONANFILE: conanfile,\n                     \"file.txt\": \"\",\n                     \"file1.txt\": \"\",\n                     \"file.cpp\": \"\",\n                     \"file_temp.cpp\": \"\"})\n        client.run(\"export .\")\n        layout = client.exported_layout()\n        export_path = layout.export()\n        exports_sources_path = layout.export_sources()\n        assert os.path.exists(os.path.join(export_path, \"file.txt\"))\n        assert not os.path.exists(os.path.join(export_path, \"file1.txt\"))\n        assert os.path.exists(os.path.join(exports_sources_path, \"file.cpp\"))\n        assert not os.path.exists(os.path.join(exports_sources_path, \"file_temp.cpp\"))\n\n    def test_exclude_folders(self):\n        client = TestClient(light=True)\n        client.save({CONANFILE: GenConanfile(\"hello\", \"1.2\").with_exports(\"*.txt\", \"!*/temp/*\"),\n                     \"file.txt\": \"\",\n                     \"any/temp/file1.txt\": \"\",\n                     \"other/sub/file2.txt\": \"\"})\n        client.run(\"export .\")\n        layout = client.exported_layout()\n        export_path = layout.export()\n        assert os.path.exists(os.path.join(export_path, \"file.txt\"))\n        assert not os.path.exists(os.path.join(export_path, \"any/temp/file1.txt\"))\n        assert os.path.exists(os.path.join(export_path, \"other/sub/file2.txt\"))\n\n\nclass TestExport:\n\n    @pytest.fixture(autouse=True)\n    def setup(self):\n        self.client = TestClient(light=True)\n        self.files = {\"conanfile.py\": GenConanfile(\"hello0\", \"0.1\").with_exports(\"*\"),\n                      \"main.cpp\": \"MyMain\",\n                      \"CMakeLists.txt\": \"MyCmake\",\n                      \"executable\": \"myexe\"}\n        self.ref = RecipeReference(\"hello0\", \"0.1\", \"lasote\", \"stable\")\n        self.client.save(self.files)\n        self.client.run(\"export . --user=lasote --channel=stable\")\n\n    def test_basic(self):\n        reg_path = self.client.exported_layout().export()\n        manif = FileTreeManifest.load(reg_path)\n\n        assert '%s: Exported' % str(self.ref) in self.client.out\n        assert '%s: Exported to cache folder: %s' % (str(self.ref), reg_path) in self.client.out\n        assert os.path.exists(reg_path)\n\n        for name in list(self.files.keys()):\n            assert os.path.exists(os.path.join(reg_path, name))\n\n        expected_sums = {'CMakeLists.txt': '3cf710785270c7e98a30d4a90ea66492',\n                         'conanfile.py': '5dbbe4328efa3342baba2a7ca961ede1',\n                         'executable': 'db299d5f0d82f113fad627a21f175e59',\n                         'main.cpp': 'd9c03c934a4b3b1670775c17c26f39e9'}\n        assert expected_sums == manif.file_sums\n\n    def test_case_sensitive(self):\n        self.ref = RecipeReference(\"hello0\", \"0.1\", \"lasote\", \"stable\")\n        self.client.save({\"conanfile.py\": GenConanfile(\"hello0\", \"0.1\").with_exports(\"*\")})\n        self.client.run(\"export . --user=lasote --channel=stable\")\n        assert \"hello0/0.1@lasote/stable: Exported\" in self.client.out\n\n    def test_export_filter(self):\n        self.client.save({CONANFILE: GenConanfile(\"openssl\", \"2.0.1\")})\n        self.client.run(\"export . --user=lasote --channel=stable\")\n        layout = self.client.exported_layout()\n        export_path = layout.export()\n        assert sorted(os.listdir(export_path)) == [CONANFILE, CONAN_MANIFEST]\n\n        content = \"\"\"\nfrom conan import ConanFile\n\nclass OpenSSLConan(ConanFile):\n    name = \"openssl\"\n    version = \"2.0.1\"\n    exports = ('*.txt', '*.h')\n\"\"\"\n        self.client.save({CONANFILE: content})\n        self.client.run(\"export . --user=lasote --channel=stable\")\n        layout = self.client.exported_layout()\n        export_path = layout.export()\n        assert sorted(os.listdir(export_path)) == ['CMakeLists.txt', CONANFILE, CONAN_MANIFEST]\n\n        # Now exports being a list instead a tuple\n        content = \"\"\"\nfrom conan import ConanFile\n\nclass OpenSSLConan(ConanFile):\n    name = \"openssl\"\n    version = \"2.0.1\"\n    exports = ['*.txt', '*.h']\n\"\"\"\n        self.client.save({CONANFILE: content})\n        self.client.run(\"export . --user=lasote --channel=stable\")\n        layout = self.client.exported_layout()\n        export_path = layout.export()\n        assert sorted(os.listdir(export_path)) == ['CMakeLists.txt', CONANFILE, CONAN_MANIFEST]\n\n\nclass TestExportMetadata:\n\n    def test_revision_mode_hash(self):\n        t = TestClient(light=True)\n        t.save({'conanfile.py': GenConanfile().with_revision_mode(\"hash\")})\n        t.run(f\"export . --name=name --version=version\")\n        layout = t.exported_layout()\n        assert layout.reference.revision == \"99c241d3d47396772cd1ac5a36307a29\"\n\n    def test_revision_mode_invalid(self):\n        t = TestClient(light=True)\n        t.save({'conanfile.py': GenConanfile().with_revision_mode(\"auto\")})\n        t.run(\"export . --name=name --version=version\", assert_error=True)\n        assert \"ERROR: Revision mode should be one of 'hash' (default) or 'scm'\" in t.out\n\n    def test_export_no_params(self):\n        client = TestClient(light=True)\n        client.save({\"conanfile.py\": GenConanfile(\"lib\", \"1.0\")})\n        client.run('export .')\n        assert \"lib/1.0: Exported\" in client.out\n\n    def test_export_with_name_and_version(self):\n        client = TestClient(light=True)\n        client.save({\"conanfile.py\": GenConanfile()})\n\n        client.run('export . --name=lib --version=1.0')\n        assert \"lib/1.0: Exported\" in client.out\n\n    def test_export_with_only_user_channel(self):\n        \"\"\"This should be the recommended way and only from Conan 2.0\"\"\"\n        client = TestClient(light=True)\n        client.save({\"conanfile.py\": GenConanfile(\"lib\", \"1.0\")})\n\n        client.run('export .  --version= --user=user --channel=channel')\n        assert \"lib/1.0@user/channel: Exported\" in client.out\n\n    def test_export_conflict_no_user_channel(self):\n        client = TestClient(light=True)\n        client.save({\"conanfile.py\": GenConanfile()})\n\n        client.run('export . --name=pkg --version=0.1 --user=user --channel=channel')\n        assert \"pkg/0.1@user/channel: Exported\" in client.out\n        client.run('export . --name=pkg --version=0.1 --user=other --channel=stable')\n        assert \"pkg/0.1@other/stable: Exported\" in client.out\n        client.run('export . --name=pkg --version=0.1')\n        assert \"pkg/0.1: Exported\" in client.out\n        client.run('export . --name=pkg --version=0.1')\n        assert \"pkg/0.1: Exported\" in client.out\n\n\n@pytest.mark.skipif(platform.system() != \"Linux\", reason=\"Needs case-sensitive filesystem\")\ndef test_export_casing():\n    # https://github.com/conan-io/conan/issues/8583\n    client = TestClient(light=True)\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            exports = \"file1\", \"FILE1\"\n            exports_sources = \"test\", \"TEST\"\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile,\n                 \"test\": \"some lowercase\",\n                 \"TEST\": \"some UPPERCASE\",\n                 \"file1\": \"file1 lowercase\",\n                 \"FILE1\": \"file1 UPPERCASE\"\n                 })\n    assert client.load(\"test\") == \"some lowercase\"\n    assert client.load(\"TEST\") == \"some UPPERCASE\"\n    assert client.load(\"file1\") == \"file1 lowercase\"\n    assert client.load(\"FILE1\") == \"file1 UPPERCASE\"\n    client.run(\"export . --name=pkg --version=0.1\")\n    layout = client.exported_layout()\n    export_src_folder = layout.export_sources()\n    assert load(os.path.join(export_src_folder, \"test\")) == \"some lowercase\"\n    assert load(os.path.join(export_src_folder, \"TEST\")) == \"some UPPERCASE\"\n    exports_folder = layout.export()\n    assert load(os.path.join(exports_folder, \"file1\")) == \"file1 lowercase\"\n    assert load(os.path.join(exports_folder, \"FILE1\")) == \"file1 UPPERCASE\"\n\n\ndef test_export_invalid_refs():\n    c = TestClient(light=True)\n    c.save({\"conanfile.py\": GenConanfile()})\n    c.run(\"export . --name=pkg% --version=0.1\", assert_error=True)\n    assert \"ERROR: Invalid package name 'pkg%'\" in c.out\n    c.run(\"export . --name=pkg --version=0.1%\", assert_error=True)\n    assert \"ERROR: Invalid package version '0.1%'\" in c.out\n    c.run(\"export . --name=pkg --version=0.1 --user=user%\", assert_error=True)\n    assert \"ERROR: Invalid package user 'user%'\" in c.out\n    c.run(\"export . --name=pkg --version=0.1 --user=user --channel=channel%\", assert_error=True)\n    assert \"ERROR: Invalid package channel 'channel%'\" in c.out\n\n\ndef test_allow_temp_uppercase():\n    c = TestClient(light=True)\n    c.save({\"conanfile.py\": GenConanfile()})\n    c.run(\"export . --name=Pkg --version=0.1\", assert_error=True)\n    assert \"ERROR: Conan packages names 'Pkg/0.1' must be all lowercase\" in c.out\n    c.save_home({\"global.conf\": \"core:allow_uppercase_pkg_names=True\"})\n    c.run(\"export . --name=Pkg --version=0.1\")\n    assert \"WARN: Package name 'Pkg/0.1' has uppercase, \" \\\n           \"and has been allowed by temporary config.\" in c.out\n\n\ndef test_warn_special_chars_refs():\n    c = TestClient(light=True)\n    c.save({\"conanfile.py\": GenConanfile()})\n    c.run(\"export . --name=pkg.name --version=0.1\")\n    assert \"WARN: Name containing special chars is discouraged 'pkg.name'\" in c.out\n    c.run(\"export . --name=name --version=0.1 --user=user+some\")\n    assert \"WARN: User containing special chars is discouraged 'user+some'\" in c.out\n    c.run(\"export . --name=pkg.name --version=0.1 --user=user --channel=channel+some\")\n    assert \"WARN: Channel containing special chars is discouraged 'channel+some'\" in c.out\n\n\ndef test_export_json():\n    c = TestClient(light=True)\n    c.save({\"conanfile.py\": GenConanfile()})\n    c.run(\"export . --name=foo --version=0.1 --format json\")\n    info = json.loads(c.stdout)\n    assert info[\"reference\"] == \"foo/0.1#4d670581ccb765839f2239cc8dff8fbd\"\n    assert len(info) == 1  # Only \"reference\" key yet\n"
  },
  {
    "path": "test/integration/command/export/exports_method_test.py",
    "content": "import os\nimport textwrap\n\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import save_files, load\n\n\nclass TestExportsMethod:\n\n    def test_export_method(self):\n        client = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import copy\n\n            class MethodConan(ConanFile):\n                exports = \"file.txt\"\n                def export(self):\n                    copy(self, \"LICENSE.md\", self.recipe_folder, self.export_folder)\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile, \"LICENSE.md\": \"license\", \"file.txt\": \"file\"})\n        client.run(\"export . --name=pkg --version=0.1\")\n        assert \"pkg/0.1: Copied 1 '.txt' file: file.txt\" in client.out\n        assert \"pkg/0.1: Calling export()\" in client.out\n        assert \"Copied 1 '.md' file: LICENSE.md\" in client.out\n\n        layout = client.exported_layout()\n\n        exported_files = os.listdir(layout.export())\n        assert \"file.txt\" in exported_files\n        assert \"LICENSE.md\" in exported_files\n\n    def test_export_method_parent_folder(self):\n        folder = temp_folder()\n        save_files(folder, {\"subdir/subdir2/file2.txt\": \"\", \"subdir/file1.txt\": \"\"})\n        client = TestClient(current_folder=os.path.join(folder, \"recipe\"))\n        conanfile = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.files import copy\n\n            class MethodConan(ConanFile):\n                def export(self):\n                    self.output.info(\"Executing export() method\")\n                    copy(self, \"*.txt\", os.path.join(self.recipe_folder, \"../subdir\"),\n                         self.export_folder)\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"export . --name=pkg --version=0.1\")\n        assert \"Copied 2 '.txt' files: file1.txt, file2.txt\" in client.out\n\n        layout = client.exported_layout()\n\n        assert os.path.isfile(os.path.join(layout.export(), \"file1.txt\"))\n        assert os.path.isfile(os.path.join(layout.export(), \"subdir2\", \"file2.txt\"))\n\n    def test_export_no_settings_options_method(self):\n        client = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import copy\n\n            class MethodConan(ConanFile):\n                settings = \"os\"\n                def export(self):\n                    if self.settings.os == \"Windows\":\n                        copy(self, \"LICENSE.md\", self.recipe_folder, self.export_folder)\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile, \"LICENSE.md\": \"license\"})\n        client.run(\"export . --name=pkg --version=0.1\", assert_error=True)\n        assert \"ERROR: pkg/0.1: Error in export() method, line 8\" in client.out\n\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import copy\n\n            class MethodConan(ConanFile):\n                options = {\"myopt\": [\"myval\", \"other\"]}\n                default_options = {\"myopt\": \"myval\"}\n                def export(self):\n                    if self.default_options[\"myopt\"] == \"myval\":\n                        copy(self, \"LICENSE.md\", self.recipe_folder, self.export_folder)\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"export . --name=pkg --version=0.1\", assert_error=True)\n        assert \"ERROR: pkg/0.1: Error in export() method, line 9\" in client.out\n\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class MethodConan(ConanFile):\n                options = {\"myopt\": [\"myval\"]}\n                default_options = {\"myopt\": \"myval\"}\n                def export(self):\n                    pass\n                def export_sources(self):\n                    pass\n                def build(self):\n                    self.output.info(\"MYOPT: %s\" % self.options.myopt)\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --name=pkg --version=0.1\")\n        assert \"pkg/0.1: MYOPT: myval\" in client.out\n\n    def test_export_folders(self):\n        client = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n           from conan import ConanFile\n           from conan.tools.files import save, load\n           import os\n\n           class MethodConan(ConanFile):\n               def export(self):\n                   content = load(self, os.path.join(os.getcwd(), \"data.txt\"))\n                   save(self, os.path.join(self.export_folder, \"myfile.txt\"), content)\n           \"\"\")\n        client.save({\"recipe/conanfile.py\": conanfile, \"recipe/data.txt\": \"mycontent\"})\n        client.run(\"export recipe --name=pkg --version=0.1\")\n        layout = client.exported_layout()\n        assert \"mycontent\" == load(os.path.join(layout.export(), \"myfile.txt\"))\n        client.current_folder = os.path.join(client.current_folder, \"recipe\")\n        client.run(\"export . --name=pkg --version=0.1\")\n        layout = client.exported_layout()\n        assert \"mycontent\" == load(os.path.join(layout.export(), \"myfile.txt\"))\n\n    def test_export_attribute_error(self):\n        client = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class MethodConan(ConanFile):\n                export = \"file.txt\"\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile, \"file.txt\": \"file\"})\n        client.run(\"export . --name=pkg --version=0.1\", assert_error=True)\n        assert \"ERROR: conanfile 'export' must be a method\" in client.out\n\n    def test_exports_method_error(self):\n        client = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class MethodConan(ConanFile):\n                def exports(self):\n                    pass\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"export . --name=pkg --version=0.1\", assert_error=True)\n        assert \"ERROR: conanfile 'exports' shouldn't be a method, use 'export()' instead\" in client.out\n\n\nclass TestExportsSourcesMethod:\n\n    def test_export_sources_method(self):\n        client = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import copy\n\n            class MethodConan(ConanFile):\n                exports_sources = \"file.txt\"\n                def export_sources(self):\n                    copy(self, \"LICENSE.md\", self.recipe_folder, self.export_sources_folder)\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile, \"LICENSE.md\": \"license\", \"file.txt\": \"file\"})\n        client.run(\"export . --name=pkg --version=0.1\")\n        assert \"pkg/0.1: Copied 1 '.txt' file: file.txt\" in client.out\n        assert \"Copied 1 '.md' file: LICENSE.md\" in client.out\n\n        layout = client.exported_layout()\n\n        exported_files = os.listdir(layout.export_sources())\n        assert \"file.txt\" in exported_files\n        assert \"LICENSE.md\" in exported_files\n\n    def test_export_source_folders(self):\n        client = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n           from conan import ConanFile\n           from conan.tools.files import save, load\n           import os\n\n           class MethodConan(ConanFile):\n               def export_sources(self):\n                   content = load(self, os.path.join(os.getcwd(), \"data.txt\"))\n                   save(self, os.path.join(self.export_sources_folder, \"myfile.txt\"), content)\n           \"\"\")\n        client.save({\"recipe/conanfile.py\": conanfile, \"recipe/data.txt\": \"mycontent\"})\n        client.run(\"export recipe --name=pkg --version=0.1\")\n        layout = client.exported_layout()\n        assert \"mycontent\" == load(os.path.join(layout.export_sources(), \"myfile.txt\"))\n        client.current_folder = os.path.join(client.current_folder, \"recipe\")\n        client.run(\"export . --name=pkg --version=0.1\")\n        layout = client.exported_layout()\n        assert \"mycontent\" == load(os.path.join(layout.export_sources(), \"myfile.txt\"))\n\n    def test_export_sources_attribute_error(self):\n        client = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class MethodConan(ConanFile):\n                export_sources = \"file.txt\"\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile, \"file.txt\": \"file\"})\n        client.run(\"export . --name=pkg --version=0.1\", assert_error=True)\n        assert \"ERROR: conanfile 'export_sources' must be a method\" in client.out\n\n    def test_exports_sources_method_error(self):\n        client = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class MethodConan(ConanFile):\n                def exports_sources(self):\n                    pass\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"export . --name=pkg --version=0.1\", assert_error=True)\n        assert (\"ERROR: conanfile 'exports_sources' shouldn't be a method, \"\n                \"use 'export_sources()' instead\") in client.out\n\n    def test_exports_sources_upload_error(self):\n        # https://github.com/conan-io/conan/issues/7377\n        client = TestClient(default_server_user=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import load, copy\n\n            class MethodConan(ConanFile):\n                def export_sources(self):\n                    copy(self, \"*\", self.recipe_folder, self.export_sources_folder)\n                def build(self):\n                    self.output.info(\"CONTENT: %s\" % load(self, \"myfile.txt\"))\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile,\n                     \"myfile.txt\": \"mycontent\"})\n        client.run(\"export . --name=pkg --version=0.1\")\n        assert \"Copied 1 '.txt' file: myfile.txt\" in client.out\n        client.run(\"upload pkg/0.1 -r default\")\n        client.run(\"remove * -c\")\n        client.run(\"install --requires=pkg/0.1@ --build='*'\")\n        assert \"pkg/0.1: Sources downloaded from 'default'\" in client.out\n        assert \"pkg/0.1: CONTENT: mycontent\" in client.out\n"
  },
  {
    "path": "test/integration/command/export/test_export.py",
    "content": "import textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_basic():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class TestConan(ConanFile):\n            name = \"hello\"\n            version = \"1.2\"\n            user = \"myuser\"\n            channel = \"mychannel\"\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"export .\")\n    assert \"hello/1.2@myuser/mychannel\" in client.out\n    client.run(\"list *\")\n    assert \"hello/1.2@myuser/mychannel\" in client.out\n    client.run(\"create .\")\n    assert \"hello/1.2@myuser/mychannel\" in client.out\n    assert \"hello/1.2:\" not in client.out\n\n\ndef test_export_cci():\n    c = TestClient(light=True)\n    c.save({\"conanfile.py\": GenConanfile(\"mypkg\", \"cci.123\")})\n    c.run(\"export .\")\n    assert (\"WARN: risk: Version 'cci.123' contains an alphanumeric \"\n            \"major alongside a minor version\") in c.out\n\n    c.save({\"conanfile.py\": GenConanfile(\"mypkg\", \"develop\")})\n    c.run(\"export .\")\n    assert \"WARN\" not in c.out\n\n    c.save({\"conanfile.py\": GenConanfile(\"mypkg\", \"cci.123\")\n           .with_class_attribute(\"package_id_embed_mode='full_mode'\")})\n    c.run(\"export .\")\n    assert \"WARN\" not in c.out\n"
  },
  {
    "path": "test/integration/command/export_pkg_test.py",
    "content": "import json\nimport os\nimport re\n\nimport textwrap\nfrom textwrap import dedent\n\nfrom conan.internal.paths import CONANFILE\nfrom conan.test.utils.tools import TestClient, GenConanfile\nfrom conan.internal.util.files import load\n\n\nclass TestExportPkg:\n\n    def test_dont_touch_server(self):\n        # https://github.com/conan-io/conan/issues/3432\n        client = TestClient(servers={\"default\": None},\n                            requester_class=None, inputs=[\"admin\", \"password\"])\n\n        client.save({\"conanfile.py\": GenConanfile().with_name(\"pkg\").with_version(\"0.1\")})\n        client.run(\"install .\")\n        client.run(\"export-pkg . --user=lasote --channel=stable \")\n\n    def test_transitive_without_settings(self):\n        # https://github.com/conan-io/conan/issues/3367\n        client = TestClient()\n        client.save({\"pkgc/conanfile.py\": GenConanfile(\"pkgc\", \"0.1\"),\n                     \"pkgb/conanfile.py\": GenConanfile(\"pkgb\", \"0.1\").with_requires(\"pkgc/0.1\"),\n                     \"pkga/conanfile.py\": GenConanfile(\"pkga\", \"0.1\").with_requires(\"pkgb/0.1\")})\n        client.run(\"create pkgc\")\n        client.run(\"create pkgb\")\n\n        client.run(\"build pkga -bf=build\")\n        client.run(\"export-pkg pkga \")\n        package_id = re.search(r\"Packaging to (\\S+)\", str(client.out)).group(1)\n        assert f\"conanfile.py (pkga/0.1): Package '{package_id}' created\" in client.out\n\n        # we can export-pkg without the dependencies binaries if we need to optimize\n        client.run(\"remove pkgc*:* -c\")\n        client.run(\"remove pkgb*:* -c\")\n        client.run(\"export-pkg pkga --skip-binaries\")\n        package_id = re.search(r\"Packaging to (\\S+)\", str(client.out)).group(1)\n        assert f\"conanfile.py (pkga/0.1): Package '{package_id}' created\" in client.out\n\n    def test_package_folder_errors(self):\n        # https://github.com/conan-io/conan/issues/2350\n        client = TestClient()\n        client.save({CONANFILE: GenConanfile()})\n        client.run(\"export-pkg --name=hello --version=0.1 --user=lasote --channel=stable\")\n        assert (\"conanfile.py (hello/0.1@lasote/stable): package(): \"\n                \"WARN: No files in this package!\") in client.out\n\n    def test_options(self):\n        # https://github.com/conan-io/conan/issues/2242\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Hello(ConanFile):\n                name = \"hello\"\n                version = \"0.1\"\n                options = { \"optionOne\": [True, False, 123] }\n                default_options =  {\"optionOne\": True}\n            \"\"\")\n        client = TestClient()\n        client.save({CONANFILE: conanfile})\n        client.run(\"export-pkg .\")\n        client.run(\"list hello/0.1:*\")\n        assert \"optionOne: True\" in client.out\n        assert \"optionOne: False\" not in client.out\n        assert \"optionOne: 123\" not in client.out\n        client.run(\"export-pkg . -o optionOne=False\")\n        client.run(\"list hello/0.1:*\")\n        assert \"optionOne: True\" in client.out\n        assert \"optionOne: False\" in client.out\n        assert \"optionOne: 123\" not in client.out\n        client.run(\"export-pkg . -o hello/*:optionOne=123\")\n        client.run(\"list hello/0.1:*\")\n        assert \"optionOne: True\" in client.out\n        assert \"optionOne: False\" in client.out\n        assert \"optionOne: 123\" in client.out\n\n    def test_profile_environment(self):\n        # https://github.com/conan-io/conan/issues/4832\n        conanfile = dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.env import VirtualBuildEnv\n            class helloPythonConan(ConanFile):\n                def package(self):\n                    build_env = VirtualBuildEnv(self).vars()\n                    with build_env.apply():\n                        self.output.info(\"ENV-VALUE: %s!!!\" % os.getenv(\"MYCUSTOMVAR\"))\n            \"\"\")\n        profile = dedent(\"\"\"\n            [buildenv]\n            MYCUSTOMVAR=MYCUSTOMVALUE\n            \"\"\")\n        client = TestClient()\n        client.save({CONANFILE: conanfile,\n                     \"myprofile\": profile})\n        client.run(\"export-pkg . --name=hello --version=0.1 --user=lasote --channel=stable \"\n                   \" -pr=myprofile\")\n        assert \"conanfile.py (hello/0.1@lasote/stable): ENV-VALUE: MYCUSTOMVALUE!!!\" in client.out\n\n    def test_build_folders(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.files import copy\n            class TestConan(ConanFile):\n                name = \"hello\"\n                version = \"0.1\"\n                settings = \"os\"\n\n                def package(self):\n                    copy(self, \"*.h\", os.path.join(self.source_folder, \"include\"),\n                         os.path.join(self.package_folder, \"inc\"))\n                    copy(self, \"*.lib\", os.path.join(self.build_folder, \"lib\"),\n                         os.path.join(self.package_folder, \"lib\"))\n            \"\"\")\n        client.save({CONANFILE: conanfile,\n                     \"include/header.h\": \"//Windows header\",\n                     \"include/header.txt\": \"\",\n                     \"libs/what\": \"\",\n                     \"lib/hello.lib\": \"My Lib\",\n                     \"lib/bye.txt\": \"\"}, clean_first=True)\n        client.run(\"export-pkg . --user=lasote --channel=stable -s os=Windows -vvv\")\n        assert \"copy(pattern=*.h) copied 1 files\" in client.out\n        assert \"copy(pattern=*.lib) copied 1 files\" in client.out\n        package_folder = client.created_layout().package()\n        inc = os.path.join(package_folder, \"inc\")\n        assert os.listdir(inc) == [\"header.h\"]\n        assert load(os.path.join(inc, \"header.h\")) == \"//Windows header\"\n        lib = os.path.join(package_folder, \"lib\")\n        assert os.listdir(lib) == [\"hello.lib\"]\n        assert load(os.path.join(lib, \"hello.lib\")) == \"My Lib\"\n\n    def test_default_source_folder(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.files import copy\n            class TestConan(ConanFile):\n\n                def package(self):\n                    copy(self, \"*.h\", os.path.join(self.source_folder, \"src\"),\n                         os.path.join(self.package_folder, \"include\"))\n                    copy(self, \"*.lib\", self.build_folder, os.path.join(self.package_folder, \"lib\"),\n                         keep_path=False)\n            \"\"\")\n        client.save({CONANFILE: conanfile,\n                     \"src/header.h\": \"contents\",\n                     \"build/lib/hello.lib\": \"My Lib\"})\n        client.run(\"export-pkg . --name=hello --version=0.1 --user=lasote --channel=stable \"\n                   \"-s os=Windows\")\n\n        package_folder = client.created_layout().package()\n        header = os.path.join(package_folder, \"include/header.h\")\n        assert os.path.exists(header)\n\n        hello_path = os.path.join(package_folder, \"lib\", \"hello.lib\")\n        assert os.path.exists(hello_path)\n\n    def test_build_source_folders(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.files import copy\n            class TestConan(ConanFile):\n                settings = \"os\"\n                name = \"hello\"\n                version = \"0.1\"\n\n                def layout(self):\n                    self.folders.build = \"build\"\n                    self.folders.source = \"src\"\n\n                def package(self):\n                    copy(self, \"*.h\", os.path.join(self.source_folder, \"include\"),\n                         os.path.join(self.package_folder, \"inc\"))\n                    copy(self, \"*.lib\", os.path.join(self.build_folder, \"lib\"),\n                         os.path.join(self.package_folder, \"lib\"))\n            \"\"\")\n        client.save({CONANFILE: conanfile,\n                     \"src/include/header.h\": \"//Windows header\",\n                     \"src/include/header.txt\": \"\",\n                     \"build/libs/what\": \"\",\n                     \"build/lib/hello.lib\": \"My Lib\",\n                     \"build/lib/bye.txt\": \"\"})\n        client.run(\"export-pkg . --user=lasote --channel=stable -s os=Windows\")\n\n        package_folder = client.created_layout().package()\n        inc = os.path.join(package_folder, \"inc\")\n        assert os.listdir(inc) == [\"header.h\"]\n        assert load(os.path.join(inc, \"header.h\")) == \"//Windows header\"\n        lib = os.path.join(package_folder, \"lib\")\n        assert os.listdir(lib) == [\"hello.lib\"]\n        assert load(os.path.join(lib, \"hello.lib\")) == \"My Lib\"\n\n    def test_partial_references(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import copy\n            class TestConan(ConanFile):\n                name = \"hello\"\n                version = \"0.1\"\n                settings = \"os\"\n\n                def package(self):\n                    copy(self, \"*\", self.source_folder, self.package_folder)\n            \"\"\")\n        # Partial reference is ok\n        client.save({CONANFILE: conanfile, \"file.txt\": \"txt contents\"})\n        client.run(\"export-pkg . --user=conan --channel=stable\")\n        assert (\"conanfile.py (hello/0.1@conan/stable): package(): \"\n                \"Packaged 1 '.txt' file: file.txt\") in client.out\n\n        # Specify different name or version is not working\n        client.run(\"export-pkg . --name=lib\", assert_error=True)\n        assert \"ERROR: Package recipe with name lib!=hello\" in client.out\n\n        client.run(\"export-pkg . --version=1.1\", assert_error=True)\n        assert \"ERROR: Package recipe with version 1.1!=0.1\" in client.out\n\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import copy\n            class TestConan(ConanFile):\n                settings = \"os\"\n\n                def package(self):\n                    copy(self, \"*\", self.source_folder, self.package_folder)\n            \"\"\")\n        # Partial reference is ok\n        client.save({CONANFILE: conanfile, \"file.txt\": \"txt contents\"})\n        client.run(\"export-pkg . --name=anyname --version=1.222 --user=conan --channel=stable\")\n        assert (\"conanfile.py (anyname/1.222@conan/stable): package(): \"\n                \"Packaged 1 '.txt' file: file.txt\") in client.out\n\n    def test_with_deps(self):\n        client = TestClient()\n        client.save({\"conanfile.py\": GenConanfile()})\n        client.run(\"create . --name=hello --version=0.1 --user=lasote --channel=stable\")\n        conanfile = GenConanfile().with_name(\"hello1\").with_version(\"0.1\")\\\n                                  .with_import(\"from conan.tools.files import copy, collect_libs\") \\\n                                  .with_require(\"hello/0.1@lasote/stable\")\n\n        conanfile = str(conanfile) + \"\"\"\\n    def package_info(self):\n        self.cpp_info.libs = collect_libs(self)\n    def layout(self):\n        self.folders.build = \"Release_x86\"\n    def package(self):\n        copy(self, \"*\", self.source_folder, self.package_folder)\n        copy(self, \"*\", self.build_folder, self.package_folder)\n        \"\"\"\n        client.save({\"conanfile.py\": conanfile}, clean_first=True)\n        client.save({\"Release_x86/lib/libmycoollib.a\": \"\"})\n        settings = ('-s os=Windows -s compiler=gcc -s compiler.version=4.9 '\n                    '-s compiler.libcxx=libstdc++ -s build_type=Release -s arch=x86')\n        client.run(\"export-pkg . --name=hello1 --version=0.1 --user=lasote --channel=stable %s\"\n                   % settings)\n\n        consumer = (GenConanfile().with_requires(\"hello1/0.1@lasote/stable\")\n                    .with_settings(\"os\", \"build_type\"))\n\n        client.save({CONANFILE: consumer}, clean_first=True)\n        client.run(\"install conanfile.py -g CMakeDeps\")\n        assert \"hello/0.1@lasote/stable: Already installed!\" in client.out\n        assert \"hello1/0.1@lasote/stable: Already installed!\" in client.out\n\n        cmakeinfo = client.load(\"hello1-release-data.cmake\")\n        assert \"set(hello1_LIBS_RELEASE mycoollib)\" in cmakeinfo\n\n    def test_export_pkg_version_type(self):\n        client = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Hello(ConanFile):\n                def requirements(self):\n                    assert type(self.version) is str, \"Version should be a string\"\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --name=hello --version=0.1\")\n        # This used to trigger the assertion error\n        client.run(\"export-pkg . --name=hello --version=0.1\")\n\n    def test_export_pkg_json(self):\n        client = TestClient()\n        client.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n\n        # Wrong folders\n        client.run(\"export-pkg . --format=json\", redirect_stdout=\"exported.json\")\n        graph = json.loads(client.load(\"exported.json\"))\n        node = graph[\"graph\"][\"nodes\"][\"0\"]\n        assert \"pkg/0.1\" in node[\"ref\"]\n        # https://github.com/conan-io/conan/issues/15041\n        assert \"da39a3ee5e6b4b0d3255bfef95601890afd80709\" == node[\"package_id\"]\n        assert \"485dad6cb11e2fa99d9afbe44a57a164\" == node[\"rrev\"]\n        assert \"0ba8627bd47edc3a501e8f0eb9a79e5e\" == node[\"prev\"]\n        assert \"Build\" == node[\"binary\"]\n        assert node[\"rrev_timestamp\"] is not None\n        assert node[\"prev_timestamp\"] is not None\n\n        # Make sure the exported json file can be used for ``conan lsit --graph`` input to upload\n        client.run(\"list --graph=exported.json -gb=build --format=json\")\n        pkglist = json.loads(client.stdout)\n        revs = pkglist[\"Local Cache\"][\"pkg/0.1\"][\"revisions\"][\"485dad6cb11e2fa99d9afbe44a57a164\"]\n        assert \"da39a3ee5e6b4b0d3255bfef95601890afd80709\" in revs[\"packages\"]\n\n    def test_export_pkg_no_ref(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.files import copy\n            class TestConan(ConanFile):\n                name = \"hello\"\n                version = \"0.1\"\n\n                def package(self):\n                    copy(self, \"*.h\", os.path.join(self.source_folder, \"src\"),\n                         os.path.join(self.package_folder, \"include\"))\n            \"\"\")\n        client.save({CONANFILE: conanfile,\n                     \"src/header.h\": \"contents\"})\n        client.run(\"export-pkg . -s os=Windows\")\n        package_folder = client.created_layout().package()\n        header = os.path.join(package_folder, \"include/header.h\")\n        assert os.path.exists(header)\n\n\ndef test_build_policy_never():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import copy\n        class TestConan(ConanFile):\n            build_policy = \"never\"\n\n            def package(self):\n                copy(self, \"*.h\", os.path.join(self.source_folder, \"src\"),\n                     os.path.join(self.package_folder, \"include\"))\n        \"\"\")\n    client.save({CONANFILE: conanfile,\n                 \"src/header.h\": \"contents\"})\n    client.run(\"export-pkg . --name=pkg --version=1.0\")\n    assert \"conanfile.py (pkg/1.0): package(): Packaged 1 '.h' file: header.h\" in client.out\n    # check for https://github.com/conan-io/conan/issues/10736\n    client.run(\"export-pkg . --name=pkg --version=1.0\")\n    assert \"conanfile.py (pkg/1.0): package(): Packaged 1 '.h' file: header.h\" in client.out\n    client.run(\"install --requires=pkg/1.0@ --build='*'\")\n    client.assert_listed_require({\"pkg/1.0\": \"Cache\"})\n    assert \"conanfile.py (pkg/1.0): Calling build()\" not in client.out\n\n\ndef test_build_policy_never_missing():\n    # https://github.com/conan-io/conan/issues/9798\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile().with_class_attribute('build_policy = \"never\"'),\n                 \"consumer.txt\": \"[requires]\\npkg/1.0\"})\n    client.run(\"export . --name=pkg --version=1.0\")\n    client.run(\"install --requires=pkg/1.0@ --build='*'\", assert_error=True)\n    assert \"ERROR: Missing binary: pkg/1.0\" in client.out\n\n    client.run(\"install --requires=pkg/1.0@ --build=missing\", assert_error=True)\n    assert \"ERROR: Missing binary: pkg/1.0\" in client.out\n\n\ndef test_export_pkg_json_formatter():\n    \"\"\"\n    Tests the ``conan export-pkg . -f json`` result\n    \"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class MyTest(ConanFile):\n            name = \"pkg\"\n            version = \"0.2\"\n\n            def package_info(self):\n                self.cpp_info.libs = [\"pkg\"]\n                self.cpp_info.includedirs = [\"path/includes/pkg\", \"other/include/path/pkg\"]\n                self.cpp_info.libdirs = [\"one/lib/path/pkg\"]\n                self.cpp_info.defines = [\"pkg_onedefinition\", \"pkg_twodefinition\"]\n                self.cpp_info.cflags = [\"pkg_a_c_flag\"]\n                self.cpp_info.cxxflags = [\"pkg_a_cxx_flag\"]\n                self.cpp_info.sharedlinkflags = [\"pkg_shared_link_flag\"]\n                self.cpp_info.exelinkflags = [\"pkg_exe_link_flag\"]\n                self.cpp_info.sysroot = \"/path/to/folder/pkg\"\n                self.cpp_info.frameworks = [\"pkg_oneframework\", \"pkg_twoframework\"]\n                self.cpp_info.system_libs = [\"pkg_onesystemlib\", \"pkg_twosystemlib\"]\n                self.cpp_info.frameworkdirs = [\"one/framework/path/pkg\"]\n                self.cpp_info.set_property(\"pkg_config_name\", \"pkg_other_name\")\n                self.cpp_info.set_property(\"pkg_config_aliases\", [\"pkg_alias1\", \"pkg_alias2\"])\n                self.cpp_info.components[\"cmp1\"].libs = [\"libcmp1\"]\n                self.cpp_info.components[\"cmp1\"].set_property(\"pkg_config_name\", \"compo1\")\n                self.cpp_info.components[\"cmp1\"].set_property(\"pkg_config_aliases\", [\"compo1_alias\"])\n                self.cpp_info.components[\"cmp1\"].sysroot = \"/another/sysroot\"\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create .\")\n    client.save({\"conanfile.py\": GenConanfile().with_name(\"hello\").with_version(\"0.1\")\n                .with_require(\"pkg/0.2\")}, clean_first=True)\n    client.run(\"export-pkg . -f json\")\n    info = json.loads(client.stdout)\n    nodes = info[\"graph\"][\"nodes\"]\n    hello_pkg_ref = 'hello/0.1#18d5440ae45afc4c36139a160ac071c7'\n    pkg_pkg_ref = 'pkg/0.2#926714b5fb0a994f47ec37e071eba1da'\n    hello_cpp_info = pkg_cpp_info = None\n    for n in nodes.values():\n        ref = n[\"ref\"]\n        if ref == hello_pkg_ref:\n            assert n['binary'] == \"Build\"\n            hello_cpp_info = n['cpp_info']\n        elif ref == pkg_pkg_ref:\n            assert n['binary'] == \"Cache\"\n            pkg_cpp_info = n['cpp_info']\n    assert hello_cpp_info and pkg_cpp_info\n    # hello/0.1 cpp_info\n    assert hello_cpp_info['root'][\"libs\"] is None\n    assert len(hello_cpp_info['root'][\"bindirs\"]) == 1\n    assert len(hello_cpp_info['root'][\"libdirs\"]) == 1\n    assert hello_cpp_info['root'][\"sysroot\"] is None\n    assert hello_cpp_info['root'][\"properties\"] is None\n    # pkg/0.2 cpp_info\n    # root info\n\n    assert pkg_cpp_info['root'][\"libs\"] == ['pkg']\n    assert len(pkg_cpp_info['root'][\"bindirs\"]) == 1\n    assert len(pkg_cpp_info['root'][\"libdirs\"]) == 1\n    assert pkg_cpp_info['root'][\"sysroot\"] == '/path/to/folder/pkg'\n    assert pkg_cpp_info['root'][\"system_libs\"] == ['pkg_onesystemlib', 'pkg_twosystemlib']\n    assert pkg_cpp_info['root']['cflags'] == ['pkg_a_c_flag']\n    assert pkg_cpp_info['root']['cxxflags'] == ['pkg_a_cxx_flag']\n    assert pkg_cpp_info['root']['defines'] == ['pkg_onedefinition', 'pkg_twodefinition']\n    assert pkg_cpp_info['root'][\"properties\"] == {'pkg_config_name': 'pkg_other_name',\n                                                  'pkg_config_aliases': ['pkg_alias1', 'pkg_alias2']}\n    # component info\n    assert pkg_cpp_info[\"cmp1\"][\"libs\"] == [\"libcmp1\"]\n\n\ndef test_export_pkg_dont_update_src():\n    \"\"\"\n    There was a bug in 1.X and sources were not updated correctly in export-pkg\n    close https://github.com/conan-io/conan/issues/6041\n    \"\"\"\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import load\n        class Hello(ConanFile):\n            name = \"hello\"\n            version = \"0.1\"\n            exports_sources = \"*.cpp\"\n            def build(self):\n                content = load(self, \"src/hello.cpp\")\n                self.output.info(\"CONTENT: {}\".format(content))\n        \"\"\")\n\n    c.save({\"conanfile.py\": conanfile,\n            \"src/hello.cpp\": \"old code!\"})\n    c.run(\"install .\")\n    c.run(\"build .\")\n    c.run(\"export-pkg .\")\n    c.run(\"install --requires=hello/0.1@ --build=hello*\")\n    assert \"hello/0.1: CONTENT: old code!\" in c.out\n    # Now locally change the source code\n    c.save({\"src/hello.cpp\": \"updated code!\"})\n    c.run(\"install .\")\n    c.run(\"build .\")\n    c.run(\"export-pkg .\")\n    c.run(\"install --requires=hello/0.1@ --build=hello*\")\n    assert \"hello/0.1: CONTENT: updated code!\" in c.out\n\n\ndef test_negate_tool_requires():\n    c = TestClient()\n    profile = textwrap.dedent(\"\"\"\n        [tool_requires]\n        !mypkg/*:cmake/3.24\n        \"\"\")\n    c.save({\"myprofile\": profile,\n            \"conanfile.py\": GenConanfile(\"mypkg\", \"0.1\")})\n    c.run(\"export-pkg . -pr=myprofile\")\n    assert \"conanfile.py (mypkg/0.1): Created package\" in c.out\n\n\ndef test_export_pkg_tool_requires():\n    \"\"\" when a package has \"tool_requires\" that it needs at the package() method, like\n    typical cmake.install() or autotools.install() (tool_require msys2), then it is necessary:\n    - to install the dependencies\n    - to inject the tool-requirements\n    - to propagate the environment and the conf\n    \"\"\"\n    c = TestClient(default_server_user=True)\n    tool = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Tool(ConanFile):\n            name = \"tool\"\n            version = \"0.1\"\n            def package_info(self):\n                self.buildenv_info.define(\"MYVAR\", \"MYVALUE\")\n                self.conf_info.define(\"user.team:conf\", \"CONF_VALUE\")\n            \"\"\")\n    consumer = textwrap.dedent(\"\"\"\n        import platform\n        from conan import ConanFile\n\n        class Consumer(ConanFile):\n            name = \"consumer\"\n            version = \"0.1\"\n            tool_requires = \"tool/0.1\"\n            def package(self):\n                self.output.info(f\"MYCONF {self.conf.get('user.team:conf')}\")\n                cmd = \"set MYVAR\" if platform.system() == \"Windows\" else \"echo MYVAR=$MYVAR\"\n                self.run(cmd)\n            \"\"\")\n    c.save({\"tool/conanfile.py\": tool,\n            \"consumer/conanfile.py\": consumer})\n\n    c.run(\"create tool\")\n    c.run(\"export-pkg consumer\")\n    assert \"conanfile.py (consumer/0.1): MYCONF CONF_VALUE\" in c.out\n    assert \"MYVAR=MYVALUE\" in c.out\n    c.run(\"upload tool* -r=default -c\")\n    c.run(\"remove tool* -c\")\n    c.run(\"export-pkg consumer\")\n    assert \"conanfile.py (consumer/0.1): MYCONF CONF_VALUE\" in c.out\n    assert \"MYVAR=MYVALUE\" in c.out\n\n\ndef test_export_pkg_output_folder():\n    \"\"\" If the local build is using a different output-folder, it should work and export it\n    \"\"\"\n    c = TestClient()\n    consumer = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import save, copy\n\n        class Consumer(ConanFile):\n            name = \"consumer\"\n            version = \"0.1\"\n\n            def build(self):\n                save(self, \"myfile.txt\", \"\")\n            def package(self):\n                copy(self, \"*\", src=self.build_folder, dst=self.package_folder)\n            \"\"\")\n    c.save({\"conanfile.py\": consumer})\n\n    c.run(\"build . -of=mytmp\")\n    c.run(\"export-pkg . -of=mytmp\")\n    assert \"Packaged 1 '.txt' file: myfile.txt\" in c.out\n    assert os.path.exists(os.path.join(c.current_folder, \"mytmp\", \"myfile.txt\"))\n\n\ndef test_export_pkg_test_package():\n    \"\"\" If there is a test_package, run it\n    \"\"\"\n    c = TestClient()\n    test_conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Test(ConanFile):\n            def requirements(self):\n                self.requires(self.tested_reference_str)\n            def test(self):\n                self.output.info(\"RUN TEST PACKAGE!!!!\")\n            \"\"\")\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\"),\n            \"test_package/conanfile.py\": test_conanfile})\n\n    c.run(\"export-pkg . \")\n    assert \"test_package\" in c.out\n    assert \"RUN TEST PACKAGE!!!!\" in c.out\n\n    c.run('export-pkg . -tf=\"\"')\n    assert \"test_package\" not in c.out\n    assert \"RUN TEST\" not in c.out\n\n\ndef test_export_pkg_test_package_build_require():\n    \"\"\" Test --build-require\n    \"\"\"\n    c = TestClient()\n    test_conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Test(ConanFile):\n            def build_requirements(self):\n                self.tool_requires(self.tested_reference_str)\n            def test(self):\n                self.output.info(f\"RUN TEST PACKAGE!!!!\")\n            \"\"\")\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_setting(\"os\"),\n            \"test_package/conanfile.py\": test_conanfile})\n\n    c.run(\"export-pkg . -s:b os=Windows -s:h os=Linux --build-require --lockfile-out=conan.lock\")\n    assert \"test_package\" in c.out\n    assert \"RUN TEST PACKAGE!!!!\" in c.out\n    lock = json.loads(c.load(\"conan.lock\"))\n    assert \"pkg/1.0\" in lock[\"build_requires\"][0]\n\n\ndef test_export_pkg_remote_python_requires():\n    \"\"\" Test that remote python-requires can be resolved\n    \"\"\"\n    c = TestClient(default_server_user=True)\n    c.save({\"tool/conanfile.py\": GenConanfile(\"tool\", \"1.0\"),\n            \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_python_requires(\"tool/1.0\")})\n\n    c.run(\"create tool\")\n    c.run(\"upload tool* -r=default -c\")\n    c.run(\"remove * -c\")\n    c.run(\"export-pkg pkg\")\n    assert \"conanfile.py (pkg/1.0): Exported package binary\" in c.out\n\n\ndef test_remote_none():\n    # https://github.com/conan-io/conan/pull/14705\n    c = TestClient(default_server_user=True)\n    c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\"),\n            \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\"),\n            \"pkg/test_package/conanfile.py\": GenConanfile().with_test(\"pass\").with_requires(\"dep/0.1\")})\n    c.run(\"create dep\")\n    c.run(\"upload dep* -r=default -c\")\n    c.run(\"build pkg\")\n    c.run(\"remove dep*:* -c\")\n    c.run(\"export-pkg pkg\")    # This used to crash\n    # No longer crash\n    assert \"pkg/0.1 (test package): Running test()\" in c.out\n\n\ndef test_remote_none_tool_requires():\n    # https://github.com/conan-io/conan/pull/14705\n    c = TestClient(default_server_user=True)\n    c.save({\"tool/conanfile.py\": GenConanfile(\"tool\", \"0.1\").with_settings(\"compiler\"),\n            \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_tool_requires(\"tool/0.1\"),\n            \"pkg/test_package/conanfile.py\": GenConanfile().with_test(\"pass\")})\n    settings = \"-s:b compiler=gcc -s:b compiler.version=9 -s:b compiler.libcxx=libstdc++11\"\n    c.run(f\"create tool {settings} -s:b compiler.cppstd=20 --build-require\")\n    c.run(f\"build pkg {settings} -s:b compiler.cppstd=17\")\n    c.run(f\"export-pkg pkg {settings} -s:b compiler.cppstd=17\")  # This used to crash\n    # No longer crash\n    assert \"pkg/0.1 (test package): Running test()\" in c.out\n\n\ndef test_export_pkg_set_version_python_requires():\n    # https://github.com/conan-io/conan/issues/16223\n    c = TestClient(light=True)\n    py_require = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class TestBuild:\n            def set_version(self):\n                assert self.version\n\n        class TestModule(ConanFile):\n            name = \"pyreq\"\n            version = \"0.1\"\n            package_type = \"python-require\"\n    \"\"\")\n    pkg = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class TestPkgConan(ConanFile):\n            name=\"testpkg\"\n            python_requires = \"pyreq/0.1\"\n            python_requires_extend = \"pyreq.TestBuild\"\n        \"\"\")\n    c.save({\"pyreq/conanfile.py\": py_require,\n            \"pkg/conanfile.py\": pkg})\n\n    c.run(\"create pyreq\")\n    c.run(\"export-pkg pkg --version=1.0+0\")\n    assert \"conanfile.py (testpkg/1.0+0): Exported package binary\" in c.out\n"
  },
  {
    "path": "test/integration/command/help_test.py",
    "content": "from unittest.mock import patch\n\nfrom conan import __version__\nfrom conan.test.utils.env import environment_update\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestHelp:\n\n    def test_version(self):\n        c = TestClient()\n        c.run(\"--version\")\n        assert \"Conan version %s\" % __version__ in c.out\n\n    def test_unknown_command(self):\n        c = TestClient()\n        c.run(\"some_unknown_command123\", assert_error=True)\n        assert \"'some_unknown_command123' is not a Conan command\" in c.out\n\n    def test_similar(self):\n        c = TestClient()\n        c.run(\"instal\", assert_error=True)\n        assert \"The most similar command is\" in c.out\n        assert \"install\" in c.out\n\n        c.run(\"remole\", assert_error=True)\n        assert \"The most similar commands are\" in c.out\n        assert \"remove\" in c.out\n        assert \"remote\" in c.out\n\n    def test_help(self):\n        c = TestClient()\n        c.run(\"-h\")\n        assert \"Creator commands\" in c.out\n        assert \"Consumer commands\" in c.out\n\n    def test_help_command(self):\n        c = TestClient()\n        c.run(\"new -h\")\n        assert \"Create a new example recipe\" in c.out\n\n    def test_help_subcommand(self):\n        c = TestClient()\n        c.run(\"cache -h\")\n        # When listing subcommands, but line truncated\n        assert \"Perform file operations in the local cache (of recipes and/or packages)\" in c.out\n        c.run(\"cache path -h\")\n        assert \"Show the path to the Conan cache for a given reference\" in c.out\n\n\ndef test_all_commands_call_args_parse():\n    tc = TestClient(light=True)\n    tc.run(\"-h\")\n    commands = tc.api.command.cli._builtin_commands\n    with environment_update({\"CONAN_WORKSPACE_ENABLE\": \"will_break_next\"}):\n        for command, info in commands.items():\n            if len(info._subcommands) > 0:\n                for subcommand in info._subcommands.values():\n                    with patch(\"conan.cli.command.ConanArgumentParser.parse_args\",\n                               side_effect=Exception(\"called\")) as mock_run:\n                        try:\n                            tc.run(f\"{command} {subcommand.name} -h\")\n                        except:\n                            pass\n                        finally:\n                            assert mock_run.called, f'Command \"conan {command} {subcommand.name}\" did not call parse_args()'\n            else:\n                with patch(\"conan.cli.command.ConanArgumentParser.parse_args\",\n                           side_effect=Exception(\"called\")) as mock_run:\n                    try:\n                        tc.run(f\"{command} -h\")\n                    except:\n                        pass\n                    finally:\n                        assert mock_run.called, f'Command \"conan {command}\" did not call parse_args()'\n"
  },
  {
    "path": "test/integration/command/info/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/command/info/info_options_test.py",
    "content": "from conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_info_options():\n    # packages with dash\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile(\"my-package\", \"1.3\")\n                .with_option(\"shared\", [True, False])\n                .with_default_option(\"shared\", False)})\n\n    # local\n    client.run(\"graph info .\")\n    assert \"shared: False\" in client.out\n    client.run(\"graph info . -o shared=True\")\n    assert \"shared: True\" in client.out\n    client.run(\"graph info . -o my-package*:shared=True\")\n    assert \"shared: True\" in client.out\n\n    # in cache\n    client.run(\"export .\")\n    client.run(\"graph info --requires=my-package/1.3\")\n    assert \"shared: False\" in client.out\n    client.run(\"graph info --requires=my-package/1.3 -o shared=True\")\n    assert \"shared: True\" in client.out\n    client.run(\"graph info --requires=my-package/1.3 -o my-package*:shared=True\")\n    assert \"shared: True\" in client.out\n\n"
  },
  {
    "path": "test/integration/command/info/info_test.py",
    "content": "import json\nimport os\nimport textwrap\n\nfrom conan.cli.exit_codes import ERROR_GENERAL\nfrom conan.test.utils.tools import NO_SETTINGS_PACKAGE_ID, TestClient, GenConanfile\n\n\nclass TestBasicCliOutput:\n\n    def test_info_settings(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class MyTest(ConanFile):\n                name = \"pkg\"\n                version = \"0.2\"\n                settings = \"build_type\", \"compiler\"\n                author = \"John Doe\"\n                license = \"MIT\"\n                url = \"https://foo.bar.baz\"\n                homepage = \"https://foo.bar.site\"\n                topics = \"foo\", \"bar\", \"qux\"\n                provides = \"libjpeg\", \"libjpg\"\n                deprecated = \"other-pkg\"\n                options = {\"shared\": [True, False], \"fPIC\": [True, False]}\n                default_options = {\"shared\": False, \"fPIC\": True}\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"graph info . -s build_type=Debug -s compiler=gcc -s compiler.version=11\")\n        assert \"build_type: Debug\" in client.out\n        assert \"context: host\" in client.out\n        assert \"license: MIT\" in client.out\n        assert \"homepage: https://foo.bar.site\" in client.out\n        assert \"compiler: gcc\" in client.out\n        assert \"compiler.version: 11\" in client.out\n        assert \"prev: None\" in client.out\n        assert \"fPIC: True\" in client.out\n        assert \"shared: False\" in client.out\n        # Create the package\n        client.run(\"create .\")\n        pref = client.get_latest_package_reference(\"pkg/0.2\")\n        client.run(\"graph info .\")\n        # It's a consumer so we can not get the prev because it's not even a package yet\n        assert \"prev: None\" in client.out\n        # Now, let's create another consumer requiring the previous package\n        client.save({\"conanfile.txt\": \"[requires]\\npkg/0.2\"}, clean_first=True)\n        client.run(\"graph info .\")\n        assert textwrap.dedent(f\"\"\"\n            {repr(pref.ref)}:\n              ref: {repr(pref.ref)}\n              id: 1\n              recipe: Cache\n              package_id: {pref.package_id}\n              prev: {pref.revision}\"\"\") in client.out\n\n    def test_nontuple_topics(self):\n        client = TestClient()\n        # This is the representation that should always happen,\n        # we wouldn't expect topics not to be a tuple here\n        conanfile = textwrap.dedent(\"\"\"\n                            from conan import ConanFile\n\n                            class MyTest(ConanFile):\n                                name = \"pkg\"\n                                version = \"0.2\"\n                                provides = (\"bar\",)\n                                topics = (\"foo\",)\n                            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"graph info . --format=json\")\n        recipe = json.loads(client.stdout)[\"graph\"][\"nodes\"][\"0\"]\n        assert type(recipe[\"topics\"]) is list\n        assert recipe[\"topics\"] == [\"foo\"]\n        assert type(recipe[\"provides\"]) is list\n        assert recipe[\"provides\"] == [\"bar\"]\n\n        # But this used to fail,\n        # topics were not converted to a list internally if one was not provided\n        client2 = TestClient()\n        conanfile2 = textwrap.dedent(\"\"\"\n                    from conan import ConanFile\n\n                    class MyTest(ConanFile):\n                        name = \"pkg\"\n                        version = \"0.2\"\n                        provides = \"bar\"\n                        topics = \"foo\"\n                    \"\"\")\n        client2.save({\"conanfile.py\": conanfile2})\n        client2.run(\"graph info . --format=json\")\n        recipe = json.loads(client2.stdout)[\"graph\"][\"nodes\"][\"0\"]\n        assert type(recipe[\"topics\"]) is list\n        assert recipe[\"topics\"] == [\"foo\"]\n        assert type(recipe[\"provides\"]) is list\n        assert recipe[\"provides\"] == [\"bar\"]\n\n\nclass TestConanfilePath:\n    def test_cwd(self):\n        # Check the first positional argument is a relative path\n        client = TestClient()\n        conanfile = GenConanfile(\"pkg\", \"0.1\").with_setting(\"build_type\")\n        client.save({\"subfolder/conanfile.py\": conanfile})\n        client.run(\"graph info ./subfolder -s build_type=Debug\")\n        assert \"build_type: Debug\" in client.out\n\n    def test_wrong_path_parameter(self):\n        # check that the positional parameter must exist and file must be found\n        client = TestClient()\n\n        client.run(\"graph info\", assert_error=True)\n        assert \"ERROR: Conanfile not found\" in client.out\n\n        client.run(\"graph info not_real_path\", assert_error=True)\n        assert \"ERROR: Conanfile not found\" in client.out\n\n        client.run(\"graph info conanfile.txt\", assert_error=True)\n        assert \"ERROR: Conanfile not found\" in client.out\n\n        client.run(\"graph info --requires=foo/1.0\", assert_error=True)\n        assert \"ERROR: Package 'foo/1.0' not resolved: No remote defined.\" in client.out\n\n        client.run(\"graph info . --requires=foo/1.0\", assert_error=True)\n        assert (\"--requires and --tool-requires arguments are incompatible \"\n                \"with [path] '.' argument\") in client.out\n\n\nclass TestFilters:\n\n    def test_filter_fields(self):\n        # The --filter arg should work, specifying which fields to show only\n        c = TestClient()\n        c.save({\"conanfile.py\": GenConanfile()\n               .with_class_attribute(\"author = 'myself'\")\n               .with_class_attribute(\"license = 'MIT'\")\n               .with_class_attribute(\"url = 'https://url.com'\")})\n        c.run(\"graph info . \")\n        assert \"license: MIT\" in c.out\n        assert \"author: myself\" in c.out\n        c.run(\"graph info . --filter=license\")\n        assert \"license: MIT\" in c.out\n        assert \"author\" not in c.out\n        c.run(\"graph info . --filter=author\")\n        assert \"license\" not in c.out\n        assert \"author: myself\" in c.out\n        c.run(\"graph info . --filter=author --filter=license\")\n        assert \"license\" in c.out\n        assert \"author: myself\" in c.out\n\n    def test_filter_fields_json(self):\n        # The --filter arg should work, specifying which fields to show only\n        c = TestClient()\n        c.save({\"conanfile.py\": GenConanfile()\n               .with_class_attribute(\"author = 'myself'\")\n               .with_class_attribute(\"license = 'MIT'\")\n               .with_class_attribute(\"url = 'https://url.com'\")})\n        c.run(\"graph info . --filter=license --format=json\")\n        assert \"author\" not in c.out\n        assert '\"license\": \"MIT\"' in c.out\n        c.run(\"graph info . --filter=license --format=html\", assert_error=True)\n        assert \"Formatted output 'html' cannot filter fields\" in c.out\n\n\nclass TestJsonOutput:\n    def test_json_package_filter(self):\n        client = TestClient()\n        conanfile = GenConanfile(\"pkg\", \"0.1\").with_setting(\"build_type\").with_requires(\"dep/0.1\")\n        client.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\"),\n                     \"conanfile.py\": conanfile})\n        client.run(\"create dep\")\n        client.run(\"graph info . --package-filter=nothing --format=json\")\n        assert '\"nodes\": {}' in client.out\n        client.run(\"graph info . --package-filter=pkg* --format=json\")\n        graph = json.loads(client.stdout)\n        assert len(graph[\"graph\"][\"nodes\"]) == 1\n        assert graph[\"graph\"][\"nodes\"][\"0\"][\"ref\"] == \"pkg/0.1\"\n\n        # Consumer & filtering\n        client.run(\"graph info . --package-filter=& --format=json\")\n        graph = json.loads(client.stdout)\n        assert len(graph[\"graph\"][\"nodes\"]) == 1\n        assert graph[\"graph\"][\"nodes\"][\"0\"][\"ref\"] == \"pkg/0.1\"\n\n        # This returns nothing, doesn't work that way, serialized graph doesn't have the consumer\n        client.run(\"graph info --requires=dep/0.1 --package-filter=& --format=json\")\n        graph = json.loads(client.stdout)\n        assert len(graph[\"graph\"][\"nodes\"]) == 1\n        assert graph[\"graph\"][\"nodes\"][\"1\"][\"name\"] == \"dep\"\n\n        # Filter matches all\n        client.run(\"graph info . --package-filter=* --format=json\")\n        graph = json.loads(client.stdout)\n        assert len(graph[\"graph\"][\"nodes\"]) == 2\n        assert graph[\"graph\"][\"nodes\"][\"0\"][\"ref\"] == \"pkg/0.1\"\n        assert graph[\"graph\"][\"nodes\"][\"1\"][\"name\"] == \"dep\"\n\n    def test_json_info_outputs(self):\n        client = TestClient()\n        conanfile = GenConanfile(\"pkg\", \"0.1\").with_setting(\"build_type\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"graph info . -s build_type=Debug --format=json\")\n        graph = json.loads(client.stdout)\n        assert graph[\"graph\"][\"nodes\"][\"0\"][\"settings\"][\"build_type\"] == \"Debug\"\n\n    def test_json_info_requirements(self):\n        c = TestClient()\n        c.save({\"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\"),\n                \"app/conanfile.py\": GenConanfile().with_require(\"pkg/[>=0.0 <1.0]\")})\n        c.run(\"create pkg\")\n        c.run(\"graph info app --format=json\")\n        graph = json.loads(c.stdout)\n        assert graph[\"graph\"][\"nodes\"][\"0\"][\"dependencies\"][\"1\"][\"require\"] == \"pkg/[>=0.0 <1.0]\"\n\n\nclass TestAdvancedCliOutput:\n    \"\"\" Testing more advanced fields output, like SCM or PYTHON-REQUIRES\n    \"\"\"\n\n    def test_python_requires(self):\n        # https://github.com/conan-io/conan/issues/9277\n        client = TestClient()\n        client.save({\"conanfile.py\": GenConanfile()})\n        client.run(\"export . --name=tool --version=0.1\")\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class pkg(ConanFile):\n                python_requires = \"tool/0.1\"\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n\n        client.run(\"graph info .\")\n        assert \"python_requires:\\n    tool/0.1#4d670581ccb765839f2239cc8dff8fbd\" in client.out\n\n        client.run(\"graph info . --format=json\")\n        info = json.loads(client.stdout)\n        pyrequires = info[\"graph\"][\"nodes\"][\"0\"][\"python_requires\"]\n        tool = pyrequires[\"tool/0.1#4d670581ccb765839f2239cc8dff8fbd\"]\n        info = info[\"graph\"][\"nodes\"][\"0\"][\"info\"]\n        assert info[\"python_requires\"] == [\"tool/0.1.Z\"]\n        # lets make sure the path exists\n        assert tool[\"recipe\"] == \"Cache\"\n        assert tool[\"remote\"] is None\n        assert os.path.exists(tool[\"path\"])\n\n    def test_build_id_info(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                settings = \"build_type\"\n\n                def build_id(self):\n                    self.info_build.settings.build_type = \"Any\"\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"export .\")\n        client.save({\"conanfile.py\": GenConanfile().with_requires(\"pkg/0.1\")}, clean_first=True)\n        client.run(\"graph info . -s build_type=Release\")\n        assert \"build_id: ec0cd314abe055f7de86cd6493e31977d2b87884\" in client.out\n        assert \"package_id: efa83b160a55b033c4ea706ddb980cd708e3ba1b\" in client.out\n\n        client.run(\"graph info . -s build_type=Debug\")\n        assert \"build_id: ec0cd314abe055f7de86cd6493e31977d2b87884\" in client.out\n        assert \"package_id: 9e186f6d94c008b544af1569d1a6368d8339efc5\" in client.out\n\n\nclass TestEditables:\n    def test_info_paths(self):\n        # https://github.com/conan-io/conan/issues/7054\n        c = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                def layout(self):\n                    self.folders.source = \".\"\n                    self.folders.build = \".\"\n            \"\"\")\n        c.save({\"pkg/conanfile.py\": conanfile,\n                \"consumer/conanfile.py\": GenConanfile().with_require(\"pkg/0.1\")})\n        c.run(\"editable add pkg --name=pkg --version=0.1\")\n        # TODO: Check this --package-filter with *\n        c.run(\"graph info consumer --package-filter=pkg*\")\n        # FIXME: Paths are not diplayed yet\n        assert \"source_folder: None\" in c.out\n\n\nclass TestInfoTestPackage:\n    # https://github.com/conan-io/conan/issues/10714\n\n    def test_tested_reference_str(self):\n        client = TestClient()\n        client.save({\"conanfile.py\": GenConanfile(\"tool\", \"0.1\")})\n        client.run(\"export .\")\n\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class HelloConan(ConanFile):\n\n                def requirements(self):\n                    self.requires(self.tested_reference_str)\n\n                def build_requirements(self):\n                    self.build_requires(self.tested_reference_str)\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n\n        for args in [\"\", \" --build=*\"]:\n            client.run(\"graph info . \" + args)\n            assert \"AttributeError: 'HelloConan' object has no attribute 'tested_reference_str'\"\\\n                   not in client.out\n\n\nclass TestDeployers:\n\n    def test_custom_deploy(self):\n        c = TestClient()\n        conanfile = GenConanfile(\"pkg\", \"0.1\").with_class_attribute(\"license = 'MIT'\")\n        c.save({\"conanfile.py\": conanfile})\n        c.run(\"create .\")\n        collectlicenses = textwrap.dedent(r\"\"\"\n            from conan.tools.files import save\n\n            def deploy(graph, output_folder, **kwargs):\n                contents = []\n                conanfile = graph.root.conanfile\n                for pkg in graph.nodes:\n                    d = pkg.conanfile\n                    contents.append(\"LICENSE {}: {}!\".format(d.ref, d.license))\n                contents = \"\\n\".join(contents)\n                conanfile.output.info(contents)\n                save(conanfile, \"licenses.txt\", contents)\n            \"\"\")\n        c.save({\"conanfile.py\": GenConanfile().with_requires(\"pkg/0.1\")\n                                              .with_class_attribute(\"license='GPL'\"),\n                \"collectlicenses.py\": collectlicenses})\n        c.run(\"graph info . --deployer=collectlicenses\")\n        assert \"conanfile.py: LICENSE : GPL!\" in c.out\n        assert \"LICENSE pkg/0.1: MIT!\" in c.out\n        contents = c.load(\"licenses.txt\")\n        assert \"LICENSE pkg/0.1: MIT!\" in contents\n        assert \"LICENSE : GPL!\" in contents\n\n\nclass TestErrorsInGraph:\n    # https://github.com/conan-io/conan/issues/12735\n\n    def test_error_in_recipe(self):\n        c = TestClient()\n        dep = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                name = \"dep\"\n                version = \"0.1\"\n                def package_id(self):\n                    a = b\n            \"\"\")\n        c.save({\"dep/conanfile.py\": dep,\n                \"consumer/conanfile.py\": GenConanfile().with_requires(\"dep/0.1\")})\n        c.run(\"export dep\")\n        exit_code = c.run(\"graph info consumer\", assert_error=True)\n        assert \"name 'b' is not defined\" in c.out\n        assert exit_code == ERROR_GENERAL\n\n    def test_error_exports(self):\n        c = TestClient()\n        dep = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import replace_in_file\n            class Pkg(ConanFile):\n                name = \"dep\"\n                version = \"0.1\"\n                def export(self):\n                    replace_in_file(self, \"conanfile.py\", \"from conan\", \"from conans\")\n            \"\"\")\n        c.save({\"dep/conanfile.py\": dep,\n                \"consumer/conanfile.py\": GenConanfile().with_requires(\"dep/0.1\")})\n        c.run(\"export dep\")\n        exit_code = c.run(\"graph info consumer\", assert_error=True)\n        assert \"ERROR: Package 'dep/0.1' not resolved: dep/0.1: Cannot load\" in c.out\n        assert exit_code == ERROR_GENERAL\n\n    def test_missing_invalid(self):\n        c = TestClient()\n        dep_invalid = textwrap.dedent(\n            \"\"\"\n           from conan import ConanFile\n           from conan.errors import ConanInvalidConfiguration\n           class Pkg(ConanFile):\n               name = \"dep_invalid\"\n               settings = \"os\", \"build_type\"\n               version = \"0.1\"\n               def validate(self):\n                   raise ConanInvalidConfiguration(\"Invalid package\")\n        \"\"\"\n        )\n\n        c.save({\n                \"dep/conanfile.py\": GenConanfile(\"dep\").with_version(\"0.1\"),\n                \"dep_invalid/conanfile.py\": dep_invalid,\n                \"consumer/conanfile.py\": GenConanfile(\"consumer\").with_requires(\"dep/0.1\")\n                                                                 .with_requires(\"dep_invalid/0.1\"),\n            })\n        c.run(\"export dep\")\n        c.run(\"export dep_invalid\")\n        exit_code = c.run(\"graph info consumer\")\n        assert \"WARN: There are some error(s) in the graph:\" in c.out\n        assert \"- Missing packages: dep\" in c.out\n        assert \"- Invalid packages: dep_invalid\" in c.out\n        assert exit_code == 0\n\n\nclass TestInfoUpdate:\n\n    def test_update(self):\n        c = TestClient(default_server_user=True)\n        c.save({\"conanfile.py\": GenConanfile(\"tool\")})\n        c.run(\"create . --version=1.0\")\n        c.run(\"create . --version=1.1\")\n        c.run(\"upload tool/1.1 -r=default -c\")\n        c.run(\"remove tool/1.1 -c\")\n        c.save({\"conanfile.py\": GenConanfile().with_requires(\"tool/[*]\")})\n        c.run(\"graph info . --filter=recipe\")\n        assert \"tool/1.0#7fbd52996f34447f4a4c362edb5b4af5 - Cache\" in c.out\n        c.run(\"graph info . --update --filter=recipe\")\n        assert \"tool/1.1#7fbd52996f34447f4a4c362edb5b4af5 - Downloaded (default)\" in c.out\n\n\ndef test_info_not_hit_server():\n    \"\"\"\n    the command graph info shouldn't be hitting the server if packages are in the Conan cache\n    :return:\n    \"\"\"\n    c = TestClient(default_server_user=True)\n    c.save({\"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\"),\n            \"consumer/conanfile.py\": GenConanfile(\"consumer\", \"0.1\").with_require(\"pkg/0.1\")})\n    c.run(\"create pkg\")\n    c.run(\"create consumer\")\n    c.run(\"upload * -r=default -c\")\n    c.run(\"remove * -c\")\n    c.run(\"install --requires=consumer/0.1@\")\n    assert \"Downloaded\" in c.out\n    # break the server to make sure it is not being contacted at all\n    c.servers[\"default\"] = None\n    c.run(\"graph info --requires=consumer/0.1@\")\n    assert \"Downloaded\" not in c.out\n    # Now we remove the local, so it will raise errors\n    c.run(\"remove pkg* -c\")\n    c.run(\"graph info --requires=consumer/0.1@\", assert_error=True)\n    assert \"'NoneType' object \" in c.out\n    c.run(\"remote disable *\")\n    c.run(\"graph info --requires=consumer/0.1@\", assert_error=True)\n    assert \"'NoneType' object \" not in c.out\n    assert \"No remote defined\" in c.out\n\n\ndef test_graph_info_user():\n    \"\"\"\n    https://github.com/conan-io/conan/issues/15791\n    \"\"\"\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            user = \"user\"\n        \"\"\")\n\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"graph info .\")\n    assert \"pkg/0.1@user\" in c.out\n    c.run(\"graph info . --channel=channel\")\n    assert \"pkg/0.1@user/channel\" in c.out\n\n\ndef test_graph_info_bundle():\n    c = TestClient(light=True)\n    c.save({\"subfolder/conanfile.py\": GenConanfile(\"liba\", \"1.0\")})\n    c.run(\"create ./subfolder\")\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class RepackageRecipe(ConanFile):\n            name = \"lib\"\n            version = \"1.0\"\n            def requirements(self):\n                self.requires(\"liba/1.0\")\n            vendor = True\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"create .\")\n    c.save({\"conanfile.py\": GenConanfile(\"consumer\", \"1.0\").with_requires(\"lib/1.0\")})\n\n    c.run(\"graph info . --build='lib*'\")\n    c.assert_listed_binary({\"lib/1.0\": (NO_SETTINGS_PACKAGE_ID, \"Invalid\")})\n\n    c.run(\"graph info . -c tools.graph:vendor=build --build='lib*'\")\n    c.assert_listed_binary({\"lib/1.0\": (NO_SETTINGS_PACKAGE_ID, \"Build\")})\n\n\ndef test_graph_info_provides_conflict_html():\n    \"\"\" This test also makes sure that the serialization of the GraphProvidesConflict works\"\"\"\n    tc = TestClient(light=True)\n    tc.save({\"bar/conanfile.py\": GenConanfile(\"bar\", \"1.0\"),\n             \"foo/conanfile.py\": GenConanfile(\"foo\", \"1.0\").with_provides(\"bar\")})\n\n    tc.run(\"export bar\")\n    tc.run(\"export foo\")\n    tc.run(\"graph info --requires=bar/1.0 --requires=foo/1.0 --format=html\", assert_error=True)\n    # It got properly serialized\n    assert '\"type\": \"provide_conflict\"' in tc.out\n    assert \"Both 'bar/1.0' and 'foo/1.0' provide '['bar']'\"\n"
  },
  {
    "path": "test/integration/command/info/test_graph_info_graphical.py",
    "content": "import os\nimport textwrap\n\nfrom conan.test.utils.tools import TestClient, GenConanfile\n\n\nclass TestInfo:\n\n    def _create(self, name, version, deps=None, export=True):\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class pkg(ConanFile):\n                name = \"{name}\"\n                version = \"{version}\"\n                license = {license}\n                description = \"blah\"\n                url = \"myurl\"\n                {requires}\n            \"\"\")\n        requires = \"\"\n        if deps:\n            requires = \"requires = {}\".format(\", \".join('\"{}\"'.format(d) for d in deps))\n\n        conanfile = conanfile.format(name=name, version=version, requires=requires,\n                                     license='\"MIT\"')\n\n        self.client.save({\"conanfile.py\": conanfile}, clean_first=True)\n        if export:\n            self.client.run(\"export . --user=lasote --channel=stable\")\n\n    def test_graph(self):\n        self.client = TestClient()\n\n        test_deps = {\n            \"hello0\": [\"hello1\", \"hello2\", \"hello3\"],\n            \"hello1\": [\"hello4\"],\n            \"hello2\": [],\n            \"hello3\": [\"hello7\"],\n            \"hello4\": [\"hello5\", \"hello6\"],\n            \"hello5\": [],\n            \"hello6\": [],\n            \"hello7\": [\"hello8\"],\n            \"hello8\": [\"hello9\", \"hello10\"],\n            \"hello9\": [],\n            \"hello10\": [],\n        }\n\n        def create_export(testdeps, name):\n            deps = testdeps[name]\n            for dep in deps:\n                create_export(testdeps, dep)\n\n            expanded_deps = [\"%s/0.1@lasote/stable\" % dep for dep in deps]\n            export = False if name == \"hello0\" else True\n            self._create(name, \"0.1\", expanded_deps, export=export)\n\n        create_export(test_deps, \"hello0\")\n\n        # arbitrary case - file will be named according to argument\n        self.client.run(\"graph info . --format=dot\")\n        contents = self.client.stdout\n\n        expected = textwrap.dedent(\"\"\"\n            \"hello8/0.1@lasote/stable\" -> \"hello9/0.1@lasote/stable\"\n            \"hello8/0.1@lasote/stable\" -> \"hello10/0.1@lasote/stable\"\n            \"hello4/0.1@lasote/stable\" -> \"hello5/0.1@lasote/stable\"\n            \"hello4/0.1@lasote/stable\" -> \"hello6/0.1@lasote/stable\"\n            \"hello3/0.1@lasote/stable\" -> \"hello7/0.1@lasote/stable\"\n            \"hello7/0.1@lasote/stable\" -> \"hello8/0.1@lasote/stable\"\n            \"conanfile.py (hello0/0.1)\" -> \"hello1/0.1@lasote/stable\"\n            \"conanfile.py (hello0/0.1)\" -> \"hello2/0.1@lasote/stable\"\n            \"conanfile.py (hello0/0.1)\" -> \"hello3/0.1@lasote/stable\"\n            \"hello1/0.1@lasote/stable\" -> \"hello4/0.1@lasote/stable\"\n            \"\"\")\n        for line in expected.splitlines():\n            assert line in contents\n\n    def test_graph_html(self):\n        self.client = TestClient()\n\n        test_deps = {\n            \"hello0\": [\"hello1\"],\n            \"hello1\": [],\n        }\n\n        def create_export(testdeps, name):\n            deps = testdeps[name]\n            for dep in deps:\n                create_export(testdeps, dep)\n\n            expanded_deps = [\"%s/0.1@lasote/stable\" % dep for dep in deps]\n            export = False if name == \"hello0\" else True\n            self._create(name, \"0.1\", expanded_deps, export=export)\n\n        create_export(test_deps, \"hello0\")\n\n        # arbitrary case - file will be named according to argument\n        self.client.run(\"graph info . --format=html\")\n        html = self.client.stdout\n        # Just make sure it doesn't crash\n        assert \"<body>\" in html\n\n\ndef test_user_templates():\n    \"\"\" Test that a user can override the builtin templates putting templates/graph.html and\n    templates/graph.dot in the home\n    \"\"\"\n    c = TestClient()\n    c.save({'lib.py': GenConanfile(\"lib\", \"0.1\")})\n    c.run(\"create lib.py\")\n    template_folder = os.path.join(c.cache_folder, 'templates')\n    c.save({\"graph.html\": '{{ base_template_path }}',\n            \"graph.dot\": '{{ base_template_path }}'}, path=template_folder)\n    c.run(\"graph info --requires=lib/0.1 --format=html\")\n    assert template_folder in c.stdout\n    c.run(\"graph info --requires=lib/0.1 --format=dot\")\n    assert template_folder in c.stdout\n\n\ndef test_graph_info_html_error_reporting_output():\n    tc = TestClient()\n    tc.save({\"lib/conanfile.py\": GenConanfile(\"lib\"),\n             \"ui/conanfile.py\": GenConanfile(\"ui\", \"1.0\").with_requirement(\"lib/1.0\"),\n             \"math/conanfile.py\": GenConanfile(\"math\", \"1.0\").with_requirement(\"lib/2.0\")})\n    tc.run(\"export lib/ --version=1.0\")\n    tc.run(\"export lib/ --version=2.0\")\n    tc.run(\"export ui\")\n    tc.run(\"export math\")\n\n    tc.run(\"graph info --requires=math/1.0 --requires=ui/1.0 --format=html\", assert_error=True,\n           redirect_stdout=\"graph.html\")\n    assert \"ERROR: Version conflict:\" in tc.out  # check that it doesn't crash\n\n    # change order,  just in case\n    tc.run(\"graph info --requires=ui/1.0 --requires=math/1.0 --format=html\", assert_error=True,\n           redirect_stdout=\"graph.html\")\n    assert \"ERROR: Version conflict:\" in tc.out  # check that it doesn't crash\n\n    # direct conflict also doesn't crash\n    tc.run(\"graph info --requires=ui/1.0 --requires=lib/2.0 --format=html\", assert_error=True,\n           redirect_stdout=\"graph.html\")\n    assert \"ERROR: Version conflict:\" in tc.out  # check that it doesn't crash\n    # Check manually\n    # tc.run_command(f\"{tc.current_folder}/graph.html\")\n\n\ndef test_graph_conflict_diamond():\n    c = TestClient()\n    c.save({\"math/conanfile.py\": GenConanfile(\"math\"),\n            \"engine/conanfile.py\": GenConanfile(\"engine\", \"1.0\").with_requires(\"math/1.0\"),\n            \"ai/conanfile.py\": GenConanfile(\"ai\", \"1.0\").with_requires(\"math/1.0.1\"),\n            \"game/conanfile.py\": GenConanfile(\"game\", \"1.0\").with_requires(\"engine/1.0\", \"ai/1.0\"),\n            })\n    c.run(\"create math --version=1.0\")\n    c.run(\"create math --version=1.0.1\")\n    c.run(\"create math --version=1.0.2\")\n    c.run(\"create engine\")\n    c.run(\"create ai\")\n    c.run(\"graph info game --format=html\", assert_error=True, redirect_stdout=\"graph.html\")\n    # check that it doesn't crash\n    assert \"ERROR: Version conflict: Conflict between math/1.0.1 and math/1.0 in the graph.\" in c.out\n\n\ndef test_graph_conflict_loop():\n    c = TestClient(light=True)\n    c.save({\"lib_a/conanfile.py\": GenConanfile(\"lib_a\", \"1.0\").with_requires(\"lib_b/1.0\"),\n            \"lib_b/conanfile.py\": GenConanfile(\"lib_b\", \"1.0\").with_requires(\"lib_c/1.0\"),\n            \"lib_c/conanfile.py\": GenConanfile(\"lib_c\", \"1.0\").with_requires(\"lib_a/1.0\"),\n            \"lib_x/conanfile.py\": GenConanfile(\"lib_x\", \"1.0\").with_requires(\"lib_a/1.0\"),\n            })\n    c.run(\"export lib_a\")\n    c.run(\"export lib_b\")\n    c.run(\"export lib_c\")\n    c.run(\"graph info lib_x --format=html\", assert_error=True, redirect_stdout=\"graph.html\")\n    # checked manually\n    #c.open(\"graph.html\")\n\ndef test_graph_missing_error():\n    c = TestClient()\n    c.save({\"engine/conanfile.py\": GenConanfile(\"engine\", \"1.0\").with_requires(\"math/1.0\"),\n            \"game/conanfile.py\": GenConanfile(\"game\", \"1.0\").with_requires(\"engine/1.0\"),\n            })\n    c.run(\"export engine\")\n    c.run(\"graph info game --format=html\", assert_error=True, redirect_stdout=\"graph.html\")\n    # check that it doesn't crash, tested manually\n    assert \"ERROR: Package 'math/1.0' not resolved: No remote defined\" in c.out\n"
  },
  {
    "path": "test/integration/command/info/test_info_build_order.py",
    "content": "import json\nimport os\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_info_build_order():\n    c = TestClient()\n    c.save({\"dep/conanfile.py\": GenConanfile(),\n            \"pkg/conanfile.py\": GenConanfile().with_requires(\"dep/0.1\"),\n            \"consumer/conanfile.txt\": \"[requires]\\npkg/0.1\"})\n    c.run(\"export dep --name=dep --version=0.1\")\n    c.run(\"export pkg --name=pkg --version=0.1\")\n    c.run(\"graph build-order consumer --build=missing --format=json\")\n    bo_json = json.loads(c.stdout)\n\n    result = [\n        [\n            {\n                \"ref\": \"dep/0.1#4d670581ccb765839f2239cc8dff8fbd\",\n                \"depends\": [],\n                \"packages\": [[\n                    {\n                        \"package_id\": \"da39a3ee5e6b4b0d3255bfef95601890afd80709\",\n                        'prev': None,\n                        'filenames': [],\n                        'info': {},\n                        \"context\": \"host\",\n                        'depends': [],\n                        \"binary\": \"Build\",\n                        'build_args': '--requires=dep/0.1 --build=dep/0.1',\n                        \"options\": [],\n                        \"overrides\": {}\n                    }\n                ]]\n            }\n        ],\n        [\n            {\n                \"ref\": \"pkg/0.1#1ac8dd17c0f9f420935abd3b6a8fa032\",\n                \"depends\": [\n                    \"dep/0.1#4d670581ccb765839f2239cc8dff8fbd\"\n                ],\n                \"packages\": [[\n                    {\n                        \"package_id\": \"59205ba5b14b8f4ebc216a6c51a89553021e82c1\",\n                        'prev': None,\n                        'filenames': [],\n                        'info': {'requires': ['dep/0.1']},\n                        \"context\": \"host\",\n                        'depends': [],\n                        \"binary\": \"Build\",\n                        'build_args': '--requires=pkg/0.1 --build=pkg/0.1',\n                        \"options\": [],\n                        \"overrides\": {}\n                    }\n                ]]\n            }\n        ]\n    ]\n\n    assert bo_json == result\n\n    c.run(\"graph build-order consumer --order-by=recipe --build=missing --format=json\")\n    bo_json = json.loads(c.stdout)\n    assert bo_json[\"order_by\"] == \"recipe\"\n    assert bo_json[\"order\"] == result\n\n    c.run(\"graph build-order consumer --build=missing --order-by=recipe --reduce --format=json\")\n    bo_json = json.loads(c.stdout)\n    assert bo_json[\"order_by\"] == \"recipe\"\n    assert bo_json[\"order\"] == result\n\n    # test html format\n    c.run(\"graph build-order consumer --build=missing --format=html\")\n    assert \"<body>\" in c.stdout\n    c.run(\"graph build-order consumer --order-by=recipe --build=missing --format=html\")\n    assert \"<body>\" in c.stdout\n    c.run(\"graph build-order consumer --order-by=configuration --build=missing --format=html\")\n    assert \"<body>\" in c.stdout\n\n\ndef test_info_build_order_configuration():\n    c = TestClient()\n    c.save({\"dep/conanfile.py\": GenConanfile(),\n            \"pkg/conanfile.py\": GenConanfile().with_requires(\"dep/0.1\"),\n            \"consumer/conanfile.txt\": \"[requires]\\npkg/0.1\"})\n    c.run(\"export dep --name=dep --version=0.1\")\n    c.run(\"export pkg --name=pkg --version=0.1\")\n    c.run(\"graph build-order consumer --build=missing --order=configuration --format=json\")\n    bo_json = json.loads(c.stdout)\n    assert bo_json[\"order_by\"] == \"configuration\"\n\n    result = [\n        [\n            {\n                \"ref\": \"dep/0.1#4d670581ccb765839f2239cc8dff8fbd\",\n                \"pref\": \"dep/0.1#4d670581ccb765839f2239cc8dff8fbd:da39a3ee5e6b4b0d3255bfef95601890afd80709\",\n                \"depends\": [],\n                \"package_id\": \"da39a3ee5e6b4b0d3255bfef95601890afd80709\",\n                'prev': None,\n                'filenames': [],\n                'info': {},\n                \"context\": \"host\",\n                \"binary\": \"Build\",\n                'build_args': '--requires=dep/0.1 --build=dep/0.1',\n                \"options\": [],\n                \"overrides\": {}\n            }\n        ],\n        [\n            {\n                \"ref\": \"pkg/0.1#1ac8dd17c0f9f420935abd3b6a8fa032\",\n                \"pref\": \"pkg/0.1#1ac8dd17c0f9f420935abd3b6a8fa032:59205ba5b14b8f4ebc216a6c51a89553021e82c1\",\n                \"depends\": [\n                    \"dep/0.1#4d670581ccb765839f2239cc8dff8fbd:da39a3ee5e6b4b0d3255bfef95601890afd80709\"\n                ],\n                \"package_id\": \"59205ba5b14b8f4ebc216a6c51a89553021e82c1\",\n                'prev': None,\n                'filenames': [],\n                'info': {'requires': ['dep/0.1']},\n                \"context\": \"host\",\n                \"binary\": \"Build\",\n                'build_args': '--requires=pkg/0.1 --build=pkg/0.1',\n                \"options\": [],\n                \"overrides\": {}\n\n            }\n        ]\n    ]\n\n    assert bo_json[\"order\"] == result\n\n    c.run(\"graph build-order consumer --build=missing --order=configuration --reduce --format=json\")\n    bo_json = json.loads(c.stdout)\n    assert bo_json[\"order\"] == result\n\n\ndef test_info_build_order_configuration_text_formatter():\n    c = TestClient()\n    c.save({\"dep/conanfile.py\": GenConanfile(),\n            \"pkg/conanfile.py\": GenConanfile().with_requires(\"dep/0.1\"),\n            \"consumer/conanfile.txt\": \"[requires]\\npkg/0.1\"})\n    c.run(\"export dep --name=dep --version=0.1\")\n    c.run(\"export pkg --name=pkg --version=0.1\")\n    c.run(\"graph build-order consumer --build=missing --order=configuration --format=text\")\n    assert textwrap.dedent(\"\"\"\\\n    ======== Computing the build order ========\n    dep/0.1#4d670581ccb765839f2239cc8dff8fbd:da39a3ee5e6b4b0d3255bfef95601890afd80709 - Build\n    pkg/0.1#1ac8dd17c0f9f420935abd3b6a8fa032:59205ba5b14b8f4ebc216a6c51a89553021e82c1 - Build\n    \"\"\") in c.out\n\n\ndef test_info_build_order_build_require():\n    c = TestClient()\n    c.save({\"dep/conanfile.py\": GenConanfile(),\n            \"pkg/conanfile.py\": GenConanfile().with_tool_requires(\"dep/0.1\"),\n            \"consumer/conanfile.txt\": \"[requires]\\npkg/0.1\"})\n    c.run(\"export dep --name=dep --version=0.1\")\n    c.run(\"export pkg --name=pkg --version=0.1\")\n    c.run(\"graph build-order  consumer --build=missing --format=json\")\n    bo_json = json.loads(c.stdout)\n    result = [\n        [\n            {\n                \"ref\": 'dep/0.1#4d670581ccb765839f2239cc8dff8fbd',\n                \"depends\": [],\n                \"packages\": [[\n                    {\n                        \"package_id\": \"da39a3ee5e6b4b0d3255bfef95601890afd80709\",\n                        'prev': None,\n                        'filenames': [],\n                        'info': {},\n                        \"context\": \"build\",\n                        'depends': [],\n                        \"binary\": \"Build\",\n                        'build_args': '--tool-requires=dep/0.1 --build=dep/0.1',\n                        \"options\": [],\n                        \"overrides\": {}\n                    }\n                ]]\n            }\n        ],\n        [\n            {\n                \"ref\": \"pkg/0.1#b5a40d7314ce57ebdcf8fa31257f3de1\",\n                \"depends\": [\n                    \"dep/0.1#4d670581ccb765839f2239cc8dff8fbd\"\n                ],\n                \"packages\": [[\n                    {\n                        \"package_id\": \"da39a3ee5e6b4b0d3255bfef95601890afd80709\",\n                        'prev': None,\n                        'filenames': [],\n                        'info': {},\n                        \"context\": \"host\",\n                        'depends': [],\n                        \"binary\": \"Build\",\n                        'build_args': '--requires=pkg/0.1 --build=pkg/0.1',\n                        \"options\": [],\n                        \"overrides\": {}\n                    }\n                ]]\n            }\n        ]\n    ]\n\n    assert bo_json == result\n\n\ndef test_info_build_order_options():\n    c = TestClient()\n    # The normal default_options do NOT propagate to build_requires, it is necessary to use\n    # self.requires(..., options=xxx)\n    c.save({\"tool/conanfile.py\": GenConanfile().with_option(\"myopt\", [1, 2, 3]),\n            \"dep1/conanfile.py\": GenConanfile().with_tool_requirement(\"tool/0.1\",\n                                                                      options={\"myopt\": 1}),\n            \"dep2/conanfile.py\": GenConanfile().with_tool_requirement(\"tool/0.1\",\n                                                                      options={\"myopt\": 2}),\n            \"consumer/conanfile.txt\": \"[requires]\\ndep1/0.1\\ndep2/0.1\"})\n    c.run(\"export tool --name=tool --version=0.1\")\n    c.run(\"export dep1 --name=dep1 --version=0.1\")\n    c.run(\"export dep2 --name=dep2 --version=0.1\")\n\n    c.run(\"graph build-order  consumer --build=missing --format=json\")\n    bo_json = json.loads(c.stdout)\n    result = [\n        [\n            {'ref': 'tool/0.1#b4c19a1357b43877a2019dd2804336a9',\n             'depends': [],\n             'packages': [[\n                 {'package_id': '1124b99dc8cd3c8bbf79121c7bf86ce40c725a40', 'prev': None,\n                  'context': 'build', 'depends': [], \"overrides\": {},\n                  'binary': 'Build', 'options': ['tool/0.1:myopt=2'], 'filenames': [],\n                  'info': {'options': {'myopt': '2'}},\n                  'build_args': '--tool-requires=tool/0.1 --build=tool/0.1 -o:b=\"tool/0.1:myopt=2\"'},\n                 {'package_id': 'a9035d84c5880b26c4b44acf70078c9a7dd37412', 'prev': None,\n                  'context': 'build', 'depends': [], \"overrides\": {},\n                  'info': {'options': {'myopt': '1'}},\n                  'binary': 'Build', 'options': ['tool/0.1:myopt=1'],\n                  'filenames': [],\n                  'build_args': '--tool-requires=tool/0.1 --build=tool/0.1 -o:b=\"tool/0.1:myopt=1\"'}\n             ]]}\n        ],\n        [\n            {'ref': 'dep1/0.1#7f0d80f9cb8c6bab06def7f6fb8f3b86',\n             'depends': ['tool/0.1#b4c19a1357b43877a2019dd2804336a9'],\n             'packages': [[\n                 {'package_id': 'da39a3ee5e6b4b0d3255bfef95601890afd80709', 'prev': None,\n                  'context': 'host', 'depends': [], 'binary': 'Build', 'options': [],\n                  'filenames': [], 'info': {}, \"overrides\": {},\n                  'build_args': '--requires=dep1/0.1 --build=dep1/0.1'}\n             ]]},\n            {'ref': 'dep2/0.1#23c789d2b36f0461e52cd6f139f97f5e',\n             'depends': ['tool/0.1#b4c19a1357b43877a2019dd2804336a9'],\n             'packages': [[\n                 {'package_id': 'da39a3ee5e6b4b0d3255bfef95601890afd80709', 'prev': None,\n                  'context': 'host', 'depends': [], 'binary': 'Build', 'options': [],\n                  'filenames': [], 'info': {}, \"overrides\": {},\n                  'build_args': '--requires=dep2/0.1 --build=dep2/0.1'}\n             ]]}\n        ]\n    ]\n    assert bo_json == result\n\n\ndef test_info_build_order_merge_multi_product():\n    c = TestClient()\n    c.save({\"dep/conanfile.py\": GenConanfile(),\n            \"pkg/conanfile.py\": GenConanfile().with_requires(\"dep/0.1\"),\n            \"consumer1/conanfile.txt\": \"[requires]\\npkg/0.1\",\n            \"consumer2/conanfile.txt\": \"[requires]\\npkg/0.2\"})\n    c.run(\"export dep --name=dep --version=0.1\")\n    c.run(\"export pkg --name=pkg --version=0.1\")\n    c.run(\"export pkg --name=pkg --version=0.2\")\n    c.run(\"graph build-order consumer1  --build=missing --format=json\", redirect_stdout=\"bo1.json\")\n    c.run(\"graph build-order consumer2  --build=missing --format=json\", redirect_stdout=\"bo2.json\")\n    c.run(\"graph build-order-merge --file=bo1.json --file=bo2.json --format=json\",\n          redirect_stdout=\"bo3.json\")\n\n    bo_json = json.loads(c.load(\"bo3.json\"))\n\n    result = [\n        [\n            {\n                \"ref\": \"dep/0.1#4d670581ccb765839f2239cc8dff8fbd\",\n                \"depends\": [],\n                \"packages\": [[\n                    {\n                        \"package_id\": \"da39a3ee5e6b4b0d3255bfef95601890afd80709\",\n                        'prev': None,\n                        'filenames': [\"bo1\", \"bo2\"],\n                        'info': {},\n                        \"context\": \"host\",\n                        'depends': [],\n                        \"binary\": \"Build\",\n                        'build_args': '--requires=dep/0.1 --build=dep/0.1',\n                        \"options\": [],\n                        \"overrides\": {}\n                    }\n                ]]\n            }\n        ],\n        [\n            {\n                \"ref\": \"pkg/0.1#1ac8dd17c0f9f420935abd3b6a8fa032\",\n                \"depends\": [\n                    \"dep/0.1#4d670581ccb765839f2239cc8dff8fbd\"\n                ],\n                \"packages\": [[\n                    {\n                        \"package_id\": \"59205ba5b14b8f4ebc216a6c51a89553021e82c1\",\n                        'prev': None,\n                        'filenames': [\"bo1\"],\n                        'info': {'requires': ['dep/0.1']},\n                        \"context\": \"host\",\n                        'depends': [],\n                        \"binary\": \"Build\",\n                        'build_args': '--requires=pkg/0.1 --build=pkg/0.1',\n                        \"options\": [],\n                        \"overrides\": {}\n                    }\n                ]]\n            },\n            {\n                \"ref\": \"pkg/0.2#1ac8dd17c0f9f420935abd3b6a8fa032\",\n                \"depends\": [\n                    \"dep/0.1#4d670581ccb765839f2239cc8dff8fbd\"\n                ],\n                \"packages\": [[\n                    {\n                        \"package_id\": \"59205ba5b14b8f4ebc216a6c51a89553021e82c1\",\n                        'prev': None,\n                        'filenames': [\"bo2\"],\n                        'info': {'requires': ['dep/0.1']},\n                        \"context\": \"host\",\n                        'depends': [],\n                        \"binary\": \"Build\",\n                        'build_args': '--requires=pkg/0.2 --build=pkg/0.2',\n                        \"options\": [],\n                        \"overrides\": {}\n                    }\n                ]]\n            }\n        ]\n    ]\n\n    assert bo_json == result\n\n    # test that html format for build-order-merge generates something\n    c.run(\"graph build-order-merge --file=bo1.json --file=bo2.json --format=html\")\n    assert \"<body>\" in c.stdout\n\n\ndef test_info_build_order_merge_multi_product_configurations():\n    c = TestClient()\n    c.save({\"dep/conanfile.py\": GenConanfile(),\n            \"pkg/conanfile.py\": GenConanfile().with_requires(\"dep/0.1\"),\n            \"consumer1/conanfile.txt\": \"[requires]\\npkg/0.1\",\n            \"consumer2/conanfile.txt\": \"[requires]\\npkg/0.2\"})\n    c.run(\"export dep --name=dep --version=0.1\")\n    c.run(\"export pkg --name=pkg --version=0.1\")\n    c.run(\"export pkg --name=pkg --version=0.2\")\n    c.run(\"graph build-order consumer1  --build=missing --order=configuration --format=json\",\n          redirect_stdout=\"bo1.json\")\n    c.run(\"graph build-order consumer2  --build=missing --order=configuration --format=json\",\n          redirect_stdout=\"bo2.json\")\n    c.run(\"graph build-order-merge --file=bo1.json --file=bo2.json --format=json\",\n          redirect_stdout=\"bo3.json\")\n\n    bo_json = json.loads(c.load(\"bo3.json\"))\n    assert bo_json[\"order_by\"] == \"configuration\"\n    result = [\n        [\n            {\n                \"ref\": \"dep/0.1#4d670581ccb765839f2239cc8dff8fbd\",\n                \"pref\": \"dep/0.1#4d670581ccb765839f2239cc8dff8fbd:da39a3ee5e6b4b0d3255bfef95601890afd80709\",\n                \"package_id\": \"da39a3ee5e6b4b0d3255bfef95601890afd80709\",\n                \"prev\": None,\n                \"context\": \"host\",\n                \"binary\": \"Build\",\n                \"options\": [],\n                \"filenames\": [\n                    \"bo1\",\n                    \"bo2\"\n                ],\n                'info': {},\n                \"depends\": [],\n                \"overrides\": {},\n                \"build_args\": \"--requires=dep/0.1 --build=dep/0.1\"\n            }\n        ],\n        [\n            {\n                \"ref\": \"pkg/0.1#1ac8dd17c0f9f420935abd3b6a8fa032\",\n                \"pref\": \"pkg/0.1#1ac8dd17c0f9f420935abd3b6a8fa032:59205ba5b14b8f4ebc216a6c51a89553021e82c1\",\n                \"package_id\": \"59205ba5b14b8f4ebc216a6c51a89553021e82c1\",\n                \"prev\": None,\n                \"context\": \"host\",\n                \"binary\": \"Build\",\n                \"options\": [],\n                \"filenames\": [\n                    \"bo1\"\n                ],\n                'info': {'requires': ['dep/0.1']},\n                \"depends\": [\n                    \"dep/0.1#4d670581ccb765839f2239cc8dff8fbd:da39a3ee5e6b4b0d3255bfef95601890afd80709\"\n                ],\n                \"overrides\": {},\n                \"build_args\": \"--requires=pkg/0.1 --build=pkg/0.1\"\n            },\n            {\n                \"ref\": \"pkg/0.2#1ac8dd17c0f9f420935abd3b6a8fa032\",\n                \"pref\": \"pkg/0.2#1ac8dd17c0f9f420935abd3b6a8fa032:59205ba5b14b8f4ebc216a6c51a89553021e82c1\",\n                \"package_id\": \"59205ba5b14b8f4ebc216a6c51a89553021e82c1\",\n                \"prev\": None,\n                \"context\": \"host\",\n                \"binary\": \"Build\",\n                \"options\": [],\n                \"filenames\": [\n                    \"bo2\"\n                ],\n                'info': {'requires': ['dep/0.1']},\n                \"depends\": [\n                    \"dep/0.1#4d670581ccb765839f2239cc8dff8fbd:da39a3ee5e6b4b0d3255bfef95601890afd80709\"\n                ],\n                \"overrides\": {},\n                \"build_args\": \"--requires=pkg/0.2 --build=pkg/0.2\"\n            }\n        ]\n    ]\n\n    assert bo_json[\"order\"] == result\n\n\ndef test_info_build_order_merge_conditionals():\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            settings = \"os\"\n            def requirements(self):\n                if self.settings.os == \"Windows\":\n                    self.requires(\"depwin/[>0.0 <1.0]\")\n                else:\n                    self.requires(\"depnix/[>0.0 <1.0]\")\n        \"\"\")\n    c.save({\"dep/conanfile.py\": GenConanfile(),\n            \"pkg/conanfile.py\": conanfile,\n            \"consumer/conanfile.txt\": \"[requires]\\npkg/0.1\"})\n    c.run(\"export dep --name=depwin --version=0.1\")\n    c.run(\"export dep --name=depnix --version=0.1\")\n    c.run(\"export pkg --name=pkg --version=0.1\")\n    c.run(\"graph build-order consumer --format=json --build=missing -s os=Windows\",\n          redirect_stdout=\"bo_win.json\")\n    c.run(\"graph build-order consumer --format=json --build=missing -s os=Linux\",\n          redirect_stdout=\"bo_nix.json\")\n    c.run(\"graph build-order-merge --file=bo_win.json --file=bo_nix.json --format=json\",\n          redirect_stdout=\"bo3.json\")\n\n    bo_json = json.loads(c.load(\"bo3.json\"))\n\n    result = [\n        [\n            {\n                \"ref\": \"depwin/0.1#4d670581ccb765839f2239cc8dff8fbd\",\n                \"depends\": [],\n                \"packages\": [[\n                    {\n                        \"package_id\": \"da39a3ee5e6b4b0d3255bfef95601890afd80709\",\n                        'prev': None,\n                        'filenames': [\"bo_win\"],\n                        'info': {},\n                        \"context\": \"host\",\n                        'depends': [],\n                        \"binary\": \"Build\",\n                        'build_args': '--requires=depwin/0.1 --build=depwin/0.1',\n                        \"options\": [],\n                        \"overrides\": {}\n                    }\n                ]]\n            },\n            {\n                \"ref\": \"depnix/0.1#4d670581ccb765839f2239cc8dff8fbd\",\n                \"depends\": [],\n                \"packages\": [[\n                    {\n                        \"package_id\": \"da39a3ee5e6b4b0d3255bfef95601890afd80709\",\n                        'prev': None,\n                        'filenames': [\"bo_nix\"],\n                        'info': {},\n                        \"context\": \"host\",\n                        'depends': [],\n                        \"binary\": \"Build\",\n                        'build_args': '--requires=depnix/0.1 --build=depnix/0.1',\n                        \"options\": [],\n                        \"overrides\": {}\n                    }\n                ]]\n            }\n        ],\n        [\n            {\n                \"ref\": \"pkg/0.1#b615ac4c7cd16631cd9e924b68596fce\",\n                \"depends\": [\n                    \"depwin/0.1#4d670581ccb765839f2239cc8dff8fbd\",\n                    \"depnix/0.1#4d670581ccb765839f2239cc8dff8fbd\"\n                ],\n                \"packages\": [[\n                    {\n                        \"package_id\": \"b23846b9b10455081d89a9dfacd01f7712d04b95\",\n                        'prev': None,\n                        'filenames': [\"bo_win\"],\n                        'info': {'requires': ['depwin/0.1'],\n                                 'settings': {'os': 'Windows'}},\n                        \"context\": \"host\",\n                        'depends': [],\n                        \"binary\": \"Build\",\n                        'build_args': '--requires=pkg/0.1 --build=pkg/0.1',\n                        \"options\": [],\n                        \"overrides\": {}\n                    },\n                    {\n                        \"package_id\": \"dc29fa55ec82fab6bd820398c7a152ae5f7d4e28\",\n                        'prev': None,\n                        'filenames': [\"bo_nix\"],\n                        'info': {'requires': ['depnix/0.1'],\n                                 'settings': {'os': 'Linux'}},\n                        \"context\": \"host\",\n                        'depends': [],\n                        \"binary\": \"Build\",\n                        'build_args': '--requires=pkg/0.1 --build=pkg/0.1',\n                        \"options\": [],\n                        \"overrides\": {}\n                    }\n                ]]\n            }\n        ]\n    ]\n\n    assert bo_json == result\n\n\ndef test_info_build_order_lockfile_location():\n    \"\"\" the lockfile should be in the caller cwd\n    https://github.com/conan-io/conan/issues/13850\n    \"\"\"\n    c = TestClient()\n    c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\"),\n            \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_requires(\"dep/0.1\")})\n    c.run(\"create dep\")\n    c.run(\"lock create pkg --lockfile-out=myconan.lock\")\n    assert os.path.exists(os.path.join(c.current_folder, \"myconan.lock\"))\n    c.run(\"graph build-order pkg --lockfile=myconan.lock --lockfile-out=myconan2.lock\")\n    assert os.path.exists(os.path.join(c.current_folder, \"myconan2.lock\"))\n\n\ndef test_build_order_missing_package_check_error():\n    c = TestClient()\n    c.save({\"dep/conanfile.py\": GenConanfile(),\n            \"pkg/conanfile.py\": GenConanfile().with_requires(\"dep/0.1\"),\n            \"consumer/conanfile.txt\": \"[requires]\\npkg/0.1\"})\n    c.run(\"export dep --name=dep --version=0.1\")\n    c.run(\"export pkg --name=pkg --version=0.1\")\n\n    exit_code = c.run(\"graph build-order consumer --build='pkg/*' --order=configuration --format=json\", assert_error=True)\n    bo_json = json.loads(c.stdout)\n    assert bo_json[\"order_by\"] == \"configuration\"\n    assert exit_code != 0\n    assert \"dep/0.1:da39a3ee5e6b4b0d3255bfef95601890afd80709: Missing binary\" in c.out\n\n    result = [\n        [\n            {\n                \"ref\": \"dep/0.1#4d670581ccb765839f2239cc8dff8fbd\",\n                \"pref\": \"dep/0.1#4d670581ccb765839f2239cc8dff8fbd:da39a3ee5e6b4b0d3255bfef95601890afd80709\",\n                \"package_id\": \"da39a3ee5e6b4b0d3255bfef95601890afd80709\",\n                \"prev\": None,\n                \"context\": \"host\",\n                \"binary\": \"Missing\",\n                \"options\": [],\n                \"filenames\": [],\n                'info': {},\n                \"depends\": [],\n                \"overrides\": {},\n                \"build_args\": None,\n            }\n        ],\n        [\n            {\n                \"ref\": \"pkg/0.1#1ac8dd17c0f9f420935abd3b6a8fa032\",\n                \"pref\": \"pkg/0.1#1ac8dd17c0f9f420935abd3b6a8fa032:59205ba5b14b8f4ebc216a6c51a89553021e82c1\",\n                \"package_id\": \"59205ba5b14b8f4ebc216a6c51a89553021e82c1\",\n                \"prev\": None,\n                \"context\": \"host\",\n                \"binary\": \"Build\",\n                \"options\": [],\n                \"filenames\": [],\n                'info': {'requires': ['dep/0.1']},\n                \"depends\": [\n                    \"dep/0.1#4d670581ccb765839f2239cc8dff8fbd:da39a3ee5e6b4b0d3255bfef95601890afd80709\"\n                ],\n                \"overrides\": {},\n                \"build_args\": \"--requires=pkg/0.1 --build=pkg/0.1\",\n            }\n        ],\n    ]\n\n    assert bo_json[\"order\"] == result\n\n\ndef test_info_build_order_broken_recipe():\n    # https://github.com/conan-io/conan/issues/14104\n    c = TestClient()\n    dep = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import replace_in_file\n        class Pkg(ConanFile):\n            name = \"dep\"\n            version = \"0.1\"\n            def export(self):\n                replace_in_file(self, \"conanfile.py\", \"from conan\", \"from conans\")\n        \"\"\")\n    c.save({\"conanfile.py\": dep})\n    c.run(\"export .\")\n    c.run(\"graph build-order --requires=dep/0.1 --format=json\", assert_error=True)\n    assert \"ImportError\" in c.out\n    assert \"It is possible that this recipe is not Conan 2.0 ready\" in c.out\n\n\nclass TestBuildOrderReduce:\n    @pytest.mark.parametrize(\"order\", [\"recipe\", \"configuration\"])\n    def test_build_order_reduce(self, order):\n        c = TestClient()\n        c.save({\"liba/conanfile.py\": GenConanfile(\"liba\", \"0.1\"),\n                \"libb/conanfile.py\": GenConanfile(\"libb\", \"0.1\").with_requires(\"liba/0.1\"),\n                \"libc/conanfile.py\": GenConanfile(\"libc\", \"0.1\").with_requires(\"libb/0.1\"),\n                \"consumer/conanfile.txt\": \"[requires]\\nlibc/0.1\"})\n        c.run(\"create liba\")\n        c.run(\"create libb\")\n        c.run(\"create libc\")\n        c.run(\"remove liba:* -c\")\n        c.run(\"remove libc:* -c\")\n        c.run(f\"graph build-order consumer --order={order} --build=missing --reduce --format=json\")\n        bo_json = json.loads(c.stdout)\n        order_json = bo_json[\"order\"]\n        assert len(order_json) == 2  # 2 levels\n        level0, level1 = order_json\n        assert len(level0) == 1\n        assert level0[0][\"ref\"] == \"liba/0.1#a658e7beaaae5d6be0b6f67dcc9859e2\"\n        # then libc -> directly on liba, no libb involved\n        assert len(level1) == 1\n        assert level1[0][\"ref\"] == \"libc/0.1#c04c370ad966390e67388565b56f019a\"\n        depends = \"liba/0.1#a658e7beaaae5d6be0b6f67dcc9859e2\"\n        if order == \"configuration\":\n            depends += \":da39a3ee5e6b4b0d3255bfef95601890afd80709\"\n        assert level1[0][\"depends\"] == [depends]\n\n    @pytest.mark.parametrize(\"order\", [\"recipe\", \"configuration\"])\n    def test_build_order_merge_reduce(self, order):\n        c = TestClient()\n        c.save({\"liba/conanfile.py\": GenConanfile(\"liba\", \"0.1\").with_settings(\"os\"),\n                \"libb/conanfile.py\": GenConanfile(\"libb\", \"0.1\").with_settings(\"os\")\n                                                                .with_requires(\"liba/0.1\"),\n                \"libc/conanfile.py\": GenConanfile(\"libc\", \"0.1\").with_settings(\"os\")\n                                                                .with_requires(\"libb/0.1\"),\n                \"consumer/conanfile.txt\": \"[requires]\\nlibc/0.1\"})\n        for _os in (\"Windows\", \"Linux\"):\n            c.run(f\"create liba -s os={_os}\")\n            c.run(f\"create libb -s os={_os}\")\n            c.run(f\"create libc -s os={_os}\")\n\n        c.run(\"remove liba:* -c\")\n        c.run(\"remove libc:* -c\")\n        c.run(f\"graph build-order consumer --order={order} --build=missing -s os=Windows \"\n              \"--format=json\", redirect_stdout=\"windows.json\")\n        c.run(f\"graph build-order consumer --order={order} --build=missing -s os=Linux \"\n              \"--format=json\", redirect_stdout=\"linux.json\")\n\n        c.run(f\"graph build-order-merge --file=windows.json --file=linux.json --reduce \"\n              \"--format=json\")\n        bo_json = json.loads(c.stdout)\n        order_json = bo_json[\"order\"]\n        assert len(order_json) == 2  # 2 levels\n        level0, level1 = order_json\n        if order == \"recipe\":\n            assert len(level0) == 1\n            assert level0[0][\"ref\"] == \"liba/0.1#8c6ed89c12ab2ce78b239224bd7cb79e\"\n            # then libc -> directly on liba, no libb involved\n            assert len(level1) == 1\n            assert level1[0][\"ref\"] == \"libc/0.1#66db2600b9d6a2a61c9051fcf47da4a3\"\n            depends = \"liba/0.1#8c6ed89c12ab2ce78b239224bd7cb79e\"\n            assert level1[0][\"depends\"] == [depends]\n        else:\n            assert len(level0) == 2\n            liba1 = \"liba/0.1#8c6ed89c12ab2ce78b239224bd7cb79e:\" \\\n                    \"ebec3dc6d7f6b907b3ada0c3d3cdc83613a2b715\"\n            liba2 = \"liba/0.1#8c6ed89c12ab2ce78b239224bd7cb79e:\" \\\n                    \"9a4eb3c8701508aa9458b1a73d0633783ecc2270\"\n            assert level0[0][\"pref\"] == liba1\n            assert level0[1][\"pref\"] == liba2\n            # then libc -> directly on liba, no libb involved\n            assert len(level1) == 2\n            assert level1[0][\"ref\"] == \"libc/0.1#66db2600b9d6a2a61c9051fcf47da4a3\"\n            assert level1[0][\"depends\"] == [liba1]\n            assert level1[1][\"ref\"] == \"libc/0.1#66db2600b9d6a2a61c9051fcf47da4a3\"\n            assert level1[1][\"depends\"] == [liba2]\n\n    def test_error_reduced(self):\n        c = TestClient()\n        c.save({\"conanfile.py\": GenConanfile(\"liba\", \"0.1\")})\n        c.run(\"graph build-order . --format=json\", redirect_stdout=\"bo1.json\")\n        c.run(\"graph build-order . --order-by=recipe --reduce --format=json\",\n              redirect_stdout=\"bo2.json\")\n        c.run(f\"graph build-order-merge --file=bo1.json --file=bo2.json\", assert_error=True)\n        assert \"ERROR: Reduced build-order file cannot be merged: bo2.json\"\n        # different order\n        c.run(f\"graph build-order-merge --file=bo2.json --file=bo1.json\", assert_error=True)\n        assert \"ERROR: Reduced build-order file cannot be merged: bo2.json\"\n\n    def test_error_different_orders(self):\n        c = TestClient()\n        c.save({\"conanfile.py\": GenConanfile(\"liba\", \"0.1\")})\n        c.run(\"graph build-order . --format=json\", redirect_stdout=\"bo1.json\")\n        c.run(\"graph build-order . --order-by=recipe --format=json\", redirect_stdout=\"bo2.json\")\n        c.run(\"graph build-order . --order-by=configuration --format=json\",\n              redirect_stdout=\"bo3.json\")\n        c.run(f\"graph build-order-merge --file=bo1.json --file=bo2.json\")\n        # Not error\n        c.run(f\"graph build-order-merge --file=bo1.json --file=bo3.json\", assert_error=True)\n        assert \"ERROR: Cannot merge build-orders of recipe!=configuration\" in c.out\n        c.run(f\"graph build-order-merge --file=bo2.json --file=bo3.json\", assert_error=True)\n        assert \"ERROR: Cannot merge build-orders of recipe!=configuration\" in c.out\n        # different order\n        c.run(f\"graph build-order-merge --file=bo3.json --file=bo2.json\", assert_error=True)\n        assert \"ERROR: Cannot merge build-orders of configuration!=recipe\" in c.out\n\n    def test_merge_missing_error(self):\n        tc = TestClient(light=True)\n        tc.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"1.0\")})\n        tc.run(\"export dep\")\n        tc.run(\"graph build-order --order=recipe --requires=dep/1.0 --format=json\", assert_error=True, redirect_stdout=\"order.json\")\n        tc.run(\"graph build-order-merge --file=order.json --file=order.json --format=json\", assert_error=True)\n        assert \"dep/1.0:da39a3ee5e6b4b0d3255bfef95601890afd80709: Missing binary\" in tc.out\n        assert \"IndexError: list index out of range\" not in tc.out\n\n    def test_merge_invalid_error(self):\n        tc = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.errors import ConanInvalidConfiguration\n        class Pkg(ConanFile):\n            name = \"dep\"\n            version = \"1.0\"\n            def validate(self):\n                raise ConanInvalidConfiguration(\"This configuration is not valid\")\n        \"\"\")\n        tc.save({\"dep/conanfile.py\": conanfile})\n        tc.run(\"export dep\")\n        tc.run(\"graph build-order --order=recipe --requires=dep/1.0 --format=json\", assert_error=True, redirect_stdout=\"order.json\")\n        tc.run(\"graph build-order-merge --file=order.json --file=order.json --format=json\", assert_error=True)\n        assert \"dep/1.0:da39a3ee5e6b4b0d3255bfef95601890afd80709: Invalid configuration\" in tc.out\n        assert \"IndexError: list index out of range\" not in tc.out\n\n    def test_reduce_should_remove_recipe(self):\n        tc = TestClient()\n        tc.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"1.0\").with_settings(\"os\")})\n        tc.run(\"export dep\")\n        tc.run(\"create dep -s os=Windows\")\n        tc.run(\"graph build-order -s os=Windows --build=missing --order=recipe --requires=dep/1.0 \"\n               \"--format=json\", redirect_stdout=\"windows.json\")\n        tc.run(\"graph build-order -s os=Linux --build=missing --order=recipe --requires=dep/1.0 \"\n               \"--format=json\", redirect_stdout=\"linux.json\")\n        tc.run(\"graph build-order-merge --file=windows.json --file=linux.json --reduce \"\n               \"--format=json\")\n        order = json.loads(tc.stdout)\n        assert order[\"order\"][0][0][\"ref\"] == \"dep/1.0#1674c18bb63f0c9778d2811c21f581a0\"\n        assert len(order[\"order\"][0][0][\"packages\"][0]) == 1\n        assert order[\"order\"][0][0][\"packages\"][0][0][\"binary\"] == \"Build\"\n\n\ndef test_multi_configuration_profile_args():\n    c = TestClient()\n    c.save({\"pkg/conanfile.py\": GenConanfile().with_settings(\"os\"),\n            \"consumer/conanfile.txt\": \"[requires]\\npkg/0.1\",\n            \"mypr\": \"\"})\n    c.run(\"export pkg --name=pkg --version=0.1\")\n    args = \"-pr=mypr -s:b os=Linux -o:h *:shared=True -c:h user.my:conf=1\"\n    c.run(f\"graph build-order consumer --format=json --build=missing -s os=Windows {args} \"\n          \"--order-by=recipe\", redirect_stdout=\"bo_win.json\")\n    c.run(f\"graph build-order consumer --format=json --build=missing -s os=Linux {args} \"\n          \"--order-by=recipe\", redirect_stdout=\"bo_nix.json\")\n    c.run(\"graph build-order-merge --file=bo_win.json --file=bo_nix.json --format=json\",\n          redirect_stdout=\"bo3.json\")\n    bo_json = json.loads(c.load(\"bo3.json\"))\n    win = '-pr:h=\"mypr\" -s:h=\"os=Windows\" -o:h=\"*:shared=True\" -c:h=\"user.my:conf=1\" -s:b=\"os=Linux\"'\n    nix = '-pr:h=\"mypr\" -s:h=\"os=Linux\" -o:h=\"*:shared=True\" -c:h=\"user.my:conf=1\" -s:b=\"os=Linux\"'\n    assert bo_json[\"profiles\"] == {\"bo_win\": {\"args\": win}, \"bo_nix\": {\"args\": nix}}\n\n\ndef test_build_order_space_in_options():\n    tc = TestClient(light=True)\n    tc.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"1.0\").with_option(\"flags\", [\"ANY\", None])\n                                                           .with_option(\"extras\", [\"ANY\", None]),\n             \"conanfile.txt\": textwrap.dedent(\"\"\"\n             [requires]\n             dep/1.0\n\n             [options]\n             dep/*:flags=define=FOO define=BAR define=BAZ\n             dep/*:extras=cxx=\"yes\" gnuext='no'\n             \"\"\")})\n\n    tc.run(\"create dep\")\n    tc.run(\"graph build-order . --order-by=configuration --build=dep/1.0 -f=json\", redirect_stdout=\"order.json\")\n    order = json.loads(tc.load(\"order.json\"))\n    assert order[\"order\"][0][0][\"build_args\"] == '''--requires=dep/1.0 --build=dep/1.0 -o=\"dep/*:extras=cxx=\"yes\" gnuext='no'\" -o=\"dep/*:flags=define=FOO define=BAR define=BAZ\"'''\n\n\ndef test_build_order_build_context_compatible():\n    c = TestClient()\n    foo = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.build import check_min_cppstd\n\n        class Pkg(ConanFile):\n            name = \"foo\"\n            version = \"1.0\"\n            settings = \"os\", \"compiler\"\n            def validate_build(self):\n                check_min_cppstd(self, 17)\n\n            def validate(self):\n                check_min_cppstd(self, 14)\n        \"\"\")\n    bar = GenConanfile(\"bar\", \"1.0\").with_settings(\"os\", \"compiler\").with_tool_requirement(\"foo/1.0\")\n\n    profile = textwrap.dedent(\"\"\"\n        [settings]\n        compiler=gcc\n        compiler.cppstd=gnu14\n        compiler.libcxx=libstdc++11\n        compiler.version=11\n        os=Linux\n        \"\"\")\n    c.save({\"conanfile_foo.py\": foo,\n            \"conanfile_bar.py\": bar,\n            \"profile\": profile})\n    c.run(\"export conanfile_foo.py\")\n    c.run(\"export conanfile_bar.py\")\n\n    #  \"--require/bar.1.0\" and \"require=foo/1.0\" along with `--build=missing` would cause both\n    # packages to be built in the host context - with foo being built with cppstd=17\n    # (because the default cppstd=14 is not enough) bar requires foo in the \"build\" context -\n    # where cppstd=14 - but it can reuse the one built for cppstd=17\n    # (via compatibility plugin)\n\n    # The three approaches are equivalent:\n    #  - Using \"--build=missing\" and forcing  \"-s foo/*:compiler.cppstd=17\", means, build missing\n    #    binaries, and for foo I want the compiler.cppstd=17 binary. This approach could build other\n    #    missing binaries too\n    #  - Using \"--build=compatible:foo/*\" and \"--build=missing:bar/*\" means, build only missing\n    #    binary for bar, and for \"foo\", build a compatible one if the main one is missing. This\n    #    approach prevents other packages (not foo/bar) from accidentally being built.\n    #  - Last approach, passing both \"--build=missing:foo/*\" and \"--build=compatible:foo/*\" is\n    #    similar to the other two in final behavior, but the --build=missing:foo avoids doing the\n    #    compatibility check for consumption of \"foo\", and goes directly to the build check\n\n    for approach in (\"--build=missing -s foo/*:compiler.cppstd=17\",\n                     '--build=\"compatible:foo/*\" --build=\"missing:bar/*\"',\n                     '--build=\"missing:foo/*\" --build=\"compatible:foo/*\" --build=\"missing:bar/*\"'):\n        c.run(f'graph build-order --require=foo/1.0 --require=bar/1.0 -pr:a profile {approach}')\n        c.assert_listed_binary({\"foo/1.0\": [\"4e2ae338231ae18d0d43b9e119404d2b2c416758\", \"Build\"],\n                                \"bar/1.0\": [\"5e4ffcc1ff33697a4ee96f66f0d2228ec458f25c\", \"Build\"]})\n        c.assert_listed_binary({\"foo/1.0\": [\"4e2ae338231ae18d0d43b9e119404d2b2c416758\", \"Build\"]},\n                               build=True)\n\n\ndef test_info_build_order_editable():\n    c = TestClient()\n    c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\"),\n            \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_requires(\"dep/0.1\"),\n            \"consumer/conanfile.txt\": \"[requires]\\npkg/0.1\"})\n    c.run(\"editable add dep\")\n    c.run(\"export pkg\")\n\n    c.run(\"graph build-order consumer --build=missing --build=editable -f=json --order-by=recipe\")\n    bo_json = json.loads(c.stdout)\n    pkg = bo_json[\"order\"][0][0][\"packages\"][0][0]\n    assert pkg[\"binary\"] == \"EditableBuild\"\n    assert pkg[\"build_args\"] == \"--requires=dep/0.1 --build=dep/0.1\"\n\n    c.run(\"graph build-order consumer --build=missing --build=editable -f=json \"\n          \"--order-by=configuration\")\n    bo_json = json.loads(c.stdout)\n    pkg = bo_json[\"order\"][0][0]\n    assert pkg[\"binary\"] == \"EditableBuild\"\n    assert pkg[\"build_args\"] == \"--requires=dep/0.1 --build=dep/0.1\"\n\n\ndef test_build_order_path_reqs_mixed_args():\n    # This used not to crash in previous versions\n    # Also make sure we can properly used them separately\n    tc = TestClient(light=True)\n    tc.run(\"graph build-order . --requires=foo/1.0\", assert_error=True)\n    assert \"ERROR: --requires and --tool-requires arguments are incompatible with [path] '.' argument\" in tc.out\n\n    tc.run(\"graph build-order --requires=foo/1.0\", assert_error=True)\n    assert \"Package 'foo/1.0' not resolved: No remote defined\" in tc.out\n\n    tc.run(\"graph build-order .\", assert_error=True)\n    assert \"Conanfile not found\" in tc.out\n"
  },
  {
    "path": "test/integration/command/info/test_info_folders.py",
    "content": "import os\nimport textwrap\nimport json\nimport pytest\n\nfrom conan.internal.paths import CONANFILE\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.cache.conan_reference_layout import EXPORT_FOLDER\n\nconanfile_py = \"\"\"\nfrom conan import ConanFile\n\nclass AConan(ConanFile):\n    name = \"package\"\n    version = \"0.1.0\"\n\"\"\"\n\nwith_deps_path_file = \"\"\"\nfrom conan import ConanFile\n\nclass BConan(ConanFile):\n    name = \"package2\"\n    version = \"0.2.0\"\n    requires = \"package/0.1.0@user/testing\"\n\"\"\"\n\ndeps_txt_file = \"\"\"\n[requires]\npackage2/0.2.0@user/testing\n\"\"\"\n\n\n@pytest.fixture()\ndef client_deps():\n    client = TestClient()\n    client.save({CONANFILE: conanfile_py})\n    client.run(f\"export . --user=user --channel=testing\")\n    client.save({CONANFILE: with_deps_path_file}, clean_first=True)\n    client.run(f\"export . --user=user --channel=testing\")\n    client.save({'conanfile.txt': deps_txt_file}, clean_first=True)\n    return client\n\n\ndef test_basic():\n    client = TestClient()\n    client.save({CONANFILE: conanfile_py})\n    client.run(f\"export . --user=user --channel=testing\")\n    client.run(f\"graph info --requires=package/0.1.0@user/testing --format=json\")\n    nodes = json.loads(client.stdout)[\"graph\"][\"nodes\"]\n    assert client.cache_folder in nodes[\"1\"][\"recipe_folder\"]\n    assert os.path.basename(nodes[\"1\"][\"recipe_folder\"]).strip() == EXPORT_FOLDER\n    assert nodes[\"1\"][\"source_folder\"] is None\n    assert nodes[\"1\"][\"build_folder\"] is None\n    assert nodes[\"1\"][\"package_folder\"] is None\n\n\ndef test_build_id():\n    # https://github.com/conan-io/conan/issues/6915\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Pkg(ConanFile):\n            options = {\"myOption\": [True, False]}\n            def build_id(self):\n                self.info_build.options.myOption = \"Any\"\n        \"\"\")\n    client.save({CONANFILE: conanfile})\n    client.run(f\"export . --name=pkg --version=0.1 --user=user --channel=testing\")\n    client.run(f\"graph info --requires=pkg/0.1@user/testing -o pkg/*:myOption=True\")\n    out = str(client.out).replace(\"\\\\\", \"/\")\n    assert \"package_id: b868c8ab4ae6ddccfe19fabd62a5e180d4b18a2b\" in out\n    assert \"build_id: d5d6fc54af6f589e338090910ac18c848a87720d\" in out\n\n    client.run(\"graph info --requires=pkg/0.1@user/testing -o pkg/*:myOption=False\")\n    out = str(client.out).replace(\"\\\\\", \"/\")\n    assert \"package_id: 41e2e23ac9570fd23f421bcd0cf9e5cbab49e6ee\" in out\n    assert \"build_id: d5d6fc54af6f589e338090910ac18c848a87720d\" in out\n\n\ndef test_deps_basic(client_deps):\n    for ref in [f\"--requires=package2/0.2.0@user/testing\", \"conanfile.txt\"]:\n        client_deps.run(f\"graph info {ref} --format=json\")\n        nodes = json.loads(client_deps.stdout)\n        found_ref = False\n        assert len(nodes[\"graph\"][\"nodes\"]) == 3\n\n        for _, node in nodes[\"graph\"][\"nodes\"].items():\n            if node[\"ref\"] == \"conanfile\":\n                assert node[\"source_folder\"] is None\n            else:\n                assert client_deps.cache_folder in node[\"recipe_folder\"]\n                assert os.path.basename(node[\"recipe_folder\"]).strip() == EXPORT_FOLDER\n            assert node[\"source_folder\"] is None\n            assert node[\"build_folder\"] is None\n            assert node[\"package_folder\"] is None\n            found_ref = found_ref or \"package/0.1.0@user/testing\" in node[\"ref\"]\n        assert found_ref\n\n\ndef test_deps_specific_information(client_deps):\n    client_deps.run(\"graph info . --package-filter package/* --format=json\")\n    nodes = json.loads(client_deps.stdout)[\"graph\"][\"nodes\"]\n    assert len(nodes) == 1\n    assert \"package/0.1.0@user/testing\" in nodes[\"2\"][\"ref\"]\n    assert nodes[\"2\"][\"source_folder\"] is None\n    assert nodes[\"2\"][\"build_folder\"] is None\n    assert nodes[\"2\"][\"package_folder\"] is None\n\n    client_deps.run(\"graph info . --package-filter package* --format=json\")\n    nodes = json.loads(client_deps.stdout)[\"graph\"][\"nodes\"]\n    assert len(nodes) == 2\n    assert \"package2/0.2.0@user/testing\" in nodes[\"1\"][\"ref\"]\n    assert nodes[\"1\"][\"source_folder\"] is None\n    assert nodes[\"1\"][\"build_folder\"] is None\n    assert nodes[\"1\"][\"package_folder\"] is None\n    assert \"package/0.1.0@user/testing\" in nodes[\"2\"][\"ref\"]\n    assert nodes[\"2\"][\"source_folder\"] is None\n    assert nodes[\"2\"][\"build_folder\"] is None\n    assert nodes[\"2\"][\"package_folder\"] is None\n\n\ndef test_single_field():\n    client = TestClient()\n    client.save({CONANFILE: conanfile_py})\n    client.run(f\"export . --user=user --channel=testing\")\n    client.run(f\"graph info --requires package/0.1.0@user/testing --format=json\")\n    nodes = json.loads(client.stdout)[\"graph\"][\"nodes\"]\n    assert len(nodes) == 2\n    assert \"package/0.1.0@user/testing\" in nodes[\"1\"][\"ref\"]\n    assert nodes[\"1\"][\"source_folder\"] is None\n    assert nodes[\"1\"][\"build_folder\"] is None\n    assert nodes[\"1\"][\"package_folder\"] is None\n\n\ndef test_direct_conanfile():\n    client = TestClient()\n    client.save({CONANFILE: conanfile_py})\n    client.run(\"graph info .\")\n    output = client.out\n    assert \"export_folder\" not in output\n    assert \"source_folder: None\" in output\n    assert \"build_folder: None\" in output\n    assert \"package_folder: None\" in output\n"
  },
  {
    "path": "test/integration/command/install/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/command/install/install_cascade_test.py",
    "content": "from collections import OrderedDict\n\nfrom conan.test.utils.tools import TestServer, GenConanfile, TestClient\n\n\ndef test_cascade():\n    \"\"\"\n    app -> E -> D -> B -> A\n      \\\\-> F -> C -------/\n    \"\"\"\n    server = TestServer()\n    servers = OrderedDict([(\"default\", server)])\n    c = TestClient(servers=servers)\n    c.save({\"a/conanfile.py\": GenConanfile(\"liba\", \"1.0\"),\n            \"b/conanfile.py\": GenConanfile(\"libb\", \"1.0\").with_requires(\"liba/1.0\"),\n            \"c/conanfile.py\": GenConanfile(\"libc\", \"1.0\").with_requires(\"liba/1.0\"),\n            \"d/conanfile.py\": GenConanfile(\"libd\", \"1.0\").with_requires(\"libb/1.0\"),\n            \"e/conanfile.py\": GenConanfile(\"libe\", \"1.0\").with_requires(\"libd/1.0\"),\n            \"f/conanfile.py\": GenConanfile(\"libf\", \"1.0\").with_requires(\"libc/1.0\", \"libd/1.0\"),\n            \"app/conanfile.py\": GenConanfile().with_requires(\"libe/1.0\", \"libf/1.0\")})\n\n    for pkg in (\"a\", \"b\", \"c\", \"d\", \"e\", \"f\"):\n        c.run(f\"create {pkg}\")\n\n    def _assert_built(refs):\n        for ref in refs:\n            assert \"{}: Copying sources to build folder\".format(ref) in c.out\n        for ref in [\"liba/1.0\", \"libb/1.0\", \"libc/1.0\", \"libd/1.0\", \"libe/1.0\", \"libf/1.0\"]:\n            if ref not in refs:\n                assert \"{}: Copying sources to build folder\".format(ref) not in c.out\n\n    # Building A everything is built\n    c.run(\"install app --build=liba* --build cascade\")\n    assert \"Using build-mode 'cascade' is generally inefficient\" in c.out\n    _assert_built([\"liba/1.0\", \"libb/1.0\", \"libc/1.0\", \"libd/1.0\", \"libe/1.0\", \"libf/1.0\"])\n\n    c.run(\"install app --build=libd* --build cascade\")\n    _assert_built([\"libd/1.0\", \"libe/1.0\", \"libf/1.0\"])\n\n    c.run(\"install app --build=libe* --build cascade\")\n    _assert_built([\"libe/1.0\"])\n\n    c.run(\"install app  --build cascade\")\n    _assert_built([])\n\n    c.run(\"install app --build=libc* --build cascade\")\n    _assert_built([\"libc/1.0\", \"libf/1.0\"])\n"
  },
  {
    "path": "test/integration/command/install/install_missing_dep_test.py",
    "content": "from conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestInstallMissingDependency:\n\n    def test_missing_dep(self):\n        client = TestClient()\n\n        # Create deps packages\n        dep1_conanfile = GenConanfile(\"dep1\")\n        client.save({\"conanfile.py\": dep1_conanfile}, clean_first=True)\n        client.run(\"create . --name=dep1 --version=1.0 --user=lasote --channel=testing\")\n        client.run(\"create . --name=dep1 --version=2.0 --user=lasote --channel=testing\")\n\n        dep2_conanfile = GenConanfile(\"dep2\", \"1.0\").with_require(\"dep1/1.0@lasote/testing\")\n        client.save({\"conanfile.py\": dep2_conanfile}, clean_first=True)\n        client.run(\"create . --user=lasote --channel=testing\")\n\n        # Create final package\n        # foo -------------> dep1/1.0\n        #   \\ -> dep2/1.0---->/\n        conanfile = GenConanfile(\"foo\", \"1.0\").with_require(\"dep1/1.0@lasote/testing\")\\\n                                              .with_require(\"dep2/1.0@lasote/testing\")\n        client.save({\"conanfile.py\": conanfile}, clean_first=True)\n        client.run(\"create . --user=lasote --channel=testing\")\n\n        # Bump version of one dependency\n        # foo -------------> dep1/2.0\n        #   \\ -> dep2/1.0---->/\n        conanfile = GenConanfile(\"foo\", \"1.0\").with_requirement(\"dep1/2.0@lasote/testing\", force=True) \\\n                                              .with_require(\"dep2/1.0@lasote/testing\")\n        client.save({\"conanfile.py\": conanfile}, clean_first=True)\n        client.run(\"create . --user=lasote --channel=testing\", assert_error=True)\n        client.assert_overrides({\"dep1/1.0@lasote/testing\":\n                                ['dep1/2.0@lasote/testing']})\n\n        assert \"Can't find a 'dep2/1.0@lasote/testing' package\" in client.out\n        assert \"dep1/2.Y.Z\" in client.out\n\n    def test_missing_multiple_dep(self):\n        client = TestClient()\n\n        dep1_conanfile = GenConanfile()\n        client.save({\"conanfile.py\": dep1_conanfile}, clean_first=True)\n        client.run(\"export . --name=dep1 --version=1.0\")\n        client.run(\"export . --name=dep2 --version=1.0\")\n\n        conanfile = GenConanfile().with_require(\"dep1/1.0\").with_require(\"dep2/1.0\")\n        client.save({\"conanfile.py\": conanfile}, clean_first=True)\n        client.run(\"create . --name=pkg --version=1.0\", assert_error=True)\n        assert \"ERROR: Missing prebuilt package for 'dep1/1.0', 'dep2/1.0'\" in client.out\n        assert \"Try to build locally from sources using the '--build=dep1/1.0 --build=dep2/1.0'\" in client.out\n"
  },
  {
    "path": "test/integration/command/install/install_parallel_test.py",
    "content": "from conan.test.utils.tools import GenConanfile, TestClient\n\n\nclass TestInstallParallel:\n\n    def test_basic_parallel_install(self):\n        client = TestClient(default_server_user=True)\n        threads = 4\n        counter = 8\n\n        client.save_home({\"global.conf\": f\"core.download:parallel={threads}\"})\n        client.save({\"conanfile.py\": GenConanfile()})\n\n        for i in range(counter):\n            client.run(\"create . --name=pkg%s --version=0.1 --user=user --channel=testing\" % i)\n        client.run(\"upload * --confirm -r default\")\n        client.run(\"remove * -c\")\n\n        # Lets consume the packages\n        conanfile_txt = [\"[requires]\"]\n        for i in range(counter):\n            conanfile_txt.append(\"pkg%s/0.1@user/testing\" % i)\n        conanfile_txt = \"\\n\".join(conanfile_txt)\n\n        client.save({\"conanfile.txt\": conanfile_txt}, clean_first=True)\n        client.run(\"install .\")\n        assert \"Downloading binary packages in %s parallel threads\" % threads in client.out\n        for i in range(counter):\n            assert \"pkg%s/0.1@user/testing: Package installed\" % i in client.out\n"
  },
  {
    "path": "test/integration/command/install/install_test.py",
    "content": "import json\nimport os\nimport re\nimport textwrap\nfrom collections import OrderedDict\n\nimport pytest\n\nfrom conan.test.utils.tools import NO_SETTINGS_PACKAGE_ID\nfrom conan.test.utils.tools import TestClient, TestServer, GenConanfile\nfrom conan.internal.util.files import mkdir, save\n\n\n@pytest.fixture()\ndef client():\n    c = TestClient(default_server_user=True)\n    c.save_home({\"settings.yml\": \"os: [Windows, Macos, Linux, FreeBSD]\\nos_build: [Windows, Macos]\",\n                 \"profiles/default\": \"[settings]\\nos=Windows\"})\n    return c\n\n\ndef test_install_reference_txt(client):\n    # Test to check the \"conan install <path> <reference>\" command argument\n    client.save({\"conanfile.txt\": \"\"})\n    client.run(\"install .\")\n    assert \"conanfile.txt\" in client.out\n\n\ndef test_install_reference_error(client):\n    # Test to check the \"conan install <path> <reference>\" command argument\n    client.run(\"install --requires=pkg/0.1@myuser/testing --user=user --channel=testing\", assert_error=True)\n    assert \"ERROR: Can't use --name, --version, --user or --channel arguments with --requires\" in client.out\n    client.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\")})\n    client.run(\"install . --channel=testing\", assert_error=True)\n    assert \"Can't specify channel 'testing' without user\" in client.out\n\n\ndef test_install_args_error():\n    c = TestClient()\n    c.run(\"install . --requires=zlib/1.0\", assert_error=True)\n    assert \"--requires and --tool-requires arguments are incompatible\" in c.out\n\n\ndef test_four_subfolder_install(client):\n    # https://github.com/conan-io/conan/issues/3950\n    client.save({\"path/to/sub/folder/conanfile.txt\": \"\"})\n    # If this doesn't, fail, all good\n    client.run(\" install path/to/sub/folder\")\n\n\n@pytest.mark.artifactory_ready\ndef test_install_system_requirements(client):\n    client.save({\"conanfile.py\": textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class MyPkg(ConanFile):\n            def system_requirements(self):\n                self.output.info(\"Running system requirements!!\")\n        \"\"\")})\n    client.run(\" install .\")\n    assert \"Running system requirements!!\" in client.out\n    client.run(\"export . --name=pkg --version=0.1 --user=lasote --channel=testing\")\n    client.run(\" install --requires=pkg/0.1@lasote/testing --build='*'\")\n    assert \"Running system requirements!!\" in client.out\n    client.run(\"upload * --confirm -r default\")\n    client.run('remove \"*\" -c')\n    client.run(\" install --requires=pkg/0.1@lasote/testing\")\n    assert \"Running system requirements!!\" in client.out\n\n\ndef test_install_transitive_pattern(client):\n    # Make sure a simple conan install doesn't fire package_info() so self.package_folder breaks\n    client.save({\"conanfile.py\": textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            options = {\"shared\": [True, False, \"header\"]}\n            default_options = {\"shared\": False}\n            def package_info(self):\n                self.output.info(\"PKG OPTION: %s\" % self.options.shared)\n        \"\"\")})\n    client.run(\"create . --name=pkg --version=0.1 --user=user --channel=testing -o shared=True\")\n    assert \"pkg/0.1@user/testing: PKG OPTION: True\" in client.out\n    client.save({\"conanfile.py\": textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            requires = \"pkg/0.1@user/testing\"\n            options = {\"shared\": [True, False, \"header\"]}\n            default_options = {\"shared\": False}\n            def package_info(self):\n                self.output.info(\"PKG2 OPTION: %s\" % self.options.shared)\n        \"\"\")})\n\n    client.run(\"create . --name=pkg2 --version=0.1 --user=user --channel=testing -o *:shared=True\")\n    assert \"pkg/0.1@user/testing: PKG OPTION: True\" in client.out\n    assert \"pkg2/0.1@user/testing: PKG2 OPTION: True\" in client.out\n    client.run(\" install --requires=pkg2/0.1@user/testing -o *:shared=True\")\n    assert \"pkg/0.1@user/testing: PKG OPTION: True\" in client.out\n    assert \"pkg2/0.1@user/testing: PKG2 OPTION: True\" in client.out\n    # Priority of non-scoped options\n    client.run(\"create . --name=pkg2 --version=0.1 --user=user --channel=testing -o shared=header -o *:shared=True\")\n    assert \"pkg/0.1@user/testing: PKG OPTION: True\" in client.out\n    assert \"pkg2/0.1@user/testing: PKG2 OPTION: header\" in client.out\n    client.run(\" install --requires=pkg2/0.1@user/testing -o shared=header -o *:shared=True\")\n    assert \"pkg/0.1@user/testing: PKG OPTION: True\" in client.out\n    assert \"pkg2/0.1@user/testing: PKG2 OPTION: header\" in client.out\n    # Prevalence of exact named option\n    client.run(\"create . --name=pkg2 --version=0.1 --user=user --channel=testing -o *:shared=True -o pkg2*:shared=header\")\n    assert \"pkg/0.1@user/testing: PKG OPTION: True\" in client.out\n    assert \"pkg2/0.1@user/testing: PKG2 OPTION: header\" in client.out\n    client.run(\" install --requires=pkg2/0.1@user/testing -o *:shared=True -o pkg2*:shared=header\")\n    assert \"pkg/0.1@user/testing: PKG OPTION: True\" in client.out\n    assert \"pkg2/0.1@user/testing: PKG2 OPTION: header\" in client.out\n    # Prevalence of exact named option reverse\n    client.run(\"create . --name=pkg2 --version=0.1 --user=user --channel=testing -o *:shared=True -o pkg/*:shared=header \"\n               \"--build=missing\")\n    assert \"pkg/0.1@user/testing: PKG OPTION: header\" in client.out\n    assert \"pkg2/0.1@user/testing: PKG2 OPTION: True\" in client.out\n    client.run(\" install --requires=pkg2/0.1@user/testing -o *:shared=True -o pkg/*:shared=header\")\n    assert \"pkg/0.1@user/testing: PKG OPTION: header\" in client.out\n    assert \"pkg2/0.1@user/testing: PKG2 OPTION: True\" in client.out\n    # Prevalence of alphabetical pattern\n    client.run(\"create . --name=pkg2 --version=0.1 --user=user --channel=testing -o *:shared=True -o pkg2*:shared=header\")\n    assert \"pkg/0.1@user/testing: PKG OPTION: True\" in client.out\n    assert \"pkg2/0.1@user/testing: PKG2 OPTION: header\" in client.out\n    client.run(\" install --requires=pkg2/0.1@user/testing -o *:shared=True -o pkg2*:shared=header\")\n    assert \"pkg/0.1@user/testing: PKG OPTION: True\" in client.out\n    assert \"pkg2/0.1@user/testing: PKG2 OPTION: header\" in client.out\n    # Prevalence of last match, even first pattern match\n    client.run(\"create . --name=pkg2 --version=0.1 --user=user --channel=testing -o pkg2*:shared=header -o *:shared=True\")\n    assert \"pkg/0.1@user/testing: PKG OPTION: True\" in client.out\n    assert \"pkg2/0.1@user/testing: PKG2 OPTION: True\" in client.out\n    client.run(\" install --requires=pkg2/0.1@user/testing -o pkg2*:shared=header -o *:shared=True\")\n    assert \"pkg/0.1@user/testing: PKG OPTION: True\" in client.out\n    assert \"pkg2/0.1@user/testing: PKG2 OPTION: True\" in client.out\n    # Prevalence and override of alphabetical pattern\n    client.run(\"create . --name=pkg2 --version=0.1 --user=user --channel=testing -o *:shared=True -o pkg*:shared=header\")\n    assert \"pkg/0.1@user/testing: PKG OPTION: header\" in client.out\n    assert \"pkg2/0.1@user/testing: PKG2 OPTION: header\" in client.out\n    client.run(\" install --requires=pkg2/0.1@user/testing -o *:shared=True -o pkg*:shared=header\")\n    assert \"pkg/0.1@user/testing: PKG OPTION: header\" in client.out\n    assert \"pkg2/0.1@user/testing: PKG2 OPTION: header\" in client.out\n\n\ndef test_install_package_folder(client):\n    # Make sure a simple conan install doesn't fire package_info() so self.package_folder breaks\n    client.save({\"conanfile.py\": textwrap.dedent(\"\"\"\\\n        from conan import ConanFile\n        import os\n        class Pkg(ConanFile):\n            def package_info(self):\n                self.dummy_doesnt_exist_not_break\n                self.output.info(\"Hello\")\n                self.env_info.PATH = os.path.join(self.package_folder, \"bin\")\n        \"\"\")})\n    client.run(\"install .\")\n    assert \"Hello\" not in client.out\n\n\ndef test_install_cwd(client):\n    client.save({\"conanfile.py\": GenConanfile(\"hello\", \"0.1\").with_setting(\"os\")})\n    client.run(\"export . --user=lasote --channel=stable\")\n    client.save({\"conanfile.txt\": \"[requires]\\nhello/0.1@lasote/stable\"}, clean_first=True)\n\n    client.run(\"install . --build=missing -s os_build=Windows\")\n    assert \"hello/0.1@lasote/stable#a20db3358243e96aa07f654eaada1564 - Cache\" in client.out\n\n\ndef test_install_with_profile(client):\n    # Test for https://github.com/conan-io/conan/pull/2043\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class TestConan(ConanFile):\n            settings = \"os\"\n            def requirements(self):\n                self.output.info(\"PKGOS=%s\" % self.settings.os)\n        \"\"\")\n\n    client.save({\"conanfile.py\": conanfile})\n    save(os.path.join(client.paths.profiles_path, \"myprofile\"), \"[settings]\\nos=Linux\")\n    client.run(\"install . -pr=myprofile --build='*'\")\n    assert \"PKGOS=Linux\" in client.out\n    mkdir(os.path.join(client.current_folder, \"myprofile\"))\n    client.run(\"install . -pr=myprofile\")\n    save(os.path.join(client.paths.profiles_path, \"myotherprofile\"), \"[settings]\\nos=FreeBSD\")\n    client.run(\"install . -pr=myotherprofile\")\n    assert \"PKGOS=FreeBSD\" in client.out\n    client.save({\"myotherprofile\": \"Some garbage without sense [garbage]\"})\n    client.run(\"install . -pr=myotherprofile\")\n    assert \"PKGOS=FreeBSD\" in client.out\n    client.run(\"install . -pr=./myotherprofile\", assert_error=True)\n    assert \"Error while parsing line 0\" in client.out\n\n\ndef test_install_with_path_errors(client):\n    # Install without path param allowed, but nothing found\n    client.run(\"install\", assert_error=True)\n    assert \"Conanfile not found\" in client.out\n\n    # Install without path param allowed, but nothing found\n    client.run(\"install . --requires=foo/1.0\", assert_error=True)\n    assert \"--requires and --tool-requires arguments are incompatible with [path]\" in client.out\n\n    # Path with wrong conanfile.txt path\n    client.run(\"install not_real_dir/conanfile.txt\", assert_error=True)\n    assert \"Conanfile not found\" in client.out\n\n\ndef test_install_argument_order(client):\n    # https://github.com/conan-io/conan/issues/2520\n    conanfile_boost = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class BoostConan(ConanFile):\n            name = \"boost\"\n            version = \"0.1\"\n            options = {\"shared\": [True, False]}\n            default_options = {\"shared\": True}\n        \"\"\")\n    conanfile = GenConanfile().with_require(\"boost/0.1\")\n\n    client.save({\"conanfile.py\": conanfile,\n                 \"conanfile_boost.py\": conanfile_boost})\n    client.run(\"create conanfile_boost.py \")\n    client.run(\"install . -o boost/*:shared=True --build=missing\")\n    output_0 = client.out\n    client.run(\"install . -o boost/*:shared=True --build missing\")\n    output_1 = client.out\n    client.run(\"install -o boost/*:shared=True . --build missing\")\n    output_2 = client.out\n    client.run(\"install -o boost/*:shared=True --build missing .\")\n    output_3 = client.out\n    assert \"ERROR\" not in output_3\n    assert output_0 == output_1\n    assert output_1 == output_2\n    assert output_2 == output_3\n\n    client.run(\"install -o boost/*:shared=True --build boost . --build missing\")\n    output_4 = client.out\n    client.run(\"install -o boost/*:shared=True --build missing --build boost .\")\n    output_5 = client.out\n    assert output_4 == output_5\n\n\ndef test_install_anonymous(client):\n    # https://github.com/conan-io/conan/issues/4871\n    client.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n    client.run(\"create . --user=lasote --channel=testing\")\n    client.run(\"upload * --confirm -r default\")\n    client2 = TestClient(servers=client.servers, inputs=[])\n    client2.run(\"install --requires=pkg/0.1@lasote/testing\")\n    assert \"pkg/0.1@lasote/testing: Package installed\" in client2.out\n\n\n@pytest.mark.artifactory_ready\ndef test_install_without_ref(client):\n    client.save({\"conanfile.py\": GenConanfile(\"lib\", \"1.0\")})\n    client.run('create .')\n    assert \"lib/1.0: Package '{}' created\".format(NO_SETTINGS_PACKAGE_ID) in client.out\n\n    client.run('upload lib/1.0 -c -r default')\n    assert \"Uploading recipe 'lib/1.0\" in client.out\n\n    client.run('remove \"*\" -c')\n\n    # This fails, Conan thinks this is a path\n    client.run('install lib/1.0', assert_error=True)\n    fake_path = os.path.join(client.current_folder, \"lib\", \"1.0\")\n    assert \"Conanfile not found at {}\".format(fake_path) in client.out\n\n    # Try this syntax to upload too\n    client.run('install --requires=lib/1.0@')\n    client.run('upload lib/1.0 -c -r default')\n\n\n@pytest.mark.artifactory_ready\ndef test_install_disabled_remote(client):\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"create . --name=pkg --version=0.1 --user=lasote --channel=testing\")\n    client.run(\"upload * --confirm -r default\")\n    client.run(\"remote disable default\")\n    client.run(\"install --requires=pkg/0.1@lasote/testing -r default\", assert_error=True)\n    assert \"ERROR: Remote 'default' can't be found or is disabled\" in client.out\n    client.run(\"remote enable default\")\n    client.run(\"install --requires=pkg/0.1@lasote/testing -r default\")\n    client.run(\"remote disable default\")\n    client.run(\"install --requires=pkg/0.1@lasote/testing --update -r default\", assert_error=True)\n    assert \"ERROR: Remote 'default' can't be found or is disabled\" in client.out\n\n\ndef test_install_no_remotes(client):\n    client.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n    client.run(\"create .\")\n    client.run(\"upload * --confirm -r default\")\n    client.run(\"remove * -c\")\n    client.run(\"install --requires=pkg/0.1 -nr\", assert_error=True)\n    assert \"ERROR: Package 'pkg/0.1' not resolved: No remote defined\" in client.out\n    client.run(\"install --requires=pkg/0.1\")  # this works without issue\n    client.run(\"install --requires=pkg/0.1 -nr\")  # and now this too, pkg in cache\n\n\ndef test_install_skip_disabled_remote():\n    client = TestClient(servers=OrderedDict({\"default\": TestServer(),\n                                             \"server2\": TestServer(),\n                                             \"server3\": TestServer()}),\n                        inputs=2*[\"admin\", \"password\"])\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"create . --name=pkg --version=0.1 --user=lasote --channel=testing\")\n    client.run(\"upload * --confirm -r default\")\n    client.run(\"upload * --confirm -r server3\")\n    client.run(\"remove * -c\")\n    client.run(\"remote disable default\")\n    client.run(\"install --requires=pkg/0.1@lasote/testing\", assert_error=False)\n    assert \"Trying with 'default'...\" not in client.out\n\n\ndef test_install_without_update_fail(client):\n    # https://github.com/conan-io/conan/issues/9183\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"create . --name=zlib --version=1.0\")\n    client.run(\"upload * --confirm -r default\")\n    client.save({\"conanfile.py\": GenConanfile().with_requires(\"zlib/1.0\")})\n    client.run(\"remote disable default\")\n    client.run(\"install .\")\n    assert \"zlib/1.0: Already installed\" in client.out\n\n\ndef test_install_version_range_reference(client):\n    # https://github.com/conan-io/conan/issues/5905\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"create . --name=pkg --version=0.1 --user=user --channel=channel\")\n    client.run(\"install --requires=pkg/[*]@user/channel\")\n    assert \"pkg/0.1@user/channel: Already installed!\" in client.out\n    client.run(\"install --requires=pkg/[>0]@user/channel\")\n    assert \"pkg/0.1@user/channel: Already installed!\" in client.out\n\n\ndef test_install_error_never(client):\n    client.save({\"conanfile.py\": GenConanfile(\"hello0\", \"0.1\")})\n    client.run(\"create .\")\n    client.run(\"install . --build never --build missing\", assert_error=True)\n    assert \"ERROR: --build=never not compatible with other options\" in client.out\n    client.run(\"install conanfile.py --build never --build Hello\", assert_error=True)\n    assert \"ERROR: --build=never not compatible with other options\" in client.out\n    client.run(\"install ./conanfile.py --build never --build outdated\", assert_error=True)\n    assert \"ERROR: --build=never not compatible with other options\" in client.out\n\n\ndef test_package_folder_available_consumer():\n    \"\"\"\n    The package folder is not available when doing a consumer conan install \".\"\n    We don't want to provide the package folder for the \"cmake install\" nor the \"make install\",\n    as a consumer you could call the build system and pass the prefix PATH manually.\n    \"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    from conan.tools.cmake import cmake_layout\n    class HelloConan(ConanFile):\n        settings = \"os\", \"arch\", \"build_type\"\n        def layout(self):\n            cmake_layout(self)\n        def generate(self):\n            self.output.warning(\"Package folder is None? {}\".format(self.package_folder is None))\n            self.output.warning(\"Package folder: {}\".format(self.package_folder))\n    \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n\n    # Installing it with \"install .\" with output folder\n    client.run(\"install . -of=my_build\")\n    assert \"WARN: Package folder is None? True\" in client.out\n\n    # Installing it with \"install .\" without output folder\n    client.run(\"install .\")\n    assert \"WARN: Package folder is None? True\" in client.out\n\n\ndef test_install_multiple_requires_cli():\n    \"\"\"\n    Test that it is possible to install multiple --requires=xxx --requires=yyy\n    \"\"\"\n    c = TestClient()\n    c.save({\"conanfile.py\": GenConanfile()})\n    c.run(\"create . --name=pkg1 --version=0.1\")\n    c.run(\"create . --name=pkg2 --version=0.1\")\n\n    c.run(\"graph info --requires=pkg1/0.1 --requires=pkg2/0.1\")\n    assert \"pkg1/0.1\" in c.out\n    assert \"pkg2/0.1\" in c.out\n    c.run(\"install --requires=pkg1/0.1 --requires=pkg2/0.1\")\n    assert \"pkg1/0.1\" in c.out\n    assert \"pkg2/0.1\" in c.out\n    c.run(\"lock create --requires=pkg1/0.1 --requires=pkg2/0.1 --lockfile-out=conan.lock\")\n    lock = c.load(\"conan.lock\")\n    assert \"pkg1/0.1\" in lock\n    assert \"pkg2/0.1\" in lock\n\n\ndef test_install_json_formatter():\n    \"\"\"\n    Tests the ``conan install . -f json`` result\n    \"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class MyTest(ConanFile):\n            name = \"pkg\"\n            version = \"0.2\"\n\n            def package_info(self):\n                self.cpp_info.libs = [\"pkg\"]\n                self.cpp_info.includedirs = [\"path/includes/pkg\", \"other/include/path/pkg\"]\n                self.cpp_info.libdirs = [\"one/lib/path/pkg\"]\n                self.cpp_info.defines = [\"pkg_onedefinition\", \"pkg_twodefinition\"]\n                self.cpp_info.cflags = [\"pkg_a_c_flag\"]\n                self.cpp_info.cxxflags = [\"pkg_a_cxx_flag\"]\n                self.cpp_info.sharedlinkflags = [\"pkg_shared_link_flag\"]\n                self.cpp_info.exelinkflags = [\"pkg_exe_link_flag\"]\n                self.cpp_info.sysroot = \"/path/to/folder/pkg\"\n                self.cpp_info.frameworks = [\"pkg_oneframework\", \"pkg_twoframework\"]\n                self.cpp_info.system_libs = [\"pkg_onesystemlib\", \"pkg_twosystemlib\"]\n                self.cpp_info.frameworkdirs = [\"one/framework/path/pkg\"]\n                self.cpp_info.set_property(\"pkg_config_name\", \"pkg_other_name\")\n                self.cpp_info.set_property(\"pkg_config_aliases\", [\"pkg_alias1\", \"pkg_alias2\"])\n                self.cpp_info.components[\"cmp1\"].libs = [\"libcmp1\"]\n                self.cpp_info.components[\"cmp1\"].set_property(\"pkg_config_name\", \"compo1\")\n                self.cpp_info.components[\"cmp1\"].set_property(\"pkg_config_aliases\", [\"compo1_alias\"])\n                self.cpp_info.components[\"cmp1\"].sysroot = \"/another/sysroot\"\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create .\")\n    client.save({\"conanfile.py\": GenConanfile().with_name(\"hello\").with_version(\"0.1\")\n                .with_require(\"pkg/0.2\")}, clean_first=True)\n    client.run(\"install . -f json\")\n    info = json.loads(client.stdout)\n    nodes = info[\"graph\"][\"nodes\"]\n    hello_pkg_ref = 'hello/0.1'  # no revision available\n    pkg_pkg_ref = 'pkg/0.2#926714b5fb0a994f47ec37e071eba1da'\n    hello_cpp_info = pkg_cpp_info = None\n    for _, n in nodes.items():\n        ref = n[\"ref\"]\n        if ref == hello_pkg_ref:\n            assert n['binary'] is None\n            hello_cpp_info = n['cpp_info']\n        elif ref == pkg_pkg_ref:\n            assert n['binary'] == \"Cache\"\n            pkg_cpp_info = n['cpp_info']\n\n    hello = nodes[\"0\"]\n    assert hello[\"ref\"] == hello_pkg_ref\n    assert hello[\"recipe_folder\"] == client.current_folder\n    assert hello[\"build_folder\"] == client.current_folder\n    assert hello[\"generators_folder\"] == client.current_folder\n    assert hello[\"package_folder\"] is None\n\n    assert hello_cpp_info and pkg_cpp_info\n    # hello/0.1 cpp_info\n    assert hello_cpp_info['root'][\"libs\"] is None\n    assert len(hello_cpp_info['root'][\"bindirs\"]) == 1\n    assert len(hello_cpp_info['root'][\"libdirs\"]) == 1\n    assert hello_cpp_info['root'][\"sysroot\"] is None\n    assert hello_cpp_info['root'][\"properties\"] is None\n    # pkg/0.2 cpp_info\n    # root info\n    assert pkg_cpp_info['root'][\"libs\"] == ['pkg']\n    assert len(pkg_cpp_info['root'][\"bindirs\"]) == 1\n    assert len(pkg_cpp_info['root'][\"libdirs\"]) == 1\n    assert pkg_cpp_info['root'][\"sysroot\"] == '/path/to/folder/pkg'\n    assert pkg_cpp_info['root'][\"system_libs\"] == ['pkg_onesystemlib', 'pkg_twosystemlib']\n    assert pkg_cpp_info['root']['cflags'] == ['pkg_a_c_flag']\n    assert pkg_cpp_info['root']['cxxflags'] == ['pkg_a_cxx_flag']\n    assert pkg_cpp_info['root']['defines'] == ['pkg_onedefinition', 'pkg_twodefinition']\n    assert pkg_cpp_info['root'][\"properties\"] == {\n        'pkg_config_aliases': ['pkg_alias1', 'pkg_alias2'],\n        'pkg_config_name': 'pkg_other_name'}\n    # component info\n    assert pkg_cpp_info['cmp1'][\"libs\"] == ['libcmp1']\n    assert pkg_cpp_info['cmp1'][\"bindirs\"][0].endswith(\"bin\")  # Abs path /bin\n    assert pkg_cpp_info['cmp1'][\"libdirs\"][0].endswith(\"lib\")  # Abs path /lib\n    assert pkg_cpp_info['cmp1'][\"sysroot\"] == \"/another/sysroot\"\n    assert pkg_cpp_info['cmp1'][\"properties\"] == {'pkg_config_aliases': ['compo1_alias'],\n                                                  'pkg_config_name': 'compo1'}\n\n\ndef test_upload_skip_binaries_not_hit_server():\n    \"\"\"\n    When upload_policy = \"skip\", no need to try to install from servers\n    \"\"\"\n    c = TestClient(servers={\"default\": None})  # Broken server, will raise error if used\n    conanfile = GenConanfile(\"pkg\", \"0.1\").with_class_attribute('upload_policy = \"skip\"')\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"export .\")\n    c.run(\"install --requires=pkg/0.1 --build=missing\")\n    # This would crash if hits the server, but it doesnt\n    assert \"pkg/0.1: Created package\" in c.out\n\n\ndef test_upload_skip_build_missing():\n    c = TestClient(default_server_user=True)\n    pkg1 = GenConanfile(\"pkg1\", \"1.0\").with_class_attribute('upload_policy = \"skip\"')\n    pkg2 = GenConanfile(\"pkg2\", \"1.0\").with_requirement(\"pkg1/1.0\", visible=False)\n    pkg3 = GenConanfile(\"pkg3\", \"1.0\").with_requirement(\"pkg2/1.0\")\n    c.save({\"pkg1/conanfile.py\": pkg1,\n            \"pkg2/conanfile.py\": pkg2,\n            \"pkg3/conanfile.py\": pkg3,\n            })\n    c.run(\"create pkg1\")\n    c.run(\"create pkg2\")\n    c.run(\"remove pkg1/*:* -c\")  # remove binaries\n    c.run(\"create pkg3 --build=missing\")\n    assert re.search(r\"Skipped binaries(\\s*)pkg1/1.0\", c.out)\n\n\ndef test_upload_skip_build_compatibles():\n    c = TestClient()\n    pkg1 = textwrap.dedent(\"\"\"\\\n        from conan import ConanFile\n        class Pkg1(ConanFile):\n            name = \"pkg1\"\n            version = \"1.0\"\n            settings = \"build_type\"\n            upload_policy = \"skip\"\n            def compatibility(self):\n                if self.settings.build_type == \"Debug\":\n                    return [{\"settings\": [(\"build_type\", \"Release\")]}]\n            \"\"\")\n    pkg2 = GenConanfile(\"pkg2\", \"1.0\").with_requirement(\"pkg1/1.0\")\n    pkg3 = GenConanfile(\"pkg3\", \"1.0\").with_requirement(\"pkg2/1.0\")\n    c.save({\"pkg1/conanfile.py\": pkg1,\n            \"pkg2/conanfile.py\": pkg2,\n            \"pkg3/conanfile.py\": pkg3,\n            })\n    c.run(\"create pkg1 -s build_type=Release\")\n    pkg1id = c.created_package_id(\"pkg1/1.0\")\n    c.run(\"create pkg2 -s build_type=Release\")\n    c.run(\"remove pkg1/*:* -c\")  # remove binaries\n    c.run(\"create pkg3 -s build_type=Release --build=missing\")\n    c.assert_listed_binary({\"pkg1/1.0\": (pkg1id, \"Build\")})\n    c.run(\"install pkg3 -s build_type=Debug --build=missing\")\n    c.assert_listed_binary({\"pkg1/1.0\": (pkg1id, \"Cache\")})\n\n\ndef test_install_json_format():\n    # https://github.com/conan-io/conan/issues/14414\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class MyTest(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            settings = \"build_type\"\n\n            def package_info(self):\n                self.conf_info.define(\"user.myteam:myconf\", \"myvalue\")\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create .\")\n    client.run(\"install --requires=pkg/0.1 --format=json\")\n    data = json.loads(client.stdout)\n    conf_info = data[\"graph\"][\"nodes\"][\"1\"][\"conf_info\"]\n    assert {'user.myteam:myconf': 'myvalue'} == conf_info\n\n\ndef test_install_json_format_not_visible():\n    \"\"\"\n    The dependencies that are needed at built time, even if they are not visible, or not standard\n    libraries (headers=False, libs=False, run=False), like for example some build assets\n    So direct dependencies of a consumer package or a package that needs to be built cannot be\n    skipped\n    \"\"\"\n    c = TestClient()\n    dep = GenConanfile(\"dep\", \"0.1\").with_package_file(\"somefile.txt\", \"contents!!!\")\n    app = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import load\n\n        class Pkg(ConanFile):\n            settings = \"os\", \"arch\", \"build_type\"\n            name=\"pkg\"\n            version=\"0.0.1\"\n\n            def requirements(self):\n                self.requires(\"dep/0.1\", visible=False, headers=False, libs=False, run=False)\n\n            def build(self):\n                p = os.path.join(self.dependencies[\"dep\"].package_folder, \"somefile.txt\")\n                c = load(self, p)\n                self.output.info(f\"LOADED! {c}\")\n        \"\"\")\n    c.save({\"dep/conanfile.py\": dep,\n            \"app/conanfile.py\": app})\n    c.run(\"export-pkg dep\")\n    c.run(\"install app --format=json\")\n    c.assert_listed_binary({\"dep/0.1\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\", \"Cache\")})\n    data = json.loads(c.stdout)\n    pkg_folder = data[\"graph\"][\"nodes\"][\"1\"][\"package_folder\"]\n    assert pkg_folder is not None\n\n    c.run(\"create app\")\n    assert \"pkg/0.0.1: LOADED! contents!!!\" in c.out\n"
  },
  {
    "path": "test/integration/command/install/install_update_test.py",
    "content": "import os\nimport textwrap\nfrom time import sleep\n\nfrom conan.api.model import RecipeReference\nfrom conan.test.utils.tools import TestClient, GenConanfile, TestServer\nfrom conan.internal.util.files import load\n\n\ndef test_update_binaries():\n    client = TestClient(default_server_user=True)\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import save, load\n        import os, random\n        class Pkg(ConanFile):\n            def package(self):\n                save(self, os.path.join(self.package_folder, \"file.txt\"), str(random.random()))\n\n            def package_info(self):\n                content = load(self, os.path.join(self.package_folder, \"file.txt\"))\n                self.output.warning(\"CONTENT=>{}#\".format(content))\n\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=pkg --version=0.1 --user=lasote --channel=testing\")\n    client.run(\"upload pkg/0.1@lasote/testing -r default\")\n\n    client2 = TestClient(servers=client.servers, inputs=[\"admin\", \"password\"])\n    client2.run(\"install --requires=pkg/0.1@lasote/testing\")\n\n    def get_value_from_output(output):\n        tmp = str(output).split(\"CONTENT=>\")[1]\n        return tmp.split(\"#\")[0]\n\n    value = get_value_from_output(client2.out)\n\n    client.run(\"create . --name=pkg --version=0.1 --user=lasote --channel=testing\")  # Because of random, this should be NEW prev\n    client.run(\"upload pkg/0.1@lasote/testing -r default\")\n\n    client2.run(\"install --requires=pkg/0.1@lasote/testing\")\n    new_value = get_value_from_output(client2.out)\n    assert value == new_value\n\n    client2.run(\"install --requires=pkg/0.1@lasote/testing --update\")\n    assert \"Current package revision is older than the remote one\" in client2.out\n    new_value = get_value_from_output(client2.out)\n    assert value != new_value\n\n    # Now check newer local modifications are not overwritten\n    client.run(\"create . --name=pkg --version=0.1 --user=lasote --channel=testing\")\n    client.run(\"upload pkg/0.1@lasote/testing -r default\")\n\n    client2.save({\"conanfile.py\": conanfile})\n    client2.run(\"create . --name=pkg --version=0.1 --user=lasote --channel=testing\")\n    client2.run(\"install --requires=pkg/0.1@lasote/testing\")\n    value2 = get_value_from_output(client2.out)\n    client2.run(\"install --requires=pkg/0.1@lasote/testing --update -r default\")\n    assert \"Current package revision is newer than the remote one\" in client2.out\n    new_value = get_value_from_output(client2.out)\n    assert value2 == new_value\n\n\ndef test_update_not_date():\n    client = TestClient(default_server_user=True)\n    # Regression for https://github.com/conan-io/conan/issues/949\n    client.save({\"conanfile.py\": GenConanfile(\"hello0\", \"1.0\")})\n    client.run(\"export . --user=lasote --channel=stable\")\n    client.save({\"conanfile.py\": GenConanfile(\"hello1\", \"1.0\").\n                with_requirement(\"hello0/1.0@lasote/stable\")},\n                clean_first=True)\n    client.run(\"install . --build='*'\")\n    client.run(\"upload hello0/1.0@lasote/stable -r default\")\n\n    prev = client.get_latest_package_reference(\"hello0/1.0@lasote/stable\")\n\n    ref = RecipeReference.loads(\"hello0/1.0@lasote/stable\")\n\n    initial_recipe_timestamp = client.cache.get_latest_recipe_revision(ref).timestamp\n    initial_package_timestamp = prev.timestamp\n\n    # Change and rebuild package\n    client.save({\"conanfile.py\": GenConanfile(\"hello0\", \"1.0\").with_class_attribute(\"author = 'O'\")},\n                clean_first=True)\n    client.run(\"export . --user=lasote --channel=stable\")\n    client.run(\"install --requires=hello0/1.0@lasote/stable --build='*'\")\n\n    rebuild_recipe_timestamp = client.cache.get_latest_recipe_revision(ref).timestamp\n    rebuild_package_timestamp = client.get_latest_package_reference(ref).timestamp\n\n    assert rebuild_recipe_timestamp != initial_recipe_timestamp\n    assert rebuild_package_timestamp != initial_package_timestamp\n\n    # back to the consumer, try to update\n    client.save({\"conanfile.py\": GenConanfile(\"hello1\", \"1.0\").\n                with_requirement(\"hello0/1.0@lasote/stable\")}, clean_first=True)\n    # First assign the preference to a remote, it has been cleared when exported locally\n    client.run(\"install . --update\")\n    # *1 With revisions here is removing the package because it doesn't belong to the recipe\n\n    client.assert_listed_require({\"hello0/1.0@lasote/stable\": \"Newer\"})\n\n    failed_update_recipe_timestamp = client.cache.get_latest_recipe_revision(ref).timestamp\n    failed_update_package_timestamp = client.get_latest_package_reference(ref).timestamp\n\n    assert rebuild_recipe_timestamp == failed_update_recipe_timestamp\n    assert rebuild_package_timestamp == failed_update_package_timestamp\n\n\ndef test_reuse():\n    client = TestClient(default_server_user=True)\n    conanfile = GenConanfile(\"hello0\", \"1.0\")\\\n        .with_exports_sources(\"*\")\\\n        .with_import(\"from conan.tools.files import copy\")\\\n        .with_package(\"copy(self, '*', self.source_folder, self.package_folder)\")\n    client.save({\"conanfile.py\": conanfile,\n                 \"header.h\": \"content1\"})\n    client.run(\"export . --user=lasote --channel=stable\")\n    client.run(\"install --requires=hello0/1.0@lasote/stable --build='*'\")\n    client.run(\"upload hello0/1.0@lasote/stable -r default\")\n\n    client2 = TestClient(servers=client.servers, inputs=[\"admin\", \"password\"])\n    client2.run(\"install --requires=hello0/1.0@lasote/stable\")\n    assert \"hello0/1.0@lasote/stable: Retrieving package\" in client2.out\n\n    client.save({\"header.h\": \"//EMPTY!\"})\n    sleep(1)\n    client.run(\"export . --user=lasote --channel=stable\")\n    client.run(\"install --requires=hello0/1.0@lasote/stable --build='*'\")\n    client.run(\"upload hello0/1.0@lasote/stable -r default\")\n\n    client2.run(\"install --requires=hello0/1.0@lasote/stable --update\")\n    ref = RecipeReference.loads(\"hello0/1.0@lasote/stable\")\n    pref = client.get_latest_package_reference(ref)\n    package_path = client2.get_latest_pkg_layout(pref).package()\n    header = load(os.path.join(package_path, \"header.h\"))\n    assert header == \"//EMPTY!\"\n\n\ndef test_update_binaries_failed():\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"create . --name=pkg --version=0.1 --user=lasote --channel=testing\")\n    client.run(\"install --requires=pkg/0.1@lasote/testing --update\")\n    assert \"WARN: Can't update, there are no remotes defined\" in client.out\n\n\ndef test_install_update_repeated_tool_requires():\n    \"\"\"\n    Test that requiring the same thing multiple times, like a tool-requires, only\n    require checking the servers 1, so it is much faster\n\n    https://github.com/conan-io/conan/issues/13508\n    \"\"\"\n    c = TestClient(default_server_user=True)\n    c.save({\"tool/conanfile.py\": GenConanfile(\"tool\", \"0.1\"),\n            \"liba/conanfile.py\": GenConanfile(\"liba\", \"0.1\"),\n            \"libb/conanfile.py\": GenConanfile(\"libb\", \"0.1\").with_requires(\"liba/0.1\"),\n            \"libc/conanfile.py\": GenConanfile(\"libc\", \"0.1\").with_requires(\"libb/0.1\"),\n            \"profile\": \"[tool_requires]\\ntool/0.1\"\n            })\n    c.run(\"create tool\")\n    c.run(\"create liba\")\n    c.run(\"create libb\")\n    c.run(\"create libc\")\n    c.run(\"install libc --update -pr=profile\")\n    assert 1 == str(c.out).count(\"tool/0.1: Checking remote\")\n\n\nclass TestUpdateOldPolicy:\n    def test_multi_remote_update_resolution(self):\n        c = TestClient(servers={\"r1\": TestServer(), \"r2\": TestServer(), \"r3\": TestServer()},\n                       inputs=[\"admin\", \"password\"] * 3, light=True)\n        c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n        c.run(\"export .\")\n        rev1 = c.exported_recipe_revision()\n        c.run(\"upload * -r=r1 -c\")\n        # second revision\n        c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_class_attribute(\"auther = 'me'\")})\n        c.run(\"export .\")\n        rev2 = c.exported_recipe_revision()\n        assert rev1 != rev2\n        c.run(\"upload * -r=r2 -c\")  # By default uploads latest revisions only\n        assert rev1 not in c.out\n        assert rev2 in c.out\n        # going back to the previous revision\n        c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n        c.run(\"export .\")  # Makes it the latest\n        rev3 = c.exported_recipe_revision()\n        assert rev1 == rev3\n        c.run(\"upload * -r=r3 -c\")  # By default uploads latest revisions only\n        assert rev3 in c.out\n        assert rev2 not in c.out\n\n        # now test the --update, it will pick up the latest revision, which is r3\n        c.run(\"remove * -c\")\n        c.run(\"graph info --requires=pkg/0.1 --update\")\n        assert f\"pkg/0.1#{rev3} - Downloaded (r3)\" in c.out\n\n        # But if we enable order-based first found timestamp, it will pick up r2\n        c.run(\"remove * -c\")\n        c.run(\"graph info --requires=pkg/0.1 --update -cc core:update_policy=legacy\")\n        assert \"The 'core:update_policy' conf is deprecated and will be removed\" in c.out\n        assert f\"pkg/0.1#{rev2} - Downloaded (r2)\" in c.out\n\n    def test_multi_remote_update_resolution_2_remotes(self):\n        c = TestClient(servers={\"r1\": TestServer(), \"r2\": TestServer()},\n                       inputs=[\"admin\", \"password\"] * 2, light=True)\n        c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n        c.run(\"export .\")\n        rev1 = c.exported_recipe_revision()\n        c.run(\"upload * -r=r1 -c\")\n        # second revision\n        c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_class_attribute(\"auther = 'me'\")})\n        c.run(\"export .\")\n        rev2 = c.exported_recipe_revision()\n        assert rev1 != rev2\n        c.run(\"upload * -r=r1 -c\")\n        c.run(\"list *#* -r=r1\")\n\n        # Upload the first, old revision to the other remote\n        c.run(f\"upload pkg/0.1#{rev1} -r=r2 -c\")\n        assert rev1 in c.out\n        assert rev2 not in c.out\n        c.run(\"list *#* -r=r2\")\n\n        # now test the --update, it will pick up the latest revision, which is r3\n        c.run(\"remove * -c\")\n        c.run(\"graph info --requires=pkg/0.1 --update\")\n        assert f\"pkg/0.1#{rev1} - Downloaded (r2)\" in c.out\n\n        # But if we enable order-based first found timestamp, it will pick up r2\n        c.run(\"remove * -c\")\n        c.run(\"graph info --requires=pkg/0.1 --update -cc core:update_policy=legacy\")\n        assert f\"pkg/0.1#{rev2} - Downloaded (r1)\" in c.out\n\n    def test_lockfile(self):\n        # https://github.com/conan-io/conan/issues/18006\n        c = TestClient(default_server_user=True, light=True)  # needs server to fail\n        c.save_home({\"global.conf\": \"core:update_policy=legacy\"})\n        c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\"),\n                \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_python_requires(\"dep/0.1\")})\n        c.run(\"create dep\")\n        c.run(\"lock create pkg --lockfile-out base.lock --build=* --update\")\n        c.run(\"lock create pkg --lockfile base.lock --lockfile-out full.lock --build=* --update\")\n        # it doesn't crash\n        assert \"Generated lockfile\" in c.out\n"
  },
  {
    "path": "test/integration/command/install/test_graph_build_mode.py",
    "content": "import json\n\nimport pytest\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.fixture(scope=\"module\")\ndef build_all():\n    \"\"\" Build a simple graph to test --build option\n        foobar <- bar <- foo\n               <--------|\n        All packages are built from sources to keep a cache.\n    :return: TestClient instance\n    \"\"\"\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile().with_setting(\"build_type\")})\n    client.run(\"export . --name=foo --version=1.0 --user=user --channel=testing\")\n    client.save({\"conanfile.py\": GenConanfile().with_require(\"foo/1.0@user/testing\")\n                .with_setting(\"build_type\")})\n    client.run(\"export . --name=bar --version=1.0 --user=user --channel=testing\")\n    client.save({\"conanfile.py\": GenConanfile().with_require(\"foo/1.0@user/testing\")\n                .with_require(\"bar/1.0@user/testing\")\n                .with_setting(\"build_type\")})\n    client.run(\"export . --name=foobar --version=1.0 --user=user --channel=testing\")\n    client.run(\"install --requires=foobar/1.0@user/testing --build='*'\")\n    return client\n\n\nfoo_id = \"efa83b160a55b033c4ea706ddb980cd708e3ba1b\"\nbar_id = \"7d0bb2b97d4339b0d3ded1418a2593f35b9cf267\"\nfoobar_id = \"af8f885f621ba7baac3f5b1d2c18cfdf5ba2550c\"\n\n\ndef check_if_build_from_sources(refs_modes, output):\n    for ref, mode in refs_modes.items():\n        if mode == \"Build\":\n            assert \"{}/1.0@user/testing: Forced build from source\".format(ref) in output\n        else:\n            assert \"{}/1.0@user/testing: Forced build from source\".format(ref) not in output\n\n\ndef test_install_build_single(build_all):\n    \"\"\" When only --build=<ref> is passed, only <ref> must be built\n    \"\"\"\n    build_all.run(\"install --requires=foobar/1.0@user/testing --build=foo/*\")\n    build_all.assert_listed_binary({\"bar/1.0@user/testing\": (bar_id, \"Cache\"),\n                                    \"foo/1.0@user/testing\": (foo_id, \"Build\"),\n                                    \"foobar/1.0@user/testing\": (foobar_id, \"Cache\"),\n                                    })\n    assert \"foo/1.0@user/testing: Forced build from source\" in build_all.out\n    assert \"bar/1.0@user/testing: Forced build from source\" not in build_all.out\n    assert \"foobar/1.0@user/testing: Forced build from source\" not in build_all.out\n\n\ndef test_install_build_double(build_all):\n    \"\"\" When both --build=<ref1> and --build=<ref2> are passed, only both should be built\n    \"\"\"\n    build_all.run(\"install --requires=foobar/1.0@user/testing --build=foo/* --build=bar/*\")\n    build_all.assert_listed_binary({\"bar/1.0@user/testing\": (bar_id, \"Build\"),\n                                    \"foo/1.0@user/testing\": (foo_id, \"Build\"),\n                                    \"foobar/1.0@user/testing\": (foobar_id, \"Cache\"),\n                                    })\n    assert \"foo/1.0@user/testing: Forced build from source\" in build_all.out\n    assert \"bar/1.0@user/testing: Forced build from source\" in build_all.out\n    assert \"foobar/1.0@user/testing: Forced build from source\" not in build_all.out\n\n\n@pytest.mark.parametrize(\"build_arg,mode\", [(\"--build=\", \"Cache\"),\n                                            (\"--build=*\", \"Build\")])\ndef test_install_build_only(build_arg, mode, build_all):\n    \"\"\" When only --build is passed wo args, that is a command arg error\n        When only --build= is passed, it's a no-op, same as not passing any value\n        When only --build=* is passed, all packages must be built from sources\n    \"\"\"\n    build_all.run(\"install --requires=foobar/1.0@user/testing {}\".format(build_arg))\n\n    build_all.assert_listed_binary({\"bar/1.0@user/testing\": (bar_id, mode),\n                                    \"foo/1.0@user/testing\": (foo_id, mode),\n                                    \"foobar/1.0@user/testing\": (foobar_id, mode),\n                                    })\n\n    if \"Build\" == mode:\n        assert \"foo/1.0@user/testing: Forced build from source\" in build_all.out\n        assert \"bar/1.0@user/testing: Forced build from source\" in build_all.out\n        assert \"foobar/1.0@user/testing: Forced build from source\" in build_all.out\n    else:\n        assert \"foo/1.0@user/testing: Forced build from source\" not in build_all.out\n        assert \"bar/1.0@user/testing: Forced build from source\" not in build_all.out\n        assert \"foobar/1.0@user/testing: Forced build from source\" not in build_all.out\n\n\n@pytest.mark.parametrize(\"build_arg,bar,foo,foobar\", [(\"--build=\", \"Cache\", \"Build\", \"Cache\"),\n                                                      (\"--build=*\", \"Build\", \"Build\", \"Build\")])\ndef test_install_build_all_with_single(build_arg, bar, foo, foobar, build_all):\n    \"\"\" When --build is passed with another package, only the package must be built from sources.\n        When --build= is passed with another package, only the package must be built from sources.\n        When --build=* is passed with another package, all packages must be built from sources.\n    \"\"\"\n    build_all.run(\"install --requires=foobar/1.0@user/testing --build=foo/* {}\".format(build_arg))\n    build_all.assert_listed_binary({\"bar/1.0@user/testing\": (bar_id, bar),\n                                    \"foo/1.0@user/testing\": (foo_id, foo),\n                                    \"foobar/1.0@user/testing\": (foobar_id, foobar),\n                                    })\n    check_if_build_from_sources({\"foo\": foo, \"bar\": bar, \"foobar\": foobar}, build_all.out)\n\n\n@pytest.mark.parametrize(\"build_arg,bar,foo,foobar\", [(\"--build=\", \"Cache\", \"Cache\", \"Cache\"),\n                                                      (\"--build=*\", \"Build\", \"Cache\", \"Build\")])\ndef test_install_build_all_with_single_skip(build_arg, bar, foo, foobar, build_all):\n    \"\"\" When --build is passed with a skipped package, not all packages must be built from sources.\n        When --build= is passed with another package, only the package must be built from sources.\n        When --build=* is passed with another package, not all packages must be built from sources.\n        The arguments order matter, that's why we need to run twice.\n    \"\"\"\n    for argument in [\"--build=!foo/* {}\".format(build_arg),\n                     \"{} --build=!foo/*\".format(build_arg)]:\n        build_all.run(\"install --requires=foobar/1.0@user/testing {}\".format(argument))\n        build_all.assert_listed_binary({\"bar/1.0@user/testing\": (bar_id, bar),\n                                        \"foo/1.0@user/testing\": (foo_id, foo),\n                                        \"foobar/1.0@user/testing\": (foobar_id, foobar),\n                                        })\n        check_if_build_from_sources({\"foo\": foo, \"bar\": bar, \"foobar\": foobar}, build_all.out)\n\n\n@pytest.mark.parametrize(\"build_arg,bar,foo,foobar\", [(\"--build=\", \"Cache\", \"Cache\", \"Cache\"),\n                                                      (\"--build=*\", \"Cache\", \"Cache\", \"Build\")])\ndef test_install_build_all_with_double_skip(build_arg, bar, foo, foobar, build_all):\n    \"\"\" When --build is passed with a skipped package, not all packages must be built from sources.\n        When --build= is passed with another package, only the package must be built from sources.\n        When --build=* is passed with another package, not all packages must be built from sources.\n        The arguments order matter, that's why we need to run twice.\n    \"\"\"\n    for argument in [\"--build=!foo/* --build=~bar/* {}\".format(build_arg),\n                     \"{} --build=!foo/* --build=~bar/*\".format(build_arg)]:\n        build_all.run(\"install --requires=foobar/1.0@user/testing {}\".format(argument))\n\n        build_all.assert_listed_binary({\"bar/1.0@user/testing\": (bar_id, bar),\n                                        \"foo/1.0@user/testing\": (foo_id, foo),\n                                        \"foobar/1.0@user/testing\": (foobar_id, foobar),\n                                        })\n\n\ndef test_build_consumer():\n    \"\"\" If the consumer is built from sources, the dependencies must be built too\n    \"\"\"\n    client = TestClient()\n    client.save({\"dep1/conanfile.py\": GenConanfile(\"dep1\", \"1.0\").with_build_msg(\"TEST: Building dep1\"),\n                 \"dep2/conanfile.py\": GenConanfile(\"dep2\", \"1.0\").with_build_msg(\"TEST: Building dep2\"),\n                 \"conanfile.py\": GenConanfile(\"consumer\", \"1.0\")\n                    .with_build_msg(\"TEST: Building consumer\").with_requires(\"dep1/1.0\", \"dep2/1.0\")})\n    client.run(\"create dep1\")\n    client.run(\"create dep2\")\n    client.run(\"export .\")\n\n    # Still makes little sense, but just to test the logic\n    client.run(\"create . --build=* --build=!&\", assert_error=True)\n    assert \"TEST: Building consumer\" not in client.out\n\n    client.run(f\"graph info --requires=consumer/1.0 --build=& -f=json\", redirect_stdout=\"graph.json\")\n    graph = json.loads(client.load(\"graph.json\"))\n    assert graph[\"graph\"][\"nodes\"][\"1\"][\"binary\"] == \"Build\"  # Would be missing if not built\n    assert graph[\"graph\"][\"nodes\"][\"2\"][\"binary\"] == \"Cache\"\n    assert graph[\"graph\"][\"nodes\"][\"3\"][\"binary\"] == \"Cache\"\n\n    client.run(f\"graph info . --build=& -f=json\", redirect_stdout=\"graph.json\")\n    graph = json.loads(client.load(\"graph.json\"))\n    assert graph[\"graph\"][\"nodes\"][\"0\"][\"binary\"] is None\n    assert graph[\"graph\"][\"nodes\"][\"1\"][\"binary\"] == \"Cache\"\n    assert graph[\"graph\"][\"nodes\"][\"2\"][\"binary\"] == \"Cache\"\n"
  },
  {
    "path": "test/integration/command/install/test_install_transitive.py",
    "content": "import os\n\nimport pytest\n\nfrom conan.internal.model.info import load_binary_info\nfrom conan.api.model import RecipeReference\nfrom conan.internal.paths import CONANFILE_TXT, CONANINFO\nfrom conan.test.utils.tools import TestClient,  GenConanfile\nfrom conan.internal.util.files import load\n\n\n@pytest.fixture()\ndef client():\n    c = TestClient()\n    c.save_home({\"settings.yaml\": \"os: [Windows, Macos, Linux, FreeBSD]\\nos_build: [Windows, Macos]\\narch_build: [x86_64]\",\n                 \"profiles/default\":  \"[settings]\\nos=Windows\"})\n\n    def base_conanfile(name):\n        return GenConanfile(name, \"0.1\").with_option(\"language\", [0, 1])\\\n            .with_default_option(\"language\", 0).with_settings(\"os\")\n\n    c.save({\"conanfile.py\": base_conanfile(\"hello0\")})\n    c.run(\"export . --user=lasote --channel=stable\")\n    c.save({\"conanfile.py\": base_conanfile(\"hello1\").with_requires(\"hello0/0.1@lasote/stable\")})\n    c.run(\"export . --user=lasote --channel=stable\")\n    c.save({\"conanfile.py\": base_conanfile(\"hello2\").with_requires(\"hello1/0.1@lasote/stable\")})\n    c.run(\"export . --user=lasote --channel=stable\")\n    return c\n\n\ndef test_install_combined(client):\n    client.run(\"install . --build=missing\")\n    client.run(\"install . --build=missing --build hello1/*\")\n    assert \"hello0/0.1@lasote/stable: Already installed!\" in client.out\n    assert \"hello1/0.1@lasote/stable: Forced build from source\" in client.out\n\n\ndef test_install_transitive_cache(client):\n    client.run(\"install --requires=hello2/0.1@lasote/stable --build=missing\")\n    assert \"hello0/0.1@lasote/stable: Generating the package\" in client.out\n    assert \"hello1/0.1@lasote/stable: Generating the package\" in client.out\n    assert \"hello2/0.1@lasote/stable: Generating the package\" in client.out\n\n\ndef test_upper_option(client):\n    client.run(\"install conanfile.py -o hello2*:language=1 -o hello1*:language=0 \"\n               \"-o hello0*:language=1 --build missing\")\n    package_id = client.created_package_id(\"hello0/0.1@lasote/stable\")\n    package_id2 = client.created_package_id(\"hello1/0.1@lasote/stable\")\n    ref = RecipeReference.loads(\"hello0/0.1@lasote/stable\")\n    pref = client.get_latest_package_reference(ref, package_id)\n    hello0 = client.get_latest_pkg_layout(pref).package()\n\n    hello0_info = os.path.join(hello0, CONANINFO)\n    hello0_conan_info = load_binary_info(load(hello0_info))\n    assert \"1\" == hello0_conan_info[\"options\"][\"language\"]\n\n    pref1 = client.get_latest_package_reference(RecipeReference.loads(\"hello1/0.1@lasote/stable\"), package_id2)\n    hello1 = client.get_latest_pkg_layout(pref1).package()\n    hello1_info = os.path.join(hello1, CONANINFO)\n    hello1_conan_info = load_binary_info(load(hello1_info))\n    assert \"0\" == hello1_conan_info[\"options\"][\"language\"]\n\n\ndef test_inverse_upper_option(client):\n    client.run(\"install . -o language=0 -o hello1*:language=1 -o hello0*:language=0 --build missing\")\n    package_id = client.created_package_id(\"hello0/0.1@lasote/stable\")\n    package_id2 = client.created_package_id(\"hello1/0.1@lasote/stable\")\n    ref = RecipeReference.loads(\"hello0/0.1@lasote/stable\")\n    pref = client.get_latest_package_reference(ref, package_id)\n    hello0 = client.get_latest_pkg_layout(pref).package()\n\n    hello0_info = os.path.join(hello0, CONANINFO)\n    hello0_conan_info = load_binary_info(load(hello0_info))\n    assert \"0\" == hello0_conan_info[\"options\"][\"language\"]\n\n    pref1 = client.get_latest_package_reference(RecipeReference.loads(\"hello1/0.1@lasote/stable\"), package_id2)\n    hello1 = client.get_latest_pkg_layout(pref1).package()\n    hello1_info = os.path.join(hello1, CONANINFO)\n    hello1_conan_info = load_binary_info(load(hello1_info))\n    assert \"1\" == hello1_conan_info[\"options\"][\"language\"]\n\n\ndef test_upper_option_txt(client):\n    files = {CONANFILE_TXT: \"\"\"[requires]\n        hello1/0.1@lasote/stable\n\n        [options]\n        hello0*:language=1\n        hello1*:language=0\n        \"\"\"}\n    client.save(files, clean_first=True)\n\n    client.run(\"install . --build missing\")\n    package_id = client.created_package_id(\"hello0/0.1@lasote/stable\")\n    package_id2 = client.created_package_id(\"hello1/0.1@lasote/stable\")\n    ref = RecipeReference.loads(\"hello0/0.1@lasote/stable\")\n    pref = client.get_latest_package_reference(ref, package_id)\n    hello0 = client.get_latest_pkg_layout(pref).package()\n    hello0_info = os.path.join(hello0, CONANINFO)\n    hello0_conan_info = load_binary_info(load(hello0_info))\n    assert \"1\" == hello0_conan_info[\"options\"][\"language\"]\n\n    pref1 = client.get_latest_package_reference(RecipeReference.loads(\"hello1/0.1@lasote/stable\"), package_id2)\n    hello1 = client.get_latest_pkg_layout(pref1).package()\n    hello1_info = os.path.join(hello1, CONANINFO)\n    hello1_conan_info = load_binary_info(load(hello1_info))\n    assert \"0\" == hello1_conan_info[\"options\"][\"language\"]\n"
  },
  {
    "path": "test/integration/command/list/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/command/list/list_test.py",
    "content": "import json\nimport os\nimport re\nimport textwrap\nimport time\nfrom collections import OrderedDict\nfrom unittest.mock import patch, Mock\n\nimport pytest\n\nfrom conan.errors import ConanException\nfrom conan.internal.errors import ConanConnectionError\nfrom conan.internal.util.files import save\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.env import environment_update\nfrom conan.test.utils.tools import TestClient, TestServer, NO_SETTINGS_PACKAGE_ID\n\n\nclass TestParamErrors:\n\n    def test_default_pattern(self):\n        c = TestClient()\n        c.run(\"list\")\n        assert \"Found 0 pkg/version\" in c.out\n\n        c.run(\"list -c\")\n        assert \"Found 0 pkg/version\" in c.out\n\n        c.run('list -r=\"*\"', assert_error=True)\n        assert \"ERROR: Remotes for pattern '*' can't be found\" in c.out\n\n        c.run(\"list --remote remote1 --cache\", assert_error=True)\n        assert \"ERROR: Remote 'remote1' can't be found or is disabled\" in c.out\n\n    def test_query_param(self):\n        c = TestClient()\n        c.run(\"list * --graph=myjson\", assert_error=True)\n        assert \"ERROR: Cannot define both the pattern and the graph json file\" in c.out\n\n        c.run(\"list * --graph-binaries=x\", assert_error=True)\n        assert \"ERROR: --graph-recipes and --graph-binaries require a --graph input\" in c.out\n\n        c.run(\"list * --graph-recipes=x\", assert_error=True)\n        assert \"ERROR: --graph-recipes and --graph-binaries require a --graph input\" in c.out\n\n        c.run(\"list * -p os=Linux\", assert_error=True)\n        assert \"--package-query and --filter-xxx can only be done for binaries\" in c.out\n\n    def test_wrong_package_query(self):\n        c = TestClient(light=True)\n        c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n        c.run(\"create .\")\n        c.run('list *:* -p \"not os=Linux\"')\n        assert \"ERROR: Invalid package query: not os=Linux. 'not' operator is not allowed\" in c.out\n\n    def test_graph_file_error(self):\n        # This can happen when reusing the same file in input and output\n        c = TestClient(light=True)\n        c.run(\"list --graph=graph.json\", assert_error=True)\n        assert \"ERROR: Graph file not found\" in c.out\n        c.save({\"graph.json\": \"\"})\n        c.run(\"list --graph=graph.json\", assert_error=True)\n        assert \"ERROR: Graph file invalid JSON:\" in c.out\n        text = b'\\x2b\\x2f\\x76\\x38J\\xe2nis\\xa7'\n        with open(os.path.join(c.current_folder, \"graph.json\"), 'wb') as handle:\n            handle.write(text)\n        c.run(\"list --graph=graph.json\", assert_error=True)\n        assert \"ERROR: Graph file broken\" in c.out\n\n        # This can happen when using a pkg list file instead of a graph file\n        c.save({\"conanfile.py\": GenConanfile(\"lib\")})\n        c.run(\"create . --version=1.0 --format=json\", redirect_stdout=\"graph.json\")\n        c.run(\"list --graph graph.json --format=json\", redirect_stdout=\"pkglist.json\")\n        c.run(\"list --graph pkglist.json\", assert_error=True)\n        assert (\n            'Expected a graph file but found an unexpected JSON file format. '\n            'You can create a \"graph\" JSON file by running'\n            in c.out\n        )\n        assert (\n            \"conan [ graph-info | create | export-pkg | install | test ] --format=json > graph.json\"\n            in c.out\n        )\n\n\n@pytest.fixture(scope=\"module\")\ndef client():\n    servers = OrderedDict([(\"default\", TestServer()),\n                           (\"other\", TestServer())])\n    c = TestClient(servers=servers, inputs=2*[\"admin\", \"password\"])\n    c.save({\n        \"zlib.py\": GenConanfile(\"zlib\"),\n        \"zlib_ng.py\": GenConanfile(\"zlib_ng\", \"1.0.0\"),\n        \"zli.py\": GenConanfile(\"zli\", \"1.0.0\"),\n        \"zli_rev2.py\": GenConanfile(\"zli\", \"1.0.0\").with_settings(\"os\")\n                                                   .with_package_file(\"f.txt\", env_var=\"MYREV\"),\n        \"zlix.py\": GenConanfile(\"zlix\", \"1.0.0\"),\n        \"test.py\": GenConanfile(\"test\", \"1.0\").with_requires(\"zlix/1.0.0\")\n\n                                              .with_python_requires(\"zlix/1.0.0\"),\n        \"conf.py\": GenConanfile(\"conf\", \"1.0\")\n    })\n    c.run(\"create zli.py\")\n    c.run(\"create zlib.py --version=1.0.0 --user=user --channel=channel\")\n    c.run(\"create zlib.py --version=2.0.0 --user=user --channel=channel\")\n    c.run(\"create zlix.py\")\n    c.run(\"create test.py\")\n    c.run('create conf.py -c tools.info.package_id:confs=\"[\\'tools.build:cxxflags\\']\"'\n          ' -c tools.build:cxxflags=\"[\\'--flag1\\']\"')\n    c.run(\"upload * -r=default -c\")\n    c.run(\"upload * -r=other -c\")\n\n    time.sleep(1.0)\n    # We create and upload new revisions later, to avoid timestamp overlaps (low resolution)\n    with environment_update({\"MYREV\": \"0\"}):\n        c.run(\"create zli_rev2.py -s os=Windows\")\n        c.run(\"create zli_rev2.py -s os=Linux\")\n    c.run(\"upload * -r=default -c\")\n    with environment_update({\"MYREV\": \"42\"}):\n        c.run(\"create zli_rev2.py -s os=Windows\")\n    c.run(\"upload * -r=default -c\")\n    return c\n\n\ndef remove_timestamps(item):\n    if isinstance(item, dict):\n        if item.get(\"timestamp\"):\n            item[\"timestamp\"] = \"\"\n        for v in item.values():\n            remove_timestamps(v)\n    return item\n\n\nclass TestListRefs:\n\n    @staticmethod\n    def check(client, pattern, remote, expected):\n        r = \"-r=default\" if remote else \"\"\n        r_msg = \"default\" if remote else \"Local Cache\"\n        client.run(f\"list {pattern} {r}\")\n        expected = textwrap.indent(expected, \"  \")\n        expected_output = f\"{r_msg}\\n\" + expected\n        expected_output = re.sub(r\"\\(.*\\)\", \"\", expected_output)\n        output = re.sub(r\"\\(.*\\)\", \"\", str(client.out))\n        assert expected_output in output\n\n    @staticmethod\n    def check_json(client, pattern, remote, expected):\n        r = \"-r=default\" if remote else \"\"\n        r_msg = \"default\" if remote else \"Local Cache\"\n        client.run(f\"list {pattern} {r} --format=json\", redirect_stdout=\"file.json\")\n        list_json = client.load(\"file.json\")\n        list_json = json.loads(list_json)\n        assert remove_timestamps(list_json[r_msg]) == remove_timestamps(expected)\n\n    @pytest.mark.parametrize(\"remote\", [True, False])\n    def test_list_recipes(self, client, remote):\n        pattern = \"z*\"\n        expected = textwrap.dedent(f\"\"\"\\\n          zli\n            zli/1.0.0\n          zlib\n            zlib/1.0.0@user/channel\n            zlib/2.0.0@user/channel\n          zlix\n            zlix/1.0.0\n        \"\"\")\n        self.check(client, pattern, remote, expected)\n        expected_json = {\n            \"zli/1.0.0\": {},\n            \"zlib/1.0.0@user/channel\": {},\n            \"zlib/2.0.0@user/channel\": {},\n            \"zlix/1.0.0\": {}\n        }\n        self.check_json(client, pattern, remote, expected_json)\n\n    @pytest.mark.parametrize(\"remote\", [True, False])\n    def test_list_recipes_only_user_channel(self, client, remote):\n        pattern = \"*@user/channel\"\n        expected = textwrap.dedent(f\"\"\"\\\n              zlib\n                zlib/1.0.0@user/channel\n                zlib/2.0.0@user/channel\n            \"\"\")\n        self.check(client, pattern, remote, expected)\n        expected_json = {\n            \"zlib/1.0.0@user/channel\": {},\n            \"zlib/2.0.0@user/channel\": {},\n        }\n        self.check_json(client, pattern, remote, expected_json)\n\n    @pytest.mark.parametrize(\"remote\", [True, False])\n    def test_list_recipes_without_user_channel(self, client, remote):\n        pattern = \"z*@\"\n        expected = textwrap.dedent(f\"\"\"\\\n              zli\n                zli/1.0.0\n              zlix\n                zlix/1.0.0\n            \"\"\")\n        self.check(client, pattern, remote, expected)\n\n    @pytest.mark.parametrize(\"remote\", [True, False])\n    @pytest.mark.parametrize(\"pattern\", [\"zlib\", \"zlib/*\", \"*@user/channel\"])\n    def test_list_recipe_versions(self, client, pattern, remote):\n        expected = textwrap.dedent(f\"\"\"\\\n            zlib\n              zlib/1.0.0@user/channel\n              zlib/2.0.0@user/channel\n            \"\"\")\n        self.check(client, pattern, remote, expected)\n        expected_json = {\n            \"zlib/1.0.0@user/channel\": {},\n            \"zlib/2.0.0@user/channel\": {}\n        }\n        self.check_json(client, pattern, remote, expected_json)\n\n    @pytest.mark.parametrize(\"remote\", [True, False])\n    @pytest.mark.parametrize(\"pattern, solution\", [(\"zlib/[*]\", (\"1.0.0\", \"2.0.0\")),\n                                                   (\"zlib*/[*]\", (\"1.0.0\", \"2.0.0\")),\n                                                   (\"zlib/[<2]\", (\"1.0.0\",)),\n                                                   (\"zlib/[>1]\", (\"2.0.0\",))])\n    def test_list_recipe_version_ranges(self, client, pattern, solution, remote):\n        expected_json = {f\"zlib/{v}@user/channel\": {} for v in solution}\n        self.check_json(client, pattern, remote, expected_json)\n\n    @pytest.mark.parametrize(\"remote\", [True, False])\n    def test_list_recipe_version_ranges_patterns(self, client, remote):\n        pattern = \"*/[>1]\"\n        expected_json = {'zlib/2.0.0@user/channel': {}}\n        self.check_json(client, pattern, remote, expected_json)\n        pattern = \"z*/[<2]\"\n        expected_json = {'zli/1.0.0': {},\n                         'zlib/1.0.0@user/channel': {},\n                         'zlix/1.0.0': {}}\n        self.check_json(client, pattern, remote, expected_json)\n\n    def test_version_range_prerelease(self):\n        tc = TestClient(light=True)\n        tc.save({\"conanfile.py\": GenConanfile(\"foo\", \"1.0-pre.1\")})\n        tc.run(\"export .\")\n        tc.run(\"list * \",)\n        assert \"foo/1.0-pre.1\" in tc.out\n        tc.run(\"list foo/[>=1.0]\")\n        assert \"foo/1.0-pre.1\" not in tc.out\n        tc.run(\"list foo/[>=1.0] -cc core.version_ranges:resolve_prereleases=True\")\n        assert \"foo/1.0-pre.1\" in tc.out\n\n    @pytest.mark.parametrize(\"remote\", [True, False])\n    def test_list_recipe_versions_exact(self, client, remote):\n        pattern = \"zli/1.0.0\"\n        # by default, when a reference is complete, we show latest recipe revision\n        expected = textwrap.dedent(f\"\"\"\\\n          zli\n            zli/1.0.0\n          \"\"\")\n        self.check(client, pattern, remote, expected)\n        expected_json = {\n            \"zli/1.0.0\": {}\n        }\n        self.check_json(client, pattern, remote, expected_json)\n\n    @pytest.mark.parametrize(\"remote\", [True, False])\n    @pytest.mark.parametrize(\"pattern\", [\"nomatch\", \"nomatch*\", \"nomatch/*\"])\n    def test_list_recipe_no_match(self, client, pattern, remote):\n        if pattern == \"nomatch\":  # EXACT IS AN ERROR\n            expected = \"ERROR: Recipe 'nomatch' not found\\n\"\n        else:\n            expected = \"WARN: There are no matching recipe references\\n\"\n\n        self.check(client, pattern, remote, expected)\n        if pattern == \"nomatch\":\n            expected_json = {\"error\": \"Recipe 'nomatch' not found\"}\n        else:\n            expected_json = {}\n        self.check_json(client, pattern, remote, expected_json)\n\n    @pytest.mark.parametrize(\"remote\", [True, False])\n    @pytest.mark.parametrize(\"pattern\", [\"zli/1.0.0#latest\",\n                                         \"zli/1.0.0#b58eeddfe2fd25ac3a105f72836b3360\"])\n    def test_list_recipe_latest_revision(self, client, remote, pattern):\n        # by default, when a reference is complete, we show latest recipe revision\n        expected = textwrap.dedent(f\"\"\"\\\n          zli\n            zli/1.0.0\n              revisions\n                b58eeddfe2fd25ac3a105f72836b3360 (10-11-2023 10:13:13)\n          \"\"\")\n        self.check(client, pattern, remote, expected)\n        expected_json = {\n            \"zli/1.0.0\": {\n                \"revisions\": {\n                    \"b58eeddfe2fd25ac3a105f72836b3360\": {\n                        \"timestamp\": \"2023-01-10 00:25:32 UTC\"\n                    }\n                }\n            }\n        }\n        self.check_json(client, pattern, remote, expected_json)\n\n    @pytest.mark.parametrize(\"remote\", [True, False])\n    def test_list_recipe_all_latest_revision(self, client, remote):\n        # we can show the latest revision from several matches, if we add ``#latest``\n        pattern = \"zlib/*#latest\"\n        expected = textwrap.dedent(f\"\"\"\\\n            zlib\n              zlib/1.0.0@user/channel\n                revisions\n                  ffd4bc45820ddb320ab224685b9ba3fb (10-11-2023 10:13:13)\n              zlib/2.0.0@user/channel\n                revisions\n                  ffd4bc45820ddb320ab224685b9ba3fb (10-11-2023 10:13:13)\n            \"\"\")\n        self.check(client, pattern, remote, expected)\n\n    @pytest.mark.parametrize(\"remote\", [True, False])\n    def test_list_recipe_several_revision(self, client, remote):\n        # we can show the latest revision from several matches, if we add ``#latest``\n        pattern = \"zli/1.0.0#*\"\n        expected = textwrap.dedent(f\"\"\"\\\n            zli\n              zli/1.0.0\n                revisions\n                  f034dc90894493961d92dd32a9ee3b78 (10-11-2023 10:13:13)\n                  b58eeddfe2fd25ac3a105f72836b3360 (10-11-2023 10:13:13)\n            \"\"\")\n        self.check(client, pattern, remote, expected)\n\n    @pytest.mark.parametrize(\"remote\", [True, False])\n    def test_list_recipe_multiple_revision(self, client, remote):\n        pattern = \"zli*#*\"\n        expected = textwrap.dedent(f\"\"\"\\\n            zli\n              zli/1.0.0\n                revisions\n                  f034dc90894493961d92dd32a9ee3b78 (10-11-2023 10:13:13)\n                  b58eeddfe2fd25ac3a105f72836b3360 (10-11-2023 10:13:13)\n            zlib\n              zlib/1.0.0@user/channel\n                revisions\n                  ffd4bc45820ddb320ab224685b9ba3fb (10-11-2023 10:13:13)\n              zlib/2.0.0@user/channel\n                revisions\n                  ffd4bc45820ddb320ab224685b9ba3fb (10-11-2023 10:13:13)\n            zlix\n              zlix/1.0.0\n                revisions\n                  81f598d1d8648389bb7d0494fffb654e (10-11-2023 10:13:13)\n            \"\"\")\n        self.check(client, pattern, remote, expected)\n\n\nclass TestListPrefs:\n\n    @staticmethod\n    def check(client, pattern, remote, expected):\n        r = \"-r=default\" if remote else \"\"\n        r_msg = \"default\" if remote else \"Local Cache\"\n        client.run(f\"list {pattern} {r}\")\n        expected = textwrap.indent(expected, \"  \")\n        expected_output = f\"{r_msg}\\n\" + expected\n        expected_output = re.sub(r\"\\(.*\\)\", \"\", expected_output)\n        output = re.sub(r\"\\(.*\\)\", \"\", str(client.out))\n        assert expected_output in output\n\n    @staticmethod\n    def check_json(client, pattern, remote, expected):\n        r = \"-r=default\" if remote else \"\"\n        r_msg = \"default\" if remote else \"Local Cache\"\n        client.run(f\"list {pattern} {r} --format=json\", redirect_stdout=\"file.json\")\n        list_json = client.load(\"file.json\")\n        list_json = json.loads(list_json)\n        assert remove_timestamps(list_json[r_msg]) == remove_timestamps(expected)\n\n    @pytest.mark.parametrize(\"remote\", [True, False])\n    def test_list_pkg_ids(self, client, remote):\n        pattern = \"zli/1.0.0:*\"\n        expected = textwrap.dedent(f\"\"\"\\\n          zli\n            zli/1.0.0\n              revisions\n                b58eeddfe2fd25ac3a105f72836b3360 (10-11-2023 10:13:13)\n                  packages\n                    9a4eb3c8701508aa9458b1a73d0633783ecc2270\n                      info\n                        settings\n                          os: Linux\n                    ebec3dc6d7f6b907b3ada0c3d3cdc83613a2b715\n                      info\n                        settings\n                          os: Windows\n          \"\"\")\n        self.check(client, pattern, remote, expected)\n        expected_json = {\n            \"zli/1.0.0\": {\n                \"revisions\": {\n                    \"b58eeddfe2fd25ac3a105f72836b3360\": {\n                        \"timestamp\": \"2023-01-10 16:30:27 UTC\",\n                        \"packages\": {\n                            \"9a4eb3c8701508aa9458b1a73d0633783ecc2270\": {\n                                \"info\": {\n                                    \"settings\": {\n                                        \"os\": \"Linux\"\n                                    }\n                                }\n                            },\n                            \"ebec3dc6d7f6b907b3ada0c3d3cdc83613a2b715\": {\n                                \"info\": {\n                                    \"settings\": {\n                                        \"os\": \"Windows\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        self.check_json(client, pattern, remote, expected_json)\n\n    @pytest.mark.parametrize(\"remote\", [True, False])\n    def test_list_pkg_ids_confs(self, client, remote):\n        pattern = \"conf/*:*\"\n        expected = textwrap.dedent(\"\"\"\\\n          conf\n            conf/1.0\n              revisions\n                e4e1703f72ed07c15d73a555ec3a2fa1 (10-11-2023 10:13:13)\n                  packages\n                    78c6fa29e8164ce399087ad6067c8f9e2f1c4ad0\n                      info\n                        conf\n                          tools.build:cxxflags: ['--flag1']\n          \"\"\")\n        self.check(client, pattern, remote, expected)\n        expected_json = {\n            \"conf/1.0\": {\n                \"revisions\": {\n                    \"e4e1703f72ed07c15d73a555ec3a2fa1\": {\n                        \"timestamp\": \"2023-01-10 10:07:33 UTC\",\n                        \"packages\": {\n                            \"78c6fa29e8164ce399087ad6067c8f9e2f1c4ad0\": {\n                                \"info\": {\n                                    \"conf\": {\n                                        \"tools.build:cxxflags\": \"['--flag1']\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        self.check_json(client, pattern, remote, expected_json)\n\n    @pytest.mark.parametrize(\"remote\", [True, False])\n    def test_list_pkg_ids_requires(self, client, remote):\n        pattern = \"test/*:*\"\n        expected = textwrap.dedent(\"\"\"\\\n          test\n            test/1.0\n              revisions\n                7df6048d3cb39b75618717987fb96453 (10-11-2023 10:13:13)\n                  packages\n                    81d0d9a6851a0208c2bb35fdb34eb156359d939b\n                      info\n                        requires\n                          zlix/1.Y.Z\n                        python_requires\n                          zlix/1.0.Z\n          \"\"\")\n        self.check(client, pattern, remote, expected)\n        expected_json = {\n            \"test/1.0\": {\n                \"revisions\": {\n                    \"7df6048d3cb39b75618717987fb96453\": {\n                        \"timestamp\": \"2023-01-10 22:17:13 UTC\",\n                        \"packages\": {\n                            \"81d0d9a6851a0208c2bb35fdb34eb156359d939b\": {\n                                \"info\": {\n                                    \"requires\": [\n                                        \"zlix/1.Y.Z\"\n                                    ],\n                                    \"python_requires\": [\n                                        \"zlix/1.0.Z\"\n                                    ]\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        self.check_json(client, pattern, remote, expected_json)\n\n    @pytest.mark.parametrize(\"remote\", [True, False])\n    def test_list_pkg_ids_all_rrevs(self, client, remote):\n        pattern = \"zli/1.0.0#*:*\"\n        expected = textwrap.dedent(f\"\"\"\\\n          zli\n            zli/1.0.0\n              revisions\n                f034dc90894493961d92dd32a9ee3b78 (2023-01-10 22:19:58 UTC)\n                  packages\n                    da39a3ee5e6b4b0d3255bfef95601890afd80709\n                      info\n                b58eeddfe2fd25ac3a105f72836b3360 (2023-01-10 22:19:59 UTC)\n                  packages\n                    9a4eb3c8701508aa9458b1a73d0633783ecc2270\n                      info\n                        settings\n                          os: Linux\n                    ebec3dc6d7f6b907b3ada0c3d3cdc83613a2b715\n                      info\n                        settings\n                          os: Windows\n           \"\"\")\n        self.check(client, pattern, remote, expected)\n\n    @pytest.mark.parametrize(\"remote\", [True, False])\n    @pytest.mark.parametrize(\"version\", [\"1.0.0\", \"[>=1.0.0 <2]\"])\n    def test_list_latest_prevs(self, client, remote, version):\n        pattern = f'\"zli/{version}:*#latest\"'\n        expected = textwrap.dedent(f\"\"\"\\\n          zli\n            zli/1.0.0\n              revisions\n                b58eeddfe2fd25ac3a105f72836b3360 (2023-01-10 22:27:34 UTC)\n                  packages\n                    9a4eb3c8701508aa9458b1a73d0633783ecc2270\n                      revisions\n                        9beff32b8c94ea0ce5a5e67dad95f525 (10-11-2023 10:13:13)\n                      info\n                        settings\n                          os: Linux\n                    ebec3dc6d7f6b907b3ada0c3d3cdc83613a2b715\n                      revisions\n                        d9b1e9044ee265092e81db7028ae10e0 (10-11-2023 10:13:13)\n                      info\n                        settings\n                          os: Windows\n          \"\"\")\n        self.check(client, pattern, remote, expected)\n\n    @pytest.mark.parametrize(\"remote\", [True, False])\n    def test_list_all_prevs(self, client, remote):\n        pattern = \"zli/1.0.0:*#*\"\n        # TODO: This is doing a package_id search, but not showing info\n        expected = textwrap.dedent(f\"\"\"\\\n          zli\n            zli/1.0.0\n              revisions\n                b58eeddfe2fd25ac3a105f72836b3360 (2023-01-10 22:41:09 UTC)\n                  packages\n                    9a4eb3c8701508aa9458b1a73d0633783ecc2270\n                      revisions\n                        9beff32b8c94ea0ce5a5e67dad95f525 (2023-01-10 22:41:09 UTC)\n                      info\n                        settings\n                          os: Linux\n                    ebec3dc6d7f6b907b3ada0c3d3cdc83613a2b715\n                      revisions\n                        24532a030b4fcdfed699511f6bfe35d3 (2023-01-10 22:41:09 UTC)\n                        d9b1e9044ee265092e81db7028ae10e0 (2023-01-10 22:41:10 UTC)\n                      info\n                        settings\n                          os: Windows\n          \"\"\")\n        self.check(client, pattern, remote, expected)\n\n    @pytest.mark.parametrize(\"remote\", [True, False])\n    def test_list_package_id_all_prevs(self, client, remote):\n        pattern = \"zli/1.0.0:ebec3dc6d7f6b907b3ada0c3d3cdc83613a2b715#*\"\n        # TODO: We might want to improve the output, grouping PREVS for the\n        #  same package_id\n        expected_json = {\n            \"zli/1.0.0\": {\n                \"revisions\": {\n                    \"b58eeddfe2fd25ac3a105f72836b3360\": {\n                        \"timestamp\": \"2023-01-10 22:45:49 UTC\",\n                        \"packages\": {\n                            \"ebec3dc6d7f6b907b3ada0c3d3cdc83613a2b715\": {\n                                \"revisions\": {\n                                    \"d9b1e9044ee265092e81db7028ae10e0\": {\n                                        \"timestamp\": \"2023-01-10 22:45:49 UTC\"\n                                    },\n                                    \"24532a030b4fcdfed699511f6bfe35d3\": {\n                                        \"timestamp\": \"2023-01-10 22:45:49 UTC\"\n                                    }\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        }\n        self.check_json(client, pattern, remote, expected_json)\n        expected = textwrap.dedent(f\"\"\"\\\n          zli\n            zli/1.0.0\n              revisions\n                b58eeddfe2fd25ac3a105f72836b3360 (2023-01-10 22:41:09 UTC)\n                  packages\n                    ebec3dc6d7f6b907b3ada0c3d3cdc83613a2b715\n                      revisions\n                        24532a030b4fcdfed699511f6bfe35d3 (2023-01-10 22:41:09 UTC)\n                        d9b1e9044ee265092e81db7028ae10e0 (2023-01-10 22:41:10 UTC)\n          \"\"\")\n        self.check(client, pattern, remote, expected)\n\n    @pytest.mark.parametrize(\"remote\", [True, False])\n    def test_list_package_id_single(self, client, remote):\n        pattern = \"zli/1.0.0:ebec3dc6d7f6b907b3ada0c3d3cdc83613a2b715\"\n        expected = textwrap.dedent(f\"\"\"\\\n          zli\n            zli/1.0.0\n              revisions\n                b58eeddfe2fd25ac3a105f72836b3360 (2023-01-10 23:13:12 UTC)\n                  packages\n                    ebec3dc6d7f6b907b3ada0c3d3cdc83613a2b715\n                      info\n                        settings\n                          os: Windows\n          \"\"\")\n        self.check(client, pattern, remote, expected)\n\n    @pytest.mark.parametrize(\"remote\", [True, False])\n    def test_list_missing_package_id(self, client, remote):\n        pattern = \"zli/1.0.0:nonexists_id\"\n        expected = \"ERROR: Package ID 'zli/1.0.0:nonexists_id' not found\\n\"\n        self.check(client, pattern, remote, expected)\n\n    @pytest.mark.parametrize(\"remote\", [True, False])\n    def test_query(self, client, remote):\n        pattern = \"zli/1.0.0:* -p os=Linux\"\n        expected = textwrap.dedent(f\"\"\"\\\n          zli\n            zli/1.0.0\n              revisions\n                b58eeddfe2fd25ac3a105f72836b3360 (10-11-2023 10:13:13)\n                  packages\n                    9a4eb3c8701508aa9458b1a73d0633783ecc2270\n                      info\n                        settings\n                          os: Linux\n          \"\"\")\n        self.check(client, pattern, remote, expected)\n\n\ndef test_list_prefs_query_custom_settings():\n    \"\"\"\n    Make sure query works for custom settings\n    # https://github.com/conan-io/conan/issues/13071\n    \"\"\"\n    c = TestClient(default_server_user=True)\n    settings = textwrap.dedent(\"\"\"\\\n        newsetting:\n            value1:\n            value2:\n                subsetting: [1, 2, 3]\n        \"\"\")\n    save(c.paths.settings_path_user, settings)\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_settings(\"newsetting\")})\n    c.run(\"create . -s newsetting=value1\")\n    c.run(\"create . -s newsetting=value2 -s newsetting.subsetting=1\")\n    c.run(\"create . -s newsetting=value2 -s newsetting.subsetting=2\")\n    c.run(\"upload * -r=default -c\")\n    c.run(\"list pkg/1.0:* -p newsetting=value1\")\n    assert \"newsetting: value1\" in c.out\n    assert \"newsetting: value2\" not in c.out\n    c.run(\"list pkg/1.0:* -p newsetting=value1 -r=default\")\n    assert \"newsetting: value1\" in c.out\n    assert \"newsetting: value2\" not in c.out\n    c.run('list pkg/1.0:* -p \"newsetting=value2 AND newsetting.subsetting=1\"')\n    assert \"newsetting: value2\" in c.out\n    assert \"newsetting.subsetting: 1\" in c.out\n    assert \"newsetting.subsetting: 2\" not in c.out\n    c.run('list pkg/1.0:* -p \"newsetting=value2 AND newsetting.subsetting=1\" -r=default')\n    assert \"newsetting: value2\" in c.out\n    assert \"newsetting.subsetting: 1\" in c.out\n    assert \"newsetting.subsetting: 2\" not in c.out\n\n\ndef test_list_query_options():\n    \"\"\"\n    Make sure query works for custom settings\n    https://github.com/conan-io/conan/issues/13617\n    \"\"\"\n    c = TestClient(default_server_user=True)\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_option(\"myoption\", [1, 2, 3])})\n    c.run(\"create . -o myoption=1\")\n    c.run(\"create . -o myoption=2\")\n    c.run(\"create . -o myoption=3\")\n\n    c.run(\"list pkg/1.0:* -p options.myoption=1\")\n    assert \"myoption: 1\" in c.out\n    assert \"myoption: 2\" not in c.out\n    assert \"myoption: 3\" not in c.out\n    c.run(\"list pkg/1.0:* -p options.myoption=2\")\n    assert \"myoption: 1\" not in c.out\n    assert \"myoption: 2\" in c.out\n    assert \"myoption: 3\" not in c.out\n\n    c.run(\"upload * -r=default -c\")\n    c.run(\"list pkg/1.0:* -p options.myoption=1 -r=default\")\n    assert \"myoption: 1\" in c.out\n    assert \"myoption: 2\" not in c.out\n    assert \"myoption: 3\" not in c.out\n    c.run(\"list pkg/1.0:* -p options.myoption=2 -r=default\")\n    assert \"myoption: 1\" not in c.out\n    assert \"myoption: 2\" in c.out\n    assert \"myoption: 3\" not in c.out\n\n\ndef test_list_empty_settings():\n    \"\"\"\n    If settings are empty, do not crash\n    \"\"\"\n    c = TestClient(default_server_user=True)\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\")})\n    c.run(\"create .\")\n\n    c.run(\"list pkg/1.0:* -p os=Windows -f=json\")\n    revisions = json.loads(c.stdout)[\"Local Cache\"][\"pkg/1.0\"][\"revisions\"]\n    pkgs = revisions[\"a69a86bbd19ae2ef7eedc64ae645c531\"][\"packages\"]\n    assert pkgs == {}\n    c.run(\"list pkg/1.0:* -p os=None -f=json\")\n    revisions = json.loads(c.stdout)[\"Local Cache\"][\"pkg/1.0\"][\"revisions\"]\n    pkgs = revisions[\"a69a86bbd19ae2ef7eedc64ae645c531\"][\"packages\"]\n    assert pkgs == {NO_SETTINGS_PACKAGE_ID: {\"info\": {}}}\n\n\nclass TestListNoUserChannel:\n    def test_no_user_channel(self):\n        c = TestClient(default_server_user=True)\n        c.save({\"zlib.py\": GenConanfile(\"zlib\"), })\n\n        c.run(\"create zlib.py --version=1.0.0\")\n        c.run(\"create zlib.py --version=1.0.0 --user=user --channel=channel\")\n        c.run(\"upload * -r=default -c\")\n\n        c.run(\"list zlib/1.0.0#latest\")\n        assert \"user/channel\" not in c.out\n        c.run(\"list zlib/1.0.0#latest -r=default\")\n        assert \"user/channel\" not in c.out\n\n        c.run(\"list zlib/1.0.0:*\")\n        assert \"user/channel\" not in c.out\n        c.run(\"list zlib/1.0.0:* -r=default\")\n        assert \"user/channel\" not in c.out\n\n\nclass TestListRemotes:\n    \"\"\" advanced use case:\n    - check multiple remotes output\n    \"\"\"\n\n    def test_search_no_matching_recipes(self, client):\n        expected_output = textwrap.dedent(\"\"\"\\\n        Connecting to remote 'default' with user 'admin'\n        Connecting to remote 'other' with user 'admin'\n        Local Cache\n          ERROR: Recipe 'whatever/0.1' not found\n        default\n          ERROR: Recipe 'whatever/0.1' not found\n        other\n          ERROR: Recipe 'whatever/0.1' not found\n        \"\"\")\n\n        client.run('list -c -r=\"*\" whatever/0.1')\n        assert expected_output == client.out\n\n    def test_fail_if_no_configured_remotes(self):\n        client = TestClient()\n        client.run('list -r=\"*\" whatever/1.0#123', assert_error=True)\n        assert \"ERROR: Remotes for pattern '*' can't be found or are disabled\" in client.out\n\n    @pytest.mark.parametrize(\"exc,output\", [\n        (ConanConnectionError(\"Review your network!\"), \"ERROR: Review your network!\"),\n        (ConanException(\"Boom!\"), \"ERROR: Boom!\")\n    ])\n    def test_search_remote_errors_but_no_raising_exceptions(self, client, exc, output):\n        with patch(\"conan.api.subapi.list._search_recipes\", new=Mock(side_effect=exc)):\n            client.run(f'list whatever/1.0 -r=\"*\"')\n        expected_output = textwrap.dedent(f\"\"\"\\\n            default\n              {output}\n            other\n              {output}\n            \"\"\")\n        assert expected_output == client.out\n\n\nclass TestListHTML:\n    def test_list_html(self):\n        c = TestClient()\n        c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"1.2.3\"),\n                \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"2.3.4\").with_requires(\"dep/1.2.3\")\n                .with_settings(\"os\", \"arch\").with_shared_option(False)})\n        c.run(\"create dep\")\n        c.run(\"create pkg -s os=Windows -s arch=x86\")\n        # Revision is needed explicitly!\n        c.run(\"list pkg/2.3.4#latest --format=html\")\n        assert \"<!DOCTYPE html>\" in c.stdout\n        # TODO: The actual good html is missing\n\n    def test_list_html_custom(self):\n        \"\"\" test that tools.info.package_id:confs works, affecting the package_id and\n        can be listed when we are listing packages\n        \"\"\"\n        c = TestClient()\n        c.save({'lib.py': GenConanfile(\"lib\", \"0.1\")})\n        c.run(\"create lib.py\")\n        template_folder = os.path.join(c.cache_folder, 'templates')\n        c.save({\"list_packages.html\": '{{ base_template_path }}'}, path=template_folder)\n        c.run(\"list lib/0.1#latest --format=html\")\n        assert template_folder in c.stdout\n\n\nclass TestListCompact:\n    def test_list_compact(self):\n        c = TestClient()\n        c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_settings(\"os\", \"arch\")\n                                                          .with_shared_option(False)})\n        c.run(\"create . -s os=Windows -s arch=x86\")\n        c.run(\"create . -s os=Linux -s arch=armv8\")\n        c.run(\"create . -s os=Macos -s arch=armv8 -o shared=True\")\n        c.run(\"list pkg:* --format=compact\")\n\n        expected = textwrap.dedent(\"\"\"\\\n            pkg/1.0#03591c8b22497dd74214e08b3bf2a56f:2a67a51fbf36a4ee345b2125dd2642be60ffd3ec\n              settings: Macos, armv8\n              options: shared=True\n            pkg/1.0#03591c8b22497dd74214e08b3bf2a56f:2d46abc802bbffdf2af11591e3e452bc6149ea2b\n              settings: Linux, armv8\n              options: shared=False\n            pkg/1.0#03591c8b22497dd74214e08b3bf2a56f:d2e97769569ac0a583d72c10a37d5ca26de7c9fa\n              settings: Windows, x86\n              options: shared=False\n            \"\"\")\n        assert textwrap.indent(expected, \"      \") in c.stdout\n\n    def test_list_compact_no_settings_no_options(self):\n        c = TestClient()\n        c.save({\"pkg/conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_settings(\"os\", \"arch\"),\n                \"other/conanfile.py\": GenConanfile(\"other\", \"1.0\")})\n        c.run(\"create pkg -s os=Windows -s arch=x86\")\n        c.run(\"create other\")\n        c.run(\"list *:* --format=compact\")\n        expected_output = re.sub(r\"%.* \", \"%timestamp \",\n                                 re.sub(r\"\\(.*\\)\", \"(timestamp)\", c.stdout))\n\n        expected = textwrap.dedent(\"\"\"\\\n            Local Cache\n              other/1.0\n                other/1.0#d3c8cc5e6d23ca8c6f0eaa6285c04cbd%timestamp (timestamp)\n                  other/1.0#d3c8cc5e6d23ca8c6f0eaa6285c04cbd:da39a3ee5e6b4b0d3255bfef95601890afd80709\n              pkg/1.0\n                pkg/1.0#d24b74828b7681f08d8f5ba0e7fd791e%timestamp (timestamp)\n                  pkg/1.0#d24b74828b7681f08d8f5ba0e7fd791e:c11e463c49652ba9c5adc62573ee49f966bd8417\n                    settings: Windows, x86\n            \"\"\")\n\n        assert expected == expected_output\n\n    @pytest.mark.parametrize(\"pattern\", [\n        \"pkg/*\",\n        \"pkg/1.0\",\n        \"pkg/1.0#*\",\n        \"pkg/1.0#*:*\",\n        \"pkg/1.0#*:*#*\",\n        \"pkg/1.0#a69a86bbd19ae2ef7eedc64ae645c531:*\",\n        \"pkg/1.0#a69a86bbd19ae2ef7eedc64ae645c531:*\",\n        \"pkg/1.0#a69a86bbd19ae2ef7eedc64ae645c531:*#*\",\n        \"pkg/1.0#a69a86bbd19ae2ef7eedc64ae645c531:da39a3ee5e6b4b0d3255bfef95601890afd80709#*\",\n        \"pkg/1.0#a69a86bbd19ae2ef7eedc64ae645c531:da39a3ee5e6b4b0d3255bfef95601890afd80709#\"\n        \"0ba8627bd47edc3a501e8f0eb9a79e5e\"\n    ])\n    def test_list_compact_patterns(self, pattern):\n        c = TestClient(light=True)\n        c.save({\"pkg/conanfile.py\": GenConanfile(\"pkg\", \"1.0\")})\n        c.run(\"create pkg\")\n        c.run(f\"list {pattern} --format=compact\")\n\n\nclass TestListBinaryFilter:\n\n    @pytest.mark.parametrize(\"remote\", [True, False])\n    def test_list_filter(self, remote):\n        r = \"-r=default\" if remote else \"\"\n        c = TestClient(default_server_user=remote)\n        c.save({\"pkg/conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_settings(\"os\", \"arch\")\n                                                              .with_shared_option(False),\n                \"header/conanfile.py\": GenConanfile(\"header\", \"1.0\"),\n                \"profile_linux\": \"[settings]\\nos=Linux\",\n                \"profile_armv8\": \"[settings]\\narch=armv8\",\n                \"profile_shared\": \"[options]\\n*:shared=True\"})\n        c.run(\"create pkg -s os=Windows -s arch=x86\")\n        c.run(\"create pkg -s os=Linux -s arch=armv8\")\n        c.run(\"create pkg -s os=Macos -s arch=armv8 -o shared=True\")\n        c.run(\"create header\")\n        if remote:\n            c.run(\"upload *:* -r=default -c\")\n        pkg_key = \"default\" if remote else \"Local Cache\"\n\n        c.run(f\"list *:* -fp=profile_linux --format=json {r}\")\n        result = json.loads(c.stdout)\n        header = result[pkg_key][\"header/1.0\"][\"revisions\"][\"747cc49983b14bdd00df50a0671bd8b3\"]\n        assert header[\"packages\"] == {\"da39a3ee5e6b4b0d3255bfef95601890afd80709\": {\"info\": {}}}\n        pkg = result[pkg_key][\"pkg/1.0\"][\"revisions\"][\"03591c8b22497dd74214e08b3bf2a56f\"]\n        assert len(pkg[\"packages\"]) == 1\n        settings = pkg[\"packages\"][\"2d46abc802bbffdf2af11591e3e452bc6149ea2b\"][\"info\"][\"settings\"]\n        assert settings == {\"arch\": \"armv8\", \"os\": \"Linux\"}\n\n        # for linux + x86 only the header-only is a match\n        c.run(f\"list *:* -fp=profile_linux -fs=arch=x86 --format=json {r}\")\n        result = json.loads(c.stdout)\n        header = result[pkg_key][\"header/1.0\"][\"revisions\"][\"747cc49983b14bdd00df50a0671bd8b3\"]\n        assert header[\"packages\"] == {\"da39a3ee5e6b4b0d3255bfef95601890afd80709\": {\"info\": {}}}\n        pkg = result[pkg_key][\"pkg/1.0\"][\"revisions\"][\"03591c8b22497dd74214e08b3bf2a56f\"]\n        assert pkg[\"packages\"] == {}\n\n        c.run(f\"list *:* -fp=profile_armv8 --format=json {r}\")\n        result = json.loads(c.stdout)\n        header = result[pkg_key][\"header/1.0\"][\"revisions\"][\"747cc49983b14bdd00df50a0671bd8b3\"]\n        assert header[\"packages\"] == {\"da39a3ee5e6b4b0d3255bfef95601890afd80709\": {\"info\": {}}}\n        pkg = result[pkg_key][\"pkg/1.0\"][\"revisions\"][\"03591c8b22497dd74214e08b3bf2a56f\"]\n        assert len(pkg[\"packages\"]) == 2\n        settings = pkg[\"packages\"][\"2d46abc802bbffdf2af11591e3e452bc6149ea2b\"][\"info\"][\"settings\"]\n        assert settings == {\"arch\": \"armv8\", \"os\": \"Linux\"}\n        settings = pkg[\"packages\"][\"2a67a51fbf36a4ee345b2125dd2642be60ffd3ec\"][\"info\"][\"settings\"]\n        assert settings == {\"arch\": \"armv8\", \"os\": \"Macos\"}\n\n        c.run(f\"list *:* -fp=profile_shared --format=json {r}\")\n        result = json.loads(c.stdout)\n        header = result[pkg_key][\"header/1.0\"][\"revisions\"][\"747cc49983b14bdd00df50a0671bd8b3\"]\n        assert header[\"packages\"] == {\"da39a3ee5e6b4b0d3255bfef95601890afd80709\": {\"info\": {}}}\n        pkg = result[pkg_key][\"pkg/1.0\"][\"revisions\"][\"03591c8b22497dd74214e08b3bf2a56f\"]\n        assert len(pkg[\"packages\"]) == 1\n        settings = pkg[\"packages\"][\"2a67a51fbf36a4ee345b2125dd2642be60ffd3ec\"][\"info\"][\"settings\"]\n        assert settings == {\"arch\": \"armv8\", \"os\": \"Macos\"}\n\n        c.run(f\"list *:* -fs os=Windows -fo *:shared=False --format=json {r}\")\n        result = json.loads(c.stdout)\n        header = result[pkg_key][\"header/1.0\"][\"revisions\"][\"747cc49983b14bdd00df50a0671bd8b3\"]\n        assert header[\"packages\"] == {\"da39a3ee5e6b4b0d3255bfef95601890afd80709\": {\"info\": {}}}\n        pkg = result[pkg_key][\"pkg/1.0\"][\"revisions\"][\"03591c8b22497dd74214e08b3bf2a56f\"]\n        assert len(pkg[\"packages\"]) == 1\n        settings = pkg[\"packages\"][\"d2e97769569ac0a583d72c10a37d5ca26de7c9fa\"][\"info\"][\"settings\"]\n        assert settings == {\"arch\": \"x86\", \"os\": \"Windows\"}\n\n        # &: will also match every package being listed, as if it was a consumer\n        c.run(f\"list *:* -fo &:shared=False --format=json {r}\")\n        result = json.loads(c.stdout)\n        header = result[pkg_key][\"header/1.0\"][\"revisions\"][\"747cc49983b14bdd00df50a0671bd8b3\"]\n        assert header[\"packages\"] == {\"da39a3ee5e6b4b0d3255bfef95601890afd80709\": {\"info\": {}}}\n        pkg = result[pkg_key][\"pkg/1.0\"][\"revisions\"][\"03591c8b22497dd74214e08b3bf2a56f\"]\n        assert len(pkg[\"packages\"]) == 2\n        settings = pkg[\"packages\"][\"d2e97769569ac0a583d72c10a37d5ca26de7c9fa\"][\"info\"][\"settings\"]\n        assert settings == {\"arch\": \"x86\", \"os\": \"Windows\"}\n\n\ndef test_overlapping_versions():\n    tc = TestClient(light=True)\n    tc.save({\"conanfile.py\": GenConanfile(\"foo\")})\n    tc.run(\"export . --version=1.0\")\n    tc.run(\"export . --version=1.0.0\")\n    tc.run(\"list * -c -f=json\", redirect_stdout=\"list.json\")\n    results = json.loads(tc.load(\"list.json\"))\n    assert len(results[\"Local Cache\"]) == 2\n\n\ndef test_list_local_recipe_index():\n    c = TestClient(light=True)\n    c.run(f\"new local_recipes_index -d name=pkg -d version=0.1 -d url='https://conan-fake-url.com' \")\n    c.run(f\"remote add local '{c.current_folder}'\")\n\n    c.run(\"list '*' -r=local\")\n    assert \"Found 1 pkg/version recipes matching * in local\" in c.out\n    c.run(\"list '*/*' -r=local\")\n    assert \"Found 1 pkg/version recipes matching */* in local\" in c.out\n    c.run(\"list '*/0.1' -r=local\")\n    assert \"Found 1 pkg/version recipes matching */0.1 in local\" in c.out\n    c.run(\"list 'pkg/*' -r=local\")\n    assert \"Found 1 pkg/version recipes matching pkg/* in local\" in c.out\n    c.run(\"list 'pkg/0.*' -r=local\")\n    assert \"Found 1 pkg/version recipes matching pkg/0.* in local\" in c.out\n    c.run(\"list 'pkg' -r=local\")\n    assert \"Found 1 pkg/version recipes matching pkg in local\" in c.out\n    c.run(\"list 'pkg/0.1' -r=local\")\n    assert \"Found 1 pkg/version recipes matching pkg/0.1 in local\" in c.out\n    c.run(\"list 'foo' -r=local\")\n    assert \"ERROR: Recipe 'foo' not found\" in c.out\n    c.run(\"list '/#@&%%&@#/' -r=local\")\n    assert \"ERROR: Recipe '/' not found\" in c.out\n    c.run(\"list 'pkg/0.1@a' -r=local\")\n    assert \"ERROR: Recipe 'pkg/0.1@a' not found\" in c.out\n    c.run(\"list 'pkg%0.1#a@b/c' -r=local\")\n    assert \"ERROR: Recipe 'pkg%0.1' not found\" in c.out\n"
  },
  {
    "path": "test/integration/command/list/search_test.py",
    "content": "import textwrap\nfrom collections import OrderedDict\nfrom unittest.mock import patch, Mock\n\nimport pytest\n\nfrom conan.internal.errors import ConanConnectionError\nfrom conan.errors import ConanException\nfrom conan.api.model import RecipeReference\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient, TestServer\n\n\nclass TestSearch:\n\n    @pytest.fixture\n    def remotes(self):\n        self.servers = OrderedDict()\n        self.servers[\"remote1\"] = TestServer(server_capabilities=[])\n        self.servers[\"remote2\"] = TestServer(server_capabilities=[])\n\n        self.client = TestClient(servers=self.servers)\n\n    def test_search_no_params(self):\n        self.servers = OrderedDict()\n        self.client = TestClient(servers=self.servers)\n\n        self.client.run(\"search\", assert_error=True)\n        assert \"error: the following arguments are required: reference\" in self.client.out\n\n    def test_search_no_matching_recipes(self, remotes):\n        expected_output = (\"Connecting to remote 'remote1' anonymously\\n\"\n                           \"Connecting to remote 'remote2' anonymously\\n\"\n                           \"remote1\\n\"\n                           \"  ERROR: Recipe 'whatever' not found\\n\"\n                           \"remote2\\n\"\n                           \"  ERROR: Recipe 'whatever' not found\\n\")\n\n        self.client.run(\"search whatever\")\n        assert expected_output == self.client.out\n\n    def test_search_no_configured_remotes(self):\n        self.servers = OrderedDict()\n        self.client = TestClient(servers=self.servers)\n\n        self.client.run(\"search whatever\", assert_error=True)\n        assert \"There are no remotes to search from\" in self.client.out\n\n    def test_search_disabled_remote(self, remotes):\n        self.client.run(\"remote disable remote1\")\n        self.client.run(\"search whatever -r remote1\", assert_error=True)\n        expected_output = \"ERROR: Remote 'remote1' can't be found or is disabled\"\n        assert expected_output in self.client.out\n\n\nclass TestRemotes:\n\n    @pytest.fixture(autouse=True)\n    def _setup(self):\n        self.servers = OrderedDict()\n        self.users = {}\n        self.client = TestClient()\n\n    def _add_remote(self, remote_name):\n        self.servers[remote_name] = TestServer(users={\"user\": \"passwd\"})\n        self.users[remote_name] = [(\"user\", \"passwd\")]\n        self.client = TestClient(servers=self.servers, inputs=[\"user\", \"passwd\"])\n\n    def _add_recipe(self, remote, reference):\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class MyLib(ConanFile):\n                pass\n            \"\"\")\n\n        self.client.save({'conanfile.py': conanfile})\n        reference = RecipeReference.loads(str(reference))\n        self.client.run(f\"export . --name={reference.name} --version={reference.version} --user={reference.user} --channel={reference.channel}\")\n        self.client.run(\"upload --force -r {} {}\".format(remote, reference))\n\n    @pytest.mark.parametrize(\"exc,output\", [\n        (ConanConnectionError(\"Review your network!\"),\n         \"ERROR: Review your network!\"),\n        (ConanException(\"Boom!\"), \"ERROR: Boom!\")\n    ])\n    def test_search_remote_errors_but_no_raising_exceptions(self, exc, output):\n        self._add_remote(\"remote1\")\n        self._add_remote(\"remote2\")\n        with patch(\"conan.api.subapi.list._search_recipes\", new=Mock(side_effect=exc)):\n            self.client.run(\"search whatever\")\n        expected_output = textwrap.dedent(f\"\"\"\\\n        remote1\n          {output}\n        remote2\n          {output}\n        \"\"\")\n        assert expected_output == self.client.out\n\n    def test_no_remotes(self):\n        self.client.run(\"search something\", assert_error=True)\n        expected_output = \"There are no remotes to search from\"\n        assert expected_output in self.client.out\n\n    def test_search_by_name(self):\n        remote_name = \"remote1\"\n        recipe_name = \"test_recipe/1.0.0@user/channel\"\n        self._add_remote(remote_name)\n        self._add_recipe(remote_name, recipe_name)\n\n        self.client.run(\"search -r {} {}\".format(remote_name, \"test_recipe\"))\n\n        expected_output = (\n            \"remote1\\n\"\n            \"  test_recipe\\n\"\n            \"    {}\\n\".format(recipe_name)\n        )\n\n        assert expected_output in self.client.out\n\n    def test_search_in_all_remotes(self):\n        remote1 = \"remote1\"\n        remote2 = \"remote2\"\n\n        remote1_recipe1 = \"test_recipe/1.0.0@user/channel\"\n        remote1_recipe2 = \"test_recipe/1.1.0@user/channel\"\n        remote2_recipe1 = \"test_recipe/2.0.0@user/channel\"\n        remote2_recipe2 = \"test_recipe/2.1.0@user/channel\"\n\n        expected_output = (\n            \"remote1\\n\"\n            \"  test_recipe\\n\"\n            \"    test_recipe/1.0.0@user/channel\\n\"\n            \"    test_recipe/1.1.0@user/channel\\n\"\n            \"remote2\\n\"\n            \"  test_recipe\\n\"\n            \"    test_recipe/2.0.0@user/channel\\n\"\n            \"    test_recipe/2.1.0@user/channel\\n\"\n        )\n\n        self._add_remote(remote1)\n        self._add_recipe(remote1, remote1_recipe1)\n        self._add_recipe(remote1, remote1_recipe2)\n\n        self._add_remote(remote2)\n        self._add_recipe(remote2, remote2_recipe1)\n        self._add_recipe(remote2, remote2_recipe2)\n\n        self.client.run(\"search test_recipe\")\n        assert expected_output in self.client.out\n\n    def test_search_in_one_remote(self):\n        remote1 = \"remote1\"\n        remote2 = \"remote2\"\n\n        remote1_recipe1 = \"test_recipe/1.0.0@user/channel\"\n        remote1_recipe2 = \"test_recipe/1.1.0@user/channel\"\n        remote2_recipe1 = \"test_recipe/2.0.0@user/channel\"\n        remote2_recipe2 = \"test_recipe/2.1.0@user/channel\"\n\n        expected_output = (\n            \"remote1\\n\"\n            \"  test_recipe\\n\"\n            \"    test_recipe/1.0.0@user/channel\\n\"\n            \"    test_recipe/1.1.0@user/channel\\n\"\n        )\n\n        self._add_remote(remote1)\n        self._add_recipe(remote1, remote1_recipe1)\n        self._add_recipe(remote1, remote1_recipe2)\n\n        self._add_remote(remote2)\n        self._add_recipe(remote2, remote2_recipe1)\n        self._add_recipe(remote2, remote2_recipe2)\n\n        self.client.run(\"search -r remote1 test_recipe\")\n        assert expected_output in self.client.out\n\n    def test_search_package_found_in_one_remote(self):\n\n        remote1 = \"remote1\"\n        remote2 = \"remote2\"\n\n        remote1_recipe1 = \"test_recipe/1.0.0@user/channel\"\n        remote1_recipe2 = \"test_recipe/1.1.0@user/channel\"\n        remote2_recipe1 = \"another_recipe/2.0.0@user/channel\"\n        remote2_recipe2 = \"another_recipe/2.1.0@user/channel\"\n\n        expected_output = (\n            \"remote1\\n\"\n            \"  test_recipe\\n\"\n            \"    test_recipe/1.0.0@user/channel\\n\"\n            \"    test_recipe/1.1.0@user/channel\\n\"\n            \"remote2\\n\"\n            \"  ERROR: Recipe 'test_recipe' not found\\n\"\n        )\n\n        self._add_remote(remote1)\n        self._add_recipe(remote1, remote1_recipe1)\n        self._add_recipe(remote1, remote1_recipe2)\n\n        self._add_remote(remote2)\n        self._add_recipe(remote2, remote2_recipe1)\n        self._add_recipe(remote2, remote2_recipe2)\n\n        self.client.run(\"search test_recipe\")\n        assert expected_output in self.client.out\n\n    def test_search_in_missing_remote(self):\n        remote1 = \"remote1\"\n\n        remote1_recipe1 = \"test_recipe/1.0.0@user/channel\"\n        remote1_recipe2 = \"test_recipe/1.1.0@user/channel\"\n\n        self._add_remote(remote1)\n        self._add_recipe(remote1, remote1_recipe1)\n        self._add_recipe(remote1, remote1_recipe2)\n\n        self.client.run(\"search -r wrong_remote test_recipe\", assert_error=True)\n        expected_output = \"ERROR: Remote 'wrong_remote' can't be found or is disabled\"\n        assert expected_output in self.client.out\n\n    def test_search_wildcard(self):\n        remote1 = \"remote1\"\n\n        remote1_recipe1 = \"test_recipe/1.0.0@user/channel\"\n        remote1_recipe2 = \"test_recipe/1.1.0@user/channel\"\n        remote1_recipe3 = \"test_another/2.1.0@user/channel\"\n        remote1_recipe4 = \"test_another/4.1.0@user/channel\"\n\n        expected_output = (\n            \"remote1\\n\"\n            \"  test_another\\n\"\n            \"    test_another/2.1.0@user/channel\\n\"\n            \"    test_another/4.1.0@user/channel\\n\"\n            \"  test_recipe\\n\"\n            \"    test_recipe/1.0.0@user/channel\\n\"\n            \"    test_recipe/1.1.0@user/channel\\n\"\n        )\n\n        self._add_remote(remote1)\n        self._add_recipe(remote1, remote1_recipe1)\n        self._add_recipe(remote1, remote1_recipe2)\n        self._add_recipe(remote1, remote1_recipe3)\n        self._add_recipe(remote1, remote1_recipe4)\n\n        self.client.run(\"search test_*\")\n        assert expected_output in self.client.out\n\n\ndef test_no_user_channel_error():\n    # https://github.com/conan-io/conan/issues/13170\n    c = TestClient(default_server_user=True)\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\")})\n    c.run(\"export . --version=1.0\")\n    c.run(\"export . --version=1.0 --user=user --channel=channel\")\n    c.run(\"list *\")\n    assert \"pkg/1.0\" in [s.strip() for s in str(c.out).splitlines()]\n    assert \"pkg/1.0@user/channel\" in c.out\n    # I want to list only those without user/channel\n    c.run(\"list pkg/*@\")\n    assert \"pkg/1.0\" in c.out\n    assert \"user/channel\" not in c.out\n\n    # The same underlying logic is used in upload\n    c.run(\"upload pkg/*@ -r=default -c\")\n    assert \"Uploading recipe 'pkg/1.0\" in c.out\n    assert \"user/channel\" not in c.out\n\n    c.run(\"search pkg/*@ -r=default\")\n    assert \"pkg/1.0\" in c.out\n    assert \"user/channel\" not in c.out\n"
  },
  {
    "path": "test/integration/command/list/test_combined_pkglist_flows.py",
    "content": "import json\nfrom collections import OrderedDict\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.env import environment_update\nfrom conan.test.utils.tools import TestClient, TestServer\n\n\nclass TestListUpload:\n    refs = [\"zli/1.0.0#f034dc90894493961d92dd32a9ee3b78\",\n            \"zlib/1.0.0@user/channel#ffd4bc45820ddb320ab224685b9ba3fb\"]\n\n    @pytest.fixture()\n    def client(self):\n        c = TestClient(default_server_user=True, light=True)\n        c.save({\n            \"zlib.py\": GenConanfile(\"zlib\"),\n            \"zli.py\": GenConanfile(\"zli\", \"1.0.0\")\n        })\n        c.run(\"create zli.py\")\n        c.run(\"create zlib.py --version=1.0.0 --user=user --channel=channel\")\n        return c\n\n    def test_list_upload_recipes(self, client):\n        pattern = \"z*#latest\"\n        client.run(f\"list {pattern} --format=json\", redirect_stdout=\"pkglist.json\")\n        client.run(\"upload --list=pkglist.json -r=default\")\n        for r in self.refs:\n            assert f\"Uploading recipe '{r}'\" in client.out\n        assert \"Uploading package\" not in client.out\n\n    def test_list_upload_packages(self, client):\n        pattern = \"z*#latest:*#latest\"\n        client.run(f\"list {pattern} --format=json\", redirect_stdout=\"pkglist.json\")\n        client.run(\"upload --list=pkglist.json -r=default\")\n        for r in self.refs:\n            assert f\"Uploading recipe '{r}'\" in client.out\n        assert str(client.out).count(\"Uploading package\") == 2\n\n    def test_list_upload_empty_list(self, client):\n        client.run(f\"install --requires=zlib/1.0.0@user/channel -f json\",\n                   redirect_stdout=\"install_graph.json\")\n\n        # Generate an empty pkglist.json\n        client.run(f\"list --format=json --graph=install_graph.json --graph-binaries=bogus\",\n                   redirect_stdout=\"pkglist.json\")\n\n        # No binaries should be uploaded since the pkglist is empty, but the command\n        # should not error\n        client.run(\"upload --list=pkglist.json -r=default\")\n        assert \"No packages were uploaded because the package list is empty.\" in client.out\n\n\nclass TestGraphCreatedUpload:\n    def test_create_upload(self):\n        c = TestClient(default_server_user=True, light=True)\n        c.save({\"zlib/conanfile.py\": GenConanfile(\"zlib\", \"1.0\"),\n                \"app/conanfile.py\": GenConanfile(\"app\", \"1.0\").with_requires(\"zlib/1.0\")})\n        c.run(\"create zlib\")\n        c.run(\"create app --format=json\", redirect_stdout=\"graph.json\")\n        c.run(\"list --graph=graph.json --format=json\", redirect_stdout=\"pkglist.json\")\n        c.run(\"upload --list=pkglist.json -r=default\")\n        assert \"Uploading recipe 'app/1.0#0fa1ff1b90576bb782600e56df642e19'\" in c.out\n        assert \"Uploading recipe 'zlib/1.0#c570d63921c5f2070567da4bf64ff261'\" in c.out\n        assert \"Uploading package 'app\" in c.out\n        assert \"Uploading package 'zlib\" in c.out\n\n\nclass TestExportUpload:\n    def test_export_upload(self):\n        c = TestClient(default_server_user=True, light=True)\n        c.save({\"zlib/conanfile.py\": GenConanfile(\"zlib\", \"1.0\")})\n        c.run(\"export zlib --format=pkglist\", redirect_stdout=\"pkglist.json\")\n        c.run(\"upload --list=pkglist.json -r=default -c\")\n        assert \"Uploading recipe 'zlib/1.0#c570d63921c5f2070567da4bf64ff261'\" in c.out\n\n\nclass TestCreateGraphToPkgList:\n    def test_graph_pkg_nonexistant(self):\n        c = TestClient(light=True)\n        c.run(\"list --graph=non-existent-file.json\", assert_error=True)\n        assert \"ERROR: Graph file not found\" in c.out\n\n    def test_graph_pkg_list_only_built(self):\n        c = TestClient(light=True)\n        c.save({\"zlib/conanfile.py\": GenConanfile(\"zlib\", \"1.0\"),\n                \"app/conanfile.py\": GenConanfile(\"app\", \"1.0\").with_requires(\"zlib/1.0\")\n                                                              .with_settings(\"os\")\n                                                              .with_shared_option(False)})\n        c.run(\"create zlib\")\n        c.run(\"create app --format=json -s os=Linux\", redirect_stdout=\"graph.json\")\n        c.run(\"list --graph=graph.json --graph-binaries=build --format=json\")\n        pkglist = json.loads(c.stdout)[\"Local Cache\"]\n        assert len(pkglist) == 1\n        pkgs = pkglist[\"app/1.0\"][\"revisions\"][\"8263c3c32802e14a2f03a0b1fcce0d95\"][\"packages\"]\n        assert len(pkgs) == 1\n        pkg_app = pkgs[\"d8b3bdd894c3eb9bf2a3119ee0f8c70843ace0ac\"]\n        assert pkg_app[\"info\"][\"requires\"] == [\"zlib/1.0.Z\"]\n        assert pkg_app[\"info\"][\"settings\"] == {'os': 'Linux'}\n        assert pkg_app[\"info\"][\"options\"] == {'shared': 'False'}\n\n    def test_graph_pkg_list_all_recipes_only(self):\n        \"\"\"\n        --graph-recipes=* selects all the recipes in the graph\n        \"\"\"\n        c = TestClient(light=True)\n        c.save({\"zlib/conanfile.py\": GenConanfile(\"zlib\", \"1.0\"),\n                \"app/conanfile.py\": GenConanfile(\"app\", \"1.0\").with_requires(\"zlib/1.0\")})\n        c.run(\"create zlib\")\n        c.run(\"create app --format=json\", redirect_stdout=\"graph.json\")\n        c.run(\"list --graph=graph.json --graph-recipes=* --format=json\")\n        pkglist = json.loads(c.stdout)[\"Local Cache\"]\n        assert len(pkglist) == 2\n        assert \"packages\" not in pkglist[\"app/1.0\"][\"revisions\"][\"0fa1ff1b90576bb782600e56df642e19\"]\n        assert \"packages\" not in pkglist[\"zlib/1.0\"][\"revisions\"][\"c570d63921c5f2070567da4bf64ff261\"]\n\n    def test_graph_pkg_list_python_requires(self):\n        \"\"\"\n        include python_requires too\n        \"\"\"\n        c = TestClient(default_server_user=True, light=True)\n        c.save({\"pytool/conanfile.py\": GenConanfile(\"pytool\", \"0.1\"),\n                \"zlib/conanfile.py\": GenConanfile(\"zlib\", \"1.0\").with_python_requires(\"pytool/0.1\"),\n                \"app/conanfile.py\": GenConanfile(\"app\", \"1.0\").with_requires(\"zlib/1.0\")})\n        c.run(\"create pytool\")\n        c.run(\"create zlib\")\n        c.run(\"upload * -c -r=default\")\n        c.run(\"remove * -c\")\n        c.run(\"create app --format=json\", redirect_stdout=\"graph.json\")\n        c.run(\"list --graph=graph.json --format=json\")\n        pkglist = json.loads(c.stdout)[\"Local Cache\"]\n        assert len(pkglist) == 3\n        assert \"96aec08148a2392127462c800e1c8af6\" in pkglist[\"pytool/0.1\"][\"revisions\"]\n        pkglist = json.loads(c.stdout)[\"default\"]\n        assert len(pkglist) == 2\n        assert \"96aec08148a2392127462c800e1c8af6\" in pkglist[\"pytool/0.1\"][\"revisions\"]\n\n    def test_graph_pkg_list_create_python_requires(self):\n        \"\"\"\n        include python_requires too\n        \"\"\"\n        c = TestClient(default_server_user=True, light=True)\n        c.save({\"conanfile.py\": GenConanfile(\"pytool\", \"0.1\").with_package_type(\"python-require\")})\n        c.run(\"create . --format=json\", redirect_stdout=\"graph.json\")\n        c.run(\"list --graph=graph.json --format=json\")\n        pkglist = json.loads(c.stdout)[\"Local Cache\"]\n        assert len(pkglist) == 1\n        assert \"62a6a9e5347b789bfc6572948ea19f85\" in pkglist[\"pytool/0.1\"][\"revisions\"]\n\n\nclass TestGraphInfoToPkgList:\n    def test_graph_pkg_list_only_built(self):\n        c = TestClient(default_server_user=True, light=True)\n        c.save({\"zlib/conanfile.py\": GenConanfile(\"zlib\", \"1.0\"),\n                \"app/conanfile.py\": GenConanfile(\"app\", \"1.0\").with_requires(\"zlib/1.0\")})\n        c.run(\"create zlib\")\n        c.run(\"create app --format=json\")\n        c.run(\"upload * -c -r=default\")\n        c.run(\"remove * -c\")\n        c.run(\"graph info --requires=app/1.0 --format=json\", redirect_stdout=\"graph.json\")\n        c.run(\"list --graph=graph.json --graph-binaries=build --format=json\")\n        pkglist = json.loads(c.stdout)\n        assert len(pkglist[\"Local Cache\"]) == 0\n        assert len(pkglist[\"default\"]) == 2\n        c.run(\"install --requires=app/1.0 --format=json\", redirect_stdout=\"graph.json\")\n        c.run(\"list --graph=graph.json --graph-binaries=download --format=json\")\n        pkglist = json.loads(c.stdout)\n        assert len(pkglist[\"Local Cache\"]) == 2\n        assert len(pkglist[\"default\"]) == 2\n        c.run(\"list --graph=graph.json --graph-binaries=build --format=json\")\n        pkglist = json.loads(c.stdout)\n        assert len(pkglist[\"Local Cache\"]) == 0\n        assert len(pkglist[\"default\"]) == 2\n\n\nclass TestPkgListFindRemote:\n    \"\"\" we can recover a list of remotes for an already installed graph, for metadata download\n    \"\"\"\n    def test_graph_2_pkg_list_remotes(self):\n        servers = OrderedDict([(\"default\", TestServer()), (\"remote2\", TestServer())])\n        c = TestClient(servers=servers, inputs=2 * [\"admin\", \"password\"], light=True)\n        c.save({\"zlib/conanfile.py\": GenConanfile(\"zlib\", \"1.0\"),\n                \"app/conanfile.py\": GenConanfile(\"app\", \"1.0\").with_requires(\"zlib/1.0\")})\n        c.run(\"create zlib\")\n        c.run(\"create app \")\n        c.run(\"upload zlib* -c -r=default\")\n        c.run(\"upload zlib* -c -r=remote2\")\n        c.run(\"upload app* -c -r=remote2\")\n\n        # This install, packages will be in the cache\n        c.run(\"install --requires=app/1.0 --format=json\", redirect_stdout=\"graph.json\")\n        # So list, will not have remote at all\n        c.run(\"list --graph=graph.json --format=json\", redirect_stdout=\"pkglist.json\")\n\n        pkglist = json.loads(c.load(\"pkglist.json\"))\n        assert len(pkglist[\"Local Cache\"]) == 2\n        assert \"default\" not in pkglist  # The remote doesn't even exist\n\n        # Lets now compute a list finding in the remotes\n        c.run(\"pkglist find-remote pkglist.json --format=json\", redirect_stdout=\"remotepkg.json\")\n        pkglist = json.loads(c.stdout)\n        assert \"Local Cache\" not in pkglist\n        assert len(pkglist[\"default\"]) == 1\n        assert \"zlib/1.0\" in pkglist[\"default\"]\n        assert len(pkglist[\"remote2\"]) == 2\n        assert \"app/1.0\" in pkglist[\"remote2\"]\n        assert \"zlib/1.0\" in pkglist[\"remote2\"]\n\n        c.run(\"download --list=remotepkg.json -r=default --metadata=*\")\n        assert \"zlib/1.0: Retrieving recipe metadata from remote 'default'\" in c.out\n        assert \"zlib/1.0: Retrieving package metadata\" in c.out\n        c.run(\"download --list=remotepkg.json -r=remote2 --metadata=*\")\n        assert \"app/1.0: Retrieving recipe metadata from remote 'remote2'\" in c.out\n        assert \"app/1.0: Retrieving package metadata\" in c.out\n\n    def test_input_only_name_version(self):\n        c = TestClient(default_server_user=True, light=True)\n        c.save({\"zlib/conanfile.py\": GenConanfile(\"zlib\", \"1.0\")})\n        c.run(\"create zlib\")\n        c.run(\"upload zlib* -c -r=default\")\n\n        # Create input pkglist for find-remote\n        c.run(f\"list * --format=json\", redirect_stdout=\"mylist.json\")\n        pkglist = json.loads(c.load(\"mylist.json\"))\n        expected = {\"zlib/1.0\": {}}\n        assert pkglist[\"Local Cache\"] == expected\n\n        c.run(\"pkglist find-remote mylist.json --format=json --remote default\")\n        pkglist = json.loads(c.stdout)\n        assert pkglist[\"default\"] == expected\n\n    def test_input_recipe_revisions(self):\n        c = TestClient(default_server_user=True, light=True)\n        c.save({\"zlib/conanfile.py\": GenConanfile(\"zlib\", \"1.0\")})\n        c.run(\"create zlib\")\n        c.run(\"upload zlib* -c -r=default\")\n\n        # Create input pkglist for find-remote\n        c.run(f\"list *#* --format=json\", redirect_stdout=\"mylist.json\")\n\n        def _check(origin):\n            pkglist = json.loads(c.load(\"mylist.json\"))\n            revs = pkglist[origin][\"zlib/1.0\"][\"revisions\"]\n            assert list(revs) == [\"c570d63921c5f2070567da4bf64ff261\"]\n            assert \"packages\" not in revs[\"c570d63921c5f2070567da4bf64ff261\"]\n\n        _check(\"Local Cache\")\n\n        c.run(\"pkglist find-remote mylist.json --format=json --remote default\",\n              redirect_stdout=\"mylist.json\")\n        _check(\"default\")\n\n    def test_input_only_package_ids(self):\n        c = TestClient(default_server_user=True, light=True)\n        c.save({\"zlib/conanfile.py\": GenConanfile(\"zlib\", \"1.0\").with_settings(\"os\")})\n        c.run(\"create zlib -s os=Linux\")\n        c.run(\"upload zlib* -c -r=default\")\n\n        # Create input pkglist for find-remote\n        c.run(f\"list *:* --format=json\", redirect_stdout=\"mylist.json\")\n\n        def _check(origin):\n            pkglist = json.loads(c.load(\"mylist.json\"))\n            revs = pkglist[origin][\"zlib/1.0\"][\"revisions\"]\n            assert list(revs) == [\"1cb7410d0365f87510a6767c7bef804e\"]\n            info = {\"info\": {'settings': {'os': 'Linux'}}}\n            expected = {\"9a4eb3c8701508aa9458b1a73d0633783ecc2270\": info}\n            assert revs[\"1cb7410d0365f87510a6767c7bef804e\"][\"packages\"] == expected\n\n        c.run(\"pkglist find-remote mylist.json --format=json --remote default\",\n              redirect_stdout=\"mylist.json\")\n        _check(\"default\")\n\n    def test_graph_pkg_list_of_recipes_and_binaries(self):\n        c = TestClient(default_server_user=True, light=True)\n        c.save({\"zlib/conanfile.py\": GenConanfile(\"zlib\", \"1.0\").with_settings(\"os\")})\n        c.run(\"create zlib -s os=Linux\")\n        c.run(\"upload zlib* -c -r=default\")\n\n        # Create input pkglist for find-remote\n        c.run(f\"list *#*:*#* --format=json\", redirect_stdout=\"mylist.json\")\n\n        def _check(origin):\n            pkglist = json.loads(c.load(\"mylist.json\"))\n            revs = pkglist[origin][\"zlib/1.0\"][\"revisions\"]\n            assert list(revs) == [\"1cb7410d0365f87510a6767c7bef804e\"]\n            expected = {'settings': {'os': 'Linux'}}\n            pkgs = revs[\"1cb7410d0365f87510a6767c7bef804e\"][\"packages\"]\n            assert list(pkgs) == [\"9a4eb3c8701508aa9458b1a73d0633783ecc2270\"]\n            pkg = pkgs[\"9a4eb3c8701508aa9458b1a73d0633783ecc2270\"]\n            assert pkg[\"info\"] == expected\n            assert list(pkg[\"revisions\"]) == [\"1d3c57385f4133c1fbd6d13bd538496e\"]\n\n        _check(\"Local Cache\")\n        c.run(\"pkglist find-remote mylist.json --format=json --remote default\",\n              redirect_stdout=\"mylist.json\")\n        _check(\"default\")\n\n    def test_graph_pkg_list_counter_example(self):\n        c = TestClient(default_server_user=True, light=True)\n        c.save({\"conanfile.py\": GenConanfile(\"zlib\", \"1.0\").with_package_file(\"file.txt\",\n                                                                              env_var=\"MY_VAR\")})\n\n        with environment_update({\"MY_VAR\": \"1\"}):\n            c.run(\"create .\")\n        with environment_update({\"MY_VAR\": \"2\"}):\n            c.run(\"create .\")\n        c.run(\"upload zlib*:*#* -c -r=default\")\n\n        # Create input pkglist for find-remote\n        c.run(f\"list zlib/1.0#latest:*#latest --format=json\", redirect_stdout=\"mylist.json\")\n\n        def _check(origin):\n            pkglist = json.loads(c.load(\"mylist.json\"))\n            prevs = pkglist[origin][\"zlib/1.0\"][\"revisions\"]\n            input_pkgs = prevs[\"212b9babae6a4b8a8362703cec4257ad\"][\"packages\"]\n            prevs = input_pkgs[\"da39a3ee5e6b4b0d3255bfef95601890afd80709\"][\"revisions\"]\n            assert len(prevs) == 1\n\n        _check(\"Local Cache\")\n        c.run(\"pkglist find-remote mylist.json --format=json --remote default\",\n              redirect_stdout=\"mylist.json\")\n        _check(\"default\")\n\n\nclass TestPkgListMerge:\n    \"\"\" deep merge lists\n    \"\"\"\n    def test_graph_2_pkg_list_remotes(self):\n        servers = OrderedDict([(\"default\", TestServer()), (\"remote2\", TestServer())])\n        c = TestClient(servers=servers, inputs=2 * [\"admin\", \"password\"])\n        c.save({\"zlib/conanfile.py\": GenConanfile(\"zlib\", \"1.0\").with_settings(\"build_type\"),\n                \"bzip2/conanfile.py\": GenConanfile(\"bzip2\", \"1.0\").with_settings(\"build_type\"),\n                \"app/conanfile.py\": GenConanfile(\"app\", \"1.0\").with_requires(\"zlib/1.0\", \"bzip2/1.0\")\n                                                              .with_settings(\"build_type\")})\n        c.run(\"create zlib\")\n        c.run(\"create bzip2\")\n        c.run(\"create app \")\n\n        c.run(\"list zlib:* --format=json\", redirect_stdout=\"list1.json\")\n        c.run(\"list bzip2:* --format=json\", redirect_stdout=\"list2.json\")\n        c.run(\"list app:* --format=json\", redirect_stdout=\"list3.json\")\n        c.run(\"pkglist merge --list=list1.json --list=list2.json --list=list3.json --format=json\",\n              redirect_stdout=\"release.json\")\n        final = json.loads(c.stdout)\n        assert \"app/1.0\" in final[\"Local Cache\"]\n        assert \"zlib/1.0\" in final[\"Local Cache\"]\n        assert \"bzip2/1.0\" in final[\"Local Cache\"]\n\n        c.run(\"create zlib -s build_type=Debug\")\n        c.run(\"create bzip2 -s build_type=Debug\")\n        c.run(\"create app -s build_type=Debug\")\n        c.run(\"list *:* -fs build_type=Debug --format=json\", redirect_stdout=\"debug.json\")\n        c.run(\"pkglist merge --list=release.json --list=debug.json --format=json\",\n              redirect_stdout=\"release.json\")\n        final = json.loads(c.stdout)\n        rev = final[\"Local Cache\"][\"zlib/1.0\"][\"revisions\"][\"11f74ff5f006943c6945117511ac8b64\"]\n        assert len(rev[\"packages\"]) == 2  # Debug and Release\n        settings = rev[\"packages\"][\"efa83b160a55b033c4ea706ddb980cd708e3ba1b\"][\"info\"][\"settings\"]\n        assert settings == {\"build_type\": \"Release\"}\n        settings = rev[\"packages\"][\"9e186f6d94c008b544af1569d1a6368d8339efc5\"][\"info\"][\"settings\"]\n        assert settings == {\"build_type\": \"Debug\"}\n        rev = final[\"Local Cache\"][\"bzip2/1.0\"][\"revisions\"][\"9e0352b3eb99ba4ac79bc7eeae2102c5\"]\n        assert len(rev[\"packages\"]) == 2  # Debug and Release\n        settings = rev[\"packages\"][\"efa83b160a55b033c4ea706ddb980cd708e3ba1b\"][\"info\"][\"settings\"]\n        assert settings == {\"build_type\": \"Release\"}\n        settings = rev[\"packages\"][\"9e186f6d94c008b544af1569d1a6368d8339efc5\"][\"info\"][\"settings\"]\n        assert settings == {\"build_type\": \"Debug\"}\n\n    def test_pkglist_file_error(self):\n        # This can happen when reusing the same file in input and output\n        c = TestClient(light=True)\n        c.run(\"pkglist merge -l mylist.json\", assert_error=True)\n        assert \"ERROR: Package list file missing or broken:\" in c.out\n        c.save({\"mylist.json\": \"\"})\n        c.run(\"pkglist merge -l mylist.json\", assert_error=True)\n        assert \"ERROR: Package list file invalid JSON:\" in c.out\n\n        # This can happen when using a graph JSON file instead of a package list file\n        c.save({\"conanfile.py\": GenConanfile(\"lib\")})\n        c.run(\"create . --version=1.0 --format=json\", redirect_stdout=\"out/graph.json\")\n        c.run(\"pkglist merge -l out/graph.json\", assert_error=True)\n        assert (\n            'ERROR: Expected a package list file but found a graph file. '\n            'You can create a \"package list\" JSON file by running:' in c.out\n        )\n        assert \"conan list --graph graph.json --format=json > pkglist.json\" in c.out\n\n\nclass TestDownloadUpload:\n    @pytest.fixture()\n    def client(self):\n        c = TestClient(default_server_user=True, light=True)\n        c.save({\n            \"zlib.py\": GenConanfile(\"zlib\"),\n            \"zli.py\": GenConanfile(\"zli\", \"1.0.0\")\n        })\n        c.run(\"create zli.py\")\n        c.run(\"create zlib.py --version=1.0.0 --user=user --channel=channel\")\n        c.run(\"upload * -r=default -c\")\n        c.run(\"remove * -c\")\n        return c\n\n    @pytest.mark.parametrize(\"prev_list\", [False, True])\n    def test_download_upload_all(self, client, prev_list):\n        # We need to be consequeent with the pattern, it is not the same defaults for\n        # download and for list\n        pattern = \"zlib/*#latest:*#latest\"\n        if prev_list:\n            client.run(f\"list {pattern} -r=default --format=json\", redirect_stdout=\"pkglist.json\")\n            # Overwriting previous pkglist.json\n            pattern = \"--list=pkglist.json\"\n\n        client.run(f\"download {pattern} -r=default --format=json\", redirect_stdout=\"pkglist.json\")\n        # TODO: Discuss \"origin\"\n        assert \"Local Cache\" in client.load(\"pkglist.json\")\n        client.run(\"remove * -r=default -c\")\n        client.run(\"upload --list=pkglist.json -r=default\")\n        assert f\"Uploading recipe 'zlib/1.0.0\" in client.out\n        assert f\"Uploading recipe 'zli/\" not in client.out\n        assert \"Uploading package 'zlib/1.0.0\" in client.out\n        assert \"Uploading package 'zli/\" not in client.out\n\n    def test_download_upload_all_no_removed(self):\n        c = TestClient(default_server_user=True, light=True)\n        c.save({\"zlib.py\": GenConanfile(\"zlib\", \"0.1\")})\n        c.run(\"create zlib.py \")\n        c.run(\"upload * -r=default -c --format=json\", redirect_stdout=\"pkglist.json\")\n        c.run(\"remove * -c\")\n        c.run(f\"download --list=pkglist.json -r=default --format=json\",\n              redirect_stdout=\"pkglist.json\")\n        # The original \"files\" and \"upload-urls\" fields of first upload are removed\n        pkglist_json = c.load(\"pkglist.json\")\n        assert \"files\" not in pkglist_json\n        assert \"upload-urls\" not in pkglist_json\n        c.run(\"upload --list=pkglist.json -r=default --format=json\")\n        # It doesn't crash anymore\n\n    @pytest.mark.parametrize(\"prev_list\", [False, True])\n    def test_download_upload_only_recipes(self, client, prev_list):\n        if prev_list:\n            pattern = \"zlib/*#latest\"\n            client.run(f\"list {pattern} -r=default --format=json\", redirect_stdout=\"pkglist.json\")\n            # Overwriting previous pkglist.json\n            pattern = \"--list=pkglist.json\"\n        else:\n            pattern = \"zlib/*#latest --only-recipe\"\n        client.run(f\"download {pattern} -r=default --format=json\", redirect_stdout=\"pkglist.json\")\n        # TODO: Discuss \"origin\"\n        assert \"Local Cache\" in client.load(\"pkglist.json\")\n        # Download binary too! Just to make sure it is in the cache, but not uploaded\n        # because it is not in the orignal list of only recipes\n        client.run(f\"download * -r=default\")\n        client.run(\"remove * -r=default -c\")\n        client.run(\"upload --list=pkglist.json -r=default\")\n        assert f\"Uploading recipe 'zlib/1.0.0\" in client.out\n        assert f\"Uploading recipe 'zli/\" not in client.out\n        assert \"Uploading package 'zlib/1.0.0\" not in client.out\n        assert \"Uploading package 'zli/\" not in client.out\n\n\nclass TestListRemove:\n    @pytest.fixture()\n    def client(self):\n        c = TestClient(default_server_user=True, light=True)\n        c.save({\n            \"zlib.py\": GenConanfile(\"zlib\"),\n            \"zli.py\": GenConanfile(\"zli\", \"1.0.0\")\n        })\n        c.run(\"create zli.py\")\n        c.run(\"create zlib.py --version=1.0.0 --user=user --channel=channel\")\n        c.run(\"upload * -r=default -c\")\n        return c\n\n    def test_remove_nothing_only_refs(self, client):\n        # It is necessary to do *#* for actually removing something\n        client.run(f\"list * --format=json\", redirect_stdout=\"pkglist.json\")\n        client.run(f\"remove --list=pkglist.json -c --format=json\")\n        assert \"Nothing to remove, package list do not contain recipe revisions\" in client.out\n        result = json.loads(client.stdout)\n        assert result[\"Local Cache\"] == {}  # Nothing was removed\n\n    @pytest.mark.parametrize(\"remote\", [False, True])\n    def test_remove_all(self, client, remote):\n        # It is necessary to do *#* for actually removing something\n        remote = \"-r=default\" if remote else \"\"\n        client.run(f\"list *#* {remote} --format=json\", redirect_stdout=\"pkglist.json\")\n        client.run(f\"remove --list=pkglist.json {remote} -c --dry-run\")\n        assert \"zli/1.0.0#f034dc90894493961d92dd32a9ee3b78:\" \\\n               \" Removed recipe and all binaries\" in client.out\n        assert \"zlib/1.0.0@user/channel#ffd4bc45820ddb320ab224685b9ba3fb:\" \\\n               \" Removed recipe and all binaries\" in client.out\n\n        client.run(f\"remove --list=pkglist.json {remote} -c --format=json\")\n        result = json.loads(client.stdout)\n        origin = \"Local Cache\" if not remote else \"default\"\n        assert len(result[origin][\"zli/1.0.0\"][\"revisions\"]) == 1\n        assert len(result[origin][\"zlib/1.0.0@user/channel\"][\"revisions\"]) == 1\n        assert \"packages\" not in client.stdout  # Packages are not listed at all\n\n        client.run(f\"list * {remote}\")\n        assert \"There are no matching recipe references\" in client.out\n\n    @pytest.mark.parametrize(\"remote\", [False, True])\n    def test_remove_packages_no_revisions(self, client, remote):\n        # It is necessary to do *#*:*#* for actually removing binaries\n        remote = \"-r=default\" if remote else \"\"\n        client.run(f\"list *#*:* {remote} --format=json\", redirect_stdout=\"pkglist.json\")\n        client.run(f\"remove --list=pkglist.json {remote} -c --format=json\")\n        assert \"No binaries to remove for 'zli/1.0.0#f034dc90894493961d92dd32a9ee3b78'\" in client.out\n        assert \"No binaries to remove for 'zlib/1.0.0@user/channel\" \\\n               \"#ffd4bc45820ddb320ab224685b9ba3fb\" in client.out\n        result = json.loads(client.stdout)\n        origin = \"Local Cache\" if not remote else \"default\"\n        assert result[origin] == {}  # Nothing was removed\n\n    @pytest.mark.parametrize(\"remote\", [False, True])\n    def test_remove_packages(self, client, remote):\n        # It is necessary to do *#*:*#* for actually removing binaries\n        remote = \"-r=default\" if remote else \"\"\n        client.run(f\"list *#*:*#* {remote} --format=json\", redirect_stdout=\"pkglist.json\")\n        client.run(f\"remove --list=pkglist.json {remote} -c --dry-run\")\n        assert \"Removed recipe and all binaries\" not in client.out\n        assert \"zli/1.0.0#f034dc90894493961d92dd32a9ee3b78: Removed binaries\" in client.out\n        assert \"zlib/1.0.0@user/channel#ffd4bc45820ddb320ab224685b9ba3fb: \" \\\n               \"Removed binaries\" in client.out\n\n        client.run(f\"remove --list=pkglist.json {remote} -c --format=json\")\n        result = json.loads(client.stdout)\n        origin = \"Local Cache\" if not remote else \"default\"\n        zli_revs = result[origin][\"zli/1.0.0\"][\"revisions\"]\n        zli_uc_revs = result[origin][\"zlib/1.0.0@user/channel\"][\"revisions\"]\n        assert len(zli_revs) == 1\n        assert len(zli_uc_revs) == 1\n        assert len(zli_revs[\"f034dc90894493961d92dd32a9ee3b78\"][\"packages\"]) == 1\n        assert len(zli_uc_revs[\"ffd4bc45820ddb320ab224685b9ba3fb\"][\"packages\"]) == 1\n\n        client.run(f\"list *:* {remote}\")\n        assert \"zli/1.0.0\" in client.out\n        assert \"zlib/1.0.0@user/channel\" in client.out\n\n\nclass TestListGraphContext:\n\n    @pytest.mark.parametrize(\"context, refs, not_refs\", [\n        (\"build\", [\"cmake/1.0\", \"m4/1.0\", \"protobuf/1.0\"], []),\n        (\"build-only\", [\"cmake/1.0\", \"m4/1.0\"], [\"protobuf/1.0\"]),\n        (\"host\", [\"zlib/1.0\", \"protobuf/1.0\"], []),\n        (\"host-only\", [\"zlib/1.0\"], [\"protobuf/1.0\"])\n    ])\n    def test_list_graph_context(self, context, refs, not_refs):\n        c = TestClient(default_server_user=True, light=True)\n        c.save({\n            \"zlib/conanfile.py\": GenConanfile(\"zlib\", \"1.0\").with_settings(\"os\"),\n            \"cmake/conanfile.py\": GenConanfile(\"cmake\", \"1.0\").with_settings(\"os\"),\n            \"m4/conanfile.py\": GenConanfile(\"m4\", \"1.0\").with_settings(\"os\"),\n            \"protobuf/conanfile.py\": GenConanfile(\"protobuf\", \"1.0\").with_settings(\"os\"),\n            \"app/conanfile.py\": GenConanfile(\"app\", \"1.0\").with_settings(\"os\")\n            .with_requires(\"zlib/1.0\", \"protobuf/1.0\")\n            .with_tool_requires(\"cmake/1.0\", \"m4/1.0\", \"protobuf/1.0\")})\n        c.run(\"create zlib\")\n        c.run(\"create protobuf\")\n        c.run(\"create cmake\")\n        c.run(\"create m4\")\n        c.run(\"create app --format=json\", redirect_stdout=\"graph.json\")\n        # Now, let's filter the pkgs\n        c.run(f\"list --graph=graph.json --graph-context={context} --format=json\",\n              redirect_stdout=\"pkglist.json\")\n        content = json.loads(c.load(\"pkglist.json\"))\n        for ref in refs:\n            assert content[\"Local Cache\"][ref][\"revisions\"]\n        for ref in not_refs:\n            assert content[\"Local Cache\"].get(ref) is None\n        # Let's upload all the packages\n        c.run(f\"list --graph=graph.json --format=json\", redirect_stdout=\"pkglist.json\")\n        c.run(\"upload --list=pkglist.json -r=default\")\n        c.run(\"remove * -c\")\n        c.run(\"create app --format=json\", redirect_stdout=\"graph.json\")\n        # Now, let's filter the pkgs\n        c.run(f\"list --graph=graph.json --graph-context={context} -r=default --format=json\",\n              redirect_stdout=\"pkglist.json\")\n        content = json.loads(c.load(\"pkglist.json\"))\n        for ref in refs:\n            assert content[\"default\"][ref][\"revisions\"]\n        for ref in not_refs:\n            assert content[\"default\"].get(ref) is None\n\n    def test_graph_list(self):\n        tc = TestClient(light=True)\n        tc.save({\"conanfile.py\": GenConanfile(\"lib\", \"1.0\")})\n\n        tc.run(\"graph info . -f json --build=never --no-remote --filter=context\",\n               redirect_stdout=\"graph_context.json\")\n\n        tc.run(\"list --graph=graph_context.json --graph-context=build-only --format=json\",\n               assert_error=True)\n        assert \"Note that the graph file should not be filtered\" in tc.out\n\n    @pytest.mark.parametrize(\"context\", [\"build-only\", \"host-only\"])\n    def test_context_only_binary_mismatch(self, context):\n        tc = TestClient(light=True)\n        tc.save({\n                \"protobuf/conanfile.py\": GenConanfile(\"protobuf\", \"1.0\"),\n                \"onnx/conanfile.py\": GenConanfile(\"onnx\", \"1.0\")\n                    .with_requires(\"protobuf/1.0\")\n                    .with_tool_requires(\"protobuf/1.0\")})\n\n        tc.run(\"create protobuf\")\n        tc.run(\"create onnx\")\n        # Note that here, the protobuf from tool_requires is skipped!\n        tc.run(\"graph info --requires=onnx/1.0 -f=json\", redirect_stdout=\"graph.json\")\n        tc.run(f\"list --graph=graph.json --graph-context={context} --format=json\")\n        # We removed both protobuf binaries, not even the recipe is still there\n        assert \"protobuf/1.0\" not in tc.out\n\n    @pytest.mark.parametrize(\"context\", [\"build-only\", \"host-only\"])\n    # We're building onnx to ensure the build context protobuf binary is not skipped\n    @pytest.mark.parametrize(\"build_onnx\", [True, False])\n    def test_context_only_binary_different_pkg_id(self, context, build_onnx):\n        tc = TestClient(light=True)\n        tc.save({\n            \"protobuf/conanfile.py\": GenConanfile(\"protobuf\", \"1.0\")\n            .with_shared_option(),\n            \"onnx/conanfile.py\": GenConanfile(\"onnx\", \"1.0\")\n            .with_requirement(\"protobuf/1.0\", options={\"shared\": True})\n            .with_tool_requires(\"protobuf/1.0\")})\n\n        tc.run(\"create protobuf -o &:shared=True\")\n        protobuf_host_shared_pkgid = tc.created_layout().reference.package_id\n        tc.run(\"create protobuf -o &:shared=False\")\n        protobuf_build_static_pkgid = tc.created_layout().reference.package_id\n\n        tc.run(\"create onnx\")\n        build_arg = \"-b=&\" if build_onnx else \"\"\n        tc.run(f\"graph info --requires=onnx/1.0 {build_arg} -f=json\", redirect_stdout=\"graph.json\")\n        tc.run(f\"list --graph=graph.json --graph-context={context} --format=json\")\n        if context == \"build-only\":\n            if not build_onnx:\n                # If we have skipped the protobuf build binary, the recipe is gone too\n                # because we have no protobuf packages being used\n                assert \"protobuf/1.0\" not in tc.out\n            else:\n                assert \"protobuf/1.0\" in tc.out\n                assert protobuf_build_static_pkgid in tc.out\n                assert protobuf_host_shared_pkgid not in tc.out\n        else:\n            assert \"protobuf/1.0\" in tc.out\n            assert protobuf_build_static_pkgid not in tc.out\n            assert protobuf_host_shared_pkgid in tc.out\n\n    @pytest.mark.parametrize(\"context\", [\"build-only\", \"host-only\"])\n    def test_context_only_consumer_recipe_no_named(self, context):\n        tc = TestClient()\n        tc.save({\n            \"protobuf/conanfile.py\": GenConanfile(\"protobuf\", \"1.0\"),\n            \"consumer/conanfile.py\": GenConanfile()\n                .with_tool_requires(\"protobuf/1.0\")\n                .with_requires(\"protobuf/1.0\")})\n\n        tc.run(\"create protobuf\")\n        tc.run(f\"graph info consumer -f=json\", redirect_stdout=\"graph.json\")\n        tc.run(f\"list --graph=graph.json --graph-context={context}\")\n        assert \"protobuf/1.0\" not in tc.out\n"
  },
  {
    "path": "test/integration/command/list/test_list_lru.py",
    "content": "import json\nimport time\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestLRU:\n    def test_error_lru_remote(self):\n        c = TestClient(default_server_user=True)\n        c.run(\"list * --lru=1s -r=default\", assert_error=True)\n        assert \"'--lru' cannot be used in remotes, only in cache\" in c.out\n\n    @pytest.mark.parametrize(\"method\", [\"list\", \"remove\"])\n    def test_cache_clean_lru(self, method):\n        c = TestClient()\n        c.save({\"conanfile.py\": GenConanfile()})\n        c.run(\"create . --name=pkg --version=0.1\")\n        c.run(\"create . --name=dep --version=0.2\")\n\n        time.sleep(2)\n        # This should update the LRU\n        c.run(\"install --requires=pkg/0.1\")\n        # Removing recipes (+ its binaries) that recipes haven't been used\n        if method == \"list\":\n            c.run(\"list *#* --lru=1s --format=json\", redirect_stdout=\"old.json\")\n            c.run(\"remove --list=old.json -c\")\n        else:\n            c.run(\"remove * --lru=1s -c\")\n        # Do the checks\n        c.run(\"list *:*#*\")\n        assert \"pkg\" in c.out\n        assert \"da39a3ee5e6b4b0d3255bfef95601890afd80709\" in c.out\n        assert \"dep\" not in c.out\n\n        time.sleep(2)\n        # This should update the LRU of the recipe only\n        c.run(\"graph info --requires=pkg/0.1\")\n        # IMPORTANT: Note the pattern is NOT the same as the equivalent for 'conan remove'\n        if method == \"list\":\n            c.run(\"list *#*:*#* --lru=1s --format=json\", redirect_stdout=\"old.json\")\n            c.run(\"remove --list=old.json -c\")\n        else:\n            c.run(\"remove *:* --lru=1s -c\")\n\n        # Check the binary has been removed, but the recipe is still there\n        c.run(\"list *:*\")\n\n        assert \"pkg\" in c.out\n        assert \"da39a3ee5e6b4b0d3255bfef95601890afd80709\" not in c.out\n        assert \"dep\" not in c.out\n\n    def test_lru_just_created(self):\n        c = TestClient()\n        c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n        c.run(\"create .\")\n        c.run(\"list * --lru=1d\", assert_error=True)\n        assert \"'--lru' must be used with recipe revision pattern\" in c.out\n        c.run(\"list *#* --lru=1d\")\n        assert \"pkg/0.1\" not in c.out\n        # What if no revision, but package id is passed\n        c.run(\"list pkg/0.1:* --lru=1d\", assert_error=True)\n        assert \"'--lru' must be used with package revision pattern\" in c.out\n        # Doesn't fail, but packages is empty\n        c.run(\"list pkg/0.1:*#* --lru=1d --format=json\")\n        pkgs = json.loads(c.stdout)\n        rev = pkgs[\"Local Cache\"][\"pkg/0.1\"][\"revisions\"][\"485dad6cb11e2fa99d9afbe44a57a164\"]\n        assert rev[\"packages\"] == {}\n\n    def test_update_lru_when_used_as_dependency(self):\n        \"\"\"Show that using a recipe as a dependency will update its LRU\"\"\"\n        c = TestClient()\n        c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"1.0\"),\n                \"conanfile.py\": GenConanfile(\"app\", \"1.0\").with_require(\"dep/1.0\")})\n\n        c.run(\"create dep\")\n        time.sleep(2)\n        c.run(\"create .\")\n        # Dep is not removed because its lru was updated as part of the above create\n        c.run(\"remove * --lru=1s -c -f=json\", redirect_stdout=\"removed.json\")\n        removed = json.loads(c.load(\"removed.json\"))\n        assert len(removed[\"Local Cache\"]) == 0\n\n    def test_lru_invalid_time_unit(self):\n        c = TestClient(light=True)\n        c.run(f\"list *#* --lru=1x\")\n        assert \"ERROR: Unrecognized time unit: 'x'\" in c.out\n\n    def test_lru_invalid_time_value_edge_cases(self):\n        c = TestClient(light=True)\n        c.run(\"list *#* --lru=as\")\n        assert \"ERROR: invalid literal for int() with base 10: 'a'\" in c.out\n        c.run(\"list *#* --lru=s\")\n        assert \"ERROR: invalid literal for int() with base 10: ''\" in c.out\n\n    def test_lru_not_in_remotes(self):\n        c = TestClient(light=True, default_server_user=True)\n        c.run(\"list *#* --lru=1s -r=default\", assert_error=True)\n        assert \"'--lru' cannot be used in remotes, only in cache\" in c.out\n"
  },
  {
    "path": "test/integration/command/remote/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/command/remote/remote_test.py",
    "content": "import json\nimport os\nimport pytest\nfrom collections import OrderedDict\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient, TestServer\nfrom conan.internal.util.files import load\n\n\nclass TestRemoteServer:\n\n    @pytest.fixture(autouse=True)\n    def setup(self):\n        self.servers = OrderedDict()\n        for i in range(3):\n            test_server = TestServer()\n            self.servers[\"remote%d\" % i] = test_server\n\n        self.client = TestClient(servers=self.servers, inputs=3 * [\"admin\", \"password\"], light=True)\n\n    def test_list_json(self):\n        self.client.run(\"remote list --format=json\")\n        data = json.loads(self.client.stdout)\n\n        assert data[0][\"name\"] == \"remote0\"\n        assert data[1][\"name\"] == \"remote1\"\n        assert data[2][\"name\"] == \"remote2\"\n        # TODO: Check better\n\n    def test_basic(self):\n        self.client.run(\"remote list\")\n        assert \"remote0: http://\" in self.client.out\n        assert \"remote1: http://\" in self.client.out\n        assert \"remote2: http://\" in self.client.out\n\n        self.client.run(\"remote add origin https://myurl\")\n        self.client.run(\"remote list\")\n        lines = str(self.client.out).splitlines()\n        assert \"origin: https://myurl\" in lines[3]\n\n        self.client.run(\"remote update origin --url https://2myurl\")\n        self.client.run(\"remote list\")\n        assert \"origin: https://2myurl\" in self.client.out\n\n        self.client.run(\"remote update remote0 --url https://remote0url\")\n        self.client.run(\"remote list\")\n        output = str(self.client.out)\n        assert \"remote0: https://remote0url\" in output.splitlines()[0]\n\n        self.client.run(\"remote remove remote0\")\n        self.client.run(\"remote list\")\n        output = str(self.client.out)\n        assert \"remote1: http://\" in output.splitlines()[0]\n\n    def test_remove_remote(self):\n        self.client.run(\"remote list\")\n        assert \"remote0: http://\" in self.client.out\n        assert \"remote1: http://\" in self.client.out\n        assert \"remote2: http://\" in self.client.out\n        self.client.run(\"remote remove remote1\")\n        self.client.run(\"remote list\")\n        assert \"remote1\" not in self.client.out\n        assert \"remote0\" in self.client.out\n        assert \"remote2\" in self.client.out\n        self.client.run(\"remote remove remote2\")\n        self.client.run(\"remote list\")\n        assert \"remote1\" not in self.client.out\n        assert \"remote0\" in self.client.out\n        assert \"remote2\" not in self.client.out\n\n    def test_remove_remote_all(self):\n        self.client.run(\"remote list\")\n        assert \"remote0: http://\" in self.client.out\n        assert \"remote1: http://\" in self.client.out\n        assert \"remote2: http://\" in self.client.out\n        self.client.run(\"remote remove *\")\n        self.client.run(\"remote list\")\n        assert \"remote1\" not in self.client.out\n        assert \"remote0\" not in self.client.out\n        assert \"remote2\" not in self.client.out\n\n    def test_remove_remote_no_user(self):\n        self.client.save({\"conanfile.py\": GenConanfile()})\n        self.client.run(\"remote remove remote0\")\n        self.client.run(\"remote list\")\n        assert \"remote0\" not in self.client.out\n\n    def test_insert(self):\n        self.client.run(\"remote add origin https://myurl --index\", assert_error=True)\n\n        self.client.run(\"remote add origin https://myurl --index=0\")\n        self.client.run(\"remote add origin2 https://myurl2 --index=0\")\n        self.client.run(\"remote list\")\n        lines = str(self.client.out).splitlines()\n        assert \"origin2: https://myurl2\" in lines[0]\n        assert \"origin: https://myurl\" in lines[1]\n\n        self.client.run(\"remote add origin3 https://myurl3 --index=1\")\n        self.client.run(\"remote list\")\n        lines = str(self.client.out).splitlines()\n        assert \"origin2: https://myurl2\" in lines[0]\n        assert \"origin3: https://myurl3\" in lines[1]\n        assert \"origin: https://myurl\" in lines[2]\n\n    def test_duplicated_error(self):\n        \"\"\" check remote name are not duplicated\n        \"\"\"\n        self.client.run(\"remote add remote1 http://otherurl\", assert_error=True)\n        assert (\"ERROR: Remote 'remote1' already exists in remotes (use --force to continue)\"\n                in self.client.out)\n\n        self.client.run(\"remote list\")\n        assert \"otherurl\" not in self.client.out\n        self.client.run(\"remote add remote1 http://otherurl --force\")\n        assert \"WARN: Remote 'remote1' already exists in remotes\" in self.client.out\n\n        self.client.run(\"remote list\")\n        assert \"remote1: http://otherurl\" in self.client.out\n\n    def test_missing_subarguments(self):\n        self.client.run(\"remote\", assert_error=True)\n        assert \"ERROR: Exiting with code: 2\" in self.client.out\n\n    def test_invalid_url(self):\n        self.client.run(\"remote add foobar foobar.com\")\n        assert (\"WARN: The URL 'foobar.com' is invalid. It must contain scheme and hostname.\"\n                in self.client.out)\n        self.client.run(\"remote list\")\n        assert \"foobar.com\" in self.client.out\n\n        self.client.run(\"remote update foobar --url pepe.org\")\n        assert (\"WARN: The URL 'pepe.org' is invalid. It must contain scheme and hostname.\"\n                in self.client.out)\n        self.client.run(\"remote list\")\n        assert \"pepe.org\" in self.client.out\n\n    def test_errors(self):\n        self.client.run(\"remote update origin --url https://foo.com\", assert_error=True)\n        assert \"ERROR: Remote 'origin' doesn't exist\" in self.client.out\n\n        self.client.run(\"remote remove origin\", assert_error=True)\n        assert \"ERROR: Remote 'origin' can't be found or is disabled\" in self.client.out\n\n\nclass TestRemoteModification:\n    def test_rename(self):\n        client = TestClient(light=True)\n        client.save({\"conanfile.py\": GenConanfile()})\n        client.run(\"export . --name=hello --version=0.1 --user=user --channel=testing\")\n        client.run(\"remote add r1 https://r1\")\n        client.run(\"remote add r2 https://r2\")\n        client.run(\"remote add r3 https://r3\")\n        client.run(\"remote rename r2 mynewr2\")\n        client.run(\"remote list\")\n        lines = str(client.out).splitlines()\n        assert \"r1: https://r1\" in lines[0]\n        assert \"mynewr2: https://r2\" in lines[1]\n        assert \"r3: https://r3\" in lines[2]\n\n        # Rename to an existing one\n        client.run(\"remote rename mynewr2 r1\", assert_error=True)\n        assert \"Remote 'r1' already exists\" in client.out\n\n    def test_update_insert(self):\n        client = TestClient(light=True)\n        client.run(\"remote add r1 https://r1\")\n        client.run(\"remote add r2 https://r2\")\n        client.run(\"remote add r3 https://r3\")\n\n        client.run(\"remote update r2 --url https://r2new --index=0\")\n        client.run(\"remote list\")\n        lines = str(client.out).splitlines()\n        assert \"r2: https://r2new\" in lines[0]\n        assert \"r1: https://r1\" in lines[1]\n        assert \"r3: https://r3\" in lines[2]\n\n        client.run(\"remote update r2 --url https://r2new2\")\n        client.run(\"remote update r2 --index=2\")\n        client.run(\"remote list\")\n        lines = str(client.out).splitlines()\n        assert \"r1: https://r1\" in lines[0]\n        assert \"r3: https://r3\" in lines[1]\n        assert \"r2: https://r2new2\" in lines[2]\n\n    def test_update_insert_same_url(self):\n        # https://github.com/conan-io/conan/issues/5107\n        client = TestClient(light=True)\n        client.run(\"remote add r1 https://r1\")\n        client.run(\"remote add r2 https://r2\")\n        client.run(\"remote add r3 https://r3\")\n        client.run(\"remote update r2 --url https://r2\")\n        client.run(\"remote update r2 --index 0\")\n        client.run(\"remote list\")\n        assert str(client.out).find(\"r2\") < str(client.out).find(\"r1\")\n        assert str(client.out).find(\"r1\") < str(client.out).find(\"r3\")\n\n    def test_verify_ssl(self):\n        client = TestClient(light=True)\n        client.run(\"remote add my-remote http://someurl\")\n        client.run(\"remote add my-remote2 http://someurl2 --insecure\")\n        client.run(\"remote add my-remote3 http://someurl3\")\n\n        registry = load(client.paths.remotes_path)\n        data = json.loads(registry)\n        assert data[\"remotes\"][0][\"name\"] == \"my-remote\"\n        assert data[\"remotes\"][0][\"url\"] == \"http://someurl\"\n        assert data[\"remotes\"][0][\"verify_ssl\"] is True\n\n        assert data[\"remotes\"][1][\"name\"] == \"my-remote2\"\n        assert data[\"remotes\"][1][\"url\"] == \"http://someurl2\"\n        assert data[\"remotes\"][1][\"verify_ssl\"] is False\n\n        assert data[\"remotes\"][2][\"name\"] == \"my-remote3\"\n        assert data[\"remotes\"][2][\"url\"] == \"http://someurl3\"\n        assert data[\"remotes\"][2][\"verify_ssl\"] is True\n\n    def test_remote_disable(self):\n        client = TestClient(light=True)\n        client.run(\"remote add my-remote0 http://someurl0\")\n        client.run(\"remote add my-remote1 http://someurl1\")\n        client.run(\"remote add my-remote2 http://someurl2\")\n        client.run(\"remote add my-remote3 http://someurl3\")\n        client.run(\"remote disable my-remote0\")\n        assert \"my-remote0\" in client.out\n        assert \"Enabled: False\" in client.out\n        client.run(\"remote disable my-remote3\")\n        assert \"my-remote3\" in client.out\n        assert \"Enabled: False\" in client.out\n        registry = load(client.paths.remotes_path)\n        data = json.loads(registry)\n        assert data[\"remotes\"][0][\"name\"] == \"my-remote0\"\n        assert data[\"remotes\"][0][\"url\"] == \"http://someurl0\"\n        assert data[\"remotes\"][0][\"disabled\"] is True\n        assert data[\"remotes\"][3][\"name\"] == \"my-remote3\"\n        assert data[\"remotes\"][3][\"url\"] == \"http://someurl3\"\n        assert data[\"remotes\"][3][\"disabled\"] is True\n\n        # check that they are still listed, as disabled\n        client.run(\"remote list\")\n        assert \"my-remote0: http://someurl0 [Verify SSL: True, Enabled: False]\" in client.out\n        assert \"my-remote3: http://someurl3 [Verify SSL: True, Enabled: False]\" in client.out\n\n        client.run(\"remote disable * --format=json\")\n\n        registry = load(client.paths.remotes_path)\n        data = json.loads(registry)\n        for remote in data[\"remotes\"]:\n            assert remote[\"disabled\"] is True\n\n        data = json.loads(client.stdout)\n        for remote in data:\n            assert remote[\"enabled\"] is False\n\n        client.run(\"remote enable *\")\n        registry = load(client.paths.remotes_path)\n        data = json.loads(registry)\n        for remote in data[\"remotes\"]:\n            assert \"disabled\" not in remote\n        assert \"my-remote0\" in client.out\n        assert \"my-remote1\" in client.out\n        assert \"my-remote2\" in client.out\n        assert \"my-remote3\" in client.out\n        assert \"Enabled: False\" not in client.out\n\n    def test_invalid_remote_disable(self):\n        client = TestClient(light=True)\n\n        client.run(\"remote disable invalid_remote\", assert_error=True)\n        msg = \"ERROR: Remote 'invalid_remote' can't be found or is disabled\"\n        assert msg in client.out\n\n        client.run(\"remote enable invalid_remote\", assert_error=True)\n        assert msg in client.out\n\n        client.run(\"remote disable invalid_wildcard_*\")\n\n    def test_remote_disable_already_set(self):\n        \"\"\"\n        Check that we don't raise an error if the remote is already in the required state\n        \"\"\"\n        client = TestClient(light=True)\n\n        client.run(\"remote add my-remote0 http://someurl0\")\n        client.run(\"remote enable my-remote0\")\n        client.run(\"remote enable my-remote0\")\n\n        client.run(\"remote disable my-remote0\")\n        client.run(\"remote disable my-remote0\")\n\n    def test_verify_ssl_error(self):\n        client = TestClient(light=True)\n        client.run(\"remote add my-remote http://someurl some_invalid_option=foo\", assert_error=True)\n\n        assert \"unrecognized arguments: some_invalid_option=foo\" in client.out\n        data = json.loads(load(client.paths.remotes_path))\n        assert data[\"remotes\"] == []\n\n\ndef test_add_duplicated_url():\n    \"\"\" allow duplicated URL with --force\n    \"\"\"\n    c = TestClient(light=True)\n    c.run(\"remote add remote1 http://url\")\n    c.run(\"remote add remote2 http://url\", assert_error=True)\n    assert \"ERROR: Remote url already existing in remote 'remote1'\" in c.out\n    c.run(\"remote list\")\n    assert \"remote1\" in c.out\n    assert \"remote2\" not in c.out\n    c.run(\"remote add remote2 http://url --force\")\n    assert \"WARN: Remote url already existing in remote 'remote1'.\" in c.out\n    c.run(\"remote list\")\n    assert \"remote1\" in c.out\n    assert \"remote2\" in c.out\n    # make sure we can remove both\n    # https://github.com/conan-io/conan/issues/13569\n    c.run(\"remote remove *\")\n    c.run(\"remote list\")\n    assert \"remote1\" not in c.out\n    assert \"remote2\" not in c.out\n\n\ndef test_add_duplicated_name_url():\n    \"\"\" do not add extra remote with same name and same url\n        # https://github.com/conan-io/conan/issues/13569\n    \"\"\"\n    c = TestClient(light=True)\n    c.run(\"remote add remote1 http://url\")\n    c.run(\"remote add remote1 http://url --force\")\n    assert \"WARN: Remote 'remote1' already exists in remotes\" in c.out\n    c.run(\"remote list\")\n    assert 1 == str(c.out).count(\"remote1\")\n\n\ndef test_add_wrong_conancenter():\n    \"\"\" Avoid common error of adding the wrong ConanCenter URL\n    \"\"\"\n    c = TestClient(light=True)\n    c.run(\"remote add whatever https://conan.io/center\", assert_error=True)\n    assert \"Wrong ConanCenter remote URL. You are adding the web https://conan.io/center\" in c.out\n    assert \"the correct remote API is https://center2.conan.io\" in c.out\n    c.run(\"remote add conancenter https://center2.conan.io\")\n    c.run(\"remote update conancenter --url=https://conan.io/center\", assert_error=True)\n    assert \"Wrong ConanCenter remote URL. You are adding the web https://conan.io/center\" in c.out\n    assert \"the correct remote API is https://center2.conan.io\" in c.out\n\n\ndef test_using_frozen_center():\n    \"\"\" If the legacy center.conan.io is in the remote list warn about it.\n    \"\"\"\n    c = TestClient(light=True)\n    c.run(\"remote add whatever https://center.conan.io\")\n    assert (\"The remote 'https://center.conan.io' is now frozen and has been \"\n            \"replaced by 'https://center2.conan.io'.\") in c.out\n    assert 'conan remote update whatever --url=\"https://center2.conan.io\"' in c.out\n\n    c.run(\"remote list\")\n    assert (\"The remote 'https://center.conan.io' is now frozen and has been \"\n            \"replaced by 'https://center2.conan.io'.\") in c.out\n\n    c.run(\"remote remove whatever\")\n\n    c.run(\"remote add conancenter https://center2.conan.io\")\n    assert (\"The remote 'https://center.conan.io' is now frozen and has been \"\n            \"replaced by 'https://center2.conan.io'.\") not in c.out\n\n    c.run(\"remote list\")\n    assert (\"The remote 'https://center.conan.io' is now frozen and has been \"\n            \"replaced by 'https://center2.conan.io'.\") not in c.out\n\n    c.run(\"remote update conancenter --url=https://center.conan.io\")\n    assert (\"The remote 'https://center.conan.io' is now frozen and has been \"\n            \"replaced by 'https://center2.conan.io'.\") in c.out\n\n    c.run(\"remote disable conancenter\")\n    assert (\"The remote 'https://center.conan.io' is now frozen and has been \"\n            \"replaced by 'https://center2.conan.io'.\") not in c.out\n\n\ndef test_wrong_remotes_json_file():\n    c = TestClient(light=True)\n    c.save_home({\"remotes.json\": \"\"})\n    c.run(\"remote list\", assert_error=True)\n    assert \"ERROR: Error loading JSON remotes file\" in c.out\n\n\ndef test_allowed_packages_remotes():\n    tc = TestClient(light=True, default_server_user=True)\n    tc.save({\"conanfile.py\": GenConanfile(),\n             \"app/conanfile.py\": GenConanfile(\"app\", \"1.0\")\n            .with_requires(\"liba/1.0\")\n            .with_requires(\"libb/[>=1.0]\")})\n    tc.run(\"create . --name=liba --version=1.0\")\n    tc.run(\"create . --name=libb --version=1.0\")\n    tc.run(\"create app\")\n    tc.run(\"upload * -r=default -c\")\n    tc.run(\"remove * -c\")\n\n    tc.run(\"install --requires=app/1.0 -r=default\")\n    assert \"app/1.0: Downloaded recipe revision 04ab3bc4b945a2ee44285962c277906d\" in tc.out\n    assert \"liba/1.0: Downloaded recipe revision 4d670581ccb765839f2239cc8dff8fbd\" in tc.out\n    tc.run(\"remove * -c\")\n\n    # lib/2.* pattern does not match the one being required by app, should not be found\n    tc.run('remote update default --allowed-packages=\"app/*\" --allowed-packages=\"liba/2.*\"')\n\n    tc.run(\"install --requires=app/1.0 -r=default\", assert_error=True)\n    assert \"app/1.0: Downloaded recipe revision 04ab3bc4b945a2ee44285962c277906d\" in tc.out\n    assert \"liba/1.0: Downloaded recipe revision 4d670581ccb765839f2239cc8dff8fbd\" not in tc.out\n    assert \"ERROR: Package 'liba/1.0' not resolved: Unable to find 'liba/1.0' in remotes\" in tc.out\n    assert \"Required by 'app/1.0'\" in tc.out\n    tc.run(\"remove * -c\")\n\n    tc.run('remote update default --allowed-packages=\"liba/*\" --allowed-packages=\"app/*\"')\n    tc.run(\"remote list -f=json\")\n    assert \"app/*\" in tc.out\n\n    tc.run(\"install --requires=app/1.0 -r=default\", assert_error=True)\n    assert \"app/1.0: Downloaded recipe revision 04ab3bc4b945a2ee44285962c277906d\" in tc.out\n    assert \"liba/1.0: Downloaded recipe revision 4d670581ccb765839f2239cc8dff8fbd\" in tc.out\n    assert \"ERROR: Package 'libb/[>=1.0]' not resolved\" in tc.out\n    tc.run(\"remove * -c\")\n\n    tc.run('remote update default --allowed-packages=\"liba/*\" --allowed-packages=\"app/*\"')\n    tc.run(\"install --requires=app/1.0 -r=default\", assert_error=True)\n    assert \"app/1.0: Downloaded recipe revision 04ab3bc4b945a2ee44285962c277906d\" in tc.out\n    assert \"liba/1.0: Downloaded recipe revision 4d670581ccb765839f2239cc8dff8fbd\" in tc.out\n    assert \"ERROR: Package 'libb/[>=1.0]' not resolved\" in tc.out\n    tc.run(\"remove * -c\")\n\n    tc.run('remote update default --allowed-packages=\"*\"')\n    tc.run(\"install --requires=app/1.0 -r=default\")\n    assert \"app/1.0: Downloaded recipe revision 04ab3bc4b945a2ee44285962c277906d\" in tc.out\n    assert \"liba/1.0: Downloaded recipe revision 4d670581ccb765839f2239cc8dff8fbd\" in tc.out\n    assert \"libb/1.0: Downloaded recipe revision 4d670581ccb765839f2239cc8dff8fbd\" in tc.out\n\n\ndef test_remote_allowed_packages_new():\n    \"\"\"Test that the allowed packages are saved in the remotes.json file when adding a new remote\"\"\"\n    tc = TestClient(light=True)\n    tc.run(\"remote add foo https://foo -ap='liba/*'\")\n    remotes = json.loads(load(os.path.join(tc.cache_folder, \"remotes.json\")))\n    assert remotes[\"remotes\"][0][\"allowed_packages\"] == [\"liba/*\"]\n\n\ndef test_remote_allowed_negation():\n    tc = TestClient(light=True, default_server_user=True)\n    tc.save({\"conanfile.py\": GenConanfile()})\n    tc.run(\"create . --name=config --version=1.0\")\n    tc.run(\"create . --name=lib --version=1.0\")\n    tc.run(\"upload * -c -r=default\")\n    tc.run(\"remove * -c\")\n\n    tc.run('remote update default --allowed-packages=\"!config/*\"')\n    tc.run(\"install --requires=lib/1.0 -r=default\")\n    assert \"lib/1.0: Downloaded recipe revision\" in tc.out\n\n    tc.run(\"install --requires=config/1.0 -r=default\", assert_error=True)\n    assert (\"ERROR: Package 'config/1.0' not resolved: Unable to find \"\n            \"'config/1.0' in remotes\") in tc.out\n"
  },
  {
    "path": "test/integration/command/remote/remote_verify_ssl_test.py",
    "content": "import requests\nfrom requests.models import Response\n\nfrom conan.test.utils.tools import TestClient\n\nresp = Response()\nresp._content = b'{\"results\": []}'\nresp.status_code = 200\nresp.headers = {\"Content-Type\": \"application/json\", \"X-Conan-Server-Capabilities\": \"revisions\"}\n\n\nclass RequesterMockFalse:\n    expected = False\n\n    def __init__(self, *args, **kwargs):\n        pass\n\n    def get(self, url, *args, **kwargs):  # noqa\n        assert kwargs[\"verify\"] is self.expected\n        return resp\n\n    def Session(self):  # noqa\n        return self\n\n    @property\n    def codes(self):\n        return requests.codes\n\n    def mount(self, *args, **kwargs):\n        pass\n\n\nclass RequesterMockTrue(RequesterMockFalse):\n    expected = True\n\n\nclass TestVerifySSL:\n\n    def test_verify_ssl(self):\n        c = TestClient(requester_class=RequesterMockTrue)\n        c.run(\"remote add myremote https://localhost --insecure\")\n        c.run(\"remote list\")\n        assert \"Verify SSL: False\" in c.out\n\n        c.run(\"remote update myremote --url https://localhost --secure\")\n        c.run(\"remote list\")\n        assert \"Verify SSL: True\" in c.out\n\n        c.run(\"remote remove myremote\")\n        c.run(\"remote add myremote https://localhost\")\n        c.run(\"remote list\")\n        assert \"Verify SSL: True\" in c.out\n\n        # Verify that SSL is checked in requests\n        c.run(\"search op* -r myremote\")\n        assert \"WARN: There are no matching recipe references\" in c.out\n\n        # Verify that SSL is not checked in requests\n        c = TestClient(requester_class=RequesterMockFalse)\n        c.run(\"remote add myremote https://localhost --insecure\")\n        c.run(\"search op* -r myremote\")\n        assert \"WARN: There are no matching recipe references\" in c.out\n"
  },
  {
    "path": "test/integration/command/remote/test_remote_users.py",
    "content": "import json\nimport textwrap\nimport time\nfrom collections import OrderedDict\nfrom datetime import timedelta\n\nfrom unittest.mock import patch\n\nfrom conan.internal.api.remotes.localdb import LocalDB\nfrom conan.test.utils.tools import TestClient, TestServer\nfrom conan.test.utils.env import environment_update\n\n\nclass TestUser:\n\n    def test_command_user_no_remotes(self):\n        \"\"\" Test that proper error is reported when no remotes are defined and conan user is executed\n        \"\"\"\n        client = TestClient()\n        client.run(\"remote list-users\", assert_error=True)\n        assert \"ERROR: No remotes defined\" in client.out\n\n        client.run(\"remote login wrong_remote foo -p bar\", assert_error=True)\n        assert \"ERROR: Remote 'wrong_remote' can't be found or is disabled\" in client.out\n\n    def test_command_user_list(self):\n        \"\"\" Test list of user is reported for all remotes or queried remote\n        \"\"\"\n        servers = OrderedDict()\n        servers[\"default\"] = TestServer()\n        servers[\"test_remote_1\"] = TestServer()\n        client = TestClient(servers=servers)\n\n        # Test with wrong remote right error is reported\n        client.run(\"remote login Test_Wrong_Remote foo\", assert_error=True)\n        assert \"ERROR: Remote 'Test_Wrong_Remote' can't be found or is disabled\" in client.out\n\n        # Test user list for all remotes is reported\n        client.run(\"remote list-users\")\n        assert textwrap.dedent(\"\"\"\n        default:\n          No user\n        test_remote_1:\n          No user\"\"\") not in client.out\n\n    def test_with_remote_no_connect(self):\n        test_server = TestServer()\n        client = TestClient(servers={\"default\": test_server})\n        client.run('remote list-users')\n        assert textwrap.dedent(\"\"\"\n                default:\n                  No user\"\"\") not in client.out\n\n        client.run('remote set-user default john')\n        assert \"Changed user of remote 'default' from 'None' (anonymous) to 'john'\" in client.out\n        localdb = LocalDB(client.cache_folder)\n        assert ('john', None, None) == localdb.get_login(test_server.fake_url)\n\n        client.run('remote set-user default will')\n        assert \"Changed user of remote 'default' from 'john' (anonymous) to 'will'\" in client.out\n        assert ('will', None, None) == localdb.get_login(test_server.fake_url)\n\n        client.run('remote logout default')\n        assert \"Changed user of remote 'default' from 'will' (anonymous) to 'None' (anonymous)\" in client.out\n        assert (None, None, None) == localdb.get_login(test_server.fake_url)\n\n    def test_command_user_with_password(self):\n        \"\"\" Checks the -p option, that obtains a token from the password.\n        Useful for integrations as travis, that interactive password is not\n        possible\n        \"\"\"\n        test_server = TestServer()\n        servers = {\"default\": test_server}\n        client = TestClient(servers=servers, inputs=[\"admin\", \"password\"])\n        client.run('remote login default dummy -p ping_pong2', assert_error=True)\n        assert \"ERROR: Wrong user or password\" in client.out\n        client.run('remote login default admin -p password')\n        assert \"ERROR: Wrong user or password\" not in client.out\n        assert \"Changed user of remote 'default' from 'None' (anonymous) to 'admin'\" in client.out\n        client.run('remote logout default')\n        assert \"Changed user of remote 'default' from 'admin' (authenticated) to 'None' (anonymous)\" in client.out\n        localdb = LocalDB(client.cache_folder)\n        assert (None, None, None) == localdb.get_login(test_server.fake_url)\n        client.run('remote list-users')\n        assert 'default:\\n  No user' in client.out\n\n    def test_command_user_with_password_spaces(self):\n        \"\"\" Checks the -p option, that obtains a token from the password.\n        Useful for integrations as travis, that interactive password is not\n        possible\n        \"\"\"\n        test_server = TestServer(users={\"lasote\": 'my \"password'})\n        servers = {\"default\": test_server}\n        client = TestClient(servers=servers, inputs=[\"lasote\", \"mypass\"])\n        client.run(r'remote login default lasote -p=\"my \\\"password\"')\n        assert \"Connecting to remote\" not in client.out\n        assert \"Changed user of remote 'default' from 'None' (anonymous) to 'lasote'\" in client.out\n        client.run('remote logout default')\n        client.run(r'remote login default lasote -p \"my \\\"password\"')\n        assert \"ERROR: Wrong user or password\" not in client.out\n        assert \"Changed user of remote 'default' from 'None' (anonymous) to 'lasote'\" in client.out\n\n    def test_clean(self):\n        test_server = TestServer()\n        servers = {\"default\": test_server}\n        client = TestClient(servers=servers, inputs=2*[\"admin\", \"password\"])\n        base = '''\nfrom conan import ConanFile\n\nclass ConanLib(ConanFile):\n    name = \"lib\"\n    version = \"0.1\"\n'''\n        files = {\"conanfile.py\": base}\n        client.save(files)\n        client.run(\"export . --user=lasote --channel=stable\")\n        client.run(\"upload lib/0.1@lasote/stable -r default --only-recipe\")\n        client.run(\"remote list-users\")\n        assert 'default:\\n  Username: admin\\n  authenticated: True' in client.out\n        client.run(\"remote logout default\")\n        assert \"Changed user of remote 'default' from 'admin' (authenticated) to 'None' (anonymous)\" in client.out\n        client.run(\"remote list-users\")\n        assert 'default:\\n  No user' in client.out\n        # --force will force re-authentication, otherwise not necessary to auth\n        client.run(\"upload lib/0.1@lasote/stable -r default --force --only-recipe\")\n        client.run(\"remote list-users\")\n        assert 'default:\\n  Username: admin\\n  authenticated: True' in client.out\n\n    def test_command_interactive_only(self):\n        test_server = TestServer()\n        servers = {\"default\": test_server}\n        client = TestClient(servers=servers, inputs=[\"password\"])\n        client.run('remote login default admin -p')\n        assert \"Changed user of remote 'default' from 'None' (anonymous) to 'admin' (authenticated)\" in client.out\n\n    def test_command_user_with_interactive_password_login_prompt_disabled(self):\n        \"\"\" Interactive password should not work.\n        \"\"\"\n        test_server = TestServer()\n        servers = {\"default\": test_server}\n        client = TestClient(servers=servers,  inputs=[])\n        conan_conf = \"core:non_interactive=True\"\n        client.save_home({\"global.conf\": conan_conf})\n        client.run('remote login default admin -p', assert_error=True)\n        assert 'ERROR: Conan interactive mode disabled' in client.out\n        assert \"Please enter a password for user 'admin'\" not in client.out\n        client.run(\"remote list-users\")\n        assert \"default:\\n  No user\" in client.out\n\n    def test_authenticated(self):\n        test_server = TestServer(users={\"lasote\": \"mypass\", \"danimtb\": \"passpass\"})\n        servers = OrderedDict()\n        servers[\"default\"] = test_server\n        servers[\"other_server\"] = TestServer()\n        client = TestClient(servers=servers, inputs=[\"lasote\", \"mypass\", \"mypass\", \"mypass\"])\n        client.run(\"remote logout default\")\n        assert \"Changed user of remote 'default' from 'None' (anonymous) to 'None' (anonymous)\" in client.out\n        assert \"[authenticated]\" not in client.out\n        client.run('remote set-user default bad_user')\n        client.run(\"remote list-users\")\n        assert 'default:\\n  Username: bad_user\\n  authenticated: False' in client.out\n        client.run(\"remote set-user default lasote\")\n        client.run(\"remote list-users\")\n        assert 'default:\\n  Username: lasote\\n  authenticated: False' in client.out\n        client.run(\"remote login default lasote -p mypass\")\n        client.run(\"remote list-users\")\n        assert 'default:\\n  Username: lasote\\n  authenticated: True' in client.out\n\n        client.run(\"remote login default danimtb -p passpass\")\n        assert \"Changed user of remote 'default' from 'lasote' (authenticated) to 'danimtb' (authenticated)\" in client.out\n        client.run(\"remote list-users\")\n        assert 'default:\\n  Username: danimtb\\n  authenticated: True' in client.out\n\n    def test_json(self):\n        default_server = TestServer(users={\"lasote\": \"mypass\", \"danimtb\": \"passpass\"})\n        other_server = TestServer()\n        servers = OrderedDict()\n        servers[\"default\"] = default_server\n        servers[\"other_server\"] = other_server\n        client = TestClient(servers=servers, inputs=[\"lasote\", \"mypass\", \"danimtb\", \"passpass\"])\n        client.run(\"remote list-users -f json\")\n        info = json.loads(client.stdout)\n        assert info == [\n                            {\n                                \"name\": \"default\",\n                                \"authenticated\": False,\n                                \"user_name\": None\n                            },\n                            {\n                                \"name\": \"other_server\",\n                                \"authenticated\": False,\n                                \"user_name\": None\n                            }\n                        ]\n\n        client.run('remote set-user default bad_user')\n        client.run(\"remote list-users -f json\")\n        info = json.loads(client.stdout)\n        assert info == [\n            {\n                \"name\": \"default\",\n                \"authenticated\": False,\n                \"user_name\": \"bad_user\"\n            },\n            {\n                \"name\": \"other_server\",\n                \"authenticated\": False,\n                \"user_name\": None\n            }\n        ]\n\n        client.run('remote set-user default lasote')\n        client.run(\"remote list-users -f json\")\n        info = json.loads(client.stdout)\n        assert info == [\n            {\n                \"name\": \"default\",\n                \"authenticated\": False,\n                \"user_name\": \"lasote\"\n            },\n            {\n                \"name\": \"other_server\",\n                \"authenticated\": False,\n                \"user_name\": None\n            }\n        ]\n\n        client.run(\"remote login default lasote -p mypass\")\n        client.run(\"remote list-users -f json\")\n        info = json.loads(client.stdout)\n        assert info == [\n            {\n                \"name\": \"default\",\n                \"authenticated\": True,\n                \"user_name\": \"lasote\"\n            },\n            {\n                \"name\": \"other_server\",\n                \"authenticated\": False,\n                \"user_name\": None\n            }\n        ]\n\n        client.run(\"remote login default danimtb -p passpass\")\n        client.run(\"remote list-users -f json\")\n        info = json.loads(client.stdout)\n        assert info == [\n            {\n                \"name\": \"default\",\n                \"authenticated\": True,\n                \"user_name\": \"danimtb\"\n            },\n            {\n                \"name\": \"other_server\",\n                \"authenticated\": False,\n                \"user_name\": None\n            }\n        ]\n        client.run(\"remote set-user other_server lasote\")\n        client.run(\"remote list-users -f json\")\n        info = json.loads(client.stdout)\n        assert info == [\n            {\n                \"name\": \"default\",\n                \"authenticated\": True,\n                \"user_name\": \"danimtb\"\n            },\n            {\n                \"name\": \"other_server\",\n                \"authenticated\": False,\n                \"user_name\": \"lasote\"\n            }\n        ]\n\n        client.run(\"remote logout '*'\")\n        client.run(\"remote set-user default danimtb\")\n        client.run(\"remote list-users -f json\")\n        info = json.loads(client.stdout)\n        assert info == [\n            {\n                \"name\": \"default\",\n                \"authenticated\": False,\n                \"user_name\": \"danimtb\"\n            },\n            {\n                \"name\": \"other_server\",\n                \"authenticated\": False,\n                \"user_name\": None\n            }\n        ]\n        client.run(\"remote list-users\")\n        assert \"default:\\n  Username: danimtb\\n  authenticated: False\" in client.out\n        assert \"other_server:\\n  No user\\n\" in client.out\n\n    def test_skip_auth(self):\n        default_server = TestServer(users={\"lasote\": \"mypass\", \"danimtb\": \"passpass\"})\n        servers = OrderedDict()\n        servers[\"default\"] = default_server\n        client = TestClient(servers=servers)\n        # Regular auth\n        client.run(\"remote login default lasote -p mypass\")\n\n        # Now skip the auth but keeping the same user\n        client.run(\"remote set-user default lasote\")\n        assert \"Changed user of remote 'default' from 'lasote' (authenticated) to 'lasote' (authenticated)\" in client.out\n\n        # If we change the user the credentials are removed\n        client.run(\"remote set-user default flanders\")\n        assert \"Changed user of remote 'default' from 'lasote' (authenticated) to 'flanders' (anonymous)\" in client.out\n\n        client.run(\"remote login default lasote -p BAD_PASS\", assert_error=True)\n        assert \"Wrong user or password\" in client.out\n\n        # Login again correctly\n        client.run(\"remote login default lasote -p mypass\")\n\n    def test_login_multiremote(self):\n        servers = OrderedDict()\n        servers[\"default\"] = TestServer(users={\"admin\": \"password\"})\n        servers[\"other\"] = TestServer(users={\"admin\": \"password\"})\n        c = TestClient(servers=servers, inputs=[\"admin\", \"password\", \"wrong\", \"wrong\"])\n        # This must fail, not autthenticate in the next remote\n        c.run(\"remote login *\", assert_error=True)\n        assert \"ERROR: Wrong user or password. [Remote: other]\" in c.out\n\n\ndef test_user_removed_remote_removed():\n    # Make sure that removing a remote clears the credentials\n    # https://github.com/conan-io/conan/issues/5562\n    c = TestClient(default_server_user=True)\n    server_url = c.servers[\"default\"].fake_url\n    c.run(\"remote login default admin -p password\")\n    localdb = LocalDB(c.cache_folder)\n    login = localdb.get_login(server_url)\n    assert login[0] == \"admin\"\n    c.run(\"remote remove default\")\n    login = localdb.get_login(server_url)\n    assert login == (None, None, None)\n\n\nclass TestRemoteAuth:\n    def test_remote_auth(self):\n        servers = OrderedDict()\n        servers[\"default\"] = TestServer(users={\"lasote\": \"mypass\", \"danimtb\": \"passpass\"})\n        servers[\"other_server\"] = TestServer(users={\"lasote\": \"mypass\"})\n        c = TestClient(servers=servers, inputs=[\"lasote\", \"mypass\", \"danimtb\", \"passpass\",\n                                                \"lasote\", \"mypass\"])\n        c.run(\"remote auth *\")\n        text = textwrap.dedent(\"\"\"\\\n            default:\n                user: lasote\n            other_server:\n                user: lasote\"\"\")\n        assert text in c.out\n\n        c.run(\"remote auth * --format=json\")\n        result = json.loads(c.stdout)\n        assert result == {'default': {'user': 'lasote'}, 'other_server': {'user': 'lasote'}}\n\n    def test_remote_auth_force(self):\n        servers = OrderedDict()\n        servers[\"default\"] = TestServer(users={\"lasote\": \"mypass\", \"danimtb\": \"passpass\"})\n        servers[\"other_server\"] = TestServer(users={\"lasote\": \"mypass\"})\n        c = TestClient(servers=servers, inputs=[\"lasote\", \"mypass\", \"danimtb\", \"passpass\",\n                                                \"lasote\", \"mypass\"])\n\n        with patch(\"conan.internal.rest.rest_client_v2.RestV2Methods.check_credentials\") as check_credentials_mock:\n            c.run(\"remote auth --force *\")\n            check_credentials_mock.assert_called_with(True)\n\n    def test_remote_auth_force_false(self):\n        servers = OrderedDict()\n        servers[\"default\"] = TestServer(users={\"lasote\": \"mypass\", \"danimtb\": \"passpass\"})\n        servers[\"other_server\"] = TestServer(users={\"lasote\": \"mypass\"})\n        c = TestClient(servers=servers, inputs=[\"lasote\", \"mypass\", \"danimtb\", \"passpass\",\n                                                \"lasote\", \"mypass\"])\n\n        with patch(\"conan.internal.rest.rest_client_v2.RestV2Methods.check_credentials\") as check_credentials_mock:\n            c.run(\"remote auth *\")\n            check_credentials_mock.assert_called_with(False)\n\n    def test_remote_auth_with_user(self):\n        servers = OrderedDict()\n        servers[\"default\"] = TestServer(users={\"lasote\": \"mypass\"})\n        servers[\"other_server\"] = TestServer()\n        c = TestClient(servers=servers, inputs=[\"lasote\", \"mypass\"])\n        c.run(\"remote set-user default lasote\")\n        c.run(\"remote auth * --with-user\")\n        text = textwrap.dedent(\"\"\"\\\n            default:\n                user: lasote\n            other_server:\n                user: None\"\"\")\n        assert text in c.out\n\n    def test_remote_auth_with_user_env_var(self):\n        servers = OrderedDict()\n        servers[\"default\"] = TestServer(users={\"lasote\": \"mypass\"})\n        servers[\"other_server\"] = TestServer()\n        c = TestClient(servers=servers)\n        with environment_update({\"CONAN_LOGIN_USERNAME_DEFAULT\": \"lasote\",\n                                 \"CONAN_PASSWORD_DEFAULT\": \"mypass\"}):\n            c.run(\"remote auth * --with-user\")\n        text = textwrap.dedent(\"\"\"\\\n            default:\n                user: lasote\n            other_server:\n                user: None\"\"\")\n        assert text in c.out\n\n    def test_remote_auth_error(self):\n        servers = OrderedDict()\n        servers[\"default\"] = TestServer(users={\"user\": \"password\"})\n        c = TestClient(servers=servers, inputs=[\"user1\", \"pass\", \"user2\", \"pass\", \"user3\", \"pass\"])\n        c.run(\"remote auth *\")\n        assert \"error: Too many failed login attempts, bye!\" in c.out\n\n    def test_remote_auth_server_expire_token_secret(self):\n        server = TestServer(users={\"myuser\": \"password\", \"myotheruser\": \"otherpass\"})\n        c = TestClient(servers={\"default\": server}, inputs=[\"myuser\", \"password\",\n                                                            \"myotheruser\", \"otherpass\",\n                                                            \"user\", \"pass\", \"user\", \"pass\",\n                                                            \"user\", \"pass\"])\n        c.run(\"remote auth *\")\n        assert \"Remote 'default' needs authentication, obtaining credentials\" in c.out\n        assert \"user: myuser\" in c.out\n        c.run(\"remote auth *\")\n        assert \"Remote 'default' needs authentication, obtaining credentials\" not in c.out\n        assert \"user: myuser\" in c.out\n        # Invalidate server secret\n        server.test_server.ra.api_v2.credentials_manager.secret = \"potato\" * 6\n        c.run(\"remote auth *\")\n        assert \"user: myotheruser\" in c.out\n        # Invalidate server secret again\n        server.test_server.ra.api_v2.credentials_manager.secret = \"potato2\" * 6\n        c.run(\"remote auth *\")\n        assert \"error: Too many failed login attempts, bye!\" in c.out\n\n    def test_remote_auth_server_expire_token(self):\n        server = TestServer(users={\"myuser\": \"password\", \"myotheruser\": \"otherpass\"})\n        server.test_server.ra.api_v2.credentials_manager.expire_time = timedelta(seconds=2)\n        c = TestClient(servers={\"default\": server}, inputs=[\"myuser\", \"password\",\n                                                            \"myotheruser\", \"otherpass\",\n                                                            \"user\", \"pass\", \"user\", \"pass\",\n                                                            \"user\", \"pass\"])\n        c.run(\"remote auth *\")\n        assert \"user: myuser\" in c.out\n        # token not expired yet, should work\n        c.run(\"remote auth *\")\n        assert \"user: myuser\" in c.out\n        # Token should expire\n        time.sleep(3)\n        c.run(\"remote auth *\")\n        assert \"user: myotheruser\" in c.out\n        # Token should expire\n        time.sleep(3)\n        c.run(\"remote auth *\")\n        assert \"error: Too many failed login attempts, bye!\" in c.out\n\n    def test_auth_after_logout(self):\n        server = TestServer(users={\"myuser\": \"password\"})\n        c = TestClient(servers={\"default\": server}, inputs=[\"myuser\", \"password\"]*2)\n        c.run(\"remote auth *\")\n        assert \"Remote 'default' needs authentication, obtaining credentials\" in c.out\n        assert \"user: myuser\" in c.out\n        c.run(\"remote logout *\")\n        assert \"Changed user of remote 'default' from 'myuser' (authenticated) to 'None'\" in c.out\n        c.run(\"remote auth *\")\n        assert \"Remote 'default' needs authentication, obtaining credentials\" in c.out\n        assert \"user: myuser\" in c.out\n"
  },
  {
    "path": "test/integration/command/remove_empty_dirs_test.py",
    "content": "import os\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestRemoveEmptyDirs:\n\n    def test_basic(self):\n        client = TestClient()\n        client.save({\"conanfile.py\": GenConanfile(\"hello\", \"0.1\")})\n        client.run(\"export . --user=lasote --channel=stable\")\n        ref_layout = client.exported_layout()\n        assert os.path.exists(ref_layout.base_folder)\n        client.run(\"remove hello* -c\")\n        assert not os.path.exists(ref_layout.base_folder)\n\n    def test_shared_folder(self):\n        client = TestClient()\n        client.save({\"conanfile.py\": GenConanfile(\"hello\", \"0.1\")})\n        client.run(\"export . --user=lasote --channel=stable\")\n        ref_layout = client.exported_layout()\n        assert os.path.exists(ref_layout.base_folder)\n        client.run(\"export . --user=lasote2 --channel=stable\")\n        ref_layout2 = client.exported_layout()\n        assert os.path.exists(ref_layout2.base_folder)\n        client.run(\"remove hello/0.1@lasote/stable -c\")\n        assert not os.path.exists(ref_layout.base_folder)\n        assert os.path.exists(ref_layout2.base_folder)\n"
  },
  {
    "path": "test/integration/command/remove_test.py",
    "content": "import json\nimport os\nimport shutil\n\nimport pytest\n\nfrom conan.api.conan_api import ConanAPI\nfrom conan.internal.errors import NotFoundException\nfrom conan.api.model import PkgReference\nfrom conan.api.model import RecipeReference\nfrom conan.test.utils.tools import NO_SETTINGS_PACKAGE_ID, TestClient, GenConanfile\nfrom conan.test.utils.env import environment_update\n\n\nclass TestRemoveWithoutUserChannel:\n\n    @pytest.mark.parametrize(\"dry_run\", [True, False])\n    def test_local(self, dry_run):\n        client = TestClient()\n        client.save({\"conanfile.py\": GenConanfile()})\n        client.run(\"create . --name=lib --version=1.0\")\n        ref_layout = client.exported_layout()\n        pkg_layout = client.created_layout()\n        extra = \" --dry-run\" if dry_run else \"\"\n        client.run(\"remove lib/1.0 -c\" + extra)\n        assert os.path.exists(ref_layout.base_folder) == dry_run\n        assert os.path.exists(pkg_layout.base_folder) == dry_run\n\n    @pytest.mark.parametrize(\"confirm\", [True, False])\n    def test_local_dryrun_output(self, confirm):\n        client = TestClient()\n        client.save({\"conanfile.py\": GenConanfile()})\n        client.run(\"create . --name=lib --version=1.0\")\n        client.run(\"remove lib/1.0 --dry-run\", inputs=[\"yes\" if confirm else \"no\"])\n        assert \"(yes/no)\" in client.out  # Users are asked even when dry-run is set\n        if confirm:\n            assert \"Removed recipe and all binaries\" in client.out  # Output it printed for dry-run\n        else:\n            assert \"Removed recipe and all binaries\" not in client.out\n\n    @pytest.mark.artifactory_ready\n    def test_remote(self):\n        client = TestClient(default_server_user=True)\n        client.save({\"conanfile.py\": GenConanfile()})\n        client.run(\"create . --name=lib --version=1.0\")\n        client.run(\"upload lib/1.0 -r default -c\")\n        client.run(\"remove lib/1.0 -c\")\n        # we can still install it\n        client.run(\"install --requires=lib/1.0@\")\n        assert \"lib/1.0: Retrieving package\" in client.out\n        client.run(\"remove lib/1.0 -c\")\n\n        # Now remove remotely, dry run first\n        client.run(\"remove lib/1.0 -c -r default --dry-run\")\n\n        # we can still install it\n        client.run(\"install --requires=lib/1.0@\")\n        assert \"lib/1.0: Retrieving package\" in client.out\n        client.run(\"remove lib/1.0 -c\")\n\n        # Now remove remotely, for real this time\n        client.run(\"remove lib/1.0 -c -r default\")\n\n        client.run(\"install --requires=lib/1.0@\", assert_error=True)\n        assert \"Unable to find 'lib/1.0' in remotes\" in client.out\n\n\nclass TestRemovePackageRevisions:\n\n    @pytest.mark.artifactory_ready\n    def test_remove_package_revision(self):\n        \"\"\" Remove package ID based on recipe revision. The package must be deleted, but\n            the recipe must be preserved\n        \"\"\"\n        ref = RecipeReference.loads(\"foobar/0.1@user/testing#4d670581ccb765839f2239cc8dff8fbd\")\n        pref_arg = PkgReference(ref, NO_SETTINGS_PACKAGE_ID)\n        pref = PkgReference(ref, NO_SETTINGS_PACKAGE_ID, \"0ba8627bd47edc3a501e8f0eb9a79e5e\")\n        c = TestClient(light=True, default_server_user=True)\n        c.save({\"conanfile.py\": GenConanfile()})\n        c.run(\"create . --name=foobar --version=0.1 --user=user --channel=testing\")\n        assert c.package_exists(pref)\n        c.run(\"upload * -r default -c\")\n        c.run(f\"list {ref}:*\")\n        assert NO_SETTINGS_PACKAGE_ID in c.out\n\n        # remove from cache\n        c.run(f\"remove -c {pref_arg.repr_notime()}\")\n        assert not c.package_exists(pref)\n\n        # remove From server\n        c.run(f\"remove -c {pref_arg.repr_notime()} -r=default\")\n        c.run(f\"list {ref}:*\")\n        assert NO_SETTINGS_PACKAGE_ID not in c.out\n\n    @pytest.mark.artifactory_ready\n    def test_remove_all_packages_but_the_recipe_at_remote(self):\n        \"\"\" Remove all the packages but not the recipe in a remote\n        \"\"\"\n        c = TestClient(default_server_user=True)\n        c.save({\"conanfile.py\": GenConanfile(\"foobar\", \"0.1\").with_settings(\"arch\")})\n        c.run(\"create . --user=user --channel=testing -s arch=x86_64\")\n        c.run(\"create . --user=user --channel=testing -s arch=x86\")\n        c.run(\"upload * -r default -c\")\n\n        c.run(\"list *:* -r default\")\n        assert \"foobar/0.1@user/testing\" in c.out\n        assert \"arch: x86_64\" in c.out\n        assert \"arch: x86\" in c.out\n\n        c.run(\"remove -c foobar/0.1@user/testing:* -r default\")\n        c.run(\"list *:* -r default\")\n        assert \"foobar/0.1@user/testing\" in c.out\n        assert \"arch: x86_64\" not in c.out\n        assert \"arch: x86\" not in c.out\n\n\n# populated packages of bar\nbar_rrev = \"bar/1.1#7db54b020cc95b8bdce49cd6aa5623c0\"\nbar_rrev2 = \"bar/1.1#78b42a981b29d2cb00fda10b72f1e72a\"\npkg_id_debug = \"9e186f6d94c008b544af1569d1a6368d8339efc5\"\npkg_id_release = \"efa83b160a55b033c4ea706ddb980cd708e3ba1b\"\nbar_rrev2_debug = '{}:{}'.format(bar_rrev2, pkg_id_debug)\nbar_rrev2_release = '{}:{}'.format(bar_rrev2, pkg_id_release)\n\nbar_prev1 = \"ee1ca5821b390a75d7168f4567f9ba75\"\nbar_prev2 = \"f523273047249d5a136fe48d33f645bb\"\nbar_rrev2_release_prev1 = \"{}#{}\".format(bar_rrev2_release, bar_prev1)\nbar_rrev2_release_prev2 = \"{}#{}\".format(bar_rrev2_release, bar_prev2)\n\n\n@pytest.fixture(scope=\"module\")\ndef _populated_client_base():\n    \"\"\"\n    foo/1.0@ (one revision) no packages\n    foo/1.0@user/channel (one revision)  no packages\n    fbar/1.1@ (one revision)  no packages\n\n    bar/1.0@ (two revision) => Debug, Release => (two package revision each)\n    \"\"\"\n    # To generate different package revisions\n    package_lines = 'save(self, os.path.join(self.package_folder, \"foo.txt\"), ' \\\n                    'os.getenv(\"foo_test\", \"Na\"))'\n    client = TestClient(default_server_user=True)\n    conanfile = str(GenConanfile().with_settings(\"build_type\")\n                                  .with_package(package_lines)\n                                  .with_import(\"from conan.tools.files import save\")\n                                  .with_import(\"import os\")\n                                  .with_import(\"import time\"))\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"export . --name foo --version 1.0\")\n    client.run(\"export . --name foo --version 1.0 --user user --channel channel\")\n    client.run(\"export . --name fbar --version 1.1\")\n\n    # Two package revisions for bar/1.1 (Release)\n    for _i in range(2):\n        with environment_update({'foo_test': str(_i)}):\n            client.run(\"create . --name=bar --version=1.1 -s build_type=Release\")\n    client.run(\"create . --name=bar --version=1.1 -s build_type=Debug\")\n\n    prefs = _get_revisions_packages(client, bar_rrev2_release, False)\n    assert set(prefs) == {bar_rrev2_release_prev1, bar_rrev2_release_prev2}\n\n    # Two recipe revisions for bar/1.1\n    client.save({\"conanfile.py\": conanfile + \"\\n # THIS IS ANOTHER RECIPE REVISION\"})\n    client.run(\"create . --name=bar --version=1.1 -s build_type=Debug\")\n\n    client.run(\"upload '*#*:*#*' -c -r default\")\n\n    return client\n\n\n@pytest.fixture()\ndef populated_client(_populated_client_base):\n    \"\"\" this is much faster than creating and uploading everythin\n    \"\"\"\n    client = TestClient(default_server_user=True)\n    shutil.rmtree(client.cache_folder)\n    shutil.copytree(_populated_client_base.cache_folder, client.cache_folder)\n    shutil.rmtree(client.servers[\"default\"].test_server._base_path)\n    shutil.copytree(_populated_client_base.servers[\"default\"].test_server._base_path,\n                    client.servers[\"default\"].test_server._base_path)\n    client.update_servers()\n    return client\n\n\n@pytest.mark.parametrize(\"with_remote\", [True, False])\n@pytest.mark.parametrize(\"data\", [\n    {\"remove\": \"foo*\", \"recipes\": ['bar/1.1', 'fbar/1.1']},\n    {\"remove\": \"foo/*\", \"recipes\": ['bar/1.1', 'fbar/1.1']},\n    {\"remove\": \"*\", \"recipes\": []},\n    {\"remove\": \"*/*\", \"recipes\": []},\n    {\"remove\": \"*/*#*\", \"recipes\": []},\n    {\"remove\": \"*/*#z*\", \"recipes\": ['foo/1.0@user/channel', 'foo/1.0', 'bar/1.1', 'fbar/1.1']},\n    {\"remove\": \"f*\", \"recipes\": [\"bar/1.1\"]},\n    {\"remove\": \"*/1.1\", \"recipes\": [\"foo/1.0\", \"foo/1.0@user/channel\"]},\n    {\"remove\": \"*/*@user/*\", \"recipes\": [\"foo/1.0\", \"fbar/1.1\", \"bar/1.1\"]},\n    {\"remove\": \"*/*@*\", \"recipes\": ['foo/1.0', 'fbar/1.1', 'bar/1.1']},\n    {\"remove\": \"*/*#*:*\", \"recipes\": ['bar/1.1', 'foo/1.0@user/channel', 'foo/1.0', 'fbar/1.1']},\n    {\"remove\": \"foo/1.0@user/channel:*\", \"recipes\": ['bar/1.1', 'foo/1.0@user/channel', 'foo/1.0',\n                                                     'fbar/1.1']},\n    {\"remove\": \"foo/*@\", \"recipes\": ['foo/1.0@user/channel', 'bar/1.1', 'fbar/1.1']},\n    {\"remove\": \"foo\", \"recipes\": ['bar/1.1', 'fbar/1.1']},\n    {\"remove\": \"*#\", \"recipes\": []},\n    {\"remove\": \"*/*#\", \"recipes\": []},\n])\ndef test_new_remove_recipes_expressions(populated_client, with_remote, data):\n    r = \"-r default\" if with_remote else \"\"\n    assert \"error\" not in data\n    populated_client.run(\"remove {} -c {}\".format(data[\"remove\"], r))\n    populated_client.run(f\"list {r} --format=json\")\n    origin = \"default\" if with_remote else \"Local Cache\"\n    assert set(json.loads(populated_client.stdout)[origin]) == set(data[\"recipes\"])\n\n\n@pytest.mark.parametrize(\"with_remote\", [True, False])\n@pytest.mark.parametrize(\"data\", [\n    {\"remove\": \"bar/*#*\", \"rrevs\": []},\n    {\"remove\": \"bar/1.1#z*\", \"rrevs\": [bar_rrev, bar_rrev2]},\n    {\"remove\": \"bar/1.1#*9*\", \"rrevs\": []},\n    {\"remove\": \"bar/1.1#*2a\", \"rrevs\": [bar_rrev]},\n    {\"remove\": \"bar*#*50\", \"rrevs\": [bar_rrev, bar_rrev2]},\n    {\"remove\": \"bar*#latest\", \"rrevs\": [bar_rrev2]},  # latest is bar_rrev\n    {\"remove\": \"bar*#!latest\", \"rrevs\": [bar_rrev]},  # latest is bar_rrev\n    {\"remove\": \"bar*#~latest\", \"rrevs\": [bar_rrev]},  # latest is bar_rrev\n])\ndef test_new_remove_recipe_revisions_expressions(populated_client, with_remote, data):\n    r = \"-r default\" if with_remote else \"\"\n    error = data.get(\"error\", False)\n    populated_client.run(\"remove {} -c {}\".format(data[\"remove\"], r), assert_error=error)\n    if not error:\n        rrevs = _get_revisions_recipes(populated_client, \"bar/1.1\", with_remote)\n        assert rrevs == set(data[\"rrevs\"])\n\n\n@pytest.mark.parametrize(\"with_remote\", [True, False])\n@pytest.mark.parametrize(\"data\", [\n    {\"remove\": \"bar/1.1#*:*\", \"prefs\": []},\n    {\"remove\": \"bar/1.1#*:*#*\", \"prefs\": []},\n    {\"remove\": \"bar/1.1#z*:*\", \"prefs\": [bar_rrev2_debug, bar_rrev2_release]},\n    {\"remove\": \"bar/1.1#*:*#kk*\", \"prefs\": [bar_rrev2_debug, bar_rrev2_release]},\n    {\"remove\": \"bar/1.1#*:{}*\".format(pkg_id_release), \"prefs\": [bar_rrev2_debug]},\n    {\"remove\": \"bar/1.1#*:*{}\".format(pkg_id_release[-12:]), \"prefs\": [bar_rrev2_debug]},\n    {\"remove\": \"{}:*{}*\".format(bar_rrev2, pkg_id_debug[5:15]), \"prefs\": [bar_rrev2_release]},\n    {\"remove\": \"*/*#*:*{}*\".format(pkg_id_debug[5:15]), \"prefs\": [bar_rrev2_release]},\n    {\"remove\": '*/*#*:* -p build_type=\"fake\"', \"prefs\": [bar_rrev2_release, bar_rrev2_debug]},\n    {\"remove\": '*/*#*:* -p build_type=\"Release\"', \"prefs\": [bar_rrev2_debug]},\n    {\"remove\": '*/*#*:* -p build_type=\"Debug\"', \"prefs\": [bar_rrev2_release]},\n    # Errors\n    {\"remove\": '*/*#*:*#* -p', \"error\": True,\n     \"error_msg\": \"argument -p/--package-query: expected one argument\"},\n    {\"remove\": \"bar/1.1#*:\", \"prefs\": []},\n    {\"remove\": \"bar/1.1#*:234234*#\", \"prefs\": [bar_rrev2_debug, bar_rrev2_release]},\n    {\"remove\": \"bar/1.1:234234*\", \"prefs\": [bar_rrev2_debug, bar_rrev2_release]},\n    {\"remove\": \"bar/1.1:* -p os=Windows\", \"prefs\": [bar_rrev2_debug, bar_rrev2_release]},\n])\ndef test_new_remove_package_expressions(populated_client, with_remote, data):\n    # Remove the ones we are not testing here\n    r = \"-r default\" if with_remote else \"\"\n    pids = _get_all_packages(populated_client, bar_rrev2, with_remote)\n    assert pids == {bar_rrev2_debug, bar_rrev2_release}\n\n    error = data.get(\"error\", False)\n    populated_client.run(\"remove {} -c {}\".format(data[\"remove\"], r), assert_error=error)\n    if not error:\n        pids = _get_all_packages(populated_client, bar_rrev2, with_remote)\n        assert pids == set(data[\"prefs\"])\n    elif data.get(\"error_msg\"):\n        assert data.get(\"error_msg\") in populated_client.out\n\n\n@pytest.mark.parametrize(\"with_remote\", [True, False])\n@pytest.mark.parametrize(\"data\", [\n    {\"remove\": '{}#*kk*'.format(bar_rrev2_release), \"prevs\": [bar_rrev2_release_prev1,\n                                                              bar_rrev2_release_prev2]},\n    {\"remove\": '{}#*'.format(bar_rrev2_release), \"prevs\": []},\n    {\"remove\": '{}*#{}* -p \"build_type=Debug\"'.format(bar_rrev2_release, bar_prev2[:3]),\n     \"prevs\": [bar_rrev2_release_prev1, bar_rrev2_release_prev2]},\n    {\"remove\": '{}*#{}* -p \"build_type=Release\"'.format(bar_rrev2_release, bar_prev2[:3]),\n     \"prevs\": [bar_rrev2_release_prev1]},\n    {\"remove\": '{}*#* -p \"build_type=Release\"'.format(bar_rrev2_release), \"prevs\": []},\n    {\"remove\": '{}*#* -p \"build_type=Debug\"'.format(bar_rrev2_release),\n     \"prevs\": [bar_rrev2_release_prev1, bar_rrev2_release_prev2]},\n    # Errors\n    {\"remove\": '{}#'.format(bar_rrev2_release), \"prevs\": []},\n    {\"remove\": '{}#latest'.format(bar_rrev2_release), \"prevs\": [bar_rrev2_release_prev1]},\n    {\"remove\": '{}#!latest'.format(bar_rrev2_release), \"prevs\": [bar_rrev2_release_prev2]},\n    {\"remove\": '{}#~latest'.format(bar_rrev2_release), \"prevs\": [bar_rrev2_release_prev2]},\n])\ndef test_new_remove_package_revisions_expressions(populated_client, with_remote, data):\n    # Remove the ones we are not testing here\n    r = \"-r default\" if with_remote else \"\"\n    populated_client.run(\"remove f/* -c {}\".format(r))\n\n    prefs = _get_revisions_packages(populated_client, bar_rrev2_release, with_remote)\n    assert set(prefs) == {bar_rrev2_release_prev1, bar_rrev2_release_prev2}\n\n    assert \"error\" not in data\n    populated_client.run(\"remove {} -c {}\".format(data[\"remove\"], r))\n    prefs = _get_revisions_packages(populated_client, bar_rrev2_release, with_remote)\n    assert set(prefs) == set(data[\"prevs\"])\n\n\ndef test_package_query_no_package_ref(populated_client):\n    populated_client.run(\"remove * -p 'compiler=clang'\", assert_error=True)\n    assert \"--package-query supplied but the pattern does not match packages\" in populated_client.out\n\n\ndef _get_all_packages(client, ref, with_remote):\n    ref = RecipeReference.loads(ref)\n    with client.mocked_servers():\n        api = ConanAPI(client.cache_folder)\n        remote = api.remotes.get(\"default\") if with_remote else None\n        try:\n            return set([r.repr_notime() for r in api.list._packages_configurations(ref, remote=remote)])  # noqa\n        except NotFoundException:\n            return set()\n\n\ndef _get_revisions_recipes(client, ref, with_remote):\n    ref = RecipeReference.loads(ref)\n    with client.mocked_servers():\n        api = ConanAPI(client.cache_folder)\n        remote = api.remotes.get(\"default\") if with_remote else None\n        try:\n            return set([r.repr_notime() for r in api.list.recipe_revisions(ref, remote=remote)])\n        except NotFoundException:\n            return set()\n\n\ndef _get_revisions_packages(client, pref, with_remote):\n    pref = PkgReference.loads(pref)\n    with client.mocked_servers():\n        api = ConanAPI(client.cache_folder)\n        remote = api.remotes.get(\"default\") if with_remote else None\n        try:\n            return set([r.repr_notime() for r in api.list.package_revisions(pref, remote=remote)])\n        except NotFoundException:\n            return set()\n"
  },
  {
    "path": "test/integration/command/require/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/command/require/test_command_require.py",
    "content": "import textwrap\n\nfrom conan.test.utils.tools import GenConanfile, TestClient\n\n\ndef test_add_require():\n    \"\"\"\n    Testing the \"conan dep add\" command which should always use the highest version\n    found in the first remote server or the local cache\n    \"\"\"\n    client = TestClient(default_server_user=True, light=True)\n    # No conanfile is present - error\n    client.run(\"require add hello\", assert_error=True)\n    assert \"ERROR: Conanfile not found at\" in client.out\n    client.save({\"conanfile.py\": GenConanfile(name=\"app\")})\n    # No requirements define\n    client.run(\"require add\", assert_error=True)\n    assert \"ERROR: You need to add any requires, tool_requires or test_requires.\" in client.out\n    # No remote recipe \"hello\" exists\n    client.run(\"require add hello\")\n    assert \"ERROR: Recipe hello not found.\" in client.out\n    hello_lib = GenConanfile(name=\"hello\")\n    client.save({\"hello/conanfile.py\": hello_lib})\n    client.run(\"create hello --version=1.0\")\n    client.run(\"create hello --version=2.0\")\n    client.run(\"create hello --version=3.0\")\n    client.run(\"upload * --confirm -r default\")\n    # Save a normal requires \"hello\"\n    client.run(\"require add hello\")\n    assert \"Added 'hello/[>=3.0 <4]' as a new requires.\" in client.out\n    content = client.load(\"conanfile.py\")\n    assert 'self.requires(\"hello/[>=3.0 <4]\")' in content\n    # Checking that it works\n    client.run(\"install .\")\n    expected = textwrap.dedent(\"\"\"\\\n    Resolved version ranges\n        hello/[>=3.0 <4]: hello/3.0\n    \"\"\")\n    assert expected in client.out\n    # Let's add the same \"hello\" but now as tool_requires and test_requires\n    client.run(\"require add --tool=hello --test=hello\")  # [tool|test]_requires\n    assert \"Added 'hello/[>=3.0 <4]' as a new tool_requires.\" in client.out\n    assert \"Added 'hello/[>=3.0 <4]' as a new test_requires.\" in client.out\n    # Try to add them again - does nothing and shows a warning\n    client.run(\"require add hello --tool=hello --test=hello\")\n    assert \"The requires hello is already in use.\" in client.out\n    assert \"The tool_requires hello is already in use.\" in client.out\n    assert \"The test_requires hello is already in use.\" in client.out\n\n    # Using only the local cache\n    bye_lib = GenConanfile(name=\"bye\")\n    client.save({\"bye/conanfile.py\": bye_lib})\n    client.run(\"create bye --version=1.0\")\n    client.run(\"create bye --version=2.0\")\n    client.run(\"require add bye --no-remote\")  # from cache\n    assert \"Added 'bye/[>=2.0 <3]' as a new requires.\" in client.out\n\n    # Using a specific version (it does not look for it neither locally nor remotely)\n    client.run(\"require add mylib/1.2\")\n    assert \"Added 'mylib/[>=1.2 <2]' as a new requires.\" in client.out\n\n    # Using commit as a version\n    client.run(\"require add other/cci.20203034\")  # can not bump the version, won't use vrange\n    assert \"Added 'other/cci.20203034' as a new requires.\" in client.out\n\n\ndef test_remove_require():\n    client = TestClient(light=True)\n    # No conanfile is present - error\n    client.run(\"require remove hello\", assert_error=True)\n    assert \"ERROR: Conanfile not found at\" in client.out\n    client.save({\"conanfile.py\": GenConanfile(name=\"app\")})\n    # No requirement \"hello\" declared\n    client.run(\"require remove hello\")\n    assert \"WARN: The requires hello is not declared in your conanfile.\" in client.out\n    client.save({\"conanfile.py\": GenConanfile(name=\"app\")\n                .with_requirement(\"hello/1.2\")\n                .with_tool_requirement(\"hello/1.2\")\n                .with_test_requirement(\"hello/1.2\")})\n    client.run(\"require remove hello --tool=hello --test=hello\")\n    assert \"Removed hello dependency as requires.\" in client.out\n    assert \"Removed hello dependency as tool_requires.\" in client.out\n    assert \"Removed hello dependency as test_requires.\" in client.out\n    content = client.load(\"conanfile.py\")\n    assert 'self.requires(\"hello/1.2\"' not in content\n    assert 'self.tool_requires(\"hello/1.2\"' not in content\n    assert 'self.test_requires(\"hello/1.2\"' not in content\n    client.run(\"require remove hello --tool=hello --test=hello\")\n    assert \"WARN: The requires hello is not declared in your conanfile.\" in client.out\n    assert \"WARN: The tool_requires hello is not declared in your conanfile.\" in client.out\n    assert \"WARN: The test_requires hello is not declared in your conanfile.\" in client.out\n"
  },
  {
    "path": "test/integration/command/source_test.py",
    "content": "import os\nimport re\nimport textwrap\nfrom collections import OrderedDict\n\nimport pytest\n\nfrom conan.internal.paths import CONANFILE\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient, TestServer\n\n\nclass TestSource:\n\n    def test_local_flow_patch(self):\n        # https://github.com/conan-io/conan/issues/2327\n        conanfile = \"\"\"from conan import ConanFile\nfrom conan.tools.files import save, load\nimport os\nclass TestexportConan(ConanFile):\n    name = \"test\"\n    version = \"0.1\"\n\n    exports = \"mypython.py\"\n    exports_sources = \"patch.patch\"\n\n    def source(self):\n        save(self, \"hello/hello.h\", \"my hello header!\")\n        patch = os.path.join(self.source_folder, \"patch.patch\")\n        self.output.info(\"PATCH: %s\" % load(self, patch))\n        header = os.path.join(self.source_folder, \"hello/hello.h\")\n        self.output.info(\"HEADER: %s\" % load(self, header))\n        python = os.path.join(self.recipe_folder, \"mypython.py\")\n        self.output.info(\"PYTHON: %s\" % load(self, python))\n\"\"\"\n        client = TestClient(light=True)\n        client.save({\"conanfile.py\": conanfile,\n                     \"patch.patch\": \"mypatch\",\n                     \"mypython.py\": \"mypython\"})\n        client.run(\"source .\")\n        assert \"conanfile.py (test/0.1): PATCH: mypatch\" in client.out\n        assert \"conanfile.py (test/0.1): HEADER: my hello header!\" in client.out\n        assert \"conanfile.py (test/0.1): PYTHON: mypython\" in client.out\n\n        client.run(\"create . \")\n        assert \"test/0.1: PATCH: mypatch\" in client.out\n        assert \"test/0.1: HEADER: my hello header!\" in client.out\n        assert \"test/0.1: PYTHON: mypython\" in client.out\n\n    def test_apply_patch(self):\n        # https://github.com/conan-io/conan/issues/2327\n        # Test if a patch can be applied in source() both in create\n        # and local flow\n        client = TestClient(light=True)\n        conanfile = \"\"\"from conan import ConanFile\nfrom conan.tools.files import load\nimport os\nclass Pkg(ConanFile):\n    exports_sources = \"*\"\n    def source(self):\n        patch = os.path.join(self.source_folder, \"mypatch\")\n        self.output.info(\"PATCH: %s\" % load(self, patch))\n\"\"\"\n        client.save({\"conanfile.py\": conanfile,\n                     \"mypatch\": \"this is my patch\"})\n        client.run(\"source .\")\n        assert \"PATCH: this is my patch\" in client.out\n        client.run(\"source .\")\n        assert \"PATCH: this is my patch\" in client.out\n        client.run(\"create . --name=pkg --version=0.1 --user=user --channel=testing\")\n        assert \"PATCH: this is my patch\" in client.out\n\n    def test_source_warning_os_build(self):\n        # https://github.com/conan-io/conan/issues/2368\n        conanfile = '''from conan import ConanFile\nclass ConanLib(ConanFile):\n    pass\n'''\n        client = TestClient(light=True)\n        client.save({CONANFILE: conanfile})\n        client.run(\"source .\")\n        assert \"This package defines both 'os' and 'os_build'\" not in client.out\n\n    def test_source_with_path_errors(self):\n        client = TestClient(light=True)\n        client.save({\"conanfile.txt\": \"contents\"}, clean_first=True)\n\n        # Path with conanfile.txt\n        client.run(\"source conanfile.txt\", assert_error=True)\n        assert \"A conanfile.py is needed, %s is not acceptable\" \\\n                      % os.path.join(client.current_folder, \"conanfile.txt\") in client.out\n\n    def test_source_local_cwd(self):\n        conanfile = '''\nimport os\nfrom conan import ConanFile\n\nclass ConanLib(ConanFile):\n    name = \"hello\"\n    version = \"0.1\"\n\n    def source(self):\n        self.output.info(\"Running source!\")\n        self.output.info(\"cwd=>%s\" % os.getcwd())\n'''\n        client = TestClient(light=True)\n        client.save({CONANFILE: conanfile})\n\n        client.run(\"install .\")\n        client.run(\"source .\")\n        assert \"conanfile.py (hello/0.1): Calling source()\" in client.out\n        assert \"conanfile.py (hello/0.1): cwd=>%s\" % client.current_folder in client.out\n\n    def test_local_source(self):\n        conanfile = '''\nfrom conan import ConanFile\nfrom conan.tools.files import save\n\nclass ConanLib(ConanFile):\n\n    def source(self):\n        self.output.info(\"Running source!\")\n        err\n        save(self, \"file1.txt\", \"Hello World\")\n'''\n        # First, failing source()\n        client = TestClient(light=True)\n        client.save({CONANFILE: conanfile})\n\n        client.run(\"source .\", assert_error=True)\n        assert \"conanfile.py: Running source!\" in client.out\n        assert \"ERROR: conanfile.py: Error in source() method, line 9\" in client.out\n\n        # Fix the error and repeat\n        client.save({CONANFILE: conanfile.replace(\"err\", \"\")})\n        client.run(\"source\")\n        assert \"conanfile.py: Calling source() in\" in client.out\n        assert \"conanfile.py: Running source!\" in client.out\n        assert \"Hello World\" == client.load(\"file1.txt\")\n\n    def test_local_source_layout_root(self):\n        # Ensure that if a root folder is specified Conan source method\n        # uses it. This is especially important when running with\n        # no_copy_source where both the build()  and source() methods\n        # need to reference source_folder (so the value must be the\n        # same in both methods)\n        conanfile = textwrap.dedent('''\n            from conan import ConanFile\n            from conan.tools.files import save, load\n\n            class ConanLib(ConanFile):\n\n                def layout(self):\n                    self.folders.root = \"..\"\n                    self.folders.source = \"src\"\n\n                def source(self):\n                    self.output.info(f\"In the source() method the Source folder is: {self.source_folder}\")\n                    save(self, \"source_file.c\", \"conent\")\n\n                def build(self):\n                    self.output.info(f\"In the build() method the Source folder is: {self.source_folder}\")\n                    load(self, f\"{self.source_folder}/source_file.c\")\n            ''')\n        client = TestClient(light=True)\n        client.save({CONANFILE: conanfile})\n\n        client.run(\"source .\")\n        # The build method will fail if source() and build() don't\n        # both use the correct source_folder\n        client.run(\"build .\")\n        assert \"conanfile.py: Calling build()\" in client.out  # doesn't fail\n\n    def test_retrieve_exports_sources(self):\n        # For Conan 2.0 if we install a package from a remote and we want to upload to other\n        # remote we need to download the sources, as we consider revisions immutable, let's\n        # iterate through the remotes to get the sources from the first match\n        servers = OrderedDict()\n        for index in range(2):\n            servers[f\"server{index}\"] = TestServer([(\"*/*@*/*\", \"*\")], [(\"*/*@*/*\", \"*\")],\n                                                   users={\"user\": \"password\"})\n\n        client = TestClient(servers=servers, inputs=3*[\"user\", \"password\"])\n        client.save({\"conanfile.py\": GenConanfile().with_exports_sources(\"*\"),\n                     \"sources.cpp\": \"sources\"})\n        client.run(\"create . --name=hello --version=0.1\")\n        rrev = client.exported_recipe_revision()\n        client.run(\"upload hello/0.1 -r server0\")\n        # Ensure we uploaded it\n        assert re.search(r\"Uploading recipe 'hello/0.1#.*' \\(.*\\)\", client.out)\n        assert re.search(r\"Uploading package 'hello/0.1#.*' \\(.*\\)\", client.out)\n        client.run(\"remove * -c\")\n\n        # install from server0 that has the sources, upload to server1 (does not have the package)\n        # download the sources from server0\n        client.run(\"install --requires=hello/0.1@ -r server0\")\n        client.run(\"upload hello/0.1 -r server1\")\n        assert \"Sources downloaded from 'server0'\" in client.out\n\n        # install from server1 that has the sources, upload to server1\n        # Will not download sources, revision already in server\n        client.run(\"remove * -c\")\n        client.run(\"install --requires=hello/0.1@ -r server1\")\n        client.run(\"upload hello/0.1 -r server1\")\n        assert f\"'hello/0.1#{rrev}' already in server, skipping upload\" in client.out\n        assert \"Sources downloaded from 'server0'\" not in client.out\n\n        # install from server0 and build\n        # download sources from server0\n        client.run(\"remove * -c\")\n        client.run(\"install --requires=hello/0.1@ -r server0 --build='*'\")\n        assert \"Sources downloaded from 'server0'\" in client.out\n\n    def test_source_method_called_once(self):\n        \"\"\"\n        Test that the source() method will be executed just once, and the source code will\n        be shared for all the package builds.\n        \"\"\"\n\n        conanfile = textwrap.dedent('''\n            import os\n            from conan import ConanFile\n            from conan.tools.files import save\n\n            class ConanLib(ConanFile):\n\n                def source(self):\n                    save(self, os.path.join(self.source_folder, \"main.cpp\"), \"void main() {}\")\n                    self.output.info(\"Running source!\")\n            ''')\n\n        client = TestClient()\n        client.save({CONANFILE: conanfile})\n\n        client.run(\"create . --name=lib --version=1.0\")\n        assert \"Running source!\" in client.out\n\n        client.run(\"create . --name=lib --version=1.0\")\n        assert \"Running source!\" not in client.out\n\n        client.run(\"create . --name=lib --version=1.0 -s build_type=Debug\")\n        assert \"Running source!\" not in client.out\n\n    def test_source_method_called_again_if_left_dirty(self):\n        \"\"\"\n        If we fail in retreiving sources make sure the source() method will be called\n        next time we create\n        \"\"\"\n\n        conanfile = textwrap.dedent('''\n            import os\n            from conan import ConanFile\n\n            class ConanLib(ConanFile):\n\n                def source(self):\n                    self.output.info(\"Running source!\")\n                    assert False\n            ''')\n\n        client = TestClient(light=True)\n        client.save({CONANFILE: conanfile})\n\n        client.run(\"create . --name=lib --version=1.0\", assert_error=True)\n        assert \"Running source!\" in client.out\n\n        client.run(\"create . --name=lib --version=1.0\", assert_error=True)\n        assert \"Running source!\" in client.out\n        assert \"Source folder is corrupted, forcing removal\" in client.out\n\n\nclass TestSourceWithoutDefaultProfile:\n    # https://github.com/conan-io/conan/issues/12371\n    @pytest.fixture()\n    def client(self):\n        c = TestClient()\n        # The ``source()`` should still receive necessary configuration\n        c.save_home({\"global.conf\": \"tools.files.download:retry=MYCACHE\"})\n        # Make sure we don't have default profile\n        os.remove(os.path.join(c.cache_folder, \"profiles\", \"default\"))\n        return c\n\n    def test_source_without_default_profile(self, client):\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class Pkg(ConanFile):\n                def source(self):\n                    c = self.conf.get(\"tools.files.download:retry\")\n                    self.output.info(\"CACHE:{}!!\".format(c))\n                \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"source .\")\n        assert \"conanfile.py: Calling source()\" in client.out\n        assert \"CACHE:MYCACHE!!\" in client.out\n\n    def test_source_with_layout(self, client):\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.cmake import cmake_layout\n            class Pkg(ConanFile):\n                settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n                def layout(self):\n                    cmake_layout(self)\n                def source(self):\n                    c = self.conf.get(\"tools.files.download:retry\")\n                    self.output.info(\"CACHE:{}!!\".format(c))\n                \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"source .\")\n        assert \"conanfile.py: Calling source()\" in client.out\n        assert \"CACHE:MYCACHE!!\" in client.out\n\n\ndef test_source_python_requires():\n    c = TestClient(default_server_user=True)\n    c.save({\"conanfile.py\": GenConanfile(\"pytool\", \"0.1\")})\n    c.run(\"export . \")\n    c.run(\"upload * -r=default -c\")\n    c.run(\"remove * -c\")\n\n    c.save({\"conanfile.py\": GenConanfile().with_python_requires(\"pytool/0.1\")}, clean_first=True)\n    c.run(\"source . \")\n    assert \"pytool/0.1: Not found in local cache, looking in remotes\" in c.out\n    assert \"pytool/0.1: Downloaded recipe\" in c.out\n\n\n@pytest.mark.parametrize(\"attribute\", [\"info\", \"settings\", \"options\"])\ndef test_source_method_forbidden_attributes(attribute):\n    conanfile = textwrap.dedent(f\"\"\"\n    from conan import ConanFile\n    class Package(ConanFile):\n        def source(self):\n            self.output.info(self.{attribute})\n    \"\"\")\n    client = TestClient(light=True)\n    client.save({\"conanfile.py\": conanfile})\n\n    client.run(\"source .\", assert_error=True)\n    assert f\"'self.{attribute}' access in 'source()' method is forbidden\" in client.out\n"
  },
  {
    "path": "test/integration/command/test_audit.py",
    "content": "import json\nimport os\nimport platform\nimport sys\nfrom contextlib import contextmanager\n\nimport pytest\nfrom unittest.mock import patch, MagicMock\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.env import environment_update\nfrom conan.test.utils.tools import TestClient\n\n_sbom_zlib_1_2_11 = \"\"\"\n{\n  \"components\" : [ {\n    \"author\" : \"<Put your name here> <And your email here>\",\n    \"bom-ref\" : \"pkg:conan/zlib@1.2.11?rref=6754320047c5dd54830baaaf9fc733c4\",\n    \"description\" : \"<Description of zlib package here>\",\n    \"licenses\" : [ {\n      \"license\" : {\n        \"name\" : \"<Put the package license here>\"\n      }\n    } ],\n    \"name\" : \"zlib\",\n    \"purl\" : \"pkg:conan/zlib@1.2.11\",\n    \"type\" : \"library\",\n    \"version\" : \"1.2.11\"\n  } ],\n  \"dependencies\" : [ {\n    \"ref\" : \"pkg:conan/zlib@1.2.11?rref=6754320047c5dd54830baaaf9fc733c4\"\n  } ],\n  \"metadata\" : {\n    \"component\" : {\n      \"author\" : \"<Put your name here> <And your email here>\",\n      \"bom-ref\" : \"pkg:conan/zlib@1.2.11?rref=6754320047c5dd54830baaaf9fc733c4\",\n      \"name\" : \"zlib/1.2.11\",\n      \"type\" : \"library\"\n    },\n    \"timestamp\" : \"2025-06-10T08:13:11Z\",\n    \"tools\" : [ {\n      \"externalReferences\" : [ {\n        \"type\" : \"website\",\n        \"url\" : \"https://github.com/conan-io/conan\"\n      } ],\n      \"name\" : \"Conan-io\"\n    } ]\n  },\n  \"serialNumber\" : \"urn:uuid:4f7ce240-4c6d-4a87-bfb6-78d0fbc839e3\",\n  \"bomFormat\" : \"CycloneDX\",\n  \"specVersion\" : \"1.4\",\n  \"version\" : 1\n}\n\"\"\"\n\n\n@contextmanager\ndef proxy_response(status, data, retry_after=60):\n    with patch(\"conan.api.conan_api.ConanAPI._ApiHelpers.requester\") as conanRequesterMock:\n        return_status = MagicMock()\n        return_status.status_code = status\n        return_status.json = MagicMock(return_value=data)\n        return_status.headers = {\"retry-after\": retry_after}\n        conanRequesterMock.post = MagicMock(return_value=return_status)\n\n        yield conanRequesterMock, return_status\n\n\ndef test_conan_audit_proxy():\n    successful_response = {\n        \"data\": {\n            \"query\": {\n                \"vulnerabilities\": {\n                    \"totalCount\": 1,\n                    \"edges\": [\n                        {\n                            \"node\": {\n                                \"name\": \"CVE-2023-45853\",\n                                \"description\": \"Zip vulnerability\" + \"a\" * 90,  # Force wrapping\n                                \"severity\": \"Critical\",\n                                \"cvss\": {\n                                    \"preferredBaseScore\": 8.9\n                                },\n                                \"aliases\": [\n                                    \"CVE-2023-45853\",\n                                    \"JFSA-2023-000272529\"\n                                ],\n                                \"advisories\": [\n                                    {\n                                        \"name\": \"CVE-2023-45853\"\n                                    },\n                                    {\n                                        \"name\": \"JFSA-2023-000272529\"\n                                    }\n                                ],\n                                \"references\": [\n                                    \"https://pypi.org/project/pyminizip/#history\",\n                                ]\n                            }\n                        }\n                    ]\n                }\n            }\n        },\n        \"error\": None\n    }\n\n    tc = TestClient(light=True, default_server_user=True)\n\n    tc.save({\"conanfile.py\": GenConanfile(\"zlib\", \"1.2.11\"),\n             \"sbom.cdx.json\": _sbom_zlib_1_2_11})\n    tc.run(\"create . --lockfile-out=conan.lock\")\n    tc.run(\"upload * -c -r=default\")\n\n    tc.run(\"list * -r=default -f=json\", redirect_stdout=\"pkglist_remote.json\")\n\n    tc.run(\"list '*' -f=json\", redirect_stdout=\"pkglist.json\")\n\n    tc.run(\"audit list zlib/1.2.11\", assert_error=True)\n    assert \"Authentication required for the CVE provider: 'conancenter\" in tc.out\n\n    tc.run(\"audit provider auth conancenter --token=valid_token\")\n\n    with proxy_response(200, successful_response):\n        tc.run(\"audit list zlib/1.2.11\")\n        assert \"zlib/1.2.11 1 vulnerability found\" in tc.out\n\n        tc.run(\"audit list -l=pkglist.json\")\n        assert \"zlib/1.2.11 1 vulnerability found\" in tc.out\n\n        tc.run(\"audit list -l=pkglist_remote.json -r=default\")\n        assert \"zlib/1.2.11 1 vulnerability found\" in tc.out\n\n        tc.run(\"audit list --lockfile=conan.lock\")\n        assert \"zlib/1.2.11 1 vulnerability found\" in tc.out\n\n        tc.run(\"audit list --sbom=sbom.cdx.json\")\n        assert \"zlib/1.2.11 1 vulnerability found\" in tc.out\n\n        tc.run(\"audit scan --requires=zlib/1.2.11\")\n        assert \"zlib/1.2.11 1 vulnerability found\" in tc.out\n\n        tc.save({\"conanfile.txt\": \"[requires]\\nzlib/1.2.11\\n\"}, clean_first=True)\n        tc.run(\"audit scan\")\n        assert \"zlib/1.2.11 1 vulnerability found\" in tc.out\n\n        tc.run(\"audit scan . --requires=zlib/1.2.11\", assert_error=True)\n        assert \"--requires and --tool-requires arguments are incompatible with [path] '.' argument\" in tc.out\n\n        tc.run(\"audit list zlib/1.2.11 -f=html\")\n        assert \"CVE-2023-45853\" in tc.out\n\n    # Now some common errors, like rate limited or missing lib, but it should not fail!\n    with proxy_response(429, {\"error\": \"Rate limit exceeded\"}):\n        tc.run(\"audit list zlib/1.2.11\", assert_error=True)\n        assert \"You have exceeded the number of allowed requests\" in tc.out\n        assert \"The limit will reset in 1 minute\" in tc.out\n\n    with proxy_response(429, {\"error\": \"Rate limit exceeded\"}, retry_after=2 * 3600):\n        tc.run(\"audit list zlib/1.2.11\", assert_error=True)\n        assert \"You have exceeded the number of allowed requests\" in tc.out\n        assert \"The limit will reset in 2 hours and 0 minute\" in tc.out\n\n    with proxy_response(400, {\"error\": \"Not found\"}):\n        # Not finding a package should not be an error\n        tc.run(\"audit list zlib/1.2.11\")\n        assert \"Package 'zlib/1.2.11' not scanned: Not found.\" in tc.stdout\n\n    with proxy_response(403, {\"error\": \"Error not shown\"}):\n        tc.run(\"audit list zlib/1.2.11\", assert_error=True)\n        assert \"ERROR: Authentication error (403)\" in tc.out\n        assert \"Error not shown\" not in tc.out\n\n    with proxy_response(500, {\"error\": \"Internal error\"}):\n        tc.run(\"audit list zlib/1.2.11\", assert_error=True)\n        assert \"Internal server error (500)\" in tc.out\n\n    with proxy_response(405, {\"error\": \"Method not allowed\"}):\n        tc.run(\"audit list zlib/1.2.11\", assert_error=True)\n        assert \"Error in zlib/1.2.11 (405)\" in tc.out\n\n    tc.run(\"audit provider add myprivate --url=foo --type=private --token=valid_token\")\n\n    tc.run(\"audit provider list\")\n    assert \"(type: conan-center-proxy)\" in tc.out\n    assert \"(type: private)\" in tc.out\n\n    tc.run(\"audit provider remove conancenter\")\n    tc.run(\"audit list zlib/1.2.11\", assert_error=True)\n    assert (\"ERROR: Provider 'conancenter' not found. Please specify a valid provider name or add \"\n            \"it using: 'conan audit provider add conancenter --url=https://audit.conan.io/ \"\n            \"--type=conan-center-proxy --token=<token>'\") in tc.out\n    assert \"If you don't have a valid token, register at: https://audit.conan.io/register.\" in tc.out\n\n    if platform.system() != \"Windows\":\n        providers_stat = os.stat(os.path.join(tc.cache_folder, \"audit_providers.json\"))\n        # Assert that only the current user can read/write the file\n        assert providers_stat.st_uid == os.getuid()\n        assert providers_stat.st_gid == os.getgid()\n        assert providers_stat.st_mode & 0o777 == 0o600\n\n\ndef test_conan_audit_private():\n    successful_response = {\n        \"data\": {\n            \"query\": {\n                \"vulnerabilities\": {\n                    \"totalCount\": 1,\n                    \"edges\": [\n                        {\n                            \"node\": {\n                                \"name\": \"CVE-2023-45853\",\n                                \"description\": \"Zip vulnerability\",\n                                \"severity\": \"Critical\",\n                                \"cvss\": {\n                                    \"preferredBaseScore\": 8.9\n                                },\n                                \"aliases\": [\n                                    \"CVE-2023-45853\",\n                                    \"JFSA-2023-000272529\"\n                                ],\n                                \"withdrawn\": True,\n                                \"publishedAt\": \"Yesterday\",\n                                \"advisories\": [\n                                    {\n                                        \"name\": \"CVE-2023-45853\",\n                                        \"shortDescription\": \"Zip vulnerability (CVE)\",\n                                        \"severity\": \"Critical\"\n                                    },\n                                    {\n                                        \"name\": \"JFSA-2023-000272529\",\n                                        \"shortDescription\": \"Zip vulnerability (JFSA)\",\n                                        \"severity\": \"Moderate\",\n                                        \"impactReasons\": [\n                                            {\"name\": \"Reason 1\", \"isPositive\": True},\n                                            {\"name\": \"Reason 2\", \"isPositive\": False}\n                                        ]\n                                    }\n                                ],\n                                \"references\": [\n                                    \"https://pypi.org/project/pyminizip/#history\",\n                                ],\n                                \"vulnerablePackages\": {\n                                    \"totalCount\": 1,\n                                    \"edges\": [{\n                                        \"node\": {\"fixVersions\": [{\"version\": \"1.2.12\"}]}\n                                    }]\n                                }\n                            }\n                        }\n                    ]\n                }\n            }\n        }\n    }\n\n    tc = TestClient(light=True)\n\n    tc.save({\"conanfile.py\": GenConanfile(\"zlib\", \"1.2.11\"),\n             \"sbom.cdx.json\": _sbom_zlib_1_2_11})\n    tc.run(\"create . --lockfile-out=conan.lock\")\n\n    tc.run(\"list '*' -f=json\", redirect_stdout=\"pkglist.json\")\n\n    # TODO: If the CLI does not allow tokenless provider, should this case not be handled?\n    tc.run(\"audit provider add myprivate --url=foo --type=private --token=f\")\n    # Now, remove the token as if the user didn't set it manually in the json\n    providers = json.loads(tc.load_home(\"audit_providers.json\"))\n    providers[\"myprivate\"].pop(\"token\", None)\n    tc.save_home({\"audit_providers.json\": json.dumps(providers)})\n\n    tc.run(\"audit list zlib/1.2.11 -p=myprivate\", assert_error=True)\n    assert \"Missing authentication token for 'myprivate' provider\" in tc.out\n\n    tc.run(\"audit provider auth myprivate --token=valid_token\")\n\n    with proxy_response(200, successful_response):\n        tc.run(\"audit list zlib/1.2.11 -p=myprivate\")\n        assert \"zlib/1.2.11 1 vulnerability found\" in tc.out\n\n        tc.run(\"audit list -l=pkglist.json -p=myprivate\")\n        assert \"zlib/1.2.11 1 vulnerability found\" in tc.out\n\n        tc.run(\"audit list --lockfile=conan.lock -p=myprivate\")\n        assert \"zlib/1.2.11 1 vulnerability found\" in tc.out\n\n        tc.run(\"audit list --sbom=sbom.cdx.json -p=myprivate\")\n        assert \"zlib/1.2.11 1 vulnerability found\" in tc.out\n\n        tc.run(\"audit scan --requires=zlib/1.2.11  -p=myprivate\")\n        assert \"zlib/1.2.11 1 vulnerability found\" in tc.out\n\n        tc.run(\"audit list zlib/1.2.11 -p=myprivate -f=html\")\n        assert \"CVE-2023-45853\" in tc.out\n        assert \"Yesterday\" in tc.out\n        assert \"[WITHDRAWN]\" in tc.out\n        # Fixed version\n        assert \"1.2.12\" in tc.out\n        assert \"Zip vulnerability (JFSA)\" in tc.out\n        assert 'inherit;\">Reason 1</li>' in tc.out  # Positive impact\n        assert 'red;\">Reason 2</li>' in tc.out  # Negative impact\n\n    # Now some common errors, like rate limited or missing lib, but it should not fail!\n    with proxy_response(400, {\"errors\": [{\"message\": \"Ref not found\"}]}):\n        # Not finding a package should not be an error\n        tc.run(\"audit list zlib/1.2.11 -p=myprivate\")\n        assert \"Package 'zlib/1.2.11' not scanned: Not found.\" in tc.stdout\n\n    with proxy_response(403, {\"errors\": [{\"message\": \"Authentication error\"}]}):\n        tc.run(\"audit list zlib/1.2.11 -p=myprivate\")\n        assert \"Unknown error\" in tc.out\n\n    with proxy_response(500, {\"errors\": [{\"message\": \"Internal error\"}]}):\n        tc.run(\"audit list zlib/1.2.11 -p=myprivate\")\n        assert \"Unknown error\" in tc.out\n\n    with proxy_response(405, {\"errors\": [{\"message\": \"Method not allowed\"}]}):\n        tc.run(\"audit list zlib/1.2.11 -p=myprivate\")\n        assert \"Unknown error\" in tc.out\n\n    with proxy_response(404, {\"errors\": [{\"message\": \"Not found\"}]}):\n        tc.run(\"audit list zlib/1.2.11 -p=myprivate\")\n        assert \"An error occurred while connecting to the 'myprivate' provider\" in tc.out\n\n\n@pytest.mark.skipif(sys.version_info < (3, 10),\n                    reason=\"Strict Base64 validation introduced in Python 3.10\")\ndef test_conan_audit_corrupted_token():\n    tc = TestClient(light=True)\n\n    json_path = os.path.join(tc.cache_folder, \"audit_providers.json\")\n    with open(json_path, \"r\") as f:\n        data = json.load(f)\n\n    # this is not a valid base64 string and will raise an exception\n    data[\"conancenter\"][\"token\"] = \"corrupted_token\"\n\n    with open(json_path, \"w\") as f:\n        json.dump(data, f)\n    tc.run(\"audit list zlib/1.2.11\", assert_error=True)\n    assert \"Invalid token format for provider 'conancenter'. The token might be corrupt.\" in tc.out\n\n\ndef test_audit_list_conflicting_args():\n    tc = TestClient(light=True)\n    tc.save({\"pkglist.json\": '{\"Local Cache\": {\"zlib/1.2.11\": {}}}'})\n    tc.run(\"audit list zlib/1.2.11 -l=pkglist.json\", assert_error=True)\n    assert \"argument -l/--list: not allowed with argument reference\" in tc.out\n\n\ndef test_audit_provider_add_missing_url():\n    tc = TestClient(light=True)\n    tc.run(\"audit provider add myprivate --type=private --token=valid_token\", assert_error=True)\n    assert \"Name, URL and type are required to add a provider\" in tc.out\n\n\ndef test_audit_provider_remove_nonexistent():\n    tc = TestClient(light=True)\n    tc.run(\"audit provider remove nonexistingprovider\", assert_error=True)\n    assert \"Provider 'nonexistingprovider' not found\" in tc.out\n\n\ndef test_audit_list_missing_arguments():\n    tc = TestClient(light=True)\n    tc.run(\"audit list\", assert_error=True)\n    assert \"one of the arguments reference\" in tc.out\n\n\ndef test_audit_provider_env_credentials_with_proxy(monkeypatch):\n    tc = TestClient(light=True)\n    # Authenticate the provider with an old token to verify that the env variable overrides it\n    tc.run(\"audit provider auth conancenter --token=old_token\")\n\n    captured_headers = {}\n\n    def fake_post(url, headers, json):  # noqa\n        # Capture the headers used in the request\n        captured_headers.update(headers)\n        response = MagicMock()\n        response.status_code = 200\n        response.json.return_value = {\n            \"data\": {\"query\": {\"vulnerabilities\": {\"totalCount\": 0, \"edges\": []}}}\n        }\n        response.headers = {\"retry-after\": 60}\n        return response\n\n    with environment_update({\"CONAN_AUDIT_PROVIDER_TOKEN_CONANCENTER\": \"env_token_value\"}):\n        with patch(\"conan.api.conan_api.ConanAPI._ApiHelpers.requester\",\n                   new_callable=MagicMock) as requester_mock:\n            requester_mock.post = fake_post\n            tc.run(\"audit list zlib/1.2.11\")\n\n    # Verify that the Authorization header uses the token from the environment variable\n    assert captured_headers.get(\"Authorization\") == \"Bearer env_token_value\"\n\n\ndef test_audit_global_error_exception():\n    \"\"\"\n    Test that a global error returned by the provider results in ConanException\n    raised by the formatter, using the 'details' field.\n    \"\"\"\n    tc = TestClient(light=True)\n    tc.run(\"audit provider auth conancenter --token=valid_token\")\n\n    mock_provider_result = {\n        \"data\": {},\n        \"conan_error\": \"Fatal error.\"\n    }\n\n    with patch(\"conan.api.conan_api.AuditAPI.list\", return_value=mock_provider_result):\n        tc.run(\"audit list zlib/1.2.11\", assert_error=True)\n        assert \"ERROR: Fatal error.\" in tc.out\n\n        tc.run(\"audit list zlib/1.2.11 -f json\", assert_error=True)\n        assert \"ERROR: Fatal error.\" in tc.out\n\n        tc.run(\"audit list zlib/1.2.11 -f html\", assert_error=True)\n        assert \"ERROR: Fatal error.\" in tc.out\n\n\n@pytest.mark.parametrize(\"severity_level, threshold, should_fail\", [\n    (1.0, None, False),\n    (8.9, None, False),\n    (9.0, None, True),\n    (9.1, None, True),\n    (5.0, 5.1, False),\n    (5.1, 5.1, True),\n    (5.2, 5.1, True),\n    (9.0, 11.0, False),\n])\ndef test_audit_scan_threshold_error(severity_level, threshold, should_fail):\n    \"\"\"In case the severity level is equal or higher than the found for a CVE,\n       the command should output the information as usual, and exit with non-success code error.\n    \"\"\"\n    successful_response = {\n        \"data\": {\n            \"query\": {\n                \"vulnerabilities\": {\n                    \"totalCount\": 1,\n                    \"edges\": [\n                        {\n                            \"node\": {\n                                \"name\": \"CVE-2023-45853\",\n                                \"description\": \"Zip vulnerability\",\n                                \"severity\": \"Critical\",\n                                \"cvss\": {\n                                    \"preferredBaseScore\": severity_level\n                                },\n                                \"aliases\": [\n                                    \"CVE-2023-45853\",\n                                    \"JFSA-2023-000272529\"\n                                ],\n                                \"advisories\": [\n                                    {\n                                        \"name\": \"CVE-2023-45853\"\n                                    },\n                                    {\n                                        \"name\": \"JFSA-2023-000272529\"\n                                    }\n                                ],\n                                \"references\": [\n                                    \"https://pypi.org/project/pyminizip/#history\",\n                                ]\n                            }\n                        }\n                    ]\n                }\n            }\n        }\n    }\n\n    tc = TestClient(light=True)\n\n    tc.save({\"conanfile.py\": GenConanfile(\"foobar\", \"0.1.0\")})\n    tc.run(\"export .\")\n    tc.run(\"audit provider auth conancenter --token=valid_token\")\n\n    with proxy_response(200, successful_response):\n        severity_param = \"\" if threshold is None else f\"-sl {threshold}\"\n        tc.run(f\"audit scan --requires=foobar/0.1.0 {severity_param}\", assert_error=should_fail)\n        assert \"foobar/0.1.0 1 vulnerability found\" in tc.out\n        assert f\"CVSS: {severity_level}\" in tc.out\n        if should_fail:\n            if threshold is None:\n                threshold = \"9.0\"\n            assert f\"ERROR: The package foobar/0.1.0 has a CVSS score {severity_level} and exceeded the threshold severity level {threshold}\" in tc.out\n\n\ndef test_parse_error_crash_when_no_edges():\n    from conan.cli.commands.audit import _parse_error_threshold\n\n    scan_result = {\n        \"data\": {\n            # this used to crash because dav1d not having vulnerabilities field\n            \"dav1d/1.4.3\": {\"error\": {\"details\": \"Package 'dav1d/1.4.3' not scanned: Not found.\"}},\n            \"zlib/1.2.11\": {\n                \"vulnerabilities\": {\n                    \"totalCount\": 1,\n                    \"edges\": [\n                        {\"node\": {\"cvss\": {\"preferredBaseScore\": 7.0}}}\n                    ]\n                }\n            }\n        }\n    }\n\n    _parse_error_threshold(scan_result, error_level=5.0)\n    assert \"conan_error\" in scan_result\n    assert \"zlib/1.2.11\" in scan_result[\"conan_error\"]\n    assert \"7.0\" in scan_result[\"conan_error\"]\n\n\n@pytest.mark.parametrize(\"package_context\", [\"build\", \"host\"])\n@pytest.mark.parametrize(\"filter_context\", [\"build\", \"host\", None])\ndef test_audit_scan_context_filter(package_context, filter_context):\n    tc = TestClient(light=True)\n\n    tc.save({\"conanfile.py\": GenConanfile(\"zlib\", \"1.2.11\")})\n    tc.run(\"export .\")\n    tc.run(\"audit provider auth conancenter --token=valid_token\")\n\n    requires = \"requires\" if package_context == \"host\" else \"tool-requires\"\n    context = \"\" if filter_context is None else f\"--context={filter_context}\"\n\n    with proxy_response(200, {}):\n        tc.run(f\"audit scan --{requires}=zlib/1.2.11 {context}\")\n        if filter_context is None or filter_context == package_context:\n            assert \"Requesting vulnerability info for: zlib/1.2.11\" in tc.out\n        else:\n            assert \"Requesting vulnerability info for: zlib/1.2.11\" not in tc.out\n\n\nclass TestAuditApiBranchouts:\n    def test_audit_load_provider_default(self):\n        tc = TestClient(light=True)\n        tc.run(\"audit provider list -f=json\", redirect_stdout=\"before.json\")\n        os.unlink(os.path.join(tc.cache_folder, \"audit_providers.json\"))\n        tc.run(\"audit provider list -f=json\", redirect_stdout=\"after.json\")\n        before = json.loads(tc.load(\"before.json\"))\n        after = json.loads(tc.load(\"after.json\"))\n        assert after[0][\"url\"] == \"https://audit.conan.io/\"\n        after[0][\"url\"] = before[0][\"url\"]\n        # And the rest is the same\n        assert before == after\n\n    def test_audit_provider_add_duplicate(self):\n        tc = TestClient(light=True)\n        tc.run(\"audit provider add conancenter --url=foo --type=conan-center-proxy --token=valid_token\",\n               assert_error=True)\n        assert \"Provider 'conancenter' already exists\" in tc.out\n\n\nclass TestAuditScanBranchouts:\n    def test_audit_scan_graph_error(self):\n        tc = TestClient(light=True)\n        tc.save({\"bar/conanfile.py\": GenConanfile(\"bar\", \"1.0\"),\n                 \"foo/conanfile.py\": GenConanfile(\"foo\", \"1.0\").with_provides(\"bar\")})\n        tc.run(\"export bar\")\n        tc.run(\"export foo\")\n        tc.run(\"audit scan --requires=foo/1.0 --requires=bar/1.0\", assert_error=True)\n        assert \"Provide Conflict\" in tc.out\n\n\nclass TestAuditListBranchouts:\n    def test_audit_list_pkglist_empty(self):\n        tc = TestClient(light=True)\n        tc.save({\"pkglist.json\": '{\"Local Cache\": {}}'})\n        tc.run(\"audit provider auth conancenter --token=valid_token\")\n        tc.run(\"audit list -l=pkglist.json\")\n        assert \"Nothing to list\" in tc.out\n        assert \"Total vulnerabilities found: 0\" in tc.out\n\n    def test_audit_list_sbom_non_cyclone(self):\n        tc = TestClient(light=True)\n        tc.save({\"sbom.json\": '{\"bomFormat\": \"SPDX\"}'})\n        tc.run(\"audit list --sbom=sbom.json\", assert_error=True)\n        assert \"Unsupported SBOM format, only CycloneDX is supported\" in tc.out\n\n\nclass TestAuditProviderBranchouts:\n    def test_provider_json_format(self):\n        tc = TestClient(light=True)\n        tc.run(\"audit provider list -f=json\", redirect_stdout=\"out.json\")\n        out = json.loads(tc.load(\"out.json\"))\n        assert len(out) == 1\n\n    def test_provider_add_spaces_in_name(self):\n        tc = TestClient(light=True)\n        tc.run('audit provider add \"my private\" --url=foo --type=private --token=valid_token',\n               assert_error=True)\n        assert \"Name cannot contain spaces\" in tc.out\n\n    def test_provider_add_user_input_token(self):\n        tc = TestClient(light=True, inputs=[\"valid_token\"])\n        tc.run('audit provider add private --url=foo --type=private')\n        providers = json.loads(tc.load_home(\"audit_providers.json\"))\n        assert providers[\"private\"][\"token\"] == 'Z1RWYEZUWmBeT2U='\n\n    def test_provider_remove_no_name(self):\n        tc = TestClient(light=True)\n        tc.run('audit provider remove \"\"', assert_error=True)\n        assert \"Name required to remove a provider\" in tc.out\n\n    def test_provider_auth_no_name(self):\n        tc = TestClient(light=True)\n        tc.run('audit provider auth \"\"', assert_error=True)\n        assert \"Name is required to authenticate on a provider\" in tc.out\n\n    def test_provider_auth_user_input_token(self):\n        tc = TestClient(light=True, inputs=[\"valid_token\"])\n        tc.run('audit provider auth conancenter')\n        providers = json.loads(tc.load_home(\"audit_providers.json\"))\n        assert providers[\"conancenter\"][\"token\"] == 'Z1RWYEZUWmBeT2U='\n"
  },
  {
    "path": "test/integration/command/test_build.py",
    "content": "import json\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_build_cmd_deploy_generators():\n    \"\"\"\n    Test that \"conan build --deployer/--generators\" args work\n    \"\"\"\n    c = TestClient()\n    c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"1.0\"),\n            \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_settings(\"build_type\")\n                                                          .with_requires(\"dep/1.0\")})\n    c.run(\"create dep\")\n    c.run(\"build pkg --deployer=full_deploy --deployer-folder=./myfolder -g=CMakeDeps\")\n    cmake = c.load(\"pkg/dep-release-data.cmake\")\n    current_folder = c.current_folder.replace(\"\\\\\", \"/\")\n    path = f'{current_folder}/myfolder/full_deploy/host/dep/1.0'\n    assert f'set(dep_PACKAGE_FOLDER_RELEASE \"{path}\")' in cmake\n\n\ndef test_build_output_json():\n    \"\"\"\n    The build command should have the --format=json option.\n    \"\"\"\n    _OUTPUT_FILE = \"output.json\"\n\n    client = TestClient()\n    conanfile = GenConanfile()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"build --format=json\", redirect_stdout=_OUTPUT_FILE)\n    output = json.loads(client.load(_OUTPUT_FILE))\n\n    assert \"graph\" in output\n    assert \"nodes\" in output[\"graph\"]\n"
  },
  {
    "path": "test/integration/command/test_forced_download_source.py",
    "content": "import json\nimport os\nimport textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.fixture()\ndef client():\n    c = TestClient(default_server_user=True)\n    dep = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Dep(ConanFile):\n            name = \"dep\"\n            version = \"0.1\"\n            def source(self):\n                self.output.info(\"RUNNING SOURCE!!\")\n            \"\"\")\n\n    c.save({\"dep/conanfile.py\": dep})\n    c.run(\"create dep\")\n    c.run(\"upload * -c -r=default\")\n    c.run(\"remove * -c\")\n    return c\n\n\ndef test_install(client):\n    client.run(\"install --requires=dep/0.1\")\n    assert \"RUNNING SOURCE\" not in client.out\n    client.run(\"install --requires=dep/0.1 -c tools.build:download_source=True --format=json\")\n    assert \"RUNNING SOURCE\" in client.out\n    graph = json.loads(client.stdout)\n    zlib = graph[\"graph\"][\"nodes\"][\"1\"]\n    assert os.path.exists(zlib[\"source_folder\"])\n    client.run(\"install --requires=dep/0.1 -c tools.build:download_source=True --format=json\")\n    assert \"RUNNING SOURCE\" not in client.out\n    graph = json.loads(client.stdout)\n    zlib = graph[\"graph\"][\"nodes\"][\"1\"]\n    assert os.path.exists(zlib[\"source_folder\"])\n\n\ndef test_info(client):\n    client.run(\"graph info --requires=dep/0.1\")\n    assert \"RUNNING SOURCE\" not in client.out\n    # Even if the package is to be built, it shouldn't download sources unless the conf is defined\n    client.run(\"graph info --requires=dep/0.1 --build=dep*\")\n    assert \"RUNNING SOURCE\" not in client.out\n    client.run(\"graph info --requires=dep/0.1 -c tools.build:download_source=True\")\n    assert \"RUNNING SOURCE\" in client.out\n    client.run(\"graph info --requires=dep/0.1 -c tools.build:download_source=True\")\n    assert \"RUNNING SOURCE\" not in client.out\n\n\ndef test_info_editable():\n    \"\"\" graph info for editable shouldn't crash, but it also shoudn't do anythin\n    # https://github.com/conan-io/conan/issues/15003\n    \"\"\"\n    c = TestClient()\n    dep = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Dep(ConanFile):\n            name = \"dep\"\n            version = \"0.1\"\n\n            def source(self):\n                self.output.info(\"RUNNING SOURCE!!\")\n            \"\"\")\n\n    c.save({\"conanfile.py\": dep})\n    c.run(\"editable add .\")\n    c.run(\"graph info --requires=dep/0.1\")\n    assert \"RUNNING SOURCE\" not in c.out\n    c.run(\"graph info --requires=dep/0.1 -c tools.build:download_source=True\")\n    assert \"RUNNING SOURCE\" not in c.out  # BUT it doesn't crash, it used to crash\n\n\ndef test_build_editable_with_download_source():\n    \"\"\" conan build with -b=editable and tools.build:download_source=True should not crash\n    # https://github.com/conan-io/conan/issues/19757\n    \"\"\"\n    c = TestClient()\n    liba = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class LibA(ConanFile):\n            name = \"liba\"\n            version = \"0.1\"\n\n            def source(self):\n                self.output.info(\"RUNNING SOURCE!!\")\n        \"\"\")\n    consumer = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Consumer(ConanFile):\n            requires = \"liba/0.1\"\n        \"\"\")\n\n    c.save({\"liba/conanfile.py\": liba,\n            \"consumer/conanfile.py\": consumer})\n    c.run(\"editable add liba\")\n    c.run(\"build consumer -b=editable -c tools.build:download_source=True\")\n    assert \"RUNNING SOURCE\" not in c.out\n"
  },
  {
    "path": "test/integration/command/test_graph_find_binaries.py",
    "content": "import json\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestFilterProfile:\n    @pytest.fixture()\n    def client(self):\n        c = TestClient()\n        c.save({\"lib/conanfile.py\": GenConanfile(\"lib\", \"1.0\").with_settings(\"os\", \"build_type\")\n               .with_shared_option()})\n        c.run(\"create lib -s os=Linux\")\n        c.run(\"create lib -s os=Windows\")\n        c.run(\"create lib -s os=Windows -o *:shared=True\")\n        return c\n\n    def test_exact_match(self, client):\n        c = client\n        c.run(\"graph explain --requires=lib/1.0 --missing=lib/1.0 -s os=Windows\")\n        expected = textwrap.dedent(\"\"\"\\\n            settings: Windows, Release\n            options: shared=False\n            diff\n              explanation: This binary is an exact match for the defined inputs\n            \"\"\")\n        assert textwrap.indent(expected, \"      \") in c.out\n        c.run(\"graph explain --requires=lib/1.0 --missing=lib/1.0 -s os=Windows --format=json\")\n        closest = json.loads(c.stdout)[\"closest_binaries\"]\n        revisions = closest[\"lib/1.0\"][\"revisions\"]\n        pkgs = revisions[\"5313a980ea0c56baeb582c510d6d9fbc\"][\"packages\"]\n        assert len(pkgs) == 1\n        pkg1 = pkgs[\"3d714b452400b3c3d6a964f42d5ec5004a6f22dc\"]\n        assert pkg1[\"diff\"][\"platform\"] == {}\n        assert pkg1[\"diff\"][\"settings\"] == {}\n        assert pkg1[\"diff\"][\"options\"] == {}\n        assert pkg1[\"diff\"][\"dependencies\"] == {}\n        assert pkg1[\"diff\"][\"explanation\"] == \"This binary is an exact match for the defined inputs\"\n\n    def test_settings_incomplete(self, client):\n        c = client\n        c.save({\"windows\": \"[settings]\\nos=Windows\"})\n        c.run(\"graph explain --requires=lib/1.0 -pr windows\")\n        expected = textwrap.dedent(\"\"\"\\\n            settings: Windows, Release\n            options: shared=False\n            diff\n              settings\n                expected: build_type=None\n                existing: build_type=Release\n              explanation: This binary was built with different settings.\n            \"\"\")\n        assert textwrap.indent(expected, \"      \") in c.out\n        c.run(\"graph explain --requires=lib/1.0 -pr windows --format=json\")\n        closest = json.loads(c.stdout)[\"closest_binaries\"]\n        revisions = closest[\"lib/1.0\"][\"revisions\"]\n        pkgs = revisions[\"5313a980ea0c56baeb582c510d6d9fbc\"][\"packages\"]\n        assert len(pkgs) == 1\n        pkg1 = pkgs[\"3d714b452400b3c3d6a964f42d5ec5004a6f22dc\"]\n        assert pkg1[\"diff\"][\"platform\"] == {}\n        assert pkg1[\"diff\"][\"settings\"] == {'existing': ['build_type=Release'],\n                                            'expected': ['build_type=None']}\n        assert pkg1[\"diff\"][\"options\"] == {}\n        assert pkg1[\"diff\"][\"dependencies\"] == {}\n        assert pkg1[\"diff\"][\"explanation\"] == \"This binary was built with different settings.\"\n\n    def test_settings_with_option(self, client):\n        c = client\n        c.save({\"windows\": \"[settings]\\nos=Windows\\n[options]\\n*:shared=True\"})\n        c.run(\"graph explain --requires=lib/1.0 -pr windows\")\n        expected = textwrap.dedent(\"\"\"\\\n            settings: Windows, Release\n            options: shared=True\n            diff\n              settings\n                expected: build_type=None\n                existing: build_type=Release\n              explanation: This binary was built with different settings.\n            \"\"\")\n        assert textwrap.indent(expected, \"      \") in c.out\n\n    def test_different_option(self, client):\n        # We find 1 closest match in Linux static\n        c = client\n        c.save({\"linux\": \"[settings]\\nos=Linux\\nbuild_type=Release\\n[options]\\n*:shared=True\"})\n        c.run(\"graph explain --requires=lib/1.0 -pr linux\")\n        expected = textwrap.dedent(\"\"\"\\\n            remote: Local Cache\n            settings: Linux, Release\n            options: shared=False\n            diff\n              options\n                expected: shared=True\n                existing: shared=False\n              explanation: This binary was built with the same settings, but different options\n            \"\"\")\n        assert textwrap.indent(expected, \"      \") in c.out\n        c.run(\"graph explain --requires=lib/1.0 -pr linux --format=json\")\n        closest = json.loads(c.stdout)[\"closest_binaries\"]\n        revisions = closest[\"lib/1.0\"][\"revisions\"]\n        pkgs = revisions[\"5313a980ea0c56baeb582c510d6d9fbc\"][\"packages\"]\n        assert len(pkgs) == 1\n        pkg1 = pkgs[\"499989797d9192081b8f16f7d797b107a2edd8da\"]\n        assert pkg1[\"diff\"][\"platform\"] == {}\n        assert pkg1[\"diff\"][\"settings\"] == {}\n        assert pkg1[\"diff\"][\"options\"] == {'existing': ['shared=False'], 'expected': ['shared=True']}\n        assert pkg1[\"diff\"][\"dependencies\"] == {}\n        assert pkg1[\"diff\"][\"explanation\"] == \"This binary was built with the same settings, \" \\\n                                              \"but different options\"\n\n    def test_different_option_none(self):\n        # We find 1 closest match in Linux static\n        c = TestClient()\n        c.save({\"conanfile.py\": GenConanfile(\"lib\", \"1.0\").with_option(\"opt\", [None, 1])})\n        c.run(\"create .\")\n        c.run(\"graph explain --requires=lib/1.0 -o *:opt=1\")\n        expected = textwrap.dedent(\"\"\"\\\n            remote: Local Cache\n            diff\n              options\n                expected: opt=1\n                existing: opt=None\n              explanation: This binary was built with the same settings, but different options\n            \"\"\")\n        assert textwrap.indent(expected, \"      \") in c.out\n\n        c.run(\"remove * -c\")\n        c.run(\"create . -o *:opt=1\")\n        c.run(\"graph explain --requires=lib/1.0\")\n        expected = textwrap.dedent(\"\"\"\\\n            remote: Local Cache\n            options: opt=1\n            diff\n              options\n                expected: opt=None\n                existing: opt=1\n              explanation: This binary was built with the same settings, but different options\n            \"\"\")\n        assert textwrap.indent(expected, \"      \") in c.out\n\n    def test_different_setting(self, client):\n        # We find 1 closest match in Linux static\n        c = client\n        c.save({\"windows\": \"[settings]\\nos=Windows\\nbuild_type=Debug\\n[options]\\n*:shared=True\"})\n        c.run(\"graph explain --requires=lib/1.0 -pr windows\")\n        expected = textwrap.dedent(\"\"\"\\\n            remote: Local Cache\n            settings: Windows, Release\n            options: shared=True\n            diff\n              settings\n                expected: build_type=Debug\n                existing: build_type=Release\n              explanation: This binary was built with different settings.\n            \"\"\")\n        assert textwrap.indent(expected, \"      \") in c.out\n        c.run(\"graph explain --requires=lib/1.0 -pr windows --format=json\")\n        closest = json.loads(c.stdout)[\"closest_binaries\"]\n        revisions = closest[\"lib/1.0\"][\"revisions\"]\n        pkgs = revisions[\"5313a980ea0c56baeb582c510d6d9fbc\"][\"packages\"]\n        assert len(pkgs) == 1\n        pkg1 = pkgs[\"c2dd2d51b5074bdb5b7d717929372de09830017b\"]\n        assert pkg1[\"diff\"][\"platform\"] == {}\n        assert pkg1[\"diff\"][\"settings\"] == {'existing': ['build_type=Release'],\n                                            'expected': ['build_type=Debug']}\n        assert pkg1[\"diff\"][\"options\"] == {}\n        assert pkg1[\"diff\"][\"dependencies\"] == {}\n        assert pkg1[\"diff\"][\"explanation\"] == \"This binary was built with different settings.\"\n\n    def test_different_settings_target(self):\n        c = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\\\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                name = \"tool\"\n                version = \"1.0\"\n                def package_id(self):\n                    self.info.settings_target = self.settings_target.copy()\n                    self.info.settings_target.constrained([\"os\"])\n                \"\"\")\n        c.save({\"conanfile.py\": conanfile})\n        c.run(\"create . --build-require -s:b os=Windows -s:h os=Linux\")\n\n        c.run(\"graph explain --tool-requires=tool/1.0 -s:b os=Windows -s:h os=Macos\")\n        expected = textwrap.dedent(\"\"\"\\\n            remote: Local Cache\n            settings_target: os=Linux\n            diff\n              settings_target\n                expected: os=Macos\n                existing: os=Linux\n              explanation: This binary was built with different settings_target.\n            \"\"\")\n        assert textwrap.indent(expected, \"      \") in c.out\n        c.run(\"graph explain --tool-requires=tool/1.0 -s:b os=Windows -s:h os=Macos --format=json\")\n        closest = json.loads(c.stdout)[\"closest_binaries\"]\n        revisions = closest[\"tool/1.0\"][\"revisions\"]\n        pkgs = revisions[\"4cc4b286a46dc2ed188d8c417eadb4e6\"][\"packages\"]\n        assert len(pkgs) == 1\n        pkg1 = pkgs[\"d66135125c07cc240b8d6adda090b76d60341205\"]\n        assert pkg1[\"diff\"][\"platform\"] == {}\n        assert pkg1[\"diff\"][\"settings_target\"] == {'existing': ['os=Linux'],\n                                                   'expected': ['os=Macos']}\n        assert pkg1[\"diff\"][\"options\"] == {}\n        assert pkg1[\"diff\"][\"dependencies\"] == {}\n        assert pkg1[\"diff\"][\"explanation\"] == \"This binary was built with different settings_target.\"\n\n    def test_different_platform(self, client):\n        # We find closest match in other platforms\n        c = client\n        c.save({\"macos\": \"[settings]\\nos=Macos\\nbuild_type=Release\\n[options]\\n*:shared=True\"})\n        c.run(\"graph explain --requires=lib/1.0 -pr macos\")\n        expected = textwrap.dedent(\"\"\"\\\n            remote: Local Cache\n            settings: Windows, Release\n            options: shared=True\n            diff\n              platform\n                expected: os=Macos\n                existing: os=Windows\n              explanation: This binary belongs to another OS or Architecture, highly incompatible.\n            \"\"\")\n        assert textwrap.indent(expected, \"      \") in c.out\n        c.run(\"graph explain --requires=lib/1.0 -pr macos --format=json\")\n        closest = json.loads(c.stdout)[\"closest_binaries\"]\n        revisions = closest[\"lib/1.0\"][\"revisions\"]\n        pkgs = revisions[\"5313a980ea0c56baeb582c510d6d9fbc\"][\"packages\"]\n        assert len(pkgs) == 1\n        pkg1 = pkgs[\"c2dd2d51b5074bdb5b7d717929372de09830017b\"]\n        assert pkg1[\"diff\"][\"platform\"] == {'existing': ['os=Windows'], 'expected': ['os=Macos']}\n        assert pkg1[\"diff\"][\"settings\"] == {}\n        assert pkg1[\"diff\"][\"options\"] == {}\n        assert pkg1[\"diff\"][\"dependencies\"] == {}\n        assert pkg1[\"diff\"][\"explanation\"] == \"This binary belongs to another OS or Architecture, \" \\\n                                              \"highly incompatible.\"\n\n    def test_different_conf(self, client):\n        # We find closest match in other platforms\n        c = client\n        c.save_home({\"global.conf\": \"tools.info.package_id:confs=['user.foo:bar']\"})\n        c.run(\"graph explain --requires=lib/1.0 -c user.foo:bar=42 -s os=Linux\")\n        expected = textwrap.dedent(\"\"\"\\\n            remote: Local Cache\n            settings: Linux, Release\n            options: shared=False\n            diff\n              confs\n                expected: user.foo:bar=42\n                existing: user.foo:bar=None\n              explanation: This binary has same settings, options and dependencies, but different confs\n            \"\"\")\n        assert textwrap.indent(expected, \"      \") in c.out\n        c.run(\"graph explain --requires=lib/1.0 -c user.foo:bar=42 -s os=Linux -f=json\")\n        closest = json.loads(c.stdout)[\"closest_binaries\"]\n        revisions = closest[\"lib/1.0\"][\"revisions\"]\n        pkgs = revisions[\"5313a980ea0c56baeb582c510d6d9fbc\"][\"packages\"]\n        assert len(pkgs) == 1\n        pkg1 = pkgs[\"499989797d9192081b8f16f7d797b107a2edd8da\"]\n        assert pkg1[\"diff\"][\"platform\"] == {}\n        assert pkg1[\"diff\"][\"settings\"] == {}\n        assert pkg1[\"diff\"][\"options\"] == {}\n        assert pkg1[\"diff\"][\"dependencies\"] == {}\n        assert pkg1[\"diff\"][\"confs\"] == {\"expected\": [\"user.foo:bar=42\"],\n                                         \"existing\": [\"user.foo:bar=None\"]}\n        assert pkg1[\"diff\"][\"explanation\"] == \"This binary has same settings, options and \" \\\n                                              \"dependencies, but different confs\"\n\n\nclass TestMissingBinaryDeps:\n    @pytest.fixture()\n    def client(self):\n        c = TestClient()\n        c.save({\"dep/conanfile.py\": GenConanfile(\"dep\").with_settings(\"os\"),\n                \"lib/conanfile.py\": GenConanfile(\"lib\", \"1.0\").with_settings(\"os\")\n               .with_requires(\"dep/[>=1.0]\")})\n        c.run(\"create dep --version=1.0 -s os=Linux\")\n        c.run(\"create lib -s os=Linux\")\n        c.run(\"create dep --version=2.0 -s os=Linux\")\n        return c\n\n    def test_other_platform(self, client):\n        c = client\n        c.run(\"install --requires=lib/1.0 -s os=Windows\", assert_error=True)\n        assert \"ERROR: Missing prebuilt package for 'dep/2.0', 'lib/1.0'\" in c.out\n        # We use the --missing=lib/1.0 to specify we want this binary and not dep/2.0\n        c.run(\"graph explain --requires=lib/1.0 --missing=lib/1.0 -s os=Windows\")\n        expected = textwrap.dedent(\"\"\"\\\n            settings: Linux\n            requires: dep/1.Y.Z\n            diff\n              platform\n                expected: os=Windows\n                existing: os=Linux\n              dependencies\n                expected: dep/2.Y.Z\n                existing: dep/1.Y.Z\n              explanation: This binary belongs to another OS or Architecture, highly incompatible.\n            \"\"\")\n        assert textwrap.indent(expected, \"      \") in c.out\n\n    def test_other_dependencies(self, client):\n        c = client\n        c.run(\"install --requires=lib/1.0 -s os=Linux\", assert_error=True)\n        assert \"ERROR: Missing prebuilt package for 'lib/1.0'\" in c.out\n        c.run(\"graph explain --requires=lib/1.0 -s os=Linux\")\n        expected = textwrap.dedent(\"\"\"\\\n            settings: Linux\n            requires: dep/1.Y.Z\n            diff\n              dependencies\n                expected: dep/2.Y.Z\n                existing: dep/1.Y.Z\n              explanation: This binary has same settings and options, but different dependencies\n               \"\"\")\n        assert textwrap.indent(expected, \"      \") in c.out\n\n    def test_different_python_requires(self):\n        c = TestClient(light=True)\n        c.save({\"tool/conanfile.py\": GenConanfile(\"tool\"),\n                \"lib/conanfile.py\": GenConanfile(\"lib\", \"1.0\").with_python_requires(\"tool/[>=1.0]\")})\n        c.run(\"create tool --version=1.0\")\n        c.run(\"create lib\")\n        c.run(\"create tool --version=2.0\")\n        c.run(\"graph explain --requires=lib/1.0\")\n        expected = textwrap.dedent(\"\"\"\\\n            remote: Local Cache\n            python_requires: tool/1.0.Z\n            diff\n              python_requires\n                expected: tool/2.0.Z\n                existing: tool/1.0.Z\n              explanation: This binary has same settings, options and dependencies, but different python_requires\n            \"\"\")\n        assert textwrap.indent(expected, \"      \") in c.out\n        c.run(\"graph explain --requires=lib/1.0 -s os=Linux --format=json\")\n        closest = json.loads(c.stdout)[\"closest_binaries\"]\n        revisions = closest[\"lib/1.0\"][\"revisions\"]\n        pkgs = revisions[\"7bf17caa5bf9d2ed1dd8b337e9623fc0\"][\"packages\"]\n        assert len(pkgs) == 1\n        pkg1 = pkgs[\"5ccdb706197ca94edc0ecee9ef0d0b11b887d937\"]\n        assert pkg1[\"diff\"][\"platform\"] == {}\n        assert pkg1[\"diff\"][\"settings\"] == {}\n        assert pkg1[\"diff\"][\"options\"] == {}\n        assert pkg1[\"diff\"][\"dependencies\"] == {}\n        assert pkg1[\"diff\"][\"python_requires\"] == {\"expected\": [\"tool/2.0.Z\"],\n                                                   \"existing\": [\"tool/1.0.Z\"]}\n        assert pkg1[\"diff\"][\"explanation\"] == \"This binary has same settings, options and \" \\\n                                              \"dependencies, but different python_requires\"\n\n    def test_build_requires(self):\n        c = TestClient(light=True)\n        c.save_home({\"global.conf\": \"core.package_id:default_build_mode=minor_mode\"})\n        c.save({\"tool/conanfile.py\": GenConanfile(\"tool\"),\n                \"lib/conanfile.py\": GenConanfile(\"lib\", \"1.0\").with_tool_requires(\"tool/[>=1.0]\")})\n        c.run(\"create tool --version=1.0\")\n        c.run(\"create lib\")\n        c.run(\"create tool --version=2.0\")\n        c.run(\"graph explain --requires=lib/1.0\")\n        expected = textwrap.dedent(\"\"\"\\\n            remote: Local Cache\n            build_requires: tool/1.0.Z\n            diff\n              build_requires\n                expected: tool/2.0.Z\n                existing: tool/1.0.Z\n              explanation: This binary has same settings, options and dependencies, but different build_requires\n            \"\"\")\n        assert textwrap.indent(expected, \"      \") in c.out\n        c.run(\"graph explain --requires=lib/1.0 -s os=Linux --format=json\")\n        closest = json.loads(c.stdout)[\"closest_binaries\"]\n        revisions = closest[\"lib/1.0\"][\"revisions\"]\n        pkgs = revisions[\"4790f7f1561b52be5d39f0bc8e9acbed\"][\"packages\"]\n        assert len(pkgs) == 1\n        pkg1 = pkgs[\"c9d96a611b8c819f35728d58d743f6a78a1b5942\"]\n        assert pkg1[\"diff\"][\"platform\"] == {}\n        assert pkg1[\"diff\"][\"settings\"] == {}\n        assert pkg1[\"diff\"][\"options\"] == {}\n        assert pkg1[\"diff\"][\"dependencies\"] == {}\n        assert pkg1[\"diff\"][\"build_requires\"] == {\"expected\": [\"tool/2.0.Z\"],\n                                                  \"existing\": [\"tool/1.0.Z\"]}\n        assert pkg1[\"diff\"][\"explanation\"] == \"This binary has same settings, options and \" \\\n                                              \"dependencies, but different build_requires\"\n\n\ndef test_change_in_package_type():\n    tc = TestClient(light=True)\n    tc.save({\n        \"libc/conanfile.py\": GenConanfile(\"libc\", \"1.0\"),\n        \"libb/conanfile.py\": GenConanfile(\"libb\", \"1.0\")\n        .with_requires(\"libc/1.0\"),\n        \"liba/conanfile.py\": GenConanfile(\"liba\", \"1.0\")\n        .with_requires(\"libb/1.0\")\n    })\n\n    tc.run(\"create libc\")\n    tc.run(\"create libb\")\n    tc.run(\"create liba\")\n\n    tc.save({\n        \"libc/conanfile.py\": GenConanfile(\"libc\", \"1.0\")\n        .with_package_type(\"application\")\n    })\n    tc.run(\"create libc\")\n\n    tc.run(\"create liba\", assert_error=True)\n    assert \"Missing binary: libb/1.0\" in tc.out\n\n    tc.run(\"graph explain --requires=liba/1.0\")\n    # This fails, graph explain thinks everything is ok\n    assert \"explanation: This binary is an exact match for the defined inputs\" not in tc.out\n\n\ndef test_conf_difference_shown():\n    tc = TestClient(light=True)\n    tc.save({\n        \"libc/conanfile.py\": GenConanfile(\"libc\", \"1.0\"),\n        \"libb/conanfile.py\": GenConanfile(\"libb\", \"1.0\").with_requires(\"libc/1.0\"),\n        \"liba/conanfile.py\": GenConanfile(\"liba\", \"1.0\").with_requires(\"libb/1.0\")\n    })\n    tc.save_home({\"global.conf\": \"tools.info.package_id:confs=['user.foo:bar']\"})\n\n    tc.run(\"create libc\")\n    tc.run(\"create libb\")\n    tc.run(\"create liba\")\n\n    tc.run(\"remove libc/*:* -c\")\n\n    tc.run(\"create libc -c user.foo:bar=42\")\n\n    tc.run(\"create liba\", assert_error=True)\n    assert \"Missing prebuilt package for 'libc/1.0'\" in tc.out\n\n    tc.run(\"graph explain --requires=liba/1.0\")\n    assert \"conf: user.foo:bar=42\" in tc.out\n\n\nclass TestDistance:\n    def test_multiple_distance_ordering(self):\n        tc = TestClient()\n        tc.save({\n            \"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_requires(\"dep/1.0\"),\n            \"dep/conanfile.py\": GenConanfile(\"dep\", \"1.0\")\n            .with_option(\"shared\", [True, False])\n            .with_option(\"fPIC\", [True, False])})\n\n        tc.run(\"create dep -o shared=True -o fPIC=True\")\n        tc.run(\"create dep -o shared=True -o fPIC=False\")\n\n        tc.run('graph explain . -o *:shared=False -o *:fPIC=False')\n        # We don't expect the further binary to show\n        assert \"a657a8fc96dd855e2a1c90a9fe80125f0c4635a0\" not in tc.out\n        # We expect the closer binary to show\n        assert \"a6923b987deb1469815dda84aab36ac34f370c48\" in tc.out\n\n\ndef test_no_binaries():\n    # https://github.com/conan-io/conan/issues/15819\n    c = TestClient()\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n    c.run(\"export .\")\n    c.run(\"graph explain --requires=pkg/0.1\")\n    assert \"ERROR: No package binaries exist\" in c.out\n    # The json is not an issue, it won't have anything as contents\n"
  },
  {
    "path": "test/integration/command/test_inspect.py",
    "content": "import json\nimport textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_basic_inspect():\n    t = TestClient()\n    t.save({\"foo/conanfile.py\": GenConanfile().with_name(\"foo\").with_shared_option()})\n    t.run(\"inspect foo/conanfile.py\")\n    lines = t.out.splitlines()\n    assert lines == ['default_options:',\n                     '    shared: False',\n                     'generators: []',\n                     'label: ',\n                     'languages: []',\n                     'name: foo',\n                     'options:',\n                     '    shared: False',\n                     'options_definitions:',\n                     \"    shared: ['True', 'False']\",\n                     'package_type: None',\n                     'requires: []',\n                     'revision_mode: hash',\n                     'vendor: False'\n                     ]\n\n\ndef test_options_description():\n    t = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\\\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            options = {\"shared\": [True, False, None], \"fpic\": [True, False, None]}\n            options_description = {\"shared\": \"Some long explanation about shared option\",\n                                   \"fpic\": \"Yet another long explanation of fpic\"}\n            \"\"\")\n    t.save({\"foo/conanfile.py\": conanfile})\n    t.run(\"inspect foo/conanfile.py\")\n    assert \"shared: Some long explanation about shared option\" in t.out\n    assert \"fpic: Yet another long explanation of fpic\" in t.out\n\n\ndef test_missing_conanfile():\n    t = TestClient()\n    t.run(\"inspect missing/conanfile.py\", assert_error=True)\n    assert \"Conanfile not found at\" in t.out\n\n\ndef test_dot_and_folder_conanfile():\n    t = TestClient()\n    t.save({\"conanfile.py\": GenConanfile().with_name(\"foo\")})\n    t.run(\"inspect\")\n    assert 'name: foo' in t.out\n    t.save({\"foo/conanfile.py\": GenConanfile().with_name(\"foo\")}, clean_first=True)\n    t.run(\"inspect foo\")\n    assert 'name: foo' in t.out\n\n\ndef test_inspect_understands_setname():\n    tc = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n\n    class Pkg(ConanFile):\n        settings = \"os\", \"arch\"\n        def set_name(self):\n            self.name = \"foo\"\n\n        def set_version(self):\n            self.version = \"1.0\"\n    \"\"\")\n\n    tc.save({\"conanfile.py\": conanfile})\n    tc.run(\"inspect .\")\n    assert \"foo\" in tc.out\n    assert \"1.0\" in tc.out\n\n\ndef test_normal_inspect():\n    tc = TestClient()\n    tc.run(\"new basic -d name=pkg -d version=1.0\")\n    tc.run(\"inspect .\")\n    assert tc.out.splitlines() == ['description: A basic recipe',\n                                   'generators: []',\n                                   'homepage: <Your project homepage goes here>',\n                                   'label: ',\n                                   'languages: []',\n                                   'license: <Your project license goes here>',\n                                   'name: pkg',\n                                   'options:',\n                                   'options_definitions:',\n                                   'package_type: None',\n                                   'requires: []',\n                                   'revision_mode: hash',\n                                   'vendor: False',\n                                   'version: 1.0']\n\n\ndef test_empty_inspect():\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n\n    class Pkg(ConanFile):\n        pass\"\"\")\n    tc = TestClient()\n    tc.save({\"conanfile.py\": conanfile})\n    tc.run(\"inspect . -f json\")\n\n\ndef test_basic_new_inspect():\n    tc = TestClient()\n    tc.run(\"new basic\")\n    tc.run(\"inspect . -f json\")\n\n    tc.run(\"new cmake_lib -d name=pkg -d version=1.0 -f\")\n    tc.run(\"inspect . -f json\")\n\n\ndef test_requiremens_inspect():\n    tc = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n\n    class Pkg(ConanFile):\n        requires = \"zlib/1.2.13\"\n        license = \"MIT\", \"Apache\"\n    \"\"\")\n    tc.save({\"conanfile.py\": conanfile})\n    tc.run(\"inspect .\")\n    assert ['generators: []',\n            'label: ',\n            'languages: []',\n            \"license: ['MIT', 'Apache']\",\n            'options:',\n            'options_definitions:',\n            'package_type: None',\n            \"requires: [{'ref': 'zlib/1.2.13', 'require': 'zlib/1.2.13', 'run': False, \"\n            \"'libs': True, 'skip': False, 'test': False, 'force': False, 'direct': True, 'build': \"\n            \"False, 'transitive_headers': None, 'transitive_libs': None, 'headers': \"\n            \"True, 'package_id_mode': None, 'visible': True}]\",\n            'revision_mode: hash',\n            'vendor: False'] == tc.out.splitlines()\n\n\ndef test_pythonrequires_remote():\n    tc = TestClient(default_server_user=True)\n    pyrequires = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n\n    class MyBase:\n        def set_name(self):\n            self.name = \"my_company_package\"\n\n    class PyReq(ConanFile):\n        name = \"pyreq\"\n        version = \"1.0\"\n        package_type = \"python-require\"\n    \"\"\")\n    tc.save({\"pyreq/conanfile.py\": pyrequires})\n    tc.run(\"create pyreq/\")\n    tc.run(\"upload pyreq/1.0 -r default\")\n    tc.run(\"search * -r default\")\n    assert \"pyreq/1.0\" in tc.out\n    tc.run(\"remove * -c\")\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n\n    class Pkg(ConanFile):\n        python_requires = \"pyreq/1.0\"\n        python_requires_extend = \"pyreq.MyBase\"\n\n        def set_version(self):\n            self.version = \"1.0\"\n    \"\"\")\n    tc.save({\"conanfile.py\": conanfile})\n    # Not specifying the remote also works\n    tc.run(\"inspect .\")\n    assert \"pyreq/1.0: Downloaded recipe revision 0ca726ab0febe1100901fffb27dc421f\" in tc.out\n    assert \"name: my_company_package\" in tc.out\n    assert \"version: 1.0\" in tc.out\n    # It now finds it on the cache, because it was downloaded\n    tc.run(\"inspect . -nr\")\n    assert \"name: my_company_package\" in tc.out\n    assert \"version: 1.0\" in tc.out\n    assert \"'recipe': 'Cache'\" in tc.out\n    tc.run(\"remove pyreq/* -c\")\n    # And now no remotes fails\n    tc.run(\"inspect . -nr\", assert_error=True)\n    assert \"Cannot resolve python_requires 'pyreq/1.0': No remote defined\" in tc.out\n\n\ndef test_serializable_inspect():\n    tc = TestClient()\n    tc.save({\"conanfile.py\": GenConanfile(\"a\", \"1.0\")\n            .with_requires(\"b/2.0\")\n            .with_setting(\"os\")\n            .with_option(\"shared\", [True, False])\n            .with_generator(\"CMakeDeps\")})\n    tc.run(\"inspect . --format=json\")\n    assert json.loads(tc.out)[\"name\"] == \"a\"\n"
  },
  {
    "path": "test/integration/command/test_new.py",
    "content": "import os\nimport textwrap\n\nimport pytest\n\nfrom conan import __version__\nfrom conan.internal.util.files import save\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestNewCommand:\n    def test_new_cmake_lib(self):\n        client = TestClient(light=True)\n        client.run(\"new cmake_lib -d name=pkg -d version=1.3\")\n        conanfile = client.load(\"conanfile.py\")\n        assert \"CMakeToolchain\" in conanfile\n        conanfile = client.load(\"test_package/conanfile.py\")\n        assert \"CMakeToolchain\" in conanfile\n        cmake = client.load(\"test_package/CMakeLists.txt\")\n        assert \"find_package\" in cmake\n\n        # Test at least it exports correctly\n        client.run(\"export . --user=myuser --channel=testing\")\n        assert \"pkg/1.3@myuser/testing\" in client.out\n\n    def test_new_cmake_exe(self):\n        client = TestClient(light=True)\n        client.run(\"new cmake_exe -d name=pkg -d version=1.3\")\n        conanfile = client.load(\"conanfile.py\")\n        assert \"CMakeToolchain\" in conanfile\n        conanfile = client.load(\"test_package/conanfile.py\")\n        assert \"def test(self):\" in conanfile\n\n        # Test at least it exports correctly\n        client.run(\"export . --user=myuser --channel=testing\")\n        assert \"pkg/1.3@myuser/testing\" in client.out\n\n    def test_new_basic_template(self):\n        tc = TestClient(light=True)\n        tc.run(\"new basic\")\n        assert '# self.requires(\"zlib/1.2.13\")' in tc.load(\"conanfile.py\")\n\n        tc.run(\"new basic -d name=mygame -d requires=math/1.0 -d requires=ai/1.0 -f\")\n        conanfile = tc.load(\"conanfile.py\")\n        assert 'self.requires(\"math/1.0\")' in conanfile\n        assert 'self.requires(\"ai/1.0\")' in conanfile\n        assert 'name = \"mygame\"' in conanfile\n\n    def test_new_basic_template_multi_arg(self):\n        tc = TestClient(light=True)\n        tc.run(\"new basic -d name=mygame -d requires=d1/1.0 -d requires=d2/1.0 -d requires=d3/1.0\")\n        conanfile = tc.load(\"conanfile.py\")\n        assert 'self.requires(\"d1/1.0\")' in conanfile\n        assert 'self.requires(\"d2/1.0\")' in conanfile\n        assert 'self.requires(\"d3/1.0\")' in conanfile\n\n    def test_new_defaults(self):\n        c = TestClient(light=True)\n        for t in (\"cmake_lib\", \"cmake_exe\", \"meson_lib\", \"meson_exe\", \"msbuild_lib\",\n                  \"msbuild_exe\", \"bazel_lib\", \"bazel_exe\", \"autotools_lib\", \"autotools_exe\"):\n            c.save({}, clean_first=True)\n            c.run(f\"new {t}\")\n            conanfile = c.load(\"conanfile.py\")\n            assert 'name = \"mypkg\"' in conanfile\n            assert 'version = \"0.1\"' in conanfile\n            if t == \"cmake_lib\":\n                cmake = c.load(\"CMakeLists.txt\")\n                assert \"src/mypkg.cpp\" in cmake\n                cpp = c.load(\"src/mypkg.cpp\")\n                assert \"mypkg()\" in cpp\n                hpp = c.load(\"include/mypkg.h\")\n                assert \"void mypkg();\" in hpp\n\n            c.run(f\"new {t} -d name=mylib -f\")\n            conanfile = c.load(\"conanfile.py\")\n            assert 'name = \"mylib\"' in conanfile\n            assert 'version = \"0.1\"' in conanfile\n\n\nclass TestNewCommandUserTemplate:\n\n    @pytest.mark.parametrize(\"folder\", (\"mytemplate\", \"sub/mytemplate\"))\n    def test_user_template(self, folder):\n        client = TestClient(light=True)\n        template1 = textwrap.dedent(\"\"\"\n            class Conan(ConanFile):\n                name = \"{{name}}\"\n                version = \"{{version}}\"\n                conan_version = \"{{conan_version}}\"\n        \"\"\")\n        save(os.path.join(client.cache_folder, f\"templates/command/new/{folder}/conanfile.py\"),\n             template1)\n        client.run(f\"new {folder} -d name=hello -d version=0.1\")\n        conanfile = client.load(\"conanfile.py\")\n        assert 'name = \"hello\"' in conanfile\n        assert 'version = \"0.1\"' in conanfile\n        assert 'conan_version = \"{}\"'.format(__version__) in conanfile\n\n    def test_user_template_abs(self):\n        tmp_folder = temp_folder()\n        client = TestClient(light=True)\n        template1 = textwrap.dedent(\"\"\"\n            class Conan(ConanFile):\n                name = \"{{name}}\"\n        \"\"\")\n        save(os.path.join(tmp_folder, \"conanfile.py\"), template1)\n        client.run(f'new \"{tmp_folder}\" -d name=hello -d version=0.1')\n        conanfile = client.load(\"conanfile.py\")\n        assert 'name = \"hello\"' in conanfile\n\n    def test_user_template_filenames(self):\n        client = TestClient(light=True)\n        save(os.path.join(client.cache_folder, \"templates/command/new/mytemplate/{{name}}\"), \"Hi!\")\n        client.run(f\"new mytemplate -d name=pkg.txt\")\n        assert \"Hi!\" == client.load(\"pkg.txt\")\n\n    def test_skip_files(self):\n        client = TestClient(light=True)\n        template1 = textwrap.dedent(\"\"\"\n            class Conan(ConanFile):\n                name = \"{{name}}\"\n                version = \"{{version}}\"\n                conan_version = \"{{conan_version}}\"\n        \"\"\")\n        path = os.path.join(client.cache_folder, f\"templates/command/new/mytemplate\")\n        save(os.path.join(path, \"conanfile.py\"), template1)\n        save(os.path.join(path, \"file.h\"), \"{{header}}\")\n\n        client.run(f\"new mytemplate -d name=hello -d version=0.1 -d header=\")\n        assert not os.path.exists(os.path.join(client.current_folder, \"file.h\"))\n        assert not os.path.exists(os.path.join(client.current_folder, \"file.cpp\"))\n        client.run(f\"new mytemplate -d name=hello -d version=0.1 -d header=xxx -f\")\n        assert os.path.exists(os.path.join(client.current_folder, \"file.h\"))\n        assert not os.path.exists(os.path.join(client.current_folder, \"file.cpp\"))\n\n    def test_template_image_files(self):\n        \"\"\" problematic files that we dont want to render with Jinja, like PNG or other binaries,\n        have to be explicitly excluded from render\"\"\"\n        client = TestClient(light=True)\n        template_dir = \"templates/command/new/t_dir\"\n        png = \"$&(){}{}{{}{}\"\n        save(os.path.join(client.cache_folder, template_dir, \"myimage.png\"), png)\n        client.run(\"new t_dir -d name=hello -d version=0.1\", assert_error=True)\n        assert \"TemplateSyntaxError\" in client.out\n\n        save(os.path.join(client.cache_folder, template_dir, \"not_templates\"), \"*.png\")\n        client.run(\"new t_dir -d name=hello -d version=0.1\")\n        myimage = client.load(\"myimage.png\")\n        assert myimage == png\n        assert not os.path.exists(os.path.join(client.current_folder, \"not_templates\"))\n\n        client.run(\"new t_dir -d name=hello -d version=0.1\", assert_error=True)\n        assert \"File 'myimage.png' already exists, and --force not defined, aborting\" in client.out\n\n    def test_wrong_argument(self):\n        c = TestClient(light=True)\n        save(os.path.join(c.cache_folder, f\"templates/command/new/mytpl/conanfile.py\"), \"\")\n        c.run(f\"new mytpl -d version\", assert_error=True)\n        assert \"ERROR: Template definitions must be 'key=value', received 'version'\" in c.out\n\n    def test_missing_argument(self):\n        c = TestClient(light=True)\n        save(os.path.join(c.cache_folder, f\"templates/command/new/mytpl/file.txt\"), \"{{myarg}}\")\n        c.run(f\"new mytpl\", assert_error=True)\n        assert (\"ERROR: Missing definitions for the template. \"\n                \"Required definitions are: 'myarg'\") in c.out\n\n\nclass TestNewErrors:\n    def test_template_errors(self):\n        client = TestClient(light=True)\n        client.run(\"new mytemplate\", assert_error=True)\n        assert \"ERROR: Template doesn't exist\" in client.out\n\n    def test_forced(self):\n        client = TestClient(light=True)\n        client.run(\"new cmake_lib -d name=hello -d version=0.1\")\n        client.run(\"new cmake_lib -d name=hello -d version=0.1\", assert_error=True)\n        assert \"ERROR: File 'CMakeLists.txt' already exists, and --force not defined\" in client.out\n        client.run(\"new cmake_lib -d name=bye -d version=0.2 --force\")\n        conanfile = client.load(\"conanfile.py\")\n        assert 'name = \"bye\"' in conanfile\n        assert 'version = \"0.2\"' in conanfile\n\n    def test_duplicated(self):\n        client = TestClient(light=True)\n        client.run(\"new cmake_lib -d name=hello -d name=0.1\", assert_error=True)\n        assert \"ERROR: name argument can't be multiple: ['hello', '0.1']\" in client.out\n\n        # It will create a list and assign to it, but it will not fail ugly\n        client.run(\"new cmake_lib -d name=pkg -d version=0.1 -d version=0.2\", assert_error=True)\n        assert \"ERROR: version argument can't be multiple: ['0.1', '0.2']\" in client.out\n\n    def test_name_uppercase(self):\n        client = TestClient(light=True)\n        client.run(\"new cmake_lib -d name=Hello\", assert_error=True)\n        assert \"ERROR: name argument must be lowercase: Hello\" in client.out\n\n    def test_new_change_folder(self):\n        client = TestClient(light=True)\n        client.run(\"new cmake_lib -d name=hello -d version=0.1 -o=myfolder\")\n        assert os.path.exists(os.path.join(client.current_folder, \"myfolder\", \"conanfile.py\"))\n"
  },
  {
    "path": "test/integration/command/test_outdated.py",
    "content": "import json\nfrom collections import OrderedDict\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient, TestServer\n\n\n@pytest.fixture\ndef create_libs():\n    tc = TestClient(default_server_user=True, light=True)\n    tc.save({\"conanfile.py\": GenConanfile()})\n    tc.run(\"create . --name=zlib --version=1.0\")\n    tc.run(\"create . --name=zlib --version=2.0\")\n    tc.run(\"create . --name=foo --version=1.0\")\n    tc.run(\"create . --name=foo --version=2.0\")\n\n    tc.save({\"conanfile.py\": GenConanfile().with_requires(\"foo/[>=1.0]\")})\n    tc.run(\"create . --name=libcurl --version=1.0\")\n\n    # Upload all created libs to the remote\n    tc.run(\"upload * -c -r=default\")\n\n    tc.save({\"conanfile.py\": GenConanfile(\"app\", \"1.0\")\n            .with_requires(\"zlib/1.0\", \"libcurl/[>=1.0]\")})\n    return tc\n\n\ndef test_outdated_command(create_libs):\n    tc = create_libs\n\n    # Remove versions from cache so they are found as outdated\n    tc.run(\"remove foo/2.0 -c\")\n    tc.run(\"remove zlib/2.0 -c\")\n\n    tc.run(\"graph outdated . --format=json\")\n    output = json.loads(tc.stdout)\n    assert \"zlib\" in output\n    assert \"foo\" in output\n    assert \"libcurl\" not in output\n    assert output[\"zlib\"][\"current_versions\"] == [\"zlib/1.0\"]\n    assert output[\"zlib\"][\"version_ranges\"] == []\n    assert output[\"zlib\"][\"latest_remote\"][\"ref\"] == \"zlib/2.0\"\n    assert output[\"zlib\"][\"latest_remote\"][\"remote\"].startswith(\"default\")\n    assert output[\"foo\"][\"current_versions\"] == [\"foo/1.0\"]\n    assert output[\"foo\"][\"version_ranges\"] == [\"foo/[>=1.0]\"]\n    assert output[\"foo\"][\"latest_remote\"][\"ref\"] == \"foo/2.0\"\n    assert output[\"foo\"][\"latest_remote\"][\"remote\"].startswith(\"default\")\n\n\ndef test_recipe_with_lockfile(create_libs):\n    tc = create_libs\n\n    # Remove versions from cache so they are found as outdated\n    tc.run(\"remove foo/2.0 -c\")\n    tc.run(\"remove zlib/2.0 -c\")\n\n    # Creating the lockfile sets foo/1.0 as only valid version for the recipe\n    tc.run(\"lock create .\")\n    tc.run(\"graph outdated . --format=json\")\n    output = json.loads(tc.stdout)\n    assert \"foo\" in output\n    assert output[\"foo\"][\"current_versions\"] == [\"foo/1.0\"]\n    # Creating the lockfile makes the previous range obsolete\n    assert output[\"foo\"][\"version_ranges\"] == []\n\n    # Adding foo/2.0 to the lockfile forces the download so foo is no longer outdated\n    tc.run(\"lock add --requires=foo/2.0\")\n    tc.run(\"graph outdated . --format=json\")\n    output = json.loads(tc.stdout)\n    assert \"foo\" not in output\n\n\ndef test_recipe_with_no_remote_ref(create_libs):\n    tc = create_libs\n\n    # Remove versions from cache so they are found as outdated\n    tc.run(\"remove foo/2.0 -c\")\n    tc.run(\"remove zlib/2.0 -c\")\n    tc.run(\"remove libcurl -c\")\n\n    tc.run(\"graph outdated . --format=json\")\n    output = json.loads(tc.stdout)\n    # Check that libcurl doesn't appear as there is no version in the remotes\n    assert \"zlib\" in output\n    assert \"foo\" in output\n    assert \"libcurl\" not in output\n\n\ndef test_cache_ref_newer_than_latest_in_remote(create_libs):\n    tc = create_libs\n\n    tc.run(\"remove foo/2.0 -c -r=default\")\n\n    tc.run(\"graph outdated . --format=json\")\n    output = json.loads(tc.stdout)\n    # Check that foo doesn't appear because the version in cache is higher than the latest version\n    # in remote\n    assert \"zlib\" in output\n    assert \"libcurl\" not in output\n    assert \"foo\" not in output\n\n\ndef test_two_remotes():\n    # remote1: zlib/1.0, libcurl/2.0, foo/1.0\n    # remote2: zlib/[1.0, 2.0], libcurl/1.0, foo/1.0\n    # local cache: zlib/1.0, libcurl/1.0, foo/1.0\n    servers = OrderedDict()\n    for i in [1, 2]:\n        test_server = TestServer()\n        servers[\"remote%d\" % i] = test_server\n\n    tc = TestClient(servers=servers, inputs=2 * [\"admin\", \"password\"], light=True)\n\n    tc.save({\"conanfile.py\": GenConanfile()})\n    tc.run(\"create . --name=zlib --version=1.0\")\n    tc.run(\"create . --name=foo --version=1.0\")\n    tc.run(\"create . --name=zlib --version=2.0\")\n\n    tc.save({\"conanfile.py\": GenConanfile().with_requires(\"foo/[>=1.0]\")})\n    tc.run(\"create . --name=libcurl --version=1.0\")\n    tc.run(\"create . --name=libcurl --version=2.0\")\n\n    # Upload the created libraries  1.0 to remotes\n    tc.run(\"upload zlib/1.0 -c -r=remote1\")\n    tc.run(\"upload libcurl/2.0 -c -r=remote1\")\n    tc.run(\"upload foo/1.0 -c -r=remote1\")\n\n    tc.run(\"upload zlib/* -c -r=remote2\")\n    tc.run(\"upload libcurl/1.0 -c -r=remote2\")\n    tc.run(\"upload foo/1.0 -c -r=remote2\")\n\n    # Remove from cache the 2.0 libraries\n    tc.run(\"remove libcurl/2.0 -c\")\n    tc.run(\"remove zlib/2.0 -c\")\n\n    tc.save({\"conanfile.py\": GenConanfile(\"app\", \"1.0\")\n            .with_requires(\"zlib/1.0\", \"libcurl/[>=1.0]\")})\n\n    tc.run(\"graph outdated . --format=json\")\n    output = json.loads(tc.stdout)\n    assert \"zlib\" in output\n    assert \"libcurl\" in output\n    assert \"foo\" not in output\n    assert output[\"libcurl\"][\"latest_remote\"][\"ref\"].startswith(\"libcurl/2.0\")\n    assert output[\"libcurl\"][\"latest_remote\"][\"remote\"].startswith(\"remote1\")\n    assert output[\"zlib\"][\"latest_remote\"][\"ref\"].startswith(\"zlib/2.0\")\n    assert output[\"zlib\"][\"latest_remote\"][\"remote\"].startswith(\"remote2\")\n\n\ndef test_duplicated_tool_requires():\n    tc = TestClient(default_server_user=True)\n    # Create libraries needed to generate the dependency graph\n    tc.save({\"conanfile.py\": GenConanfile()})\n    tc.run(\"create . --name=cmake --version=1.0\")\n    tc.run(\"create . --name=cmake --version=2.0\")\n    tc.run(\"create . --name=cmake --version=3.0\")\n    tc.save({\"conanfile.py\": GenConanfile().with_tool_requires(\"cmake/1.0\")})\n    tc.run(\"create . --name=foo --version=1.0\")\n    tc.save({\"conanfile.py\": GenConanfile().with_tool_requires(\"cmake/[>=1.0]\")})\n    tc.run(\"create . --name=bar --version=1.0\")\n\n    # Upload the created libraries to remote\n    tc.run(\"upload * -c -r=default\")\n\n    tc.save({\"conanfile.py\": GenConanfile(\"app\", \"1.0\")\n            .with_requires(\"foo/1.0\", \"bar/1.0\").with_tool_requires(\"cmake/[<=2.0]\")})\n\n    tc.run(\"graph outdated . --format=json\")\n    output = json.loads(tc.stdout)\n\n    assert sorted(output[\"cmake\"][\"current_versions\"]) == [\"cmake/1.0\", \"cmake/2.0\", \"cmake/3.0\"]\n    assert sorted(output[\"cmake\"][\"version_ranges\"]) == [\"cmake/[<=2.0]\", \"cmake/[>=1.0]\"]\n    assert output[\"cmake\"][\"latest_remote\"][\"ref\"] == \"cmake/3.0\"\n\n\ndef test_no_outdated_dependencies():\n    tc = TestClient(default_server_user=True)\n\n    tc.save({\"conanfile.py\": GenConanfile()})\n    tc.run(\"create . --name=foo --version=1.0\")\n    tc.run(\"upload * -c -r=default\")\n\n    tc.run(\"graph outdated .\")\n\n    assert \"No outdated dependencies in graph\" in tc.stdout\n"
  },
  {
    "path": "test/integration/command/test_output.py",
    "content": "import json\nimport os\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient\nfrom conan.test.utils.env import environment_update\n\n\nclass TestOutputLevel:\n    def test_invalid_output_level(self):\n        t = TestClient(light=True)\n        t.save({\"conanfile.py\": GenConanfile(\"foo\", \"1.0\")})\n        t.run(\"create . -vfooling\", assert_error=True)\n        assert \"argument -v: invalid choice: 'fooling'\" in t.out\n\n        with environment_update({\"CONAN_LOG_LEVEL\": \"fail\"}):\n            t.run(\"create .\", assert_error=True)\n            assert \"Invalid argument '-vfail' defined in CONAN_LOG_LEVEL \" \\\n                   \"environment variable\" in t.out\n\n    def test_output_level(self):\n        lines = (\"self.output.trace('This is a trace')\",\n                 \"self.output.debug('This is a debug')\",\n                 \"self.output.verbose('This is a verbose')\",\n                 \"self.output.info('This is a info')\",\n                 \"self.output.highlight('This is a highlight')\",\n                 \"self.output.success('This is a success')\",\n                 \"self.output.warning('This is a warning')\",\n                 \"self.output.error('This is a error')\",\n                 )\n\n        t = TestClient(light=True)\n        t.save({\"conanfile.py\": GenConanfile(\"foo\", \"1.0\").with_package(*lines)})\n\n        # By default, it prints > info\n        t.run(\"create .\")\n        assert \"This is a trace\" not in t.out\n        assert \"This is a debug\" not in t.out\n        assert \"This is a verbose\" not in t.out\n        assert \"This is a info\" in t.out\n        assert \"This is a highlight\" in t.out\n        assert \"This is a success\" in t.out\n        assert \"This is a warning\" in t.out\n        assert \"This is a error\" in t.out\n\n        # Check if -v argument is equal to VERBOSE level\n        t.run(\"create . -v\")\n        assert \"This is a trace\" not in t.out\n        assert \"This is a debug\" not in t.out\n        assert \"This is a verbose\" in t.out\n        assert \"This is a info\" in t.out\n        assert \"This is a highlight\" in t.out\n        assert \"This is a success\" in t.out\n        assert \"This is a warning\" in t.out\n        assert \"This is a error\" in t.out\n\n        # Print also verbose traces\n        t.run(\"create . -vverbose\")\n        assert \"This is a trace\" not in t.out\n        assert \"This is a debug\" not in t.out\n        assert \"This is a verbose\" in t.out\n        assert \"This is a info\" in t.out\n        assert \"This is a highlight\" in t.out\n        assert \"This is a success\" in t.out\n        assert \"This is a warning\" in t.out\n        assert \"This is a error\" in t.out\n\n        # Print also debug traces\n        t.run(\"create . -vv\")\n        assert \"This is a trace\" not in t.out\n        assert \"This is a debug\" in t.out\n        assert \"This is a verbose\" in t.out\n        assert \"This is a info\" in t.out\n        assert \"This is a highlight\" in t.out\n        assert \"This is a success\" in t.out\n        assert \"This is a warning\" in t.out\n        assert \"This is a error\" in t.out\n        t.run(\"create . -vdebug\")\n        assert \"This is a trace\" not in t.out\n        assert \"This is a debug\" in t.out\n        assert \"This is a verbose\" in t.out\n        assert \"This is a info\" in t.out\n        assert \"This is a highlight\" in t.out\n        assert \"This is a success\" in t.out\n        assert \"This is a warning\" in t.out\n        assert \"This is a error\" in t.out\n\n        # Print also \"trace\" traces\n        t.run(\"create . -vvv\")\n        assert \"This is a trace\" in t.out\n        assert \"This is a debug\" in t.out\n        assert \"This is a verbose\" in t.out\n        assert \"This is a info\" in t.out\n        assert \"This is a highlight\" in t.out\n        assert \"This is a success\" in t.out\n        assert \"This is a warning\" in t.out\n        assert \"This is a error\" in t.out\n        t.run(\"create . -vtrace\")\n        assert \"This is a trace\" in t.out\n        assert \"This is a debug\" in t.out\n        assert \"This is a verbose\" in t.out\n        assert \"This is a info\" in t.out\n        assert \"This is a highlight\" in t.out\n        assert \"This is a success\" in t.out\n        assert \"This is a warning\" in t.out\n        assert \"This is a error\" in t.out\n\n        # With notice\n        t.run(\"create . -vstatus\")\n        assert \"This is a trace\" not in t.out\n        assert \"This is a debug\" not in t.out\n        assert \"This is a verbose\" not in t.out\n        assert \"This is a info\" in t.out\n        assert \"This is a highlight\" in t.out\n        assert \"This is a success\" in t.out\n        assert \"This is a warning\" in t.out\n        assert \"This is a error\" in t.out\n\n        # With notice\n        t.run(\"create . -vnotice\")\n        assert \"This is a trace\" not in t.out\n        assert \"This is a debug\" not in t.out\n        assert \"This is a verbose\" not in t.out\n        assert \"This is a info\" not in t.out\n        assert \"This is a highlight\" in t.out\n        assert \"This is a success\" in t.out\n        assert \"This is a warning\" in t.out\n        assert \"This is a error\" in t.out\n\n        # With warnings\n        t.run(\"create . -vwarning\")\n        assert \"This is a trace\" not in t.out\n        assert \"This is a debug\" not in t.out\n        assert \"This is a verbose\" not in t.out\n        assert \"This is a info\" not in t.out\n        assert \"This is a highlight\" not in t.out\n        assert \"This is a success\" not in t.out\n        assert \"This is a warning\" in t.out\n        assert \"This is a error\" in t.out\n\n        # With errors\n        t.run(\"create . -verror\")\n        assert \"This is a trace\" not in t.out\n        assert \"This is a debug\" not in t.out\n        assert \"This is a verbose\" not in t.out\n        assert \"This is a info\" not in t.out\n        assert \"This is a highlight\" not in t.out\n        assert \"This is a success\" not in t.out\n        assert \"This is a warning\" not in t.out\n        assert \"This is a error\" in t.out\n\n\ndef test_output_level_envvar():\n    lines = (\"self.output.trace('This is a trace')\",\n             \"self.output.debug('This is a debug')\",\n             \"self.output.verbose('This is a verbose')\",\n             \"self.output.info('This is a info')\",\n             \"self.output.highlight('This is a highlight')\",\n             \"self.output.success('This is a success')\",\n             \"self.output.warning('This is a warning')\",\n             \"self.output.error('This is a error')\",\n             )\n\n    t = TestClient(light=True)\n    t.save({\"conanfile.py\": GenConanfile().with_package(*lines)})\n\n    # Check if -v argument is equal to VERBOSE level\n    with environment_update({\"CONAN_LOG_LEVEL\": \"verbose\"}):\n        t.run(\"create . --name foo --version 1.0\")\n        assert \"This is a trace\" not in t.out\n        assert \"This is a debug\" not in t.out\n        assert \"This is a verbose\" in t.out\n        assert \"This is a info\" in t.out\n        assert \"This is a highlight\" in t.out\n        assert \"This is a success\" in t.out\n        assert \"This is a warning\" in t.out\n        assert \"This is a error\" in t.out\n\n        # Check if -v argument is equal to VERBOSE level\n    with environment_update({\"CONAN_LOG_LEVEL\": \"error\"}):\n        t.run(\"create . --name foo --version 1.0\")\n        assert \"This is a trace\" not in t.out\n        assert \"This is a debug\" not in t.out\n        assert \"This is a verbose\" not in t.out\n        assert \"This is a info\" not in t.out\n        assert \"This is a highlight\" not in t.out\n        assert \"This is a success\" not in t.out\n        assert \"This is a warning\" not in t.out\n        assert \"This is a error\" in t.out\n\n\nclass TestWarningHandling:\n    warning_lines = (\"self.output.warning('Tagged warning', warn_tag='tag')\",\n                     \"self.output.warning('Untagged warning')\")\n    error_lines = (\"self.output.error('Tagged error', error_type='exception')\",\n                   \"self.output.error('Untagged error')\")\n\n    def test_warning_as_error_deprecated_syntax(self):\n        t = TestClient(light=True)\n        t.save({\"conanfile.py\": GenConanfile(\"foo\", \"1.0\").with_package(*self.warning_lines)})\n\n        t.save_home({\"global.conf\": \"core:warnings_as_errors=[]\"})\n        t.run(\"create . -vwarning\")\n        assert \"WARN: Untagged warning\" in t.out\n        assert \"WARN: tag: Tagged warning\" in t.out\n\n        t.save_home({\"global.conf\": \"core:warnings_as_errors=['*']\"})\n        t.run(\"create . -vwarning\", assert_error=True)\n        assert \"ConanException: tag: Tagged warning\" in t.out\n        # We bailed early, didn't get a chance to print this one\n        assert \"Untagged warning\" not in t.out\n\n        t.save_home({\"global.conf\": \"\"\"core:warnings_as_errors=['*']\\ncore:skip_warnings=[\"tag\"]\"\"\"})\n        t.run(\"create . -verror\", assert_error=True)\n        assert \"ConanException: Untagged warning\" in t.out\n        assert \"Tagged warning\" not in t.out\n\n        t.save_home({\"global.conf\": \"core:warnings_as_errors=[]\"})\n        t.run(\"create . -verror\")\n        assert \"ERROR: Untagged warning\" not in t.out\n        assert \"ERROR: tag: Tagged warning\" not in t.out\n\n    def test_skip_warnings(self):\n        t = TestClient(light=True)\n        t.save({\"conanfile.py\": GenConanfile(\"foo\", \"1.0\").with_package(*self.warning_lines)})\n\n        t.save_home({\"global.conf\": \"core:skip_warnings=[]\"})\n        t.run(\"create . -vwarning\")\n        assert \"WARN: Untagged warning\" in t.out\n        assert \"WARN: tag: Tagged warning\" in t.out\n\n        t.save_home({\"global.conf\": \"core:skip_warnings=['tag']\"})\n        t.run(\"create . -vwarning\")\n        assert \"WARN: Untagged warning\" in t.out\n        assert \"WARN: tag: Tagged warning\" not in t.out\n\n        t.save_home({\"global.conf\": \"core:skip_warnings=['unknown']\"})\n        t.run(\"create . -vwarning\")\n        assert \"WARN: Untagged warning\" not in t.out\n        assert \"WARN: tag: Tagged warning\" in t.out\n\n        t.save_home({\"global.conf\": \"core:skip_warnings=['unknown', 'tag']\"})\n        t.run(\"create . -vwarning\")\n        assert \"WARN: Untagged warning\" not in t.out\n        assert \"WARN: tag: Tagged warning\" not in t.out\n\n    def test_exception_errors(self):\n        t = TestClient(light=True)\n        t.save({\"conanfile.py\": GenConanfile(\"foo\", \"1.0\").with_package(*self.error_lines)})\n\n        t.save_home({\"global.conf\": \"core:warnings_as_errors=[]\"})\n        t.run(\"create .\")\n        assert \"ERROR: Tagged error\" in t.out\n        assert \"ERROR: Untagged error\" in t.out\n\n        t.save_home({\"global.conf\": \"core:warnings_as_errors=['*']\"})\n        t.run(\"create .\", assert_error=True)\n        assert \"ERROR: Tagged error\" in t.out\n        assert \"ConanException: Untagged error\" in t.out\n\n        t.run(\"create . -vquiet\", assert_error=True)\n        assert \"ERROR: Tagged error\" not in t.out\n        assert \"ConanException: Untagged error\" not in t.out\n\n\ndef test_formatter_redirection_to_file():\n    c = TestClient(light=True)\n    c.save({\"conanfile.py\":  GenConanfile(\"pkg\", \"0.1\")})\n\n    c.run(\"config home --out-file=cmd_out.txt\")\n    assert \"Formatted output saved to 'cmd_out.txt'\" in c.out\n    cmd_out = c.load(\"cmd_out.txt\")\n    assert f\"{c.cache_folder}\" in cmd_out\n    assert not f\"{c.cache_folder}\" in c.stdout\n\n    c.run(\"graph info . --format=json --out-file=graph.json\")\n    assert \"Formatted output saved to 'graph.json'\" in c.out\n    graph = json.loads(c.load(\"graph.json\"))\n    assert len(graph[\"graph\"][\"nodes\"]) == 1\n    assert \"nodes\" not in c.stdout\n\n    c.run(\"graph info . --format=html --out-file=graph.html\")\n    assert \"Formatted output saved to 'graph.html'\" in c.out\n    html = c.load(\"graph.html\")\n    assert \"<head>\" in html\n    assert \"<head>\" not in c.stdout\n\n    c.run(\"install . --format=json --out-file=graph.json\")\n    assert \"Formatted output saved to 'graph.json'\" in c.out\n    graph = json.loads(c.load(\"graph.json\"))\n    assert len(graph[\"graph\"][\"nodes\"]) == 1\n    assert \"nodes\" not in c.stdout\n\n\ndef test_redirect_to_file_create_dir():\n    c = TestClient(light=True)\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n    c.run(\"config home --out-file=subdir/cmd_out.txt\")\n    cmd_out = c.load(\"subdir/cmd_out.txt\")\n    assert f\"{c.cache_folder}\" in cmd_out\n\n    base = temp_folder()\n    c = TestClient(light=True, current_folder=os.path.join(base, \"sub1\"))\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n    c.run(\"config home --out-file=../subdir/cmd_out.txt\")\n    cmd_out = c.load(\"../subdir/cmd_out.txt\")\n    assert f\"{c.cache_folder}\" in cmd_out\n"
  },
  {
    "path": "test/integration/command/test_package_test.py",
    "content": "import json\nimport os\nimport textwrap\n\nfrom conan.api.model import RecipeReference\nfrom conan.internal.paths import CONANFILE\nfrom conan.test.utils.tools import NO_SETTINGS_PACKAGE_ID, TestClient, GenConanfile\nfrom conan.internal.util.files import load\n\n\nclass TestPackageTest:\n\n    def test_basic(self):\n        client = TestClient()\n        test_package = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class TestPackage(ConanFile):\n            def requirements(self):\n                self.requires(self.tested_reference_str)\n            def test(self):\n                self.output.info(\"TESTING\")\n        \"\"\")\n        client.save({CONANFILE: GenConanfile(\"hello\", \"0.1\"),\n                     \"test_package/conanfile.py\": test_package})\n        client.run(\"create . --user=lasote --channel=stable\")\n        assert \"hello/0.1@lasote/stable: Created package\" in client.out\n        client.run(\"test test_package hello/0.1@lasote/stable\")\n        assert \"hello/0.1@lasote/stable (test package): TESTING\" in client.out\n        client.run(\"test hello/0.1@lasote/stable\")\n        assert \"hello/0.1@lasote/stable (test package): TESTING\" in client.out\n\n    def test_basic_json(self):\n        client = TestClient()\n        client.save({CONANFILE: GenConanfile(\"hello\", \"0.1\"),\n                     \"test_package/conanfile.py\": GenConanfile().with_test(\"pass\")})\n        client.run(\"create . --format=json\")\n        graph = json.loads(client.stdout)\n        assert graph[\"graph\"][\"nodes\"][\"1\"][\"ref\"] == \"hello/0.1#a90ba236e5310a473dae9f767a41db91\"\n\n    def test_test_only(self):\n        test_conanfile = GenConanfile().with_test(\"pass\")\n        client = TestClient()\n        client.save({CONANFILE: GenConanfile().with_name(\"hello\").with_version(\"0.1\"),\n                     \"test_package/conanfile.py\": test_conanfile})\n        client.run(\"create . --user=lasote --channel=stable\")\n        client.run(\"test test_package hello/0.1@lasote/stable\")\n\n        assert \"Exporting package recipe\" not in client.out\n        assert \"Forced build from source\" not in client.out\n        assert \"Package '%s' created\" % NO_SETTINGS_PACKAGE_ID not in client.out\n        assert \"Forced build from source\" not in client.out\n        assert \"hello/0.1@lasote/stable: Already installed!\" in client.out\n\n        client.save({\"test_package/conanfile.py\": test_conanfile}, clean_first=True)\n        client.run(\"test test_package hello/0.1@lasote/stable\")\n        assert \"hello/0.1@lasote/stable: Configuring sources\" not in client.out\n        assert \"hello/0.1@lasote/stable: Created package\" not in client.out\n        assert \"hello/0.1@lasote/stable: Already installed!\" in client.out\n        assert \"hello/0.1@lasote/stable (test package): Running test()\" in client.out\n\n    def test_wrong_version(self):\n        test_conanfile = GenConanfile().with_test(\"pass\").with_require(\"hello/0.2@user/cc\")\n        client = TestClient()\n        client.save({CONANFILE: GenConanfile().with_name(\"hello\").with_version(\"0.1\"),\n                     \"test_package/conanfile.py\": test_conanfile})\n        client.run(\"create . --user=user --channel=channel\", assert_error=True)\n        assert \"Duplicated requirement: hello/0.1@user/channel\" in client.out\n\n    def test_other_requirements(self):\n        test_conanfile = (GenConanfile().with_require(\"other/0.2@user2/channel2\")\n                                        .with_test(\"pass\"))\n        client = TestClient()\n        other_conanfile = GenConanfile().with_name(\"other\").with_version(\"0.2\")\n        client.save({CONANFILE: other_conanfile})\n        client.run(\"export . --user=user2 --channel=channel2\")\n        client.run(\"install --requires=other/0.2@user2/channel2 --build='*'\")\n        client.save({CONANFILE: GenConanfile().with_name(\"hello\").with_version(\"0.1\"),\n                     \"test_package/conanfile.py\": test_conanfile})\n        client.run(\"create . --user=user --channel=channel\")\n        assert \"hello/0.1@user/channel: Created package\" in client.out\n\n        # explicit override of user/channel works\n        client.run(\"create . --user=lasote --channel=stable\")\n        assert \"hello/0.1@lasote/stable: Created package\" in client.out\n\n    def test_test_with_path_errors(self):\n        client = TestClient()\n        client.save({\"conanfile.txt\": \"contents\"}, clean_first=True)\n\n        # Path with conanfile.txt\n        client.run(\"test conanfile.txt other/0.2@user2/channel2\", assert_error=True)\n\n        assert (\"A conanfile.py is needed, %s is not acceptable\"\n                % os.path.join(client.current_folder, \"conanfile.txt\") in client.out)\n\n        # Path with wrong conanfile path\n        client.run(\"test not_real_dir/conanfile.py other/0.2@user2/channel2\", assert_error=True)\n        assert (\"Conanfile not found at %s\"\n                % os.path.join(client.current_folder, \"not_real_dir\", \"conanfile.py\") in client.out)\n\n    def test_check_version(self):\n        client = TestClient()\n        client.save({CONANFILE: GenConanfile()})\n        client.run(\"create . --name=dep --version=1.1\")\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                requires = \"dep/1.1\"\n                def build(self):\n                    ref = self.dependencies[\"dep\"].ref\n                    self.output.info(\"BUILD Dep VERSION %s\" % ref.version)\n            \"\"\")\n        test_conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                def requirements(self):\n                    self.requires(self.tested_reference_str)\n                def build(self):\n                    ref = self.dependencies[\"hello\"].ref\n                    self.output.info(\"BUILD HELLO VERSION %s\" % ref.version)\n                def test(self):\n                    ref = self.dependencies[\"hello\"].ref\n                    self.output.info(\"TEST HELLO VERSION %s\" % ref.version)\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile,\n                     \"test_package/conanfile.py\": test_conanfile})\n        client.run(\"create . --name=hello --version=0.1\")\n        assert \"hello/0.1: BUILD Dep VERSION 1.1\" in client.out\n        assert \"hello/0.1 (test package): BUILD HELLO VERSION 0.1\" in client.out\n        assert \"hello/0.1 (test package): TEST HELLO VERSION 0.1\" in client.out\n\n\nclass TestPackageBuild:\n    def test_build_all(self):\n        c = TestClient()\n        c.save({\"tool/conanfile.py\": GenConanfile(\"tool\", \"0.1\"),\n                \"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\"),\n                \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_requires(\"dep/0.1\"),\n                \"pkg/test_package/conanfile.py\": GenConanfile().with_tool_requires(\"tool/0.1\")\n                                                               .with_test(\"pass\")})\n        c.run(\"export tool\")\n        c.run(\"export dep\")\n        c.run(\"create pkg --build=*\")\n\n        c.assert_listed_binary({\"dep/0.1\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\", \"Build\"),\n                                \"pkg/0.1\": (\"59205ba5b14b8f4ebc216a6c51a89553021e82c1\", \"Build\")})\n        c.assert_listed_require({\"tool/0.1\": \"Cache\"}, build=True, test_package=True)\n        c.assert_listed_binary({\"tool/0.1\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\", \"Build\")},\n                               build=True, test_package=True)\n        # Note we do NOT rebuild the already built binaries\n        c.assert_listed_binary({\"dep/0.1\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\", \"Cache\"),\n                                \"pkg/0.1\": (\"59205ba5b14b8f4ebc216a6c51a89553021e82c1\", \"Cache\")},\n                               test_package=True)\n\n    def test_build_missing(self):\n        c = TestClient()\n        c.save({\"tool/conanfile.py\": GenConanfile(\"tool\", \"0.1\"),\n                \"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\"),\n                \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_requires(\"dep/0.1\"),\n                \"pkg/test_package/conanfile.py\": GenConanfile().with_tool_requires(\"tool/0.1\")\n                                                               .with_test(\"pass\")})\n        c.run(\"export tool\")\n        c.run(\"create dep\")\n        c.run(\"create pkg --build=missing\")\n        c.assert_listed_binary({\"dep/0.1\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\", \"Cache\"),\n                                \"pkg/0.1\": (\"59205ba5b14b8f4ebc216a6c51a89553021e82c1\", \"Build\")})\n        c.assert_listed_require({\"tool/0.1\": \"Cache\"}, build=True, test_package=True)\n        c.assert_listed_binary({\"tool/0.1\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\", \"Build\")},\n                               build=True, test_package=True)\n        c.assert_listed_binary({\"dep/0.1\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\", \"Cache\"),\n                                \"pkg/0.1\": (\"59205ba5b14b8f4ebc216a6c51a89553021e82c1\", \"Cache\")},\n                               test_package=True)\n\n    def test_build_test_package_dep(self):\n        c = TestClient()\n        c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\"),\n                \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\"),\n                \"pkg/test_package/conanfile.py\": GenConanfile().with_requires(\"dep/0.1\")\n                                                               .with_test(\"pass\")})\n        c.run(\"export dep\")\n        c.run('create pkg --build=missing --build-test=\"\"', assert_error=True)\n        c.assert_listed_binary({\"pkg/0.1\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\", \"Build\")})\n        c.assert_listed_binary({\"dep/0.1\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\", \"Missing\"),\n                                \"pkg/0.1\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\", \"Cache\")},\n                               test_package=True)\n        c.run(\"create pkg --build-test=missing\")\n        c.assert_listed_binary({\"pkg/0.1\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\", \"Build\")})\n        c.assert_listed_binary({\"dep/0.1\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\", \"Build\"),\n                                \"pkg/0.1\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\", \"Cache\")},\n                               test_package=True)\n\n\nclass TestConanTestTest:\n\n    def test_partial_reference(self):\n        # Create two packages to test with the same test\n        conanfile = '''\nfrom conan import ConanFile\n\nclass HelloConan(ConanFile):\n    name = \"hello\"\n    version = \"0.1\"\n'''\n        client = TestClient()\n        client.save({CONANFILE: conanfile})\n        client.run(\"create . --user=conan --channel=stable\")\n        client.run(\"create . --user=conan --channel=testing\")\n        client.run(\"create . --user=conan --channel=foo\")\n\n        def test(conanfile_test, test_reference, path=None):\n            path = path or \".\"\n            client.save({os.path.join(path, CONANFILE): conanfile_test}, clean_first=True)\n            client.run(\"test %s %s\" % (path, test_reference))\n\n        # Specify a valid name\n        test('''\nfrom conan import ConanFile\n\nclass HelloTestConan(ConanFile):\n    def requirements(self):\n        self.requires(self.tested_reference_str)\n    def test(self):\n        self.output.warning(\"Tested ok!\")\n''', \"hello/0.1@conan/stable\")\n        assert \"Tested ok!\" in client.out\n\n    def test_test_package_env(self):\n        client = TestClient()\n        conanfile = '''\nfrom conan import ConanFile\n\nclass HelloConan(ConanFile):\n    name = \"hello\"\n    version = \"0.1\"\n    def package_info(self):\n        self.buildenv_info.define(\"MYVAR\", \"new/pythonpath/value\")\n\n        '''\n        test_package = '''\nimport os, platform\nfrom conan import ConanFile\nfrom conan.tools.env import VirtualBuildEnv\n\nclass HelloTestConan(ConanFile):\n    generators = \"VirtualBuildEnv\"\n\n    def requirements(self):\n        self.build_requires(self.tested_reference_str)\n\n    def build(self):\n        build_env = VirtualBuildEnv(self).vars()\n        with build_env.apply():\n            assert(\"new/pythonpath/value\" in os.environ[\"MYVAR\"])\n\n    def test(self):\n        build_env = VirtualBuildEnv(self).vars()\n        with build_env.apply():\n            assert(\"new/pythonpath/value\" in os.environ[\"MYVAR\"])\n'''\n\n        client.save({\"conanfile.py\": conanfile, \"test_package/conanfile.py\": test_package})\n        client.run(\"create . --user=lasote --channel=testing\")\n        client.run(\"test test_package hello/0.1@lasote/testing\")\n\n    def test_fail_test_package(self):\n        client = TestClient()\n        conanfile = \"\"\"\nfrom conan import ConanFile\nfrom conan.tools.files import copy\n\nclass HelloConan(ConanFile):\n    name = \"hello\"\n    version = \"0.1\"\n    exports_sources = \"*\"\n\n    def package(self):\n        copy(self, \"*\", self.source_folder, self.package_folder)\n\"\"\"\n        test_conanfile = \"\"\"\nfrom conan import ConanFile\n\nclass HelloReuseConan(ConanFile):\n    def requirements(self):\n        self.requires(self.tested_reference_str)\n    def test(self):\n        pass\n\"\"\"\n        client.save({\"conanfile.py\": conanfile,\n                     \"FindXXX.cmake\": \"Hello FindCmake\",\n                     \"test/conanfile.py\": test_conanfile})\n        client.run(\"create . --user=lasote --channel=stable\")\n        ref = RecipeReference.loads(\"hello/0.1@lasote/stable\")\n        client.run(f\"test test {str(ref)}\")\n        pref = client.get_latest_package_reference(ref, NO_SETTINGS_PACKAGE_ID)\n        assert \"Hello FindCmake\" == load(os.path.join(client.get_latest_pkg_layout(pref).package(), \"FindXXX.cmake\"))\n        client.save({\"FindXXX.cmake\": \"Bye FindCmake\"})\n        client.run(f\"test test {str(ref)}\")  # Test do not rebuild the package\n        pref = client.get_latest_package_reference(ref, NO_SETTINGS_PACKAGE_ID)\n        assert \"Hello FindCmake\" == load(os.path.join(client.get_latest_pkg_layout(pref).package(), \"FindXXX.cmake\"))\n        client.run(\"create . --user=lasote --channel=stable\")  # create rebuild the package\n        pref = client.get_latest_package_reference(ref, NO_SETTINGS_PACKAGE_ID)\n        assert \"Bye FindCmake\" == load(os.path.join(client.get_latest_pkg_layout(pref).package(), \"FindXXX.cmake\"))\n\n\ndef test_no_reference_in_test_package():\n    client = TestClient()\n    test_conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        import os\n\n        class HelloReuseConan(ConanFile):\n            def test(self):\n                self.output.warning(\"At test: {}\".format(self.tested_reference_str))\n        \"\"\")\n\n    client.save({\"conanfile.py\": GenConanfile(), \"test_package/conanfile.py\": test_conanfile})\n    client.run(\"create . --name=foo --version=1.0\", assert_error=True)\n    assert \"doesn't declare any requirement, use `self.tested_reference_str` to require the \" \\\n           \"package being created\" in client.out\n\n\ndef test_tested_reference_str():\n    \"\"\"\n    At the test_package/conanfile the variable `self.tested_reference_str` is injected with the\n    str of the reference being tested. It is available in all the methods.\n    \"\"\"\n    client = TestClient()\n    test_conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    import os\n\n    class HelloReuseConan(ConanFile):\n\n        def generate(self):\n            self.output.warning(\"At generate: {}\".format(self.tested_reference_str))\n            assert len(self.dependencies.values()) == 1\n            assert len(self.dependencies.build.values()) == 1\n\n        def build(self):\n            self.output.warning(\"At build: {}\".format(self.tested_reference_str))\n\n        def build_requirements(self):\n            self.output.warning(\"At build_requirements: {}\".format(self.tested_reference_str))\n            self.build_requires(self.tested_reference_str)\n\n        def test(self):\n            self.output.warning(\"At test: {}\".format(self.tested_reference_str))\n    \"\"\")\n\n    client.save({\"conanfile.py\": GenConanfile(), \"test_package/conanfile.py\": test_conanfile})\n    client.run(\"create . --name=foo --version=1.0\")\n    for method in (\"generate\", \"build\", \"build_requirements\", \"test\"):\n        assert \"At {}: foo/1.0\".format(method) in client.out\n\n\ndef test_folder_output():\n    \"\"\" the \"conan test\" command should also follow the test_output layout folder\n    \"\"\"\n    c = TestClient()\n    c.save({\"conanfile.py\": GenConanfile(\"hello\", \"0.1\")})\n    c.run(\"create .\")\n    c.save({\"test_package/conanfile.py\": GenConanfile().with_test(\"pass\").with_settings(\"build_type\")\n                                                       .with_generator(\"CMakeDeps\")})\n    # c.run(\"create .\")\n    c.run(\"test test_package hello/0.1@\")\n    assert os.path.exists(os.path.join(c.current_folder,\n                                       \"test_package/hello-config.cmake\"))\n\n\ndef test_removing_test_package_build_folder():\n    \"\"\" The test_package could crash if not cleaning correctly the test_package\n    output folder. This will still crassh if the layout is not creating different build folders\n    \"\"\"\n    client = TestClient()\n    test_package = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import save\n        class Test(ConanFile):\n            def requirements(self):\n                self.requires(self.tested_reference_str)\n            def generate(self):\n                assert not os.path.exists(\"myfile.txt\")\n                save(self, \"myfile.txt\", \"\")\n            def layout(self):\n                self.folders.build = \"mybuild\"\n                self.folders.generators = \"mybuild\"\n            def test(self):\n                pass\n            \"\"\")\n    client.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\"),\n                 \"test_package/conanfile.py\": test_package})\n    client.run(\"create .\")\n    # This was crashing because not cleaned\n    client.run(\"create .\")\n    assert \"Removing previously existing 'test_package' build folder\" in client.out\n\n\ndef test_test_package_lockfile_location():\n    \"\"\" the lockfile should be in the caller cwd\n    https://github.com/conan-io/conan/issues/13850\n    \"\"\"\n    c = TestClient()\n    c.save({\"conanfile.py\": GenConanfile(\"dep\", \"0.1\"),\n            \"test_package/conanfile.py\": GenConanfile().with_test(\"pass\")})\n    c.run(\"create . --lockfile-out=myconan.lock\")\n    assert os.path.exists(os.path.join(c.current_folder, \"myconan.lock\"))\n    c.run(\"test test_package dep/0.1 --lockfile=myconan.lock --lockfile-out=myconan2.lock\")\n    assert os.path.exists(os.path.join(c.current_folder, \"myconan2.lock\"))\n\n\ndef test_package_missing_binary_msg():\n    # https://github.com/conan-io/conan/issues/13904\n    c = TestClient()\n    c.save({\"conanfile.py\": GenConanfile(\"dep\", \"0.1\"),\n            \"test_package/conanfile.py\": GenConanfile().with_test(\"pass\")})\n    c.run(\"export .\")\n    c.run(\"test test_package dep/0.1\", assert_error=True)\n    assert \"ERROR: Missing binary: dep/0.1\" in c.out\n    assert \"This is a **test_package** missing binary.\" in c.out\n    c.run(\"test test_package dep/0.1 --build=dep/0.1\")\n    c.assert_listed_binary({\"dep/0.1\": (NO_SETTINGS_PACKAGE_ID, \"Build\")})\n\n\ndef test_test_binary_missing():\n    # Trying to reproduce https://github.com/conan-io/conan/issues/14352,\n    # without success so far\n    c = TestClient()\n    c.save({\"zlib/conanfile.py\": GenConanfile(\"zlib\", \"0.1\"),\n            \"openssl/conanfile.py\": GenConanfile(\"openssl\", \"0.1\").with_requires(\"zlib/0.1\"),\n            \"cmake/conanfile.py\": GenConanfile(\"cmake\", \"0.1\").with_requires(\"openssl/0.1\"),\n            \"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\").with_requires(\"openssl/0.1\")\n                                                          .with_tool_requires(\"cmake/0.1\"),\n            \"dep/test_package/conanfile.py\": GenConanfile().with_test(\"pass\")})\n    c.run(\"export zlib\")\n    c.run(\"export openssl\")\n    c.run(\"export cmake\")\n    c.run(\"export dep\")\n    c.run(\"test dep/test_package dep/0.1 --build=missing\")\n"
  },
  {
    "path": "test/integration/command/test_profile.py",
    "content": "import json\nimport os\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_profile_path():\n    c = TestClient()\n    c.run(\"profile path default\")\n    assert \"default\" in c.out\n\n\ndef test_profile_path_missing():\n    c = TestClient()\n    c.run(\"profile path notexisting\", assert_error=True)\n    assert \"ERROR: Profile not found: notexisting\" in c.out\n\n\ndef test_ignore_paths_when_listing_profiles():\n    c = TestClient()\n    ignore_path = '.DS_Store'\n\n    # just in case\n    os.makedirs(c.paths.profiles_path, exist_ok=True)\n    # This a \"touch\" equivalent\n    open(os.path.join(c.paths.profiles_path, '.DS_Store'), 'w').close()\n    os.utime(os.path.join(c.paths.profiles_path, \".DS_Store\"))\n\n    c.run(\"profile list\")\n\n    assert ignore_path not in c.out\n\n\ndef test_shorthand_syntax():\n    tc = TestClient()\n    tc.save({\"profile\": \"[conf]\\nuser:profile=True\"})\n    tc.run(\"profile show -h\")\n    assert \"[-pr:b\" in tc.out\n    assert \"[-pr:h\" in tc.out\n    assert \"[-pr:a\" in tc.out\n\n    tc.run(\n        \"profile show -o:a=both_options=True -pr:a=profile -s:a=os=WindowsCE -s:a=os.platform=conan -c:a=user.conf:cli=True -f=json\")\n\n    out = json.loads(tc.stdout)\n    assert out == {'build': {'build_env': '',\n                             'conf': {'user.conf:cli': True, 'user:profile': True},\n                             'options': {'both_options': 'True'},\n                             'package_settings': {},\n                             'settings': {'os': 'WindowsCE', 'os.platform': 'conan'},\n                             'tool_requires': {}},\n                   'host': {'build_env': '',\n                            'conf': {'user.conf:cli': True, 'user:profile': True},\n                            'options': {'both_options': 'True'},\n                            'package_settings': {},\n                            'settings': {'os': 'WindowsCE', 'os.platform': 'conan'},\n                            'tool_requires': {}}}\n\n    tc.save({\"pre\": textwrap.dedent(\"\"\"\n            [settings]\n            os=Linux\n            compiler=gcc\n            compiler.version=11\n            \"\"\"),\n             \"mid\": textwrap.dedent(\"\"\"\n            [settings]\n            compiler=clang\n            compiler.version=14\n            \"\"\"),\n             \"post\": textwrap.dedent(\"\"\"\n            [settings]\n            compiler.version=13\n            \"\"\")})\n\n    tc.run(\"profile show -pr:a=pre -pr:a=mid -pr:a=post -f=json\")\n    out = json.loads(tc.stdout)\n    assert out == {'build': {'build_env': '',\n                             'conf': {},\n                             'options': {},\n                             'package_settings': {},\n                             'settings': {'compiler': 'clang',\n                                          'compiler.version': '13',\n                                          'os': 'Linux'},\n                             'tool_requires': {}},\n                   'host': {'build_env': '',\n                            'conf': {},\n                            'options': {},\n                            'package_settings': {},\n                            'settings': {'compiler': 'clang',\n                                         'compiler.version': '13',\n                                         'os': 'Linux'},\n                            'tool_requires': {}}}\n\n    tc.run(\"profile show -pr:a=pre -pr:h=post -f=json\")\n    out = json.loads(tc.stdout)\n    assert out == {'build': {'build_env': '',\n                             'conf': {},\n                             'options': {},\n                             'package_settings': {},\n                             'settings': {'compiler': 'gcc',\n                                          'compiler.version': '11',\n                                          'os': 'Linux'},\n                             'tool_requires': {}},\n                   'host': {'build_env': '',\n                            'conf': {},\n                            'options': {},\n                            'package_settings': {},\n                            'settings': {'compiler': 'gcc',\n                                         'compiler.version': '13',\n                                         'os': 'Linux'},\n                            'tool_requires': {}}}\n\n    tc.run(\"profile show -pr:a=pre -o:b foo=False -o:a foo=True -o:h foo=False -f=json\")\n    out = json.loads(tc.stdout)\n    assert out == {'build': {'build_env': '',\n                             'conf': {},\n                             'options': {'foo': 'True'},\n                             'package_settings': {},\n                             'settings': {'compiler': 'gcc',\n                                          'compiler.version': '11',\n                                          'os': 'Linux'},\n                             'tool_requires': {}},\n                   'host': {'build_env': '',\n                            'conf': {},\n                            'options': {'foo': 'False'},\n                            'package_settings': {},\n                            'settings': {'compiler': 'gcc',\n                                         'compiler.version': '11',\n                                         'os': 'Linux'},\n                            'tool_requires': {}}}\n    tc.run(\"profile show -o:shared=True\", assert_error=True)\n    assert 'Invalid empty package name in options. Use a pattern like `mypkg/*:shared`' in tc.out\n\n\ndef test_profile_show_json():\n    c = TestClient()\n    c.save({\"myprofilewin\": \"[settings]\\nos=Windows\\n\"\n                            \"[tool_requires]\\nmytool/*:mytool/1.0\\n\"\n                            \"[conf]\\nuser.conf:value=42\\nlibiconv/*:tools.env.virtualenv:powershell=False\\n\"\n                            \"[options]\\n*:myoption=True\\n\"\n                            \"[replace_requires]\\ncmake/*: cmake/3.29.0\\n\"\n                            \"[platform_requires]\\ncmake/3.29.0\\n\",\n            \"myprofilelinux\": \"[settings]\\nos=Linux\"})\n    c.run(\"profile show -pr:b=myprofilewin -pr:h=myprofilelinux --format=json\")\n\n    profile = json.loads(c.stdout)\n    assert profile[\"host\"][\"settings\"] == {\"os\": \"Linux\"}\n\n    assert profile[\"build\"][\"settings\"] == {\"os\": \"Windows\"}\n    # Check that tool_requires are properly serialized in json format\n    # https://github.com/conan-io/conan/issues/15183\n    assert profile[\"build\"][\"tool_requires\"] == {'mytool/*': [\"mytool/1.0\"]}\n\n\n@pytest.mark.parametrize(\"new_global\", [None, 0, 1, True, False, \"\"])\ndef test_settings_serialize(new_global):\n    tc = TestClient(light=True)\n    settings_user = \"new_global: [null, 0, 1, True, False, '']\"\n    tc.save_home({\"settings_user.yml\": settings_user})\n    tc.save({\"conanfile.py\": GenConanfile(\"foo\", \"1.0\").with_settings(\"new_global\")})\n\n    s = f\"-s new_global={new_global}\" if new_global is not None else \"\"\n    tc.run(f\"create . {s}\")\n    if new_global is None:\n        assert \"settings: new_global=\" not in tc.out\n    else:\n        assert f\"settings: new_global={new_global}\" in tc.out\n"
  },
  {
    "path": "test/integration/command/test_run.py",
    "content": "import textwrap\n\nimport pytest\nimport platform\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\nexecutable = \"myapp.bat\" if platform.system() == \"Windows\" else \"myapp.sh\"\n\n\n@pytest.fixture(scope=\"module\")\ndef client():\n    tc = TestClient(default_server_user=True)\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import save\n        import os\n\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            # So that the requirement is run=True even for --requires\n            package_type = \"application\"\n            options = {\"foo\": [True, False, \"bar\"]}\n            default_options = {\"foo\": True}\n            settings = \"os\"\n\n            def package(self):\n                executable = os.path.join(self.package_folder, \"bin\", '\"\"\" + executable + \"\"\"')\n                save(self, executable, f\"echo Hello World! foo={self.options.foo}\")\n                # Make it executable\n                os.chmod(executable, 0o755)\n        \"\"\")\n    tc.save({\"pkg/conanfile.py\": conanfile})\n    tc.run(\"create pkg\")\n    return tc\n\n\n@pytest.mark.parametrize(\"context_flag\", [\"host\", \"build\", None])\n@pytest.mark.parametrize(\"requires_context\", [\"host\", \"build\",])\n@pytest.mark.parametrize(\"use_conanfile\", [True, False])\ndef test_run(client, context_flag, requires_context, use_conanfile):\n    context_arg = {\n        \"host\": \"--context=host\",\n        \"build\": \"--context=build\",\n        None: \"\",\n    }.get(context_flag)\n    should_find_binary = (context_flag == requires_context) or (context_flag is None)\n    if use_conanfile:\n        conanfile_consumer = GenConanfile(\"consumer\", \"1.0\").with_settings(\"os\")\n        if requires_context == \"host\":\n            conanfile_consumer.with_requires(\"pkg/0.1\")\n        else:\n            conanfile_consumer.with_tool_requires(\"pkg/0.1\")\n\n        client.save({\"conanfile.py\": conanfile_consumer})\n        client.run(f\"run {executable} {context_arg}\", assert_error=not should_find_binary)\n    else:\n        requires = \"requires\" if requires_context == \"host\" else \"tool-requires\"\n        client.run(f\"run {executable} --{requires}=pkg/0.1 {context_arg}\",\n                   assert_error=not should_find_binary)\n    if should_find_binary:\n        assert \"Hello World!\" in client.out\n    else:\n        if platform.system() == \"Windows\":\n            assert \"not recognized as an internal or external command\" in client.out\n        else:\n            assert \"Error 127 while executing\" in client.out\n\n\ndef test_run_context_priority(client):\n    client.run(\"create pkg -o=pkg/*:foo=False\")\n\n    client.run(f\"run {executable} --requires=pkg/0.1 --tool-requires=pkg/0.1 -o:b=pkg/*:foo=False\")\n    # True is host, False is build, run gives priority to host\n    assert \"Hello World! foo=True\" in client.out\n\n\ndef test_run_missing_executable(client):\n    client.run(f\"run a-binary-name-that-does-not-exist --requires=pkg/0.1\", assert_error=True)\n    if platform.system() == \"Windows\":\n        assert \"not recognized as an internal or external command\" in client.out\n    else:\n        assert \"Error 127 while executing\" in client.out\n\n\ndef test_run_missing_binary(client):\n    client.run(\"run foo --requires=pkg/0.1 -o=pkg/*:foo=bar\", assert_error=True)\n    assert \"Error installing the dependencies\" in client.out\n    assert \"Missing prebuilt package for 'pkg/0.1'\" in client.out\n\n\ndef test_run_missing_package(client):\n    client.run(\"run foo --requires=pkg/2.1\", assert_error=True)\n    assert \"Error installing the dependencies\" in client.out\n    assert \"Package 'pkg/2.1' not resolved\" in client.out\n\n\n@pytest.mark.skipif(platform.system() == \"Windows\", reason=\"Unix only\")\ndef test_run_status_is_propagated(client):\n    client.run(\"run false --requires=pkg/0.1\", assert_error=True)\n    assert \"Error installing the dependencies\" not in client.out\n    assert \"ERROR: Error 1 while executing\" in client.out\n"
  },
  {
    "path": "test/integration/command/test_version.py",
    "content": "from conan.test.utils.tools import TestClient\nfrom conan import __version__\nimport json\nimport platform\nimport sys\n\n\ndef _python_version():\n    return platform.python_version().replace(\"\\n\", \"\")\n\n\ndef _sys_version():\n    return sys.version.replace(\"\\n\", \"\")\n\n\ndef test_version_json():\n    \"\"\"\n    Conan version command should be able to output a json with the version and python version.\n    \"\"\"\n    t = TestClient()\n    t.run(\"version --format=json\")\n    js = json.loads(t.stdout)\n    assert js[\"version\"] == __version__\n    assert js[\"conan_path\"] == sys.argv[0]\n    assert js[\"python\"][\"version\"] == _python_version()\n    assert js[\"python\"][\"sys_version\"] == _sys_version()\n    assert js[\"python\"][\"sys_executable\"] == sys.executable\n    assert js[\"python\"][\"is_frozen\"] == getattr(sys, 'frozen', False)\n    assert js[\"python\"][\"architecture\"] == platform.machine()\n    assert js[\"system\"][\"version\"] == platform.version()\n    assert js[\"system\"][\"platform\"] == platform.platform()\n    assert js[\"system\"][\"system\"] == platform.system()\n    assert js[\"system\"][\"release\"] == platform.release()\n    assert js[\"system\"][\"cpu\"] == platform.processor()\n\n\ndef test_version_text():\n    \"\"\"\n    Conan version command should be able to output a raw text with the version and python version.\n    \"\"\"\n    t = TestClient()\n    t.run(\"version --format=text\")\n    _validate_text_output(t.out)\n\n\ndef test_version_raw():\n    \"\"\"\n    Conan version command should be able to output a raw text with the version and python version,\n    when no format is specified.\n    \"\"\"\n    t = TestClient()\n    t.run(\"version\")\n    _validate_text_output(t.out)\n\n\ndef _validate_text_output(output):\n    lines = output.splitlines()\n    assert f'version: {__version__}' in lines\n    assert f'conan_path: {sys.argv[0]}' in lines\n    assert 'python' in lines\n    assert f'  version: {_python_version()}' in lines\n    assert f'  sys_version: {_sys_version()}' in lines\n    assert f'  sys_executable: {sys.executable}' in lines\n    assert f'  is_frozen: {getattr(sys, \"frozen\", False)}' in lines\n    assert f'  architecture: {platform.machine()}' in lines\n    assert 'system' in lines\n    assert f'  version: {platform.version()}' in lines\n    assert f'  platform: {platform.platform()}' in lines\n    assert f'  system: {platform.system()}' in lines\n    assert f'  release: {platform.release()}' in lines\n    assert f'  cpu: {platform.processor()}' in lines\n"
  },
  {
    "path": "test/integration/command/upload/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/command/upload/test_upload_bundle.py",
    "content": "import json\nimport os\nimport textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_upload_pkg_list():\n    \"\"\" Test how a custom command can create an upload pkglist and print it\n    \"\"\"\n    c = TestClient(default_server_user=True, light=True)\n    mycommand = textwrap.dedent(\"\"\"\n        import json\n        import os\n\n        from conan.cli.command import conan_command, OnceArgument\n        from conan.api.model import ListPattern\n        from conan.api.output import cli_out_write\n\n        @conan_command(group=\"custom commands\")\n        def upload_pkglist(conan_api, parser, *args, **kwargs):\n            \\\"\"\"\n            create an upload pkglist\n            \\\"\"\"\n            parser.add_argument('reference',\n                                help=\"Recipe reference or package reference, can contain * as \"\n                                      \"wildcard at any reference field.\")\n            # using required, we may want to pass this as a positional argument?\n            parser.add_argument(\"-r\", \"--remote\", action=OnceArgument, required=True,\n                                help='Upload to this specific remote')\n            args = parser.parse_args(*args)\n\n            remote = conan_api.remotes.get(args.remote)\n            enabled_remotes = conan_api.remotes.list()\n\n            ref_pattern = ListPattern(args.reference, package_id=\"*\")\n            package_list = conan_api.list.select(ref_pattern)\n            if not package_list:\n                raise ConanException(\"No recipes found matching pattern '{}'\".format(args.reference))\n\n            # Check if the recipes/packages are in the remote\n            conan_api.upload.check_upstream(package_list, remote, enabled_remotes)\n            conan_api.upload.prepare(package_list, enabled_remotes)\n            cli_out_write(json.dumps(package_list.serialize(), indent=4))\n        \"\"\")\n\n    command_file_path = os.path.join(c.cache_folder, 'extensions',\n                                     'commands', 'cmd_upload_pkglist.py')\n    c.save({command_file_path: mycommand})\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n    c.run(\"create .\")\n    c.run('upload-pkglist \"*\" -r=default', redirect_stdout=\"mypkglist.json\")\n    pkglist = c.load(\"mypkglist.json\")\n    pkglist = json.loads(pkglist)\n    assert pkglist[\"pkg/0.1\"][\"revisions\"][\"485dad6cb11e2fa99d9afbe44a57a164\"][\"upload\"] is True\n"
  },
  {
    "path": "test/integration/command/upload/test_upload_parallel.py",
    "content": "from requests import ConnectionError\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient, TestRequester\n\n\ndef test_upload_parallel_error():\n    \"\"\"Cause an error in the parallel transfer and see some message\"\"\"\n\n    class FailOnReferencesUploader(TestRequester):\n        fail_on = [\"lib1\", \"lib3\"]\n\n        def put(self, *args, **kwargs):\n            if any(ref in args[0] for ref in self.fail_on):\n                raise ConnectionError(\"Connection fails with lib2 and lib4 references!\")\n            else:\n                return super(FailOnReferencesUploader, self).put(*args, **kwargs)\n\n    client = TestClient(requester_class=FailOnReferencesUploader, default_server_user=True)\n    client.save_home({\"global.conf\": f\"core.upload:parallel=2\\ncore.upload:retry_wait=0\"})\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run('remote login default admin -p password')\n    for index in range(4):\n        client.run('create . --name=lib{} --version=1.0 --user=user --channel=channel'.format(index))\n    client.run('upload lib* -c -r default', assert_error=True)\n    assert \"Connection fails with lib2 and lib4 references!\" in client.out\n    assert \"Execute upload again to retry upload the failed files\" in client.out\n\n\ndef test_upload_parallel_success():\n    \"\"\"Upload 2 packages in parallel with success\"\"\"\n\n    client = TestClient(default_server_user=True)\n    client.save_home({\"global.conf\": f\"core.upload:parallel=2\"})\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run('create . --name=lib0 --version=1.0 --user=user --channel=channel')\n    client.run('create . --name=lib1 --version=1.0 --user=user --channel=channel')\n    client.run('remote login default admin -p password')\n    client.run('upload lib* -c -r default')\n    assert \"Uploading recipe 'lib0/1.0@user/channel#4d670581ccb765839f2239cc8dff8fbd'\" in client.out\n    assert \"Uploading recipe 'lib1/1.0@user/channel#4d670581ccb765839f2239cc8dff8fbd'\" in client.out\n    client.run('search lib0/1.0@user/channel -r default')\n    assert \"lib0/1.0@user/channel\" in client.out\n    client.run('search lib1/1.0@user/channel -r default')\n    assert \"lib1/1.0@user/channel\" in client.out\n\n\ndef test_upload_parallel_fail_on_interaction():\n    \"\"\"Upload 2 packages in parallel and fail because non_interactive forced\"\"\"\n    client = TestClient(default_server_user=True)\n    client.save_home({\"global.conf\": f\"core.upload:parallel=2\\ncore:non_interactive=True\"})\n    client.save({\"conanfile.py\": GenConanfile()})\n    num_references = 2\n    for index in range(num_references):\n        client.run('create . --name=lib{} --version=1.0 --user=user --channel=channel'.format(index))\n\n    client.run('remote logout default')\n    client.run('upload lib* -c -r default', assert_error=True)\n    assert \"ERROR: Conan interactive mode disabled. [Remote: default]\" in client.out\n"
  },
  {
    "path": "test/integration/command/upload/test_upload_patterns.py",
    "content": "import re\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\nfrom conan.test.utils.env import environment_update\n\n\nclass TestUploadPatterns:\n    @pytest.fixture(scope=\"class\")  # Takes 6 seconds, reuse it\n    def client(self):\n        \"\"\" create a few packages, with several recipe revisions, several pids, several prevs\n        \"\"\"\n        client = TestClient(default_server_user=True)\n\n        for pkg in (\"pkga\", \"pkgb\"):\n            for version in (\"1.0\", \"1.1\"):\n                for rrev in (\"rev1\", \"rev2\"):\n                    client.save({\"conanfile.py\": GenConanfile().with_settings(\"os\")\n                                .with_class_attribute(f\"potato='{rrev}'\")\n                                .with_package_file(\"file\", env_var=\"MYVAR\")})\n                    for the_os in (\"Windows\", \"Linux\"):\n                        for prev in (\"prev1\", \"prev2\"):\n                            with environment_update({\"MYVAR\": prev}):\n                                client.run(f\"create . --name={pkg} --version={version} \"\n                                           f\"-s os={the_os}\")\n        return client\n\n    @staticmethod\n    def assert_uploaded(pattern, result, client, only_recipe=False, query=None):\n        def ref_map(r):\n            rev1 = \"ad55a66b62acb63ffa99ea9b75c16b99\"\n            rev2 = \"127fb537a658ad6a57153a038960dc53\"\n            pid1 = \"ebec3dc6d7f6b907b3ada0c3d3cdc83613a2b715\"\n            pid2 = \"9a4eb3c8701508aa9458b1a73d0633783ecc2270\"\n            if \"Linux\" in r:\n                prev1 = \"7ce684c6109943482b9174dd089e717b\"\n                prev2 = \"772234192e8e4ba71b018d2e7c02423e\"\n            else:\n                prev1 = \"45f88f3c318bd43d1bc48a5d408a57ef\"\n                prev2 = \"c5375d1f517ecb1ed6c9532b0f4d86aa\"\n\n            r = r.replace(\"prev1\", prev1).replace(\"prev2\", prev2).replace(\"Windows\", pid1)\n            r = r.replace(\"Linux\", pid2).replace(\"rev1\", rev1).replace(\"rev2\", rev2)\n            return r\n\n        pattern = ref_map(pattern)\n        only_recipe = \"\" if not only_recipe else \"--only-recipe\"\n        query = \"\" if not query else f\"-p={query}\"\n        client.run(f\"upload {pattern} -r=default -c {only_recipe} {query}\")\n        out = str(client.out)\n\n        uploaded_recipes = [f\"{p}/{v}#{rr}\" for p in result[0]\n                            for v in result[1]\n                            for rr in result[2]]\n        uploaded_packages = [f\"{r}:{pid}#{pr}\" for r in uploaded_recipes\n                             for pid in result[3]\n                             for pr in result[4]]\n\n        # Checks\n        upload_recipe_count = out.count(\"Uploading recipe\")\n        skipped_recipe_count = len(re.findall(\"Recipe '.+' already in server, skipping\", out))\n        assert upload_recipe_count + skipped_recipe_count == len(uploaded_recipes)\n        for recipe in uploaded_recipes:\n            recipe = ref_map(recipe)\n            upload = f\"Uploading recipe '{recipe}\" in out\n            existing = f\"Recipe '{recipe}' already in server\" in out\n            assert upload or existing\n        upload_pkg_count = out.count(\"Uploading package\")\n        skipped_pkg_count = len(re.findall(\"Package '.+' already in server, skipping\", out))\n        assert upload_pkg_count + skipped_pkg_count == len(uploaded_packages)\n        for pkg in uploaded_packages:\n            pkg = ref_map(pkg)\n            upload = f\"Uploading package '{pkg}\" in out\n            existing = f\"Package '{pkg}' already in server\" in out\n            assert upload or existing\n\n    def test_all_latest(self, client):\n        result = (\"pkga\", \"pkgb\"), (\"1.0\", \"1.1\"), (\"rev2\",), (\"Windows\", \"Linux\"), (\"prev2\",)\n        self.assert_uploaded(\"*\", result, client)\n\n    def test_all(self, client):\n        result = (\"pkga\", \"pkgb\"), (\"1.0\", \"1.1\"), (\"rev1\", \"rev2\",), (\"Windows\", \"Linux\"), \\\n                 (\"prev1\", \"prev2\")\n        self.assert_uploaded(\"*#*:*#*\", result, client)\n\n    def test_pkg(self, client):\n        result = (\"pkga\",), (\"1.0\", \"1.1\"), (\"rev2\",), (\"Windows\", \"Linux\"), (\"prev2\",)\n        self.assert_uploaded(\"pkga\", result, client)\n        # equivalent to using explicitly latest\n        self.assert_uploaded(\"pkga#latest\", result, client)\n\n    def test_pkg_rrev(self, client):\n        result = (\"pkga\",), (\"1.0\", \"1.1\"), (\"rev1\",), (\"Windows\", \"Linux\"), (\"prev2\",)\n        self.assert_uploaded(\"pkga#rev1\", result, client)\n        # equivalent to using explicitly latest\n        self.assert_uploaded(\"pkga#rev1:*#latest\", result, client)\n\n    def test_pkg_rrevs(self, client):\n        result = (\"pkga\",), (\"1.0\", \"1.1\"), (\"rev1\", \"rev2\"), (\"Windows\", \"Linux\"), (\"prev2\",)\n        self.assert_uploaded(\"pkga#*\", result, client)\n\n    def test_pkg_pid(self, client):\n        result = (\"pkga\",), (\"1.0\", \"1.1\"), (\"rev2\",), (\"Windows\",), (\"prev2\",)\n        self.assert_uploaded(\"pkga:Windows\", result, client)\n        self.assert_uploaded(\"pkga:Windows#latest\", result, client)\n\n    def test_pkg_rrev_pid(self, client):\n        result = (\"pkga\",), (\"1.0\", \"1.1\"), (\"rev1\",), (\"Windows\",), (\"prev2\",)\n        self.assert_uploaded(\"pkga#rev1:Windows\", result, client)\n\n    def test_pkg_rrevs_pid(self, client):\n        result = (\"pkga\",), (\"1.0\", \"1.1\"), (\"rev1\", \"rev2\"), (\"Windows\",), (\"prev2\",)\n        self.assert_uploaded(\"pkga#*:Windows\", result, client)\n\n    def test_pkg_rrev_pid_prev(self, client):\n        result = (\"pkga\",), (\"1.0\", \"1.1\"), (\"rev1\",), (\"Windows\",), (\"prev1\",)\n        self.assert_uploaded(\"pkga#rev1:Windows#prev1\", result, client)\n\n    # Only recipes\n    def test_all_latest_only_recipe(self, client):\n        result = (\"pkga\", \"pkgb\"), (\"1.0\", \"1.1\"), (\"rev2\",), (), ()\n        self.assert_uploaded(\"*\", result, client, only_recipe=True)\n\n    def test_pkg_only_recipe(self, client):\n        result = (\"pkga\",), (\"1.0\", \"1.1\"), (\"rev2\",), (), ()\n        self.assert_uploaded(\"pkga\", result, client, only_recipe=True)\n\n    def test_pkg_rrev_only_recipe(self, client):\n        result = (\"pkga\",), (\"1.0\", \"1.1\"), (\"rev1\",), (), ()\n        self.assert_uploaded(\"pkga#rev1\", result, client, only_recipe=True)\n\n    def test_pkg_rrevs_only_recipe(self, client):\n        result = (\"pkga\",), (\"1.0\", \"1.1\"), (\"rev1\", \"rev2\"), (), ()\n        self.assert_uploaded(\"pkga#*\", result, client, only_recipe=True)\n\n    # Package query\n    def test_pkg_query(self, client):\n        result = (\"pkga\",), (\"1.0\", \"1.1\"), (\"rev2\",), (\"Windows\",), (\"prev2\",)\n        self.assert_uploaded(\"pkga\", result, client, query=\"os=Windows\")\n\n\nclass TestUploadPatternErrors:\n\n    @pytest.fixture(scope=\"class\")\n    def client(self):\n        client = TestClient(default_server_user=True)\n        client.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n        client.run(f\"create .\")\n        return client\n\n    @staticmethod\n    def assert_error(pattern, error, client, only_recipe=False, query=None):\n        only_recipe = \"\" if not only_recipe else \"--only-recipe\"\n        query = \"\" if not query else f\"-p={query}\"\n        client.run(f\"upload {pattern} -r=default {only_recipe} {query}\", assert_error=True)\n        assert error in client.out\n\n    def test_recipe_not_found(self, client):\n        error = \"ERROR: Recipe 'zlib/1.2.11' not found\"\n        self.assert_error(\"zlib/1.2.11\", error, client)\n\n    def test_rrev_not_found(self, client):\n        error = \"ERROR: Recipe revision 'pkg/0.1#rev1' not found\"\n        self.assert_error(\"pkg/0.1#rev1\", error, client)\n\n    def test_pid_not_found(self, client):\n        rrev = \"485dad6cb11e2fa99d9afbe44a57a164\"\n        error = \"ERROR: Binary package not found: 'pkg/0.1:pid1\"\n        self.assert_error(f\"pkg/0.1#{rrev}:pid1\", error, client)\n\n    def test_prev_not_found(self, client):\n        rrev = \"485dad6cb11e2fa99d9afbe44a57a164\"\n        pid = \"da39a3ee5e6b4b0d3255bfef95601890afd80709\"\n        error = f\"ERROR: Package revision 'pkg/0.1#{rrev}:{pid}#prev' not found\"\n        self.assert_error(f\"pkg/0.1#{rrev}:{pid}#prev\", error, client)\n\n    def test_bad_package_query(self, client):\n        error = \"Invalid package query: blah. Invalid expression: blah\"\n        self.assert_error(\"* -p blah\", error, client)\n"
  },
  {
    "path": "test/integration/command/upload/upload_complete_test.py",
    "content": "import os\n\nfrom requests import ConnectionError\n\nfrom conan.internal.paths import CONAN_MANIFEST\nfrom conan.test.utils.tools import TestClient, TestRequester, TestServer, GenConanfile\nfrom conan.test.utils.env import environment_update\n\n\nclass BadConnectionUploader(TestRequester):\n    fail_on = 1\n\n    def __init__(self, *args, **kwargs):\n        super(BadConnectionUploader, self).__init__(*args, **kwargs)\n        self.counter_fail = 0\n\n    def put(self, *args, **kwargs):\n        self.counter_fail += 1\n        if self.counter_fail == self.fail_on:\n            raise ConnectionError(\"Can't connect because of the evil mock\")\n        else:\n            return super(BadConnectionUploader, self).put(*args, **kwargs)\n\n\nclass TerribleConnectionUploader(BadConnectionUploader):\n    def put(self, *args, **kwargs):\n        raise ConnectionError(\"Can't connect because of the evil mock\")\n\n\nclass FailPairFilesUploader(BadConnectionUploader):\n\n    def put(self, *args, **kwargs):\n        self.counter_fail += 1\n        if self.counter_fail % 2 == 1:\n            raise ConnectionError(\"Pair file, error!\")\n        else:\n            return super(BadConnectionUploader, self).put(*args, **kwargs)\n\n\ndef test_try_upload_bad_recipe():\n    client = TestClient(default_server_user=True, light=True)\n    client.save({\"conanfile.py\": GenConanfile(\"hello0\", \"1.2.1\")})\n    client.run(\"export . --user=frodo --channel=stable\")\n    layout = client.exported_layout()\n    os.unlink(os.path.join(layout.export(), CONAN_MANIFEST))\n    client.run(\"upload %s -r default\" % str(layout.reference), assert_error=True)\n    assert \"Cannot upload corrupted recipe\" in client.out\n\n\ndef test_upload_with_pattern():\n    client = TestClient(default_server_user=True, light=True)\n    for num in range(3):\n        client.save({\"conanfile.py\": GenConanfile(\"hello{}\".format(num), \"1.2.1\")})\n        client.run(\"export . --user=frodo --channel=stable\")\n\n    client.run(\"upload hello* --confirm -r default\")\n    for num in range(3):\n        assert \"Uploading recipe 'hello%s/1.2.1@frodo/stable\" % num in client.out\n\n    client.run(\"upload hello0* --confirm -r default\")\n    assert f\"'hello0/1.2.1@frodo/stable#761f54e34d59deb172d6078add7050a7' \"\\\n           \"already in server, skipping upload\" in client.out\n    assert \"hello1\" not in client.out\n    assert \"hello2\" not in client.out\n\n\ndef test_check_upload_confirm_question():\n    server = TestServer()\n    client = TestClient(servers={\"default\": server},\n                        inputs=[\"yes\", \"admin\", \"password\", \"n\", \"n\", \"n\"], light=True)\n    client.save({\"conanfile.py\": GenConanfile(\"hello1\", \"1.2.1\")})\n    client.run(\"export . --user=frodo --channel=stable\")\n    client.run(\"upload hello* -r default\")\n\n    assert \"Uploading recipe 'hello1/1.2.1@frodo/stable\" in client.out\n\n    client.save({\"conanfile.py\": GenConanfile(\"hello2\", \"1.2.1\")})\n    client.run(\"create . --user=frodo --channel=stable\")\n    client.run(\"upload hello* -r default\")\n\n    assert \"Uploading recipe 'hello2/1.2.1@frodo/stable\" not in client.out\n\n\ndef test_check_upload_confirm_question_yes():\n    server = TestServer()\n    client = TestClient(servers={\"default\": server},\n                        inputs=[\"yes\", \"yes\", \"yes\", \"yes\", \"yes\", \"admin\", \"password\"],\n                        light=True)\n    client.save({\"conanfile.py\": GenConanfile(\"hello1\", \"1.2.1\")})\n    client.run(\"create . \")\n    client.save({\"conanfile.py\": GenConanfile(\"hello1\", \"1.2.1\").with_package_file(\"file.txt\",\n                                                                                   env_var=\"MYVAR\")})\n\n    with environment_update({\"MYVAR\": \"0\"}):\n        client.run(\"create . \")\n    with environment_update({\"MYVAR\": \"1\"}):\n        client.run(\"create . \")\n    client.run(\"upload hello*#*:*#* -r default\")\n    assert str(client.out).count(\"(Uploaded)\") == 5\n\n\nclass TestUpload:\n\n    def _get_client(self, requester=None):\n        servers = {}\n        # All can write (for avoid authentication until we mock user_io)\n        self.test_server = TestServer([(\"*/*@*/*\", \"*\")], [(\"*/*@*/*\", \"*\")],\n                                      users={\"lasote\": \"mypass\"})\n        servers[\"default\"] = self.test_server\n        test_client = TestClient(servers=servers, inputs=[\"lasote\", \"mypass\"],\n                                 requester_class=requester, light=True)\n        return test_client\n\n    def test_upload_error(self):\n        \"\"\"Cause an error in the transfer and see some message\"\"\"\n\n        # Check for the default behaviour\n        client = self._get_client(BadConnectionUploader)\n        files = {\"conanfile.py\": GenConanfile(\"hello0\", \"1.2.1\").with_exports(\"*\")}\n        client.save(files)\n        client.run(\"export . --user=frodo --channel=stable\")\n        client.run(\"upload hello* --confirm -r default\")\n        assert \"Can't connect because of the evil mock\" in client.out\n        assert \"Waiting 5 seconds to retry...\" in client.out\n\n        # This will fail in the first put file, so, as we need to\n        # upload 3 files (conanmanifest, conanfile and tgz) will do it with 2 retries\n        client = self._get_client(BadConnectionUploader)\n        files = {\"conanfile.py\": GenConanfile(\"hello0\", \"1.2.1\").with_exports(\"*\")}\n        client.save(files)\n        client.run(\"export . --user=frodo --channel=stable\")\n        self._set_global_conf(client, retry_wait=0)\n        client.run(\"upload hello* --confirm -r default\")\n        assert \"Can't connect because of the evil mock\" in client.out\n        assert \"Waiting 0 seconds to retry...\" in client.out\n\n        # but not with 0\n        client = self._get_client(BadConnectionUploader)\n        files = {\"conanfile.py\": GenConanfile(\"hello0\", \"1.2.1\").with_exports(\"*\"),\n                 \"somefile.txt\": \"\"}\n        client.save(files)\n        client.run(\"export . --user=frodo --channel=stable\")\n        self._set_global_conf(client, retry=0, retry_wait=1)\n        client.run(\"upload hello* --confirm -r default\", assert_error=True)\n        assert \"Waiting 1 seconds to retry...\" not in client.out\n        assert (\"Execute upload again to retry upload the failed files: \"\n                \"conan_export.tgz. [Remote: default]\") in client.out\n\n        # Try with broken connection even with 10 retries\n        client = self._get_client(TerribleConnectionUploader)\n        files = {\"conanfile.py\": GenConanfile(\"hello0\", \"1.2.1\").with_exports(\"*\")}\n        client.save(files)\n        client.run(\"export . --user=frodo --channel=stable\")\n        self._set_global_conf(client, retry=10, retry_wait=0)\n        client.run(\"upload hello* --confirm -r default\", assert_error=True)\n        assert \"Waiting 0 seconds to retry...\" in client.out\n        assert \"Execute upload again to retry upload the failed files\" in client.out\n\n        # For each file will fail the first time and will success in the second one\n        client = self._get_client(FailPairFilesUploader)\n        files = {\"conanfile.py\": GenConanfile(\"hello0\", \"1.2.1\").with_exports(\"*\")}\n        client.save(files)\n        client.run(\"export . --user=frodo --channel=stable\")\n        client.run(\"install --requires=hello0/1.2.1@frodo/stable --build='*' -r default\")\n        self._set_global_conf(client, retry=3, retry_wait=0)\n        client.run(\"upload hello* --confirm -r default\")\n        assert str(client.out).count(\"WARN: network: Pair file, error!\") == 5\n\n    @staticmethod\n    def _set_global_conf(client, retry=None, retry_wait=None):\n        lines = []\n        if retry is not None:\n            lines.append(\"core.upload:retry={}\".format(retry))\n        if retry_wait is not None:\n            lines.append(\"core.upload:retry_wait={}\".format(retry_wait))\n\n        client.save_home({\"global.conf\": \"\\n\".join(lines)})\n\n    def test_upload_error_with_config(self):\n        \"\"\"Cause an error in the transfer and see some message\"\"\"\n\n        # This will fail in the first put file, so, as we need to\n        # upload 3 files (conanmanifest, conanfile and tgz) will do it with 2 retries\n        client = self._get_client(BadConnectionUploader)\n        files = {\"conanfile.py\": GenConanfile(\"hello0\", \"1.2.1\").with_exports(\"*\")}\n        client.save(files)\n        client.run(\"export . --user=frodo --channel=stable\")\n        self._set_global_conf(client, retry_wait=0)\n\n        client.run(\"upload hello* --confirm -r default\")\n        assert \"Can't connect because of the evil mock\" in client.out\n        assert \"Waiting 0 seconds to retry...\" in client.out\n\n        # but not with 0\n        client = self._get_client(BadConnectionUploader)\n        files = {\"conanfile.py\": GenConanfile(\"hello0\", \"1.2.1\").with_exports(\"*\"),\n                 \"somefile.txt\": \"\"}\n        client.save(files)\n        client.run(\"export . --user=frodo --channel=stable\")\n\n        self._set_global_conf(client, retry=0, retry_wait=1)\n        client.run(\"upload hello* --confirm -r default\", assert_error=True)\n        assert \"Waiting 1 seconds to retry...\" not in client.out\n        assert (\"Execute upload again to retry upload the failed files: \"\n                \"conan_export.tgz. [Remote: default]\") in client.out\n\n        # Try with broken connection even with 10 retries\n        client = self._get_client(TerribleConnectionUploader)\n        files = {\"conanfile.py\": GenConanfile(\"hello0\", \"1.2.1\").with_exports(\"*\")}\n        client.save(files)\n        client.run(\"export . --user=frodo --channel=stable\")\n        self._set_global_conf(client, retry=10, retry_wait=0)\n        client.run(\"upload hello* --confirm -r default\", assert_error=True)\n        assert \"Waiting 0 seconds to retry...\" in client.out\n        assert \"Execute upload again to retry upload the failed files\" in client.out\n\n        # For each file will fail the first time and will success in the second one\n        client = self._get_client(FailPairFilesUploader)\n        files = {\"conanfile.py\": GenConanfile(\"hello0\", \"1.2.1\").with_exports(\"*\")}\n        client.save(files)\n        client.run(\"export . --user=frodo --channel=stable\")\n        client.run(\"install --requires=hello0/1.2.1@frodo/stable --build='*'\")\n        self._set_global_conf(client, retry=3, retry_wait=0)\n        client.run(\"upload hello* --confirm -r default\")\n        assert str(client.out).count(\"WARN: network: Pair file, error!\") == 5\n\n    def test_upload_same_package_dont_compress(self):\n        client = self._get_client()\n        client.save({\"conanfile.py\": GenConanfile().with_exports_sources(\"*\"), \"content.txt\": \"foo\"})\n        client.run(\"create . --name foo --version 1.0\")\n\n        client.run(\"upload foo/1.0 -r default\")\n        assert \"foo/1.0: Compressing conan_sources.tgz\" in client.out\n        assert (\"foo/1.0:da39a3ee5e6b4b0d3255bfef95601890afd80709: \"\n                \"Compressing conan_package.tgz\") in client.out\n\n        client.run(\"upload foo/1.0 -r default\")\n        assert \"Compressing\" not in client.out\n        assert \"already in server, skipping upload\" in client.out\n"
  },
  {
    "path": "test/integration/command/upload/upload_compression_test.py",
    "content": "import os\n\nfrom conan.api.model import RecipeReference\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.test_files import uncompress_packaged_files\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_reuse_uploaded_tgz():\n    client = TestClient(default_server_user=True)\n    # Download packages from a remote, then copy to another channel\n    # and reupload them. Because they have not changed, the tgz is not created again\n\n    # UPLOAD A PACKAGE\n    ref = RecipeReference.loads(\"hello0/0.1@user/stable\")\n    files = {\"conanfile.py\": GenConanfile(\"hello0\", \"0.1\").with_exports(\"*\"),\n             \"another_export_file.lib\": \"to compress\"}\n    client.save(files)\n    client.run(\"create . --user=user --channel=stable\")\n    client.run(\"upload %s -r default\" % str(ref))\n    assert \"Compressing conan_export.tgz\" in client.out\n    assert \"Compressing conan_package.tgz\" in client.out\n\n\ndef test_reuse_downloaded_tgz():\n    # Download packages from a remote, then copy to another channel\n    # and reupload them. It needs to compress it again, not tgz is kept\n    client = TestClient(default_server_user=True)\n    # UPLOAD A PACKAGE\n    files = {\"conanfile.py\": GenConanfile(\"hello0\", \"0.1\").with_exports(\"*\"),\n             \"another_export_file.lib\": \"to compress\"}\n    client.save(files)\n    client.run(\"create . --user=user --channel=stable\")\n    client.run(\"upload hello0/0.1@user/stable -r default\")\n    assert \"Compressing conan_export.tgz\" in client.out\n    assert \"Compressing conan_package.tgz\" in client.out\n\n    # Other user downloads the package\n    # THEN A NEW USER DOWNLOADS THE PACKAGES AND UPLOADS COMPRESSING AGAIN\n    # BECAUSE ONLY TGZ IS KEPT WHEN UPLOADING\n    other_client = TestClient(servers=client.servers, inputs=[\"admin\", \"password\"])\n    other_client.run(\"download hello0/0.1@user/stable -r default\")\n    other_client.run(\"upload hello0/0.1@user/stable -r default\")\n    assert \"Compressing conan_export.tgz\" in client.out\n    assert \"Compressing conan_package.tgz\" in client.out\n\n\ndef test_upload_only_tgz_if_needed():\n    client = TestClient(default_server_user=True)\n    ref = RecipeReference.loads(\"hello0/0.1@user/stable\")\n    conanfile = GenConanfile(\"hello0\", \"0.1\").with_exports(\"*\").with_package_file(\"lib/file.lib\",\n                                                                                  \"File\")\n    client.save({\"conanfile.py\": conanfile,\n                 \"file.txt\": \"contents\"})\n    client.run(\"create . --user=user --channel=stable\")\n\n    # Upload conans\n    client.run(\"upload %s -r default --only-recipe\" % str(ref))\n    assert \"Compressing conan_export.tgz\" in client.out\n\n    # Not needed to tgz again\n    client.run(\"upload %s -r default --only-recipe\" % str(ref))\n    assert \"Compressing\" not in client.out\n\n    # Check that conans exists on server\n    server_paths = client.servers[\"default\"].server_store\n    conan_path = server_paths.conan_revisions_root(ref)\n    assert os.path.exists(conan_path)\n\n    latest_rrev = client.cache.get_latest_recipe_revision(ref)\n    package_ids = client.cache.get_package_references(latest_rrev)\n    pref = package_ids[0]\n\n    # Upload package\n    client.run(\"upload %s#*:%s -r default -c\" % (str(ref), str(pref.package_id)))\n    assert \"Compressing conan_package.tgz\" in client.out\n\n    # Not needed to tgz again\n    client.run(\"upload %s#*:%s -r default -c\" % (str(ref), str(pref.package_id)))\n    assert \"Compressing\" not in client.out\n\n    # If we install the package again will be removed and re tgz\n    client.run(\"install --requires=%s --build missing\" % str(ref))\n    # Upload package\n    client.run(\"upload %s#*:%s -r default -c\" % (str(ref), str(pref.package_id)))\n    assert \"Compressing\" not in client.out\n\n    # Check library on server\n    folder = uncompress_packaged_files(server_paths, pref)\n    libraries = os.listdir(os.path.join(folder, \"lib\"))\n    assert len(libraries) == 1\n"
  },
  {
    "path": "test/integration/command/upload/upload_test.py",
    "content": "import json\nimport os\nimport platform\nimport stat\nimport textwrap\nfrom collections import OrderedDict\n\nimport pytest\nfrom unittest.mock import patch\nfrom requests import Response\n\nfrom conan.errors import ConanException\nfrom conan.api.model import PkgReference\nfrom conan.internal.api.uploader import gzopen_without_timestamps\nfrom conan.test.utils.tools import NO_SETTINGS_PACKAGE_ID, TestClient, TestServer, \\\n    GenConanfile, TestRequester, TestingResponse\nfrom conan.internal.util.files import is_dirty, save, set_dirty, sha1sum\n\nconanfile = \"\"\"from conan import ConanFile\nfrom conan.tools.files import copy\nclass MyPkg(ConanFile):\n    name = \"hello0\"\n    version = \"1.2.1\"\n    exports_sources = \"*\"\n\n    def package(self):\n        copy(self, \"*.cpp\", self.source_folder, self.package_folder)\n        copy(self, \"*.h\", self.source_folder, self.package_folder)\n\"\"\"\n\n\nclass TestUpload:\n\n    @pytest.mark.artifactory_ready\n    def test_upload_dirty(self):\n        client = TestClient(default_server_user=True, light=True)\n        client.save({\"conanfile.py\": GenConanfile(\"hello\", \"0.1\")})\n        client.run(\"create .\")\n\n        pkg_folder = client.created_layout().package()\n        set_dirty(pkg_folder)\n\n        client.run(\"upload * -r=default -c\", assert_error=True)\n        assert \"ERROR: Package hello/0.1:da39a3ee5e6b4b0d3255bfef95601890afd80709 i\" \\\n               \"s corrupted, aborting upload.\" in client.out\n        assert \"Remove it with 'conan remove hello/0.1:da39a3ee5e6b4b0d3255bfef95601890afd80709\" \\\n               in client.out\n\n        # Test that removeing the binary allows moving forward\n        client.run(\"remove hello/0.1:da39a3ee5e6b4b0d3255bfef95601890afd80709 -c\")\n        client.run(\"upload * -r=default --confirm\")\n\n    @pytest.mark.artifactory_ready\n    def test_upload_force(self):\n        client = TestClient(default_server_user=True, light=True)\n        conanfile_ = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import copy\n            class MyPkg(ConanFile):\n                name = \"hello\"\n                version = \"0.1\"\n                def package(self):\n                    copy(self, \"myfile.sh\", src=self.source_folder, dst=self.package_folder)\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile_,\n                    \"myfile.sh\": \"foo\"})\n\n        client.run(\"export-pkg .\")\n        client.run(\"upload * --confirm -r default\")\n        assert \"Uploading package 'hello\" in client.out\n        client.run(\"upload * --confirm -r default\")\n        assert \"Uploading package\" not in client.out\n\n        if platform.system() == \"Linux\":\n            package_file_path = os.path.join(client.current_folder, \"myfile.sh\")\n            os.system('chmod +x \"{}\"'.format(package_file_path))\n            assert os.stat(package_file_path).st_mode & stat.S_IXUSR\n            client.run(\"export-pkg .\")\n\n            client.run(\"upload * --confirm -r default\")\n            # Doesn't change revision, doesn't reupload\n            assert \"conan_package.tgz\" not in client.out\n            assert \"skipping upload\" in client.out\n            assert \"Compressing package...\" not in client.out\n\n        # with --force it really re-uploads it\n        client.run(\"upload * --confirm --force -r default\")\n        assert \"Uploading recipe 'hello\" in client.out\n        assert \"Uploading package 'hello\" in client.out\n\n        if platform.system() == \"Linux\":\n            client.run(\"remove '*' -c\")\n            client.run(\"install --requires=hello/0.1 --deployer=full_deploy\")\n            package_file_path = os.path.join(client.current_folder, \"full_deploy\", \"host\", \"hello\",\n                                             \"0.1\", \"myfile.sh\")\n            # Owner with execute permissions\n            assert os.stat(package_file_path).st_mode & stat.S_IXUSR\n\n    @pytest.mark.artifactory_ready\n    def test_pattern_upload(self):\n        client = TestClient(default_server_user=True, light=True)\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --user=user --channel=testing\")\n        client.run(\"upload hello0/*@user/testing --confirm -r default\")\n        assert \"Uploading recipe 'hello0/1.2.1@\" in client.out\n        assert \"Uploading package 'hello0/1.2.1@\" in client.out\n\n    def test_pattern_upload_no_recipes(self):\n        client = TestClient(default_server_user=True, light=True)\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"upload bogus/*@dummy/testing --confirm -r default\", assert_error=True)\n        assert \"No recipes found matching pattern 'bogus/*@dummy/testing'\" in client.out\n\n    def test_broken_sources_tgz(self):\n        # https://github.com/conan-io/conan/issues/2854\n        client = TestClient(default_server_user=True, light=True)\n        client.save({\"conanfile.py\": conanfile,\n                     \"source.h\": \"my source\"})\n        client.run(\"create . --user=user --channel=testing\")\n        layout = client.exported_layout()\n\n        def gzopen_patched(name, mode=\"r\", fileobj=None, **kwargs):  # noqa\n            raise ConanException(\"Error gzopen %s\" % name)\n        with patch('conan.internal.api.uploader.gzopen_without_timestamps', new=gzopen_patched):\n            client.run(\"upload * --confirm -r default --only-recipe\",\n                       assert_error=True)\n            assert \"Error gzopen conan_sources.tgz\" in client.out\n\n            export_download_folder = layout.download_export()\n\n            tgz = os.path.join(export_download_folder, \"conan_sources.tgz\")\n            assert os.path.exists(tgz)\n            assert is_dirty(tgz)\n\n        client.run(\"upload * --confirm -r default --only-recipe\")\n        assert \"Removing conan_sources.tgz, marked as dirty\" in client.out\n        assert os.path.exists(tgz)\n        assert not is_dirty(tgz)\n\n    def test_broken_package_tgz(self):\n        # https://github.com/conan-io/conan/issues/2854\n        client = TestClient(default_server_user=True, light=True)\n        client.save({\"conanfile.py\": conanfile,\n                     \"source.h\": \"my source\"})\n        client.run(\"create . --user=user --channel=testing\")\n        pref = client.created_layout().reference\n\n        def gzopen_patched(name, fileobj, compresslevel=None):  # noqa\n            if name == \"conan_package.tgz\":\n                raise ConanException(\"Error gzopen %s\" % name)\n            return gzopen_without_timestamps(name, fileobj)\n        with patch('conan.internal.api.uploader.gzopen_without_timestamps', new=gzopen_patched):\n            client.run(\"upload * --confirm -r default\", assert_error=True)\n            assert \"Error gzopen conan_package.tgz\" in client.out\n\n            download_folder = client.get_latest_pkg_layout(pref).download_package()\n            tgz = os.path.join(download_folder, \"conan_package.tgz\")\n            assert os.path.exists(tgz)\n            assert is_dirty(tgz)\n\n        client.run(\"upload * --confirm -r default\")\n        assert \"WARN: Removing conan_package.tgz, marked as dirty\" in client.out\n        assert os.path.exists(tgz)\n        assert not is_dirty(tgz)\n\n    def test_corrupt_upload(self):\n        c = TestClient(default_server_user=True, light=True)\n\n        c.save({\"conanfile.py\": conanfile,\n                \"include/hello.h\": \"\"})\n        c.run(\"create . --user=frodo --channel=stable\")\n        package_folder = c.created_layout().package()\n        save(os.path.join(package_folder, \"added.txt\"), \"\")\n        os.remove(os.path.join(package_folder, \"include/hello.h\"))\n        c.run(\"upload hello0/1.2.1@frodo/stable --check -r default\", assert_error=True)\n        assert (\"hello0/1.2.1@frodo/stable#3afd661184b94bdac7fb2057e7bd9baa\"\n                \":da39a3ee5e6b4b0d3255bfef95601890afd80709\"\n                \"#e70e86439dec07a0d5d3414648b0b16c: ERROR\") in c.out\n        assert \"include/hello.h (manifest: d41d8cd98f00b204e9800998ecf8427e, file: None)\" in c.out\n        assert \"added.txt (manifest: None, file: d41d8cd98f00b204e9800998ecf8427e)\" in c.out\n        assert \"ERROR: There are corrupted artifacts, check the error logs\" in c.out\n\n    @pytest.mark.artifactory_ready\n    def test_upload_modified_recipe(self):\n        client = TestClient(default_server_user=True, light=True)\n\n        client.save({\"conanfile.py\": conanfile,\n                     \"hello.cpp\": \"int i=0\"})\n        client.run(\"export . --user=frodo --channel=stable\")\n        rrev = client.exported_recipe_revision()\n        client.run(\"upload hello0/1.2.1@frodo/stable -r default\")\n        assert \"Uploading recipe 'hello0/1.2.1@frodo/stable#\" in client.out\n\n        client2 = TestClient(servers=client.servers, inputs=[\"admin\", \"password\"])\n        client2.save({\"conanfile.py\": conanfile + \"\\r\\n#end\",\n                      \"hello.cpp\": \"int i=1\"})\n        client2.run(\"export . --user=frodo --channel=stable\")\n        layout = client2.exported_layout()\n        manifest, _ = layout.recipe_manifests()\n        manifest.time += 10\n        manifest.save(layout.export())\n        client2.run(\"upload hello0/1.2.1@frodo/stable -r default\")\n        assert \"Uploading recipe 'hello0/1.2.1@frodo/stable#\" in client2.out\n\n        # first client tries to upload again\n        # The client tries to upload exactly the same revision already uploaded, so no changes\n        client.run(\"upload hello0/1.2.1@frodo/stable -r default\")\n        assert f\"'hello0/1.2.1@frodo/stable#{rrev}' already in server, skipping upload\" in client.out\n\n    @pytest.mark.artifactory_ready\n    def test_upload_unmodified_recipe(self):\n        client = TestClient(default_server_user=True, light=True)\n        files = {\"conanfile.py\": GenConanfile(\"hello0\", \"1.2.1\")}\n        client.save(files)\n        client.run(\"export . --user=frodo --channel=stable\")\n        rrev = client.exported_recipe_revision()\n        client.run(\"upload hello0/1.2.1@frodo/stable -r default\")\n        assert \"Uploading recipe 'hello0/1.2.1@frodo/stable#\" in client.out\n\n        client2 = TestClient(servers=client.servers, inputs=[\"admin\", \"password\"])\n        client2.save(files)\n        client2.run(\"export . --user=frodo --channel=stable\")\n        layout = client2.exported_layout()\n        manifest, _ = layout.recipe_manifests()\n        manifest.time += 10\n        manifest.save(layout.export())\n        client2.run(\"upload hello0/1.2.1@frodo/stable -r default\")\n        assert (f\"Recipe 'hello0/1.2.1@frodo/stable#761f54e34d59deb172d6078add7050a7' already \"\n                f\"in server, skipping upload\") in client2.out\n\n        # first client tries to upload again\n        client.run(\"upload hello0/1.2.1@frodo/stable -r default\")\n        assert (f\"Recipe 'hello0/1.2.1@frodo/stable#{rrev}' \"\n                f\"already in server, skipping upload\") in client.out\n\n    @pytest.mark.artifactory_ready\n    def test_upload_unmodified_package(self):\n        client = TestClient(default_server_user=True, light=True)\n\n        client.save({\"conanfile.py\": conanfile,\n                     \"hello.cpp\": \"\"})\n        client.run(\"create . --user=frodo --channel=stable\")\n        prev1 = client.created_layout().reference\n        client.run(\"upload hello0/1.2.1@frodo/stable -r default\")\n\n        client2 = TestClient(servers=client.servers, inputs=[\"admin\", \"password\"])\n        client2.save({\"conanfile.py\": conanfile,\n                      \"hello.cpp\": \"\"})\n        client2.run(\"create . --user=frodo --channel=stable\")\n        prev2 = client2.created_layout().reference\n        client2.run(\"upload hello0/1.2.1@frodo/stable -r default\")\n        assert f\"'{repr(prev2.ref)}' already in server, skipping upload\" in client2.out\n        assert \"Uploaded conan recipe 'hello0/1.2.1@frodo/stable' to 'default'\" not in client2.out\n        assert f\"'{prev2.repr_notime()}' already in server, skipping upload\" in client2.out\n\n        # first client tries to upload again\n        client.run(\"upload hello0/1.2.1@frodo/stable -r default\")\n        assert f\"'{repr(prev1.ref)}' already in server, skipping upload\" in client.out\n        assert \"Uploaded conan recipe 'hello0/1.2.1@frodo/stable' to 'default'\" not in client.out\n        assert f\"'{prev1.repr_notime()}' already in server, skipping upload\" in client2.out\n\n    def test_upload_no_overwrite_all(self):\n        conanfile_new = GenConanfile(\"hello\", \"1.0\").\\\n            with_import(\"from conan.tools.files import copy\").\\\n            with_exports_sources([\"*\"]).\\\n            with_package('copy(self, \"*\", self.source_folder, self.package_folder)')\n\n        client = TestClient(default_server_user=True, light=True)\n        client.save({\"conanfile.py\": conanfile_new,\n                     \"hello.h\": \"\"})\n        client.run(\"create . --user=frodo --channel=stable\")\n        prev1 = client.created_layout().reference\n        # First time upload\n        client.run(\"upload hello/1.0@frodo/stable -r default\")\n        assert \"Forbidden overwrite\" not in client.out\n        assert \"Uploading recipe 'hello/1.0@frodo/stable\" in client.out\n\n        # CASE: Upload again\n        client.run(\"upload hello/1.0@frodo/stable -r default\")\n        assert f\"'{repr(prev1.ref)}' already in server, skipping upload\" in client.out\n        assert f\"'{prev1.repr_notime()}' already in server, skipping upload\" in client.out\n\n    def test_skip_upload(self):\n        \"\"\" Check that the option --skip does not upload anything\n        \"\"\"\n        client = TestClient(default_server_user=True, light=True)\n        client.save({\"conanfile.py\": GenConanfile(\"hello0\", \"1.2.1\").with_exports(\"*\"),\n                     \"file.txt\": \"\"})\n        client.run(\"create .\")\n\n        client.run(\"upload * --dry-run -r default -c\")\n        assert \"Compressing\" in client.out\n        client.run(\"search * -r default\")\n        # after dry run nothing should be on the server\n        assert \"hello\" not in client.out\n\n        # now upload, the stuff should NOT be recompressed\n        client.run(\"upload * -c -r default\")\n        # check if compressed files are re-used\n        assert \"Compressing\" not in client.out\n        # now it should be on the server\n        client.run(\"search * -r default\")\n        assert \"hello0/1.2.1\" in client.out\n\n    def test_upload_without_sources(self):\n        client = TestClient(default_server_user=True, light=True)\n        client.save({\"conanfile.py\": GenConanfile()})\n        client.run(\"create . --name=pkg --version=0.1 --user=user --channel=testing\")\n        client.run(\"upload * --confirm -r default\")\n        client2 = TestClient(servers=client.servers, inputs=[\"admin\", \"password\",\n                                                             \"lasote\", \"mypass\"])\n\n        client2.run(\"install --requires=pkg/0.1@user/testing\")\n        client2.run(\"remote remove default\")\n        server2 = TestServer([(\"*/*@*/*\", \"*\")], [(\"*/*@*/*\", \"*\")],\n                             users={\"lasote\": \"mypass\"})\n        client2.servers = {\"server2\": server2}\n        client2.update_servers()\n        client2.run(\"upload * --confirm -r=server2\")\n\n        assert \"Uploading recipe 'pkg\" in client.out\n        assert \"Uploading package 'pkg\" in client.out\n\n    def test_upload_login_prompt_disabled_no_user(self):\n        \"\"\" Without user info, uploads should fail when login prompt has been disabled.\n        \"\"\"\n        files = {\"conanfile.py\": GenConanfile(\"hello0\", \"1.2.1\")}\n        client = TestClient(default_server_user=True, light=True)\n        client.save(files)\n        conan_conf = \"core:non_interactive=True\"\n        client.save_home({\"global.conf\": conan_conf})\n\n        client.run(\"create . --user=user --channel=testing\")\n        client.run(\"remote logout '*'\")\n        client.run(\"upload hello0/1.2.1@user/testing -r default\", assert_error=True)\n\n        assert \"Conan interactive mode disabled\" in client.out\n        assert \"-> conanmanifest.txt\" not in client.out\n        assert \"-> conanfile.py\" not in client.out\n        assert \"-> conan_export.tgz\" not in client.out\n\n    def test_upload_login_prompt_disabled_user_not_authenticated(self):\n        # When a user is not authenticated, uploads should fail when login prompt has been disabled.\n        files = {\"conanfile.py\": GenConanfile(\"hello0\", \"1.2.1\")}\n        client = TestClient(default_server_user=True, light=True)\n        client.save(files)\n        conan_conf = \"core:non_interactive=True\"\n        client.save_home({\"global.conf\": conan_conf})\n        client.run(\"create . --user=user --channel=testing\")\n        client.run(\"remote logout '*'\")\n        client.run(\"remote set-user default lasote\")\n        client.run(\"upload hello0/1.2.1@user/testing -r default\", assert_error=True)\n        assert \"Conan interactive mode disabled\" in client.out\n        assert \"-> conanmanifest.txt\" not in client.out\n        assert \"-> conanfile.py\" not in client.out\n        assert \"-> conan_export.tgz\" not in client.out\n        assert \"Please enter a password for\" not in client.out\n\n    def test_upload_login_prompt_disabled_user_authenticated(self):\n        #  When user is authenticated, uploads should work even when login prompt has been disabled.\n        client = TestClient(default_server_user=True, light=True)\n        client.save({\"conanfile.py\": GenConanfile(\"hello0\", \"1.2.1\")})\n        conan_conf = \"core:non_interactive=True\"\n        client.save_home({\"global.conf\": conan_conf})\n        client.run(\"create . --user=user --channel=testing\")\n        client.run(\"remote logout '*'\")\n        client.run(\"remote login default admin -p password\")\n        client.run(\"upload hello0/1.2.1@user/testing -r default\")\n\n        assert \"Uploading recipe 'hello0/1.2.1@\" in client.out\n        assert \"Uploading package 'hello0/1.2.1@\" in client.out\n\n    def test_upload_key_error(self):\n        files = {\"conanfile.py\": GenConanfile(\"hello0\", \"1.2.1\")}\n        server1 = TestServer([(\"*/*@*/*\", \"*\")], [(\"*/*@*/*\", \"*\")], users={\"lasote\": \"mypass\"})\n        server2 = TestServer([(\"*/*@*/*\", \"*\")], [(\"*/*@*/*\", \"*\")], users={\"lasote\": \"mypass\"})\n        servers = OrderedDict()\n        servers[\"server1\"] = server1\n        servers[\"server2\"] = server2\n        client = TestClient(servers=servers)\n        client.save(files)\n        client.run(\"create . --user=user --channel=testing\")\n        client.run(\"remote login server1 lasote -p mypass\")\n        client.run(\"remote login server2 lasote -p mypass\")\n        client.run(\"upload hello0/1.2.1@user/testing -r server1\")\n        client.run(\"remove * --confirm\")\n        client.run(\"install --requires=hello0/1.2.1@user/testing -r server1\")\n        client.run(\"remote remove server1\")\n        client.run(\"upload hello0/1.2.1@user/testing -r server2\")\n        assert \"ERROR: 'server1'\" not in client.out\n\n    def test_upload_without_user_channel(self):\n        server = TestServer(users={\"user\": \"password\"}, write_permissions=[(\"*/*@*/*\", \"*\")])\n        servers = {\"default\": server}\n        client = TestClient(servers=servers, inputs=[\"user\", \"password\"])\n\n        client.save({\"conanfile.py\": GenConanfile()})\n\n        client.run('create . --name=lib --version=1.0')\n        assert \"lib/1.0: Package '{}' created\".format(NO_SETTINGS_PACKAGE_ID) in client.out\n        client.run('upload lib/1.0 -c -r default')\n        assert \"Uploading recipe 'lib/1.0\" in client.out\n\n        # Verify that in the remote it is stored as \"_\"\n        pref = PkgReference.loads(\"lib/1.0@#0:{}#0\".format(NO_SETTINGS_PACKAGE_ID))\n        path = server.server_store.export(pref.ref)\n        assert \"/lib/1.0/_/_/0/export\" in path.replace(\"\\\\\", \"/\")\n\n        path = server.server_store.package(pref)\n        assert \"/lib/1.0/_/_/0/package\" in path.replace(\"\\\\\", \"/\")\n\n        # Should be possible with explicit package\n        client.run(f'upload lib/1.0#*:{NO_SETTINGS_PACKAGE_ID} -c -r default --force')\n        assert \"Uploading artifacts\" in client.out\n\n    def test_upload_without_cleaned_user(self):\n        \"\"\" When a user is not authenticated, uploads failed first time\n        https://github.com/conan-io/conan/issues/5878\n        \"\"\"\n\n        class EmptyCapabilitiesResponse(object):\n            def __init__(self):\n                self.ok = False\n                self.headers = {\"X-Conan-Server-Capabilities\": \"\",\n                                \"Content-Type\": \"application/json\"}\n                self.status_code = 401\n                self.content = b''\n\n        class ServerCapabilitiesRequester(TestRequester):\n            def __init__(self, *args, **kwargs):\n                self._first_ping = True\n                super(ServerCapabilitiesRequester, self).__init__(*args, **kwargs)\n\n            def get(self, url, **kwargs):\n                app, url = self._prepare_call(url, kwargs)\n                assert app\n                assert (\"/v1/\" in url and url.endswith(\"ping\")) or \"/v2\" in url\n                if url.endswith(\"ping\") and self._first_ping:\n                    self._first_ping = False\n                    return EmptyCapabilitiesResponse()\n                else:\n                    response = app.get(url, **kwargs)\n                    return TestingResponse(response)\n\n        server = TestServer(users={\"user\": \"password\"}, write_permissions=[(\"*/*@*/*\", \"*\")])\n        servers = {\"default\": server}\n        client = TestClient(requester_class=ServerCapabilitiesRequester, servers=servers,\n                            inputs=[\"user\", \"password\"])\n        files = {\"conanfile.py\": GenConanfile(\"hello0\", \"1.2.1\")}\n        client.save(files)\n        client.run(\"create . --user=user --channel=testing\")\n        client.run(\"remote logout '*'\")\n        client.run(\"upload hello0/1.2.1@user/testing -r default\")\n        assert \"Uploading recipe 'hello0/1.2.1@user/testing\" in client.out\n\n    def test_server_returns_200_ok(self):\n        # https://github.com/conan-io/conan/issues/16104\n        # If server returns 200 ok, without headers, it raises an error\n        class MyHttpRequester(TestRequester):\n            def get(self, _, **kwargs):\n                resp = Response()\n                resp.status_code = 200\n                return resp\n\n        client = TestClient(requester_class=MyHttpRequester, servers={\"default\": TestServer()})\n        client.save({\"conanfile.py\": GenConanfile(\"hello0\", \"1.2.1\")})\n        client.run(\"create . \")\n        client.run(\"upload * -c -r default\", assert_error=True)\n        assert \"doesn't seem like a valid Conan remote\" in client.out\n\n\ndef test_upload_only_without_user_channel():\n    \"\"\"\n    check that we can upload only the packages without user and channel\n    https://github.com/conan-io/conan/issues/10579\n    \"\"\"\n    c = TestClient(default_server_user=True, light=True)\n\n    c.save({\"conanfile.py\": GenConanfile(\"lib\", \"1.0\")})\n    c.run('create .')\n    c.run(\"create . --user=user --channel=channel\")\n    c.run(\"list *\")\n    assert \"lib/1.0@user/channel\" in c.out\n\n    c.run('upload */*@ -c -r=default')\n    assert \"Uploading recipe 'lib/1.0\" in c.out  # FAILS!\n    assert \"lib/1.0@user/channel\" not in c.out\n    c.run(\"search * -r=default\")\n    assert \"lib/1.0\" in c.out\n    assert \"lib/1.0@user/channel\" not in c.out\n\n    c.run('upload */*@user/channel -c -r=default')\n    assert \"Uploading recipe 'lib/1.0@user/channel\" in c.out\n    c.run(\"search * -r=default\")\n    assert \"lib/1.0@user/channel\" in c.out\n    assert \"lib/1.0\" in c.out\n\n\ndef test_upload_with_python_requires():\n    # https://github.com/conan-io/conan/issues/14503\n    c = TestClient(default_server_user=True, light=True)\n    c.save({\"tool/conanfile.py\": GenConanfile(\"tool\", \"0.1\"),\n            \"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\").with_python_requires(\"tool/[>=0.1]\")})\n    c.run(\"create tool\")\n    c.run(\"create dep\")\n    c.run(\"upload tool* -c -r=default\")\n    c.run(\"remove tool* -c\")\n    c.run(\"upload dep* -c -r=default\")\n    # This used to fail, but adding the enabled remotes to python_requires resolution, it works\n    assert \"tool/0.1: Downloaded recipe\" in c.out\n\n\ndef test_upload_list_only_recipe():\n    c = TestClient(default_server_user=True, light=True)\n    c.save({\"conanfile.py\": GenConanfile(\"liba\", \"0.1\")})\n    c.run(\"create .\")\n    c.run(\"install --requires=liba/0.1 --format=json\", redirect_stdout=\"graph.json\")\n    c.run(\"list --graph=graph.json --format=json\", redirect_stdout=\"installed.json\")\n    c.run(\"upload --list=installed.json --only-recipe -r=default -c\")\n    assert \"conan_package.tgz\" not in c.out\n\n\n@pytest.mark.parametrize(\"dry_run\", [True, False])\ndef test_upload_json_output(dry_run):\n    c = TestClient(default_server_user=True, light=True)\n    c.save({\"conanfile.py\": GenConanfile(\"liba\", \"0.1\").with_settings(\"os\")\n                                                       .with_shared_option(False)})\n    c.run(\"create . -s os=Linux\")\n    dry_run_arg = \"--dry-run\" if dry_run else \"\"\n    c.run(f\"upload * -r=default {dry_run_arg} -c --format=json\")\n    list_pkgs = json.loads(c.stdout)\n    revs = list_pkgs[\"default\"][\"liba/0.1\"][\"revisions\"][\"a565bd5defd3a99e157698fcc6e23b25\"]\n    pkg = revs[\"packages\"][\"9e0f8140f0fe6b967392f8d5da9881e232e05ff8\"]\n    prev = pkg[\"revisions\"][\"f50f552c6e04b1f241e5f7864bc3957f\"]\n    assert pkg[\"info\"] == {\"settings\": {\"os\": \"Linux\"}, \"options\": {\"shared\": \"False\"}}\n    base_url = \"v2/conans/liba/0.1/_/_/revisions/a565bd5defd3a99e157698fcc6e23b25\"\n    assert revs[\"upload-urls\"] == {\n        \"conanfile.py\": {\n            \"url\": f\"{c.servers['default']}/{base_url}/files/conanfile.py\",\n            \"checksum\": sha1sum(revs[\"files\"][\"conanfile.py\"])\n        },\n        \"conanmanifest.txt\": {\n            \"url\": f\"{c.servers['default']}/{base_url}/files/conanmanifest.txt\",\n            \"checksum\": sha1sum(revs[\"files\"][\"conanmanifest.txt\"])\n        }\n    }\n    pkg_url = \"9e0f8140f0fe6b967392f8d5da9881e232e05ff8/revisions/f50f552c6e04b1f241e5f7864bc3957f\"\n    assert prev[\"upload-urls\"] == {\n        \"conan_package.tgz\": {\n            \"url\": f\"{c.servers['default']}/{base_url}/packages/{pkg_url}/files/conan_package.tgz\",\n            \"checksum\": sha1sum(prev[\"files\"][\"conan_package.tgz\"])\n        },\n        \"conaninfo.txt\": {\n            \"url\": f\"{c.servers['default']}/{base_url}/packages/{pkg_url}/files/conaninfo.txt\",\n            \"checksum\": sha1sum(prev[\"files\"][\"conaninfo.txt\"])\n        },\n        \"conanmanifest.txt\": {\n            \"url\": f\"{c.servers['default']}/{base_url}/packages/{pkg_url}/files/conanmanifest.txt\",\n            \"checksum\": sha1sum(prev[\"files\"][\"conanmanifest.txt\"])\n        }\n    }\n\n    if dry_run:\n        # check we don't have anything about the upload-urls in the text formatter\n        c.run(\"upload * -r=default -c --dry-run\")\n        assert \"upload-urls\" not in c.out\n        assert \"url:\" not in c.out\n        assert \"checksum:\" not in c.out\n"
  },
  {
    "path": "test/integration/conan_api/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/conan_api/exit_with_code_test.py",
    "content": "import textwrap\n\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_exit_with_code():\n    base = textwrap.dedent(\"\"\"\n        import sys\n        from conan import ConanFile\n\n        class HelloConan(ConanFile):\n            name = \"hello0\"\n            version = \"0.1\"\n\n            def build(self):\n                sys.exit(34)\n        \"\"\")\n\n    client = TestClient(light=True)\n    client.save({\"conanfile.py\": base})\n    client.run(\"install .\")\n    error_code = client.run(\"build .\", assert_error=True)\n    assert error_code == 34\n    assert \"Exiting with code: 34\" in client.out\n"
  },
  {
    "path": "test/integration/conan_api/list_test.py",
    "content": "from conan.api.conan_api import ConanAPI\nfrom conan.test.utils.env import environment_update\nfrom conan.api.model import PkgReference\nfrom conan.api.model import RecipeReference\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_get_recipe_revisions():\n    \"\"\"\n    Test the \"api.list.recipe_revisions\"\n    \"\"\"\n    client = TestClient(default_server_user=True)\n    for rev in range(1, 4):\n        client.save({\"conanfile.py\": GenConanfile(\"foo\", \"1.0\").with_build_msg(f\"{rev}\")})\n        client.run(\"create .\")\n    client.run(\"upload * -r=default -c\")\n\n    api = ConanAPI(client.cache_folder)\n    # Check the revisions locally\n    ref = RecipeReference.loads(\"foo/1.0\")\n    sot = api.list.recipe_revisions(ref)\n    sot = [r.repr_notime() for r in sot]\n    assert [\"foo/1.0#6707ddcdb444fd46f92d449d11700c5a\",\n            \"foo/1.0#913d984a1b9b8a2821d8c4d4e9cf8d57\",\n            \"foo/1.0#b87cdb893042ec4b371bc6aa82a0108f\"] == sot\n\n\ndef test_get_package_revisions():\n    \"\"\"\n    Test the \"api.list.package_revisions\"\n    \"\"\"\n    client = TestClient(default_server_user=True)\n    client.save({\"conanfile.py\": GenConanfile(\"foo\", \"1.0\").with_package_file(\"f.txt\",\n                                                                              env_var=\"MYVAR\")})\n    for rev in range(3):\n        with environment_update({\"MYVAR\": f\"{rev}\"}):\n            client.run(\"create . \")\n    client.run(\"upload * -r=default -c\")\n\n    api = ConanAPI(client.cache_folder)\n    # Check the revisions locally\n    pref = PkgReference.loads(\"foo/1.0#77ead28a5fd4216349b5b2181f4d32d4:\"\n                              \"da39a3ee5e6b4b0d3255bfef95601890afd80709\")\n    sot = api.list.package_revisions(pref)\n    sot = [r.repr_notime() for r in sot]\n    assert ['foo/1.0#77ead28a5fd4216349b5b2181f4d32d4:'\n            'da39a3ee5e6b4b0d3255bfef95601890afd80709#8b34fcf0543672de78ce1fe4f7fb3daa',\n            'foo/1.0#77ead28a5fd4216349b5b2181f4d32d4:'\n            'da39a3ee5e6b4b0d3255bfef95601890afd80709#5bb077c148d587da50ce9c3212370b5d',\n            'foo/1.0#77ead28a5fd4216349b5b2181f4d32d4:'\n            'da39a3ee5e6b4b0d3255bfef95601890afd80709#370f42f40d3f353a83a0f529ba2be1ce'] == sot\n\n\ndef test_search_recipes_no_user_channel_only():\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"create . --name foo --version 1.0 --user user --channel channel\")\n    client.run(\"create . --name foo --version 1.0\")\n    client.run(\"list foo/1.0@\")\n    assert \"foo/1.0@user/channel\" not in client.out\n    assert \"foo/1.0\" in client.out\n"
  },
  {
    "path": "test/integration/conan_api/test_cli.py",
    "content": "import os\n\nimport pytest\n\nfrom conan.api.conan_api import ConanAPI\nfrom conan.cli.cli import Cli, main\nfrom conan.test.utils.env import environment_update\nfrom conan.test.utils.mocks import RedirectedTestOutput\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import redirect_output\n\n\ndef test_cli():\n    \"\"\" make sure the CLi can be reused\n    https://github.com/conan-io/conan/issues/14044\n    \"\"\"\n    folder = temp_folder()\n    api = ConanAPI(cache_folder=folder)\n    cli = Cli(api)\n    cli2 = Cli(api)\n\n    stdout = RedirectedTestOutput()\n    stderr = RedirectedTestOutput()\n    with redirect_output(stderr, stdout):\n        cli.run([\"list\", \"*\"])\n        cli.run([\"list\", \"*\"])\n        cli2.run([\"list\", \"*\"])\n        cli.run([\"list\", \"*\"])\n\n    stdout = RedirectedTestOutput()\n    stderr = RedirectedTestOutput()\n    with redirect_output(stderr, stdout):\n        cli.run()\n    # Running without args shows help, but doesn't error\n    assert \"Consumer commands\" in stdout.getvalue()\n\n\ndef test_basic_api():\n    api = ConanAPI(cache_folder=temp_folder())\n    result = api.remotes.list()\n    assert result[0].name == \"conancenter\"\n\n\ndef test_api_command():\n    # The ``CommandAPI`` requires a bit more of setup\n    api = ConanAPI(cache_folder=temp_folder())\n    cli = Cli(api)\n    cli.add_commands()\n    result = api.command.run([\"remote\", \"list\"])\n    assert result[0].name == \"conancenter\"\n\n\ndef test_main():\n    cache_folder = os.path.join(temp_folder(), \"custom\")\n    with environment_update({\"CONAN_HOME\": cache_folder}):\n        with pytest.raises(SystemExit) as e:\n            main([\"list\", \"*\"])\n        assert e.type == SystemExit\n        assert e.value.code == 0  # success\n"
  },
  {
    "path": "test/integration/conan_api/test_local_api.py",
    "content": "import os\n\nfrom conan.api.conan_api import ConanAPI\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.api.model import RecipeReference\nfrom conan.internal.util.files import save\n\n\ndef test_local_api():\n    # https://github.com/conan-io/conan/issues/17484\n    current_folder = temp_folder()\n    cache_folder = temp_folder()\n    save(os.path.join(current_folder, \"conanfile.py\"), str(GenConanfile(\"foo\", \"1.0\")))\n    api = ConanAPI(cache_folder)\n    assert api.local.editable_packages.edited_refs == {}\n    api.local.editable_add(\".\", cwd=current_folder)\n    assert list(api.local.editable_packages.edited_refs) == [RecipeReference.loads(\"foo/1.0\")]\n"
  },
  {
    "path": "test/integration/conan_api/test_profile_api.py",
    "content": "import pytest\n\nfrom conan.api.conan_api import ConanAPI\nfrom conan.errors import ConanException\n\n\ndef test_profile_api():\n    # It must be an absolute path\n    with pytest.raises(ConanException) as e:\n        ConanAPI(cache_folder=\"test\")\n    assert \"cache_folder has to be an absolute path\" in str(e.value)\n"
  },
  {
    "path": "test/integration/conan_v2/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/conan_v2/test_legacy_cpp_info.py",
    "content": "import textwrap\n\nfrom conan.api.model import RecipeReference\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import load, save\n\n\ndef test_legacy_names_filenames():\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"1.0\"\n            def package_info(self):\n                self.cpp_info.components[\"comp\"].names[\"cmake_find_package\"] = \"hello\"\n                self.cpp_info.components[\"comp\"].names[\"cmake_find_package_multi\"] = \"hello\"\n                self.cpp_info.components[\"comp\"].build_modules[\"cmake_find_package\"] = [\"nice_rel_path\"]\n                self.cpp_info.components[\"comp\"].build_modules[\"cmake_find_package\"].append(\"some_file_name\")\n                self.cpp_info.components[\"comp\"].build_modules[\"cmake_find_package_multi\"] = [\"nice_rel_path\"]\n\n                self.cpp_info.names[\"cmake_find_package\"] = \"absl\"\n                self.cpp_info.names[\"cmake_find_package_multi\"] = \"absl\"\n                self.cpp_info.filenames[\"cmake_find_package\"] = \"tensorflowlite\"\n                self.cpp_info.filenames[\"cmake_find_package_multi\"] = \"tensorflowlite\"\n                self.cpp_info.build_modules[\"cmake_find_package\"] = [\"nice_rel_path\"]\n                self.cpp_info.build_modules[\"cmake_find_package_multi\"] = [\"nice_rel_path\"]\n\n                self.env_info.whatever = \"whatever-env_info\"\n                self.env_info.PATH.append(\"/path/to/folder\")\n                self.user_info.whatever = \"whatever-user_info\"\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"create .\")\n    for name in [\"cpp_info.names\", \"cpp_info.filenames\", \"env_info\", \"user_info\", \"cpp_info.build_modules\"]:\n        assert f\"WARN: deprecated:     '{name}' used in: pkg/1.0\" in c.out\n\n    c.save_home({\"global.conf\": 'core:skip_warnings=[\"deprecated\"]'})\n    c.run(\"create .\")\n    for name in [\"cpp_info.names\", \"cpp_info.filenames\", \"env_info\", \"user_info\",\n                 \"cpp_info.build_modules\"]:\n        assert f\"'{name}' used in: pkg/1.0\" not in c.out\n\n\nclass TestLegacy1XRecipes:\n    def test_legacy_imports(self):\n        c = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"1.0\"\n            \"\"\")\n        c.save({\"pkg/conanfile.py\": conanfile,\n                \"app/conanfile.py\": GenConanfile(\"app\", \"1.0\").with_requires(\"pkg/1.0\")})\n        # With EDITABLE, we can emulate errors without exporting\n        c.run(\"export pkg\")\n        layout = c.get_latest_ref_layout(RecipeReference.loads(\"pkg/1.0\"))\n        conanfile = layout.conanfile()\n        content = load(conanfile)\n        content = content.replace(\"from conan\", \"from conans\")\n        save(conanfile, content)\n        c.run(\"install app\", assert_error=True)\n        assert \"Recipe 'pkg/1.0' seems broken.\" in c.out\n        assert \"It is possible that this recipe is not Conan 2.0 ready\" in c.out\n\n"
  },
  {
    "path": "test/integration/conanfile/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/conanfile/conan_data_test.py",
    "content": "import json\nimport os\nimport shutil\nimport sys\nimport textwrap\n\nimport pytest\nimport yaml\n\nfrom conan.api.model import RecipeReference\nfrom conan.test.utils.file_server import TestFileServer\nfrom conan.test.utils.test_files import tgz_with_contents\nfrom conan.test.utils.tools import TestClient, GenConanfile\nfrom conan.internal.util.files import md5sum, sha1sum, sha256sum, load\n\n\nclass TestConanData:\n\n    def test_conan_exports_kept(self):\n        client = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Lib(ConanFile):\n                exports = \"myfile.txt\"\n            \"\"\")\n        conandata = textwrap.dedent(\"\"\"\n            foo:\n              bar: \"as\"\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile,\n                     \"myfile.txt\": \"bar\",\n                     \"conandata.yml\": conandata})\n        ref = RecipeReference.loads(\"lib/0.1\")\n        client.run(f\"export . --name={ref.name} --version={ref.version}\")\n        export_folder = client.get_latest_ref_layout(ref).export()\n        exported_data = os.path.join(export_folder, \"conandata.yml\")\n        data = yaml.safe_load(load(exported_data))\n        assert data == {\"foo\": {\"bar\": \"as\"}}\n        assert os.path.exists(os.path.join(export_folder, \"myfile.txt\"))\n\n    def test_conan_data_everywhere(self):\n        client = TestClient(light=True)\n        conanfile = \"\"\"from conan import ConanFile\n\nclass Lib(ConanFile):\n\n    def _assert_data(self):\n        assert(self.conan_data[\"sources\"][\"all\"][\"url\"] == \"the url\")\n        assert(self.conan_data[\"sources\"][\"all\"][\"other\"] == \"field\")\n        self.output.info(\"My URL: {}\".format(self.conan_data[\"sources\"][\"all\"][\"url\"]))\n\n    def configure(self):\n        self._assert_data()\n\n    def config_options(self):\n        self._assert_data()\n\n    def source(self):\n        self._assert_data()\n\n    def build(self):\n        self._assert_data()\n\n    def package(self):\n        self._assert_data()\n\n    def package_info(self):\n        self._assert_data()\n\"\"\"\n        client.save({\"conanfile.py\": conanfile,\n                     \"conandata.yml\": \"\"\"\nsources:\n  all:\n    url: \"the url\"\n    other: \"field\"\n\"\"\"})\n        ref = RecipeReference.loads(\"lib/0.1\")\n        client.run(f\"create . --name={ref.name} --version={ref.version}\")\n        assert \"File 'conandata.yml' found. Exporting it...\" in client.out\n        assert \"My URL:\" in client.out\n        export_folder = client.get_latest_ref_layout(ref).export()\n        assert os.path.exists(os.path.join(export_folder, \"conandata.yml\"))\n\n        # Transitive loaded?\n        client.save({\"conanfile.txt\": \"[requires]\\n{}\".format(ref)}, clean_first=True)\n        client.run(\"install . \")\n        assert \"My URL:\" in client.out\n        client.run(\"install . --build='*'\")\n        assert \"My URL:\" in client.out\n\n    def test_conan_data_as_source_newtools(self):\n        client = TestClient(light=True)\n        file_server = TestFileServer()\n        client.servers[\"file_server\"] = file_server\n\n        tgz_path = tgz_with_contents({\"foo.txt\": \"foo\"})\n        if sys.version_info.major == 3 and sys.version_info.minor >= 9:\n            # Python 3.9 changed the tar algorithm. Conan tgz will have different checksums\n            # https://github.com/conan-io/conan/issues/8020\n            md5_value = \"f1d0dee6f0bf5b7747c013dd26183cdb\"\n            sha1_value = \"d45ca9ad171ca9baa93f4da99904036aa71b0ddb\"\n            sha256_value = \"b6880ef494974b8413a107429bde8d6b81a85c45a600040f5334a1d300c203b5\"\n        else:\n            md5_value = \"babc50837f9aaf46e134455966230e3e\"\n            sha1_value = \"1e5b8ff7ae58b40d698fe3d4da6ad2a47ec6f4f3\"\n            sha256_value = \"3ff04581cb0e2f9e976a9baad036f4ca9d884907c3d9382bb42a8616d3c20e42\"\n        assert md5_value == md5sum(tgz_path)\n        assert sha1_value == sha1sum(tgz_path)\n        assert sha256_value == sha256sum(tgz_path)\n\n        shutil.copy2(tgz_path, file_server.store)\n\n        conanfile = textwrap.dedent(\"\"\"\n                from conan import ConanFile\n                from conan.tools.files import get\n\n                class Lib(ConanFile):\n                    def source(self):\n                        data = self.conan_data[\"sources\"][\"all\"]\n                        get(self, **data)\n                        self.output.info(\"OK!\")\n                \"\"\")\n        conandata = textwrap.dedent(\"\"\"\n                sources:\n                  all:\n                    url: \"{}/myfile.tar.gz\"\n                    md5: \"{}\"\n                    sha1: \"{}\"\n                    sha256: \"{}\"\n                \"\"\")\n        client.save({\"conanfile.py\": conanfile,\n                     \"conandata.yml\": conandata.format(file_server.fake_url, md5_value, sha1_value,\n                                                       sha256_value)})\n\n        client.run(f\"create . --name=pkg --version=0.1\")\n        assert \"OK!\" in client.out\n\n        ref_layout = client.exported_layout()\n        source_folder = ref_layout.source()\n        downloaded_file = os.path.join(source_folder, \"foo.txt\")\n        assert \"foo\" == load(downloaded_file)\n\n    def test_invalid_yml(self):\n        client = TestClient(light=True)\n        client.save({\"conanfile.py\": GenConanfile(),\n                     \"conandata.yml\": \">>>> ::\"})\n        ref = RecipeReference.loads(\"lib/0.1\")\n        client.run(f\"create . --name={ref.name} --version={ref.version}\", assert_error=True)\n        assert \"ERROR: Error loading conanfile at\" in client.out\n        assert \": Invalid yml format at conandata.yml: while scanning a block scalar\" in client.out\n\n    def test_conan_data_development_flow(self):\n        client = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class Lib(ConanFile):\n                def layout(self):\n                    self.folders.build = \"tmp/build\"\n\n                def _assert_data(self):\n                    assert(self.conan_data[\"sources\"][\"all\"][\"url\"] == \"this url\")\n                    assert(self.conan_data[\"sources\"][\"all\"][\"other\"] == \"field\")\n                    self.output.info(\"My URL: {}\".format(self.conan_data[\"sources\"][\"all\"][\"url\"]))\n\n                def source(self):\n                    self._assert_data()\n\n                def build(self):\n                    self._assert_data()\n\n                def package(self):\n                    self._assert_data()\n            \"\"\")\n        conandata = textwrap.dedent(\"\"\"\n            sources:\n              all:\n                url: \"this url\"\n                other: \"field\"\n        \"\"\")\n        client.save({\"conanfile.py\": conanfile,\n                     \"conandata.yml\": conandata})\n        client.run(\"source .\")\n        assert \"My URL: this url\" in client.out\n        client.run(\"build . -of=tmp/build\")\n        assert \"My URL: this url\" in client.out\n        client.run(\"export-pkg . --name=name --version=version\")\n        assert \"My URL: this url\" in client.out\n\n    def test_conan_data_serialize(self):\n        c = TestClient(light=True)\n        conandata = textwrap.dedent(\"\"\"\n            src:\n                url: \"this url\"\n        \"\"\")\n        c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\"),\n                \"conandata.yml\": conandata})\n        c.run(\"graph info . --format=json\")\n        graph = json.loads(c.stdout)\n        assert graph[\"graph\"][\"nodes\"][\"0\"][\"conandata\"][\"src\"] == {\"url\": \"this url\"}\n\n        c.run(\"inspect . --format=json\")\n        result = json.loads(c.stdout)\n        assert result[\"conandata\"][\"src\"] == {\"url\": \"this url\"}\n\n\nclass TestConanDataUpdate:\n    \"\"\"\n    testing the update_conandata() method\n    \"\"\"\n    def test_conandata_update(self):\n        \"\"\" test the update_conandata() helper\n        \"\"\"\n        c = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import update_conandata\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                def export(self):\n                    update_conandata(self, {\"sources\": {\"0.1\": {\"commit\": 123, \"type\": \"git\"},\n                                                        \"0.2\": {\"url\": \"new\"}\n                                                       }\n                                           })\n\n                def source(self):\n                    data = self.conan_data[\"sources\"]\n                    self.output.info(\"0.1-commit: {}!!\".format(data[\"0.1\"][\"commit\"]))\n                    self.output.info(\"0.1-type: {}!!\".format(data[\"0.1\"][\"type\"]))\n                    self.output.info(\"0.1-url: {}!!\".format(data[\"0.1\"][\"url\"]))\n                    self.output.info(\"0.2-url: {}!!\".format(data[\"0.2\"][\"url\"]))\n            \"\"\")\n        conandata = textwrap.dedent(\"\"\"\\\n            sources:\n                \"0.1\":\n                    url: myurl\n                    commit: 234\n            \"\"\")\n        c.save({\"conanfile.py\": conanfile,\n                \"conandata.yml\": conandata})\n        c.run(\"create .\")\n        assert \"pkg/0.1: 0.1-commit: 123!!\" in c.out\n        assert \"pkg/0.1: 0.1-type: git!!\" in c.out\n        assert \"pkg/0.1: 0.1-url: myurl!!\" in c.out\n        assert \"pkg/0.1: 0.2-url: new!!\" in c.out\n\n    def test_conandata_update_error(self):\n        \"\"\" test the update_conandata() helper fails if used outside export()\n        \"\"\"\n        c = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import update_conandata\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                def source(self):\n                    update_conandata(self, {})\n            \"\"\")\n        c.save({\"conanfile.py\": conanfile})\n        c.run(\"create .\", assert_error=True)\n        assert \"The 'update_conandata()' can only be used in the 'export()' method\" in c.out\n\n    def test_conandata_create_if_not_exist(self):\n        \"\"\" test the update_conandata() creates the file if it doesn't exist\n        \"\"\"\n        c = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import update_conandata\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                def export(self):\n                    update_conandata(self, {\"data\": \"value\"})\n            \"\"\")\n        c.save({\"conanfile.py\": conanfile})\n        c.run(\"export .\")  # It doesn't fail\n        assert \"pkg/0.1: Calling export()\" in c.out\n\n\ndef test_conandata_trim():\n    \"\"\" test the explict trim_conandata() helper\n    \"\"\"\n    c = TestClient(light=True)\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import trim_conandata\n\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            def export(self):\n                trim_conandata(self)\n        \"\"\")\n    conandata_yml = textwrap.dedent(\"\"\"\\\n        sources:\n          \"1.0\":\n            url: \"url1\"\n            sha256: \"sha1\"\n        patches:\n          \"1.0\":\n            - patch_file: \"patches/some_patch\"\n              base_path: \"source_subfolder\"\n        something: else\n          \"\"\")\n    c.save({\"conanfile.py\": conanfile,\n            \"conandata.yml\": conandata_yml})\n    c.run(\"export . --version=1.0\")\n    layout = c.exported_layout()\n    data1 = load(os.path.join(layout.export(), \"conandata.yml\"))\n    assert \"pkg/1.0: Exported: pkg/1.0#70612e15e4fc9af1123fe11731ac214f\" in c.out\n    conandata_yml2 = textwrap.dedent(\"\"\"\\\n        sources:\n         \"1.0\":\n           url: \"url1\"\n           sha256: \"sha1\"\n         \"1.1\":\n           url: \"url2\"\n           sha256: \"sha2\"\n        patches:\n         \"1.1\":\n           - patch_file: \"patches/some_patch2\"\n             base_path: \"source_subfolder\"\n         \"1.0\":\n           - patch_file: \"patches/some_patch\"\n             base_path: \"source_subfolder\"\n        something: else\n        \"\"\")\n    c.save({\"conandata.yml\": conandata_yml2})\n    c.run(\"export . --version=1.0\")\n    layout = c.exported_layout()\n    data2 = load(os.path.join(layout.export(), \"conandata.yml\"))\n    assert \"1.1\" not in data2\n    assert data1 == data2\n    assert \"pkg/1.0: Exported: pkg/1.0#70612e15e4fc9af1123fe11731ac214f\" in c.out\n    # If I now try to create version 1.2 which has no patches, and then change a patch\n    # its revision should not change either\n    conandata_yml3 = textwrap.dedent(\"\"\"\\\n    sources:\n      \"1.0\":\n        url: \"url1\"\n        sha256: \"sha1\"\n      \"1.1\":\n        url: \"url2\"\n        sha256: \"sha2\"\n      \"1.3\":\n        url: \"url3\"\n        sha256: \"sha3\"\n    patches:\n      \"1.1\":\n        - patch_file: \"patches/some_patch2\"\n          base_path: \"source_subfolder\"\n      \"1.0\":\n        - patch_file: \"patches/some_patch\"\n          base_path: \"source_subfolder\"\n    something: else\"\"\")\n    c.save({\"conandata.yml\": conandata_yml3})\n    c.run(\"export . --version=1.3\")\n    initial_v13_rev = c.exported_recipe_revision()\n    conandata_yml4 = textwrap.dedent(\"\"\"\\\n        sources:\n          \"1.0\":\n            url: \"url1\"\n            sha256: \"sha1\"\n          \"1.1\":\n            url: \"url2\"\n            sha256: \"sha2\"\n          \"1.3\":\n            url: \"url3\"\n            sha256: \"sha3\"\n        patches:\n          \"1.1\":\n            - patch_file: \"patches/some_patch2-v2\"\n              base_path: \"source_subfolder\"\n          \"1.0\":\n            - patch_file: \"patches/some_patch\"\n              base_path: \"source_subfolder\"\n        something: else\"\"\")\n    c.save({\"conandata.yml\": conandata_yml4})\n    c.run(\"export . --version=1.3\")\n    second_v13_rev = c.exported_recipe_revision()\n    assert initial_v13_rev == second_v13_rev\n\n\ndef test_trim_conandata_as_hook():\n    c = TestClient(light=True)\n    c.save_home({\"extensions/hooks/hook_trim.py\": textwrap.dedent(\"\"\"\n    from conan.tools.files import trim_conandata\n\n    def post_export(conanfile):\n        trim_conandata(conanfile)\n    \"\"\")})\n\n    conandata_yml = textwrap.dedent(\"\"\"\\\n            sources:\n              \"1.0\":\n                url: \"url1\"\n                sha256: \"sha1\"\n            patches:\n              \"1.0\":\n                - patch_file: \"patches/some_patch\"\n                  base_path: \"source_subfolder\"\n            something: else\n              \"\"\")\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\"),\n            \"conandata.yml\": conandata_yml})\n    c.run(\"export . --version=1.0\")\n    layout = c.exported_layout()\n    data1 = load(os.path.join(layout.export(), \"conandata.yml\"))\n    assert \"pkg/1.0: Exported: pkg/1.0#03af39add1c7c9d68dcdb10b6968a14d\" in c.out\n    conandata_yml2 = textwrap.dedent(\"\"\"\\\n            sources:\n             \"1.0\":\n               url: \"url1\"\n               sha256: \"sha1\"\n             \"1.1\":\n               url: \"url2\"\n               sha256: \"sha2\"\n            patches:\n             \"1.1\":\n               - patch_file: \"patches/some_patch2\"\n                 base_path: \"source_subfolder\"\n             \"1.0\":\n               - patch_file: \"patches/some_patch\"\n                 base_path: \"source_subfolder\"\n            something: else\n            \"\"\")\n    c.save({\"conandata.yml\": conandata_yml2})\n    c.run(\"export . --version=1.0\")\n    layout = c.exported_layout()\n    data2 = load(os.path.join(layout.export(), \"conandata.yml\"))\n    assert \"1.1\" not in data2\n    assert data1 == data2\n    assert \"pkg/1.0: Exported: pkg/1.0#03af39add1c7c9d68dcdb10b6968a14d\" in c.out\n\n\n@pytest.mark.parametrize(\"raise_if_missing\", [True, False])\ndef test_trim_conandata_as_hook_without_conandata(raise_if_missing):\n    c = TestClient(light=True)\n    c.save_home({\"extensions/hooks/hook_trim.py\": textwrap.dedent(f\"\"\"\n    from conan.tools.files import trim_conandata\n\n    def post_export(conanfile):\n        trim_conandata(conanfile, raise_if_missing={raise_if_missing})\n    \"\"\")})\n\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\")})\n    if raise_if_missing:\n        c.run(\"export . --version=1.0\", assert_error=True)\n    else:\n        c.run(\"export . --version=1.0\")\n        assert c.exported_recipe_revision() == \"a9ec2e5fbb166568d4670a9cd1ef4b26\"\n\n\ndef test_trim_conandata_anchors():\n    \"\"\"Anchors load correctly, because trim_conandata loads the yaml instead of replacing in place\"\"\"\n    tc = TestClient(light=True)\n    tc.save({\"conanfile.py\": textwrap.dedent(\"\"\"\n     from conan import ConanFile\n     from conan.tools.files import trim_conandata\n\n     class Pkg(ConanFile):\n        name = \"pkg\"\n        def export(self):\n            trim_conandata(self)\n\n        def generate(self):\n            self.output.info(\"x: {}\".format(self.conan_data[\"mapping\"][self.version][\"x\"]))\n    \"\"\"),\n             \"conandata.yml\": textwrap.dedent(\"\"\"\n             mapping:\n                \"1.0\": &anchor\n                    \"x\": \"foo\"\n                \"2.0\": *anchor\n             \"\"\")})\n    tc.run(\"create . --version=2.0\")\n    assert \"x: foo\" in tc.out\n    pkg_layout = tc.exported_layout()\n    conandata = tc.load(pkg_layout.conandata())\n    assert conandata == textwrap.dedent(\"\"\"\\\n        mapping:\n          '2.0':\n            x: foo\n        \"\"\")\n"
  },
  {
    "path": "test/integration/conanfile/conanfile_errors_test.py",
    "content": "import textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestConanfileErrors:\n\n    def test_copy_error(self):\n        client = TestClient(light=True)\n        conanfile = textwrap.dedent('''\n            from conan import ConanFile\n\n            class HelloConan(ConanFile):\n                name = \"hello\"\n                version = \"0.1\"\n                exports = \"*\"\n                def package(self):\n                    self.copy2(\"*.h\", dst=\"include\", src=[\"include\",\"platform\"])\n            ''')\n        files = {\"conanfile.py\": conanfile, \"test.txt\": \"Hello world\"}\n        client.save(files)\n        client.run(\"export . --user=lasote --channel=stable\")\n        client.run(\"install --requires=hello/0.1@lasote/stable --build='*'\", assert_error=True)\n        assert \"hello/0.1@lasote/stable: Error in package() method, line 9\" in client.out\n        assert 'self.copy2(\"*.h\", dst=\"include\", src=[\"include\",\"platform\"]' in client.out\n        assert \"'HelloConan' object has no attribute 'copy2'\" in client.out\n\n    def test_copy_error2(self):\n        client = TestClient(light=True)\n        conanfile = textwrap.dedent('''\n            from conan import ConanFile\n\n            class HelloConan(ConanFile):\n                name = \"hello\"\n                version = \"0.1\"\n                exports = \"*\"\n                def package(self):\n                    self.copy(\"*.h\", dst=\"include\", src=[\"include\",\"platform\"])\n            ''')\n        files = {\"conanfile.py\": conanfile, \"test.txt\": \"Hello world\"}\n        client.save(files)\n        client.run(\"export . --user=lasote --channel=stable\")\n        client.run(\"install --requires=hello/0.1@lasote/stable --build='*'\", assert_error=True)\n        assert \"hello/0.1@lasote/stable: Error in package() method, line 9\" in client.out\n        assert 'self.copy(\"*.h\", dst=\"include\", src=[\"include\",\"platform\"]' in client.out\n        # It results that the error is different in different Python2/3 and OSs\n        # assert \"'list' object has no attribute 'replace'\" in client.out\n\n    def test_package_info_error(self):\n        client = TestClient(light=True)\n        conanfile = textwrap.dedent('''\n            from conan import ConanFile\n\n            class HelloConan(ConanFile):\n                name = \"hello\"\n                version = \"0.1\"\n                exports = \"*\"\n                def package_info(self):\n                    self.copy2()\n            ''')\n        files = {\"conanfile.py\": conanfile, \"test.txt\": \"Hello world\"}\n        client.save(files)\n        client.run(\"export . --user=lasote --channel=stable\")\n        client.run(\"install --requires=hello/0.1@lasote/stable --build='*'\", assert_error=True)\n        assert \"hello/0.1@lasote/stable: Error in package_info() method, line 9\" in client.out\n        assert 'self.copy2()' in client.out\n        assert \"'HelloConan' object has no attribute 'copy2'\" in client.out\n\n    def test_config_error(self):\n        client = TestClient(light=True)\n        conanfile = textwrap.dedent('''\n            from conan import ConanFile\n\n            class HelloConan(ConanFile):\n                name = \"hello\"\n                version = \"0.1\"\n                exports = \"*\"\n                def configure(self):\n                    self.copy2()\n            ''')\n        files = {\"conanfile.py\": conanfile, \"test.txt\": \"Hello world\"}\n        client.save(files)\n        client.run(\"export . --user=lasote --channel=stable\")\n        client.run(\"install --requires=hello/0.1@lasote/stable --build='*'\", assert_error=True)\n\n        assert \"ERROR: hello/0.1@lasote/stable: Error in configure() method, line 9\" in client.out\n        assert \"self.copy2()\" in client.out\n        assert \"AttributeError: 'HelloConan' object has no attribute 'copy2'\"\"\" in client.out\n\n    def test_source_error(self):\n        client = TestClient(light=True)\n        conanfile = textwrap.dedent('''\n            from conan import ConanFile\n\n            class HelloConan(ConanFile):\n                name = \"hello\"\n                version = \"0.1\"\n                exports = \"*\"\n                def source(self):\n                    self.copy2()\n            ''')\n        files = {\"conanfile.py\": conanfile, \"test.txt\": \"Hello world\"}\n        client.save(files)\n        client.run(\"export . --user=lasote --channel=stable\")\n        client.run(\"install --requires=hello/0.1@lasote/stable --build='*'\", assert_error=True)\n        assert \"hello/0.1@lasote/stable: Error in source() method, line 9\" in client.out\n        assert 'self.copy2()' in client.out\n        assert \"'HelloConan' object has no attribute 'copy2'\" in client.out\n\n    def test_duplicate_requires(self):\n        client = TestClient(light=True)\n        conanfile = textwrap.dedent('''\n            [requires]\n            foo/0.1@user/testing\n            foo/0.2@user/testing\n            ''')\n        files = {\"conanfile.txt\": conanfile}\n        client.save(files)\n        client.run(\"install . --build='*'\", assert_error=True)\n        assert \"ERROR: Duplicated requirement\" in client.out\n\n    def test_duplicate_requires_py(self):\n        client = TestClient(light=True)\n        conanfile = textwrap.dedent('''\n            from conan import ConanFile\n\n            class HelloConan(ConanFile):\n                name = \"hello\"\n                version = \"0.1\"\n                requires = \"foo/0.1@user/testing\", \"foo/0.2@user/testing\"\n            ''')\n        files = {\"conanfile.py\": conanfile}\n        client.save(files)\n        client.run(\"export .\", assert_error=True)\n        assert \"Duplicated requirement\" in client.out\n\n\nclass TestWrongMethods:\n    # https://github.com/conan-io/conan/issues/12961\n    @pytest.mark.parametrize(\"requires\", [\"requires\", \"tool_requires\",\n                                          \"test_requires\", \"build_requires\"])\n    def test_wrong_method_requires(self, requires):\n        \"\"\" this is expected to be a relatively frequent user error, and the trace was\n        very ugly and debugging complicated\n        \"\"\"\n        c = TestClient(light=True)\n        conanfile = textwrap.dedent(f\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                def {requires}(self):\n                    pass\n            \"\"\")\n        c.save({\"conanfile.py\": conanfile})\n        c.run(\"install .\", assert_error=True)\n        expected = \"requirements\" if requires == \"requires\" else \"build_requirements\"\n        assert f\" Wrong '{requires}' definition, did you mean '{expected}()'?\" in c.out\n\n\ndef test_notduplicate_requires_py():\n    client = TestClient(light=True)\n    conanfile = textwrap.dedent('''\n        from conan import ConanFile\n\n        class HelloConan(ConanFile):\n            name = \"hello\"\n            version = \"0.1\"\n            requires = \"foo/0.1@user/testing\"\n            build_requires = \"foo/0.2@user/testing\"\n        ''')\n    files = {\"conanfile.py\": conanfile}\n    client.save(files)\n    client.run(\"export .\")\n    assert \"hello/0.1: Exported\" in client.out\n\n\ndef test_requirements_change_options():\n    c = TestClient(light=True)\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class HelloConan(ConanFile):\n            name = \"hello\"\n            version = \"0.1\"\n\n            def requirements(self):\n                self.options[\"mydep\"].myoption = 3\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"create .\", assert_error=True)\n    assert \"ERROR: hello/0.1: Dependencies options were defined incorrectly.\" in c.out\n\n\n@pytest.mark.parametrize(\"property_name\", [\"libdir\", \"bindir\", \"includedir\"])\n@pytest.mark.parametrize(\"property_content\", [[], [\"mydir1\", \"mydir2\"]])\ndef test_shorthand_bad_interface(property_name, property_content):\n    c = TestClient(light=True)\n    conanfile = textwrap.dedent(f\"\"\"\n        from conan import ConanFile\n\n        class HelloConan(ConanFile):\n            name = \"hello\"\n            version = \"0.1\"\n\n            def package_info(self):\n                self.cpp_info.{property_name}s = {property_content}\n                self.output.info(self.cpp_info.{property_name})\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"create .\", assert_error=True)\n    if property_content:\n        assert (f\"The {property_name} property is undefined because \"\n                f\"{property_name}s has more than one element.\") in c.out\n    else:\n        assert (f\"The {property_name} property is undefined because \"\n                f\"{property_name}s is empty.\") in c.out\n\n\ndef test_consumer_unexpected():\n    tc = TestClient(light=True)\n    cmake_conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n\n    class CMake(ConanFile):\n        name = \"cmake\"\n        version = \"1.0\"\n        package_type = \"application\"\n\n        def package_info(self):\n            self.output.info(\"cmake/1.0 -> \" + str(self._conan_is_consumer))\n    \"\"\")\n    tc.save({\n             \"cmake/conanfile.py\": cmake_conanfile,\n             \"dep1/conanfile.py\": GenConanfile(\"dep1\", \"1.0\"),\n             \"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_requires(\"dep1/1.0\"),\n             \"profile\": \"include(default)\\n[tool_requires]\\n*: cmake/1.0\\n\"})\n    tc.run(\"export dep1\")\n    tc.run(\"create cmake\")\n    tc.run(\"create . -b=missing -pr=profile\")\n    assert \"cmake/1.0 -> True\" not in tc.out\n\n\n@pytest.mark.parametrize(\"languages\", [\n    \"['C', 'CXX']\",\n    \"['CXX']\",\n    \"'CXX'\",\n])\ndef test_language_unexpected(languages):\n    tc = TestClient(light=True)\n    tc.save({\"conanfile.py\": GenConanfile().with_class_attribute(f\"languages = {languages}\")})\n    tc.run(\"inspect .\", assert_error=True)\n    assert \"Only 'C' and 'C++' languages are allowed in 'languages' attribute\" in tc.out\n\n\ndef test_empty_languages():\n    tc = TestClient(light=True)\n    tc.save({\"conanfile.py\": GenConanfile().with_class_attribute(\"languages = []\")})\n    tc.run(\"inspect .\")\n    assert \"Only 'C' and 'C++' languages are allowed in 'languages' attribute\" not in tc.out\n"
  },
  {
    "path": "test/integration/conanfile/conanfile_helpers_test.py",
    "content": "import pytest\n\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestConanfileHelpers:\n\n    @pytest.mark.parametrize(\"scope_imports\", [True, False])\n    def test_helpers_same_name(self, scope_imports):\n        helpers = '''\ndef build_helper(output):\n    output.info(\"Building %d!\")\n    '''\n        other_helper = '''\ndef source_helper(output):\n    output.info(\"Source %d!\")\n    '''\n\n        if scope_imports:\n            file_content = '''from conan import ConanFile\nfrom myhelper import build_helper\nfrom myhelpers.other import source_helper\n\nclass ConanFileToolsTest(ConanFile):\n    exports = \"*\"\n\n    def source(self):\n        source_helper(self.output)\n\n    def build(self):\n        build_helper(self.output)\n'''\n        else:\n            file_content = '''from conan import ConanFile\nimport myhelper\nfrom myhelpers import other\n\nclass ConanFileToolsTest(ConanFile):\n    exports = \"*\"\n\n    def source(self):\n        other.source_helper(self.output)\n\n    def build(self):\n        myhelper.build_helper(self.output)\n'''\n\n        def files(number):\n            return {\"myhelper.py\": helpers % number,\n                    \"myhelpers/__init__.py\": \"\",\n                    \"myhelpers/other.py\": other_helper % number,\n                    \"conanfile.py\": file_content}\n\n        client = TestClient()\n        client.save(files(1))\n        client.run(\"export . --name=test --version=1.9 --user=user --channel=testing\")\n        client.save(files(2), clean_first=True)\n        client.run(\"export . --name=test2 --version=2.3 --user=user --channel=testing\")\n\n        files = {\"conanfile.txt\": \"\"\"[requires]\n                                    test/1.9@user/testing\\n\n                                    test2/2.3@user/testing\"\"\"}\n        client.save(files, clean_first=True)\n        client.run(\"install . --build='*'\")\n        assert \"test/1.9@user/testing: Building 1!\" in client.out\n        assert \"test/1.9@user/testing: Source 1!\" in client.out\n        assert \"test2/2.3@user/testing: Building 2!\" in client.out\n        assert \"test2/2.3@user/testing: Source 2!\" in client.out\n"
  },
  {
    "path": "test/integration/conanfile/files/.gitattributes",
    "content": "*.txt -text -diff\n"
  },
  {
    "path": "test/integration/conanfile/files/conanfile_utf8.txt",
    "content": "[requires]\n\n[generators]\nCMakeToolchain\n"
  },
  {
    "path": "test/integration/conanfile/files/conanfile_utf8_with_bom.txt",
    "content": "﻿[requires]\n\n[generators]\nCMakeToolchain\n"
  },
  {
    "path": "test/integration/conanfile/folders_access_test.py",
    "content": "import textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\nconanfile_parent = \"\"\"\nfrom conan import ConanFile\n\nclass parentLib(ConanFile):\n    name = \"parent\"\n    version = \"1.0\"\n\n    def package_info(self):\n        self.cpp_info.cxxflags.append(\"-myflag\")\n        self.buildenv_info.define(\"MyEnvVar\", \"MyEnvVarValue\")\n\"\"\"\n\n\nconanfile = \"\"\"\nimport os\nfrom conan import ConanFile\nfrom pathlib import Path\n\nclass AConan(ConanFile):\n    name = \"lib\"\n    version = \"1.0\"\n\n    # To save the folders and check later if the folder is the same\n    copy_build_folder = None\n    copy_source_folder = None\n    copy_package_folder = None\n\n    counter_package_calls = 0\n\n    no_copy_source = %(no_copy_source)s\n    requires = \"parent/1.0@conan/stable\"\n    running_local_command = %(local_command)s\n\n    def source(self):\n        assert(self.source_folder == os.getcwd())\n        assert(isinstance(self.source_path, Path))\n        assert(str(self.source_path) == self.source_folder)\n\n        # Prevented to use them, it's dangerous, because the source is run only for the first\n        # config, so only the first build_folder/package_folder would be modified\n        assert(self.build_folder is None)\n        assert(self.package_folder is None)\n\n        assert(self.source_folder is not None)\n        self.copy_source_folder = self.source_folder\n\n    def build(self):\n        assert(self.build_folder == os.getcwd())\n        assert(isinstance(self.build_path, Path))\n        assert(str(self.build_path) == self.build_folder)\n\n        if self.no_copy_source:\n            assert(self.copy_source_folder == self.source_folder)  # Only in install\n        else:\n            assert(self.source_folder == self.build_folder)\n\n        assert(self.package_folder is not None)\n        assert(isinstance(self.package_path, Path))\n        assert(str(self.package_path) == self.package_folder)\n        self.copy_build_folder = self.build_folder\n\n    def package(self):\n        assert(self.build_folder == os.getcwd())\n        assert(isinstance(self.build_path, Path))\n        assert(str(self.build_path) == self.build_folder)\n\n        if self.no_copy_source:\n            assert(self.copy_source_folder == self.source_folder)  # Only in install\n        else:\n            assert(self.source_folder == self.build_folder)\n\n        self.copy_package_folder = self.package_folder\n\n    def package_info(self):\n        assert(self.package_folder == os.getcwd())\n        assert(isinstance(self.package_path, Path))\n        assert(str(self.package_path) == self.package_folder)\n\"\"\"\n\n\nclass TestFoldersAccess:\n    \"\"\"\"Tests the presence of self.source_folder, self.build_folder, self.package_folder\n    in the conanfile methods. Also the availability of the self.deps_cpp_info, self.deps_user_info\n    and self.deps_env_info.\"\"\"\n\n    @pytest.fixture(autouse=True)\n    def setup(self):\n        self.client = TestClient(light=True)\n        self.client.save({\"conanfile.py\": conanfile_parent})\n        self.client.run(\"export . --user=conan --channel=stable\")\n\n    def test_source_local_command(self):\n        c1 = conanfile % {\"no_copy_source\": False,\n                          \"local_command\": True}\n        self.client.save({\"conanfile.py\": c1}, clean_first=True)\n        self.client.run(\"source .\")\n\n        c1 = conanfile % {\"no_copy_source\": True,\n                          \"local_command\": True}\n        self.client.save({\"conanfile.py\": c1}, clean_first=True)\n        self.client.run(\"source .\")\n\n    def test_deploy(self):\n        c1 = conanfile % {\"no_copy_source\": False,\n                          \"local_command\": False}\n        self.client.save({\"conanfile.py\": c1}, clean_first=True)\n        self.client.run(\"create . --user=user --channel=testing --build missing\")\n        self.client.run(\"install --requires=lib/1.0@user/testing\")  # Checks deploy\n\n    def test_full_install(self):\n        c1 = conanfile % {\"no_copy_source\": False,\n                          \"local_command\": False}\n        self.client.save({\"conanfile.py\": c1}, clean_first=True)\n        self.client.run(\"create . --user=conan --channel=stable --build='*'\")\n\n        c1 = conanfile % {\"no_copy_source\": True,\n                          \"local_command\": False}\n        self.client.save({\"conanfile.py\": c1}, clean_first=True)\n        self.client.run(\"create . --user=conan --channel=stable --build='*'\")\n\n        c1 = conanfile % {\"no_copy_source\": False,\n                          \"local_command\": False}\n        self.client.save({\"conanfile.py\": c1}, clean_first=True)\n        self.client.run(\"create . --user=conan --channel=stable --build='*'\")\n\n\nclass TestRecipeFolder:\n    recipe_conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import load\n        import os\n        class Pkg(ConanFile):\n            exports = \"file.txt\"\n            def init(self):\n                r = load(self, os.path.join(self.recipe_folder, \"file.txt\"))\n                self.output.info(\"INIT: {}\".format(r))\n            def set_name(self):\n                r = load(self, os.path.join(self.recipe_folder, \"file.txt\"))\n                self.output.info(\"SET_NAME: {}\".format(r))\n            def configure(self):\n                r = load(self, os.path.join(self.recipe_folder, \"file.txt\"))\n                self.output.info(\"CONFIGURE: {}\".format(r))\n            def requirements(self):\n                r = load(self, os.path.join(self.recipe_folder, \"file.txt\"))\n                self.output.info(\"REQUIREMENTS: {}\".format(r))\n            def package(self):\n                r = load(self, os.path.join(self.recipe_folder, \"file.txt\"))\n                self.output.info(\"PACKAGE: {}\".format(r))\n            def package_info(self):\n                r = load(self, os.path.join(self.recipe_folder, \"file.txt\"))\n                self.output.info(\"PACKAGE_INFO: {}\".format(r))\n        \"\"\")\n\n    def test_recipe_folder(self):\n        client = TestClient(light=True)\n        client.save({\"conanfile.py\": self.recipe_conanfile,\n                     \"file.txt\": \"MYFILE!\"})\n        client.run(\"export . --name=pkg --version=0.1 --user=user --channel=testing\")\n        assert \"INIT: MYFILE!\" in client.out\n        assert \"SET_NAME: MYFILE!\" in client.out\n        client.save({}, clean_first=True)\n        client.run(\"install --requires=pkg/0.1@user/testing --build='*'\")\n        assert \"pkg/0.1@user/testing: INIT: MYFILE!\" in client.out\n        assert \"SET_NAME\" not in client.out\n        assert \"pkg/0.1@user/testing: CONFIGURE: MYFILE!\" in client.out\n        assert \"pkg/0.1@user/testing: REQUIREMENTS: MYFILE!\" in client.out\n        assert \"pkg/0.1@user/testing: PACKAGE: MYFILE!\" in client.out\n        assert \"pkg/0.1@user/testing: PACKAGE_INFO: MYFILE!\" in client.out\n\n    def test_local_flow(self):\n        client = TestClient(light=True)\n        client.save({\"conanfile.py\": self.recipe_conanfile,\n                     \"file.txt\": \"MYFILE!\"})\n        client.run(\"install .\")\n        assert \"INIT: MYFILE!\" in client.out\n        assert \"SET_NAME: MYFILE!\" in client.out\n        assert \"conanfile.py: CONFIGURE: MYFILE!\" in client.out\n        assert \"conanfile.py: REQUIREMENTS: MYFILE!\" in client.out\n\n    def test_editable(self):\n        client = TestClient(light=True)\n        client.save({\"pkg/conanfile.py\": self.recipe_conanfile,\n                     \"pkg/file.txt\": \"MYFILE!\",\n                     \"consumer/conanfile.py\":\n                         GenConanfile().with_require(\"pkg/0.1@user/stable\")})\n        client.run(\"editable add pkg --name=pkg --version=0.1 --user=user --channel=stable\")\n\n        client.run(\"install consumer\")\n        client.assert_listed_require({\"pkg/0.1@user/stable\": \"Editable\"})\n        assert \"pkg/0.1@user/stable: INIT: MYFILE!\" in client.out\n        assert \"pkg/0.1@user/stable: CONFIGURE: MYFILE!\" in client.out\n        assert \"pkg/0.1@user/stable: REQUIREMENTS: MYFILE!\" in client.out\n        assert \"pkg/0.1@user/stable: PACKAGE_INFO: MYFILE!\" in client.out\n"
  },
  {
    "path": "test/integration/conanfile/generators_list_test.py",
    "content": "import textwrap\n\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestConanfileRepeatedGenerators:\n\n    def test_conanfile_txt(self):\n        conanfile = textwrap.dedent(\"\"\"\n            [generators]\n            CMakeDeps\n            CMakeDeps\n        \"\"\")\n\n        t = TestClient()\n        t.save({'conanfile.txt': conanfile})\n        t.run(\"install conanfile.txt\")\n        assert str(t.out).count(\"Generator 'CMakeDeps' calling 'generate()'\") == 1\n\n    def test_conanfile_py(self):\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class Recipe(ConanFile):\n                settings = \"build_type\"\n                generators = \"CMakeDeps\", \"CMakeDeps\"\n        \"\"\")\n        t = TestClient()\n        t.save({'conanfile.py': conanfile})\n        t.run(\"install conanfile.py\")\n        assert str(t.out).count(\"Generator 'CMakeDeps' calling 'generate()'\") == 1\n\n    def test_python_requires_inheritance(self):\n        pyreq = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class Recipe(ConanFile):\n                pass\n\n            class BaseConan(object):\n                generators = \"CMakeDeps\",\n        \"\"\")\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class Recipe(ConanFile):\n                settings = \"build_type\"\n                python_requires = \"base/1.0\"\n                python_requires_extend = \"base.BaseConan\"\n                settings = \"build_type\"\n                generators = \"CMakeDeps\",\n\n                def init(self):\n                    base = self.python_requires[\"base\"].module.BaseConan\n                    self.generators = base.generators + self.generators\n        \"\"\")\n\n        t = TestClient()\n        t.save({'pyreq.py': pyreq, 'conanfile.py': conanfile})\n        t.run(\"export pyreq.py --name=base --version=1.0\")\n        t.run(\"install conanfile.py\")\n        assert str(t.out).count(\"Generator 'CMakeDeps' calling 'generate()'\") == 1\n\n    def test_duplicated_generator_in_member_and_attribue(self):\n        \"\"\"\n        Ensure we raise an error when a generator is present both in the generators attribute\n        and instanced in the generate() method by the user, which we didn't use to do before 2.0\n        \"\"\"\n        conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMakeToolchain\n\n        class Recipe(ConanFile):\n            generators = \"CMakeToolchain\"\n\n            def generate(self):\n                tc = CMakeToolchain(self)\n                tc.generate()\n        \"\"\")\n\n        t = TestClient()\n        t.save({'conanfile.py': conanfile})\n        # This used to not throw any errors\n        t.run(\"install .\", assert_error=True)\n        assert \"was instantiated in the generate() method too\" in t.out\n"
  },
  {
    "path": "test/integration/conanfile/init_test.py",
    "content": "import textwrap\n\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestInit:\n    def test_wrong_init(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Lib(ConanFile):\n                def init(self):\n                    random_error\n            \"\"\")\n\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"export .\", assert_error=True)\n        assert \"Error in init() method, line 5\" in client.out\n        assert \"name 'random_error' is not defined\" in client.out\n\n    def test_init(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import load\n            import os\n            import json\n            class Lib(ConanFile):\n                exports = \"data.json\"\n                def init(self):\n                    data = load(self, os.path.join(self.recipe_folder, \"data.json\"))\n                    d = json.loads(data)\n                    self.license = d[\"license\"]\n                    self.description = d[\"description\"]\n                def export(self):\n                    self.output.info(\"description: %s\" % self.description)\n                    self.output.info(\"license: %s\" % self.license)\n                def build(self):\n                    self.output.info(\"description: %s\" % self.description)\n                    self.output.info(\"license: %s\" % self.license)\n            \"\"\")\n        data = '{\"license\": \"MIT\", \"description\": \"MyDescription\"}'\n        client.save({\"conanfile.py\": conanfile,\n                     \"data.json\": data})\n\n        client.run(\"export . --name=pkg --version=version\")\n        assert \"description: MyDescription\" in client.out\n        assert \"license: MIT\" in client.out\n        client.run(\"create . --name=pkg --version=0.1 --user=user --channel=testing\")\n        assert \"description: MyDescription\" in client.out\n        assert \"license: MIT\" in client.out\n\n    def test_options_from_yml(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\\\n            from conan import ConanFile\n\n            class Lib(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n\n                def init(self):\n                    self.options.update(self.conan_data[\"options\"],\n                                        self.conan_data[\"default_options\"])\n            \"\"\")\n        conandata = textwrap.dedent(\"\"\"\\\n            options:\n                myopt1: [1, 2, 3]\n                myopt2: [null, potato]\n                myopt3: [null, ANY]\n            default_options:\n                myopt1: 2\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile,\n                     \"conandata.yml\": conandata})\n\n        client.run(\"create . \")\n        client.run(\"create . -o &:myopt1=1 -o &:myopt2=potato -o &:myopt3=whatever\")\n        client.run(\"list *:*\")\n\n        assert \"myopt1: 2\" in client.out\n        assert \"myopt1: 1\" in client.out\n        assert \"myopt2: potato\" in client.out\n        assert \"myopt3: whatever\" in client.out\n"
  },
  {
    "path": "test/integration/conanfile/invalid_configuration_test.py",
    "content": "import textwrap\n\nimport pytest\n\nfrom conan.cli.exit_codes import ERROR_INVALID_CONFIGURATION\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestInvalidConfiguration:\n\n    @pytest.fixture(autouse=True)\n    def setup(self):\n        self.client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\\\n\n            from conan import ConanFile\n            from conan.errors import ConanInvalidConfiguration\n\n            class MyPkg(ConanFile):\n                settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n                def configure(self):\n                    if self.settings.compiler.version == \"190\":\n                        raise ConanInvalidConfiguration(\"compiler.version=12 is invalid!!\")\n            \"\"\")\n        self.client.save({\"conanfile.py\": conanfile})\n        settings = \"-s os=Windows -s compiler=msvc -s compiler.version={ver} \"\\\n                   \"-s compiler.runtime=dynamic\"\n        self.settings_msvc15 = settings.format(ver=\"192\")\n        self.settings_msvc12 = settings.format(ver=\"190\")\n\n    def test_install_method(self):\n        self.client.run(\"install . %s\" % self.settings_msvc15)\n\n        error = self.client.run(\"install . %s\" % self.settings_msvc12, assert_error=True)\n        assert error == ERROR_INVALID_CONFIGURATION\n        assert \"Invalid configuration: compiler.version=12 is invalid!!\" in self.client.out\n\n    def test_info_method(self):\n        self.client.run(\"graph info . %s\" % self.settings_msvc15)\n\n        error = self.client.run(\"graph info . %s\" % self.settings_msvc12, assert_error=True)\n        assert error == ERROR_INVALID_CONFIGURATION\n        assert \"Invalid configuration: compiler.version=12 is invalid!!\" in self.client.out\n\n    def test_create_method(self):\n        self.client.run(\"create . --name=name --version=ver %s\" % self.settings_msvc15)\n\n        error = self.client.run(\"create . --name=name --version=ver %s\" % self.settings_msvc12,\n                                assert_error=True)\n        assert error == ERROR_INVALID_CONFIGURATION\n        assert \"name/ver: Invalid configuration: compiler.version=12 is invalid!!\" in self.client.out\n\n    def test_as_requirement(self):\n        self.client.run(\"create . --name=name --version=ver %s\" % self.settings_msvc15)\n        self.client.save({\"other/conanfile.py\": GenConanfile().with_requirement(\"name/ver\")})\n        self.client.run(\"create other/ --name=other --version=1.0 %s\" % self.settings_msvc15)\n\n        error = self.client.run(\"create other/ --name=other --version=1.0 %s\" % self.settings_msvc12,\n                                assert_error=True)\n        assert error == ERROR_INVALID_CONFIGURATION\n        assert \"name/ver: Invalid configuration: compiler.version=12 is invalid!!\" in self.client.out\n"
  },
  {
    "path": "test/integration/conanfile/load_requires_file_test.py",
    "content": "from conan.test.utils.tools import TestClient\n\n\nclass TestLoadRequirementsTextFileTest:\n\n    def test_load_reqs_from_text_file(self):\n        client = TestClient()\n        conanfile = \"\"\"from conan import ConanFile\ndef reqs():\n    try:\n        content = open(\"reqs.txt\", \"r\").read()\n        lines = [line for line in content.splitlines() if line]\n        return tuple(lines)\n    except:\n        return None\n\nclass Test(ConanFile):\n    exports = \"reqs.txt\"\n    requires = reqs()\n\"\"\"\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --name=hello0 --version=0.1 --user=user --channel=channel\")\n\n        for i in (0, 1, 2):\n            reqs = \"hello%s/0.1@user/channel\" % i\n            client.save({\"conanfile.py\": conanfile,\n                         \"reqs.txt\": reqs})\n            client.run(\"create . --name=hello%s --version=0.1 --user=user --channel=channel\" % (i + 1))\n\n        client.run(\"install --requires=hello3/0.1@user/channel\")\n        client.assert_listed_require({\"hello0/0.1@user/channel\": \"Cache\",\n                                      \"hello1/0.1@user/channel\": \"Cache\",\n                                      \"hello2/0.1@user/channel\": \"Cache\",\n                                      \"hello3/0.1@user/channel\": \"Cache\"})\n"
  },
  {
    "path": "test/integration/conanfile/no_copy_source_test.py",
    "content": "import os\nimport textwrap\n\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_no_copy_source():\n    conanfile = textwrap.dedent('''\n        from conan import ConanFile\n        from conan.tools.files import copy, save, load\n        import os\n\n        class ConanFileToolsTest(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            exports_sources = \"*\"\n            no_copy_source = True\n\n            def source(self):\n                save(self, \"header.h\", \"artifact contents!\")\n\n            def build(self):\n                self.output.info(\"Source files: %s\" % load(self,\n                                          os.path.join(self.source_folder, \"file.h\")))\n                save(self, \"myartifact.lib\", \"artifact contents!\")\n\n            def package(self):\n                copy(self, \"*\", self.source_folder, self.package_folder)\n                copy(self, \"*\", self.build_folder, self.package_folder)\n        ''')\n\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile,\n                 \"file.h\": \"myfile.h contents\"})\n    client.run(\"create .\")\n    assert \"Source files: myfile.h contents\" in client.out\n    layout = client.created_layout()\n    build_folder = layout.build()\n    package_folder = layout.package()\n\n    assert \"file.h\" not in os.listdir(build_folder)\n    assert \"header.h\" not in os.listdir(build_folder)\n    assert \"file.h\" in os.listdir(package_folder)\n    assert \"header.h\" in os.listdir(package_folder)\n    assert \"myartifact.lib\" in os.listdir(package_folder)\n"
  },
  {
    "path": "test/integration/conanfile/required_conan_version_test.py",
    "content": "import textwrap\n\nfrom unittest import mock\n\nfrom conan import __version__\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_required_conan_version():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        required_conan_version = \">=100.0\"\n\n        class Lib(ConanFile):\n            pass\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"export . --name=pkg --version=1.0\", assert_error=True)\n    assert f\"Current Conan version ({__version__}) does not satisfy the defined one (>=100.0)\" in client.out\n    client.run(\"source . \", assert_error=True)\n    assert f\"Current Conan version ({__version__}) does not satisfy the defined one (>=100.0)\" in client.out\n\n    with mock.patch(\"conan.__version__\", \"101.0\"):\n        client.run(\"export . --name=pkg --version=1.0\")\n\n    with mock.patch(\"conan.__version__\", \"101.0-dev\"):\n        client.run(\"export . --name=pkg --version=1.0\")\n\n    client.run(\"install --requires=pkg/1.0@\", assert_error=True)\n    assert f\"Current Conan version ({__version__}) does not satisfy the defined one (>=100.0)\" in client.out\n\n\ndef test_required_conan_version_with_loading_issues():\n    # https://github.com/conan-io/conan/issues/11239\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n                from conan import missing_import\n\n                required_conan_version = \">=100.0\"\n\n                class Lib(ConanFile):\n                    pass\n                \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"export . --name=pkg --version=1.0\", assert_error=True)\n    assert f\"Current Conan version ({__version__}) does not satisfy the defined one (>=100.0)\" in client.out\n\n    # Assigning required_conan_version without spaces\n    conanfile = textwrap.dedent(\"\"\"\n                        from conan import missing_import\n\n                        required_conan_version=\">=100.0\"\n\n                        class Lib(ConanFile):\n                            pass\n                        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"export . --name=pkg --version=1.0\", assert_error=True)\n    assert f\"Current Conan version ({__version__}) does not satisfy the defined one (>=100.0)\" in client.out\n\n    # If the range is correct, everything works, of course\n    conanfile = textwrap.dedent(\"\"\"\n                        from conan import ConanFile\n\n                        required_conan_version = \">1.0.0\"\n\n                        class Lib(ConanFile):\n                            pass\n                        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"export . --name=pkg --version=1.0\")\n    assert \"pkg/1.0: Exported\" in client.out\n\n\ndef test_comment_after_required_conan_version():\n    \"\"\"\n    An error used to pop out if you tried to add a comment in the same line than\n    required_conan_version, as it was trying to compare against >=10.0 # This should work\n    instead of just >= 10.0\n    \"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n                from conan import ConanFile\n                from LIB_THAT_DOES_NOT_EXIST import MADE_UP_NAME\n                required_conan_version = \">=10.0\" # This should work\n                class Lib(ConanFile):\n                    pass\n                \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"export . --name=pkg --version=1.0\", assert_error=True)\n    assert f\"Current Conan version ({__version__}) does not satisfy the defined one (>=10.0)\" in client.out\n\n\ndef test_commented_out_required_conan_version():\n    \"\"\"\n    Used to not be able to comment out required_conan_version if we had to fall back\n    to regex check because of an error importing the recipe\n    \"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n                from conan import ConanFile\n                from LIB_THAT_DOES_NOT_EXIST import MADE_UP_NAME\n                required_conan_version = \">=1.0\" # required_conan_version = \">=100.0\"\n                class Lib(ConanFile):\n                    pass\n                \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"export . --name=pkg --version=10.0\", assert_error=True)\n    assert f\"Current Conan version ({__version__}) does not satisfy the defined one (>=1.0)\" not in client.out\n\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n                from conan import ConanFile\n                from LIB_THAT_DOES_NOT_EXIST import MADE_UP_NAME\n                # required_conan_version = \">=10.0\"\n                class Lib(ConanFile):\n                    pass\n                \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"export . --name=pkg --version=1.0\", assert_error=True)\n    assert f\"Current Conan version ({__version__}) does not satisfy the defined one (>=10.0)\" not in client.out\n\n\ndef test_required_conan_version_invalid_syntax():\n    \"\"\" required_conan_version used to warn of mismatching versions if spaces were present,\n     but now we have a nicer error\"\"\"\n    # https://github.com/conan-io/conan/issues/12692\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n                from conan import ConanFile\n                required_conan_version = \">= 1.0\"\n                class Lib(ConanFile):\n                    pass\"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"export . --name=pkg --version=1.0\", assert_error=True)\n    assert f\"Current Conan version ({__version__}) does not satisfy the defined one (>= 1.0)\" not in client.out\n    assert 'Error parsing version range \">=\"' in client.out\n"
  },
  {
    "path": "test/integration/conanfile/runner_test.py",
    "content": "import textwrap\n\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestRunner:\n\n    def test_ignore_error(self):\n        conanfile = \"\"\"from conan import ConanFile\nclass Pkg(ConanFile):\n    def source(self):\n        ret = self.run(\"not_a_command\", ignore_errors=True)\n        self.output.info(\"RETCODE %s\" % (ret!=0))\n\"\"\"\n        client = TestClient()\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"source .\")\n        assert \"RETCODE True\" in client.out\n\n    def test_runner_capture_output(self):\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                def source(self):\n                    self.run(\"echo 'hello Conan!'\")\n        \"\"\")\n        client = TestClient()\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"source .\")\n        assert \"hello Conan!\" in client.out\n\n    def test_custom_stream_error(self):\n        # https://github.com/conan-io/conan/issues/7888\n        conanfile = textwrap.dedent(\"\"\"\n            from io import StringIO\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                def source(self):\n                    my_buf = StringIO()\n                    self.run('echo Hello', stdout=my_buf)\n                    self.output.info(\"Buffer got msgs {}\".format(my_buf.getvalue()))\n            \"\"\")\n        client = TestClient()\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"source .\")\n        assert 'conanfile.py: Buffer got msgs Hello' in client.out\n\n    def test_custom_stream_stderr(self):\n        conanfile = textwrap.dedent(\"\"\"\n            from io import StringIO\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                def source(self):\n                    my_buf = StringIO()\n                    self.run('echo Hello 1>&2', stderr=my_buf)\n                    self.output.info(\"Buffer got stderr msgs {}\".format(my_buf.getvalue()))\n            \"\"\")\n        client = TestClient()\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"source .\")\n        assert 'conanfile.py: Buffer got stderr msgs Hello' in client.out\n"
  },
  {
    "path": "test/integration/conanfile/same_userchannel_test.py",
    "content": "import pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestUserChannelTestPackage:\n\n    def test(self):\n        # https://github.com/conan-io/conan/issues/2501\n        client = TestClient(light=True)\n        conanfile = \"\"\"from conan import ConanFile\nclass SayConan(ConanFile):\n    pass\n\"\"\"\n        test = \"\"\"from conan import ConanFile\nclass SayConan(ConanFile):\n    def requirements(self):\n        self.output.info(\"USER: %s!!\" % self.user)\n        self.output.info(\"CHANNEL: %s!!\" % self.channel)\n        self.requires(self.tested_reference_str)\n\n    def test(self):\n        pass\n\"\"\"\n\n        client.save({\"conanfile.py\": conanfile,\n                     \"test_package/conanfile.py\": test})\n        client.run(\"create . --name=pkg --version=0.1 --user=conan --channel=testing\")\n        assert \"pkg/0.1@conan/testing (test package): USER: conan!!\" in client.out\n        assert \"pkg/0.1@conan/testing (test package): CHANNEL: testing!!\" in client.out\n\n\nclass TestSameUserChannel:\n\n    @pytest.fixture(autouse=True)\n    def setup(self):\n        self.client = TestClient(light=True)\n        conanfile = \"\"\"\nfrom conan import ConanFile\n\nclass SayConan(ConanFile):\n    name = \"say\"\n    version = \"0.1\"\n    build_policy = \"missing\"\n\n    def build(self):\n        self.output.info(\"Building %s/%s\")\n\"\"\"\n        for user, channel in (\"lasote\", \"stable\"), (\"other\", \"testing\"):\n            self.client.save({\"conanfile.py\": conanfile % (user, channel)})\n            self.client.run(f\"export . --user={user} --channel={channel}\")\n\n        self.conanfile = \"\"\"\nfrom conan import ConanFile\n\nclass HelloConan(ConanFile):\n    name = \"hello\"\n    version = \"0.1\"\n    build_policy = \"missing\"\n\n    def requirements(self):\n        user_channel = \"{}/{}\".format(self.user, self.channel) if self.user else \"\"\n        self.requires(\"say/0.1@{}\".format(user_channel))\n\n    def build(self):\n        self.output.info(\"Building %s/%s\" % (self.user, self.channel) )\n\"\"\"\n\n        self.test_conanfile = str(GenConanfile().with_test(\"pass\"))\n        self.client.save({\"conanfile.py\": self.conanfile,\n                          \"test/conanfile.py\": self.test_conanfile})\n\n    def test_create(self):\n        self.client.run(\"create . --user=lasote --channel=stable\")\n        assert \"say/0.1@lasote/stable: Building lasote/stable\" in self.client.out\n        assert \"hello/0.1@lasote/stable: Building lasote/stable\" in self.client.out\n        assert \"other/testing\" not in self.client.out\n\n        self.client.save({\"conanfile.py\": self.conanfile,\n                          \"test/conanfile.py\": self.test_conanfile.replace(\"lasote/stable\",\n                                                                           \"other/testing\")})\n        self.client.run(\"create . --user=other --channel=testing\")\n        assert \"say/0.1@other/testing: Building other/testing\" in self.client.out\n        assert \"hello/0.1@other/testing: Building other/testing\" in self.client.out\n        assert \"lasote/stable\" not in self.client.out\n\n    def test_local_commands(self):\n        self.client.run(\"install .\", assert_error=True)\n        assert \"ERROR: Package 'say/0.1' not resolved: No remote defined\" in self.client.out\n\n        self.client.run(\"install . --user=lasote --channel=stable\")\n        assert \"say/0.1@lasote/stable: Building lasote/stable\" in self.client.out\n        assert \"other/testing\" not in self.client.out\n\n        self.client.run(\"install . --user=other --channel=testing\")\n        assert \"say/0.1@other/testing: Building other/testing\" in self.client.out\n        assert \"lasote/stable\" not in self.client.out\n\n        # Now use the default_ methods to declare user and channel\n        self.client = TestClient(light=True)\n        conanfile = \"\"\"\nfrom conan import ConanFile\n\nclass SayConan(ConanFile):\n    name = \"say\"\n    version = \"0.1\"\n    build_policy = \"missing\"\n    user = \"userfoo\"\n\n    def build(self):\n        self.output.info(\"Building %s/%s\" % (self.user, self.channel) )\n\n    @property\n    def channel(self):\n        return \"channelbar\"\n\"\"\"\n        self.client.save({\"conanfile.py\": conanfile})\n        self.client.run(\"install .\")\n        self.client.run(\"build .\")\n        assert \"Building userfoo/channelbar\" in self.client.out\n\n\nclass TestBuildRequireUserChannel:\n    def test(self):\n        # https://github.com/conan-io/conan/issues/2254\n        client = TestClient(light=True)\n        conanfile = \"\"\"\nfrom conan import ConanFile\n\nclass SayConan(ConanFile):\n    def build_requirements(self):\n        self.output.info(\"MYUSER: %s\" % self.user)\n        self.output.info(\"MYCHANNEL: %s\" % self.channel)\n\"\"\"\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"install . --user=myuser --channel=mychannel\")\n        assert \"MYUSER: myuser\" in client.out\n        assert \"MYCHANNEL: mychannel\" in client.out\n"
  },
  {
    "path": "test/integration/conanfile/set_name_version_test.py",
    "content": "import os\nimport textwrap\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient, NO_SETTINGS_PACKAGE_ID\nfrom conan.internal.util.files import mkdir\n\n\nclass TestSetVersionName:\n\n    @pytest.mark.parametrize(\"user_channel\", [\"\", \"@user/channel\"])\n    def test_set_version_name(self, user_channel):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Lib(ConanFile):\n                def set_name(self):\n                    self.name = \"pkg\"\n                def set_version(self):\n                    self.version = \"2.1\"\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        user_channel_arg = \"--user=user --channel=channel\" if user_channel else \"\"\n        client.run(\"export . %s\" % user_channel_arg)\n        assert \"pkg/2.1%s: Exported\" % user_channel in client.out\n        # installing it doesn't break\n        client.run(\"install --requires=pkg/2.1%s --build=missing\" % (user_channel or \"@\"))\n        client.assert_listed_require({f\"pkg/2.1{user_channel}\": \"Cache\"})\n        client.assert_listed_binary({f\"pkg/2.1{user_channel}\": (NO_SETTINGS_PACKAGE_ID, \"Build\")})\n\n        client.run(\"install --requires=pkg/2.1%s --build=missing\" % (user_channel or \"@\"))\n        client.assert_listed_require({f\"pkg/2.1{user_channel}\": \"Cache\"})\n        client.assert_listed_binary({f\"pkg/2.1{user_channel}\": (NO_SETTINGS_PACKAGE_ID, \"Cache\")})\n\n        # Local flow should also work\n        client.run(\"install .\")\n        assert \"conanfile.py (pkg/2.1):\" in client.out\n\n    def test_set_version_name_file(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import load\n            class Lib(ConanFile):\n                def set_name(self):\n                    self.name = load(self, \"name.txt\")\n                def set_version(self):\n                    self.version = load(self, \"version.txt\")\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile,\n                     \"name.txt\": \"pkg\",\n                     \"version.txt\": \"2.1\"})\n        client.run(\"export . --user=user --channel=testing\")\n        assert \"pkg/2.1@user/testing: Exported\" in client.out\n        client.run(\"install --requires=pkg/2.1@user/testing --build=missing\")\n        client.assert_listed_binary({f\"pkg/2.1@user/testing\": (NO_SETTINGS_PACKAGE_ID, \"Build\")})\n        client.run(\"install --requires=pkg/2.1@user/testing\")\n        client.assert_listed_binary({f\"pkg/2.1@user/testing\": (NO_SETTINGS_PACKAGE_ID, \"Cache\")})\n        # Local flow should also work\n        client.run(\"install .\")\n        assert \"conanfile.py (pkg/2.1):\" in client.out\n\n    def test_set_version_name_errors(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Lib(ConanFile):\n                def set_name(self):\n                    self.name = \"pkg\"\n                def set_version(self):\n                    self.version = \"2.1\"\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"export . --name=other --version=1.1 --user=user --channel=testing\")\n        assert \"pkg/2.1@user/testing\" in client.out\n        client.run(\"export .  --version=1.1 --user=user --channel=testing\")\n        assert \"pkg/2.1@user/testing\" in client.out\n        # These are checked but match and don't conflict\n        client.run(\"export . --version=2.1 --user=user --channel=testing\")\n        client.run(\"export . --name=pkg --version=2.1 --user=user --channel=testing\")\n\n        # Local flow should also fail\n        client.run(\"install . --name=other --version=1.2\")\n        assert \"\" in client.out\n\n    def test_set_version_name_appending(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n               from conan import ConanFile\n               class Lib(ConanFile):\n                   def set_name(self):\n                       self.name = self.name + \".extra\"\n                   def set_version(self):\n                       self.version = self.version + \".extra\"\n               \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"export . --name=pkg --version=1.0\")\n        assert \"pkg.extra/1.0.extra: Exported\" in client.out\n\n    def test_set_version_name_only_not_cli(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Lib(ConanFile):\n                def set_name(self):\n                    self.name = self.name or \"pkg\"\n                def set_version(self):\n                    self.version = self.version or \"2.0\"\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"export . --name=other --version=1.1 --user=user --channel=testing\")\n        assert \"other/1.1@user/testing: Exported\" in client.out\n        client.run(\"export .  --version=1.1 --user=user --channel=testing\")\n        assert \"pkg/1.1@user/testing: Exported\" in client.out\n        client.run(\"export . --user=user --channel=testing\")\n        assert \"pkg/2.0@user/testing: Exported\" in client.out\n\n        # Local flow should also work\n        client.run(\"install . --name=other --version=1.2\")\n        assert \"conanfile.py (other/1.2)\" in client.out\n        client.run(\"install .\")\n        assert \"conanfile.py (pkg/2.0)\" in client.out\n\n    def test_set_version_name_crash(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Lib(ConanFile):\n                def set_name(self):\n                    self.name = error\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"export .\", assert_error=True)\n        assert \"ERROR: conanfile.py: Error in set_name() method, line 5\" in client.out\n        assert \"name 'error' is not defined\" in client.out\n        conanfile = textwrap.dedent(\"\"\"\n           from conan import ConanFile\n           class Lib(ConanFile):\n               def set_version(self):\n                   self.version = error\n           \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"export .\", assert_error=True)\n        assert \"ERROR: conanfile.py: Error in set_version() method, line 5\" in client.out\n        assert \"name 'error' is not defined\" in client.out\n\n    def test_set_version_cwd(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.files import load\n            class Lib(ConanFile):\n                name = \"pkg\"\n                def set_version(self):\n                    self.version = load(self, \"version.txt\")\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        mkdir(os.path.join(client.current_folder, \"build\"))\n        with client.chdir(\"build\"):\n            client.save({\"version.txt\": \"2.1\"}, clean_first=True)\n            client.run(\"export .. \")\n            assert \"pkg/2.1: Exported\" in client.out\n\n\ndef test_set_version_forbidden_chars():\n    c = TestClient()\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"$$$\")})\n    c.run(\"export .\", assert_error=True)\n    assert \"ERROR: Invalid package version '$$$'\" in c.out\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Lib(ConanFile):\n            name = \"pkg\"\n            def set_version(self):\n                self.version = \"$$$\"\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"export .\", assert_error=True)\n    assert \"ERROR: Invalid package version '$$$'\" in c.out\n\n\ndef test_set_version_carriage_return():\n    c = TestClient()\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", r\"1.0\\n\")})\n    c.run(\"export .\", assert_error=True)\n    assert \"ERROR: Invalid package version '1.0\" in c.out\n\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import load\n        class Lib(ConanFile):\n            name = \"pkg\"\n            def set_version(self):\n                self.version = load(self, \"version.txt\")\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile,\n            \"version.txt\": \"1.0\\n\"})\n    c.run(\"export .\", assert_error=True)\n    assert \"ERROR: Invalid package version '1.0\" in c.out\n\n\ndef test_set_version_channel():\n    \"\"\"\n    Dynamically setting the user and channel is possible with the ``set_version()``\n    not recommended, but possible.\n    \"\"\"\n    c = TestClient()\n\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import load\n        class Lib(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            def set_version(self):\n                self.user = \"myuser\"\n                self.channel = \"mychannel\"\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"export .\")\n    assert \"pkg/0.1@myuser/mychannel: Exported\" in c.out\n"
  },
  {
    "path": "test/integration/conanfile/test_attributes_scope.py",
    "content": "import textwrap\n\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestAttributesScope:\n\n    def test_cppinfo_not_in_package_id(self):\n        # self.cpp_info is not available in 'package_id'\n        t = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class Recipe(ConanFile):\n\n                def package_id(self):\n                    self.cpp_info.libs = [\"A\"]\n        \"\"\")\n        t.save({'conanfile.py': conanfile})\n        t.run('create . --name=name --version=version', assert_error=True)\n        assert \"'self.cpp_info' access in 'package_id()' method is forbidden\" in t.out\n\n    def test_settings_not_in_package_id(self):\n        # self.cpp_info is not available in 'package_id'\n        t = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n               from conan import ConanFile\n\n               class Recipe(ConanFile):\n\n                   def package_id(self):\n                       self.settings\n           \"\"\")\n        t.save({'conanfile.py': conanfile})\n        t.run('create . --name=name --version=version', assert_error=True)\n        assert \"'self.settings' access in 'package_id()' method is forbidden\" in t.out\n\n    def test_options_not_in_package_id(self):\n        # self.cpp_info is not available in 'package_id'\n        t = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n               from conan import ConanFile\n\n               class Recipe(ConanFile):\n\n                   def package_id(self):\n                       self.options\n           \"\"\")\n        t.save({'conanfile.py': conanfile})\n        t.run('create . --name=name --version=version', assert_error=True)\n        assert \"'self.options' access in 'package_id()' method is forbidden\" in t.out\n\n    def test_info_not_in_package_info(self):\n        t = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n               from conan import ConanFile\n\n               class Recipe(ConanFile):\n\n                   def package_info(self):\n                       self.info\n           \"\"\")\n        t.save({'conanfile.py': conanfile})\n        t.run('create . --name=name --version=version', assert_error=True)\n        assert \"'self.info' access in 'package_info()' method is forbidden\" in t.out\n\n    def test_info_not_in_package(self):\n        # self.info is not available in 'package'\n        t = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class Recipe(ConanFile):\n\n                def package(self):\n                    self.info.clear()\n        \"\"\")\n        t.save({'conanfile.py': conanfile})\n        t.run('create . --name=name --version=version -s os=Linux', assert_error=True)\n        assert \"'self.info' access in 'package()' method is forbidden\" in t.out\n\n    def test_no_settings(self):\n        # self.setting is not available in 'source'\n        t = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class Recipe(ConanFile):\n                settings = \"os\",\n\n                def source(self):\n                    self.settings.os\n        \"\"\")\n        t.save({'conanfile.py': conanfile})\n        t.run('create . --name=name --version=version -s os=Linux', assert_error=True)\n        assert \"'self.settings' access in 'source()' method is forbidden\" in t.out\n\n    def test_no_options(self):\n        # self.setting is not available in 'source'\n        t = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class Recipe(ConanFile):\n                options = {'shared': [True, False]}\n\n                def source(self):\n                    self.options.shared\n        \"\"\")\n        t.save({'conanfile.py': conanfile})\n        t.run('create . --name=name --version=version -o shared=False', assert_error=True)\n        assert \"'self.options' access in 'source()' method is forbidden\" in t.out\n"
  },
  {
    "path": "test/integration/conanfile/test_conanfile_txt_encodings.py",
    "content": "import os\nimport shutil\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestEncodings:\n\n    @pytest.mark.parametrize(\"filename\", [\"conanfile_utf8.txt\",\n                                          \"conanfile_utf8_with_bom.txt\",\n                                          \"conanfile_utf16le_with_bom.txt\",\n                                          \"conanfile_utf16be_with_bom.txt\"])\n    def test_encoding(self, filename):\n        c = TestClient()\n        path = os.path.join(os.path.dirname(__file__), \"files\", filename)\n        shutil.copy(path, os.path.join(c.current_folder, \"conanfile.txt\"))\n        c.run(\"install .\")\n        assert \"Installing packages\" in c.out\n\n    def test_error(self):\n        c = TestClient()\n        conanfile = b\"\\x81\\x8D\\x8F\\x90\\x9D\"\n        open(os.path.join(c.current_folder, \"conanfile.txt\"), \"wb\").write(conanfile)\n        c.run(\"install .\", assert_error=True)\n        assert \"ERROR: Cannot load conanfile.txt\" in c.out\n        assert \"It is recommended to use utf-8 encoding\" in c.out\n\n\nclass TestProfileEncodings:\n\n    def test_encoding(self):\n        c = TestClient()\n        c.save({\"conanfile.txt\": \"\"})\n        # BOM for utf-7\n        open(os.path.join(c.current_folder, \"profile\"), \"wb\").write(b'\\x2b\\x2f\\x76\\x38')\n        c.run(\"install . -pr=profile\")\n        assert \"Installing packages\" in c.out\n\n    def test_error(self):\n        c = TestClient()\n        c.save({\"conanfile.txt\": \"\"})\n        open(os.path.join(c.current_folder, \"profile\"), \"wb\").write(b\"\\x81\\x8D\\x8F\\x90\\x9D\")\n        c.run(\"install . -pr=profile\", assert_error=True)\n        assert \"ERROR: Cannot load profile\" in c.out\n        assert \"It is recommended to use utf-8 encoding\" in c.out\n"
  },
  {
    "path": "test/integration/conanfile/test_conanfile_txt_test_requires.py",
    "content": "from conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_test_requires():\n    c = TestClient()\n    c.save({\"test/conanfile.py\": GenConanfile(\"test\", \"0.1\"),\n            \"consumer/conanfile.txt\": \"[test_requires]\\ntest/0.1\"})\n    c.run(\"create test\")\n    c.run(\"install consumer\")\n    c.assert_listed_require({\"test/0.1\": \"Cache\"}, test=True)\n    c.assert_listed_binary({\"test/0.1\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\", \"Cache\")},\n                           test=True)\n\n\ndef test_test_requires_options():\n    c = TestClient()\n    c.save({\"test/conanfile.py\": GenConanfile(\"test\", \"0.1\").with_option(\"myoption\", [1, 2, 3]),\n            \"consumer/conanfile.txt\": \"[test_requires]\\ntest/0.1\\n[options]\\n*:myoption=2\"})\n    c.run(\"create test -o myoption=2\")\n    c.assert_listed_binary({\"test/0.1\": (\"a3cb1345b8297bfdffea4ef4bb1b2694c54d1d69\", \"Build\")})\n\n    c.run(\"install consumer\")\n    c.assert_listed_require({\"test/0.1\": \"Cache\"}, test=True)\n    c.assert_listed_binary({\"test/0.1\": (\"a3cb1345b8297bfdffea4ef4bb1b2694c54d1d69\", \"Cache\")},\n                           test=True)\n"
  },
  {
    "path": "test/integration/conanfile/test_cpp_info_serialize.py",
    "content": "import json\nimport textwrap\n\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_cpp_info_serialize_round_trip():\n    \"\"\" test that serialize and deserialize CppInfo works\n    \"\"\"\n    # TODO: Define standard name for file\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\\\n        import os\n        from conan import ConanFile\n        from conan.tools import CppInfo\n\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n\n            def package(self):\n                cpp_info = CppInfo(self)\n                cpp_info.includedirs = [\"myinc\"]\n                cpp_info.libs = [\"mylib\", \"myother\"]\n                cpp_info.libdirs = [\"mylibs\"]\n                cpp_info.type = \"static-library\"\n                cpp_info.set_property(\"myprop\", \"myvalue\")\n                cpp_info.components[\"comp\"].libs = []\n                cpp_info.components[\"comp\"].type = None\n                p = os.path.join(self.package_folder, \"cpp_info.json\")\n                cpp_info.save(p)\n\n            def package_info(self):\n                cpp_info = CppInfo(self).load(\"cpp_info.json\")\n                self.cpp_info = cpp_info\n        \"\"\")\n\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"create . --format=json\")\n    graph = json.loads(c.stdout)\n    cpp_info = graph[\"graph\"][\"nodes\"][\"1\"][\"cpp_info\"][\"root\"]\n    assert cpp_info[\"includedirs\"][0].endswith(\"myinc\")\n    assert cpp_info[\"libdirs\"][0].endswith(\"mylibs\")\n    assert cpp_info[\"libs\"] == [\"mylib\", \"myother\"]\n    assert cpp_info[\"type\"] == \"static-library\"\n    assert cpp_info[\"properties\"] == {\"myprop\": \"myvalue\"}\n\n    comp = graph[\"graph\"][\"nodes\"][\"1\"][\"cpp_info\"][\"comp\"]\n    assert comp[\"type\"] is None\n"
  },
  {
    "path": "test/integration/conanfile/test_deploy_method.py",
    "content": "import textwrap\n\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_deploy_method():\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import copy, save\n        class Pkg(ConanFile):\n            name = \"{name}\"\n            version = \"0.1\"\n            {requires}\n            def package(self):\n                save(self, os.path.join(self.package_folder, f\"my{name}file.txt\"), \"HELLO!!!!\")\n            def deploy(self):\n                copy(self, \"*\", src=self.package_folder, dst=self.deploy_folder)\n            \"\"\")\n    c.save({\"dep/conanfile.py\": conanfile.format(name=\"dep\", requires=\"\"),\n            \"pkg/conanfile.py\": conanfile.format(name=\"pkg\", requires=\"requires='dep/0.1'\")})\n    c.run(\"create dep\")\n    assert \"Executing deploy()\" not in c.out\n    c.run(\"create pkg\")\n    assert \"Executing deploy()\" not in c.out\n\n    # Doesn't install by default\n    c.run(\"install --requires=pkg/0.1\")\n    assert \"Executing deploy()\" not in c.out\n\n    # Doesn't install with other patterns\n    c.run(\"install --requires=pkg/0.1 --deployer-package=other\")\n    assert \"Executing deploy()\" not in c.out\n\n    # install can deploy all\n    c.run(\"install --requires=pkg/0.1 --deployer-package=* --deployer-folder=mydeploy\")\n    assert \"dep/0.1: Executing deploy()\" in c.out\n    assert \"pkg/0.1: Executing deploy()\" in c.out\n    assert c.load(\"mydeploy/mydepfile.txt\") == \"HELLO!!!!\"\n    assert c.load(\"mydeploy/mypkgfile.txt\") == \"HELLO!!!!\"\n\n    # install can deploy only \"pkg\"\n    c.run(\"install --requires=pkg/0.1 --deployer-package=pkg/* --deployer-folder=mydeploy\")\n    assert \"dep/0.1: Executing deploy()\" not in c.out\n    assert \"pkg/0.1: Executing deploy()\" in c.out\n\n\ndef test_deploy_local():\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import copy\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            def deploy(self):\n                copy(self, \"*\", src=self.package_folder, dst=self.deploy_folder)\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"install . --deployer-package=*\", assert_error=True)\n    assert \"ERROR: conanfile.py (pkg/0.1): Error in deploy() method, line 8\" in c.out\n    assert \"copy() received 'src=None' argument\" in c.out\n\n    # Without name/version same error\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            def deploy(self):\n                assert self.package_folder  # will fail if None\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"install . --deployer-package=*\", assert_error=True)\n    assert \"ERROR: conanfile.py: Error in deploy() method, line 5\" in c.out\n\n    # I can exclude the current consumer, it won't fail\n    c.run(\"install . --deployer-package=!& --deployer-package=*\")\n    assert \"Install finished successfully\" in c.out\n\n\ndef test_deploy_method_tool_requires():\n    # Test to validate https://github.com/conan-io/docs/issues/3649\n    c = TestClient()\n    tool = textwrap.dedent(r\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import save, chdir\n        class Pkg(ConanFile):\n            name = \"tool\"\n            version = \"0.1\"\n            type = \"application\"\n\n            def package(self):\n               with chdir(self, self.package_folder):\n                   echo = \"@echo off\\necho MYTOOL RUNNING!!\"\n                   save(self, \"mytool.bat\", echo)\n                   save(self, \"mytool.sh\", echo)\n                   os.chmod(\"mytool.sh\", 0o777)\n\n            def package_info(self):\n               self.buildenv_info.prepend_path(\"PATH\", self.package_folder)\n        \"\"\")\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.env import VirtualBuildEnv\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            tool_requires = \"tool/0.1\"\n            settings = \"os\"\n\n            def deploy(self):\n                self.output.info(f\"DEPLOY {os.getcwd()}\")\n                venv = VirtualBuildEnv(self)\n                with venv.vars().apply():\n                    ext = \"bat\" if self.settings.os == \"Windows\" else \"sh\"\n                    self.run(f\"mytool.{ext}\")\n        \"\"\")\n    c.save({\"tool/conanfile.py\": tool,\n            \"pkg/conanfile.py\": conanfile})\n\n    c.run(\"create tool\")\n    c.run(\"create pkg\")\n\n    # install can deploy all\n    c.run(\"install --requires=pkg/0.1 -c:b tools.graph:skip_binaries=False --deployer-package=*\")\n    assert \"MYTOOL RUNNING!!\" in c.out\n"
  },
  {
    "path": "test/integration/conanfile/test_deprecated.py",
    "content": "import textwrap\n\nfrom conan.test.utils.tools import TestClient, GenConanfile\n\n\nclass TestDeprecated:\n    def test_no_deprecated(self):\n        t = TestClient()\n        t.save({'taskflow.py': GenConanfile(\"cpp-taskflow\", \"1.0\").with_deprecated(\"''\")})\n        t.run(\"create taskflow.py\")\n\n        assert \"Deprecated\" not in t.out\n\n    def test_deprecated_simple(self):\n        t = TestClient()\n        t.save({'taskflow.py': GenConanfile(\"cpp-taskflow\", \"1.0\").with_deprecated(\"True\")})\n        t.run(\"create taskflow.py\")\n\n        assert \"Deprecated\\n    cpp-taskflow/1.0\" in t.out\n        assert \"WARN: risk: There are deprecated packages in the graph\" in t.out\n\n        t.run(\"create taskflow.py --user=conan --channel=stable\")\n        assert \"Deprecated\\n    cpp-taskflow/1.0\" in t.out\n\n    def test_deprecated_with(self):\n        t = TestClient()\n        t.save({'taskflow.py': GenConanfile(\"cpp-taskflow\", \"1.0\").with_deprecated('\"taskflow\"')})\n        t.run(\"create taskflow.py\")\n\n        assert \"Deprecated\\n    cpp-taskflow/1.0: taskflow\" in t.out\n\n        t.run(\"create taskflow.py --user=conan --channel=stable\")\n        assert \"Deprecated\\n    cpp-taskflow/1.0@conan/stable: taskflow\" in t.out\n\n    def test_deprecated_custom_text(self):\n        tc = TestClient()\n        tc.save({\"old/conanfile.py\": GenConanfile(\"maths\", 1.0).with_deprecated('\"This is not secure, use maths/[>=2.0]\"'),\n                 \"new/conanfile.py\": GenConanfile(\"maths\", 2.0)})\n\n        tc.run(\"create new/conanfile.py\")\n        tc.run(\"create old/conanfile.py\")\n        assert \"maths/1.0: This is not secure, use maths/[>=2.0]\" in tc.out\n        tc.run(\"install --requires=maths/1.0\")\n        assert \"maths/1.0: This is not secure, use maths/[>=2.0]\" in tc.out\n\n    def test_deprecated_configure(self):\n        tc = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.scm import Version\n\n        class Pkg(ConanFile):\n            name = \"pkg\"\n\n            def configure(self):\n                if Version(self.version) < \"1.0\":\n                    self.deprecated = True\n        \"\"\")\n        tc.save({\"conanfile.py\": conanfile})\n\n        tc.run(\"graph info . --version=0.0\")\n        assert \"deprecated: True\" in tc.out\n\n        tc.run(\"graph info . --version=2.0\")\n        assert \"deprecated: None\" in tc.out\n"
  },
  {
    "path": "test/integration/conanfile/test_exception_printing.py",
    "content": "import pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\nconanfile = \"\"\"\nfrom conan import ConanFile\n\nclass ExceptionsTest(ConanFile):\n    name = \"exceptions\"\n    version = \"0.1\"\n\n    def {method}(self):\n        {method_contents}\n\n    def _aux_method(self):\n        raise Exception('Oh! an error!')\n\"\"\"\n\n\n@pytest.mark.parametrize(\"direct\", [True, False])\n@pytest.mark.parametrize(\"method\",\n                         [\"source\", \"build\", \"package\", \"package_info\", \"configure\", \"build_id\",\n                          \"package_id\", \"requirements\", \"config_options\", \"layout\", \"generate\",\n                          \"export\", \"export_sources\", \"build_requirements\", \"init\"])\ndef test_all_methods(direct, method):\n    client = TestClient()\n    if direct:\n        throw = \"raise Exception('Oh! an error!')\"\n    else:\n        throw = \"self._aux_method()\"\n\n    client.save({\"conanfile.py\": conanfile.format(method=method, method_contents=throw)})\n    client.run(\"create . \", assert_error=True)\n    assert \"Error in %s() method, line 9\" % method in client.out\n    assert \"Oh! an error!\" in client.out\n    if not direct:\n        assert \"while calling '_aux_method', line 12\" in client.out\n\n\ndef test_complete_traceback_debug():\n    \"\"\"\n    in debug level (-vv), the trace is shown (this is for recipe methods exceptions)\n    \"\"\"\n    client = TestClient()\n    throw = \"self._aux_method()\"\n    client.save({\"conanfile.py\": conanfile.format(method=\"source\", method_contents=throw)})\n    client.run(\"create . -vv\", assert_error=True)\n    assert \"Exception: Oh! an error!\" in client.out\n    assert \"ERROR: Traceback (most recent call last):\" in client.out\n\n\ndef test_complete_traceback_trace():\n    \"\"\"\n    in debug level (-vvv), the full trace is shown for ConanExceptions\n    \"\"\"\n    client = TestClient()\n    client.run(\"install --requires=pkg/1.0 -vvv\", assert_error=True)\n    assert \"Traceback (most recent call last)\" in client.out\n\n\ndef test_notracebacks_cmakedeps():\n    \"\"\"\n    CMakeDeps prints traceback\n    \"\"\"\n    c = TestClient()\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_generator(\"CMakeDeps\")})\n    c.run(\"install .\", assert_error=True)\n    assert \"Traceback\" not in c.out\n    assert \"ERROR: Error in generator 'CMakeDeps'\" in c.out\n"
  },
  {
    "path": "test/integration/conanfile/test_finalize_method.py",
    "content": "import json\nimport os\nfrom pathlib import Path\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\n\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import load, save\n\nconanfile_dep = textwrap.dedent(\"\"\"\n    import os\n    from conan import ConanFile\n    from conan.tools.files import save, copy\n\n    class TestConan(ConanFile):\n        name = \"dep\"\n        version = \"1.0\"\n        def package(self):\n            save(self, os.path.join(self.package_folder, \"file.txt\"), \"Hello World!\")\n            save(self, os.path.join(self.package_folder, \"file2.txt\"), \"Hello World 2!\")\n\n        def finalize(self):\n            self.output.info(f\"Running finalize method in {self.package_folder}\")\n            copy(self, \"file.txt\", src=self.immutable_package_folder, dst=self.package_folder)\n            save(self, os.path.join(self.package_folder, \"finalized.txt\"), \"finalized file\")\n\n        def package_info(self):\n            self.output.info(f\"Running package_info method in {self.package_folder}\")\n    \"\"\")\n\n\nclass TestBasicLocalFlows:\n\n    @pytest.fixture\n    def client(self):\n        tc = TestClient(light=True)\n        tc.save({\"dep/conanfile.py\": conanfile_dep})\n        tc.run(\"export dep\")\n        return tc\n\n    def test_basic_finalize_method(self, client):\n        client.run(\"create dep\")\n        layout = client.created_layout()\n        assert layout.package().endswith(\"p\")\n        assert f\"Package folder {layout.package()}\" in client.out\n        assert f\"Running finalize method in {layout.finalize()}\" in client.out\n        assert f\"Running package_info method in {layout.finalize()}\" in client.out\n        client.run(\"install --requires=dep/1.0\")\n        assert f\"Running package_info method in {layout.finalize()}\" in client.out\n        # Only issue is that the PackageLayout has no idea about the redirected package folder\n        # So we have to know to check for it in tests, but oh well\n        assert \"finalized.txt\" in os.listdir(layout.finalize())\n        assert \"finalized.txt\" not in os.listdir(layout.package())\n\n    def test_dependency_finalize_method(self, client):\n        client.save({\"app/conanfile.py\": textwrap.dedent(\"\"\"\n                 from conan import ConanFile\n                 class TestConan(ConanFile):\n                     name = \"app\"\n                     version = \"1.0\"\n                     requires = \"dep/1.0\"\n                     def generate(self):\n                         self.output.info(\"Running generate method\")\n                         dep_pkg_folder = self.dependencies[\"dep\"].package_folder\n                         self.output.info(f\"Dep package folder: {dep_pkg_folder}\")\n                 \"\"\")})\n        client.run(\"create dep\")\n        dep_layout = client.created_layout()\n        client.run(\"create app\")\n        assert f\"Dep package folder: {dep_layout.package()}\" not in client.out\n        assert f\"Dep package folder: {dep_layout.finalize()}\" in client.out\n\n    def test_no_non_info_access(self):\n        client = TestClient(light=True)\n        client.save({\"conanfile.py\": GenConanfile(\"dep\", \"1.0\")\n                     .with_finalize(\"self.output.info('settings.os: ' + self.settings.os)\")})\n        client.run(\"create .\", assert_error=True)\n        assert \"'self.settings' access in 'finalize()' method is forbidden\" in client.out\n\n    def test_finalize_moves_from_package(self):\n        client = TestClient(light=True)\n        client.save({\"conanfile.py\": GenConanfile(\"dep\", \"1.0\")\n                     .with_import(\"from conan.tools.files import save, rename\",\n                                  \"import os\")\n                     .with_option(\"move\", [True, False])\n                     .with_package('save(self, os.path.join(self.package_folder, \"file.txt\"), \"Hello World!\")',\n                                   \"save(self, os.path.join(self.package_folder, 'file2.txt'), 'Hello World 2!')\")\n                     # This is NOT allowed, moving from package to finalize is forbidden, only as test to ensure consistency\n                     .with_finalize(\"rename(self, os.path.join(self.immutable_package_folder, 'file.txt'), os.path.join(self.package_folder, 'file.txt')) if self.info.options.move else None\")})\n        client.run(\"create . -o=dep/*:move=True\")\n        dep_moved_layout = client.created_layout()\n        assert \"file.txt\" in os.listdir(dep_moved_layout.finalize())\n        assert \"file.txt\" not in os.listdir(dep_moved_layout.package())\n\n        client.run(\"create . -o=dep/*:move=False\")\n        dep_kept_layout = client.created_layout()\n        assert \"file.txt\" not in os.listdir(dep_kept_layout.finalize())\n        assert \"file.txt\" in os.listdir(dep_kept_layout.package())\n\n        # Now we can check that the package_id is the same for both\n        assert dep_moved_layout.reference.package_id != dep_kept_layout.reference.package_id\n\n        # This now breaks if we try to cache check-integrity the moved package\n        client.run(f\"cache check-integrity {dep_moved_layout.reference}\", assert_error=True)\n        assert \"There are corrupted artifacts\" in client.out\n\n        client.run(f\"cache check-integrity {dep_kept_layout.reference}\")\n        assert \"There are corrupted artifacts\" not in client.out\n\n    def test_cache_path_command(self, client):\n        client.run(\"create dep\")\n        dep_layout = client.created_layout()\n        pref = client.created_package_reference(\"dep/1.0\")\n        client.run(f\"cache path {pref}\")\n        assert dep_layout.package() not in client.out\n        assert dep_layout.finalize() in client.out\n\n    def test_remove_deletes_correct_folders(self, client):\n        client.run(\"create dep\")\n        dep_layout = client.created_layout()\n        client.run(\"remove * -c\")\n        assert not os.path.exists(dep_layout.package())\n        assert not os.path.exists(dep_layout.finalize())\n\n    def test_save_restore_cache(self, client):\n        # Not created in the cache, just exported, nothing breaks because there is not even a package there\n        client.run(\"cache save *:*\")\n        # Check pkglist.json has not been created inside conan cache folder\n        assert not any(Path(client.cache_folder).rglob(\"pgklist.json\"))\n        client.run(\"remove * -c\")\n        client.run(\"cache restore conan_cache_save.tgz\")\n        # Check the extracted pkglist does not persist in the cache after restore\n        assert not any(Path(client.cache_folder).rglob(\"pgklist.json\"))\n\n        # Now create the package and then save/restore\n        client.run(\"create dep\")\n        dep_layout = client.created_layout()\n        client.run(\"cache save *:* -f=json\", redirect_stdout=\"saved.json\")\n        saved = json.loads(client.load(\"saved.json\"))\n        pref = dep_layout.reference\n        saved_pkg_folder = saved[\"Local Cache\"][\"dep/1.0\"][\"revisions\"][pref.ref.revision][\"packages\"][pref.package_id][\"revisions\"][pref.revision][\"package_folder\"]\n        assert saved_pkg_folder in dep_layout.package().replace(\"\\\\\", \"/\")\n        client.run(\"remove * -c\")\n        assert not os.path.exists(dep_layout.package())\n        assert not os.path.exists(dep_layout.finalize())\n        client.run(\"cache restore conan_cache_save.tgz\")\n        client.run(f\"cache path {dep_layout.reference}\")\n        package_folder = client.out.strip()\n\n        # The finalize() folder does not exist as restoring is not considered usage, so it never runs\n        # so this is just the immutable package_folder\n        assert \"finalized.txt\" not in os.listdir(package_folder)\n\n        # But as soon as you call conan finalize, finalize() is called and so it's used,\n        # so package_folder will be the finalize folder\n        client.run(\"install --requires=dep/1.0\")\n        client.run(f\"cache path {dep_layout.reference}\")\n        package_folder = client.out.strip()\n        assert \"finalized.txt\" in os.listdir(package_folder)\n\n    def test_graph_info_output(self, client):\n        client.run(\"create dep\")\n        dep_layout = client.created_layout()\n        client.run(\"install --requires=dep/1.0 -f=json\", redirect_stdout=\"finalize.json\")\n        finalize_output = json.loads(client.load(\"finalize.json\"))\n        assert finalize_output[\"graph\"][\"nodes\"][\"1\"][\"package_folder\"] == dep_layout.finalize()\n        assert finalize_output[\"graph\"][\"nodes\"][\"1\"][\"immutable_package_folder\"] == dep_layout.package()\n\n    def test_create_pkglist_output(self, client):\n        client.run(\"create dep -f=json\", redirect_stdout=\"created.json\")\n        created_pkgid = client.created_package_id(\"dep/1.0\")\n        client.run(\"list --graph=created.json --graph-binaries=build\")\n        assert created_pkgid in client.out\n\n    def test_vendorized_basic(self, client):\n        client.run(\"create dep\")\n        client.save({\"vendor/conanfile.py\": GenConanfile(\"vendor\", \"1.0\")\n                     .with_import(\"from conan.tools.files import copy\")\n                     .with_class_attribute(\"vendor=True\")\n                     .with_requires(\"dep/1.0\")\n                     .with_package(\"copy(self, 'file.txt', src=self.dependencies['dep'].package_folder, dst=self.package_folder)\",\n                                   \"copy(self, 'finalized.txt', src=self.dependencies['dep'].package_folder, dst=self.package_folder)\",\n                                   \"copy(self, 'file2.txt', src=self.dependencies['dep'].immutable_package_folder, dst=self.package_folder)\")})\n        client.run(\"create vendor\")\n        vendor_layout = client.created_layout()\n        assert \"file.txt\" in os.listdir(vendor_layout.package())\n        assert \"finalized.txt\" in os.listdir(vendor_layout.package())\n        assert \"file2.txt\" in os.listdir(vendor_layout.package())\n\n    def test_check_integrity(self, client):\n        client.run(\"create dep\")\n        dep_layout = client.created_layout()\n        client.run(f\"cache check-integrity {dep_layout.reference}\")\n        assert \"There are corrupted artifacts\" not in client.out\n        # Even if we re-change the finalize folder contents, it should still be fine\n        save(os.path.join(dep_layout.finalize(), \"finalized.txt\"), \"Modified!\")\n        client.run(f\"cache check-integrity {dep_layout.reference}\")\n        assert \"There are corrupted artifacts\" not in client.out\n        # But as soon as we change the package, it should still fail like a normal package would\n        save(os.path.join(dep_layout.package(), \"file.txt\"), \"Modified!\")\n        client.run(f\"cache check-integrity {dep_layout.reference}\", assert_error=True)\n        assert \"There are corrupted artifacts\" in client.out\n\n    @pytest.mark.parametrize(\"with_finalize_method\", [True, False])\n    def test_access_immutable_from_consumer(self, client, with_finalize_method):\n        if not with_finalize_method:\n            client.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"1.0\")})\n        client.save({\"app/conanfile.py\": GenConanfile(\"app\", \"1.0\")\n                     .with_requires(\"dep/1.0\")\n                     .with_package(\"dep = self.dependencies['dep/1.0']\",\n                                   \"self.output.info(f'Immutable package: {dep.immutable_package_folder}')\",\n                                   # TODO: Think about if we want this interface\n                                   # \"self.output.info(f'finalize: {dep.finalize_folder}')\",\n                                   \"self.output.info(f'Package: {dep.package_folder}')\")})\n        client.run(\"create dep\")\n        dep_layout = client.created_layout()\n        client.run(\"create app\")\n        assert f\"app/1.0: Immutable package: {dep_layout.package()}\" in client.out\n        # assert f\"app/1.0: finalize: {dep_layout.finalize()}\" in client.out\n        if with_finalize_method:\n            assert f\"app/1.0: Package: {dep_layout.finalize()}\" in client.out\n        else:\n            assert f\"app/1.0: Package: {dep_layout.package()}\" in client.out\n\n    def test_cache_modification_of_custom_conf_based_on_settings(self):\n        tc = TestClient(light=True)\n        tc.save({\"conanfile.py\": GenConanfile(\"dep\", \"1.0\")\n                .with_import(\"from conan.tools.files import save\",\n                             \"import os\")\n                .with_option(\"myoption\", [True, False])\n                .with_option(\"otheroption\", [True, False])\n                .with_default_option(\"myoption\", False)\n                .with_default_option(\"otheroption\", False)\n                .with_setting(\"os\")\n                .with_package_id(\"del self.info.options.myoption\")\n                .with_finalize(\"save(self, os.path.join(self.package_folder, 'file.txt'), 'Hello World!')\",\n                              \"save(self, os.path.join(self.package_folder, 'os.conf'), str(self.info.settings.os))\",\n                              \"save(self, os.path.join(self.package_folder, 'option.conf'), str(self.info.options.get_safe('myoption')))\",\n                              \"save(self, os.path.join(self.package_folder, 'otheroption.conf'), str(self.info.options.otheroption))\")})\n        tc.run(\"create . -s=os=Linux -o=&:myoption=True -o=&:otheroption=True\")\n        layout = tc.created_layout()\n        assert \"file.txt\" in os.listdir(layout.finalize())\n        assert tc.load(os.path.join(layout.finalize(), \"os.conf\")) == \"Linux\"\n        # This is problematic, it means that the mapping for finalize() and package_id would not be 1:1 and could be outdated\n        assert tc.load(os.path.join(layout.finalize(), \"option.conf\")) == \"None\"\n        assert tc.load(os.path.join(layout.finalize(), \"otheroption.conf\")) == \"True\"\n\n\nclass TestToolRequiresFlows:\n    def test_tool_requires(self):\n        tc = TestClient(light=True)\n        tc.save({\"dep/conanfile.py\": textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.files import save, copy\n\n            class TestConan(ConanFile):\n                name = \"dep\"\n                version = \"1.0\"\n                package_type = \"application\"\n                def package(self):\n                    save(self, os.path.join(self.package_folder, \"bin\", \"executable.txt\"), \"Base\")\n\n                def finalize(self):\n                    self.output.info(f\"Running finalize method in {self.package_folder}\")\n                    copy(self, \"*\", src=self.immutable_package_folder, dst=self.package_folder)\n                    save(self, os.path.join(self.package_folder, \"bin\", \"finalized.txt\"), \"finalized file\")\n\n                def package_info(self):\n                    self.output.info(f\"Running package_info method in {self.package_folder}\")\n                    self.cpp_info.bindirs = [\"bin\"]\n\n            \"\"\"), \"app/conanfile.py\": textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            import os\n\n            class TestConan(ConanFile):\n                name = \"app\"\n                version = \"1.0\"\n\n                def build_requirements(self):\n                    self.tool_requires(\"dep/1.0\")\n\n                def build(self):\n                    self.output.info(\"Running build method\")\n                    bindir = self.dependencies.build['dep'].cpp_info.bindir\n                    self.output.info(f\"Dep bindir: {bindir}\")\n                    self.output.info(f\"Is finalized? {os.path.exists(os.path.join(bindir, 'finalized.txt'))}\")\n            \"\"\")})\n        tc.run(\"create dep --build-require\")\n        dep_layout = tc.created_layout()\n        tc.run(\"create app\")\n        # This fails. cpp_info is using the original package folder to construct the final path\n        assert f\"Dep bindir: {dep_layout.finalize()}\" in tc.out\n        assert \"app/1.0: Is finalized? True\" in tc.out\n\n    def test_test_package_uses_created_tool_which_modifies_pkgfolder(self):\n        tc = TestClient(light=True)\n        tc.save({\"conanfile.py\": GenConanfile(\"app\", \"1.0\")\n                .with_import(\"from conan.tools.files import save\")\n                .with_package_type(\"application\")\n                .with_package(\"save(self, 'file.txt', 'Hello World!')\")\n                .with_package_info({\"bindirs\": [\"bin\"]})\n                .with_finalize(\"save(self, 'finalized.txt', 'finalized file')\"),\n                 \"test_package/conanfile.py\": GenConanfile()\n                .with_import(\"from conan.tools.files import save\",\n                             \"import os\")\n                .with_test_reference_as_build_require()\n                .with_test(\"bindir = self.dependencies.build[self.tested_reference_str].cpp_info.bindir\",\n                           \"self.output.info(f'Bindir: {bindir}')\",\n                           \"save(self, os.path.join(bindir, '__pycache__.pyc'), 'Test file')\")})\n        tc.run(\"create . --build-require\")\n        app_layout = tc.created_layout()\n        assert f\"Bindir: {os.path.join(app_layout.finalize(), 'bin')}\" in tc.out\n        tc.run(f\"cache check-integrity {app_layout.reference}\")\n        assert \"There are corrupted artifacts\" not in tc.out\n\n\nclass TestRemoteFlows:\n\n    @pytest.fixture\n    def client(self):\n        tc = TestClient(light=True, default_server_user=True)\n        tc.save({\"dep/conanfile.py\": conanfile_dep})\n        tc.run(\"export dep\")\n        return tc\n\n    def test_remote_upload_finalize_method(self, client):\n        client.run(\"create dep\")\n        created_pref = client.created_package_reference(\"dep/1.0\")\n        client.run(\"upload * -r=default -c\")\n\n        # Only the package folder is uploaded, not the finalize folder\n        uploaded_pref_path = client.servers[\"default\"].test_server.server_store.package(created_pref)\n        manifest_contents = load(os.path.join(uploaded_pref_path, \"conanmanifest.txt\"))\n        assert \"file.txt\" in manifest_contents\n        assert \"finalized.txt\" not in manifest_contents\n\n        client.run(\"remove * -c\")\n        client.run(f\"download {created_pref} -r=default\")\n        downloaded_pref_layout = client.get_latest_pkg_layout(created_pref)\n        assert \"file.txt\" in os.listdir(downloaded_pref_layout.package())\n        # Download is not an \"usage\" of the package, so no finalize() is yet executed\n        assert \"finalized.txt\" not in os.listdir(downloaded_pref_layout.package())\n        assert not os.path.exists(os.path.join(downloaded_pref_layout.finalize()))\n\n        client.run(f\"cache path {created_pref}\")\n        package_folder = client.out.strip()\n        assert package_folder == downloaded_pref_layout.package()\n        assert package_folder.endswith(\"p\")\n        # Now this finalize will run the finalize() method\n        client.run(\"install --requires=dep/1.0\")\n        assert f\"Running finalize method in {downloaded_pref_layout.finalize()}\" in client.out\n\n        client.run(\"remove * -c\")\n        client.run(\"install --requires=dep/1.0 -r=default\")\n        assert \"dep/1.0: Calling finalize()\"\n        assert f\"Running finalize method in {downloaded_pref_layout.finalize()}\" in client.out\n\n    def test_upload_verify_integrity(self, client):\n        client.run(\"create dep\")\n        dep_layout = client.created_layout()\n        client.run(\"upload * -r=default -c --check\")\n        assert f\"dep/1.0#{dep_layout.reference.ref.revision}:{dep_layout.reference.package_id}\" \\\n               f\"#{dep_layout.reference.revision}: Integrity check: ok\" in client.out\n        assert \"There are corrupted artifacts\" not in client.out\n"
  },
  {
    "path": "test/integration/conanfile/test_print_in_conanfile.py",
    "content": "import json\nimport textwrap\n\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_print_in_conanfile():\n    \"\"\"\n    Tests that prints in conanfiles will not ruin json stdout outputs\n    \"\"\"\n    c = TestClient(light=True)\n    other = textwrap.dedent(\"\"\"\n        def myprint(text):\n            print(text)\n        \"\"\")\n    conanfile = textwrap.dedent(\"\"\"\n        import other\n        from conan import ConanFile\n\n        class MyTest(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n\n            def generate(self):\n                print(\"Hello world!!\")\n                other.myprint(\"Bye world!!\")\n        \"\"\")\n    c.save({\"other.py\": other,\n            \"conanfile.py\": conanfile})\n    c.run(\"install . --format=json\")\n    assert \"Hello world!!\" in c.stderr\n    assert \"Bye world!!\" in c.stderr\n    info = json.loads(c.stdout)\n    # the json is correctly loaded\n    assert \"graph\" in info\n"
  },
  {
    "path": "test/integration/conanfile/test_version_str.py",
    "content": "import textwrap\n\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_conan_version_str():\n    \"\"\"\n    conanfile.version should always be a string.\n    If comparison neeeded use Version(self.version) or self.ref.version\n    \"\"\"\n    # https://github.com/conan-io/conan/issues/10372\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.scm import Version\n\n        class Lib(ConanFile):\n            name = \"pkg\"\n            version = \"1.0\"\n\n            def _assert_data(self):\n                assert isinstance(self.version, str)\n                assert not isinstance(self.version, Version)\n\n            def configure(self):\n                self._assert_data()\n\n            def source(self):\n                self._assert_data()\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create .\")\n"
  },
  {
    "path": "test/integration/configuration/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/configuration/client_certs_test.py",
    "content": "import os\nimport textwrap\n\nfrom requests import Response\n\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient, TestRequester\nfrom conan.internal.util.files import save\n\n\nconanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    from conan.tools.files import download\n\n    class Pkg(ConanFile):\n        settings = \"os\", \"compiler\"\n\n        def source(self):\n            download(self, \"http://foo.bar/file\", \"filename.txt\")\n    \"\"\")\n\n\nclass MyHttpRequester(TestRequester):\n\n    def get(self, _, **kwargs):\n        resp = Response()\n        # resp._content = b'{\"results\": []}'\n        resp.status_code = 200\n        resp._content = b''\n        # This will be captured in the TestClient.out too\n        print(\"KWARGS auth: {}\".format(kwargs[\"auth\"]))\n        print(\"KWARGS verify: {}\".format(kwargs[\"verify\"]))\n        print(\"KWARGS cert: {}\".format(kwargs[\"cert\"]))\n        return resp\n\n\nclass TestClientCerts:\n\n    def test_pic_custom_path_client_certs(self):\n        folder = temp_folder()\n        mycert_path = os.path.join(folder, \"mycert.crt\").replace(\"\\\\\", '/')\n        mykey_path = os.path.join(folder, \"mycert.key\").replace(\"\\\\\", '/')\n        save(mycert_path, \"Fake Cert\")\n        save(mykey_path, \"Fake Key\")\n\n        client = TestClient(requester_class=MyHttpRequester)\n        conan_conf = textwrap.dedent(\"\"\"\n                                    core.net.http:client_cert= (\"{}\", \"{}\")\n                                \"\"\".format(mycert_path, mykey_path))\n        client.save_home({\"global.conf\": conan_conf})\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --name=foo --version=1.0\")\n        assert \"KWARGS cert: ('{}', '{}')\".format(mycert_path, mykey_path) in client.out\n"
  },
  {
    "path": "test/integration/configuration/conf/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/configuration/conf/test_auth_source_plugin.py",
    "content": "import json\nimport os\nimport textwrap\nfrom unittest import mock\nfrom unittest.mock import MagicMock\n\nimport pytest\n\nfrom conan import __version__\nfrom conan.internal.model.conf import ConfDefinition\nfrom conan.internal.rest.conan_requester import ConanRequester\nfrom conan.test.utils.file_server import TestFileServer\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import save\n\n\nclass TestAuthSourcePlugin:\n    @pytest.fixture\n    def setup_test_client(self):\n        client = TestClient(default_server_user=True, light=True)\n        file_server = TestFileServer()\n        client.servers[\"file_server\"] = file_server\n        client.save_home({\"global.conf\": \"tools.files.download:retry=0\"})\n\n        save(os.path.join(file_server.store, \"myfile.txt\"), \"Bye, world!\")\n\n        conanfile = textwrap.dedent(f\"\"\"\n           from conan import ConanFile\n           from conan.tools.files import download\n           class Pkg2(ConanFile):\n               name = \"pkg\"\n               version = \"1.0\"\n               def source(self):\n                   download(self, \"{file_server.fake_url}/basic-auth/myfile.txt\", \"myfile.txt\")\n           \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n\n        return client, file_server.fake_url\n\n    def test_error_source_plugin(self, setup_test_client):\n        \"\"\" Test when the plugin fails, we want a clear message and a helpful trace\n        \"\"\"\n        c, url = setup_test_client\n        auth_plugin = textwrap.dedent(\"\"\"\\\n            def auth_source_plugin(url):\n                raise Exception(\"Test Error\")\n            \"\"\")\n        c.save_home({\"extensions/plugins/auth_source.py\": auth_plugin})\n        c.run(\"source conanfile.py\", assert_error=True)\n        assert \"Test Error\" in c.out\n\n    @pytest.mark.parametrize(\"password\", [\"password\", \"bad-password\"])\n    def test_auth_source_plugin_direct_credentials(self, password, setup_test_client):\n        \"\"\" Test when the plugin give a correct and wrong password, we want a message about\n        the success or fail in login\n        \"\"\"\n        should_fail = password == \"bad-password\"\n        c, url = setup_test_client\n        auth_plugin = textwrap.dedent(f\"\"\"\\\n            def auth_source_plugin(url):\n                return {json.dumps({'user': 'user', 'password': password})}\n            \"\"\")\n        c.save_home({\"extensions/plugins/auth_source.py\": auth_plugin})\n        c.run(\"source conanfile.py\", assert_error=should_fail)\n        if should_fail:\n            assert \"AuthenticationException\" in c.out\n        else:\n            assert os.path.exists(os.path.join(c.current_folder, \"myfile.txt\"))\n\n    def test_auth_source_plugin_fallback(self, setup_test_client):\n        \"\"\" Test when the plugin do not give any user or password, we want the code to continue with\n        the rest of the input methods\n        \"\"\"\n        c, url = setup_test_client\n        auth_plugin = textwrap.dedent(\"\"\"\\\n                def auth_source_plugin(url):\n                    return None\n                \"\"\")\n        c.save_home({\"extensions/plugins/auth_source.py\": auth_plugin})\n        source_credentials = json.dumps({\"credentials\": [{\"url\": url, \"token\": \"password\"}]})\n        c.save_home({\"source_credentials.json\": source_credentials})\n        c.run(\"source conanfile.py\")\n        # As the auth plugin is not returning any password the code is falling back to the rest of\n        # the input methods in this case provided by source_credentials.json.\n        assert os.path.exists(os.path.join(c.current_folder, \"myfile.txt\"))\n\n    def test_source_auth_plugin_headers(self):\n        auth_plugin = textwrap.dedent(f\"\"\"\\\n            def auth_source_plugin(url):\n                return {json.dumps({'headers': {\"myheader\": \"myvalue\"}})}\n            \"\"\")\n        cache_folder = temp_folder()\n        save(os.path.join(cache_folder, \"extensions/plugins/auth_source.py\"), auth_plugin)\n\n        mock_http_requester = MagicMock()\n        with mock.patch(\"conan.internal.rest.conan_requester.requests\", mock_http_requester):\n            requester = ConanRequester(ConfDefinition(), cache_folder)\n            requester.get(url=\"aaa\", source_credentials=True)\n            headers = requester._http_requester.get.call_args[1][\"headers\"]\n            assert headers[\"myheader\"] == \"myvalue\"\n            assert f\"Conan/{__version__}\" in headers[\"User-Agent\"]\n\n    def test_source_credentials_headers(self):\n        cache_folder = temp_folder()\n        source_credentials = json.dumps({\"credentials\": [{\"url\": \"aaa\", \"token\": \"mytok\",\n                                                          \"headers\": {\"myheader2\": \"myvalue2\"}}]})\n        save(os.path.join(cache_folder, \"source_credentials.json\"), source_credentials)\n\n        mock_http_requester = MagicMock()\n        with mock.patch(\"conan.internal.rest.conan_requester.requests\", mock_http_requester):\n            requester = ConanRequester(ConfDefinition(), cache_folder)\n            requester.get(url=\"aaa\", source_credentials=True)\n            headers = requester._http_requester.get.call_args[1][\"headers\"]\n            assert headers[\"myheader2\"] == \"myvalue2\"\n            assert f\"Conan/{__version__}\" in headers[\"User-Agent\"]\n"
  },
  {
    "path": "test/integration/configuration/conf/test_conf.py",
    "content": "import os\nimport platform\nimport textwrap\n\nimport pytest\nfrom unittest.mock import patch\n\nfrom conan import conan_version\nfrom conan.internal.api.detect import detect_api\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.internal.util.files import save\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.fixture\ndef client():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Pkg(ConanFile):\n            def generate(self):\n                for k, v in self.conf.items():\n                    self.output.info(\"{}${}\".format(k, v))\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    return client\n\n\ndef test_basic_composition(client):\n    profile1 = textwrap.dedent(\"\"\"\\\n        [conf]\n        tools.build:verbosity=quiet\n        tools.microsoft.msbuild:vs_version=Slow\n        tools.cmake.cmaketoolchain:generator=Extra\n        \"\"\")\n    profile2 = textwrap.dedent(\"\"\"\\\n        [conf]\n        tools.build:verbosity=quiet\n        tools.microsoft.msbuild:max_cpu_count=High\n        tools.meson.mesontoolchain:backend=Super\n        \"\"\")\n    client.save({\"profile1\": profile1,\n                 \"profile2\": profile2})\n    client.run(\"install . -pr=profile1\")\n    assert \"tools.build:verbosity$quiet\" in client.out\n    assert \"tools.microsoft.msbuild:vs_version$Slow\" in client.out\n    assert \"tools.cmake.cmaketoolchain:generator$Extra\" in client.out\n\n    client.run(\"install . -pr=profile1 -pr=profile2\")\n    assert \"tools.build:verbosity$quiet\" in client.out\n    assert \"tools.microsoft.msbuild:vs_version$Slow\" in client.out\n    assert \"tools.microsoft.msbuild:max_cpu_count$High\" in client.out\n    assert \"tools.cmake.cmaketoolchain:generator$Extra\" in client.out\n    assert \"tools.meson.mesontoolchain:backend$Super\" in client.out\n\n    client.run(\"install . -pr=profile2 -pr=profile1\")\n    assert \"tools.build:verbosity$quiet\" in client.out\n    assert \"tools.microsoft.msbuild:vs_version$Slow\" in client.out\n    assert \"tools.microsoft.msbuild:max_cpu_count$High\" in client.out\n    assert \"tools.cmake.cmaketoolchain:generator$Extra\" in client.out\n    assert \"tools.meson.mesontoolchain:backend$Super\" in client.out\n\n\ndef test_basic_inclusion(client):\n    profile1 = textwrap.dedent(\"\"\"\\\n        [conf]\n        tools.build:verbosity=quiet\n        tools.microsoft.msbuild:vs_version=Slow\n        tools.cmake.cmaketoolchain:generator=Extra\n        \"\"\")\n    profile2 = textwrap.dedent(\"\"\"\\\n        include(profile1)\n        [conf]\n        tools.build:verbosity=quiet\n        tools.microsoft.msbuild:max_cpu_count=High\n        tools.meson.mesontoolchain:backend=Super\n        \"\"\")\n    client.save({\"profile1\": profile1,\n                 \"profile2\": profile2})\n\n    client.run(\"install . -pr=profile2\")\n    assert \"tools.build:verbosity$quiet\" in client.out\n    assert \"tools.microsoft.msbuild:vs_version$Slow\" in client.out\n    assert \"tools.microsoft.msbuild:max_cpu_count$High\" in client.out\n    assert \"tools.cmake.cmaketoolchain:generator$Extra\" in client.out\n    assert \"tools.meson.mesontoolchain:backend$Super\" in client.out\n\n\ndef test_composition_conan_conf(client):\n    conf = textwrap.dedent(\"\"\"\\\n        tools.build:verbosity=quiet\n        tools.microsoft.msbuild:vs_version=Slow\n        tools.cmake.cmaketoolchain:generator=Extra\n        \"\"\")\n    client.save_home({\"global.conf\": conf})\n    profile = textwrap.dedent(\"\"\"\\\n        [conf]\n        tools.build:verbosity=quiet\n        tools.microsoft.msbuild:max_cpu_count=High\n        tools.meson.mesontoolchain:backend=Super\n        \"\"\")\n    client.save({\"profile\": profile})\n    client.run(\"install . -pr=profile\")\n    assert \"tools.build:verbosity$quiet\" in client.out\n    assert \"tools.microsoft.msbuild:vs_version$Slow\" in client.out\n    assert \"tools.microsoft.msbuild:max_cpu_count$High\" in client.out\n    assert \"tools.cmake.cmaketoolchain:generator$Extra\" in client.out\n    assert \"tools.meson.mesontoolchain:backend$Super\" in client.out\n\n\ndef test_core_global_conf_not_in_profile(client):\n    client.save_home({\"global.conf\": \"core.upload:retry=1\"})\n    profile = textwrap.dedent(\"\"\"\\\n        [conf]\n        tools.build:verbosity=quiet\n        \"\"\")\n    client.save({\"profile\": profile})\n    client.run(\"install . -pr=profile\")\n    assert \"tools.build:verbosity$quiet\" in client.out\n    # The core conf is not shown\n    assert \"core.upload:retry=1\" not in client.out\n\n    # also with -cc command line argument\n    client.run(\"install . -pr=profile -cc core.upload:retry=1\")\n    assert \"tools.build:verbosity$quiet\" in client.out\n    # The core conf is not shown\n    assert \"core.upload:retry=1\" not in client.out\n\n\ndef test_new_config_file(client):\n    conf = textwrap.dedent(\"\"\"\\\n        tools.build:verbosity=quiet\n        user.mycompany.myhelper:myconfig=myvalue\n        *:tools.cmake.cmaketoolchain:generator=X\n        \"\"\")\n    client.save_home({\"global.conf\": conf})\n    client.run(\"install .\")\n    assert \"tools.build:verbosity$quiet\" in client.out\n    assert \"user.mycompany.myhelper:myconfig$myvalue\" in client.out\n    assert \"tools.cmake.cmaketoolchain:generator$X\" in client.out\n    assert \"read_only\" not in client.out\n\n    conf = textwrap.dedent(\"\"\"\\\n            tools.build:verbosity=notice\n            user.mycompany.myhelper:myconfig=myvalue\n            *:tools.cmake.cmaketoolchain:generator=X\n            cache:read_only=True\n            \"\"\")\n    client.save_home({\"global.conf\": conf})\n    client.run(\"install .\", assert_error=True)\n    assert \"[conf] 'cache:read_only' does not exist in configuration list\" in client.out\n\n\n@patch(\"conan.__version__\", \"1.26.0\")\ndef test_new_config_file_required_version():\n    client = TestClient()\n    conf = textwrap.dedent(\"\"\"\\\n        core:required_conan_version=>=2.0\n        \"\"\")\n    client.save_home({\"global.conf\": conf})\n    client.run(\"install .\", assert_error=True)\n    assert (\"Current Conan version (1.26.0) does not satisfy the defined one (>=2.0)\"\n            in client.out)\n\n\ndef test_composition_conan_conf_overwritten_by_cli_arg(client):\n    conf = textwrap.dedent(\"\"\"\\\n        tools.build:verbosity=quiet\n        tools.microsoft.msbuild:max_cpu_count=Slow\n        \"\"\")\n    client.save_home({\"global.conf\": conf})\n    profile = textwrap.dedent(\"\"\"\\\n        [conf]\n        tools.build:verbosity=quiet\n        tools.microsoft.msbuild:vs_version=High\n        \"\"\")\n    client.save({\"profile\": profile})\n    client.run(\"install . -pr=profile -c tools.build:verbosity=verbose \"\n               \"-c tools.meson.mesontoolchain:backend=Super\")\n    assert \"tools.build:verbosity$verbose\" in client.out\n    assert \"tools.microsoft.msbuild:max_cpu_count$Slow\" in client.out\n    assert \"tools.microsoft.msbuild:vs_version$High\" in client.out\n    assert \"tools.meson.mesontoolchain:backend$Super\" in client.out\n\n\ndef test_composition_conan_conf_different_data_types_by_cli_arg(client):\n    \"\"\"\n    Testing if you want to introduce a list/dict via cli\n\n    >> conan install . -c \"tools.build.flags:ccflags+=['-Werror']\"\n    >> conan install . -c \"tools.microsoft.msbuildtoolchain:compile_options={'ExceptionHandling': 'Async'}\"\n\n    \"\"\"\n    conf = textwrap.dedent(\"\"\"\\\n        tools.build:cflags=[\"-Wall\"]\n        \"\"\")\n    client.save_home({\"global.conf\": conf})\n    client.run('install . -c \"tools.build:cflags+=[\\'-Werror\\']\" '\n               '-c \"tools.microsoft.msbuildtoolchain:compile_options={\\'ExceptionHandling\\': \\'Async\\'}\"')\n\n    assert \"tools.build:cflags$['-Wall', '-Werror']\" in client.out\n    assert \"tools.microsoft.msbuildtoolchain:compile_options${'ExceptionHandling': 'Async'}\" in client.out\n\n\ndef test_jinja_global_conf(client):\n    client.save_home({\"global.conf\": \"user.mycompany:parallel = {{os.cpu_count()/2}}\\n\"\n                                     \"user.mycompany:other = {{platform.system()}}\\n\"\n                                     \"user.mycompany:dist = {{distro.id() if distro else '42'}}\\n\"\n                                     \"user.conan:version = {{conan_version}}-{{conan_version>0.1}}\"})\n    client.run(\"install .\")\n    assert \"user.mycompany:parallel={}\".format(os.cpu_count()/2) in client.out\n    assert \"user.mycompany:other={}\".format(platform.system()) in client.out\n    assert f\"user.conan:version={conan_version}-True\" in client.out\n    if platform.system() == \"Linux\":\n        import distro\n        assert \"user.mycompany:dist={}\".format(distro.id()) in client.out\n    else:\n        assert \"user.mycompany:dist=42\" in client.out\n\n\ndef test_jinja_global_conf_include(client):\n    global_conf = textwrap.dedent(\"\"\"\\\n        {% include \"user_global.conf\" %}\n        {% import \"user_global.conf\" as vars %}\n        user.mycompany:dist = {{vars.myvar*2}}\n        \"\"\")\n    user_global_conf = textwrap.dedent(\"\"\"\\\n        {% set myvar = 42 %}\n        user.mycompany:parallel = {{myvar}}\n        \"\"\")\n    client.save_home({\"global.conf\": global_conf})\n    save(os.path.join(client.cache_folder, \"user_global.conf\"), user_global_conf)\n    client.run(\"install .\")\n    assert \"user.mycompany:parallel=42\" in client.out\n    assert \"user.mycompany:dist=84\" in client.out\n\n\ndef test_jinja_global_conf_paths():\n    c = TestClient()\n    global_conf = 'user.mycompany:myfile = {{os.path.join(conan_home_folder, \"myfile\")}}'\n    c.save_home({\"global.conf\": global_conf})\n    c.run(\"config show *\")\n    cache_folder = c.cache_folder.replace(\"\\\\\", \"/\")\n    assert f\"user.mycompany:myfile: {os.path.join(cache_folder, 'myfile')}\" in c.out\n\n\ndef test_profile_detect_os_arch():\n    \"\"\" testing OS & ARCH just to test that detect_api is injected\n    \"\"\"\n    c = TestClient()\n    global_conf = textwrap.dedent(\"\"\"\n        user.myteam:myconf1={{detect_api.detect_os()}}\n        user.myteam:myconf2={{detect_api.detect_arch()}}\n        \"\"\")\n\n    c.save_home({\"global.conf\": global_conf})\n    c.run(\"config show *\")\n    _os = detect_api.detect_os()\n    _arch = detect_api.detect_arch()\n    assert f\"user.myteam:myconf1: {_os}\" in c.out\n    assert f\"user.myteam:myconf2: {_arch}\" in c.out\n\n\ndef test_empty_conf_valid():\n    tc = TestClient()\n    profile = textwrap.dedent(r\"\"\"\n    [conf]\n    user:unset=\n    \"\"\")\n    conanfile = textwrap.dedent(r\"\"\"\n    from conan import ConanFile\n\n    class BasicConanfile(ConanFile):\n        name = \"pkg\"\n        version = \"1.0\"\n\n        def generate(self):\n            self.output.warning(f'My unset conf variable is: \"{self.conf.get(\"user:unset\")}\"')\n            self.output.warning(f'My unset conf is {\"NOT\" if self.conf.get(\"user:unset\") == None else \"\"} set')\n    \"\"\")\n    tc.save({\"conanfile.py\": conanfile, \"profile\": profile})\n\n    tc.run(\"create .\")\n    assert 'pkg/1.0: WARN: My unset conf is NOT set' in tc.out\n\n    tc.run(\"create . -pr=profile\")\n    assert 'pkg/1.0: WARN: My unset conf variable is: \"\"' in tc.out\n    assert 'pkg/1.0: WARN: My unset conf is  set' in tc.out\n\n    tc.run(\"create . -c user:unset=\")\n    assert 'pkg/1.0: WARN: My unset conf variable is: \"\"' in tc.out\n    assert 'pkg/1.0: WARN: My unset conf is  set' in tc.out\n\n    tc.run('create . -c user:unset=\"\"')\n    assert 'pkg/1.0: WARN: My unset conf variable is: \"\"' in tc.out\n    assert 'pkg/1.0: WARN: My unset conf is  set' in tc.out\n\n    # And ensure this actually works for the normal case, just in case\n    tc.run(\"create . -c user:unset=Hello\")\n    assert 'pkg/1.0: WARN: My unset conf variable is: \"Hello\"' in tc.out\n    assert 'pkg/1.0: WARN: My unset conf is  set' in tc.out\n\n\ndef test_nonexisting_conf():\n    c = TestClient()\n    c.save({\"conanfile.txt\": \"\"})\n    c.run(\"install . -c tools.unknown:conf=value\", assert_error=True)\n    assert \"ERROR: [conf] 'tools.unknown:conf' does not exist in configuration\" in c.out\n    c.run(\"install . -c user.some:var=value\")  # This doesn't fail\n    c.run(\"install . -c user.some.var=value\", assert_error=True)\n    assert \"ERROR: User conf 'user.some.var' invalid format, not 'user.org.group:conf'\" in c.out\n    c.run(\"install . -c tool.build:verbosity=v\", assert_error=True)\n    assert \"ERROR: [conf] 'tool.build:verbosity' does not exist in configuration\" in c.out\n\n\ndef test_nonexisting_conf_global_conf():\n    c = TestClient()\n    c.save_home({\"global.conf\":  \"tools.unknown:conf=value\"})\n    c.save({\"conanfile.txt\": \"\"})\n    c.run(\"install . \", assert_error=True)\n    assert \"ERROR: [conf] 'tools.unknown:conf' does not exist in configuration\" in c.out\n\n\ndef test_global_conf_auto_created():\n    c = TestClient()\n    c.run(\"config list\")  # all commands will trigger\n    global_conf = c.load_home(\"global.conf\")\n    assert \"# core:non_interactive = True\" in global_conf\n\n\ndef test_command_line_core_conf():\n    c = TestClient()\n    c.run(\"config show * -cc core:default_profile=potato\")\n    assert \"core:default_profile: potato\" in c.out\n    c.run(\"config show * -cc core:default_profile=potato -cc core:default_build_profile=orange\")\n    assert \"core:default_profile: potato\" in c.out\n    assert \"core:default_build_profile: orange\" in c.out\n\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n    c.run(\"export .\")\n\n    tfolder = temp_folder()\n    c.run(f'list * -cc core.cache:storage_path=\"{tfolder}\"')\n    assert \"WARN: There are no matching recipe references\" in c.out\n    c.run(f'list *')\n    assert \"WARN: There are no matching recipe references\" not in c.out\n    assert \"pkg/0.1\" in c.out\n\n    c.run(\"list * -cc user.xxx:yyy=zzz\", assert_error=True)\n    assert \"ERROR: Only core. values are allowed in --core-conf. Got user.xxx:yyy=zzz\" in c.out\n\n\ndef test_build_test_consumer_only():\n    c = TestClient()\n    dep = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"dep\"\n            version = \"0.1\"\n            def generate(self):\n                skip = self.conf.get(\"tools.build:skip_test\", check_type=bool)\n                self.output.info(f'SKIP-TEST: {skip}')\n        \"\"\")\n    pkg = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                requires = \"dep/0.1\"\n                def generate(self):\n                    self.output.info(f'SKIP-TEST: {self.conf.get(\"tools.build:skip_test\")}')\n            \"\"\")\n    c.save_home({\"global.conf\": \"tools.build:skip_test=True\\n&:tools.build:skip_test=False\"})\n    c.save({\"dep/conanfile.py\": dep,\n            \"pkg/conanfile.py\": pkg,\n            \"pkg/test_package/conanfile.py\": GenConanfile().with_test(\"pass\")})\n    c.run(\"create dep\")\n    assert \"dep/0.1: SKIP-TEST: False\" in c.out\n    c.run('create pkg --build=* -tf=\"\"')\n    assert \"dep/0.1: SKIP-TEST: True\" in c.out\n    assert \"pkg/0.1: SKIP-TEST: False\" in c.out\n    c.run('create pkg --build=*')\n    assert \"dep/0.1: SKIP-TEST: True\" in c.out\n    assert \"pkg/0.1: SKIP-TEST: False\" in c.out\n    c.run('install pkg --build=*')\n    assert \"dep/0.1: SKIP-TEST: True\" in c.out\n    assert \"conanfile.py (pkg/0.1): SKIP-TEST: False\" in c.out\n\n\ndef test_conf_should_be_immutable():\n    c = TestClient()\n    dep = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"dep\"\n            version = \"0.1\"\n            def generate(self):\n                self.conf.append(\"user.myteam:myconf\", \"value1\")\n                self.output.info(f'user.myteam:myconf: {self.conf.get(\"user.myteam:myconf\")}')\n        \"\"\")\n    pkg = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            requires = \"dep/0.1\"\n            def generate(self):\n                self.output.info(f'user.myteam:myconf: {self.conf.get(\"user.myteam:myconf\")}')\n        \"\"\")\n    c.save_home({\"global.conf\": 'user.myteam:myconf=[\"root_value\"]'})\n    c.save({\"dep/conanfile.py\": dep,\n            \"pkg/conanfile.py\": pkg})\n    c.run(\"create dep\")\n    assert \"dep/0.1: user.myteam:myconf: ['root_value', 'value1']\" in c.out\n    c.run('create pkg --build=*')\n    assert \"dep/0.1: user.myteam:myconf: ['root_value', 'value1']\" in c.out\n    # The pkg/0.1 output should be non-modified\n    assert \"pkg/0.1: user.myteam:myconf: ['root_value']\" in c.out\n\n\ndef test_especial_strings_fail():\n    # https://github.com/conan-io/conan/issues/15777\n    c = TestClient()\n    global_conf = textwrap.dedent(\"\"\"\n        user.mycompany:myfile = re\n        user.mycompany:myother = fnmatch\n        user.mycompany:myfunct = re.search\n        user.mycompany:mydict = {1: 're', 2: 'fnmatch'}\n        \"\"\")\n    c.save_home({\"global.conf\": global_conf})\n    c.run(\"config show *\")\n    assert \"user.mycompany:myfile: re\" in c.out\n    assert \"user.mycompany:myother: fnmatch\" in c.out\n    assert \"user.mycompany:myfunct: re.search\" in c.out\n    assert \"user.mycompany:mydict: {1: 're', 2: 'fnmatch'}\" in c.out\n\n\ndef test_conf_test_package():\n    c = TestClient()\n    dep = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"dep\"\n            version = \"0.1\"\n            def generate(self):\n                self.output.info(f'user.myteam:myconf: {self.conf.get(\"user.myteam:myconf\")}')\n        \"\"\")\n    pkg = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            def requirements(self):\n                self.requires(self.tested_reference_str)\n            def generate(self):\n                self.output.info(f'user.myteam:myconf: {self.conf.get(\"user.myteam:myconf\")}')\n            def test(self):\n                pass\n        \"\"\")\n    c.save({\"conanfile.py\": dep,\n            \"test_package/conanfile.py\": pkg})\n    c.run(\"create . -c &:user.myteam:myconf=myvalue\")\n    assert \"dep/0.1: user.myteam:myconf: myvalue\" in c.out\n    assert \"dep/0.1 (test package): user.myteam:myconf: myvalue\" in c.out\n"
  },
  {
    "path": "test/integration/configuration/conf/test_conf_copy.py",
    "content": "from conan.internal.model.conf import Conf\n\n\ndef test_copy_conaninfo_conf():\n    conf = Conf()\n\n    conf.define(\"core:non_interactive\", True)\n    conf.define(\"tools.cmake.cmaketoolchain:generator\", True)\n    conf.define(\"tools.deployer:symlinks\", True)\n    conf.define(\"user.myconf:cmake-test\", True)\n\n    pattern = [\".*\"]\n    conf.define(\"tools.info.package_id:confs\", pattern)\n    result = conf.copy_conaninfo_conf().dumps()\n    assert \"tools.info.package_id:confs=%s\" % pattern in result\n    assert \"core:non_interactive\" in result\n    assert \"tools.cmake.cmaketoolchain:generator=True\" in result\n    assert \"tools.deployer:symlinks\" in result\n    assert \"user.myconf:cmake-test\" in result\n\n    pattern = [r\"tools\\..*\"]\n    conf.define(\"tools.info.package_id:confs\", pattern)\n    result = conf.copy_conaninfo_conf().dumps()\n    assert \"tools.info.package_id:confs=%s\" % pattern in result\n    assert \"core:non_interactive\" not in result\n    assert \"tools.cmake.cmaketoolchain:generator=True\" in result\n    assert \"tools.deployer:symlinks\" in result\n    assert \"user.myconf:cmake-test\" not in result\n\n    pattern = [\".*cmake\"]\n    conf.define(\"tools.info.package_id:confs\", pattern)\n    result = conf.copy_conaninfo_conf().dumps()\n    assert \"tools.info.package_id:confs=%s\" % pattern not in result\n    assert \"core:non_interactive\" not in result\n    assert \"tools.cmake.cmaketoolchain:generator=True\" in result\n    assert \"tools.deployer:symlinks\" not in result\n    assert \"user.myconf:cmake-test\" in result\n\n    pattern = [\"(tools.deploy|core)\"]\n    conf.define(\"tools.info.package_id:confs\", pattern)\n    result = conf.copy_conaninfo_conf().dumps()\n    assert \"tools.info.package_id:confs=%s\" % pattern not in result\n    assert \"core:non_interactive\" in result\n    assert \"tools.cmake.cmaketoolchain:generator=True\" not in result\n    assert \"tools.deployer:symlinks\" in result\n    assert \"user.myconf:cmake-test\" not in result\n\n"
  },
  {
    "path": "test/integration/configuration/conf/test_conf_from_br.py",
    "content": "import textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_basic():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Pkg(ConanFile):\n\n            def package_info(self):\n                self.conf_info.define_path(\"tools.android:ndk_path\", \"MY-NDK!!!\")\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=android_ndk --version=1.0\")\n\n    consumer = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"CMakeToolchain\"\n            build_requires = \"android_ndk/1.0\"\n\n            def generate(self):\n                self.output.info(\"NDK: %s\" % self.conf.get(\"tools.android:ndk_path\"))\n        \"\"\")\n    # CMakeToolchain needs compiler definition\n    linux_profile = textwrap.dedent(\"\"\"\n        [settings]\n        os = Linux\n        arch = x86_64\n        compiler = gcc\n        compiler.version = 4.9\n        compiler.libcxx = libstdc++\n        \"\"\")\n    android_profile = textwrap.dedent(\"\"\"\n        include(linux)\n        [conf]\n        tools.android:ndk_path=MY-SYSTEM-NDK!!!\n        \"\"\")\n    client.save({\"conanfile.py\": consumer,\n                 \"linux\": linux_profile,\n                 \"android\": android_profile}, clean_first=True)\n\n    client.run(\"install . -pr=linux\")\n    assert \"conanfile.py: NDK: MY-NDK!!!\" in client.out\n\n    client.run(\"install . -pr:b=default -pr:h=android\")\n    assert \"conanfile.py: NDK: MY-SYSTEM-NDK!!!\" in client.out\n\n\ndef test_basic_append():\n    c = TestClient()\n    tool = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            def package_info(self):\n                self.conf_info.append(\"user.myorg:myconf\", \"myorgconf!!!\")\n        \"\"\")\n    consumer = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            tool_requires = \"tool/1.0\"\n\n            def generate(self):\n                self.output.info(\"user.myorg:myconf: %s\" % self.conf.get(\"user.myorg:myconf\"))\n        \"\"\")\n\n    c.save({\"tool/conanfile.py\": tool,\n            \"consumer/conanfile.py\": consumer})\n    c.run(\"create tool --name=tool --version=1.0\")\n    c.run(\"install consumer\")\n    assert \"conanfile.py: user.myorg:myconf: ['myorgconf!!!']\" in c.out\n\n    c.run(\"install consumer -c user.myorg:myconf=value\", assert_error=True)\n    assert \"ERROR: It's not possible to compose str values and list ones\" in c.out\n\n    c.run(\"install consumer -c user.myorg:myconf=+value\")\n    assert \"conanfile.py: user.myorg:myconf: ['value', 'myorgconf!!!']\" in c.out\n\n\nclass TestImportant:\n\n    @staticmethod\n    def client(action, value):\n        value = '' if not value else f', {value}'\n        conanfile = textwrap.dedent(f\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                def package_info(self):\n                    self.conf_info.{action}(\"tools.android:ndk_path!\"{value})\n            \"\"\")\n        app = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                tool_requires = \"android_ndk/1.0\"\n                def generate(self):\n                    self.output.info(\"NDK: %s\" % self.conf.get(\"tools.android:ndk_path\"))\n            \"\"\")\n        c = TestClient(light=True)\n        c.save({\"conanfile.py\": conanfile})\n        c.run(\"create . --name=android_ndk --version=1.0\")\n        c.save({\"conanfile.py\": app}, clean_first=True)\n        return c\n\n    @pytest.mark.parametrize(\"action\", [\"define\", \"define_path\"])\n    def test_important_define(self, action):\n        c = self.client(action, '\"MY-NDK!!\"')\n        c.run(\"install\")\n        assert \"conanfile.py: NDK: MY-NDK!!\" in c.out\n\n        c.run(\"install -c tools.android:ndk_path=OTHERNDK!!\")\n        assert \"conanfile.py: NDK: MY-NDK!!\" in c.out\n\n        c.run(\"install -c tools.android:ndk_path+=OTHERNDK!!\", assert_error=True)\n        assert \"ERROR: It's not possible to compose list values and str ones.\" in c.out\n\n        c.run(\"install -c tools.android:ndk_path!=OTHERNDK!!\")\n        assert \"conanfile.py: NDK: OTHERNDK!!\" in c.out\n\n    @pytest.mark.parametrize(\"action\", [\"define\", \"define_path\"])\n    def test_important_define_list(self, action):\n        c = self.client(action, '[\"MY-NDK!!\"]')\n        c.run(\"install\")\n        assert \"conanfile.py: NDK: ['MY-NDK!!']\" in c.out\n\n        c.run(\"install -c tools.android:ndk_path=OTHERNDK!!\", assert_error=True)\n        assert \"ERROR: It's not possible to compose str values and list ones.\" in c.out\n\n        c.run(\"install -c tools.android:ndk_path+=OTHER! -c tools.android:ndk_path=+OTHER2!\")\n        assert \"conanfile.py: NDK: ['MY-NDK!!']\" in c.out\n\n        c.run(\"install -c tools.android:ndk_path!=OTHERNDK!!\", assert_error=True)\n        assert \"ERROR: It's not possible to compose str values and list ones.\" in c.out\n\n        c.run(\"install -c tools.android:ndk_path!+=OTHER! -c tools.android:ndk_path!=+OTHER2!\")\n        assert \"conanfile.py: NDK: ['OTHER2!', 'MY-NDK!!', 'OTHER!']\" in c.out\n\n    @pytest.mark.parametrize(\"action\", [\"append\", \"append_path\"])\n    def test_important_append(self, action):\n        c = self.client(action, '\"MY-NDK!!\"')\n        c.run(\"install\")\n        assert \"conanfile.py: NDK: ['MY-NDK!!']\" in c.out\n\n        c.run(\"install -c tools.android:ndk_path=OTHER!\", assert_error=True)\n        assert \"ERROR: It's not possible to compose str values and list ones.\" in c.out\n\n        c.run(\"install -c tools.android:ndk_path+=OTHER! -c tools.android:ndk_path=+OTHER2!\")\n        assert \"conanfile.py: NDK: ['OTHER2!', 'OTHER!', 'MY-NDK!!']\" in c.out\n\n        c.run(\"install -c tools.android:ndk_path!+=OTHER! -c tools.android:ndk_path!=+OTHER2!\")\n        assert \"conanfile.py: NDK: ['OTHER2!', 'MY-NDK!!', 'OTHER!']\" in c.out\n\n    @pytest.mark.parametrize(\"action\", [\"prepend\", \"prepend_path\"])\n    def test_important_prepend(self, action):\n        c = self.client(action, '\"MY-NDK!!\"')\n        c.run(\"install\")\n        assert \"conanfile.py: NDK: ['MY-NDK!!']\" in c.out\n        c.run(\"install -c tools.android:ndk_path=OTHER!\", assert_error=True)\n        assert \"ERROR: It's not possible to compose str values and list ones.\" in c.out\n\n        c.run(\"install -c tools.android:ndk_path+=OTHER! -c tools.android:ndk_path=+OTHER2!\")\n        assert \"conanfile.py: NDK: ['MY-NDK!!', 'OTHER2!', 'OTHER!']\" in c.out\n\n        c.run(\"install -c tools.android:ndk_path!+=OTHER! -c tools.android:ndk_path!=+OTHER2!\")\n        assert \"conanfile.py: NDK: ['OTHER2!', 'MY-NDK!!', 'OTHER!']\" in c.out\n\n    def test_important_unset(self):\n        c = self.client(\"unset\", \"\")\n        c.run(\"install\")\n        assert \"conanfile.py: NDK: None\" in c.out\n\n        c.run(\"install -c tools.android:ndk_path=OTHER!\")\n        assert \"conanfile.py: NDK: None\" in c.out\n\n        c.run(\"install -c tools.android:ndk_path+=OTHER! -c tools.android:ndk_path=+OTHER2!\")\n        assert \"conanfile.py: NDK: None\" in c.out\n\n        c.run(\"install -c tools.android:ndk_path!=OTHER!\")\n        assert \"conanfile.py: NDK: OTHER!\" in c.out\n\n        c.run(\"install -c tools.android:ndk_path!+=OTHER! -c tools.android:ndk_path!=+OTHER2!\")\n        assert \"conanfile.py: NDK: ['OTHER2!', 'OTHER!']\" in c.out\n\n    @pytest.mark.parametrize(\"action\", [\"update\", \"update_path\"])\n    def test_important_update(self, action):\n        c = self.client(action, {\"MYVALUE\": \"MY-NDK!!\"})\n        c.run(\"install\")\n        assert \"conanfile.py: NDK: {'MYVALUE': 'MY-NDK!!'}\" in c.out\n\n        c.run(\"install -c tools.android:ndk_path=OTHER!\", assert_error=True)\n        assert \"ERROR: It's not possible to compose str values and dict ones.\" in c.out\n\n        c.run(\"install -c tools.android:ndk_path=\\\"{'MYVALUE': 'OTHERVALUE!!', 'V2': 'O2!!'}\\\"\")\n        assert \"conanfile.py: NDK: {'MYVALUE': 'MY-NDK!!'}\" in c.out\n\n        c.run(\"install -c tools.android:ndk_path*=\\\"{'MYVALUE': 'OTHERVALUE!!', 'V2': 'O2!!'}\\\"\")\n        assert \"conanfile.py: NDK: {'MYVALUE': 'MY-NDK!!', 'V2': 'O2!!'}\" in c.out\n\n        c.run(\"install -c tools.android:ndk_path!=OTHER!\", assert_error=True)\n        assert \"ERROR: It's not possible to compose str values and dict ones.\" in c.out\n\n        c.run(\"install -c tools.android:ndk_path!=\\\"{'MYVALUE': 'OTHERVALUE!!', 'V2': 'O2!!'}\\\"\")\n        assert \"conanfile.py: NDK: {'MYVALUE': 'OTHERVALUE!!', 'V2': 'O2!!'}\" in c.out\n\n        c.run(\"install -c tools.android:ndk_path!*=\\\"{'MYVALUE': 'OTHERVALUE!!', 'V2': 'O2!!'}\\\"\")\n        assert \"conanfile.py: NDK: {'MYVALUE': 'OTHERVALUE!!', 'V2': 'O2!!'}\" in c.out\n\n\ndef test_basic_conf_through_cli():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Pkg(ConanFile):\n\n            def package_info(self):\n                self.output.info(\"NDK build: %s\" % self.conf.get(\"tools.android:ndk_path\"))\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=android_ndk --version=1.0\")\n\n    consumer = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"CMakeToolchain\"\n            build_requires = \"android_ndk/1.0\"\n\n            def generate(self):\n                self.output.info(\"NDK host: %s\" % self.conf.get(\"tools.android:ndk_path\"))\n        \"\"\")\n    # CMakeToolchain needs compiler definition\n    linux_profile = textwrap.dedent(\"\"\"\n        [settings]\n        os = Linux\n        arch = x86_64\n        compiler = gcc\n        compiler.version = 4.9\n        compiler.libcxx = libstdc++\n        \"\"\")\n    android_profile = textwrap.dedent(\"\"\"\n        include(linux)\n        [conf]\n        tools.android:ndk_path=MY-SYSTEM-NDK!!!\n        \"\"\")\n    client.save({\"conanfile.py\": consumer,\n                 \"linux\": linux_profile,\n                 \"android\": android_profile}, clean_first=True)\n    client.run('install . -c:b=tools.android:ndk_path=\"MY-NDK!!!\" '\n               '-c:h=tools.android:ndk_path=\"MY-SYSTEM-NDK!!!\" -pr:b=default -pr:h=android')\n    assert \"android_ndk/1.0: NDK build: MY-NDK!!!\" in client.out\n    assert \"conanfile.py: NDK host: MY-SYSTEM-NDK!!!\" in client.out\n\n\ndef test_declared_generators_get_conf():\n    # https://github.com/conan-io/conan/issues/9571\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            def package_info(self):\n                self.conf_info.append(\"tools.cmake.cmaketoolchain:user_toolchain\",\n                                      \"mytoolchain.cmake\")\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=mytool --version=1.0\")\n\n    consumer = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"CMakeToolchain\"\n            build_requires = \"mytool/1.0\"\n        \"\"\")\n    client.save({\"conanfile.py\": consumer}, clean_first=True)\n    client.run(\"install . -pr:b=default\")\n    toolchain = client.load(\"conan_toolchain.cmake\")\n    assert 'include(\"mytoolchain.cmake\")' in toolchain\n\n    consumer = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMakeToolchain\n\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            build_requires = \"mytool/1.0\"\n\n            def generate(self):\n                CMakeToolchain(self).generate()\n        \"\"\")\n    client.save({\"conanfile.py\": consumer}, clean_first=True)\n    client.run(\"install . -pr:b=default\")\n    toolchain = client.load(\"conan_toolchain.cmake\")\n    assert 'include(\"mytoolchain.cmake\")' in toolchain\n\n\ndef test_propagate_conf_info():\n    \"\"\" test we can use the conf_info to propagate information from the dependencies\n    to the consumers. The propagation is explicit.\n    TO DISCUSS: Should conf be aggregated always from all requires?\n    TODO: Backport to Conan 1.X so UserInfo is not longer necessary in 1.X\n    \"\"\"\n    # https://github.com/conan-io/conan/issues/9571\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            def package_info(self):\n                self.conf_info.define(\"user:myinfo1\", \"val1\")\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=dep1 --version=1.0\")\n    client.run(\"create . --name=dep2 --version=1.0\")\n\n    consumer = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Pkg(ConanFile):\n            requires = \"dep1/1.0\", \"dep2/1.0\"\n            def generate(self):\n                c1 = self.dependencies[\"dep1\"].conf_info.get(\"user:myinfo1\")\n                c2 = self.dependencies[\"dep2\"].conf_info.get(\"user:myinfo1\")\n                self.output.info(\"CONF1: {}\".format(c1))\n                self.output.info(\"CONF2: {}\".format(c2))\n        \"\"\")\n    client.save({\"conanfile.py\": consumer}, clean_first=True)\n    client.run(\"install . \")\n    assert \"conanfile.py: CONF1: val1\" in client.out\n    assert \"conanfile.py: CONF2: val1\" in client.out\n\n\ndef test_conf_transitive_tool():\n    \"\"\"\n    # https://github.com/conan-io/conan/issues/14421\n    app --(tool_requires)--> tool/0.1 -> lib/0.1 -(tool_require)-> libbuilder/0.1 -> zlib/0.1\n\n    profile-host = Debug\n    profile-build = Release\n    \"\"\"\n\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            version = \"0.1\"\n            settings = \"build_type\"\n            {}\n            def package_info(self):\n                self.output.info(f\"host: {{self.settings.build_type}}\")\n                self.output.info(f\"build: {{self.settings_build.build_type}}\")\n                if self.settings_target is not None:\n                    self.output.info(f\"target: {{self.settings_target.build_type}}\")\n        \"\"\")\n    client.save({\"zlib/conanfile.py\": conanfile.format(\"\"),\n                 \"libbuilder/conanfile.py\": conanfile.format(\"requires='zlib/0.1'\"),\n                 \"lib/conanfile.py\": conanfile.format(\"tool_requires='libbuilder/0.1'\"),\n                 \"tool/conanfile.py\": conanfile.format(\"requires='lib/0.1'\"),\n                 \"app/conanfile.py\": conanfile.format(\"tool_requires='tool/0.1'\")})\n    client.run(\"export zlib --name=zlib\")\n    client.run(\"export libbuilder --name=libbuilder\")\n    client.run(\"export lib --name=lib\")\n    client.run(\"export tool --name=tool\")\n    client.run(\"create app --name=app -s:b build_type=Release -s:h build_type=Debug --build=missing\")\n    for lib in \"zlib\", \"libbuilder\":\n        assert f\"{lib}/0.1: host: Release\" in client.out\n        assert f\"{lib}/0.1: build: Release\" in client.out\n        assert f\"{lib}/0.1: target: Release\" in client.out  # used to create lib/0.1 that is Release!\n    for lib in \"lib\", \"tool\":\n        assert f\"{lib}/0.1: host: Release\" in client.out\n        assert f\"{lib}/0.1: build: Release\" in client.out\n        assert f\"{lib}/0.1: target: Debug\" in client.out  # used to create app/0.1 that is Debug!\n    assert \"app/0.1: host: Debug\" in client.out\n    assert \"app/0.1: build: Release\" in client.out\n\n\ndef test_conf_both_build_and_host():\n    \"\"\"\n    # https://github.com/conan-io/conan/issues/14421\n    app --(requires)-----> protobuf(lib-host-release) -(tool_require)-> tool/0.1\n      \\\\- (tool_require)-> protobuf(protoc-build-release) -(tool_require) -> tool/0.1\n\n    profile-host = Debug\n    profile-build = Release\n    \"\"\"\n\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"tool\"\n            version = \"0.1\"\n            def package_info(self):\n                myvalue = str(self.settings_target.build_type)\n                self.conf_info.define(\"user.team:myconf\", myvalue)\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --build-require\")\n\n    myprotobuf = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Pkg(ConanFile):\n            name = \"myprotobuf\"\n            version = \"0.1\"\n            settings = \"build_type\"\n            tool_requires = \"tool/0.1\"\n\n            def generate(self):\n                self.output.info(f\"MYCONF {self.context}: {self.conf.get('user.team:myconf')}\")\n        \"\"\")\n\n    client.save({\"myprotobuf/conanfile.py\": myprotobuf,\n                 \"app/conanfile.py\": GenConanfile().with_requires(\"myprotobuf/0.1\")\n                                                   .with_tool_requires(\"myprotobuf/0.1\")},\n                clean_first=True)\n    client.run('export myprotobuf')\n    client.run(\"install app --build=missing -s:h build_type=Debug -s:b build_type=Release\")\n    assert \"myprotobuf/0.1: MYCONF build: Release\" in client.out\n    assert \"myprotobuf/0.1: MYCONF host: Debug\" in client.out\n\n\n@pytest.mark.parametrize(\"conf\", ['define(\"user.myorg:myconf\", self.options.myopt)',\n                                  'define(\"user.myorg:myconf\", self.settings.os)',\n                                  'append(\"user.myorg:myconf\", self.settings.os)',\n                                  'prepend(\"user.myorg:myconf\", self.settings.os)'])\ndef test_error_bad_types(conf):\n    c = TestClient(light=True)\n    conanfile = textwrap.dedent(f\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"tool\"\n            version = \"0.1\"\n            settings = \"os\"\n            options = {{\"myopt\": [True, False]}}\n            default_options = {{\"myopt\": True}}\n            def package_info(self):\n                self.conf_info.{conf}\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"create .\", assert_error=True)\n    assert \"ERROR: tool/0.1: Error in package_info() method, line 10\"\n    assert f'self.conf_info.{conf}' in c.out\n    assert \"Invalid 'conf' type, please use Python types (int, str, ...)\" in c.out\n\n\n@pytest.mark.parametrize(\"conf\", [\"tools.myorg.myconf\", \"user.myorg.myconf\"])\ndef test_error_missing_colon_define(conf):\n    c = TestClient(light=True)\n    conanfile = textwrap.dedent(f\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"tool\"\n            version = \"0.1\"\n            def package_info(self):\n                self.conf_info.define(\"{conf}\", 42)\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"create .\", assert_error=True)\n    assert \"ERROR: tool/0.1: Error in package_info() method:\" in c.out\n    if conf == \"tools.myorg.myconf\":\n        assert \"[conf] 'tools.myorg.myconf' does not exist in configuration\" in c.out\n    else:\n        assert f\"User conf '{conf}' invalid format, not 'user.org.group:conf'\" in c.out\n\n\ndef test_error_missing_colon_consume():\n    c = TestClient(light=True)\n    conanfile = textwrap.dedent(f\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            def generate(self):\n                self.conf.get(\"user.myorg.myconf\")\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"install .\", assert_error=True)\n    assert \"User conf 'user.myorg.myconf' invalid format, not 'user.org.group:conf'\" in c.out\n"
  },
  {
    "path": "test/integration/configuration/conf/test_conf_package_id.py",
    "content": "import json\nimport textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.fixture\ndef client():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Pkg(ConanFile):\n            def package_id(self):\n                self.info.conf.define(\"user.myconf:myitem\", self.conf.get(\"user.myconf:myitem\"))\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    return client\n\n\ndef test_package_id(client):\n    profile1 = textwrap.dedent(\"\"\"\\\n        [conf]\n        user.myconf:myitem=1\"\"\")\n    profile2 = textwrap.dedent(\"\"\"\\\n        [conf]\n        user.myconf:myitem=2\"\"\")\n    client.save({\"profile1\": profile1,\n                 \"profile2\": profile2})\n    client.run(\"create . --name=pkg --version=0.1 -pr=profile1\")\n    client.assert_listed_binary({\"pkg/0.1\": (\"7501c16e6c5c93e534dd760829859340e2dc73bc\", \"Build\")})\n    client.run(\"create . --name=pkg --version=0.1 -pr=profile2\")\n    client.assert_listed_binary({\"pkg/0.1\": (\"4eb2bd276f75d2df8fa0f4b58bd86014b7f51693\", \"Build\")})\n\n\ndef test_json_output(client):\n    client.run(\"create . --name=pkg --version=0.1 -c user.myconf:myitem=1 --format=json\")\n    graph = json.loads(client.stdout)\n    assert graph[\"graph\"][\"nodes\"][\"1\"][\"info\"][\"conf\"] == {'user.myconf:myitem': 1}\n"
  },
  {
    "path": "test/integration/configuration/conf/test_conf_profile.py",
    "content": "import textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.fixture\ndef client():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n\n        class Pkg(ConanFile):\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            generators = \"CMakeToolchain\"\n\n            def run(self, cmd, env=None, **kwargs):  # INTERCEPTOR of running\n                self.output.info(\"RECIPE-RUN: {}\".format(cmd))\n\n            def build(self):\n                cmake = CMake(self)\n                cmake.build()\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    return client\n\n\ndef test_cmake_no_config(client):\n    profile = textwrap.dedent(\"\"\"\\\n        [settings]\n        os=Windows\n        arch=x86_64\n        compiler=msvc\n        compiler.version=191\n        compiler.runtime=dynamic\n        build_type=Release\n        \"\"\")\n    client.save({\"myprofile\": profile})\n    client.run(\"create . --name=pkg --version=0.1 -pr=myprofile\")\n    assert \"-verbosity\" not in client.out\n\n\ndef test_cmake_config(client):\n    profile = textwrap.dedent(\"\"\"\\\n        [settings]\n        os=Windows\n        arch=x86_64\n        compiler=msvc\n        compiler.version=191\n        compiler.runtime=dynamic\n        build_type=Release\n        [conf]\n        tools.build:verbosity=quiet\n        \"\"\")\n    client.save({\"myprofile\": profile})\n    client.run(\"create . --name=pkg --version=0.1 -pr=myprofile\")\n    assert \"-verbosity:Quiet\" in client.out\n    client.run(\"create . --name=pkg --version=0.1 -pr=myprofile -c=tools.env.virtualenv:powershell=powershell.exe\")\n    assert \"/verbosity:Quiet\" in client.out\n\n\ndef test_cmake_config_error(client):\n    profile = textwrap.dedent(\"\"\"\\\n        [settings]\n        os=Windows\n        arch=x86_64\n        compiler=msvc\n        compiler.version=191\n        compiler.runtime=dynamic\n        build_type=Release\n        [conf]\n        tools.build:verbosity=non-existing\n        \"\"\")\n    client.save({\"myprofile\": profile})\n    client.run(\"create . --name=pkg --version=0.1 -pr=myprofile\", assert_error=True)\n    assert \"Unknown value 'non-existing' for 'tools.build:verbosity'\" in client.out\n\n\ndef test_cmake_config_package(client):\n    profile = textwrap.dedent(\"\"\"\\\n        [settings]\n        os=Windows\n        arch=x86_64\n        compiler=msvc\n        compiler.version=191\n        compiler.runtime=dynamic\n        build_type=Release\n        [conf]\n        dep*:tools.build:verbosity=quiet\n        \"\"\")\n    client.save({\"myprofile\": profile})\n    client.run(\"create . --name=pkg --version=0.1 -pr=myprofile\")\n    assert \"-verbosity\" not in client.out\n    client.run(\"create . --name=dep --version=0.1 -pr=myprofile\")\n    assert \"-verbosity:Quiet\" in client.out\n\n\ndef test_cmake_config_package_not_scoped(client):\n    profile = textwrap.dedent(\"\"\"\\\n        [settings]\n        os=Windows\n        arch=x86_64\n        compiler=msvc\n        compiler.version=191\n        compiler.runtime=dynamic\n        build_type=Release\n        [conf]\n        tools.build:verbosity=quiet\n        \"\"\")\n    client.save({\"myprofile\": profile})\n    client.run(\"create . --name=pkg --version=0.1 -pr=myprofile\")\n    assert \"-verbosity:Quiet\" in client.out\n    client.run(\"create . --name=dep --version=0.1 -pr=myprofile\")\n    assert \"-verbosity:Quiet\" in client.out\n\n\ndef test_config_profile_forbidden(client):\n    profile = textwrap.dedent(\"\"\"\\\n        [conf]\n        cache:verbosity=Minimal\n        \"\"\")\n    client.save({\"myprofile\": profile})\n    client.run(\"install . --name=pkg --version=0.1 -pr=myprofile\", assert_error=True)\n    assert (\"ERROR: Error reading 'myprofile' profile: [conf] \"\n            \"'cache:verbosity' not allowed in profiles\" in client.out)\n\n\ndef test_msbuild_config():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.microsoft import MSBuild\n\n        class Pkg(ConanFile):\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            def build(self):\n                ms = MSBuild(self)\n                self.output.info(ms.command(\"Project.sln\"))\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    profile = textwrap.dedent(\"\"\"\\\n        [settings]\n        os=Windows\n        arch=x86_64\n        compiler=msvc\n        compiler.version=191\n        compiler.runtime=dynamic\n        build_type=Release\n        [conf]\n        tools.build:verbosity=quiet\n        \"\"\")\n    client.save({\"myprofile\": profile})\n    client.run(\"create . --name=pkg --version=0.1 -pr=myprofile\")\n    assert \"-verbosity:Quiet\" in client.out\n\n\ndef test_msbuild_compile_options():\n    # This works in all platforms because MSBuildToolchain works even in Linux, it will\n    # just skip generating the conanvcvars.bat\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Pkg(ConanFile):\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            generators = \"MSBuildToolchain\"\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n\n    profile = textwrap.dedent(\"\"\"\\\n        [settings]\n        os=Windows\n        arch=x86_64\n        compiler=msvc\n        compiler.version=191\n        compiler.runtime=dynamic\n        build_type=Release\n        [conf]\n        tools.microsoft.msbuildtoolchain:compile_options={\"ExceptionHandling\": \"Async\"}\n        \"\"\")\n    client.save({\"myprofile\": profile})\n    client.run(\"install . -pr=myprofile\")\n    msbuild_tool = client.load(\"conantoolchain_release_x64.props\")\n    assert \"<ExceptionHandling>Async</ExceptionHandling>\" in msbuild_tool\n\n\ndef test_conf_package_patterns():\n    client = TestClient()\n    conanfile = GenConanfile()\n    generate = \"\"\"\n    def generate(self):\n        value = self.conf.get(\"user.build:myconfig\")\n        self.output.warning(\"{} Config:{}\".format(self.ref.name, value))\n\"\"\"\n    client.save({\"dep/conanfile.py\": str(conanfile) + generate,\n                 \"pkg/conanfile.py\": str(conanfile.with_requirement(\"dep/0.1\", visible=False)) + generate,\n                 \"consumer/conanfile.py\": str(conanfile.with_requires(\"pkg/0.1\")\n                .with_settings(\"os\", \"build_type\")) + generate})\n\n    client.run(\"export dep --name=dep --version=0.1\")\n    client.run(\"export pkg --name=pkg --version=0.1\")\n\n    # This pattern applies to no package\n    profile = \"\"\"\n    [settings]\n    os=Windows\n    [conf]\n    invented/*:user.build:myconfig=Foo\n    \"\"\"\n    client.save({\"profile\": profile})\n    client.run(\"install consumer --build=* --profile profile\")\n    assert \"WARN: dep Config:None\" in client.out\n    assert \"WARN: pkg Config:None\" in client.out\n    assert \"WARN: None Config:None\" in client.out\n\n    # This patterns applies to dep\n    profile = \"\"\"\n    [settings]\n    os=Windows\n    [conf]\n    dep/*:user.build:myconfig=Foo\n    \"\"\"\n    client.save({\"profile\": profile})\n    client.run(\"install consumer --build='*' --profile profile\")\n    assert \"WARN: dep Config:Foo\" in client.out\n    assert \"WARN: pkg Config:None\" in client.out\n    assert \"WARN: None Config:None\" in client.out\n\n    profile = \"\"\"\n    [settings]\n    os=Windows\n    [conf]\n    dep/0.1:user.build:myconfig=Foo\n    \"\"\"\n    client.save({\"profile\": profile})\n    client.run(\"install consumer --build='*' --profile profile\")\n    assert \"WARN: dep Config:Foo\" in client.out\n    assert \"WARN: pkg Config:None\" in client.out\n    assert \"WARN: None Config:None\" in client.out\n\n    # The global pattern applies to all\n    profile = \"\"\"\n    [settings]\n    os=Windows\n    [conf]\n    dep/*:user.build:myconfig=Foo\n    pkg/*:user.build:myconfig=Foo2\n    user.build:myconfig=Var\n    \"\"\"\n    client.save({\"profile\": profile})\n    client.run(\"install consumer --build='*' --profile profile\")\n    assert \"WARN: dep Config:Var\" in client.out\n    assert \"WARN: pkg Config:Var\" in client.out\n    assert \"WARN: None Config:Var\" in client.out\n\n    # \"&\" pattern for the consumer\n    profile = \"\"\"\n    [settings]\n    os=Windows\n    [conf]\n    dep/*:user.build:myconfig=Foo\n    pkg/*:user.build:myconfig=Foo2\n    &:user.build:myconfig=Var\n    \"\"\"\n\n    client.save({\"profile\": profile})\n    client.run(\"install consumer --build='*' --profile profile\")\n    assert \"WARN: dep Config:Foo\" in client.out\n    assert \"WARN: pkg Config:Foo2\" in client.out\n    assert \"WARN: None Config:Var\" in client.out\n\n\ndef test_config_package_append(client):\n    profile1 = textwrap.dedent(\"\"\"\\\n        [conf]\n        user.myteam:myconf=[\"a\", \"b\", \"c\"]\n        \"\"\")\n    profile2 = textwrap.dedent(\"\"\"\\\n        include(profile1)\n        [conf]\n        mypkg*:user.myteam:myconf+=[\"d\"]\n        mydep*:user.myteam:myconf=+[\"e\"]\n        \"\"\")\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            def generate(self):\n                self.output.info(f\"MYCONF: {self.conf.get('user.myteam:myconf')}\")\n            def build(self):\n                self.output.info(f\"MYCONFBUILD: {self.conf.get('user.myteam:myconf')}\")\n            \"\"\")\n    client.save({\"profile1\": profile1,\n                 \"profile2\": profile2,\n                 \"conanfile.py\": conanfile})\n    client.run(\"install . --name=mypkg --version=0.1 -pr=profile2\")\n    assert \"conanfile.py (mypkg/0.1): MYCONF: ['a', 'b', 'c', 'd']\" in client.out\n    client.run(\"install . --name=mydep --version=0.1 -pr=profile2\")\n    assert \"conanfile.py (mydep/0.1): MYCONF: ['e', 'a', 'b', 'c']\" in client.out\n\n    client.run(\"create . --name=mypkg --version=0.1 -pr=profile2\")\n    assert \"mypkg/0.1: MYCONFBUILD: ['a', 'b', 'c', 'd']\" in client.out\n    client.run(\"create . --name=mydep --version=0.1 -pr=profile2\")\n    assert \"mydep/0.1: MYCONFBUILD: ['e', 'a', 'b', 'c']\" in client.out\n\n\ndef test_conf_patterns_user_channel():\n    # https://github.com/conan-io/conan/issues/14139\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Pkg(ConanFile):\n            def configure(self):\n                self.output.info(f\"CONF: {self.conf.get('user.myteam:myconf')}\")\n                self.output.info(f\"CONF2: {self.conf.get('user.myteam:myconf2')}\")\n        \"\"\")\n    profile = textwrap.dedent(\"\"\"\\\n        [conf]\n        user.myteam:myconf=myvalue1\n        user.myteam:myconf2=other1\n        *@user/channel:user.myteam:myconf=myvalue2\n        *@*/*:user.myteam:myconf2=other2\n        \"\"\")\n    client.save({\"dep/conanfile.py\": conanfile,\n                 \"app/conanfile.py\": GenConanfile().with_requires(\"dep1/0.1\",\n                                                                  \"dep2/0.1@user/channel\"),\n                 \"profile\": profile})\n\n    client.run(\"create dep --name=dep1 --version=0.1\")\n    client.run(\"create dep --name=dep2 --version=0.1 --user=user --channel=channel\")\n    client.run(\"install app -pr=profile\")\n    assert \"dep1/0.1: CONF: myvalue1\" in client.out\n    assert \"dep2/0.1@user/channel: CONF: myvalue2\" in client.out\n    assert \"dep1/0.1: CONF2: other1\" in client.out\n    assert \"dep2/0.1@user/channel: CONF2: other2\" in client.out\n"
  },
  {
    "path": "test/integration/configuration/custom_setting_test_package_test.py",
    "content": "from conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import save\n\n\nclass TestConditionalReqsTest:\n\n    def test_conditional_requirements(self):\n        conanfile = GenConanfile(\"hello\", \"0.1\").with_settings(\"os\", \"build_type\", \"product\")\n\n        test_conanfile = '''\nfrom conan import ConanFile\n\nclass TestConanLib(ConanFile):\n    settings = \"os\", \"build_type\", \"product\"\n    def requirements(self):\n        self.output.info(\"TestSettings: %s, %s, %s\"\n                         % (self.settings.os, self.settings.build_type, self.settings.product))\n        self.requires(self.tested_reference_str)\n\n    def test(self):\n        pass\n'''\n        client = TestClient()\n        save(client.paths.settings_path_user, \"product: [onion, potato]\")\n        client.save({\"conanfile.py\": conanfile,\n                     \"test_package/conanfile.py\": test_conanfile})\n        client.run(\"create . -s os=Windows -s product=onion -s build_type=Release\")\n        assert \"hello/0.1 (test package): TestSettings: Windows, Release, onion\" in client.out\n"
  },
  {
    "path": "test/integration/configuration/default_profile_test.py",
    "content": "import os\nimport textwrap\n\nfrom conan.internal.paths import CONANFILE\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import NO_SETTINGS_PACKAGE_ID, TestClient\nfrom conan.test.utils.env import environment_update\nfrom conan.internal.util.files import save\n\n\nclass TestDefaultProfile:\n\n    def test_conanfile_txt_incomplete_profile(self):\n        conanfile = GenConanfile()\n\n        client = TestClient()\n\n        client.save({CONANFILE: conanfile})\n        client.run(\"create . --name=pkg --version=0.1 --user=lasote --channel=stable\")\n        assert \"pkg/0.1@lasote/stable: Package '%s' created\" % NO_SETTINGS_PACKAGE_ID in client.out\n\n        client.save({\"conanfile.txt\": \"[requires]\\npkg/0.1@lasote/stable\"}, clean_first=True)\n        client.run('install .')\n        assert \"pkg/0.1@lasote/stable: Already installed!\" in client.out\n\n    def test_change_default_profile(self):\n        br = '''\nimport os\nfrom conan import ConanFile\nfrom conan.tools.env import VirtualBuildEnv\n\nclass MyConanfile(ConanFile):\n    name = \"mylib\"\n    version = \"0.1\"\n\n    def build(self):\n        build_env = VirtualBuildEnv(self).vars()\n        with build_env.apply():\n            assert(os.environ.get(\"Value1\") == \"A\")\n'''\n        tmp = temp_folder()\n        default_profile_path = os.path.join(tmp, \"myprofile\")\n        save(default_profile_path, \"[buildenv]\\nValue1=A\")\n        client = TestClient()\n        client.save_home({\"global.conf\": \"core:default_profile={}\".format(default_profile_path)})\n\n        client.save({CONANFILE: br})\n        client.run(\"export . --user=lasote --channel=stable\")\n        client.run('install --requires=mylib/0.1@lasote/stable --build=\"*\"')\n\n        # Now use a name, in the default profile folder\n        os.unlink(default_profile_path)\n        save(os.path.join(client.paths.profiles_path, \"other\"), \"[buildenv]\\nValue1=A\")\n        client.save_home({\"global.conf\": \"core:default_profile=other\"})\n        client.save({CONANFILE: br})\n        client.run(\"export . --user=lasote --channel=stable\")\n        client.run('install --requires=mylib/0.1@lasote/stable --build=\"*\"')\n\n    def test_profile_applied_ok(self):\n        br = textwrap.dedent('''\n            from conan import ConanFile\n\n            class BuildRequireConanfile(ConanFile):\n                name = \"br\"\n                version = \"1.0\"\n\n                def package_info(self):\n                    self.buildenv_info.define(\"MyVAR\", \"from_build_require\")\n            ''')\n\n        cf = textwrap.dedent('''\n            import os, platform\n            from conan import ConanFile\n\n            class MyConanfile(ConanFile):\n                requires = \"br/1.0\"\n                def build(self):\n                    if platform.system() == \"Windows\":\n                        self.run(\"set MyVAR\")\n                    else:\n                        self.run(\"printenv MyVAR\")\n            ''')\n        client = TestClient()\n        client.save({\"br/conanfile.py\": br,\n                     \"consumer/conanfile.py\": cf,\n                     \"profile\": \"[buildenv]\\nMyVAR=23\"})\n        client.run(\"create br\")\n        client.run(\"build consumer\")\n        assert \"from_build_require\" in client.out\n        client.run(\"build consumer -pr=profile\")\n        assert \"23\" in client.out\n        assert \"from_build_require\" not in client.out\n\n    def test_env_default_profile(self):\n        conanfile = '''\nimport os\nfrom conan import ConanFile\nfrom conan.tools.env import VirtualBuildEnv\n\nclass MyConanfile(ConanFile):\n\n    def build(self):\n        build_env = VirtualBuildEnv(self).vars()\n        with build_env.apply():\n            self.output.info(\">>> env_variable={}\".format(os.environ.get('env_variable')))\n'''\n\n        client = TestClient()\n        client.save({CONANFILE: conanfile})\n\n        # Test with the 'default' profile\n        env_variable = \"env_variable=profile_default\"\n        client.save_home({\"profiles/default\": \"[settings]\\nos=Windows\\n[buildenv]\\n\" + env_variable})\n        client.run(\"create . --name=name --version=version --user=user --channel=channel\")\n        assert \">>> \" + env_variable in client.out\n\n        # Test with a profile set using and environment variable\n        tmp = temp_folder()\n        env_variable = \"env_variable=profile_environment\"\n        default_profile_path = os.path.join(tmp, 'env_profile')\n        save(default_profile_path, \"[settings]\\nos=Windows\\n[buildenv]\\n\" + env_variable)\n        with environment_update({'CONAN_DEFAULT_PROFILE': default_profile_path}):\n            client.run(\"create . --name=name --version=version --user=user --channel=channel\")\n            assert \">>> \" + env_variable in client.out\n\n        # Use relative path defined in environment variable\n        env_variable = \"env_variable=relative_profile\"\n        rel_path = os.path.join('..', 'env_rel_profile')\n        assert not os.path.isabs(rel_path)\n        default_profile_path = os.path.join(client.paths.profiles_path, rel_path)\n        save(default_profile_path, \"[settings]\\nos=Windows\\n[buildenv]\\n\" + env_variable)\n        with environment_update({'CONAN_DEFAULT_PROFILE': rel_path}):\n            client.run(\"create . --name=name --version=version --user=user --channel=channel\")\n            assert \">>> \" + env_variable in client.out\n\n        # Use non existing path\n        profile_path = os.path.join(tmp, \"this\", \"is\", \"a\", \"path\")\n        assert os.path.isabs(profile_path)\n        with environment_update({'CONAN_DEFAULT_PROFILE': profile_path}):\n            client.run(\"create . --name=name --version=version --user=user --channel=channel\",\n                       assert_error=True)\n            assert \"You need to create a default profile\" in client.out\n\n    def test_default_profile(self):\n        c = TestClient()\n        # Test with a profile set using and environment variable\n        tmp = temp_folder()\n        profile = os.path.join(tmp, 'myprofile')\n        save(profile, \"[settings]\\nos=FreeBSD\\n\")\n        with environment_update({'CONAN_DEFAULT_BUILD_PROFILE': profile}):\n            c.run(\"profile show\")\n            assert \"os=FreeBSD\" in c.out  # build profiles\n\n\ndef test_conf_default_two_profiles():\n    client = TestClient()\n    save(os.path.join(client.paths.profiles_path, \"mydefault\"), \"[settings]\\nos=FreeBSD\")\n    save(os.path.join(client.paths.profiles_path, \"mydefault_build\"), \"[settings]\\nos=Android\")\n    global_conf = textwrap.dedent(\"\"\"\n        core:default_profile=mydefault\n        core:default_build_profile=mydefault_build\n        \"\"\")\n    client.save_home({\"global.conf\": global_conf})\n    client.save({\"conanfile.txt\": \"\"})\n    client.run(\"install .\")\n    assert \"Profile host:\" in client.out\n    assert \"os=FreeBSD\" in client.out\n    assert \"Profile build:\" in client.out\n    assert \"os=Android\" in client.out\n"
  },
  {
    "path": "test/integration/configuration/invalid_settings_test.py",
    "content": "import os\nimport textwrap\n\n\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestSettingsLoad:\n    def test_invalid_settings(self):\n        client = TestClient()\n        client.save({os.path.join(client.cache_folder, 'settings.yml'): \"your buggy file\",\n                     \"conanfile.txt\": \"\"})\n        client.run(\"install .\", assert_error=True)\n        assert \"ERROR: Invalid settings.yml format: 'settings' is not a dictionary\" in client.out\n        client.save({os.path.join(client.cache_folder, 'settings.yml'): \"os:\\n    Windows: [1, ]\",\n                     \"conanfile.txt\": \"\"})\n        client.run(\"install .\", assert_error=True)\n        assert \"ERROR: Invalid settings.yml format: 'settings.os=Windows' is not a dictionary\" \\\n               in client.out\n\n    def test_invalid_yaml(self):\n        client = TestClient()\n        client.save({os.path.join(client.cache_folder, 'settings.yml'):\n                     textwrap.dedent(\"\"\"\n                        Almost:\n                            - a\n                            - valid\n                          yaml\n                     \"\"\"),\n                     \"conanfile.txt\": \"\"})\n        client.run(\"install .\", assert_error=True)\n        assert \"ERROR: Invalid settings.yml format: while parsing a block mapping\" in client.out\n"
  },
  {
    "path": "test/integration/configuration/profile_test.py",
    "content": "import json\nimport os\nimport platform\nimport textwrap\nfrom collections import OrderedDict\nfrom textwrap import dedent\n\nimport pytest\n\nfrom conan.internal.paths import CONANFILE\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.profiles import create_profile as _create_profile\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import load, save\n\nconanfile_scope_env = \"\"\"\nfrom conan import ConanFile\n\nclass AConan(ConanFile):\n    name = \"hello0\"\n    version = \"0.1\"\n    settings = \"os\", \"compiler\", \"arch\"\n\n    def build(self):\n        # Print environment vars\n        if self.settings.os == \"Windows\":\n            self.run(\"SET\")\n        else:\n            self.run(\"env\")\n\"\"\"\n\n\ndef create_profile(folder, name, settings=None, package_settings=None, options=None):\n    _create_profile(folder, name, settings, package_settings, options)\n    content = load(os.path.join(folder, name))\n    content = \"include(default)\\n    \\n\" + content\n    save(os.path.join(folder, name), content)\n\n\nclass TestProfile:\n\n    @pytest.fixture(autouse=True)\n    def setup(self):\n        self.client = TestClient()\n\n    def test_profile_relative_cwd(self):\n        self.client.save({\"conanfile.txt\": \"\", \"sub/sub/profile\": \"\"})\n        self.client.current_folder = os.path.join(self.client.current_folder, \"sub\")\n        self.client.run(\"install .. -pr=sub/profile2\", assert_error=True)\n        assert \"ERROR: Profile not found: sub/profile2\" in self.client.out\n        self.client.run(\"install .. -pr=sub/profile\")\n        assert \"Installing packages\" in self.client.out\n\n    def test_bad_syntax(self):\n        self.client.save({CONANFILE: conanfile_scope_env})\n        self.client.run(\"export . --user=lasote --channel=stable\")\n\n        profile = '''\n        [settings\n        '''\n        clang_profile_path = os.path.join(self.client.paths.profiles_path, \"clang\")\n        save(clang_profile_path, profile)\n        self.client.run(\"install --requires=hello0/0.1@lasote/stable --build missing -pr clang\",\n                        assert_error=True)\n        assert \"Error reading 'clang' profile\" in self.client.out\n        assert \"Bad syntax\" in self.client.out\n\n        profile = '''\n        [settings]\n        [invented]\n        '''\n        save(clang_profile_path, profile)\n        self.client.run(\"install --requires=hello0/0.1@lasote/stable --build missing -pr clang\",\n                        assert_error=True)\n        assert \"Unrecognized field 'invented'\" in self.client.out\n        assert \"Error reading 'clang' profile\" in self.client.out\n\n        profile = '''\n        [settings]\n        as\n        '''\n        save(clang_profile_path, profile)\n        self.client.run(\"install --requires=hello0/0.1@lasote/stable --build missing -pr clang\",\n                        assert_error=True)\n        assert \"Error reading 'clang' profile: Invalid setting line 'as'\" in self.client.out\n\n        profile = '''\n        [settings]\n        os =   a value\n        '''\n        save(clang_profile_path, profile)\n        self.client.run(\"install --requires=hello0/0.1@lasote/stable --build missing -pr clang\",\n                        assert_error=True)\n        # stripped \"a value\"\n        assert \"'a value' is not a valid 'settings.os'\" in self.client.out\n\n    @pytest.mark.parametrize(\"path\", [\"\", \"./local_profiles/\", None])\n    def test_install_with_missing_profile(self, path):\n        if path is None:\n            # Not good practice to introduce temp_folder() in the expand because it randomize\n            # the test names causing issues to split them in N processes\n            path = temp_folder() + \"/\"\n        self.client.save({CONANFILE: conanfile_scope_env})\n        self.client.run('install . -pr \"%sscopes_env\"' % path, assert_error=True)\n        assert \"ERROR: Profile not found:\" in self.client.out\n        assert \"scopes_env\" in self.client.out\n\n    @pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Windows profiles\")\n    def test_install_profile_settings(self):\n        # Create a profile and use it\n        profile_settings = OrderedDict([(\"compiler\", \"msvc\"),\n                                        (\"compiler.version\", \"191\"),\n                                        (\"compiler.runtime\", \"dynamic\"),\n                                        (\"arch\", \"x86\")])\n\n        create_profile(self.client.paths.profiles_path, \"vs_12_86\",\n                       settings=profile_settings, package_settings={})\n\n        self.client.save({\"conanfile.py\": conanfile_scope_env})\n        self.client.run(\"export . --user=lasote --channel=stable\")\n        self.client.run(\"install . --build missing -pr vs_12_86\")\n        info = self.client.out\n        for setting, value in profile_settings.items():\n            assert \"%s=%s\" % (setting, value) in info\n\n        # Try to override some settings in install command\n        self.client.run(\"install . --build missing -pr vs_12_86 -s compiler.version=191\")\n        info = self.client.out\n        for setting, value in profile_settings.items():\n            if setting != \"compiler.version\":\n                assert \"%s=%s\" % (setting, value) in info\n            else:\n                assert \"compiler.version=191\" in info\n\n        # Use package settings in profile\n        tmp_settings = OrderedDict()\n        tmp_settings[\"compiler\"] = \"gcc\"\n        tmp_settings[\"compiler.libcxx\"] = \"libstdc++11\"\n        tmp_settings[\"compiler.version\"] = \"4.8\"\n        package_settings = {\"hello0/*\": tmp_settings}\n        create_profile(self.client.paths.profiles_path,\n                       \"vs_12_86_hello0_gcc\", settings=profile_settings,\n                       package_settings=package_settings)\n        # Try to override some settings in install command\n        self.client.run(\"install . --build missing -pr vs_12_86_hello0_gcc -s compiler.version=191\")\n        info = self.client.out\n        assert \"compiler=gcc\" in info\n        assert \"compiler.libcxx=libstdc++11\" in info\n\n        # If other package is specified compiler is not modified\n        package_settings = {\"NoExistsRecipe\": tmp_settings}\n        create_profile(self.client.paths.profiles_path,\n                       \"vs_12_86_hello0_gcc\", settings=profile_settings,\n                       package_settings=package_settings)\n\n        # Mix command line package settings with profile\n        package_settings = {\"hello0/*\": tmp_settings}\n        create_profile(self.client.paths.profiles_path, \"vs_12_86_hello0_gcc\",\n                       settings=profile_settings, package_settings=package_settings)\n\n        # Try to override some settings in install command\n        self.client.run(\"install . --build missing -pr vs_12_86_hello0_gcc\"\n                        \" -s compiler.version=191 -s hello0/*:compiler.libcxx=libstdc++\")\n        info = self.client.out\n        assert \"compiler=gcc\" in info\n        assert \"compiler.libcxx=libstdc++11\" not in info\n        assert \"compiler.libcxx=libstdc++\" in info\n\n    def test_install_profile_package_settings(self):\n\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class HelloConan(ConanFile):\n                name = 'hello0'\n                version = '0.1'\n                settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n                def configure(self):\n                    self.output.info(self.settings.compiler)\n                    self.output.info(self.settings.compiler.version)\n            \"\"\")\n        self.client.save({\"conanfile.py\": conanfile})\n\n        # Create a profile and use it\n        profile_settings = OrderedDict([(\"os\", \"Windows\"),\n                                        (\"compiler\", \"msvc\"),\n                                        (\"compiler.version\", \"191\"),\n                                        (\"compiler.runtime\", \"dynamic\"),\n                                        (\"arch\", \"x86\")])\n\n        # Use package settings in profile\n        tmp_settings = OrderedDict()\n        tmp_settings[\"compiler\"] = \"gcc\"\n        tmp_settings[\"compiler.libcxx\"] = \"libstdc++11\"\n        tmp_settings[\"compiler.version\"] = \"4.8\"\n        package_settings = {\"*@lasote/*\": tmp_settings}\n        _create_profile(self.client.paths.profiles_path,\n                        \"myprofile\", settings=profile_settings,\n                        package_settings=package_settings)\n        # Try to override some settings in install command\n        self.client.run(\"install . --user=lasote --channel=testing -pr myprofile\")\n        info = self.client.out\n        assert \"(hello0/0.1@lasote/testing): gcc\" in info\n        assert \"(hello0/0.1@lasote/testing): 4.8\" in info\n\n        package_settings = {\"*@other/*\": tmp_settings}\n        _create_profile(self.client.paths.profiles_path,\n                        \"myprofile\", settings=profile_settings,\n                        package_settings=package_settings)\n        # Try to override some settings in install command\n        self.client.run(\"install . --user=lasote --channel=testing -pr myprofile\")\n        info = self.client.out\n        assert \"(hello0/0.1@lasote/testing): msvc\" in info\n        assert \"(hello0/0.1@lasote/testing): 191\" in info\n        assert \"(hello0/0.1@lasote/testing): gcc\" not in info\n        assert \"(hello0/0.1@lasote/testing): 4.8\" not in info\n\n    def test_package_settings_no_user_channel(self):\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                settings = \"os\"\n                def build(self):\n                    self.output.info(\"SETTINGS! os={}!!\".format(self.settings.os))\n                \"\"\")\n        profile = textwrap.dedent(\"\"\"\n            [settings]\n            os=Windows\n            # THIS FAILED BEFORE WITH NO MATCH\n            mypkg/0.1:os=Linux\n            mypkg/0.1@user/channel:os=FreeBSD\n            \"\"\")\n        client = TestClient()\n        client.save({\"conanfile.py\": conanfile,\n                     \"profile\": profile})\n\n        client.run(\"create . --name=mypkg --version=0.1 --user=user --channel=channel -pr=profile\")\n        assert \"mypkg/0.1@user/channel: SETTINGS! os=FreeBSD!!\" in client.out\n        client.run(\"create . --name=mypkg --version=0.1 -pr=profile\")\n        assert \"mypkg/0.1: SETTINGS! os=Linux!!\" in client.out\n\n    def test_install_profile_options(self):\n        create_profile(self.client.paths.profiles_path, \"vs_12_86\",\n                       options={\"hello0*:language\": 1,\n                                \"hello0*:static\": False})\n\n        self.client.save({\"conanfile.py\": GenConanfile(\"hello0\", \"1\").with_option(\"language\", [1, 2])\n                          .with_option(\"static\", [True, False])})\n        self.client.run(\"install . --build missing -pr vs_12_86\")\n        info = self.client.out\n        assert \"language=1\" in info\n        assert \"static=False\" in info\n\n    def test_scopes_env(self):\n        # Create a profile and use it\n        c = TestClient()\n        c.save({\"profile\": \"include(default)\\n[buildenv]\\nCXX=/path/tomy/g++\",\n                \"conanfile.py\": conanfile_scope_env})\n\n        c.run(\"build . -pr=profile\")\n        assert \"CXX=/path/tomy/g++\" in c.out\n\n        # The env variable shouldn't persist after install command\n        assert os.environ.get(\"CC\", None) != \"/path/tomy/gcc\"\n        assert os.environ.get(\"CXX\", None) != \"/path/tomy/g++\"\n\n    def test_info_with_profiles(self):\n\n        self.client.run(\"remove '*' -c\")\n        # Create a simple recipe to require\n        winreq_conanfile = '''\nfrom conan import ConanFile\n\nclass winrequireDefaultNameConan(ConanFile):\n    name = \"winrequire\"\n    version = \"0.1\"\n    settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n\n'''\n\n        files = {\"conanfile.py\": winreq_conanfile}\n        self.client.save(files)\n        self.client.run(\"export . --user=lasote --channel=stable\")\n\n        # Now require the first recipe depending on OS=windows\n        conanfile = '''from conan import ConanFile\nimport os\n\nclass DefaultNameConan(ConanFile):\n    name = \"hello\"\n    version = \"0.1\"\n    settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n\n    def requirements(self):\n        if self.settings.os == \"Windows\":\n            self.requires(\"winrequire/0.1@lasote/stable\")\n\n'''\n        files = {\"conanfile.py\": conanfile}\n        self.client.save(files)\n        self.client.run(\"export . --user=lasote --channel=stable\")\n\n        # Create a profile that doesn't activate the require\n        create_profile(self.client.paths.profiles_path, \"scopes_env\",\n                       settings={\"os\": \"Linux\"})\n\n        # Install with the previous profile\n        self.client.run(\"graph info --requires=hello/0.1@lasote/stable --profile scopes_env\")\n        assert '''Requires:\n                winrequire/0.1@lasote/stable''' not in self.client.out\n\n        # Create a profile that activate the require\n        create_profile(self.client.paths.profiles_path, \"scopes_env\",\n                       settings={\"os\": \"Windows\"})\n\n        # Install with the previous profile\n        self.client.run(\"graph info --requires=hello/0.1@lasote/stable --profile scopes_env\")\n        assert ' winrequire/0.1@lasote/stable' in self.client.out\n\n\nclass TestProfileAggregation:\n\n    profile1 = dedent(\"\"\"\n    [settings]\n    os=Windows\n    arch=x86_64\n    \"\"\")\n\n    profile2 = dedent(\"\"\"\n    [settings]\n    arch=x86\n    build_type=Debug\n    compiler=msvc\n    compiler.version=191\n    compiler.runtime=dynamic\n    \"\"\")\n\n    conanfile = dedent(\"\"\"\n    from conan import ConanFile\n    import os\n\n    class DefaultNameConan(ConanFile):\n        settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n\n        def build(self):\n            self.output.warning(\"ENV1:%s\" % os.getenv(\"ENV1\"))\n            self.output.warning(\"ENV2:%s\" % os.getenv(\"ENV2\"))\n            self.output.warning(\"ENV3:%s\" % os.getenv(\"ENV3\"))\n    \"\"\")\n\n    consumer = dedent(\"\"\"\n    from conan import ConanFile\n    import os\n\n    class DefaultNameConan(ConanFile):\n        settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n        requires = \"lib/1.0@user/channel\"\n    \"\"\")\n\n    @pytest.fixture(autouse=True)\n    def setup(self):\n        self.client = TestClient()\n        self.client.save({CONANFILE: self.conanfile,\n                          \"profile1\": self.profile1, \"profile2\": self.profile2})\n        self._pkg_lib_10_id = \"9b7f1e80c96289e8d9a3e7ded02830525090d5d4\"\n\n    def test_info(self):\n        # The latest declared profile has priority\n        self.client.run(\"create . --name=lib --version=1.0 --user=user --channel=channel --profile profile1 -pr profile2\")\n\n        self.client.save({CONANFILE: self.consumer})\n        self.client.run(\"graph info . --profile profile1 --profile profile2\")\n        assert self._pkg_lib_10_id in self.client.out\n\n    def test_export_pkg(self):\n        self.client.run(\"export-pkg . --name=lib --version=1.0 --user=user --channel=channel -pr profile1 -pr profile2\")\n        # ID for the expected settings applied: x86, Visual Studio 15,...\n        assert self._pkg_lib_10_id in self.client.out\n\n    def test_profile_crazy_inheritance(self):\n        profile1 = dedent(\"\"\"\n            [settings]\n            os=Windows\n            arch=x86_64\n            compiler=msvc\n            compiler.version=191\n            compiler.runtime=dynamic\n            \"\"\")\n\n        profile2 = dedent(\"\"\"\n            include(profile1)\n            [settings]\n            os=Linux\n            \"\"\")\n\n        self.client.save({\"profile1\": profile1, \"profile2\": profile2})\n        self.client.run(\"create . --name=lib --version=1.0 --profile profile2 -pr profile1\")\n        assert dedent(\"\"\"\\\n                             [settings]\n                             arch=x86_64\n                             compiler=msvc\n                             compiler.runtime=dynamic\n                             compiler.runtime_type=Release\n                             compiler.version=191\n                             os=Windows\"\"\") in self.client.out\n\n\ndef test_profile_from_cache_path():\n    \"\"\" When passing relative folder/profile as profile file, it MUST be used\n        conan install . -pr=profiles/default\n        /tmp/profiles/default MUST be consumed as target profile\n        https://github.com/conan-io/conan/pull/8685\n    \"\"\"\n    client = TestClient()\n    path = os.path.join(client.paths.profiles_path, \"android\", \"profile1\")\n    save(path, \"[settings]\\nos=Android\")\n    client.save({\"conanfile.txt\": \"\"})\n    client.run(\"install . -pr=android/profile1\")\n    assert \"os=Android\" in client.out\n\n\ndef test_profile_from_relative_pardir():\n    \"\"\" When passing relative ../path as profile file, it MUST be used\n        conan install . -pr=../profiles/default\n        /tmp/profiles/default MUST be consumed as target profile\n    \"\"\"\n    client = TestClient()\n    client.save({\"profiles/default\": \"[settings]\\nos=AIX\",\n                 \"current/conanfile.txt\": \"\"})\n    with client.chdir(\"current\"):\n        client.run(\"install . -pr=../profiles/default\")\n    assert \"os=AIX\" in client.out\n\n\ndef test_profile_from_relative_dotdir():\n    \"\"\" When passing relative ./path as profile file, it MUST be used\n        conan install . -pr=./profiles/default\n        /tmp/profiles/default MUST be consumed as target profile\n    \"\"\"\n    client = TestClient()\n    client.save({os.path.join(\"profiles\", \"default\"): \"[settings]\\nos=AIX\",\n                 os.path.join(\"current\", \"conanfile.txt\"): \"\"})\n    client.run(\"install ./current -pr=./profiles/default\")\n    assert \"os=AIX\" in client.out\n\n\ndef test_profile_from_temp_absolute_path():\n    \"\"\" When passing absolute path as profile file, it MUST be used\n        conan install . -pr=/tmp/profiles/default\n        /tmp/profiles/default MUST be consumed as target profile\n    \"\"\"\n    client = TestClient()\n    client.save({\"profiles/default\": \"[settings]\\nos=AIX\",\n                 \"current/conanfile.txt\": \"\"})\n    profile_path = os.path.join(client.current_folder, \"profiles\", \"default\")\n    recipe_path = os.path.join(client.current_folder, \"current\", \"conanfile.txt\")\n    client.run('install \"{}\" -pr=\"{}\"'.format(recipe_path, profile_path))\n    assert \"os=AIX\" in client.out\n\n\ndef test_consumer_specific_settings():\n    client = TestClient()\n    dep = str(GenConanfile().with_settings(\"build_type\").with_option(\"shared\", [True, False])\n              .with_default_option(\"shared\", False))\n    configure = \"\"\"\n    def configure(self):\n        self.output.warning(\"I'm {} and my build type is {}\".format(self.name,\n                                                                 self.settings.build_type))\n        self.output.warning(\"I'm {} and my shared is {}\".format(self.name, self.options.shared))\n    \"\"\"\n    dep += configure\n    client.save({\"conanfile.py\": dep})\n    client.run(\"create . --name=dep --version=1.0\")\n    client.run(\"create . --name=dep --version=1.0 -s build_type=Debug -o dep*:shared=True\")\n\n    consumer = str(GenConanfile().with_settings(\"build_type\").with_requires(\"dep/1.0\")\n                   .with_option(\"shared\", [True, False]).with_default_option(\"shared\", False))\n    consumer += configure\n    client.save({\"conanfile.py\": consumer})\n\n    # Regular install with release\n    client.run(\"install . -s build_type=Release\")\n    assert \"I'm dep and my build type is Release\" in client.out\n    assert \"I'm None and my build type is Release\" in client.out\n    assert \"I'm dep and my shared is False\" in client.out\n    assert \"I'm None and my shared is False\" in client.out\n\n    # Now the dependency by name\n    client.run(\"install . -s dep/*:build_type=Debug -o dep/*:shared=True\")\n    assert \"I'm dep and my build type is Debug\" in client.out\n    assert \"I'm None and my build type is Release\" in client.out\n    assert \"I'm dep and my shared is True\" in client.out\n    assert \"I'm None and my shared is False\" in client.out\n\n    # Now the consumer using &\n    client.run(\"install . -s &:build_type=Debug -o shared=True\")\n    assert \"I'm dep and my build type is Release\" in client.out\n    assert \"I'm None and my build type is Debug\" in client.out\n    assert \"I'm dep and my shared is False\" in client.out\n    assert \"I'm None and my shared is True\" in client.out\n\n    # Now use a conanfile.txt\n    client.save({\"conanfile.txt\": textwrap.dedent(\"\"\"\n            [requires]\n            dep/1.0\n    \"\"\")}, clean_first=True)\n\n    # Regular install with release\n    client.run(\"install . -s build_type=Release\")\n    assert \"I'm dep and my build type is Release\" in client.out\n\n    # Now the dependency by name\n    client.run(\"install . -s dep*:build_type=Debug -o dep*:shared=True\")\n    assert \"I'm dep and my build type is Debug\" in client.out\n    assert \"I'm dep and my shared is True\" in client.out\n\n    # Test that the generators take the setting\n    if platform.system() != \"Windows\":  # Toolchain in windows is multiconfig\n        # Now the consumer using &\n        client.run(\"install . -s &:build_type=Debug -g CMakeToolchain\")\n        assert \"I'm dep and my build type is Release\" in client.out\n        # Verify the cmake toolchain takes Debug\n        assert \"I'm dep and my shared is False\" in client.out\n        presets = json.loads(client.load(\"CMakePresets.json\"))\n        assert presets[\"configurePresets\"][0][\"cacheVariables\"]['CMAKE_BUILD_TYPE'] == \"Debug\"\n\n\ndef test_create_and_priority_of_consumer_specific_setting():\n    client = TestClient()\n    conanfile = str(GenConanfile().with_settings(\"build_type\").with_name(\"foo\").with_version(\"1.0\"))\n    configure = \"\"\"\n    def configure(self):\n        self.output.warning(\"I'm {} and my build type is {}\".format(self.name,\n                                                                 self.settings.build_type))\n    \"\"\"\n    conanfile += configure\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . -s foo*:build_type=Debug\")\n    assert \"I'm foo and my build type is Debug\" in client.out\n\n    client.run(\"create . -s foo*:build_type=Debug -s &:build_type=Release\")\n    assert \"I'm foo and my build type is Release\" in client.out\n\n    # The order DOES matter\n    client.run(\"create . -s &:build_type=Release -s foo*:build_type=Debug \")\n    assert \"I'm foo and my build type is Debug\" in client.out\n\n    # With test_package also works\n    test = str(GenConanfile().with_test(\"pass\").with_setting(\"build_type\"))\n    test += configure\n    client.save({\"test_package/conanfile.py\": test})\n    client.run(\"create . -s &:build_type=Debug -s build_type=Release\")\n    assert \"I'm foo and my build type is Debug\" in client.out\n    # the test package recipe has debug too\n    assert \"I'm None and my build type is Debug\" in client.out\n\n\ndef test_package_consumer_is_only_the_tested_one():\n    \"\"\"\n    the &:xxx pattern applies only to the package being tested, not other requires\n    \"\"\"\n    c = TestClient(light=True)\n    test = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Tool(ConanFile):\n            def requirements(self):\n                self.requires(self.tested_reference_str)\n                self.requires(\"dep/1.0\")\n\n            def test(self):\n                pass\n        \"\"\")\n    c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"1.0\"),\n            \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_option(\"myoption\", [1, 2]),\n            \"pkg/test_package/conanfile.py\": test})\n    c.run(\"create dep\")\n    c.run(\"create pkg -o &:myoption=1\")\n    # This would crash if myoption is applied to dep\n    assert 'pkg/0.1 (test package): Running test()' in c.out\n\n\ndef test_consumer_specific_settings_from_profile():\n    client = TestClient()\n    conanfile = str(GenConanfile().with_settings(\"build_type\").with_name(\"hello\"))\n    configure = \"\"\"\n    def configure(self):\n        self.output.warning(\"I'm {} and my build type is {}\".format(self.name,\n                                                                 self.settings.build_type))\n    \"\"\"\n    conanfile += configure\n    profile = textwrap.dedent(\"\"\"\n        include(default)\n        [settings]\n        &:build_type=Debug\n    \"\"\")\n    client.save({\"conanfile.py\": conanfile, \"my_profile.txt\": profile})\n    client.run(\"install . --profile my_profile.txt\")\n    assert \"I'm hello and my build type is Debug\" in client.out\n\n\ndef test_consumer_invalid_profile_multiple_groups():\n    \"\"\"\n    Issue related: https://github.com/conan-io/conan/issues/16448\n    \"\"\"\n    client = TestClient()\n    conanfile = GenConanfile(name=\"hello\", version=\"1.0\").with_settings(\"os\", \"arch\",\n                                                                        \"build_type\", \"compiler\")\n    prof1 = textwrap.dedent(\"\"\"\\\n    [settings]\n    arch=x86_64\n    os=Linux\n    build_type=Release\n    compiler=clang\n    compiler.libcxx=libstdc++11\n    compiler.version=18\n    compiler.cppstd=20\n\n    [conf]\n    tools.build:compiler_executables={'c': '/usr/bin/clang-18', 'cpp': '/usr/bin/clang++-18'}\n\n    [settings]\n    # Empty and duplicated section\n\n    [options]\n    package/*:option=Whatever\n\n    [conf]\n    # Another one\n    \"\"\")\n    client.save({\n        \"conanfile.py\": conanfile,\n        \"myprofs/myprofile\": prof1\n    })\n    client.run(\"build . --profile:host myprofs/myprofile -g CMakeToolchain\",\n               assert_error=True)\n    assert (\"ERROR: Error reading 'myprofs/myprofile' profile: ConfigParser: \"\n            \"Duplicated section: [settings]\") in client.out\n\n\ndef test_compose_numeric_values_scoped_pkg():\n    tc = TestClient(light=True)\n    tc.save({\"conanfile.py\": GenConanfile(\"hello\", \"0.1\")\n                .with_package(\"self.output.info('user.var.value: ' + str(self.conf.get('user.var:value')))\"),\n             \"profile\": \"\"\"[conf]\\nuser.var:value=8.1\\nhello/*:user.var:value=10\\n\"\"\"})\n\n    tc.run(\"create . -pr=profile\")\n    assert \"user.var.value: 10\" in tc.out\n\n\ndef test_nullify_settings():\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            settings = \"build_type\"\n            def configure(self):\n                if not self.settings.build_type:\n                    self.output.info(\"BUILD TYPE NOT DEFINED!!!\")\n                else:\n                    self.output.info(f\"I am a {self.settings.build_type} pkg!!!\")\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile,\n            \"profile\": \"[settings]\\nbuild_type=Release\\npkg1/*:build_type=~\"})\n    c.run(\"create . --name=pkg1 --version=0.1\")\n    c.run(\"create . --name=pkg2 --version=0.1\")\n    c.run(\"create . --name=pkg3 --version=0.1\")\n    c.save({\"conanfile.py\": GenConanfile().with_requires(\"pkg1/0.1\", \"pkg2/0.1\", \"pkg3/0.1\")})\n\n    c.run(\"graph info . -s build_type=Release -s pkg1/*:build_type=~\")\n    assert \"pkg1/0.1: BUILD TYPE NOT DEFINED!!!\" in c.out\n    assert \"pkg2/0.1: I am a Release pkg!!!\" in c.out\n    assert \"pkg3/0.1: I am a Release pkg!!!\" in c.out\n\n    c.run(\"graph info . -pr=profile\")\n    assert \"pkg1/0.1: BUILD TYPE NOT DEFINED!!!\" in c.out\n    assert \"pkg2/0.1: I am a Release pkg!!!\" in c.out\n    assert \"pkg3/0.1: I am a Release pkg!!!\" in c.out\n"
  },
  {
    "path": "test/integration/configuration/proxies_conf_test.py",
    "content": "import os\nimport textwrap\n\nfrom requests import Response\n\nfrom conan.test.utils.tools import TestClient, TestRequester\nfrom conan.test.utils.env import environment_update\n\n\nclass TestProxiesConfTest:\n\n    def test_requester_with_host_specific_proxies(self):\n        class MyHttpRequester(TestRequester):\n\n            def get(self, _, **kwargs):\n                resp = Response()\n                # resp._content = b'{\"results\": []}'\n                resp.status_code = 200\n                resp._content = b''\n                print(kwargs[\"proxies\"])\n                return resp\n\n        client = TestClient(requester_class=MyHttpRequester)\n        client.save_home({\"global.conf\": 'core.net.http:proxies = {\"myproxykey\": \"myvalue\"}'})\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import download\n\n            class Pkg(ConanFile):\n                settings = \"os\", \"compiler\"\n\n                def source(self):\n                    download(self, \"MyUrl\", \"filename.txt\")\n        \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --name=foo --version=1.0\")\n        assert \"{'myproxykey': 'myvalue'}\" in client.out\n\n    def test_new_proxy_exclude(self):\n\n        class MyHttpRequester(TestRequester):\n\n            def get(self, _, **kwargs):\n                resp = Response()\n                # resp._content = b'{\"results\": []}'\n                resp.status_code = 200\n                resp._content = b''\n                print(\"is excluded!\" if \"proxies\" not in kwargs else \"is not excluded!\")\n                return resp\n\n        client = TestClient(requester_class=MyHttpRequester)\n        client.save_home({\"global.conf\":\n             'core.net.http:no_proxy_match = [\"MyExcludedUrl*\", \"*otherexcluded_one*\"]\\n'\n             'core.net.http:proxies = {\"http\": \"value\"}'})\n        for url in (\"**otherexcluded_one***\", \"MyUrl\", \"MyExcludedUrl***\", \"**MyExcludedUrl***\"):\n            conanfile = textwrap.dedent(\"\"\"\n                from conan import ConanFile\n                from conan.tools.files import download\n\n                class Pkg(ConanFile):\n                  settings = \"os\", \"compiler\"\n\n                  def source(self):\n                      download(self, \"{}\", \"filename.txt\")\n                \"\"\").format(url)\n            client.save({\"conanfile.py\": conanfile})\n            client.run(\"create . --name=foo --version=1.0\")\n            if url in (\"MyUrl\", \"**MyExcludedUrl***\"):\n                assert \"is not excluded!\" in client.out\n            else:\n                assert \"is excluded!\" in client.out\n\n    def test_environ_kept(self):\n\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import download\n\n            class Pkg(ConanFile):\n                settings = \"os\", \"compiler\"\n\n                def source(self):\n                    download(self, \"http://foo.bar/file\", \"filename.txt\")\n            \"\"\")\n\n        class MyHttpRequester(TestRequester):\n\n            def get(self, _, **kwargs):\n                resp = Response()\n                # resp._content = b'{\"results\": []}'\n                resp.status_code = 200\n                resp._content = b''\n                assert \"HTTP_PROXY\" in os.environ\n                print(\"My requester!\")\n                return resp\n\n        client = TestClient(requester_class=MyHttpRequester)\n        client.save({\"conanfile.py\": conanfile})\n\n        with environment_update({\"HTTP_PROXY\": \"my_system_proxy\"}):\n            client.run(\"create . --name=foo --version=1.0\")\n\n        assert \"My requester!\" in client.out\n\n    def test_environ_removed(self):\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import download\n\n            class Pkg(ConanFile):\n                settings = \"os\", \"compiler\"\n\n                def source(self):\n                    download(self, \"http://MyExcludedUrl/file\", \"filename.txt\")\n            \"\"\")\n\n        class MyHttpRequester(TestRequester):\n\n            def get(self, _, **kwargs):\n                resp = Response()\n                # resp._content = b'{\"results\": []}'\n                resp.status_code = 200\n                resp._content = b''\n                assert \"HTTP_PROXY\" not in os.environ\n                assert \"http_proxy\" not in os.environ\n                print(\"My requester!\")\n                return resp\n\n        client = TestClient(requester_class=MyHttpRequester)\n        client.save_home({\"global.conf\": 'core.net.http:clean_system_proxy = True'})\n\n        with environment_update({\"http_proxy\": \"my_system_proxy\"}):\n            client.save({\"conanfile.py\": conanfile})\n            client.run(\"create . --name=foo --version=1.0\")\n            assert \"My requester!\" in client.out\n"
  },
  {
    "path": "test/integration/configuration/requester_test.py",
    "content": "import os\n\nfrom unittest import mock\nfrom unittest.mock import Mock, MagicMock\n\nfrom conan import __version__\nfrom conan.internal.rest.conan_requester import ConanRequester\nfrom conan.internal.model.conf import ConfDefinition\nfrom conan.test.utils.tools import temp_folder\nfrom conan.internal.util.files import save\n\n\nclass MockRequesterGet(Mock):\n    verify = None\n\n    def get(self, _, **kwargs):\n        self.verify = kwargs.get('verify', None)\n\n\nclass TestConanRequesterCacertPath:\n    def test_default_no_verify(self):\n        mocked_requester = MockRequesterGet()\n        with mock.patch(\"conan.internal.rest.conan_requester.requests\", mocked_requester):\n            requester = ConanRequester(ConfDefinition())\n            requester.get(url=\"aaa\", verify=False)\n            assert requester._http_requester.verify is False\n\n    def test_default_verify(self):\n        mocked_requester = MockRequesterGet()\n        with mock.patch(\"conan.internal.rest.conan_requester.requests\", mocked_requester):\n            requester = ConanRequester(ConfDefinition())\n            requester.get(url=\"aaa\", verify=True)\n            assert requester._http_requester.verify is True\n\n    def test_cache_config(self):\n        file_path = os.path.join(temp_folder(), \"whatever_cacert\")\n        save(file_path, \"\")\n        config = ConfDefinition()\n        config.update(\"core.net.http:cacert_path\", file_path)\n        mocked_requester = MockRequesterGet()\n        with mock.patch(\"conan.internal.rest.conan_requester.requests\", mocked_requester):\n            requester = ConanRequester(config)\n            requester.get(url=\"bbbb\", verify=True)\n        assert requester._http_requester.verify == file_path\n\n\nclass TestConanRequesterHeaders:\n    def test_user_agent(self):\n        mock_http_requester = MagicMock()\n        with mock.patch(\"conan.internal.rest.conan_requester.requests\", mock_http_requester):\n            requester = ConanRequester(ConfDefinition())\n            requester.get(url=\"aaa\")\n            headers = requester._http_requester.get.call_args[1][\"headers\"]\n            assert \"Conan/%s\" % __version__ in headers[\"User-Agent\"]\n\n            requester.get(url=\"aaa\", headers={\"User-Agent\": \"MyUserAgent\"})\n            headers = requester._http_requester.get.call_args[1][\"headers\"]\n            assert \"MyUserAgent\" == headers[\"User-Agent\"]\n"
  },
  {
    "path": "test/integration/configuration/required_version_test.py",
    "content": "import os\nfrom unittest import mock\n\nfrom conan import __version__\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import save\n\n\nclass TestRequiredVersion:\n\n    @mock.patch(\"conan.__version__\", \"1.26.0\")\n    def test_wrong_version(self):\n        required_version = \"1.23.0\"\n        client = TestClient(light=True)\n        client.save_home({\"global.conf\": f\"core:required_conan_version={required_version}\"})\n        client.run(\"help\", assert_error=True)\n        assert (\"Current Conan version (1.26.0) does not satisfy the defined \"\n                f\"one ({required_version})\") in client.out\n\n    @mock.patch(\"conan.__version__\", \"1.22.0\")\n    def test_exact_version(self):\n        required_version = \"1.22.0\"\n        client = TestClient(light=True)\n        client.save_home({\"global.conf\": f\"core:required_conan_version={required_version}\"})\n        client.run(\"--help\")\n\n    @mock.patch(\"conan.__version__\", \"2.1.0\")\n    def test_lesser_version(self):\n        required_version = \"<3.0\"\n        client = TestClient(light=True)\n        client.save_home({\"global.conf\": f\"core:required_conan_version={required_version}\"})\n        client.run(\"--help\")\n\n    @mock.patch(\"conan.__version__\", \"2.20.0\")\n    def test_lesser_version_error_parse(self):\n        required_version = \"2.20\"\n        client = TestClient(light=True)\n        client.save_home({\"global.conf\": f\"core:required_conan_version={required_version}\"})\n        client.run(\"--help\")\n\n    @mock.patch(\"conan.__version__\", \"1.0.0\")\n    def test_greater_version(self):\n        required_version = \">0.1.0\"\n        client = TestClient(light=True)\n        client.save_home({\"global.conf\": f\"core:required_conan_version={required_version}\"})\n        client.run(\"--help\")\n\n    @mock.patch(\"conan.__version__\", \"1.0.0\")\n    def test_greater_version_cc_override(self):\n        client = TestClient(light=True)\n        client.save_home({\"global.conf\": f\"core:required_conan_version=>0.1.0\"})\n        client.run(\"config home -cc core:required_conan_version=>2.0\", assert_error=True)\n        assert f\"Current Conan version (1.0.0) does not satisfy the defined one (>2.0)\" in client.out\n\n    @mock.patch(\"conan.__version__\", \"1.0.0\")\n    def test_version_check_before_hooks(self):\n        client = TestClient(light=True)\n        client.save_home({\"global.conf\": f\"core:required_conan_version=>2.0\",\n                          # The hook shouldn't matter, version check happens earlier\n                          \"extensions/hooks/hook_trim.py\": \"some error here\"})\n        client.run(\"config home\", assert_error=True)\n        assert f\"Current Conan version (1.0.0) does not satisfy the defined one (>2.0)\" in client.out\n\n    def test_bad_format(self):\n        required_version = \"1.0.0.0-foobar\"\n        cache_folder = temp_folder()\n        save(os.path.join(cache_folder, \"global.conf\"),\n             f\"core:required_conan_version={required_version}\")\n        c = TestClient(cache_folder, light=True)\n        c.run(\"version\", assert_error=True)\n        assert (f\"Current Conan version ({__version__}) does not satisfy \"\n                f\"the defined one ({required_version})\") in c.out\n"
  },
  {
    "path": "test/integration/configuration/test_auth_remote_plugin.py",
    "content": "import textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestAuthRemotePlugin:\n\n    def test_error_auth_remote_plugin(self):\n        \"\"\" Test when the plugin fails, we want a clear message and a helpful trace\n        \"\"\"\n        c = TestClient(default_server_user=True)\n        auth_plugin = textwrap.dedent(\"\"\"\\\n            def auth_remote_plugin(remote, user=None):\n                raise Exception(\"Test Error\")\n            \"\"\")\n        c.save_home({\"extensions/plugins/auth_remote.py\": auth_plugin})\n        c.run(\"remote logout default\")\n        c.run(\"remote login default\", assert_error=True)\n        assert \"Error while processing 'auth_remote.py' plugin\" in c.out\n        assert \"ERROR: Error while processing 'auth_remote.py' plugin, line \" in c.out\n\n    @pytest.mark.parametrize(\"password\", [\"password\", \"bad-password\"])\n    def test_auth_remote_plugin_direct_credentials(self, password):\n        \"\"\" Test when the plugin give a correct and wrong password, we want a message about\n        the success or fail in login\n        \"\"\"\n        should_fail = password == \"bad-password\"\n        c = TestClient(default_server_user=True)\n        auth_plugin = textwrap.dedent(f\"\"\"\\\n            def auth_remote_plugin(remote, user=None):\n                return \"admin\", \"{password}\"\n            \"\"\")\n        c.save_home({\"extensions/plugins/auth_remote.py\": auth_plugin})\n        c.run(\"remote logout default\")\n        c.run(\"remote login default\", assert_error=should_fail)\n        if should_fail:\n            assert \"ERROR: Wrong user or password. [Remote: default]\" in c.out\n        else:\n            assert (\"Changed user of remote 'default' from 'None' (anonymous) to \"\n                    \"'admin' (authenticated)\") in c.out\n\n    def test_auth_remote_plugin_fallback(self):\n        \"\"\" Test when the plugin do not give any user or password, we want the code to continue with\n            the rest of the input methods\n        \"\"\"\n        c = TestClient(default_server_user=True)\n        auth_plugin = textwrap.dedent(\"\"\"\\\n                def auth_remote_plugin(remote, user=None):\n                    return None, None\n                \"\"\")\n        c.save_home({\"extensions/plugins/auth_remote.py\": auth_plugin})\n        c.run(\"remote logout default\")\n        c.run(\"remote login default\")\n        # As the auth plugin is not returning any password the code is falling back to the rest of\n        # the input methods in this case the stdin provided by TestClient.\n        assert (\"Changed user of remote 'default' from 'None' (anonymous) to \"\n                \"'admin' (authenticated)\") in c.out\n"
  },
  {
    "path": "test/integration/configuration/test_custom_symlinked_home.py",
    "content": "import os\nimport platform\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient, NO_SETTINGS_PACKAGE_ID\n\n\n@pytest.mark.skipif(platform.system() == \"Windows\", reason=\"Uses symlinks\")\ndef test_custom_symlinked_home():\n    base_cache = temp_folder()\n    real_cache = os.path.join(base_cache, \"real_cache\")\n    os.makedirs(real_cache)\n    symlink_cache = os.path.join(base_cache, \"symlink_cache\")\n    os.symlink(real_cache, symlink_cache)\n    c = TestClient(cache_folder=symlink_cache)\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n    c.run(\"create .\")\n    assert \"symlink_cache\" in c.out\n    assert \"real_cache\" not in c.out\n    c.run(\"cache path pkg/0.1\")\n    assert \"symlink_cache\" in c.out\n    assert \"real_cache\" not in c.out\n    c.run(f\"cache path pkg/0.1:{NO_SETTINGS_PACKAGE_ID}\")\n    assert \"symlink_cache\" in c.out\n    assert \"real_cache\" not in c.out\n"
  },
  {
    "path": "test/integration/configuration/test_profile_jinja.py",
    "content": "import json\nimport platform\nimport textwrap\nimport os\n\nfrom conan import conan_version\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\nfrom conan.test.utils.env import environment_update\n\n\ndef test_profile_template():\n    client = TestClient()\n    tpl = textwrap.dedent(\"\"\"\\\n        # This is just to check that subprocess is injected in the render and can be used\n        {% set check_output = subprocess.check_output %}\n        [settings]\n        os = {{ {\"Darwin\": \"Macos\"}.get(platform.system(), platform.system()) }}\n        build_type = {{ os.getenv(\"MY_BUILD_TYPE\") }}\n        \"\"\")\n    client.save({\"conanfile.py\": GenConanfile(),\n                 \"profile1\": tpl})\n    with environment_update({\"MY_BUILD_TYPE\": \"Debug\"}):\n        client.run(\"install . -pr=profile1\")\n\n    current_os = {\"Darwin\": \"Macos\"}.get(platform.system(), platform.system())\n    assert \"os={}\".format(current_os)\n    assert \"build_type=Debug\"\n\n\ndef test_profile_template_variables():\n    client = TestClient()\n    tpl = textwrap.dedent(\"\"\"\n        {% set a = \"FreeBSD\" %}\n        [settings]\n        os = {{ a }}\n        \"\"\")\n    client.save({\"conanfile.py\": GenConanfile(),\n                 \"profile1\": tpl})\n    client.run(\"install . -pr=profile1\")\n    assert \"os=FreeBSD\" in client.out\n\n\ndef test_profile_template_import():\n    client = TestClient()\n    tpl1 = textwrap.dedent(\"\"\"\n        {% import \"profile_vars\" as vars %}\n        [settings]\n        os = {{ vars.a }}\n        \"\"\")\n    tpl2 = textwrap.dedent(\"\"\"\n        {% set a = \"FreeBSD\" %}\n        \"\"\")\n    client.save({\"conanfile.py\": GenConanfile(),\n                 \"profile1\": tpl1,\n                 \"profile_vars\": tpl2})\n    client.run(\"install . -pr=profile1\")\n    assert \"os=FreeBSD\" in client.out\n\n\ndef test_profile_template_import_sibling():\n    # https://github.com/conan-io/conan/issues/17431\n    client = TestClient()\n    tpl1 = textwrap.dedent(r\"\"\"\n        {% import \"sub2/profile_vars\" as vars %}\n        [settings]\n        os = {{ vars.a }}\n        \"\"\")\n    tpl2 = textwrap.dedent(\"\"\"\n        {% set a = \"FreeBSD\" %}\n        \"\"\")\n    client.save_home({\"profiles/sub1/profile1\": tpl1,\n                      \"profiles/sub2/profile_vars\": tpl2})\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"install . -pr=sub1/profile1\")\n    assert \"os=FreeBSD\" in client.out\n\n\ndef test_profile_template_include():\n    client = TestClient()\n    tpl1 = textwrap.dedent(\"\"\"\n        {% include \"profile_vars\" %}\n        \"\"\")\n    tpl2 = textwrap.dedent(\"\"\"\n        {% set a = \"FreeBSD\" %}\n        [settings]\n        os = {{ a }}\n        \"\"\")\n    client.save({\"conanfile.py\": GenConanfile(),\n                 \"profile1\": tpl1,\n                 \"profile_vars\": tpl2})\n    client.run(\"install . -pr=profile1\")\n    assert \"os=FreeBSD\" in client.out\n\n\ndef test_profile_template_include_sibling():\n    # https://github.com/conan-io/conan/issues/17431\n    client = TestClient()\n    tpl1 = textwrap.dedent(r\"\"\"\n        {% include \"sub2/profile_vars\" %}\n        \"\"\")\n    tpl2 = textwrap.dedent(\"\"\"\n        {% set a = \"FreeBSD\" %}\n        [settings]\n        os = {{ a }}\n        \"\"\")\n    client.save_home({\"profiles/sub1/profile1\": tpl1,\n                      \"profiles/sub2/profile_vars\": tpl2})\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"install . -pr=sub1/profile1\")\n    assert \"os=FreeBSD\" in client.out\n\n\ndef test_profile_template_include_from_cache():\n    # https://github.com/conan-io/conan/issues/17431\n    client = TestClient()\n    tpl1 = textwrap.dedent(r\"\"\"\n        {% include \"sub2/profile_vars\" %}\n        \"\"\")\n    tpl2 = textwrap.dedent(\"\"\"\n        {% set a = \"FreeBSD\" %}\n        [settings]\n        os = {{ a }}\n        \"\"\")\n    client.save_home({\"profiles/sub2/profile_vars\": tpl2})\n    client.save({\"conanfile.py\": GenConanfile(),\n                 \"sub1/profile1\": tpl1})\n    client.run(\"install . -pr=sub1/profile1\")\n    assert \"os=FreeBSD\" in client.out\n\n\ndef test_profile_template_profile_dir():\n    client = TestClient()\n    tpl1 = textwrap.dedent(\"\"\"\n        [conf]\n        user.toolchain:mydir = {{ os.path.join(profile_dir, \"toolchain.cmake\") }}\n        \"\"\")\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import load\n        class Pkg(ConanFile):\n            def generate(self):\n                content = load(self, self.conf.get(\"user.toolchain:mydir\"))\n                self.output.info(\"CONTENT: {}\".format(content))\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile,\n                 \"anysubfolder/profile1\": tpl1,\n                 \"anysubfolder/toolchain.cmake\": \"MyToolchainCMake!!!\"})\n    client.run(\"install . -pr=anysubfolder/profile1\")\n    assert \"conanfile.py: CONTENT: MyToolchainCMake!!!\" in client.out\n\n\ndef test_profile_conf_backslash():\n    # https://github.com/conan-io/conan/issues/15726\n    c = TestClient()\n    profile = textwrap.dedent(r\"\"\"\n        [conf]\n        user.team:myconf = \"hello\\test\"\n        \"\"\")\n    c.save({\"profile\": profile})\n    c.run(\"profile show -pr=profile\")\n    assert r\"hello\\test\" in c.out\n\n\ndef test_profile_version():\n    client = TestClient()\n    tpl1 = textwrap.dedent(\"\"\"\n        [options]\n        *:myoption={{conan_version}}\n        *:myoption2={{conan_version<13 and conan_version>1.0}}\n        \"\"\")\n\n    client.save({\"conanfile.py\": GenConanfile(),\n                 \"profile1.jinja\": tpl1})\n    client.run(\"install . -pr=profile1.jinja\")\n    assert f\"*:myoption={conan_version}\" in client.out\n    assert \"*:myoption2=True\" in client.out\n\n\ndef test_profile_template_profile_name():\n    \"\"\"\n        The property profile_name should be parsed as the profile file name when rendering profiles\n    \"\"\"\n    client = TestClient()\n    tpl1 = textwrap.dedent(\"\"\"\n        [conf]\n        user.profile:name = {{ profile_name }}\n        \"\"\")\n    tpl2 = textwrap.dedent(\"\"\"\n        include(default)\n        [conf]\n        user.profile:name = {{ profile_name }}\n        \"\"\")\n    default = textwrap.dedent(\"\"\"\n        [settings]\n        os=Windows\n        [conf]\n        user.profile:name = {{ profile_name }}\n        \"\"\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            def configure(self):\n                self.output.info(\"PROFILE NAME: {}\".format(self.conf.get(\"user.profile:name\")))\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile,\n                 \"profile_folder/foobar\": tpl1,\n                 \"another_folder/foo.profile\": tpl1,\n                 \"include_folder/include_default\": tpl2,\n                 os.path.join(client.paths.profiles_path, \"baz\"): tpl1,\n                 os.path.join(client.paths.profiles_path, \"default\"): default})\n\n    # show only file name as profile name\n    client.run(\"install . -pr=profile_folder/foobar\")\n    assert \"conanfile.py: PROFILE NAME: foobar\" in client.out\n\n    # profile_name should include file extension\n    client.run(\"install . -pr=another_folder/foo.profile\")\n    assert \"conanfile.py: PROFILE NAME: foo.profile\" in client.out\n\n    # default profile should compute profile_name by default too\n    client.run(\"install . -pr=default\")\n    assert \"conanfile.py: PROFILE NAME: default\" in client.out\n\n    # profile names should show only their names\n    client.run(\"install . -pr=baz\")\n    assert \"conanfile.py: PROFILE NAME: baz\" in client.out\n\n    # included profiles should respect the inherited profile name\n    client.run(\"install . -pr=include_folder/include_default\")\n    assert \"conanfile.py: PROFILE NAME: include_default\" in client.out\n\n\ndef test_profile_root_name():\n    c = TestClient()\n    root = textwrap.dedent(\"\"\"\n        [conf]\n        user.profile:name = {{ profile_name }}\n        user.profile:root_name = {{ root_profile_name }}\n        \"\"\")\n    tpl = textwrap.dedent(\"\"\"\n        include(myprofile)\n        \"\"\")\n\n    c.save({\"myprofile\": root,\n            \"other\": tpl})\n    c.run(\"profile show -pr=other\")\n    assert \"user.profile:name=myprofile\" in c.out\n    assert \"user.profile:root_name=other\" in c.out\n\n\nclass TestProfileDetectAPI:\n    def test_profile_detect_os_arch(self):\n        \"\"\" testing OS & ARCH just to test the UX and interface\n        \"\"\"\n        client = TestClient()\n        tpl1 = textwrap.dedent(\"\"\"\n            [settings]\n            os={{detect_api.detect_os()}}\n            arch={{detect_api.detect_arch()}}\n            \"\"\")\n\n        client.save({\"profile1\": tpl1})\n        client.run(\"profile show -pr=profile1 --context=host\")\n        pr = client.get_default_host_profile()\n        the_os = pr.settings['os']\n        arch = pr.settings['arch']\n        expected = textwrap.dedent(f\"\"\"\\\n            [settings]\n            arch={arch}\n            os={the_os}\n            \"\"\")\n        assert expected in client.out\n\n    def test_profile_detect_compiler_missing_error(self):\n        client = TestClient(light=True)\n        tpl1 = textwrap.dedent(\"\"\"\n                    {% set compiler, version, compiler_exe = detect_api.detect_clang_compiler(compiler_exe=\"not-existing-compiler\") %}\n                    {% set version = detect_api.default_compiler_version(compiler, version) %}\n                    \"\"\")\n\n        client.save({\"profile1\": tpl1})\n        client.run(\"profile show -pr=profile1\", assert_error=True)\n        assert \"No version provided to 'detect_api.default_compiler_version()' for None compiler\" in client.out\n\n\ndef test_profile_jinja_error():\n    c = TestClient(light=True)\n    profile = textwrap.dedent(\"\"\"\n        {% set arr = [\n            {# comment that triggers the error #}\n            'smth'\n        ] %}\"\"\")\n    c.save({\"profile1\": profile,\n            \"profile2\": \"include(profile1)\",\n            \"profile3\": \"include(profile2)\",\n            \"conanfile.txt\": \"\"})\n    c.run(\"profile show -pr=profile1\", assert_error=True)\n    assert \"ERROR: Error while rendering the profile template file\" in c.out\n    c.run(\"profile show -pr=profile2\", assert_error=True)\n    assert \"ERROR: Error reading 'profile2' profile: Error while \" \\\n           \"rendering the profile template file \" in c.out\n    assert \"unexpected char '#' at 21\" in c.out\n    c.run(\"profile show -pr=profile3\", assert_error=True)\n    assert \"ERROR: Error reading 'profile3' profile: Error reading 'profile2' profile: Error while \" \\\n           \"rendering the profile template file \" in c.out\n    assert \"unexpected char '#' at 21\" in c.out\n\n    # Also install messages\n    c.run(\"install . -pr=profile1\", assert_error=True)\n    assert \"ERROR: Error while rendering the profile template file\" in c.out\n    assert \"unexpected char '#' at 21\" in c.out\n\n    c.run(\"install . -pr=profile2\", assert_error=True)\n    assert \"ERROR: Error reading 'profile2' profile: Error while \" \\\n           \"rendering the profile template file \" in c.out\n    assert \"unexpected char '#' at 21\" in c.out\n    c.run(\"install . -pr=profile3\", assert_error=True)\n    assert \"ERROR: Error reading 'profile3' profile: Error reading 'profile2' profile: Error while \" \\\n           \"rendering the profile template file \" in c.out\n    assert \"unexpected char '#' at 21\" in c.out\n\n\ndef test_profile_macro_per_package():\n    client = TestClient()\n    tpl1 = textwrap.dedent(\"\"\"\n        {% macro set_windows_settings(lib) %}\n        {{lib}}/*:os=Windows\n        {{lib}}/*:arch=x86\n        {% endmacro %}\n        {% macro set_windows_conf(lib) %}\n        {{lib}}/*:user.conf:key = 2\n        {% endmacro %}\n\n        [settings]\n        os = Linux\n        {{set_windows_settings(\"mypkg\")}}\n        [conf]\n        user.conf:key = 1\n        {{set_windows_conf(\"mypkg\")}}\n        \"\"\")\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"mypkg\"\n            version = \"0.1\"\n            settings = \"os\", \"arch\"\n            def generate(self):\n                value = self.conf.get(\"user.conf:key\")\n                self.output.info(f\"os={self.settings.os}!!\")\n                self.output.info(f\"arch={self.settings.arch}!!\")\n                self.output.info(f\"user.conf:key={value}!!!!\")\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile,\n                 \"profile1\": tpl1})\n    client.run(\"install . -pr=profile1\")\n    assert \"conanfile.py (mypkg/0.1): user.conf:key=2!!!!\" in client.out\n    assert \"conanfile.py (mypkg/0.1): os=Windows!!\" in client.out\n    assert \"conanfile.py (mypkg/0.1): arch=x86!!\" in client.out\n\n\ndef test_profile_jinja_context():\n    \"\"\"\n        Test the ``context=build/host`` injection\n    \"\"\"\n    c = TestClient()\n    tpl1 = textwrap.dedent(\"\"\"\n        [conf]\n        {% if context == \"host\" %}\n        user.profile:common = myhost\n        {% elif context == \"build\" %}\n        user.profile:common = mybuild\n        {% else %}\n        user.profile:common= nocontext\n        [settings]\n        os = Linux\n        {% endif %}\n        \"\"\")\n    tpl2 = textwrap.dedent(\"\"\"\n        include(common)\n        [conf]\n        {% if context == \"host\" %}\n        user.profile:base = myhost\n        {% elif context == \"build\" %}\n        user.profile:base = mybuild\n        {% else %}\n        user.profile:base = nocontext\n        [settings]\n        arch = x86\n        {% endif %}\n        \"\"\")\n\n    c.save({\"common\": tpl1,\n            \"base\": tpl2})\n\n    c.run(\"profile show -pr:a=base --format=json\")\n    profiles = json.loads(c.stdout)\n    assert profiles[\"host\"][\"conf\"] == {\"user.profile:common\": \"myhost\",\n                                        \"user.profile:base\": \"myhost\"}\n    assert profiles[\"build\"][\"conf\"] == {\"user.profile:common\": \"mybuild\",\n                                         \"user.profile:base\": \"mybuild\"}\n\n    # Now lets test when profile is neither build/host, like when used in ``conan list``\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_settings(\"os\", \"arch\")})\n    c.run(\"create . -s os=Linux -s arch=x86\")\n    c.run(\"create . -s os=Windows -s arch=armv8\")\n\n    # This will pick the Linux+x86 package binary\n    c.run(\"list *:* --filter-profile=base\")\n    assert \"os: Windows\" not in c.out\n    assert \"arch: armv8\" not in c.out\n    assert \"os: Linux\" in c.out\n    assert \"arch: x86\" in c.out\n"
  },
  {
    "path": "test/integration/configuration/test_profile_plugin.py",
    "content": "import os\nimport textwrap\n\nfrom conan.internal.cache.home_paths import HomePaths\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestErrorsProfilePlugin:\n    \"\"\" when the plugin fails, we want a clear message and a helpful trace\n    \"\"\"\n    def test_error_profile_plugin(self):\n        c = TestClient()\n        profile_plugin = textwrap.dedent(\"\"\"\\\n            def profile_plugin(profile):\n                settings = profile.kk\n            \"\"\")\n        c.save_home({\"extensions/plugins/profile.py\": profile_plugin})\n\n        c.run(\"install --requires=zlib/1.2.3\", assert_error=True)\n        assert \"Error while processing 'profile.py' plugin, line 2\" in c.out\n        assert \"settings = profile.kk\" in c.out\n\n    def test_remove_plugin_file(self):\n        c = TestClient()\n        c.run(\"version\")  # to trigger the creation\n        os.remove(HomePaths(c.cache_folder).profile_plugin_path)\n        c.run(\"profile show\", assert_error=True)\n        assert \"ERROR: The 'profile.py' plugin file doesn't exist\" in c.out\n\n    def test_regresion_29(self):\n        # https://github.com/conan-io/conan/issues/17247\n        c = TestClient()\n        c.save({\"conanfile.txt\": \"\"})\n        c.run(\"install . -s compiler=clang -s compiler.version=19 -s compiler.cppstd=26\")\n        # doesn't fail anymore\n        c.run(\"install . -s compiler=apple-clang -s compiler.version=16 -s compiler.cppstd=26\")\n        # doesn't fail anymore\n        c.run(\"install . -s compiler=gcc -s compiler.version=14 -s compiler.cppstd=26\")\n        # doesn't fail anymore\n\n\ndef test_android_ndk_version():\n    c = TestClient()\n    c.run(\"profile show -s os=Android\")\n    assert \"os.ndk_version\" not in c.out\n    c.run(\"profile show -s os=Android -s os.ndk_version=r26\")\n    assert \"os.ndk_version=r26\" in c.out\n    c.run(\"profile show -s os=Android -s os.ndk_version=r26a\")\n    assert \"os.ndk_version=r26a\" in c.out\n"
  },
  {
    "path": "test/integration/configuration/test_profile_priority.py",
    "content": "import os\nimport textwrap\n\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import save\n\n\ndef test_profile_local_folder_priority_cache():\n    \"\"\" includes or args without \"./\" will resolve to the cache first\n    \"\"\"\n    c = TestClient()\n    c.save({\"profiles/default\": f\"include(otherprofile)\",\n            \"profiles/otherprofile\": \"[settings]\\nos=AIX\",\n            \"conanfile.txt\": \"\"})\n    save(os.path.join(c.paths.profiles_path, \"otherprofile\"), \"[settings]\\nos=FreeBSD\")\n\n    # Must use local path, otherwise look for it in the cache\n    c.run(\"install . -pr=./profiles/default\")\n    assert \"os=FreeBSD\" in c.out\n\n\ndef test_profile_local_folder_priority_relative():\n    \"\"\" The local include(./profile) must have priority over a file with same name in cache\n    \"\"\"\n    c = TestClient()\n    c.save({\"profiles/default\": f\"include(./otherprofile)\",\n            \"profiles/otherprofile\": \"[settings]\\nos=AIX\",\n            \"conanfile.txt\": \"\"})\n    save(os.path.join(c.paths.profiles_path, \"otherprofile\"), \"[settings]\\nos=FreeBSD\")\n\n    # Must use local path, otherwise look for it in the cache\n    c.run(\"install . -pr=./profiles/default\")\n    assert \"os=AIX\" in c.out\n\n\ndef test_profile_cache_folder_priority():\n    \"\"\" The cache include(./profile) must have priority over a file with same name in local\n    \"\"\"\n    c = TestClient()\n    c.save({\"otherprofile\": \"[settings]\\nos=FreeBSD\",\n            \"conanfile.txt\": \"\"})\n    save(os.path.join(c.paths.profiles_path, \"default\"), \"include(./otherprofile)\")\n    save(os.path.join(c.paths.profiles_path, \"otherprofile\"), \"[settings]\\nos=AIX\")\n\n    c.run(\"install . -pr=default\")\n    assert \"os=AIX\" in c.out\n\n\ndef test_profile_cli_priority():\n    c = TestClient()\n    profile1 = textwrap.dedent(\"\"\"\\\n        [settings]\n        os=AIX\n        [conf]\n        user.myconf:myvalue1=1\n        user.myconf:myvalue2=[2]\n        user.myconf:myvalue3={\"3\": \"4\", \"a\": \"b\"}\n        user.myconf:myvalue4={\"1\": \"2\"}\n        user.myconf:myvalue5={\"6\": \"7\"}\n        \"\"\")\n    profile2 = textwrap.dedent(\"\"\"\\\n        [settings]\n        os=FreeBSD\n        [conf]\n        user.myconf:myvalue1=2\n        user.myconf:myvalue2+=4\n        user.myconf:myvalue3*={\"3\": \"5\"}\n        user.myconf:myvalue5={\"6\": \"7\"}\n        \"\"\")\n    c.save({\"profile1\": profile1,\n            \"profile2\": profile2})\n    c.run(\"profile show -pr=./profile1 -pr=./profile2\")\n    assert \"os=FreeBSD\" in c.out\n    assert \"user.myconf:myvalue1=2\" in c.out\n    assert \"user.myconf:myvalue2=[2, 4]\" in c.out\n    assert \"user.myconf:myvalue3={'3': '5', 'a': 'b'}\" in c.out\n    assert \"user.myconf:myvalue4={'1': '2'}\" in c.out\n    assert \"user.myconf:myvalue5={'6': '7'}\" in c.out\n\n\ndef test_profiles_patterns_include():\n    # https://github.com/conan-io/conan/issues/16718\n    c = TestClient()\n    msvc = textwrap.dedent(\"\"\"\n        [settings]\n        compiler=msvc\n        compiler.cppstd=14\n        compiler.version=193\n        os=Windows\n\n        test*/*:compiler.cppstd=14\n        \"\"\")\n    clang = textwrap.dedent(\"\"\"\n        include(./msvc)\n        [settings]\n        test*/*:compiler=clang\n        test*/*:compiler.cppstd=17\n        test*/*:compiler.runtime_version=v144\n        test*/*:compiler.version=18\n        \"\"\")\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"test_pkg\"\n            version = \"0.1\"\n            settings = \"os\", \"compiler\"\n            def generate(self):\n                self.output.info(f\"MyCompiler={self.settings.compiler}!!!\")\n                self.output.info(f\"MyCompilerVersion={self.settings.compiler.version}!!!\")\n                self.output.info(f\"MyCompilerCpp={self.settings.compiler.cppstd}!!!\")\n            \"\"\")\n    c.save({\"conanfile.py\": conanfile,\n            \"msvc\": msvc,\n            \"clang\": clang})\n    c.run(\"install . -pr=clang\")\n    assert \"conanfile.py (test_pkg/0.1): MyCompiler=clang!!!\" in c.out\n    assert \"conanfile.py (test_pkg/0.1): MyCompilerVersion=18!!!\" in c.out\n    assert \"conanfile.py (test_pkg/0.1): MyCompilerCpp=17!!!\" in c.out\n"
  },
  {
    "path": "test/integration/cps/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/cps/test_cps.py",
    "content": "import json\nimport os\nimport textwrap\n\nimport pytest\n\nfrom conan.cps import CPS\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import save_files\n\n\ndef test_cps():\n    c = TestClient()\n    c.save({\"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_settings(\"build_type\")\n                                                          .with_class_attribute(\"license='MIT'\")})\n    c.run(\"create pkg\")\n\n    settings = \"-s os=Windows -s compiler=msvc -s compiler.version=191 -s arch=x86_64\"\n    c.run(f\"install --requires=pkg/0.1 {settings} -g CPSDeps\")\n    pkg = json.loads(c.load(\"build/cps/msvc-191-x86_64-release/cps/pkg.cps\"))\n    assert pkg[\"name\"] == \"pkg\"\n    assert pkg[\"version\"] == \"0.1\"\n    assert pkg[\"license\"] == \"MIT\"\n    assert pkg[\"configurations\"] == [\"release\"]\n    assert pkg[\"default_components\"] == [\"pkg\"]\n    pkg_comp = pkg[\"components\"][\"pkg\"]\n    assert pkg_comp[\"type\"] == \"interface\"\n    mapping = json.loads(c.load(\"build/cps/cpsmap-msvc-191-x86_64-release.json\"))\n    for _, path_cps in mapping.items():\n        assert os.path.exists(path_cps)\n\n\ndef test_cps_static_lib():\n    c = TestClient()\n    c.save({\"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_package_file(\"lib/pkg.a\", \"-\")\n                                                          .with_settings(\"build_type\")\n            .with_package_info(cpp_info={\"libs\": [\"pkg\"]})})\n    c.run(\"create pkg\")\n\n    settings = \"-s os=Windows -s compiler=msvc -s compiler.version=191 -s arch=x86_64\"\n    c.run(f\"install --requires=pkg/0.1 {settings} -g CPSDeps\")\n    pkg = json.loads(c.load(\"build/cps/msvc-191-x86_64-release/cps/pkg.cps\"))\n    assert pkg[\"name\"] == \"pkg\"\n    assert pkg[\"version\"] == \"0.1\"\n    assert pkg[\"configurations\"] == [\"release\"]\n    assert pkg[\"default_components\"] == [\"pkg\"]\n    pkg_comp = pkg[\"components\"][\"pkg\"]\n    assert pkg_comp[\"type\"] == \"archive\"\n    assert pkg_comp[\"location\"] is not None\n\n\ndef test_cps_header():\n    c = TestClient()\n    c.save({\"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_package_type(\"header-library\")})\n    c.run(\"create pkg\")\n\n    settings = \"-s os=Windows -s compiler=msvc -s compiler.version=191 -s arch=x86_64\"\n    c.run(f\"install --requires=pkg/0.1 {settings} -g CPSDeps\")\n    pkg = json.loads(c.load(\"build/cps/msvc-191-x86_64-release/cps/pkg.cps\"))\n    assert pkg[\"name\"] == \"pkg\"\n    assert pkg[\"version\"] == \"0.1\"\n    assert \"configurations\" not in \"pkg\"\n    assert pkg[\"default_components\"] == [\"pkg\"]\n    pkg_comp = pkg[\"components\"][\"pkg\"]\n    assert pkg_comp[\"type\"] == \"interface\"\n    assert \"location\" not in pkg_comp\n\n\ndef test_cps_in_pkg():\n    c = TestClient()\n    cps = textwrap.dedent(\"\"\"\\\n        {\n            \"cps_version\": \"0.12.0\",\n            \"name\": \"zlib\",\n            \"version\": \"1.3.1\",\n            \"configurations\": [\"release\"],\n            \"default_components\": [\"zlib\"],\n            \"components\": {\n                \"zlib\": {\n                    \"type\": \"archive\",\n                    \"includes\": [\"@prefix@/include\"],\n                    \"location\": \"@prefix@/lib/zlib.a\"\n                }\n            }\n        }\n        \"\"\")\n    cps = \"\".join(cps.splitlines())\n    conanfile = textwrap.dedent(f\"\"\"\n        import os\n        from conan.tools.files import save\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"zlib\"\n            version = \"1.3.1\"\n\n            def package(self):\n                cps = '{cps}'\n                cps_path = os.path.join(self.package_folder, \"zlib.cps\")\n                save(self, cps_path, cps)\n\n            def package_info(self):\n                from conan.cps import CPS\n                self.cpp_info = CPS.load(\"zlib.cps\").to_conan()\n        \"\"\")\n    c.save({\"pkg/conanfile.py\": conanfile})\n    c.run(\"create pkg\")\n\n    settings = \"-s os=Windows -s compiler=msvc -s compiler.version=191 -s arch=x86_64\"\n    c.run(f\"install --requires=zlib/1.3.1 {settings} -g CPSDeps\")\n\n    mapping = json.loads(c.load(\"build/cps/cpsmap-msvc-191-x86_64-release.json\"))\n    for _, path_cps in mapping.items():\n        assert os.path.exists(path_cps)\n\n    assert not os.path.exists(os.path.join(c.current_folder, \"zlib.cps\"))\n    assert not os.path.exists(os.path.join(c.current_folder, \"build\", \"cps\", \"zlib.cps\"))\n\n    c.run(f\"install --requires=zlib/1.3.1 {settings} -g CMakeDeps\")\n    cmake = c.load(\"zlib-release-x86_64-data.cmake\")\n    assert 'set(zlib_INCLUDE_DIRS_RELEASE \"${zlib_PACKAGE_FOLDER_RELEASE}/include\")' in cmake\n    assert 'set(zlib_LIB_DIRS_RELEASE \"${zlib_PACKAGE_FOLDER_RELEASE}/lib\")'\n    assert 'set(zlib_LIBS_RELEASE zlib)' in cmake\n\n\ndef test_cps_shared_in_pkg():\n    c = TestClient()\n    cps = textwrap.dedent(\"\"\"\\\n        {\n          \"components\" :\n          {\n            \"mypkg\" :\n            {\n              \"includes\" : [ \"@prefix@/include\" ],\n              \"type\" : \"dylib\"\n            }\n          },\n          \"cps_path\" : \"@prefix@/cps\",\n          \"cps_version\" : \"0.13.0\",\n          \"name\" : \"mypkg\"\n        }\n        \"\"\")\n    cps_release = textwrap.dedent(\"\"\"\\\n        {\n          \"components\" :\n          {\n            \"mypkg\" :\n            {\n              \"link_location\" : \"@prefix@/lib/mypkg.lib\",\n              \"location\" : \"@prefix@/bin/mypkg.dll\"\n            }\n          },\n          \"configuration\" : \"Release\",\n          \"name\" : \"mypkg\"\n        }\n        \"\"\")\n    cps = \"\".join(cps.splitlines())\n    cps_release = \"\".join(cps_release.splitlines())\n    conanfile = textwrap.dedent(f\"\"\"\n        import os, json\n        from conan.tools.files import save\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"mypkg\"\n            version = \"1.0\"\n\n            def package(self):\n                cps = '{cps}'\n                cps_path = os.path.join(self.package_folder, \"mypkg.cps\")\n                save(self, cps_path, cps)\n                cps = '{cps_release}'\n                cps_path = os.path.join(self.package_folder, \"mypkg@release.cps\")\n                save(self, cps_path, cps)\n\n            def package_info(self):\n                from conan.cps import CPS\n                self.cpp_info = CPS.load(\"mypkg.cps\").to_conan()\n        \"\"\")\n    c.save({\"pkg/conanfile.py\": conanfile})\n    c.run(\"create pkg\")\n\n    settings = \"-s os=Windows -s compiler=msvc -s compiler.version=191 -s arch=x86_64\"\n\n    c.run(f\"install --requires=mypkg/1.0 {settings} -g CMakeDeps\")\n    cmake = c.load(\"mypkg-release-x86_64-data.cmake\")\n    assert 'set(mypkg_INCLUDE_DIRS_RELEASE \"${mypkg_PACKAGE_FOLDER_RELEASE}/include\")' in cmake\n    assert 'set(mypkg_LIB_DIRS_RELEASE \"${mypkg_PACKAGE_FOLDER_RELEASE}/lib\")'\n    assert 'set(mypkg_LIBS_RELEASE mypkg)' in cmake\n\n\ndef test_cps_merge():\n    folder = temp_folder()\n\n    cps_base = textwrap.dedent(\"\"\"{\n        \"components\": {\n            \"mypkg\":{\n                \"includes\": [\"@prefix@/include\"],\n                \"type\": \"archive\",\n                \"definitions\": { \"*\": {\"MY_DEFINE\": null }}\n            }\n        },\n        \"cps_path\": \"@prefix@/cps\",\n        \"cps_version\": \"0.13.0\",\n        \"name\": \"mypkg\"\n        }\n        \"\"\")\n    cps_conf = textwrap.dedent(\"\"\"{\n        \"components\" : {\n            \"mypkg\" : {\n                \"link_languages\" : [ \"cpp\" ],\n                \"location\" : \"@prefix@/lib/mypkg.lib\"\n            }\n        },\n        \"configuration\" : \"Release\",\n        \"name\" : \"mypkg\"\n        }\n        \"\"\")\n    save_files(folder, {\"mypkg.cps\": cps_base,\n                        \"mypkg@release.cps\": cps_conf})\n    cps = CPS.load(os.path.join(folder, \"mypkg.cps\"))\n    json_cps = cps.serialize()\n    mypkg = json_cps[\"components\"][\"mypkg\"]\n    assert mypkg[\"includes\"] == [\"@prefix@/include\"]\n    assert mypkg[\"location\"] == \"@prefix@/lib/mypkg.lib\"\n    assert mypkg[\"type\"] == \"archive\"\n    assert mypkg[\"link_languages\"] == [\"cpp\"]\n    assert mypkg[\"definitions\"] == {'*': {'MY_DEFINE': None}}\n\n\ndef test_extended_cpp_info():\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            languages = [\"C++\"]\n            def package_info(self):\n                self.cpp_info.libs = [\"mylib\"]\n                self.cpp_info.location = \"my_custom_location\"\n                self.cpp_info.type = \"static-library\"\n                self.cpp_info.defines = [\"MY_DEFINE\", \"MY_OTHER_DEFINE=1\"]\n            \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"create .\")\n\n    settings = \"-s os=Windows -s compiler=msvc -s compiler.version=191 -s arch=x86_64\"\n    c.run(f\"install --requires=pkg/0.1 {settings} -g CPSDeps\")\n    pkg = json.loads(c.load(\"build/cps/msvc-191-x86_64-release/cps/pkg.cps\"))\n    assert pkg[\"name\"] == \"pkg\"\n    assert pkg[\"version\"] == \"0.1\"\n    assert pkg[\"default_components\"] == [\"pkg\"]\n    pkg_comp = pkg[\"components\"][\"pkg\"]\n    assert pkg_comp[\"type\"] == \"archive\"\n    assert pkg_comp[\"location\"] == \"my_custom_location\"\n    assert pkg_comp[\"link_languages\"] == [\"cpp\"]\n    assert pkg_comp[\"definitions\"] == {'cpp': {'MY_DEFINE': None, 'MY_OTHER_DEFINE': '1'}}\n\n\n@pytest.mark.parametrize(\"as_comp\", [True, False])\ndef test_cps_component_single(as_comp):\n    c = TestClient()\n    cpp_info_comp = '.components[\"core\"]' if as_comp else \"\"\n    conanfile = textwrap.dedent(f\"\"\"\\\n        from conan import ConanFile\n        from conan.tools.files import save\n        import os\n\n        class mypkgRecipe(ConanFile):\n            name = \"mypkg\"\n            version = \"0.1\"\n\n            requires = \"dep/0.1\"\n\n            def package(self):\n                save(self, os.path.join(self.package_folder, \"lib\", \"libcore.a\"), \"\")\n\n            def package_info(self):\n                self.cpp_info{cpp_info_comp}.libs = [\"core\"]\n                self.cpp_info{cpp_info_comp}.requires = [\"dep::comp1\"]\n                from conan.cps import CPS\n                cps = CPS.from_conan(self)\n                self.cpp_info = cps.to_conan()\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile,\n            \"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\")\n            .with_package_file(\"lib/comp1.a\", \"-\")\n            .with_package_file(\"lib/comp2.a\", \"-\")\n            .with_package_info(cpp_info={\"components\": {\"comp1\": {\"libs\": [\"comp1\"]},\n                                                        \"comp2\": {\"libs\": [\"comp2\"]}}})})\n    c.run(\"create dep\")\n    c.run(\"create\")\n    c.run(f\"install --requires=mypkg/0.1 -g CMakeConfigDeps\")\n    mypkg_targets = c.load(\"mypkg-Targets-release.cmake\")\n    if as_comp:\n        assert \"add_library(mypkg::core\" in mypkg_targets\n        assert \"# Requirement mypkg::core -> dep::comp1\" in mypkg_targets\n    else:\n        assert \"add_library(mypkg::core\" not in mypkg_targets\n        assert \"add_library(mypkg::mypkg\" in mypkg_targets\n        assert \"# Requirement mypkg::mypkg -> dep::comp1\" in mypkg_targets\n"
  },
  {
    "path": "test/integration/cross_building/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/cross_building/build_requires_from_profile_test.py",
    "content": "import os\nimport textwrap\n\nfrom conan.test.utils.tools import TestClient, GenConanfile\n\n\nclass TestBuildRequiresFromProfile:\n    profile_host = textwrap.dedent(\"\"\"\n        [settings]\n        os=Windows\n        arch=x86_64\n         compiler=msvc\n        compiler.version=192\n        compiler.runtime=dynamic\n\n        [tool_requires]\n        br2/version\n    \"\"\")\n\n    profile_build = textwrap.dedent(\"\"\"\n        [settings]\n        os=Macos\n        arch=x86_64\n        compiler=apple-clang\n        compiler.version=11.0\n        compiler.libcxx=libc++\n        build_type=Release\n\n        [tool_requires]\n        br3/version\n    \"\"\")\n\n    library_conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Recipe(ConanFile):\n            name = \"library\"\n            version = \"version\"\n\n            build_requires = \"br1/version\"\n    \"\"\")\n\n    def test_br_from_profile_host_and_profile_build(self):\n        t = TestClient()\n        t.save({'profile_host': self.profile_host,\n                'profile_build': self.profile_build,\n                'library.py': self.library_conanfile,\n                'br1.py': GenConanfile(),\n                'br2.py': GenConanfile(),\n                'br3.py': GenConanfile()})\n        t.run(\"export br1.py --name=br1 --version=version\")\n        t.run(\"export br2.py --name=br2 --version=version\")\n        t.run(\"export br3.py --name=br3 --version=version\")\n        t.run(\"create library.py --profile:host=profile_host --profile:build=profile_build \"\n              \"--build='*'\")\n\n\nclass TestBuildRequiresContextHostFromProfile:\n    toolchain = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Recipe(ConanFile):\n            name = \"mytoolchain\"\n            version = \"1.0\"\n            settings = \"os\"\n\n            def package_info(self):\n                self.output.info(\"PackageInfo OS=%s\" % self.settings.os)\n        \"\"\")\n    gtest = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        import os\n\n        class Recipe(ConanFile):\n            name = \"gtest\"\n            version = \"1.0\"\n            settings = \"os\"\n\n            def build(self):\n                self.output.info(\"Build OS=%s\" % self.settings.os)\n            def package_info(self):\n                self.output.info(\"PackageInfo OS=%s\" % self.settings.os)\n        \"\"\")\n    library_conanfile = textwrap.dedent(\"\"\"\n         from conan import ConanFile\n         import os\n\n         class Recipe(ConanFile):\n             name = \"library\"\n             version = \"version\"\n             settings = \"os\"\n\n             def build_requirements(self):\n                self.test_requires(\"gtest/1.0\")\n\n             def build(self):\n                self.output.info(\"Build OS=%s\" % self.settings.os)\n         \"\"\")\n    profile_host = textwrap.dedent(\"\"\"\n        [settings]\n        os = Linux\n        [tool_requires]\n        mytoolchain/1.0\n        \"\"\")\n    profile_build = textwrap.dedent(\"\"\"\n        [settings]\n        os = Windows\n        \"\"\")\n\n    def test_br_from_profile_host_and_profile_build(self):\n        t = TestClient()\n        t.save({'profile_host': self.profile_host,\n                'profile_build': self.profile_build,\n                'library.py': self.library_conanfile,\n                'mytoolchain.py': self.toolchain,\n                \"gtest.py\": self.gtest})\n        t.run(\"create mytoolchain.py -pr:h=profile_host -pr:b=profile_build --build-require\")\n\n        t.run(\"create gtest.py -pr=profile_host -pr:b=profile_build\")\n        assert \"mytoolchain/1.0: PackageInfo OS=Windows\" in t.out\n        assert \"gtest/1.0: PackageInfo OS=Linux\" in t.out\n\n        t.run(\"create gtest.py -pr=profile_host -pr:b=profile_build --build=*\")\n        assert \"mytoolchain/1.0: PackageInfo OS=Windows\" in t.out\n        assert \"gtest/1.0: Build OS=Linux\" in t.out\n        assert \"gtest/1.0: PackageInfo OS=Linux\" in t.out\n\n        t.run(\"create library.py -pr:h=profile_host -pr:b=profile_build\")\n        assert \"gtest/1.0: PackageInfo OS=Linux\" in t.out\n        assert \"library/version: Build OS=Linux\" in t.out\n        assert \"mytoolchain/1.0: PackageInfo OS=Windows\" in t.out\n\n        t.run(\"create library.py -pr:h=profile_host -pr:b=profile_build --build=*\")\n        assert \"gtest/1.0: Build OS=Linux\" in t.out\n        assert \"gtest/1.0: PackageInfo OS=Linux\" in t.out\n        assert \"library/version: Build OS=Linux\" in t.out\n        assert \"mytoolchain/1.0: PackageInfo OS=Windows\" in t.out\n\n\nclass TestBuildRequiresBothContexts:\n    toolchain_creator = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Recipe(ConanFile):\n            name = \"creator\"\n            version = \"1.0\"\n            settings = \"os\"\n\n            def package_info(self):\n                self.output.info(\"PackageInfo OS=%s\" % self.settings.os)\n        \"\"\")\n    toolchain = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        import os\n\n        class Recipe(ConanFile):\n            name = \"mytoolchain\"\n            version = \"1.0\"\n            settings = \"os\"\n            def build(self):\n                self.output.info(\"Build OS=%s\" % self.settings.os)\n\n            def package_info(self):\n                self.output.info(\"PackageInfo OS=%s\" % self.settings.os)\n        \"\"\")\n    gtest = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        import os\n\n        class Recipe(ConanFile):\n            name = \"gtest\"\n            version = \"1.0\"\n            settings = \"os\"\n\n            def build(self):\n                self.output.info(\"Build OS=%s\" % self.settings.os)\n            def package_info(self):\n                self.output.info(\"PackageInfo OS=%s\" % self.settings.os)\n        \"\"\")\n    library_conanfile = textwrap.dedent(\"\"\"\n         from conan import ConanFile\n         import os\n\n         class Recipe(ConanFile):\n             name = \"library\"\n             version = \"version\"\n             settings = \"os\"\n\n             def build_requirements(self):\n                self.test_requires(\"gtest/1.0\")\n\n             def build(self):\n                self.output.info(\"Build OS=%s\" % self.settings.os)\n         \"\"\")\n    profile_host = textwrap.dedent(\"\"\"\n        [settings]\n        os = Linux\n        [tool_requires]\n        mytoolchain/1.0\n        \"\"\")\n    profile_build = textwrap.dedent(\"\"\"\n        [settings]\n        os = Windows\n        [tool_requires]\n        mytoolchain*:creator/1.0\n        \"\"\")\n\n    def test_build_requires_both_contexts(self):\n        t = TestClient()\n        t.save({'profile_host': self.profile_host,\n                'profile_build': self.profile_build,\n                'library.py': self.library_conanfile,\n                'creator.py': self.toolchain_creator,\n                'mytoolchain.py': self.toolchain,\n                \"gtest.py\": self.gtest})\n        t.run(\"create creator.py -pr=profile_build\")\n        t.run(\"create mytoolchain.py -pr:h=profile_host -pr:b=profile_build --build-require\")\n        assert \"creator/1.0: PackageInfo OS=Windows\" in t.out\n        assert \"mytoolchain/1.0: Build OS=Windows\" in t.out\n\n        # new way, the toolchain can now run in Windows, but gtest in Linux\n        t.run(\"create gtest.py --profile=profile_host --profile:build=profile_build\")\n        assert \"creator/1.0: PackageInfo\" not in t.out  # Creator is skipped now, not needed\n        assert \"gtest/1.0: PackageInfo OS=Linux\" in t.out\n\n        t.run(\"create gtest.py --profile=profile_host --profile:build=profile_build --build=*\")\n        assert \"creator/1.0: PackageInfo OS=Windows\" in t.out\n        assert \"gtest/1.0: PackageInfo OS=Linux\" in t.out\n\n        # Declaring the build_requires in the recipe works, it is just the profile that is\n        # not transitive\n        toolchain = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            import os\n\n            class Recipe(ConanFile):\n                name = \"mytoolchain\"\n                version = \"1.0\"\n                settings = \"os\"\n                build_requires = \"creator/1.0\"\n                def build(self):\n                    self.output.info(\"Build OS=%s\" % self.settings.os)\n\n                def package_info(self):\n                    self.output.info(\"PackageInfo OS=%s\" % self.settings.os)\n            \"\"\")\n        t.save({'mytoolchain.py': toolchain})\n        t.run(\"create mytoolchain.py --profile:host=profile_build -pr:b=profile_build\")\n        assert \"creator/1.0: PackageInfo OS=Windows\" in t.out\n        assert \"mytoolchain/1.0: Build OS=Windows\" in t.out\n\n        t.run(\"create gtest.py --profile=profile_host --profile:build=profile_build --build=*\")\n        assert \"creator/1.0: PackageInfo OS=Windows\" in t.out\n        assert \"mytoolchain/1.0: Build OS=Windows\" in t.out\n        assert \"gtest/1.0: Build OS=Linux\" in t.out\n\n        t.run(\"create library.py -pr:h=profile_host --profile:build=profile_build --build=*\")\n        assert \"creator/1.0: PackageInfo OS=Windows\" in t.out\n        assert \"mytoolchain/1.0: Build OS=Windows\" in t.out\n        assert \"gtest/1.0: Build OS=Linux\" in t.out\n        assert \"gtest/1.0: PackageInfo OS=Linux\" in t.out\n        assert \"library/version: Build OS=Linux\" in t.out\n\n\ndef test_consumer_get_profile_tool_requires():\n    # [tool_requires] defined in a profile will result in applying them in the\n    # consumer, both if using a conanfile.txt of using a --requires\n    t = TestClient(light=True)\n    tool = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"tool\"\n            version = \"1.0\"\n            def package_info(self):\n                self.buildenv_info.define(\"MYVAR\", \"MYVALUE\")\n        \"\"\")\n    t.save({'profile': \"[tool_requires]\\ntool/1.0\",\n            'dep.py': GenConanfile(\"dep\", \"1.0\"),\n            'tool.py': tool,\n            'conanfile.txt': \"\"})\n    t.run(\"create tool.py\")\n    t.run(\"create dep.py\")\n    t.run(\"install . --profile ./profile\")\n    env = t.load(\"conanbuildenv.sh\")\n    assert 'export MYVAR=\"MYVALUE\"' in env\n    os.remove(os.path.join(t.current_folder, \"conanbuildenv.sh\"))\n    # also when using --requires\n    t.run(\"install --requires=dep/1.0 --profile ./profile\")\n    env = t.load(\"conanbuildenv.sh\")\n    assert 'export MYVAR=\"MYVALUE\"' in env\n"
  },
  {
    "path": "test/integration/cross_building/test_cross_build_options.py",
    "content": "import textwrap\n\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_cross_build_options():\n    # https://github.com/conan-io/conan/issues/8443\n    c = TestClient()\n    dep = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"dep\"\n            version = \"0.1\"\n            options = {\"fPIC\": [True, False]}\n            default_options = {\"fPIC\": True}\n            settings = \"os\"\n            def config_options(self):\n                if self.settings.os == \"Windows\":\n                    del self.options.fPIC\n            \"\"\")\n    consumer = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Consumer(ConanFile):\n            requires = \"dep/0.1\"\n            tool_requires = \"dep/0.1\"\n        \"\"\")\n    c.save({\"dep/conanfile.py\": dep,\n            \"consumer/conanfile.py\": consumer})\n    c.run(\"create dep -s os=Android -s os.api_level=22\")\n    c.run(\"create dep -s os=Windows\")\n    c.run(\"install consumer -s:b os=Windows -s:h os=Android -s:h os.api_level=22\")\n    # The above command used to crash, because options not there, so it works now without problems\n    assert \"Finalizing install\" in c.out\n    c.assert_listed_binary({\"dep/0.1\": (\"4333c2a38a8baf674c4e77fe475c146a4685f77a\", \"Cache\")})\n    c.assert_listed_binary({\"dep/0.1\": (\"ebec3dc6d7f6b907b3ada0c3d3cdc83613a2b715\", \"Cache\")},\n                           build=True)\n"
  },
  {
    "path": "test/integration/cross_building/test_package_test.py",
    "content": "import textwrap\n\nfrom jinja2 import Template\n\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import save\n\n\nclass TestTestPackage:\n    conanfile_tpl = Template(textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        import os\n        from conan.tools.env import VirtualBuildEnv\n\n        class Recipe(ConanFile):\n            settings = \"os\"\n            {{ build_requires|default(\"\") }}\n\n            {% if test %}\n            def requirements(self):\n                self.requires(self.tested_reference_str)\n            {% endif %}\n\n            {% raw %}\n            def build(self):\n                self.output.info(\">> settings.os: {}\".format(self.settings.os))\n                self.output.info(\">> settings_build.os: {}\".format(self.settings_build.os))\n                build_env = VirtualBuildEnv(self).vars()\n                with build_env.apply():\n                    self.output.info(\">> tools.get_env('INFO'): {}\".format(os.getenv(\"INFO\")))\n\n            def package_info(self):\n                self.buildenv_info.define(\"INFO\", \"{}-{}\".format(self.name, self.settings.os))\n\n            def test(self):\n                pass\n            {% endraw %}\n\n    \"\"\"))\n\n    conanfile_br = conanfile_tpl.render()\n    conanfile = conanfile_tpl.render(build_requires='build_requires = \"br1/version\"')\n    conanfile_test = conanfile_tpl.render(build_requires='build_requires = \"br2/version\"',\n                                          test=True)\n\n    settings_yml = textwrap.dedent(\"\"\"\n        os:\n            Host:\n            Build:\n    \"\"\")\n\n    def test_command(self):\n        t = TestClient()\n        save(t.paths.settings_path, self.settings_yml)\n        t.save({'br.py': self.conanfile_br,\n                'conanfile.py': self.conanfile,\n                'test_package/conanfile.py': self.conanfile_test,\n                'profile_host': '[settings]\\nos=Host',\n                'profile_build': '[settings]\\nos=Build', })\n        t.run(\"export br.py --name=br1 --version=version\")\n        # It is necessary to build first the test_package build_requires br2\n        t.run(\"create br.py --name=br2 --version=version -tf=\\\"\\\" --build-require \"\n              \"--profile:host=profile_host --profile:build=profile_build\")\n\n        t.run(\"create conanfile.py --name=name --version=version --build=missing\"\n              \" --profile:host=profile_host --profile:build=profile_build\")\n\n        # Build requires are built in the 'build' context:\n        assert \"br1/version: >> settings.os: Build\" in t.out\n        assert \"br1/version: >> settings_build.os: Build\" in t.out\n\n        # Package 'name' is built for the 'host' context (br1 as build_requirement)\n        assert \"name/version: >> settings.os: Host\" in t.out\n        assert \"name/version: >> settings_build.os: Build\" in t.out\n\n        # Test_package is executed with the same profiles as the package itself\n        assert \"name/version (test package): >> settings.os: Host\" in t.out\n        assert \"name/version (test package): >> settings_build.os: Build\" in t.out\n\n        t.run(\"test test_package/conanfile.py name/version@ \"\n              \"--profile:host=profile_host --profile:build=profile_build\")\n\n        assert \"name/version (test package): >> settings.os: Host\" in t.out\n        assert \"name/version (test package): >> settings_build.os: Build\" in t.out\n        assert \"name/version (test package): >> tools.get_env('INFO'): br2-Build\" in t.out\n"
  },
  {
    "path": "test/integration/editable/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/editable/editable_add_test.py",
    "content": "from conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestEditablePackageTest:\n\n    def test_install_ok(self):\n        ref = \"--name=lib --version=version  --user=user --channel=name\"\n        t = TestClient()\n        t.save({'conanfile.py': GenConanfile()})\n        t.run('editable add {}'.format(ref))\n        assert \"Reference 'lib/version@user/name' in editable mode\" in t.out\n\n    def test_editable_list_search(self):\n        ref = \"--name=lib --version=version  --user=user --channel=name\"\n        t = TestClient()\n        t.save({'conanfile.py': GenConanfile()})\n        t.run('editable add . {}'.format(ref))\n        t.run(\"editable list\")\n        assert \"lib/version@user/name\" in t.out\n        assert \"    Path:\" in t.out\n\n    def test_missing_subarguments(self):\n        t = TestClient()\n        t.run(\"editable\", assert_error=True)\n        assert \"ERROR: Exiting with code: 2\" in t.out\n\n    def test_conanfile_name(self):\n        t = TestClient()\n        t.save({'othername.py': GenConanfile(\"lib\", \"version\")})\n        t.run('editable add ./othername.py --user=user --channel=name')\n        assert \"Reference 'lib/version@user/name' in editable mode\" in t.out\n        t.run('install --requires=lib/version@user/name')\n        t.assert_listed_require({\"lib/version@user/name\": \"Editable\"})\n\n    def test_pyrequires_remote(self):\n        t = TestClient(default_server_user=True)\n        t.save({\"conanfile.py\": GenConanfile(\"pyreq\", \"1.0\")})\n        t.run(\"create .\")\n        t.run(\"upload pyreq/1.0 -c -r=default\")\n        t.run(\"remove pyreq/1.0 -c\")\n        t.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_python_requires(\"pyreq/1.0\")})\n        t.run(\"editable add . -nr\", assert_error=True)\n        assert \"Cannot resolve python_requires 'pyreq/1.0': No remote defined\" in t.out\n        t.run(\"editable add .\")\n        assert \"Reference 'pkg/1.0' in editable mode\" in t.out\n\n\ndef test_editable_no_name_version_test_package():\n    tc = TestClient()\n    tc.save({\"conanfile.py\": GenConanfile(),\n             \"test_package/conanfile.py\": GenConanfile(\"test_package\")\n            .with_test(\"self.output.info('Testing the package')\")})\n    tc.run(\"editable add . --name=foo\", assert_error=True)\n    assert \"ERROR: Editable package recipe should declare its name and version\" in tc.out\n\n    tc.run(\"editable add . --version=1.0\", assert_error=True)\n    assert \"ERROR: Editable package recipe should declare its name and version\" in tc.out\n\n    tc.run(\"editable add .\", assert_error=True)\n    assert \"ERROR: Editable package recipe should declare its name and version\" in tc.out\n"
  },
  {
    "path": "test/integration/editable/editable_remove_test.py",
    "content": "import os\nimport shutil\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestRemoveEditablePackageTest:\n\n    @pytest.fixture()\n    def client(self):\n        t = TestClient()\n        t.save({'conanfile.py': GenConanfile()})\n        t.run('editable add . --name=lib --version=version --user=user --channel=name')\n        t.run(\"editable list\")\n        assert \"lib\" in t.out\n        return t\n\n    def test_unlink(self, client):\n        client.run('editable remove -r=lib/version@user/name')\n        assert \"Removed editable 'lib/version@user/name':\" in client.out\n        client.run(\"editable list\")\n        assert \"lib\" not in client.out\n\n    def test_unlink_pattern(self, client):\n        client.run('editable remove -r=*')\n        assert \"Removed editable 'lib/version@user/name':\" in client.out\n        client.run(\"editable list\")\n        assert \"lib\" not in client.out\n\n    def test_remove_path(self, client):\n        client.run(\"editable remove\")\n        assert \"Removed editable 'lib/version@user/name':\" in client.out\n        client.run(\"editable list\")\n        assert \"lib\" not in client.out\n\n    def test_unlink_not_linked(self, client):\n        client.run('editable remove -r=otherlib/version@user/name')\n        assert \"WARN: No editables were removed\" in client.out\n        client.run(\"editable list\")\n        assert \"lib\" in client.out\n\n    def test_removed_folder(self,):\n        # https://github.com/conan-io/conan/issues/15038\n        c = TestClient()\n        c.save({'pkg/conanfile.py': GenConanfile()})\n        c.run('editable add pkg --name=lib --version=version')\n        shutil.rmtree(os.path.join(c.current_folder, \"pkg\"))\n        # https://github.com/conan-io/conan/issues/16164\n        # Making it possible, repeated issue\n        c.run(\"editable remove pkg\")\n        assert \"Removed editable 'lib/version'\" in c.out\n        c.run(\"editable list\")\n        assert \"lib\" not in c.out\n"
  },
  {
    "path": "test/integration/editable/forbidden_commands_test.py",
    "content": "import textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestOtherCommands:\n\n    def test_commands_not_blocked(self):\n        \"\"\" there is no reason to really block commands and operations over editable packages\n        except for others doing an install that depends on the editable\n        \"\"\"\n        t = TestClient(default_server_user=True)\n        t.save({'conanfile.py': GenConanfile(\"lib\", \"0.1\"),\n                \"test_package/conanfile.py\": GenConanfile().with_test(\"pass\")})\n        t.run('editable add .')\n\n        # Nothing in the cache\n        t.run(\"list *\")\n        assert \"There are no matching recipe references\" in t.out\n        t.run('list lib/0.1:*')\n        assert \"ERROR: Recipe 'lib/0.1' not found\" in t.out\n\n        t.run('export . ')\n        assert \"lib/0.1: Exported\" in t.out\n        t.run(\"list *\")\n        assert \"lib/0.1\" in t.out\n        t.run('list lib/0.1:*')\n        assert \"PID:\" not in t.out  # One binary is listed\n\n        t.run('export-pkg .')\n        assert \"lib/0.1: Exporting package\" in t.out\n\n        t.run('list lib/0.1:*')\n        assert \"lib/0.1\" in t.out  # One binary is listed\n\n        t.run('upload lib/0.1 -r default')\n        assert \"Uploading recipe 'lib/0.1\" in t.out\n\n        t.run(\"remove * -c\")\n        # Nothing in the cache\n        t.run(\"list *\")\n        assert \"There are no matching recipe references\" in t.out\n        t.run('list lib/0.1:*')\n        assert \"ERROR: Recipe 'lib/0.1' not found\" in t.out\n\n    def test_create_editable(self):\n        \"\"\"\n        test that an editable can be built with conan create\n        \"\"\"\n        t = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n           from conan import ConanFile\n           class Pkg(ConanFile):\n               name = \"lib\"\n               version = \"0.1\"\n               def build(self):\n                   self.output.info(\"MYBUILDFOLDER: {}\".format(self.build_folder))\n               \"\"\")\n        t.save({'conanfile.py': conanfile,\n                \"test_package/conanfile.py\": GenConanfile().with_test(\"pass\"),\n                \"consumer/conanfile.txt\": \"[requires]\\nlib/0.1\"})\n        t.run('editable add .')\n\n        t.run(\"list *\")\n        assert \"There are no matching\" in t.out\n\n        t.run(\"create .\")\n        package_id = \"da39a3ee5e6b4b0d3255bfef95601890afd80709\"\n        t.assert_listed_require({\"lib/0.1\": \"Editable\"})\n        t.assert_listed_binary({\"lib/0.1\": (package_id,\n                                            \"EditableBuild\")})\n        assert f\"lib/0.1: MYBUILDFOLDER: {t.current_folder}\" in t.out\n        t.run(\"list *\")\n        assert \"lib/0.1\" in t.out  # Because the create actually exports, TODO: avoid exporting?\n\n        t.run(\"install consumer --build=*\")\n        t.assert_listed_require({\"lib/0.1\": \"Editable\"})\n        t.assert_listed_binary({\"lib/0.1\": (package_id,\n                                            \"EditableBuild\")})\n        assert f\"lib/0.1: MYBUILDFOLDER: {t.current_folder}\" in t.out\n\n        t.run(\"install consumer --build=editable\")\n        t.assert_listed_require({\"lib/0.1\": \"Editable\"})\n        t.assert_listed_binary({\"lib/0.1\": (package_id,\n                                            \"EditableBuild\")})\n        assert f\"lib/0.1: MYBUILDFOLDER: {t.current_folder}\" in t.out\n"
  },
  {
    "path": "test/integration/editable/test_editable_envvars.py",
    "content": "import os\nimport re\nimport textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_editable_envvars():\n    c = TestClient()\n    dep = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Dep(ConanFile):\n            name = \"dep\"\n            version = \"1.0\"\n            def layout(self):\n                self.folders.source = \"mysource\"\n                self.folders.build = \"mybuild\"\n                self.layouts.source.runenv_info.append_path(\"MYRUNPATH\", \"mylocalsrc\")\n                self.layouts.build.buildenv_info.define_path(\"MYBUILDPATH\", \"mylocalbuild\")\n\n                self.layouts.package.buildenv_info.define_path(\"MYBUILDPATH\", \"mypkgbuild\")\n                self.layouts.package.runenv_info.append_path(\"MYRUNTPATH\", \"mypkgsrc\")\n\n            def package_info(self):\n                self.buildenv_info.define(\"OTHERVAR\", \"randomvalue\")\n        \"\"\")\n\n    c.save({\"dep/conanfile.py\": dep,\n            \"pkg/conanfile.py\": GenConanfile().with_settings(\"os\").with_requires(\"dep/1.0\")})\n    c.run(\"editable add dep  --name=dep --version=1.0\")\n    c.run(\"install pkg -s os=Linux -s:b os=Linux\")\n    build_path = os.path.join(c.current_folder, \"dep\", \"mybuild\", \"mylocalbuild\")\n    buildenv = c.load(\"pkg/conanbuildenv.sh\")\n    assert f'export MYBUILDPATH=\"{build_path}\"' in buildenv\n\n    runenv = c.load(\"pkg/conanrunenv.sh\")\n    # The package_info() buildenv is aggregated, no prob\n    # But don't use same vars\n    assert 'export OTHERVAR=\"randomvalue\"' in buildenv\n    run_path = os.path.join(c.current_folder, \"dep\", \"mysource\", \"mylocalsrc\")\n    assert f'export MYRUNPATH=\"${{MYRUNPATH:-}}${{MYRUNPATH:+:}}{run_path}\"' in runenv\n\n    c.run(\"editable remove dep\")\n    c.run(\"create dep\")\n    c.run(\"install pkg -s os=Linux -s:b os=Linux\")\n    buildenv = c.load(\"pkg/conanbuildenv.sh\")\n    assert 'mypkgbuild' in buildenv\n    assert \"mylocalbuild\" not in buildenv\n    assert 'export OTHERVAR=\"randomvalue\"' in buildenv\n    runenv = c.load(\"pkg/conanrunenv.sh\")\n    assert 'mypkgsrc' in runenv\n    assert \"mylocalsrc\" not in runenv\n\n\ndef test_editable_envvars_package_info():\n    \"\"\" if the ``layout()`` defines cpp.build.runenv_info/conf_info and the ``package_info()``\n    also defines them, the ``package_info()`` values have precedence. This is not symmetrical\n    with ``cpp_info.includedirs/xxxdirs``. The recommended solution is to use\n    ``self.layouts.package.runenvinfo/conf_info`` instead.\n    \"\"\"\n    c = TestClient()\n    dep = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Dep(ConanFile):\n            name = \"dep\"\n            version = \"1.0\"\n            def layout(self):\n                self.layouts.build.runenv_info.define(\"SOME_PATH\", \"mypath_layout\")\n                self.cpp.build.includedirs = [\"mylayoutinclude\"]\n                self.layouts.build.conf_info.define(\"user:myconf\", \"mylayoutconf\")\n\n            def package_info(self):\n                print(\"Running package_info!!\")\n                self.runenv_info.define(\"SOME_PATH\", \"mypath_pkginfo\")\n                self.cpp_info.includedirs = [\"mypkginfoinclude\"]\n                self.conf_info.define(\"user:myconf\", \"mypkginfoconf\")\n        \"\"\")\n    pkg = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Dep(ConanFile):\n            name = \"pkg\"\n            version = \"1.0\"\n            settings = \"os\", \"build_type\"\n            requires = \"dep/1.0\"\n            def generate(self):\n                myconf = self.dependencies[\"dep\"].conf_info.get(\"user:myconf\")\n                self.output.info(f\"DEP CONFINFO {myconf}\")\n        \"\"\")\n\n    c.save({\"dep/conanfile.py\": dep,\n            \"pkg/conanfile.py\": pkg})\n    c.run(\"editable add dep \")\n    c.run(\"install pkg -s os=Linux -s:b os=Linux -g CMakeDeps\")\n    assert \"conanfile.py (pkg/1.0): DEP CONFINFO mylayoutconf\" in c.out\n    cmake = c.load(\"pkg/dep-release-data.cmake\")\n    assert 'set(dep_INCLUDE_DIRS_RELEASE \"${dep_PACKAGE_FOLDER_RELEASE}/mylayoutinclude\")' in cmake\n    runenv = c.load(\"pkg/conanrunenv-release.sh\")\n    assert f'export SOME_PATH=\"mypath_layout\"' in runenv\n\n\ndef test_editable_envvars_package():\n    \"\"\" This test shows that ``self.layouts.package.runenvinfo/conf_info`` works, ignored\n    while in editable, but used when regular package\n    \"\"\"\n    c = TestClient()\n    dep = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Dep(ConanFile):\n            name = \"dep\"\n            version = \"1.0\"\n            def layout(self):\n                self.layouts.build.runenv_info.define(\"SOME_VALUE\", \"mypath_layout\")\n                self.cpp.build.includedirs = [\"mylayoutinclude\"]\n                self.layouts.build.conf_info.define(\"user:myconf\", \"mylayoutconf\")\n\n                self.layouts.package.runenv_info.define(\"SOME_VALUE\", \"mypath_pkginfo\")\n                self.cpp.package.includedirs = [\"mypkginfoinclude\"]\n                self.layouts.package.conf_info.define(\"user:myconf\", \"mypkginfoconf\")\n        \"\"\")\n    pkg = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Dep(ConanFile):\n            name = \"pkg\"\n            version = \"1.0\"\n            settings = \"os\", \"build_type\"\n            requires = \"dep/1.0\"\n            def generate(self):\n                myconf = self.dependencies[\"dep\"].conf_info.get(\"user:myconf\")\n                self.output.info(f\"DEP CONFINFO {myconf}\")\n        \"\"\")\n\n    c.save({\"dep/conanfile.py\": dep,\n            \"pkg/conanfile.py\": pkg})\n    c.run(\"editable add dep \")\n    c.run(\"install pkg -s os=Linux -s:b os=Linux -g CMakeDeps\")\n    assert \"conanfile.py (pkg/1.0): DEP CONFINFO mylayoutconf\" in c.out\n    cmake = c.load(\"pkg/dep-release-data.cmake\")\n    assert 'set(dep_INCLUDE_DIRS_RELEASE \"${dep_PACKAGE_FOLDER_RELEASE}/mylayoutinclude\")' in cmake\n    runenv = c.load(\"pkg/conanrunenv-release.sh\")\n    assert f'export SOME_VALUE=\"mypath_layout\"' in runenv\n\n    c.run(\"editable remove dep\")\n    c.run(\"create dep\")\n    c.run(\"install pkg -s os=Linux -s:b os=Linux -g CMakeDeps\")\n    assert \"conanfile.py (pkg/1.0): DEP CONFINFO mypkginfoconf\" in c.out\n    cmake = c.load(\"pkg/dep-release-data.cmake\")\n    assert 'set(dep_INCLUDE_DIRS_RELEASE \"${dep_PACKAGE_FOLDER_RELEASE}/mypkginfoinclude\")' in cmake\n    runenv = c.load(\"pkg/conanrunenv-release.sh\")\n    assert f'export SOME_VALUE=\"mypath_pkginfo\"' in runenv\n\n\ndef test_editable_conf():\n    c = TestClient()\n    # TODO: Define if we want conf.xxxx_path(), instead of (..., path=True) methods\n    dep = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Dep(ConanFile):\n            def layout(self):\n                self.folders.source = \"mysource\"\n                self.folders.build = \"mybuild\"\n                self.layouts.source.conf_info.append_path(\"user:myconf\", \"mylocalsrc\")\n                self.layouts.build.conf_info.append_path(\"user:myconf\", \"mylocalbuild\")\n                self.layouts.build.conf_info.update_path(\"user:mydictconf\", {\"a\": \"mypatha\",\n                                                                             \"b\": \"mypathb\"})\n                self.layouts.build.conf_info.define_path(\"user:mydictconf2\", {\"c\": \"mypathc\"})\n        \"\"\")\n\n    pkg = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            requires = \"dep/1.0\"\n            def generate(self):\n                conf = self.dependencies[\"dep\"].conf_info.get(\"user:myconf\")\n                self.output.info(f\"CONF: {conf}\")\n                dictconf = self.dependencies[\"dep\"].conf_info.get(\"user:mydictconf\", check_type=dict)\n                self.output.info(f\"CONFDICT: {dictconf}\")\n                dictconf2 = self.dependencies[\"dep\"].conf_info.get(\"user:mydictconf2\",\n                                                                   check_type=dict)\n                self.output.info(f\"CONFDICT: {dictconf2}\")\n        \"\"\")\n    c.save({\"dep/conanfile.py\": dep,\n            \"pkg/conanfile.py\": pkg})\n    c.run(\"editable add dep --name=dep --version=1.0\")\n    c.run(\"install pkg -s os=Linux -s:b os=Linux\")\n    out = str(c.out).replace(\"\\\\\\\\\", \"\\\\\")\n    conf_source = os.path.join(c.current_folder, \"dep\", \"mybuild\", \"mylocalbuild\")\n    conf_build = os.path.join(c.current_folder, \"dep\", \"mysource\", \"mylocalsrc\")\n    confdict1 = os.path.join(c.current_folder, \"dep\", \"mybuild\", \"mypatha\")\n    confdict2 = os.path.join(c.current_folder, \"dep\", \"mybuild\", \"mypathc\")\n    assert conf_source in out\n    assert conf_build in out\n    assert confdict1 in out\n    assert confdict2 in out\n\n\ndef test_editable_conf_tool_require_builtin():\n    c = TestClient()\n    dep = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        class Dep(ConanFile):\n            name = \"androidndk\"\n            version = \"1.0\"\n            def layout(self):\n                self.layouts.build.conf_info.define_path(\"tools.android:ndk_path\", \"mybuild\")\n                self.layouts.package.conf_info.define_path(\"tools.android:ndk_path\", \"mypkg\")\n        \"\"\")\n\n    pkg = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            tool_requires = \"androidndk/1.0\"\n            def generate(self):\n                ndk = self.conf.get(\"tools.android:ndk_path\")\n                self.output.info(f\"NDK: {ndk}!!!\")\n        \"\"\")\n    c.save({\"dep/conanfile.py\": dep,\n            \"pkg/conanfile.py\": pkg})\n    c.run(\"editable add dep\")\n    c.run(\"install pkg -s os=Linux -s:b os=Linux\")\n    ndk_path = os.path.join(c.current_folder, \"dep\", \"mybuild\")\n    assert f\"conanfile.py: NDK: {ndk_path}!!!\" in c.out\n\n    c.run(\"editable remove dep\")\n    c.run(\"create dep\")\n    c.run(\"install pkg -s os=Linux -s:b os=Linux\")\n    assert re.search(\"conanfile.py: NDK: .*mypkg!!!\", str(c.out))\n"
  },
  {
    "path": "test/integration/editable/test_editable_import.py",
    "content": "import os\nimport shutil\nimport textwrap\n\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestEditableImport:\n\n    def test_copy_from_dep_in_generate(self):\n        \"\"\" as we are removing the imports explicit functionality, test if the editable\n        can still work for the \"imports\" case. It seem possible if:\n\n        - \"dep\" package, both in cache and editable mode, defines correctly its layout\n        - Tricky: \"dep\" package musth use self.source_folder+res instead of layout to package()\n        - IMPORTANT: Consumers should use dep.cpp_info.resdirs[0], not dep.package_folder\n        \"\"\"\n        t = TestClient()\n        dep = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.files import copy\n            class Pkg(ConanFile):\n                exports_sources = \"*\"\n                def layout(self):\n                    self.folders.source = \"src\"\n                    self.cpp.source.resdirs = [\"res\"]\n                def package(self):\n                    resdir = os.path.join(self.source_folder, \"res\")\n                    copy(self, \"*\", resdir, os.path.join(self.package_folder, \"data\"))\n                def package_info(self):\n                    self.cpp_info.resdirs = [\"data\"]\n            \"\"\")\n        consumer = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.files import copy\n            class Pkg(ConanFile):\n                requires = \"dep/0.1\"\n\n                def generate(self):\n                    dep = self.dependencies[\"dep\"]\n                    resdir = dep.cpp_info.resdirs[0]\n                    copy(self, \"*\", resdir, os.path.join(self.build_folder, \"imports\"))\n            \"\"\")\n        t.save({'dep/conanfile.py': dep,\n                'dep/src/res/myfile.txt': \"mydata\",\n                \"consumer/conanfile.py\": consumer})\n\n        t.run(\"create dep --name=dep --version=0.1\")\n        t.run(\"install consumer\")\n        assert t.load(\"consumer/imports/myfile.txt\") == \"mydata\"\n\n        t.run(\"remove * -c\")\n        t.run('editable add dep --name=dep --version=0.1')\n        shutil.rmtree(os.path.join(t.current_folder, \"consumer\", \"imports\"))\n        t.run(\"install consumer\")\n        assert t.load(\"consumer/imports/myfile.txt\") == \"mydata\"\n"
  },
  {
    "path": "test/integration/editable/test_editable_layout.py",
    "content": "import os\nimport textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_editable_folders_root():\n    \"\"\" Editables with self.folders.root = \"..\" should work too\n    \"\"\"\n    c = TestClient()\n    pkg = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n\n            def layout(self):\n                self.folders.root = \"..\"\n                self.folders.build = \"mybuild\"\n                self.cpp.build.libdirs = [\"mylibdir\"]\n\n            def generate(self):\n                self.output.info(f\"PKG source_folder {self.source_folder}\")\n\n            def package_info(self):\n                self.output.info(f\"PKG package_folder {self.package_folder}\")\n        \"\"\")\n    app = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class App(ConanFile):\n            requires = \"pkg/0.1\"\n            def generate(self):\n                pkg_libdir = self.dependencies[\"pkg\"].cpp_info.libdir\n                self.output.info(f\"PKG LIBDIR {pkg_libdir}\")\n        \"\"\")\n    c.save({\"libs/pkg/conanfile.py\": pkg,\n            \"conanfile.py\": app})\n\n    c.run(\"editable add libs/pkg\")\n    c.run(\"install . --build=editable\")\n    libdir = os.path.join(c.current_folder, \"libs\", \"mybuild\", \"mylibdir\")\n    assert f\"conanfile.py: PKG LIBDIR {libdir}\" in c.out\n    assert f\"pkg/0.1: PKG package_folder {c.current_folder}\" in c.out\n    assert f\"pkg/0.1: PKG source_folder {c.current_folder}\" in c.out\n\n\ndef test_editable_folders_sibiling_root():\n    \"\"\" Editables with self.folders.root = \"..\" should work too for sibling folders\n    \"\"\"\n    c = TestClient()\n    pkg = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n\n            def layout(self):\n                self.folders.root = \"..\"\n                self.folders.build = \"mybuild\"\n                self.cpp.build.libdirs = [\"mylibdir\"]\n\n            def generate(self):\n                self.output.info(f\"PKG source_folder {self.source_folder}\")\n\n            def package_info(self):\n                self.output.info(f\"PKG package_folder {self.package_folder}\")\n        \"\"\")\n    app = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class App(ConanFile):\n            requires = \"pkg/0.1\"\n            def generate(self):\n                pkg_libdir = self.dependencies[\"pkg\"].cpp_info.libdir\n                self.output.info(f\"PKG LIBDIR {pkg_libdir}\")\n        \"\"\")\n    c.save({\"pkg/conanfile.py\": pkg,\n            \"app/conanfile.py\": app})\n\n    c.run(\"editable add pkg\")\n    c.run(\"install app --build=editable\")\n    libdir = os.path.join(c.current_folder, \"mybuild\", \"mylibdir\")\n    assert f\"conanfile.py: PKG LIBDIR {libdir}\" in c.out\n    assert f\"pkg/0.1: PKG source_folder {c.current_folder}\" in c.out\n    assert f\"pkg/0.1: PKG package_folder {c.current_folder}\" in c.out\n\n\ndef test_editable_matching_folder_names():\n    # https://github.com/conan-io/conan/issues/14091\n    client = TestClient()\n    client.save({\"hello-say/conanfile.py\": GenConanfile(\"say\", \"0.1\"),\n                 \"hello/conanfile.py\": GenConanfile(\"hello\", \"0.1\").with_settings(\"build_type\")\n                                                                   .with_require(\"say/0.1\")})\n    client.run(\"editable add hello-say\")\n    client.run(\"build hello-say\")\n    client.run(\"install hello -g CMakeDeps -s:b os=Linux\")\n    data = client.load(\"hello/say-release-data.cmake\")\n    hello_say_folder = os.path.join(client.current_folder, \"hello-say\").replace(\"\\\\\", \"/\")\n    assert f'set(say_PACKAGE_FOLDER_RELEASE \"{hello_say_folder}\")' in data\n    env = client.load(\"hello/conanbuildenv-release.sh\")\n    assert \"$script_folder/deactivate_conanbuildenv-release.sh\" in env.replace(\"\\\\\", \"/\")\n\n\ndef test_install_editable_build_folder_vars():\n    \"\"\" Make sure that the consumer generates the editable files following build_folder_vars\n    \"\"\"\n    c = TestClient()\n    profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=Windows\n        arch=x86_64\n        build_type=Release\n        [conf]\n        tools.cmake.cmake_layout:build_folder_vars=['settings.os', 'settings.arch']\n        \"\"\")\n    lib = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import cmake_layout\n        class Lib(ConanFile):\n            name = \"lib\"\n            version = \"0.1\"\n            settings = \"os\", \"arch\", \"build_type\"\n            generators = \"CMakeToolchain\"\n\n            def layout(self):\n                cmake_layout(self)\n            \"\"\")\n    app = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import cmake_layout\n        class App(ConanFile):\n            settings = \"os\", \"arch\", \"build_type\"\n            requires = \"lib/0.1\"\n            generators = \"CMakeToolchain\"\n\n            def layout(self):\n                cmake_layout(self)\n            \"\"\")\n    c.save({\"lib/conanfile.py\": lib,\n            \"app/conanfile.py\": app,\n            \"profile\": profile})\n    c.run(\"editable add lib\")\n    c.run(\"build lib -pr=profile\")\n    c.run(\"install app -pr=profile --build=editable\")\n    path = os.path.join(c.current_folder, \"lib\", \"build\", \"windows-x86_64\", \"Release\", \"generators\")\n    assert f\"lib/0.1: Writing generators to {path}\" in c.out\n"
  },
  {
    "path": "test/integration/editable/test_editable_ranges.py",
    "content": "from conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_editable_ranges():\n    c = TestClient()\n    c.save({\"dep/conanfile.py\": GenConanfile(\"dep\"),\n            \"dep2/conanfile.py\": GenConanfile(\"dep\", \"0.2\"),\n            \"other/conanfile.py\": GenConanfile(\"other\", \"23.0\"),  # shouldn't be resolved!\n            \"app/conanfile.py\": GenConanfile(\"app\", \"0.1\").with_requires(\"dep/[>=0.1]\")})\n    c.run(\"editable add other\")  # This shouldn't be used\n    c.run(\"editable add dep --version=0.1\")  # this should be used\n    c.run(\"editable add dep --version=2.0 --user=myuser --channel=mychannel\")  # This shouldn't be used\n    c.run(\"install app\")\n    c.assert_listed_require({\"dep/0.1\": \"Editable\"})\n    assert \"dep/[>=0.1]: dep/0.1\" in c.out\n\n    # new version, uses new one\n    c.run(\"editable add dep2\")\n    c.run(\"install app\")\n    c.assert_listed_require({\"dep/0.2\": \"Editable\"})\n    assert \"dep/[>=0.1]: dep/0.2\" in c.out\n    assert \"dep/0.1\" not in c.out\n\n    # If a newer one is in cache, it resolves to cache\n    c.run(\"create dep --version=0.3\")\n    c.run(\"install app\")\n    c.assert_listed_require({\"dep/0.3\": \"Cache\"})\n    assert \"dep/[>=0.1]: dep/0.3\" in c.out\n    assert \"dep/0.1\" not in c.out\n"
  },
  {
    "path": "test/integration/editable/test_editables_layout.py",
    "content": "import textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_cpp_info_editable():\n\n    client = TestClient()\n\n    conan_hello = str(GenConanfile())\n    conan_hello += \"\"\"\n    def layout(self):\n        self.folders.source = \"my_sources\"\n        self.folders.build = \"my_build\"\n\n        self.cpp.build.includedirs = [\"my_include\"]\n        self.cpp.build.libdirs = [\"my_libdir\"]\n        self.cpp.build.libs = [\"hello\"]\n        self.cpp.build.objects = [\"myobjs/myobject.o\"]\n        self.cpp.build.frameworkdirs = []  # Empty list is also explicit priority declaration\n\n        self.cpp.source.cxxflags = [\"my_cxx_flag\"]\n        self.cpp.source.includedirs = [\"my_include_source\"]\n        self.cpp.source.builddirs = [\"my_builddir_source\"]\n        self.cpp.source.set_property(\"cmake_build_modules\", [\"mypath/mybuildmodule\"])\n\n        self.cpp.package.libs = [\"lib_when_package\"]\n\n    def package_info(self):\n        # when editable: This one will be discarded because declared in build\n        self.cpp_info.includedirs = [\"package_include\"]\n\n        # when editable: This one will be discarded because declared in build\n        self.cpp_info.libs.append(\"lib_when_package2\")\n\n        self.cpp_info.objects = [\"myobject.o\"]\n        self.cpp_info.set_property(\"cmake_build_modules\", [\"mymodules/mybuildmodule\"])\n\n        # when editable: This one will be discarded because declared in source\n        self.cpp_info.cxxflags.append(\"my_cxx_flag2\")\n\n        # when editable: This one will be discarded because declared in source\n        self.cpp_info.frameworkdirs.append(\"package_frameworks_path\")\n\n        # when editable: This one WONT be discarded as has not been declared in the editables layout\n        self.cpp_info.cflags.append(\"my_c_flag\")\n     \"\"\"\n\n    client.save({\"conanfile.py\": conan_hello})\n    client.run(\"create . --name=hello --version=1.0\")\n    package_folder = client.created_layout().package().replace(\"\\\\\", \"/\") + \"/\"\n\n    conan_consumer = textwrap.dedent(\"\"\"\n    import os\n\n    from conan import ConanFile, tools\n\n    class HelloTestConan(ConanFile):\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n        requires = \"hello/1.0\"\n        def build(self):\n            info = self.dependencies[\"hello\"].cpp_info\n\n            self.output.warning(\"**includedirs:{}**\".format(info.includedirs))\n            self.output.warning(\"**libdirs:{}**\".format(info.libdirs))\n            self.output.warning(\"**builddirs:{}**\".format(info.builddirs))\n            self.output.warning(\"**frameworkdirs:{}**\".format(info.frameworkdirs))\n            self.output.warning(\"**libs:{}**\".format(info.libs))\n            self.output.warning(\"**objects:{}**\".format(info.objects))\n            self.output.warning(\"**build_modules:{}**\".format(info.get_property(\"cmake_build_modules\")))\n            self.output.warning(\"**cxxflags:{}**\".format(info.cxxflags))\n            self.output.warning(\"**cflags:{}**\".format(info.cflags))\n    \"\"\")\n    # When hello is not editable\n    client2 = TestClient(client.cache_folder)\n    client2.save({\"conanfile.py\": conan_consumer})\n    client2.run(\"create . --name=lib --version=1.0\")\n    out = str(client2.out).replace(r\"\\\\\", \"/\").replace(package_folder, \"\")\n    assert \"**includedirs:['package_include']**\" in out\n    assert \"**libdirs:['lib']**\" in out\n    assert \"**builddirs:[]**\" in out\n    assert \"**frameworkdirs:['package_frameworks_path']**\" in out\n    assert \"**libs:['lib_when_package', 'lib_when_package2']**\" in out\n    assert \"**objects:['myobject.o']**\" in out\n    assert \"**build_modules:['mymodules/mybuildmodule']**\" in out\n    assert \"**cxxflags:['my_cxx_flag2']**\" in out\n    assert \"**cflags:['my_c_flag']**\" in out\n\n    # When hello is editable\n    client.save({\"conanfile.py\": conan_hello})\n    client.run(\"editable add . --name=hello --version=1.0\")\n\n    # Create the consumer again, now it will use the hello editable\n    client2.run(\"create . --name=lib --version=1.0\")\n    base_folder = client.current_folder.replace(\"\\\\\", \"/\") + \"/\"\n    out = str(client2.out).replace(r\"\\\\\", \"/\").replace(base_folder, \"\")\n\n    assert \"**includedirs:['my_sources/my_include_source', 'my_build/my_include']**\" in out\n    assert \"**libdirs:['my_build/my_libdir']**\" in out\n    assert \"**builddirs:['my_sources/my_builddir_source']**\" in out\n    assert \"**libs:['hello']**\" in out\n    assert \"**objects:['my_build/myobjs/myobject.o']**\" in out\n    assert \"**build_modules:['my_sources/mypath/mybuildmodule']**\" in out\n    assert \"**cxxflags:['my_cxx_flag']**\" in out\n    assert \"**cflags:['my_c_flag']**\" in out\n    assert \"**frameworkdirs:[]**\" in out\n\n\ndef test_cpp_info_components_editable():\n\n    client = TestClient()\n\n    conan_hello = str(GenConanfile())\n    conan_hello += \"\"\"\n    def layout(self):\n        self.folders.source = \"my_sources\"\n        self.folders.build = \"my_build\"\n\n        self.cpp.build.components[\"foo\"].includedirs = [\"my_include_foo\"]\n        self.cpp.build.components[\"foo\"].libdirs = [\"my_libdir_foo\"]\n        self.cpp.build.components[\"foo\"].libs = [\"hello_foo\"]\n        self.cpp.build.components[\"foo\"].objects = [\"myobjs/myobject.o\"]\n\n        self.cpp.build.components[\"var\"].includedirs = [\"my_include_var\"]\n        self.cpp.build.components[\"var\"].libdirs = [\"my_libdir_var\"]\n        self.cpp.build.components[\"var\"].libs = [\"hello_var\"]\n\n        self.cpp.source.components[\"foo\"].cxxflags = [\"my_cxx_flag_foo\"]\n        self.cpp.source.components[\"foo\"].includedirs = [\"my_include_source_foo\"]\n        self.cpp.source.components[\"foo\"].builddirs = [\"my_builddir_source_foo\"]\n        self.cpp.source.components[\"foo\"].set_property(\"cmake_build_modules\",\n                                                      [\"mypath/mybuildmodule\"])\n        self.cpp.source.components[\"var\"].cxxflags = [\"my_cxx_flag_var\"]\n        self.cpp.source.components[\"var\"].includedirs = [\"my_include_source_var\"]\n        self.cpp.source.components[\"var\"].builddirs = [\"my_builddir_source_var\"]\n\n        self.cpp.package.components[\"foo\"].libs = [\"lib_when_package_foo\"]\n        self.cpp.package.components[\"var\"].libs = [\"lib_when_package_var\"]\n\n    def package_info(self):\n        # when editable: This one will be discarded because declared in build\n        self.cpp_info.components[\"foo\"].includedirs = [\"package_include_foo\"]\n\n        # when editable: This one will be discarded because declared in build\n        self.cpp_info.components[\"foo\"].libs.append(\"lib_when_package2_foo\")\n\n        self.cpp_info.components[\"foo\"].objects = [\"myobject.o\"]\n        self.cpp_info.components[\"foo\"].set_property(\"cmake_build_modules\",\n                                                    [\"mymodules/mybuildmodule\"])\n\n        # when editable: This one will be discarded because declared in source\n        self.cpp_info.components[\"foo\"].cxxflags.append(\"my_cxx_flag2_foo\")\n\n        # when editable: This one WONT be discarded as has not been declared in the editables layout\n        self.cpp_info.components[\"foo\"].cflags.append(\"my_c_flag_foo\")\n\n        # when editable: This one will be discarded because declared in build\n        self.cpp_info.components[\"var\"].includedirs = [\"package_include_var\"]\n\n        # when editable: This one will be discarded because declared in build\n        self.cpp_info.components[\"var\"].libs.append(\"lib_when_package2_var\")\n\n        # when editable: This one will be discarded because declared in source\n        self.cpp_info.components[\"var\"].cxxflags.append(\"my_cxx_flag2_var\")\n\n        # when editable: This one WONT be discarded as has not been declared in the editables layout\n        self.cpp_info.components[\"var\"].cflags.append(\"my_c_flag_var\")\n     \"\"\"\n\n    client.save({\"conanfile.py\": conan_hello})\n    client.run(\"create . --name=hello --version=1.0\")\n    package_folder = client.created_layout().package().replace(\"\\\\\", \"/\") + \"/\"\n\n    conan_consumer = textwrap.dedent(\"\"\"\n    import os\n\n    from conan import ConanFile, tools\n\n    class HelloTestConan(ConanFile):\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n        requires = \"hello/1.0\"\n        def build(self):\n            info = self.dependencies[\"hello\"].cpp_info\n\n            self.output.warning(\"**FOO includedirs:{}**\".format(info.components[\"foo\"].includedirs))\n            self.output.warning(\"**FOO libdirs:{}**\".format(info.components[\"foo\"].libdirs))\n            self.output.warning(\"**FOO builddirs:{}**\".format(info.components[\"foo\"].builddirs))\n            self.output.warning(\"**FOO libs:{}**\".format(info.components[\"foo\"].libs))\n            self.output.warning(\"**FOO cxxflags:{}**\".format(info.components[\"foo\"].cxxflags))\n            self.output.warning(\"**FOO cflags:{}**\".format(info.components[\"foo\"].cflags))\n            self.output.warning(\"**FOO objects:{}**\".format(info.components[\"foo\"].objects))\n            self.output.warning(\"**FOO build_modules:{}**\".format(\n                                        info.components[\"foo\"].get_property(\"cmake_build_modules\")))\n\n            self.output.warning(\"**VAR includedirs:{}**\".format(info.components[\"var\"].includedirs))\n            self.output.warning(\"**VAR libdirs:{}**\".format(info.components[\"var\"].libdirs))\n            self.output.warning(\"**VAR builddirs:{}**\".format(info.components[\"var\"].builddirs))\n            self.output.warning(\"**VAR libs:{}**\".format(info.components[\"var\"].libs))\n            self.output.warning(\"**VAR cxxflags:{}**\".format(info.components[\"var\"].cxxflags))\n            self.output.warning(\"**VAR cflags:{}**\".format(info.components[\"var\"].cflags))\n    \"\"\")\n    # When hello is not editable\n    client2 = TestClient(client.cache_folder)\n    client2.save({\"conanfile.py\": conan_consumer})\n    client2.run(\"create . --name=lib --version=1.0\")\n\n    out = str(client2.out).replace(r\"\\\\\", \"/\").replace(package_folder, \"\")\n    assert \"**FOO includedirs:['package_include_foo']**\" in out\n    assert \"**FOO libdirs:['lib']**\" in out  # The components does have default dirs\n    assert \"**FOO builddirs:[]**\" in out  # The components don't have default dirs for builddirs\n\n    assert \"**FOO libs:['lib_when_package_foo', 'lib_when_package2_foo']**\" in out\n    assert \"**FOO objects:['myobject.o']**\" in out\n    assert \"**FOO build_modules:['mymodules/mybuildmodule']**\" in out\n    assert \"**FOO cxxflags:['my_cxx_flag2_foo']**\" in out\n    assert \"**FOO cflags:['my_c_flag_foo']**\" in out\n\n    assert \"**VAR includedirs:['package_include_var']**\" in out\n    assert \"**VAR libdirs:['lib']**\" in out  # The components does have default dirs\n    assert \"**VAR builddirs:[]**\" in out  # The components don't have default dirs\n\n    assert \"**VAR libs:['lib_when_package_var', 'lib_when_package2_var']**\" in out\n    assert \"**VAR cxxflags:['my_cxx_flag2_var']**\" in out\n    assert \"**VAR cflags:['my_c_flag_var']**\" in out\n\n    # When hello is editable\n    client.save({\"conanfile.py\": conan_hello})\n    client.run(\"editable add . --name=hello --version=1.0\")\n\n    # Create the consumer again, now it will use the hello editable\n    client2.run(\"create . --name=lib --version=1.0\")\n    base_folder = client.current_folder.replace(\"\\\\\", \"/\") + \"/\"\n    out = str(client2.out).replace(r\"\\\\\", \"/\").replace(base_folder, \"\")\n\n    assert \"**FOO includedirs:['my_sources/my_include_source_foo', \" \\\n           \"'my_build/my_include_foo']**\" in out\n    assert \"**FOO libdirs:['my_build/my_libdir_foo']**\" in out\n    assert \"**FOO builddirs:['my_sources/my_builddir_source_foo']**\" in out\n    assert \"**FOO libs:['hello_foo']**\" in out\n    assert \"**FOO objects:['my_build/myobjs/myobject.o']**\" in out\n    assert \"**FOO build_modules:['my_sources/mypath/mybuildmodule']**\" in out\n    assert \"**FOO cxxflags:['my_cxx_flag_foo']**\" in out\n    assert \"**FOO cflags:['my_c_flag_foo']**\" in out\n\n    assert \"**VAR includedirs:['my_sources/my_include_source_var', \" \\\n           \"'my_build/my_include_var']**\" in out\n    assert \"**VAR libdirs:['my_build/my_libdir_var']**\" in out\n    assert \"**VAR builddirs:['my_sources/my_builddir_source_var']**\" in out\n    assert \"**VAR libs:['hello_var']**\" in out\n    assert \"**VAR cxxflags:['my_cxx_flag_var']**\" in out\n    assert \"**VAR cflags:['my_c_flag_var']**\" in out\n\n\ndef test_editable_package_folder():\n    \"\"\" This test checks the behavior that self.package_folder is NOT defined (i.e = None)\n    for editable packages, so it cannot be used in ``package_info()`` method\n    \"\"\"\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.cmake import cmake_layout\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n\n            def package_info(self):\n                self.output.info(\"PKG FOLDER={}!!!\".format(self.package_folder))\n\n            def layout(self):\n                cmake_layout(self)\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"create .\")\n    c.run(\"editable add .\")\n    c.run(\"install --requires=pkg/0.1@\")\n    assert \"pkg/0.1: PKG FOLDER=None!!!\"\n\n\ndef test_editable_components_absolute_paths():\n    \"\"\"\n    this was failing in https://github.com/conan-io/conan/issues/14777\n    because components aggregation had a bug\n    \"\"\"\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Pkg(ConanFile):\n            name = \"alpha\"\n            version = \"1.0\"\n\n            def layout(self):\n                self.cpp.source.components[\"headers\"].includedirs = [\"include222\"]\n                self.cpp.build.components[\"alpha1\"].libdirs = [\"alpha1\",]\n                self.cpp.build.components[\"alpha2\"].libdirs = [\"alpha2\"]\n                self.cpp.build.components[\"alpha_exe\"].bindirs = [\"alpha_exe\"]\n        \"\"\")\n    test = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"CMakeDeps\"\n\n            def requirements(self):\n                self.requires(self.tested_reference_str)\n\n            def test(self):\n                pass\n            \"\"\")\n    c.save({\"conanfile.py\": conanfile,\n            \"test_package/conanfile.py\": test})\n    c.run(\"editable add .\")\n    c.run(\"create .\")\n    # This used to crash due to \"include\" is not absolute path, now it works\n    assert \"Testing the package\" in c.out\n"
  },
  {
    "path": "test/integration/editable/transitive_editable_test.py",
    "content": "import textwrap\n\nfrom conan.test.utils.tools import TestClient, GenConanfile\n\n\ndef test_transitive_editables_half_diamond():\n    # https://github.com/conan-io/conan/issues/4445\n    client = TestClient(light=True)\n    client.save({\"libc/conanfile.py\": GenConanfile(\"libc\", \"0.1\"),\n                 \"libb/conanfile.py\": GenConanfile(\"libb\", \"0.1\").with_require(\"libc/0.1\"),\n                 \"liba/conanfile.py\": GenConanfile(\"liba\", \"0.1\").with_requires(\"libb/0.1\",\n                                                                                \"libc/0.1\")})\n    client.run(\"editable add libc\")\n    client.run(\"create libb\")\n    client.run(\"install liba\")\n    assert \"libc/0.1 - Editable\" in client.out\n    with client.chdir(\"liba/build\"):\n        client.run(\"install ..\")\n        assert \"libc/0.1 - Editable\" in client.out\n\n\ndef test_transitive_editable_test_requires():\n    \"\"\"\n    This test was crashing because editable packages was \"SKIP\"ing some dependencies as\n    \"test_requires\", but editables need the dependencies to generate() and to build()\n\n    https://github.com/conan-io/conan/issues/13543\n    \"\"\"\n    c = TestClient()\n    pkga = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMakeDeps, cmake_layout\n\n        class Pkg(ConanFile):\n            name = \"pkga\"\n            version = \"1.0\"\n\n            # Binary configuration\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n            def build_requirements(self):\n                self.test_requires(\"gtest/1.0\")\n\n            def layout(self):\n                cmake_layout(self)\n\n            def generate(self):\n                cd = CMakeDeps(self)\n                cd.generate()\n        \"\"\")\n    pkgb = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import cmake_layout\n\n        class Pkg(ConanFile):\n            name = \"pkgb\"\n            version = \"1.0\"\n\n            # Binary configuration\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n            def requirements(self):\n                self.requires(\"pkga/1.0\")\n\n            def layout(self):\n                cmake_layout(self)\n            \"\"\")\n    c.save({\"gtest/conanfile.py\": GenConanfile(\"gtest\", \"1.0\"),\n            \"pkga/conanfile.py\": pkga,\n            \"pkgb/conanfile.py\": pkgb})\n    c.run(\"create gtest\")\n    c.run(\"build pkga\")\n    c.run(\"editable add pkga\")\n    # This used to crash, due to paths in test_requires not being processed (package_info() not\n    # being called\n    c.run(\"build pkgb\")\n\n\ndef test_transitive_editables_python_requires_version_range():\n    # https://github.com/conan-io/conan/issues/14411\n    client = TestClient(default_server_user=True, light=True)\n    client.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\"),\n                 \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_python_requires(\"dep/[*]\")})\n    client.run(\"editable add pkg\", assert_error=True)\n    assert \"Version range '*' from requirement 'dep/[*]' required by 'python_requires' \" \\\n           \"could not be resolved\" in client.out\n    client.run(\"export dep\")\n    client.run(\"upload * -r=default -c\")\n    client.run(\"remove * -c\")\n    client.run(\"editable add pkg\")  # now it works, able to return from server if necessary\n    assert \"dep/0.1: Downloaded recipe revision\" in client.out\n\n\ndef test_transitive_editables_build():\n    # https://github.com/conan-io/conan/issues/6064\n    c = TestClient()\n    libb = textwrap.dedent(\"\"\"\\\n        from conan import ConanFile\n        class LibB(ConanFile):\n            name = \"libb\"\n            version = \"0.1\"\n            build_policy = \"missing\"\n            settings = \"os\", \"compiler\", \"arch\"\n\n            def build_requirements(self):\n                self.build_requires(\"liba/[>=0.0]\")\n\n            def requirements(self):\n                self.requires(\"liba/[>=0.0]\")\n        \"\"\")\n    c.save({\"liba/conanfile.py\": GenConanfile(\"liba\", \"0.1\"),\n            \"libb/conanfile.py\": libb,\n            \"app/conanfile.txt\": \"[requires]\\nlibb/0.1\"})\n    c.run(\"editable add liba\")\n    c.run(\"editable add libb\")\n    c.run(\"install app --build=*\")\n    # It doesn't crash\n    # Try also with 2 profiles\n    c.run(\"install app -s:b os=Windows --build=*\")\n    # it doesn't crash\n\n\ndef test_transitive_editable_cascade_build():\n    \"\"\"\n    https://github.com/conan-io/conan/issues/15292\n    \"\"\"\n    c = TestClient(light=True)\n    pkga = GenConanfile(\"pkga\", \"1.0\").with_package_type(\"static-library\")\n    pkgb = GenConanfile(\"pkgb\", \"1.0\").with_requires(\"pkga/1.0\").with_package_type(\"static-library\")\n    pkgc = GenConanfile(\"pkgc\", \"1.0\").with_requires(\"pkgb/1.0\").with_package_type(\"static-library\")\n    app = GenConanfile(\"app\", \"1.0\").with_requires(\"pkgc/1.0\").with_package_type(\"application\")\n    c.save({\"pkga/conanfile.py\": pkga,\n            \"pkgb/conanfile.py\": pkgb,\n            \"pkgc/conanfile.py\": pkgc,\n            \"app/conanfile.py\": app})\n    c.run(\"create pkga\")\n    c.run(\"create pkgb\")\n    pkgb_id = c.created_package_id(\"pkgb/1.0\")\n    c.run(\"create pkgc\")\n    pkgc_id = c.created_package_id(\"pkgc/1.0\")\n    c.run(\"install app\")\n    # now we want to investigate pkga\n    c.run(\"editable add pkga\")\n    pkga = GenConanfile(\"pkga\", \"1.0\").with_package_type(\"static-library\")\\\n                                      .with_class_attribute(\"some=42\")\n    c.save({\"pkga/conanfile.py\": pkga})\n    c.run(\"install app\")\n    # The consumers didn't need a new binary, even if I modified pkg\n    c.assert_listed_binary({\"pkgb/1.0\": (pkgb_id, \"Cache\"),\n                            \"pkgc/1.0\": (pkgc_id, \"Cache\")})\n    c.run(\"install app --build=editable\")\n    c.assert_listed_binary({\"pkgb/1.0\": (pkgb_id, \"Cache\"),\n                            \"pkgc/1.0\": (pkgc_id, \"Cache\")})\n    # But I can command perfectly what to do and when\n    c.run(\"install app --build=editable --build=cascade\")\n    c.assert_listed_binary({\"pkgb/1.0\": (pkgb_id, \"Build\"),\n                            \"pkgc/1.0\": (pkgc_id, \"Build\")})\n\n    # Changes in pkga are good, we export it\n    c.run(\"export pkga\")\n    # Now we remove the editable\n    c.run(\"editable remove pkga\")\n    c.run(\"install app\", assert_error=True)\n    assert \"ERROR: Missing prebuilt package for 'pkga/1.0'\" in c.out\n\n\ndef test_transitive_editable_cascade_package_id():\n    \"\"\"\n    https://github.com/conan-io/conan/issues/15292\n    \"\"\"\n    c = TestClient(light=True)\n    pkga = GenConanfile(\"pkga\", \"1.0\").with_package_type(\"static-library\")\n    pkgb = GenConanfile(\"pkgb\", \"1.0\").with_requires(\"pkga/1.0\").with_package_type(\"static-library\")\n    pkgc = GenConanfile(\"pkgc\", \"1.0\").with_requires(\"pkgb/1.0\").with_package_type(\"shared-library\")\n    app = GenConanfile(\"app\", \"1.0\").with_requires(\"pkgc/1.0\").with_package_type(\"application\")\n    c.save({\"pkga/conanfile.py\": pkga,\n            \"pkgb/conanfile.py\": pkgb,\n            \"pkgc/conanfile.py\": pkgc,\n            \"app/conanfile.py\": app})\n    c.run(\"create pkga\")\n    c.run(\"create pkgb\")\n    pkgb_id = c.created_package_id(\"pkgb/1.0\")\n    c.run(\"create pkgc\")\n    c.run(\"install app\")\n\n    # now we want to investigate pkga, we put it in editable mode\n    c.run(\"editable add pkga\")\n    pkga = GenConanfile(\"pkga\", \"1.0\").with_package_type(\"static-library\")\\\n                                      .with_class_attribute(\"some=42\")\n    c.save({\"pkga/conanfile.py\": pkga})\n    c.run(\"install app\", assert_error=True)\n    assert \"ERROR: Missing prebuilt package for 'pkgc/1.0'\" in c.out\n    c.run(\"install app --build=missing\")\n    pkgc_id = c.created_package_id(\"pkgc/1.0\")\n    # The consumers didn't need a new binary, even if I modified pkg\n    c.assert_listed_binary({\"pkgb/1.0\": (pkgb_id, \"Cache\"),\n                            \"pkgc/1.0\": (pkgc_id, \"Build\")})\n\n    # Changes in pkga are good, we export it\n    c.run(\"export pkga\")\n    # Now we remove the editable\n    c.run(\"editable remove pkga\")\n    c.run(\"install app\", assert_error=True)\n    assert \"ERROR: Missing prebuilt package for 'pkgc/1.0'\" in c.out\n    c.run(\"install app --build=missing\")\n    pkgc_id = c.created_package_id(\"pkgc/1.0\")\n    # The consumers didn't need a new binary, even if I modified pkg\n    c.assert_listed_binary({\"pkgb/1.0\": (pkgb_id, \"Cache\"),\n                            \"pkgc/1.0\": (pkgc_id, \"Build\")})\n\n\ndef test_warning_from_cache():\n    c = TestClient(light=True)\n    c.save({\"pkga/conanfile.py\":  GenConanfile(\"pkga\", \"1.0\"),\n            \"pkgb/conanfile.py\": GenConanfile(\"pkgb\", \"1.0\").with_requires(\"pkga/1.0\"),\n            \"pkgc/conanfile.py\": GenConanfile(\"pkgc\", \"1.0\").with_requires(\"pkgb/1.0\")})\n    c.run(\"editable add pkga\")\n    c.run(\"create pkgb\")\n    assert \"pkgb/1.0: WARN: risk: Package is being built in the cache using editable\" in c.out\n    c.run(\"create pkgc\")\n    assert \"pkgc/1.0: WARN: risk: Package is being built in the cache using editable\" in c.out\n    c.run(\"create pkgc --build=*\")\n    assert \"pkgb/1.0: WARN: risk: Package is being built in the cache using editable\" in c.out\n    assert \"pkgc/1.0: WARN: risk: Package is being built in the cache using editable\" in c.out\n"
  },
  {
    "path": "test/integration/environment/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/environment/test_buildenv_profile.py",
    "content": "import os\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.fixture\ndef client():\n    conanfile = textwrap.dedent(\"\"\"\n       from conan import ConanFile\n       class Pkg(ConanFile):\n           def generate(self):\n               for var in (1, 2):\n                   v = self.buildenv.vars(self).get(\"MyVar{}\".format(var))\n                   self.output.info(\"MyVar{}={}!!\".format(var, v))\n       \"\"\")\n    profile1 = textwrap.dedent(\"\"\"\n      [buildenv]\n      MyVar1=MyValue1_1\n      MyVar2=MyValue2_1\n      \"\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile,\n                 \"profile1\": profile1})\n    return client\n\n\ndef test_buildenv_profile_cli(client):\n    profile2 = textwrap.dedent(\"\"\"\n        [buildenv]\n        MyVar1=MyValue1_2\n        MyVar2+=MyValue2_2\n        \"\"\")\n    client.save({\"profile2\": profile2})\n\n    client.run(\"install . -pr=profile1 -pr=profile2\")\n    assert \"conanfile.py: MyVar1=MyValue1_2!!\" in client.out\n    assert \"conanfile.py: MyVar2=MyValue2_1 MyValue2_2\" in client.out\n\n\ndef test_buildenv_profile_include(client):\n    profile2 = textwrap.dedent(\"\"\"\n        include(profile1)\n        [buildenv]\n        MyVar1=MyValue1_2\n        MyVar2+=MyValue2_2\n        \"\"\")\n    client.save({\"profile2\": profile2})\n\n    client.run(\"install . -pr=profile2\")\n    assert \"conanfile.py: MyVar1=MyValue1_2!!\" in client.out\n    assert \"conanfile.py: MyVar2=MyValue2_1 MyValue2_2\" in client.out\n\n\ndef test_buildenv_package_patterns():\n    client = TestClient()\n    conanfile = GenConanfile()\n    generate = \"\"\"\n    def generate(self):\n        value = self.buildenv.vars(self).get(\"my_env_var\") or \"None\"\n        self.output.warning(\"{} ENV:{}\".format(self.ref.name, value))\n\"\"\"\n    client.save({\"dep/conanfile.py\": str(conanfile) + generate,\n                 \"pkg/conanfile.py\": str(conanfile.with_requirement(\"dep/0.1\", visible=False)) + generate,\n                 \"consumer/conanfile.py\": str(conanfile.with_requires(\"pkg/0.1\")\n                .with_settings(\"os\", \"build_type\", \"arch\")) + generate})\n\n    client.run(\"export dep --name=dep --version=0.1\")\n    client.run(\"export pkg --name=pkg --version=0.1\")\n\n    # This pattern applies to no package\n    profile = \"\"\"\n            include(default)\n            [buildenv]\n            invented/*:my_env_var=Foo\n            \"\"\"\n    client.save({\"profile\": profile})\n    client.run(\"install consumer --build='*' --profile profile\")\n    assert \"WARN: dep ENV:None\" in client.out\n    assert \"WARN: pkg ENV:None\" in client.out\n    assert \"WARN: None ENV:None\" in client.out\n\n    # This patterns applies to dep\n    profile = \"\"\"\n                include(default)\n                [buildenv]\n                dep/*:my_env_var=Foo\n                \"\"\"\n    client.save({\"profile\": profile})\n    client.run(\"install consumer --build='*' --profile profile\")\n    assert \"WARN: dep ENV:Foo\" in client.out\n    assert \"WARN: pkg ENV:None\" in client.out\n    assert \"WARN: None ENV:None\" in client.out\n\n    profile = \"\"\"\n                    include(default)\n                    [buildenv]\n                    dep/0.1:my_env_var=Foo\n                    \"\"\"\n    client.save({\"profile\": profile})\n    client.run(\"install consumer --build='*' --profile profile\")\n    assert \"WARN: dep ENV:Foo\" in client.out\n    assert \"WARN: pkg ENV:None\" in client.out\n    assert \"WARN: None ENV:None\" in client.out\n\n    # The global pattern applies to all\n    profile = \"\"\"\n                    include(default)\n                    [buildenv]\n                    dep/*:my_env_var=Foo\n                    pkg/*:my_env_var=Foo\n                    my_env_var=Var\n                    \"\"\"\n    client.save({\"profile\": profile})\n    client.run(\"install consumer --build='*' --profile profile\")\n    assert \"WARN: dep ENV:Var\" in client.out\n    assert \"WARN: pkg ENV:Var\" in client.out\n    assert \"WARN: None ENV:Var\" in client.out\n\n    # \"&\" pattern for the consumer\n    profile = \"\"\"\n                        include(default)\n                        [buildenv]\n                        dep/*:my_env_var=Foo\n                        pkg/*:my_env_var=Foo2\n                        &:my_env_var=Var\n                        \"\"\"\n    client.save({\"profile\": profile})\n    client.run(\"install consumer --build='*' --profile profile\")\n    assert \"WARN: dep ENV:Foo\" in client.out\n    assert \"WARN: pkg ENV:Foo2\" in client.out\n    assert \"WARN: None ENV:Var\" in client.out\n\n\ndef test_buildenv_error_unset():\n    # https://github.com/conan-io/conan/issues/19285#issuecomment-3569891282\n    c = TestClient()\n    profile = textwrap.dedent(\"\"\"\n        [buildenv]\n        CLASSPATH=!\n        OTHERPATH=\n        \"\"\")\n    c.save({\"conanfile.txt\": \"\",\n            \"profile\": profile})\n\n    c.run(\"install . -pr=profile -s:a os=Linux\")\n    env = c.load(\"conanbuildenv.sh\")\n    assert \"unset CLASSPATH\" in env\n    assert 'export OTHERPATH=\"\"' in env\n\n\ndef test_buildenv_priority_copy():\n    # https://github.com/conan-io/conan/issues/19570\n    c = TestClient()\n    profile = textwrap.dedent(\"\"\"\n        [buildenv]\n        alib/*:CUSTOM_PATH=+(path)/only_alib\n        CUSTOM_PATH=+(path)/common\n        \"\"\")\n    lib = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class AlibConan(ConanFile):\n            version = \"1.0\"\n\n            def build(self):\n                v = self.buildenv.vars(self).get(\"CUSTOM_PATH\")\n                self.output.info(f\"[{self.name}] CUSTOM_PATH={v}!!!\")\n        \"\"\")\n    conanfile_txt = textwrap.dedent(\"\"\"\n        [requires]\n        alib/1.0\n        blib/1.0\n        \"\"\")\n    c.save({\"lib/conanfile.py\": lib,\n            \"conanfile.txt\": conanfile_txt,\n            \"profile\": profile})\n    c.run(\"export lib --name=alib\")\n    c.run(\"export lib --name=blib\")\n    c.run(\"install . -pr=profile -s os=Windows --build=missing\")\n    assert f\"alib/1.0: [alib] CUSTOM_PATH=/common{os.pathsep}/only_alib!!!\" in c.out\n    assert \"blib/1.0: [blib] CUSTOM_PATH=/common!!!\" in c.out\n"
  },
  {
    "path": "test/integration/environment/test_env.py",
    "content": "import os\nimport platform\nimport subprocess\nimport textwrap\n\nimport pytest\n\nfrom conan.test.utils.env import environment_update\nfrom conan.test.utils.mocks import ConanFileMock\nfrom conan.tools.env.environment import environment_wrap_command\nfrom conan.test.utils.tools import TestClient, GenConanfile\n\n\n@pytest.fixture()\ndef client():\n    openssl = textwrap.dedent(r\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import save, chdir\n        class Pkg(ConanFile):\n            settings = \"os\"\n            package_type = \"shared-library\"\n            def package(self):\n                with chdir(self, self.package_folder):\n                    echo = \"@echo off\\necho MYOPENSSL={}!!\".format(self.settings.os)\n                    save(self, \"bin/myopenssl.bat\", echo)\n                    save(self, \"bin/myopenssl.sh\", echo)\n                    os.chmod(\"bin/myopenssl.sh\", 0o777)\n            \"\"\")\n\n    cmake = textwrap.dedent(r\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import save, chdir\n        class Pkg(ConanFile):\n            settings = \"os\"\n            requires = \"openssl/1.0\"\n            def package(self):\n                with chdir(self, self.package_folder):\n                    echo = \"@echo off\\necho MYCMAKE={}!!\".format(self.settings.os)\n                    save(self, \"mycmake.bat\", echo + \"\\ncall myopenssl.bat\")\n                    save(self, \"mycmake.sh\", echo + \"\\n myopenssl.sh\")\n                    os.chmod(\"mycmake.sh\", 0o777)\n\n            def package_info(self):\n                # Custom buildenv not defined by cpp_info\n                self.buildenv_info.prepend_path(\"PATH\", self.package_folder)\n                self.buildenv_info.define(\"MYCMAKEVAR\", \"MYCMAKEVALUE!!\")\n            \"\"\")\n\n    gtest = textwrap.dedent(r\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import save, chdir\n        class Pkg(ConanFile):\n            settings = \"os\"\n            def package(self):\n                with chdir(self, self.package_folder):\n                    prefix = \"@echo off\\n\" if self.settings.os == \"Windows\" else \"\"\n                    echo = \"{}echo MYGTEST={}!!\".format(prefix, self.settings.os)\n                    save(self, \"bin/mygtest.bat\", echo)\n                    save(self, \"bin/mygtest.sh\", echo)\n                    os.chmod(\"bin/mygtest.sh\", 0o777)\n\n            def package_info(self):\n                self.runenv_info.define(\"MYGTESTVAR\", \"MyGTestValue{}\".format(self.settings.os))\n            \"\"\")\n    client = TestClient()\n    client.save({\"cmake/conanfile.py\": cmake,\n                 \"gtest/conanfile.py\": gtest,\n                 \"openssl/conanfile.py\": openssl})\n\n    client.run(\"export openssl --name=openssl --version=1.0\")\n    client.run(\"export cmake --name=mycmake --version=1.0\")\n    client.run(\"export gtest --name=mygtest --version=1.0\")\n\n    myrunner_bat = \"@echo off\\necho MYGTESTVAR=%MYGTESTVAR%!!\\n\"\n    myrunner_sh = \"echo MYGTESTVAR=$MYGTESTVAR!!\\n\"\n    client.save({\"myrunner.bat\": myrunner_bat,\n                 \"myrunner.sh\": myrunner_sh}, clean_first=True)\n    os.chmod(os.path.join(client.current_folder, \"myrunner.sh\"), 0o777)\n    return client\n\n\n@pytest.mark.parametrize(\"gtest_run_true\", [True, False])\ndef test_complete(client, gtest_run_true):\n    \"\"\"By default, a test require has the run=False trait, so the PATH to the bat cannot be\n    accessed\"\"\"\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n\n        class Pkg(ConanFile):\n            requires = \"openssl/1.0\"\n            tool_requires = \"mycmake/1.0\"\n\n            def build_requirements(self):\n                {}\n\n            def build(self):\n                self.run(\"mycmake.bat\", env=\"conanbuildenv\")\n                assert os.path.exists(os.path.join(self.generators_folder, \"conanrunenv.sh\"))\n       \"\"\")\n    if gtest_run_true:\n        test_require = 'self.test_requires(\"mygtest/1.0\", run=True)'\n    else:\n        test_require = 'self.test_requires(\"mygtest/1.0\")'\n\n    conanfile = conanfile.format(test_require)\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"install . -s:b os=Windows -s:h os=Linux --build=missing\")\n    # Run the BUILD environment\n    if platform.system() == \"Windows\":\n        cmd = environment_wrap_command(ConanFileMock(), \"conanbuildenv\", client.current_folder, \"mycmake.bat\")\n        client.run_command(cmd)\n        assert \"MYCMAKE=Windows!!\" in client.out\n        assert \"MYOPENSSL=Windows!!\" in client.out\n\n    # Run the RUN environment\n    if platform.system() != \"Windows\":\n        cmd = environment_wrap_command(ConanFileMock(), \"conanrunenv\", client.current_folder,\n                                       \"mygtest.sh && .{}myrunner.sh\".format(os.sep))\n        client.run_command(cmd, assert_error=not gtest_run_true)\n        if gtest_run_true:\n            assert \"MYGTEST=Linux!!\" in client.out\n            assert \"MYGTESTVAR=MyGTestValueLinux!!\" in client.out\n\n    if platform.system() == \"Windows\":\n        client.run(\"build . -s:h os=Linux\")\n        assert \"MYCMAKE=Windows!!\" in client.out\n        assert \"MYOPENSSL=Windows!!\" in client.out\n\n\ndef test_profile_included_multiple():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\\\n        import os, platform\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            def generate(self):\n                buildenv = self.buildenv.vars(self)\n                self.output.info(\"MYVAR1: {}!!!\".format(buildenv.get(\"MYVAR1\")))\n                self.output.info(\"MYVAR2: {}!!!\".format(buildenv.get(\"MYVAR2\")))\n                self.output.info(\"MYVAR3: {}!!!\".format(buildenv.get(\"MYVAR3\")))\n        \"\"\")\n\n    myprofile = textwrap.dedent(\"\"\"\n       [buildenv]\n       MYVAR1=MyVal1\n       MYVAR3+=MyVal3\n       \"\"\")\n    other_profile = textwrap.dedent(\"\"\"\n       [buildenv]\n       MYVAR1=MyValOther1\n       MYVAR2=MyValOther2\n       MYVAR3=MyValOther3\n       \"\"\")\n    client.save({\"conanfile.py\": conanfile,\n                 \"myprofile\": myprofile,\n                 \"myprofile_include\": \"include(other_profile)\\n\" + myprofile,\n                 \"other_profile\": other_profile})\n    # The reference profile has priority\n    client.run(\"install . -pr=myprofile_include\")\n    assert \"MYVAR1: MyVal1!!!\" in client.out\n    assert \"MYVAR2: MyValOther2!!!\" in client.out\n    assert \"MYVAR3: MyValOther3 MyVal3!!!\" in client.out\n\n    # Equivalent to include is to put it first, then the last has priority\n    client.run(\"install . -pr=other_profile -pr=myprofile\")\n    assert \"MYVAR1: MyVal1!!!\" in client.out\n    assert \"MYVAR2: MyValOther2!!!\" in client.out\n    assert \"MYVAR3: MyValOther3 MyVal3!!!\" in client.out\n\n\ndef test_profile_buildenv():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\\\n        import os, platform\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            def generate(self):\n                self.buildenv.vars(self).save_script(\"pkgenv\")\n                if platform.system() != \"Windows\":\n                    os.chmod(\"pkgenv.sh\", 0o777)\n\n        \"\"\")\n    # Some scripts in a random system folders, path adding to the profile [env]\n\n    compiler_bat = \"@echo off\\necho MYCOMPILER!!\\necho MYPATH=%PATH%\"\n    compiler_sh = \"echo MYCOMPILER!!\\necho MYPATH=$PATH\"\n    compiler2_bat = \"@echo off\\necho MYCOMPILER2!!\\necho MYPATH2=%PATH%\"\n    compiler2_sh = \"echo MYCOMPILER2!!\\necho MYPATH2=$PATH\"\n\n    myprofile = textwrap.dedent(\"\"\"\n           [buildenv]\n           PATH+=(path){}\n           mypkg*:PATH=!\n           mypkg*:PATH+=(path){}\n           \"\"\".format(os.path.join(client.current_folder, \"compiler\"),\n                      os.path.join(client.current_folder, \"compiler2\")))\n    client.save({\"conanfile.py\": conanfile,\n                 \"myprofile\": myprofile,\n                 \"compiler/mycompiler.bat\": compiler_bat,\n                 \"compiler/mycompiler.sh\": compiler_sh,\n                 \"compiler2/mycompiler.bat\": compiler2_bat,\n                 \"compiler2/mycompiler.sh\": compiler2_sh})\n\n    os.chmod(os.path.join(client.current_folder, \"compiler\", \"mycompiler.sh\"), 0o777)\n    os.chmod(os.path.join(client.current_folder, \"compiler2\", \"mycompiler.sh\"), 0o777)\n\n    client.run(\"install . -pr=myprofile\")\n    # Run the BUILD environment\n    ext = \"bat\" if platform.system() == \"Windows\" else \"sh\"  # TODO: Decide on logic .bat vs .sh\n    cmd = environment_wrap_command(ConanFileMock(), \"conanbuildenv\", client.current_folder,\n                                   \"mycompiler.{}\".format(ext))\n    client.run_command(cmd)\n    assert \"MYCOMPILER!!\" in client.out\n    assert \"MYPATH=\" in client.out\n\n    # Now with pkg-specific env-var\n    client.run(\"install . --name=mypkg --version=1.0 -pr=myprofile\")\n    client.run_command(cmd)\n    assert \"MYCOMPILER2!!\" in client.out\n    assert \"MYPATH2=\" in client.out\n\n\ndef test_transitive_order():\n    # conanfile.py -(br)-> cmake -> openssl (unknown=static)\n    #     \\                    \\-(br)-> gcc\n    #      \\--------(br)-> gcc\n    #       \\---------------------> openssl\n    gcc = textwrap.dedent(r\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            def package_info(self):\n                self.runenv_info.append(\"MYVAR\", \"MyGCCValue\")\n        \"\"\")\n    openssl = textwrap.dedent(r\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            settings = \"os\"\n            tool_requires = \"gcc/1.0\"\n            package_type = \"shared-library\"\n            def package_info(self):\n                self.runenv_info.append(\"MYVAR\", \"MyOpenSSL{}Value\".format(self.settings.os))\n        \"\"\")\n    cmake = textwrap.dedent(r\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            requires = \"openssl/1.0\"\n            tool_requires = \"gcc/1.0\"\n            def package_info(self):\n                self.runenv_info.append(\"MYVAR\", \"MyCMakeRunValue\")\n                self.buildenv_info.append(\"MYVAR\", \"MyCMakeBuildValue\")\n        \"\"\")\n    client = TestClient()\n    client.save({\"gcc/conanfile.py\": gcc,\n                 \"cmake/conanfile.py\": cmake,\n                 \"openssl/conanfile.py\": openssl})\n\n    client.run(\"export gcc --name=gcc --version=1.0\")\n    client.run(\"export openssl --name=openssl --version=1.0\")\n    client.run(\"export cmake --name=cmake --version=1.0\")\n\n    consumer = textwrap.dedent(r\"\"\"\n        from conan import ConanFile\n        from conan.tools.env import VirtualBuildEnv, VirtualRunEnv\n        class Pkg(ConanFile):\n            requires = \"openssl/1.0\"\n            tool_requires = \"cmake/1.0\", \"gcc/1.0\"\n            def generate(self):\n                buildenv = VirtualBuildEnv(self).vars()\n                self.output.info(\"BUILDENV: {}!!!\".format(buildenv.get(\"MYVAR\")))\n                runenv = VirtualRunEnv(self).vars()\n                self.output.info(\"RUNENV: {}!!!\".format(runenv.get(\"MYVAR\")))\n        \"\"\")\n    client.save({\"conanfile.py\": consumer}, clean_first=True)\n    client.run(\"install . -s:b os=Windows -s:h os=Linux --build='*'\")\n    assert \"BUILDENV: MyOpenSSLWindowsValue MyGCCValue \"\\\n           \"MyCMakeRunValue MyCMakeBuildValue!!!\" in client.out\n    assert \"RUNENV: MyOpenSSLLinuxValue!!!\" in client.out\n\n    # Even if the generator is duplicated in command line (it used to fail due to bugs)\n    client.run(\"install . -s:b os=Windows -s:h os=Linux --build='*' -g VirtualRunEnv -g VirtualBuildEnv\")\n    assert \"BUILDENV: MyOpenSSLWindowsValue MyGCCValue \"\\\n           \"MyCMakeRunValue MyCMakeBuildValue!!!\" in client.out\n    assert \"RUNENV: MyOpenSSLLinuxValue!!!\" in client.out\n\n\ndef test_buildenv_from_requires():\n    openssl = textwrap.dedent(r\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            settings = \"os\"\n            def package_info(self):\n                self.buildenv_info.append(\"OpenSSL_ROOT\",\n                                          \"MyOpenSSL{}Value\".format(self.settings.os))\n        \"\"\")\n    poco = textwrap.dedent(r\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            requires = \"openssl/1.0\"\n            settings = \"os\"\n            def package_info(self):\n                self.buildenv_info.append(\"Poco_ROOT\", \"MyPoco{}Value\".format(self.settings.os))\n        \"\"\")\n    client = TestClient()\n    client.save({\"poco/conanfile.py\": poco,\n                 \"openssl/conanfile.py\": openssl})\n\n    client.run(\"export openssl --name=openssl --version=1.0\")\n    client.run(\"export poco --name=poco --version=1.0\")\n\n    consumer = textwrap.dedent(r\"\"\"\n        from conan import ConanFile\n        from conan.tools.env import VirtualBuildEnv\n        class Pkg(ConanFile):\n            requires = \"poco/1.0\"\n            def generate(self):\n                buildenv = VirtualBuildEnv(self).vars()\n                self.output.info(\"BUILDENV POCO: {}!!!\".format(buildenv.get(\"Poco_ROOT\")))\n                self.output.info(\"BUILDENV OpenSSL: {}!!!\".format(buildenv.get(\"OpenSSL_ROOT\")))\n        \"\"\")\n    client.save({\"conanfile.py\": consumer}, clean_first=True)\n    client.run(\"install . -s:b os=Windows -s:h os=Linux --build='*' -g VirtualBuildEnv\")\n    assert \"BUILDENV POCO: MyPocoLinuxValue!!!\" in client.out\n    assert \"BUILDENV OpenSSL: MyOpenSSLLinuxValue!!!\" in client.out\n\n\ndef test_diamond_repeated():\n    pkga = textwrap.dedent(r\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            def package_info(self):\n                self.runenv_info.define(\"MYVAR1\", \"PkgAValue1\")\n                self.runenv_info.append(\"MYVAR2\", \"PkgAValue2\")\n                self.runenv_info.prepend(\"MYVAR3\", \"PkgAValue3\")\n                self.runenv_info.prepend(\"MYVAR4\", \"PkgAValue4\")\n        \"\"\")\n    pkgb = textwrap.dedent(r\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            requires = \"pkga/1.0\"\n            def package_info(self):\n                self.runenv_info.append(\"MYVAR1\", \"PkgBValue1\")\n                self.runenv_info.append(\"MYVAR2\", \"PkgBValue2\")\n                self.runenv_info.prepend(\"MYVAR3\", \"PkgBValue3\")\n                self.runenv_info.prepend(\"MYVAR4\", \"PkgBValue4\")\n        \"\"\")\n    pkgc = textwrap.dedent(r\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            requires = \"pkga/1.0\"\n            def package_info(self):\n                self.runenv_info.append(\"MYVAR1\", \"PkgCValue1\")\n                self.runenv_info.append(\"MYVAR2\", \"PkgCValue2\")\n                self.runenv_info.prepend(\"MYVAR3\", \"PkgCValue3\")\n                self.runenv_info.prepend(\"MYVAR4\", \"PkgCValue4\")\n        \"\"\")\n    pkgd = textwrap.dedent(r\"\"\"\n       from conan import ConanFile\n       class Pkg(ConanFile):\n           requires = \"pkgb/1.0\", \"pkgc/1.0\"\n           def package_info(self):\n               self.runenv_info.append(\"MYVAR1\", \"PkgDValue1\")\n               self.runenv_info.append(\"MYVAR2\", \"PkgDValue2\")\n               self.runenv_info.prepend(\"MYVAR3\", \"PkgDValue3\")\n               self.runenv_info.define(\"MYVAR4\", \"PkgDValue4\")\n       \"\"\")\n    pkge = textwrap.dedent(r\"\"\"\n       from conan import ConanFile\n       from conan.tools.env import VirtualRunEnv\n       class Pkg(ConanFile):\n           requires = \"pkgd/1.0\"\n           def generate(self):\n                env = VirtualRunEnv(self)\n                runenv = env.vars(scope=\"run\")\n                self.output.info(\"MYVAR1: {}!!!\".format(runenv.get(\"MYVAR1\")))\n                self.output.info(\"MYVAR2: {}!!!\".format(runenv.get(\"MYVAR2\")))\n                self.output.info(\"MYVAR3: {}!!!\".format(runenv.get(\"MYVAR3\")))\n                self.output.info(\"MYVAR4: {}!!!\".format(runenv.get(\"MYVAR4\")))\n                env.generate()\n       \"\"\")\n    client = TestClient()\n    client.save({\"pkga/conanfile.py\": pkga,\n                 \"pkgb/conanfile.py\": pkgb,\n                 \"pkgc/conanfile.py\": pkgc,\n                 \"pkgd/conanfile.py\": pkgd,\n                 \"pkge/conanfile.py\": pkge})\n\n    client.run(\"export pkga --name=pkga --version=1.0\")\n    client.run(\"export pkgb --name=pkgb --version=1.0\")\n    client.run(\"export pkgc --name=pkgc --version=1.0\")\n    client.run(\"export pkgd --name=pkgd --version=1.0\")\n\n    client.run(\"install pkge --build=missing\")\n    # PkgB has higher priority (included first) so it is appended last and prepended first (wrtC)\n    assert \"MYVAR1: PkgAValue1 PkgCValue1 PkgBValue1 PkgDValue1!!!\" in client.out\n    assert \"MYVAR2: PkgAValue2 PkgCValue2 PkgBValue2 PkgDValue2!!!\" in client.out\n    assert \"MYVAR3: PkgDValue3 PkgBValue3 PkgCValue3 PkgAValue3!!!\" in client.out\n    assert \"MYVAR4: PkgDValue4!!!\" in client.out\n\n    # No settings always sh\n    conanrun = client.load(\"pkge/conanrunenv.sh\")\n    assert \"PATH\" not in conanrun\n    assert 'export MYVAR1=\"PkgAValue1 PkgCValue1 PkgBValue1 PkgDValue1\"' in conanrun\n    assert ('export MYVAR2=\"${MYVAR2:-}${MYVAR2:+ }PkgAValue2 PkgCValue2 '\n            'PkgBValue2 PkgDValue2\"') in conanrun\n    assert ('export MYVAR3=\"PkgDValue3 PkgBValue3 PkgCValue3 '\n            'PkgAValue3${MYVAR3:+ $MYVAR3}\"') in conanrun\n    assert 'export MYVAR4=\"PkgDValue4\"' in conanrun\n\n\n@pytest.mark.parametrize(\"require_run\", [True, False])\ndef test_environment_scripts_generated_envvars(require_run):\n    \"\"\"If the regular require doesn't declare the 'run' trait, the conanrunenv won't be there,\n    unless for example, the require_pkg has the pkg_type to Application\"\"\"\n    consumer_pkg = textwrap.dedent(r\"\"\"\n        from conan import ConanFile\n        from conan.tools.env import VirtualBuildEnv, VirtualRunEnv\n        class Pkg(ConanFile):\n            settings = \"os\"\n            requires = \"require_pkg/1.0\"\n            tool_requires = \"build_require_pkg/1.0\"\n            generators = \"VirtualRunEnv\", \"VirtualBuildEnv\"\n        \"\"\")\n\n    client = TestClient()\n    conanfile_br = (GenConanfile().with_package_file(\"bin/myapp\", \"myexe\")\n                                  .with_package_file(\"lib/mylib\", \"mylibcontent\")\n                                  .with_settings(\"os\"))\n    conanfile_require = (GenConanfile().with_package_file(\"bin/myapp\", \"myexe\")\n                                       .with_package_file(\"lib/mylib\", \"mylibcontent\")\n                                       .with_settings(\"os\"))\n    if require_run:\n        conanfile_require.with_package_type(\"application\")\n    client.save({\"build_require_pkg/conanfile.py\": conanfile_br,\n                 \"require_pkg/conanfile.py\": conanfile_require,\n                 \"consumer_pkg/conanfile.py\": consumer_pkg})\n\n    client.run(\"export build_require_pkg --name=build_require_pkg --version=1.0\")\n    client.run(\"export require_pkg --name=require_pkg --version=1.0\")\n\n    client.run(\"install consumer_pkg --build='*'\")\n    if platform.system() == \"Windows\":\n        conanbuildenv = client.load(\"consumer_pkg/conanbuildenv.bat\")\n        if require_run:\n            conanrunenv = client.load(\"consumer_pkg/conanrunenv.bat\")\n            assert \"LD_LIBRARY_PATH\" not in conanbuildenv\n            assert \"LD_LIBRARY_PATH\" not in conanrunenv\n        else:\n            assert not os.path.exists(\"consumer_pkg/conanrunenv.bat\")\n    else:\n        if require_run:\n            conanbuildenv = client.load(\"consumer_pkg/conanbuildenv.sh\")\n            conanrunenv = client.load(\"consumer_pkg/conanrunenv.sh\")\n            assert \"LD_LIBRARY_PATH\" in conanbuildenv\n            assert \"LD_LIBRARY_PATH\" in conanrunenv\n        else:\n            assert not os.path.exists(\"consumer_pkg/conanrunenv.sh\")\n\n    if require_run:\n        # Build context LINUX - Host context LINUX\n        client.run(\"install consumer_pkg -s:b os=Linux -s:h os=Linux --build='*'\")\n        conanbuildenv = client.load(\"consumer_pkg/conanbuildenv.sh\")\n        conanrunenv = client.load(\"consumer_pkg/conanrunenv.sh\")\n        assert \"LD_LIBRARY_PATH\" in conanbuildenv\n        assert \"LD_LIBRARY_PATH\" in conanrunenv\n\n        # Build context WINDOWS - Host context WINDOWS\n        client.run(\"install consumer_pkg -s:b os=Windows -s:h os=Windows --build='*'\")\n        conanbuildenv = client.load(\"consumer_pkg/conanbuildenv.bat\")\n        conanrunenv = client.load(\"consumer_pkg/conanrunenv.bat\")\n        assert \"LD_LIBRARY_PATH\" not in conanbuildenv\n        assert \"LD_LIBRARY_PATH\" not in conanrunenv\n\n        # Build context LINUX - Host context WINDOWS\n        client.run(\"install consumer_pkg -s:b os=Linux -s:h os=Windows --build='*'\")\n        conanbuildenv = client.load(\"consumer_pkg/conanbuildenv.sh\")\n        conanrunenv = client.load(\"consumer_pkg/conanrunenv.bat\")\n        assert \"LD_LIBRARY_PATH\" in conanbuildenv\n        assert \"LD_LIBRARY_PATH\" not in conanrunenv\n\n        # Build context WINDOWS - Host context LINUX\n        client.run(\"install consumer_pkg -s:b os=Windows -s:h os=Linux --build='*'\")\n        conanbuildenv = client.load(\"consumer_pkg/conanbuildenv.bat\")\n        conanrunenv = client.load(\"consumer_pkg/conanrunenv.sh\")\n        assert \"LD_LIBRARY_PATH\" not in conanbuildenv\n        assert \"LD_LIBRARY_PATH\" in conanrunenv\n\n\n@pytest.mark.parametrize(\"deactivation_mode\", [\"function\", None])\ndef test_multiple_deactivate(deactivation_mode):\n    conanfile = textwrap.dedent(r\"\"\"\n        from conan import ConanFile\n        from conan.tools.env import Environment\n        class Pkg(ConanFile):\n            def generate(self):\n                e1 = Environment()\n                e1.define(\"VAR1\", \"Value1\")\n                e1.vars(self).save_script(\"mybuild1\")\n                e2 = Environment()\n                e2.define(\"VAR2\", \"Value2\")\n                e2.vars(self).save_script(\"mybuild2\")\n        \"\"\")\n    display_bat = textwrap.dedent(\"\"\"\\\n        @echo off\n        echo VAR1=%VAR1%!!\n        echo VAR2=%VAR2%!!\n        \"\"\")\n    display_sh = textwrap.dedent(\"\"\"\\\n        echo VAR1=$VAR1!!\n        echo VAR2=$VAR2!!\n        \"\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile,\n                 \"display.bat\": display_bat,\n                 \"display.sh\": display_sh})\n    os.chmod(os.path.join(client.current_folder, \"display.sh\"), 0o777)\n    client.run(f\"install . {f'-c=tools.env:deactivation_mode={deactivation_mode}' if deactivation_mode else ''} \")\n\n    for _ in range(2):  # Just repeat it, so we can check things keep working\n        if platform.system() == \"Windows\":\n            deactivate_bat = \"deactivate_conanbuild\" if deactivation_mode else \"deactivate_conanbuild.bat\"\n            cmd = f\"conanbuild.bat && display.bat && {deactivate_bat} && display.bat\"\n        else:\n            deactivate_cmd = \"deactivate_conanbuild\" if deactivation_mode else \". ./deactivate_conanbuild.sh\"\n            cmd = f'. ./conanbuild.sh && ./display.sh && {deactivate_cmd} && ./display.sh'\n        out, _ = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,\n                                  shell=True, cwd=client.current_folder).communicate()\n        out = out.decode()\n        assert \"VAR1=Value1!!\" in out\n        assert \"VAR2=Value2!!\" in out\n        assert 3 == str(out).count(\"Restoring environment\")\n        assert \"VAR1=!!\" in out\n        assert \"VAR2=!!\" in out\n\n\n@pytest.mark.parametrize(\"deactivation_mode\", [\"function\", None])\ndef test_multiple_deactivate_order(deactivation_mode):\n    \"\"\"\n    https://github.com/conan-io/conan/issues/13693\n    \"\"\"\n    conanfile = textwrap.dedent(r\"\"\"\n        from conan import ConanFile\n        from conan.tools.env import Environment\n        class Pkg(ConanFile):\n            def generate(self):\n                e1 = Environment()\n                e1.define(\"MYVAR\", \"Value1\")\n                e1.vars(self).save_script(\"mybuild1\")\n                e2 = Environment()\n                e2.define(\"MYVAR\", \"Value2\")\n                e2.vars(self).save_script(\"mybuild2\")\n        \"\"\")\n    display_bat = textwrap.dedent(\"\"\"\\\n        @echo off\n        echo MYVAR=%MYVAR%!!\n        \"\"\")\n    display_sh = textwrap.dedent(\"\"\"\\\n        echo MYVAR=$MYVAR!!\n        \"\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile,\n                 \"display.bat\": display_bat,\n                 \"display.sh\": display_sh})\n    os.chmod(os.path.join(client.current_folder, \"display.sh\"), 0o777)\n    client.run(f\"install . {f'-c=tools.env:deactivation_mode={deactivation_mode}' if deactivation_mode else ''} \")\n\n    for _ in range(2):  # Just repeat it, so we can check things keep working\n        if platform.system() == \"Windows\":\n            cmd = \"conanbuild.bat && display.bat && deactivate_conanbuild.bat && display.bat\"\n        else:\n            deactivate_cmd = \"deactivate_conanbuild\" if deactivation_mode else \". ./deactivate_conanbuild.sh\"\n            cmd = f'. ./conanbuild.sh && ./display.sh && {deactivate_cmd} && ./display.sh'\n        out, _ = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,\n                                  shell=True, cwd=client.current_folder).communicate()\n        out = out.decode()\n        assert \"MYVAR=Value2!!\" in out\n        assert 3 == str(out).count(\"Restoring environment\")\n        assert \"MYVAR=!!\" in out\n\n\n@pytest.mark.skipif(platform.system() == \"Windows\", reason=\"Shell script test\")\n@pytest.mark.parametrize(\"deactivation_mode\", [\"function\", None])\ndef test_deactivate_missing_vars_stay_missing(deactivation_mode):\n    \"\"\" Tests that these two cases preserve variable status\n    1.\n    export FOO=\n    ./conanrunenv.sh that changes FOO to something with a value\n    ./deactivate_conanrunenv.sh\n    FOO is still empty\n\n    2.\n    BAR is not defined\n    ./conanrunenv.sh that changes BAR to something with a value\n    ./deactivate_conanrunenv.sh\n    BAR is still not defined\n\n    3.\n    BAZ is defined to some value\n    ./conanrunenv.sh that unsets BAZ\n    ./deactivate_conanrunenv.sh\n    BAZ is still defined to some value\n\n    4.\n    FOOBAR is empty\n    ./conanrunenv.sh that unsets FOOBAR\n    ./deactivate_conanrunenv.sh\n    FOOBAR is still empty\n    \"\"\"\n    conanfile = textwrap.dedent(r\"\"\"\n            from conan import ConanFile\n            from conan.tools.env import Environment\n            class Pkg(ConanFile):\n                def generate(self):\n                    e1 = Environment()\n                    e1.define(\"FOO\", \"Value1\")\n                    e1.define(\"BAR\", \"Value2\")\n                    e1.unset(\"BAZ\")\n                    e1.unset(\"FOOBAR\")\n                    e1.vars(self).save_script(\"mybuild1\")\n            \"\"\")\n    display_sh = textwrap.dedent(\"\"\"\\\n            echo FOO=$FOO!!\n            if [ -n \"${BAR+x}\" ]; then echo \"BAR EXISTS!!\"; fi;\n            echo BAZ=$BAZ!!\n            echo FOOBAR=$FOOBAR!!\n            \"\"\")\n    client = TestClient(light=True)\n    client.save({\"conanfile.py\": conanfile,\n                 \"display.sh\": display_sh})\n    os.chmod(os.path.join(client.current_folder, \"display.sh\"), 0o777)\n    client.run(f\"install . {f'-c=tools.env:deactivation_mode={deactivation_mode}' if deactivation_mode else ''} \")\n\n    deactivate_cmd = \"deactivate_conanbuild\" if deactivation_mode else \". ./deactivate_conanbuild.sh\"\n    cmd = (f'export FOO=&& export BAZ=Value3 && export FOOBAR='\n           f'&& . ./conanbuild.sh && {deactivate_cmd} && ./display.sh')\n    out, _ = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,\n                              shell=True, cwd=client.current_folder).communicate()\n    out = out.decode()\n    assert \"FOO=!!\" in out\n    assert \"BAR EXISTS!!\" not in out\n    assert \"BAZ=Value3!!\" in out\n    assert \"FOOBAR=!!\" in out\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Path problem in Windows only\")\n@pytest.mark.parametrize(\"num_deps\", [3, ])\ndef test_massive_paths(num_deps):\n    \"\"\" This test proves that having too many dependencies that will result in a very long PATH\n    env-var in the consumer by one VirtualXXXEnv environment, will overflow.\n    https://github.com/conan-io/conan/issues/9565\n    This seems an unsolvable limitation, the only alternatives are:\n    - shorten the paths in general (shorter cache paths)\n    - add exclusively the paths of needed things (better visibility)\n    Seems that Conan 2.0 will improve over these things, allowing larger dependencies graphs without\n    failing. Besides that, it might use the deployers to workaround shared-libs running scenarios.\n\n    The test is parameterized for being fast an passing, but if we add a num_deps >= 80 approx,\n    it will start to enter the failing scenarios. Not adding the >=80 scenario, because that tests\n    takes 1 minute by itself, not worth the value.\n    \"\"\"\n    client = TestClient(path_with_spaces=False)\n    compiler_bat = \"@echo off\\necho MYTOOL {}!!\\n\"\n    conanfile = textwrap.dedent(\"\"\"\\\n        import os\n        from conan import ConanFile\n        from conan.tools.files import copy\n        class Pkg(ConanFile):\n            exports_sources = \"*\"\n            package_type = \"application\"\n            def package(self):\n                copy(self, \"*\", self.build_folder, os.path.join(self.package_folder, \"bin\"))\n        \"\"\")\n\n    for i in range(num_deps):\n        client.save({\"conanfile.py\": conanfile,\n                     \"mycompiler{}.bat\".format(i): compiler_bat.format(i)})\n        client.run(\"create . --name=pkg{} --version=0.1\".format(i))\n\n    conanfile = textwrap.dedent(\"\"\"\\\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            settings = \"os\"\n            requires = {}\n            generators = \"VirtualRunEnv\"\n        \"\"\")\n    requires = \", \".join('\"pkg{}/0.1\"'.format(i) for i in range(num_deps))\n    conanfile = conanfile.format(requires)\n    client.save({\"conanfile.py\": conanfile}, clean_first=True)\n    client.run(\"install . -c tools.env.virtualenv:powershell=True\")\n    assert os.path.isfile(os.path.join(client.current_folder, \"conanrunenv.ps1\"))\n    assert not os.path.isfile(os.path.join(client.current_folder, \"conanrunenv.bat\"))\n    for i in range(num_deps):\n        cmd = environment_wrap_command(ConanFileMock(), \"conanrunenv\", client.current_folder,\n                                       \"mycompiler{}.bat\".format(i))\n        # if num_deps > 50:  # to be safe if we change the \"num_deps\" number\n        #    client.run_command(cmd, assert_error=True)\n        #    assert \"is not recognized as an internal\" in client.out\n        client.run_command(cmd)\n        assert \"MYTOOL {}!!\".format(i) in client.out\n\n    # Test .bats now\n    client.save({\"conanfile.py\": conanfile}, clean_first=True)\n    client.run(\"install .\")\n    assert not os.path.isfile(os.path.join(client.current_folder, \"conanrunenv.ps1\"))\n    assert os.path.isfile(os.path.join(client.current_folder, \"conanrunenv.bat\"))\n    for i in range(num_deps):\n        cmd = environment_wrap_command(ConanFileMock(), \"conanrunenv\", client.current_folder,\n                                       \"mycompiler{}.bat\".format(i))\n        # if num_deps > 50:  # to be safe if we change the \"num_deps\" number\n        #    client.run_command(cmd, assert_error=True)\n        #    # This also fails, but without an error message (in my terminal, it kills the terminal!)\n        # else:\n        client.run_command(cmd)\n        assert \"MYTOOL {}!!\".format(i) in client.out\n\n\n@pytest.mark.parametrize(\"deactivation_mode\", [\"function\", None])\ndef test_profile_build_env_spaces(deactivation_mode):\n    display_bat = textwrap.dedent(\"\"\"\\\n        @echo off\n        echo VAR1=%VAR1%!!\n        \"\"\")\n    display_sh = textwrap.dedent(\"\"\"\\\n        echo VAR1=$VAR1!!\n        \"\"\")\n    client = TestClient()\n    client.save({\"conanfile.txt\": \"\",\n                 \"profile\": \"[buildenv]\\nVAR1 = VALUE1\",\n                 \"display.bat\": display_bat,\n                 \"display.sh\": display_sh})\n    os.chmod(os.path.join(client.current_folder, \"display.sh\"), 0o777)\n    client.run(f\"install . -g VirtualBuildEnv -pr=profile {f'-c=tools.env:deactivation_mode={deactivation_mode}' if deactivation_mode else ''} \")\n\n    if platform.system() == \"Windows\":\n        cmd = \"conanbuild.bat && display.bat && deactivate_conanbuild.bat && display.bat\"\n    else:\n        deactivate_cmd = \"deactivate_conanbuild\" if deactivation_mode else \". ./deactivate_conanbuild.sh\"\n        cmd = f'. ./conanbuild.sh && ./display.sh && {deactivate_cmd} && ./display.sh'\n    out, _ = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,\n                              shell=True, cwd=client.current_folder).communicate()\n    out = out.decode()\n    assert \"VAR1= VALUE1!!\" in out\n    assert \"Restoring environment\" in out\n    assert \"VAR1=!!\" in out\n\n\ndef test_deactivate_location():\n    conanfile = textwrap.dedent(r\"\"\"\n        from conan import ConanFile\n        from conan.tools.env import Environment\n        class Pkg(ConanFile):\n            def package_info(self):\n                self.buildenv_info.define(\"FOO\", \"BAR\")\n        \"\"\")\n    client = TestClient()\n    client.save({\"pkg.py\": conanfile})\n    client.run(\"create pkg.py --name pkg --version 1.0\")\n    client.run(\"install --requires pkg/1.0@ -g VirtualBuildEnv -of=myfolder -s build_type=Release -s arch=x86_64\")\n\n    source_cmd, script_ext = (\"myfolder\\\\\", \".bat\") if platform.system() == \"Windows\" else (\". ./myfolder/\", \".sh\")\n    cmd = \"{}conanbuild{}\".format(source_cmd, script_ext)\n\n    subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True,\n                     cwd=client.current_folder).communicate()\n\n    assert not os.path.exists(os.path.join(client.current_folder,\n                                           \"deactivate_conanbuildenv-release-x86_64{}\".format(script_ext)))\n\n    assert os.path.exists(os.path.join(client.current_folder, \"myfolder\",\n                                       \"deactivate_conanbuildenv-release-x86_64{}\".format(script_ext)))\n\n\n@pytest.mark.skipif(platform.system() == \"Windows\", reason=\"Requires sh\")\ndef test_skip_virtualbuildenv_run():\n    # Build require\n    conanfile = textwrap.dedent(r\"\"\"\n           from conan import ConanFile\n           class Pkg(ConanFile):\n               def package_info(self):\n                   self.buildenv_info.define(\"FOO\", \"BAR\")\n           \"\"\")\n    client = TestClient()\n    client.save({\"pkg.py\": conanfile})\n    client.run(\"create pkg.py --name pkg --version 1.0\")\n\n    # consumer\n    conanfile = textwrap.dedent(r\"\"\"\n               import os\n               from conan import ConanFile\n               class Consumer(ConanFile):\n                   tool_requires = \"pkg/1.0\"\n                   exports_sources = \"my_script.sh\"\n                   # This can be removed at Conan 2\n                   generators = \"VirtualBuildEnv\"\n                   def build(self):\n                       path = os.path.join(self.source_folder, \"my_script.sh\")\n                       os.chmod(path, 0o777)\n                       self.run(\"'{}'\".format(path))\n               \"\"\")\n    my_script = 'echo FOO is $FOO'\n    client.save({\"conanfile.py\": conanfile, \"my_script.sh\": my_script})\n    client.run(\"create . --name consumer --version 1.0\")\n    assert \"FOO is BAR\" in client.out\n\n    # If we pass env=None no \"conanbuild\" is applied\n    # self.run(\"'{}'\".format(path), env=None)\n    conanfile = conanfile.replace(\".format(path))\",\n                                  \".format(path), env=None)\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name consumer --version 1.0\")\n    assert \"FOO is BAR\" not in client.out\n\n\ndef test_files_always_created():\n    \"\"\" test that even if there are no env-variables, the generators always create files,\n    they will be mostly empty, but exist\n    \"\"\"\n    c = TestClient()\n    c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\"),\n            \"consumer/conanfile.txt\": \"[requires]\\ndep/0.1\"})\n    c.run(\"create dep\")\n    c.run(\"install consumer -g VirtualBuildEnv -g VirtualRunEnv -of=.\")\n    ext = \"bat\" if platform.system() == \"Windows\" else \"sh\"\n\n    arch = c.get_default_host_profile().settings['arch']\n    assert os.path.isfile(os.path.join(c.current_folder, f\"conanbuild.{ext}\"))\n    assert os.path.isfile(os.path.join(c.current_folder, f\"conanrun.{ext}\"))\n    assert os.path.isfile(os.path.join(c.current_folder, f\"conanbuildenv-release-{arch}.{ext}\"))\n    assert os.path.isfile(os.path.join(c.current_folder, f\"conanbuildenv-release-{arch}.{ext}\"))\n\n\ndef test_error_with_dots_virtualenv():\n    # https://github.com/conan-io/conan/issues/12163\n    tool = textwrap.dedent(r\"\"\"\n        from conan import ConanFile\n        class ToolConan(ConanFile):\n            name = \"tool\"\n            version = \"0.1\"\n            settings = \"arch\", \"os\"\n\n            def package_info(self):\n                self.buildenv_info.define(\"DUMMY\", \"123456\")\n        \"\"\")\n    test_package = textwrap.dedent(r\"\"\"\n        from conan import ConanFile\n        import os\n\n        class ToolTestConan(ConanFile):\n            name = \"app\"\n            version = \"0.1\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"VirtualBuildEnv\"\n\n            def build_requirements(self):\n                self.tool_requires(\"tool/0.1\")\n\n            def build(self):\n                self.run(\"echo DUMMY=$DUMMY\")\n                self.run(\"set\")\n            \"\"\")\n    client = TestClient()\n    client.save({\"dep/conanfile.py\": tool,\n                 \"consumer/conanfile.py\": test_package})\n\n    client.run(\"create dep -s:b arch=armv8.3\")\n    client.run(\"create consumer -s arch=armv8.3\")\n    assert \"DUMMY=123456\" in client.out\n\n\ndef test_runenv_info_propagated():\n    \"\"\"\n    A runenv_info in a recipe, which is required by an executable that is used\n    in another place as a tool_require (also its own test_package), should be\n    propagated\n    test_package --(tool_requires)->tools-(requires)->lib(defines runenv_info)\n    https://github.com/conan-io/conan/issues/12939\n    \"\"\"\n    c = TestClient()\n    # NOTE: The lib contains ``package_type = \"shared-library\"`` to force propagation of runenv_info\n    lib = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Lib(ConanFile):\n            name = \"lib\"\n            version = \"0.1\"\n            settings = \"build_type\"\n            package_type = \"shared-library\"\n            def package_info(self):\n                self.runenv_info.define(\"MYLIBVAR\", f\"MYLIBVALUE:{self.settings.build_type}\")\n        \"\"\")\n    tool_test_package = textwrap.dedent(\"\"\"\n        import platform\n        from conan import ConanFile\n        class TestTool(ConanFile):\n            settings = \"build_type\"\n            generators = \"VirtualBuildEnv\"\n            def build_requirements(self):\n                self.tool_requires(self.tested_reference_str)\n            def build(self):\n                self.output.info(f\"Building TEST_PACKAGE IN {self.settings.build_type}!!\")\n                if platform.system()!= \"Windows\":\n                    self.run(\"echo MYLIBVAR=$MYLIBVAR\")\n                else:\n                    self.run(\"set MYLIBVAR\")\n            def test(self):\n                pass\n        \"\"\")\n    c.save({\"lib/conanfile.py\": lib,\n            \"tool/conanfile.py\": GenConanfile(\"tool\", \"0.1\").with_requires(\"lib/0.1\"),\n            \"tool/test_package/conanfile.py\": tool_test_package})\n    c.run(\"create lib -s build_type=Release\")\n    c.run(\"create tool --build-require -s:b build_type=Release -s:h build_type=Debug\")\n    assert \"tool/0.1 (test package): Building TEST_PACKAGE IN Debug!!\" in c.out\n    assert \"MYLIBVAR=MYLIBVALUE:Release\" in c.out\n\n\ndef test_deactivate_relocatable_substitute():\n    c = TestClient()\n    # this cannot be tested in CI, because permissions over root folder\n    # c.current_folder = \"/build\"\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n    c.run(\"install . -s os=Linux -s:b os=Linux\")\n    conanbuild = c.load(\"conanbuildenv.sh\")\n    result = os.path.join(\"$script_folder\", \"deactivate_conanbuildenv.sh\")\n    assert f'\"{result}\"' in conanbuild\n\n\nclass TestDotEnv:\n    def test_dotenv(self):\n        c = TestClient()\n        other_path = os.path.join(c.current_folder, \"my\", \"rel\", \"path\")\n        myprofile = textwrap.dedent(f\"\"\"\n            [buildenv]\n            MYVAR1=MyVal1\n            MYVAR3+=MyVal3\n            MYPATH+=(path)/some/path/here\n            MYOTHER_PATH=+(path){other_path}\n\n            [runenv]\n            MYRUNVAR=SomeVal1\n\n            [conf]\n            tools.env:dotenv=True\n            \"\"\")\n        c.save({\"conanfile.txt\": \"\",\n                \"myprofile\": myprofile})\n        c.run(\"install . -pr=myprofile -s build_type=Release\")\n        dotenv = c.load(\"conanbuildenv-Release.env\")\n        expected = os.path.join(c.current_folder, \"my\", \"rel\", \"path\")\n        assert f'MYOTHER_PATH=\"{expected}\"' in dotenv\n        assert f'MYPATH=\"/some/path/here\"' in dotenv\n        assert 'MYVAR3=\"MyVal3\"' in dotenv\n        assert 'MYVAR1=\"MyVal1\"' in dotenv\n        dotenv = c.load(\"conanrunenv-Release.env\")\n        assert f'MYRUNVAR=\"SomeVal1\"' in dotenv\n\n    def test_generate_only_dotenv(self):\n        # If for some reason a recipe only wants the dot env files, doable\n        c = TestClient()\n        myprofile = textwrap.dedent(f\"\"\"\n            [buildenv]\n            MYVAR1=MyVal1\n            [runenv]\n            MYRUNVAR=SomeVal1\n            \"\"\")\n        conanfile = textwrap.dedent(f\"\"\"\n            from conan import ConanFile\n            from conan.tools.env import VirtualBuildEnv, VirtualRunEnv\n            class Lib(ConanFile):\n                def generate(self):\n                    VirtualBuildEnv(self).vars().save_dotenv(\"mybuild.env\")\n                    VirtualRunEnv(self)\n            \"\"\")\n        c.save({\"conanfile.py\": conanfile,\n                \"myprofile\": myprofile})\n        c.run(\"install . -pr=myprofile\")\n        assert set(os.listdir(c.current_folder)) == {'conanfile.py', 'mybuild.env', 'myprofile'}\n        assert 'MYVAR1=\"MyVal1\"' in c.load(\"mybuild.env\")\n\n\n@pytest.mark.skipif(platform.system() not in [\"Linux\", \"Darwin\"], reason=\"Requires shell\")\n@pytest.mark.parametrize(\"path\", [False, True])\ndef test_hardened_sh(path):\n    c = TestClient()\n    echo_sh = textwrap.dedent(\"\"\"\n        set -eu\n        . ./conanbuild.sh\n        echo \"MYENVVAR1=$MYENVVAR1!!\"\n        echo \"MYENVVAR2=$MYENVVAR2!!\"\n        echo \"MYENVVAR3=$MYENVVAR3!!\"\n        \"\"\")\n    path = \"(path)\" if path else \"\"\n    myprofile = textwrap.dedent(f\"\"\"\n        [buildenv]\n        MYENVVAR1=+{path}value1\n        MYENVVAR2+={path}value2\n        MYENVVAR3=+{path}value3\n        MYENVVAR3+={path}value4\n        \"\"\")\n    c.save({\"conanfile.txt\": \"\",\n            \"myprofile\": myprofile,\n            \"myecho.sh\": echo_sh})\n    os.chmod(os.path.join(c.current_folder, \"myecho.sh\"), 0o777)\n    c.run(\"install . -pr=myprofile\")\n    c.run_command(\"./myecho.sh\")\n    sep = \":\" if path else \" \"\n    assert \"MYENVVAR1=value1!!\" in c.out\n    assert \"MYENVVAR2=value2!!\" in c.out\n    assert f\"MYENVVAR3=value3{sep}value4!!\" in c.out\n\n    with environment_update({\"MYENVVAR1\": \"init1\", \"MYENVVAR2\": \"init2\", \"MYENVVAR3\": \"init3\"}):\n        c.run_command(\"./myecho.sh\")\n        assert f\"MYENVVAR1=value1{sep}init1!!\" in c.out\n        assert f\"MYENVVAR2=init2{sep}value2!!\" in c.out\n        assert f\"MYENVVAR3=value3{sep}init3{sep}value4!!\" in c.out\n"
  },
  {
    "path": "test/integration/environment/test_runenv_profile.py",
    "content": "import textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.fixture\ndef client():\n    conanfile = textwrap.dedent(\"\"\"\n       from conan import ConanFile\n       class Pkg(ConanFile):\n           generators = \"VirtualRunEnv\"\n           def generate(self):\n               for var in (1, 2):\n                   v = self.runenv.vars(self).get(\"MyVar{}\".format(var))\n                   self.output.info(\"MyVar{}={}!!\".format(var, v))\n       \"\"\")\n    profile1 = textwrap.dedent(\"\"\"\n      [runenv]\n      MyVar1=MyValue1_1\n      MyVar2=MyValue2_1\n      \"\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile,\n                 \"profile1\": profile1})\n    return client\n\n\ndef test_buildenv_profile_cli(client):\n    client.run(\"install . -pr=profile1\")\n    assert \"conanfile.py: MyVar1=MyValue1_1!!\" in client.out\n    assert \"conanfile.py: MyVar2=MyValue2_1!!\" in client.out\n    env = client.load(\"conanrunenv.sh\")\n    assert \"MyValue1_1\" in env\n    assert \"MyValue2_1\" in env\n"
  },
  {
    "path": "test/integration/extensions/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/extensions/hooks/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/extensions/hooks/hook_test.py",
    "content": "import os\nimport textwrap\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import save\n\n\ncomplete_hook = \"\"\"\nimport os\n\ndef pre_export(conanfile):\n    conanfile.output.info(\"Hello\")\n    # TODO: To have the export_folder here needs a bit more deep refactoring\n    assert conanfile.export_folder is None\n    assert conanfile.recipe_folder, \"recipe_folder not defined\"\n\ndef post_export(conanfile):\n    conanfile.output.info(\"Hello\")\n    assert conanfile.export_folder, \"export_folder not defined\"\n    assert conanfile.export_sources_folder, \"export_sources_folder not defined\"\n    assert conanfile.recipe_folder, \"recipe_folder not defined\"\n\ndef pre_validate(conanfile):\n    conanfile.output.info(\"Hello\")\n\ndef post_validate(conanfile):\n    conanfile.output.info(\"Hello\")\n\ndef pre_source(conanfile):\n    conanfile.output.info(\"Hello\")\n    assert conanfile.source_folder, \"source_folder not defined\"\n\ndef post_source(conanfile):\n    conanfile.output.info(\"Hello\")\n    assert conanfile.source_folder, \"source_folder not defined\"\n\ndef pre_generate(conanfile):\n    conanfile.output.info(\"Hello\")\n    assert conanfile.generators_folder, \"generators_folder not defined\"\n\ndef post_generate(conanfile):\n    conanfile.output.info(\"Hello\")\n    assert conanfile.generators_folder, \"generators_folder not defined\"\n\ndef pre_build(conanfile):\n    conanfile.output.info(\"Hello\")\n    assert conanfile.source_folder, \"source_folder not defined\"\n    assert conanfile.build_folder, \"build_folder not defined\"\n\ndef post_build(conanfile):\n    conanfile.output.info(\"Hello\")\n    assert conanfile.source_folder, \"source_folder not defined\"\n    assert conanfile.build_folder, \"build_folder not defined\"\n\ndef pre_package(conanfile):\n    conanfile.output.info(\"Hello\")\n    assert conanfile.source_folder, \"source_folder not defined\"\n    assert conanfile.build_folder, \"build_folder not defined\"\n    assert conanfile.package_folder, \"package_folder not defined\"\n\ndef post_package(conanfile):\n    conanfile.output.info(\"Hello\")\n    assert conanfile.source_folder, \"source_folder not defined\"\n    assert conanfile.build_folder, \"build_folder not defined\"\n    assert conanfile.package_folder, \"package_folder not defined\"\n\ndef pre_package_info(conanfile):\n    conanfile.output.info(\"Hello\")\n\ndef post_package_info(conanfile):\n    conanfile.output.info(\"Hello\")\n\ndef post_package_id(conanfile):\n    conanfile.output.info(\"Hello\")\n\"\"\"\n\n\nclass TestHooks:\n\n    def test_complete_hook(self):\n        c = TestClient()\n        hook_path = os.path.join(c.paths.hooks_path, \"complete_hook\", \"hook_complete.py\")\n        save(hook_path, complete_hook)\n        c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n\n        c.run(\"source .\")\n        hook_msg = \"[HOOK - complete_hook/hook_complete.py]\"\n        assert f\"conanfile.py (pkg/0.1): {hook_msg} pre_source(): Hello\" in c.out\n        assert f\"conanfile.py (pkg/0.1): {hook_msg} post_source(): Hello\" in c.out\n\n        c.run(\"install .\")\n        assert f\"conanfile.py (pkg/0.1): {hook_msg} pre_validate(): Hello\" in c.out\n        assert f\"conanfile.py (pkg/0.1): {hook_msg} post_validate(): Hello\" in c.out\n        assert f\"conanfile.py (pkg/0.1): {hook_msg} pre_generate(): Hello\" in c.out\n        assert f\"conanfile.py (pkg/0.1): {hook_msg} post_generate(): Hello\" in c.out\n\n        c.run(\"build .\")\n        assert f\"conanfile.py (pkg/0.1): {hook_msg} pre_validate(): Hello\" in c.out\n        assert f\"conanfile.py (pkg/0.1): {hook_msg} post_validate(): Hello\" in c.out\n        assert f\"conanfile.py (pkg/0.1): {hook_msg} pre_build(): Hello\" in c.out\n        assert f\"conanfile.py (pkg/0.1): {hook_msg} post_build(): Hello\" in c.out\n        assert f\"conanfile.py (pkg/0.1): {hook_msg} pre_generate(): Hello\" in c.out\n        assert f\"conanfile.py (pkg/0.1): {hook_msg} post_generate(): Hello\" in c.out\n\n        c.run(\"export . \")\n        assert f\"pkg/0.1: {hook_msg} pre_export(): Hello\" in c.out\n        assert f\"pkg/0.1: {hook_msg} post_export(): Hello\" in c.out\n\n        c.run(\"export-pkg . \")\n        assert f\"pkg/0.1: {hook_msg} pre_export(): Hello\" in c.out\n        assert f\"pkg/0.1: {hook_msg} post_export(): Hello\" in c.out\n        assert f\"conanfile.py (pkg/0.1): {hook_msg} pre_package(): Hello\" in c.out\n        assert f\"conanfile.py (pkg/0.1): {hook_msg} post_package(): Hello\" in c.out\n        assert f\"conanfile.py (pkg/0.1): {hook_msg} post_package_id(): Hello\" in c.out\n\n        c.run(\"create . \")\n        assert f\"pkg/0.1: {hook_msg} pre_validate(): Hello\" in c.out\n        assert f\"pkg/0.1: {hook_msg} post_validate(): Hello\" in c.out\n        assert f\"pkg/0.1: {hook_msg} pre_export(): Hello\" in c.out\n        assert f\"pkg/0.1: {hook_msg} post_export(): Hello\" in c.out\n        assert f\"pkg/0.1: {hook_msg} pre_source(): Hello\" in c.out\n        assert f\"pkg/0.1: {hook_msg} post_source(): Hello\" in c.out\n        assert f\"pkg/0.1: {hook_msg} pre_build(): Hello\" in c.out\n        assert f\"pkg/0.1: {hook_msg} post_build(): Hello\" in c.out\n        assert f\"pkg/0.1: {hook_msg} pre_package(): Hello\" in c.out\n        assert f\"pkg/0.1: {hook_msg} post_package(): Hello\" in c.out\n        assert f\"pkg/0.1: {hook_msg} pre_package_info(): Hello\" in c.out\n        assert f\"pkg/0.1: {hook_msg} post_package_info(): Hello\" in c.out\n        assert f\"pkg/0.1: {hook_msg} post_package_id(): Hello\" in c.out\n\n    def test_import_hook(self):\n        \"\"\" Test that a hook can import another random python file\n        \"\"\"\n        custom_module = textwrap.dedent(\"\"\"\n            def my_printer(output):\n                output.info(\"my_printer(): CUSTOM MODULE\")\n            \"\"\")\n\n        my_hook = textwrap.dedent(\"\"\"\n            from custom_module.custom import my_printer\n\n            def pre_export(conanfile):\n                my_printer(conanfile.output)\n            \"\"\")\n        c = TestClient()\n        hook_path = os.path.join(c.paths.hooks_path, \"my_hook\", \"hook_my_hook.py\")\n        init_path = os.path.join(c.paths.hooks_path, \"my_hook\", \"custom_module\", \"__init__.py\")\n        custom_path = os.path.join(c.paths.hooks_path, \"my_hook\", \"custom_module\", \"custom.py\")\n        c.save({init_path: \"\",\n                custom_path: custom_module,\n                hook_path: my_hook,\n                \"conanfile.py\": GenConanfile(\"pkg\", \"1.0\")})\n\n        c.run(\"export . \")\n        assert \"[HOOK - my_hook/hook_my_hook.py] pre_export(): my_printer(): CUSTOM MODULE\" \\\n               in c.out\n\n    def test_hook_raising(self):\n        \"\"\" Test output when a hook raises\n        \"\"\"\n        c = TestClient()\n        my_hook = textwrap.dedent(\"\"\"\n            def pre_export(conanfile):\n                raise Exception(\"Boom\")\n            \"\"\")\n        hook_path = os.path.join(c.paths.hooks_path, \"my_hook\", \"hook_my_hook.py\")\n        c.save({hook_path: my_hook,\n                \"conanfile.py\": GenConanfile(\"pkg\", \"1.0\")})\n\n        c.run(\"export . \", assert_error=True)\n        assert \"ERROR: [HOOK - my_hook/hook_my_hook.py] pre_export(): Boom\" in c.out\n\n    def test_post_build_fail(self):\n        \"\"\" Test the post_build_fail hook\n        \"\"\"\n        c = TestClient()\n        my_hook = textwrap.dedent(\"\"\"\n           def post_build_fail(conanfile):\n               conanfile.output.info(\"Hello\")\n           \"\"\")\n        hook_path = os.path.join(c.paths.hooks_path, \"my_hook\", \"hook_my_hook.py\")\n        save(hook_path, my_hook)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                def build(self):\n                    raise Exception(\"Boom!\")\n            \"\"\")\n        c.save({\"conanfile.py\": conanfile})\n\n        c.run(\"build . \", assert_error=True)\n        assert \"conanfile.py: [HOOK - my_hook/hook_my_hook.py] post_build_fail(): Hello\" in c.out\n        assert \"ERROR: conanfile.py: Error in build() method, line 5\" in c.out\n\n    def test_validate_hook(self):\n        \"\"\" The validate hooks are executed only if the method is declared in the recipe.\n        \"\"\"\n        c = TestClient()\n        hook_path = os.path.join(c.paths.hooks_path, \"testing\", \"hook_complete.py\")\n        save(hook_path, complete_hook)\n\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                def validate(self):\n                    pass\n            \"\"\")\n        c.save({\"conanfile.py\": conanfile})\n\n        c.run(\"create . --name=foo --version=0.1.0\")\n        assert f\"foo/0.1.0: [HOOK - testing/hook_complete.py] pre_validate(): Hello\" in c.out\n        assert f\"foo/0.1.0: [HOOK - testing/hook_complete.py] post_validate(): Hello\" in c.out\n\n\n@pytest.mark.parametrize(\"hook_name\", [\"pre_validate\", \"post_validate\"])\ndef test_validate_invalid_configuration(hook_name):\n    \"\"\" When raising ConanInvalidConfiguration in the pre_validate and post_validate hooks,\n        it should be forwarded and preserve the same exception type.\n    \"\"\"\n    hook = textwrap.dedent(f\"\"\"\n        from conan.errors import ConanInvalidConfiguration\n        def {hook_name}(conanfile):\n            raise ConanInvalidConfiguration(\"Invalid configuration in {hook_name} hook\")\n    \"\"\")\n\n    conanfile = textwrap.dedent(f\"\"\"\n        from conan import ConanFile\n        from conan.errors import ConanException\n\n        class Pkg(ConanFile):\n            def validate(self):\n                if \"{hook_name}\" == \"pre_validate\":\n                    raise ConanException(\"Should not reach this point\")\n    \"\"\")\n\n    client = TestClient()\n    hook_path = os.path.join(client.paths.hooks_path, \"custom_hooks\", \"hook_pre_validate.py\")\n    client.save({\"conanfile.py\": conanfile,\n                 hook_path: hook})\n\n    client.run(\"build . \", assert_error=True)\n    assert f\"ERROR: conanfile.py: Invalid ID: Invalid: Invalid configuration in {hook_name} hook\" in client.out\n    assert \"Should not reach this point\" not in client.out\n"
  },
  {
    "path": "test/integration/extensions/hooks/test_post_export.py",
    "content": "import os\nimport textwrap\n\nfrom conan.internal.model.manifest import FileTreeManifest\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import save\n\n\ndef test_called_before_digest():\n    \"\"\" Test that 'post_export' hook is called before computing the digest of the\n        exported folders\n    \"\"\"\n    t = TestClient()\n    complete_hook = textwrap.dedent(\"\"\"\\\n        import os\n        from conan.tools.files import save\n        def post_export(conanfile):\n            save(conanfile, os.path.join(conanfile.export_folder, \"myfile.txt\"), \"content!!\")\n        \"\"\")\n    hook_path = os.path.join(t.paths.hooks_path, \"complete_hook\", \"hook_complete.py\")\n    save(hook_path, complete_hook)\n    t.save({'conanfile.py': GenConanfile(\"pkg\", \"0.1\")})\n    t.run(\"export .\")\n    ref_layout = t.exported_layout()\n    manifest = FileTreeManifest.load(ref_layout.export())\n    assert \"myfile.txt\" in manifest.file_sums\n"
  },
  {
    "path": "test/integration/extensions/hooks/test_post_package.py",
    "content": "import os\nimport textwrap\n\nfrom conan.internal.model.manifest import FileTreeManifest\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import save\n\n\ndef test_post_package():\n    \"\"\" Test that 'post_package' hook is called before computing the manifest\n    \"\"\"\n    t = TestClient()\n    complete_hook = textwrap.dedent(\"\"\"\\\n        import os\n        from conan.tools.files import save\n        def post_package(conanfile):\n            save(conanfile, os.path.join(conanfile.package_folder, \"myfile.txt\"), \"content!!\")\n        \"\"\")\n    hook_path = os.path.join(t.paths.hooks_path, \"complete_hook\", \"hook_complete.py\")\n    save(hook_path, complete_hook)\n    t.save({'conanfile.py': GenConanfile(\"pkg\", \"0.1\")})\n    t.run(\"create .\")\n    pref_layout = t.created_layout()\n    manifest = FileTreeManifest.load(pref_layout.package())\n    assert \"myfile.txt\" in manifest.file_sums\n\n    t.run(\"remove * -c\")\n    t.run(\"export-pkg .\")\n    pref_layout = t.created_layout()\n    manifest = FileTreeManifest.load(pref_layout.package())\n    assert \"myfile.txt\" in manifest.file_sums\n"
  },
  {
    "path": "test/integration/extensions/test_cppstd_compat.py",
    "content": "import textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_compatible_cppstd():\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            settings = \"os\", \"compiler\"\n\n            def package_info(self):\n                self.output.info(\"PackageInfo!: Cppstd version: %s!\"\n                                 % self.settings.compiler.cppstd)\n        \"\"\")\n    profile = textwrap.dedent(\"\"\"\n        [settings]\n        os = Linux\n        compiler=gcc\n        compiler.version=12\n        compiler.libcxx=libstdc++\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile,\n            \"myprofile\": profile})\n    # Create package with cppstd 17\n    c.run(\"create .  -pr=myprofile -s compiler.cppstd=17\")\n    package_id = \"95dcfeb51c04968b4ee960ee393cf2c1ebcf7782\"\n    assert f\"pkg/0.1: Package '{package_id}' created\" in c.out\n\n    # package can be used with a profile gcc cppstd20 falling back to 17\n    c.save({\"conanfile.py\": GenConanfile().with_require(\"pkg/0.1\")})\n    c.run(\"install . -pr=myprofile -s compiler.cppstd=20\")\n    assert f\"Using compatible package '{package_id}'\"\n    assert \"pkg/0.1: PackageInfo!: Cppstd version: 17!\" in c.out\n    c.assert_listed_binary({\"pkg/0.1\": (f\"{package_id}\", \"Cache\")})\n    assert \"pkg/0.1: Already installed!\" in c.out\n\n\ndef test_compatible_cppstd_missing_compiler():\n    c = TestClient()\n    settings_user = textwrap.dedent(\"\"\"\n    compiler:\n        mycompiler:\n            version: [\"12\"]\n            libcxx: [\"libstdc++\"]\n            cppstd: [15, 17, 20]\n    \"\"\")\n    conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                settings = \"os\", \"compiler\"\n\n                def package_info(self):\n                    self.output.info(\"PackageInfo!: Cppstd version: %s!\"\n                                     % self.settings.compiler.cppstd)\n            \"\"\")\n    profile = textwrap.dedent(\"\"\"\n            [settings]\n            os = Linux\n            compiler=mycompiler\n            compiler.version=12\n            compiler.libcxx=libstdc++\n            \"\"\")\n    c.save({\"conanfile.py\": conanfile,\n            \"myprofile\": profile})\n    c.save_home({\"settings_user.yml\": settings_user})\n    # Create package with cppstd 17\n    c.run(\"create .  -pr=myprofile -s compiler.cppstd=17\")\n    package_id = \"51a90090adb1cbd330a64b4c3b3b32af809af4f9\"\n    assert f\"pkg/0.1: Package '{package_id}' created\" in c.out\n\n    # package can't be used with cppstd 20 and fallback to 17, because mycompiler is not known\n    # to the default cppstd_compat function. Ensure that it does not break and warns the user\n    c.save({\"conanfile.py\": GenConanfile().with_require(\"pkg/0.1\")})\n    c.run(\"install . -pr=myprofile -s compiler.cppstd=20\", assert_error=True)\n    assert \"Missing binary: pkg/0.1:b4b07859713551e8aac612f8080888c58b4711ae\" in c.out\n    assert 'pkg/0.1: WARN: No cppstd compatibility defined for compiler \"mycompiler\"' in c.out\n"
  },
  {
    "path": "test/integration/extensions/test_plugin_cmd_wrapper.py",
    "content": "import os\nimport textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import save\n\n\ndef test_plugin_cmd_wrapper():\n    c = TestClient()\n    plugins = os.path.join(c.cache_folder, \"extensions\", \"plugins\")\n    wrapper = textwrap.dedent(\"\"\"\n        def cmd_wrapper(cmd, **kwargs):\n            return 'echo \"{}\"'.format(cmd)\n        \"\"\")\n    save(os.path.join(plugins, \"cmd_wrapper.py\"), wrapper)\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            def generate(self):\n                self.run(\"Hello world\")\n                self.run(\"Other stuff\")\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"install .\")\n    assert 'Hello world' in c.out\n    assert 'Other stuff' in c.out\n\n\ndef test_plugin_cmd_wrapper_conanfile():\n    \"\"\"\n    we can get the name of the caller conanfile too\n    \"\"\"\n    c = TestClient()\n    plugins = os.path.join(c.cache_folder, \"extensions\", \"plugins\")\n    wrapper = textwrap.dedent(\"\"\"\n        def cmd_wrapper(cmd, conanfile, **kwargs):\n            return 'echo \"{}!:{}!\"'.format(conanfile.ref, cmd)\n        \"\"\")\n    save(os.path.join(plugins, \"cmd_wrapper.py\"), wrapper)\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            def generate(self):\n                self.run(\"Hello world\")\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"install . --name=pkg --version=0.1\")\n    assert 'pkg/0.1!:Hello world!' in c.out\n\n\ndef test_plugin_profile_error_vs():\n    c = TestClient()\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\")})\n    c.run(\"create . -s compiler=msvc -s compiler.version=15 -s compiler.cppstd=14\",\n          assert_error=True)\n    assert \"The provided compiler.cppstd=14 is not supported by msvc 15. Supported values are: []\" in c.out\n    c.run(\"create . -s compiler=msvc -s compiler.version=170 -s compiler.cppstd=14\",\n          assert_error=True)\n    assert \"The provided compiler.cppstd=14 is not supported by msvc 170. Supported values are: []\" in c.out\n    c.run(\"create . -s compiler=msvc -s compiler.version=190 -s compiler.cppstd=14\")\n    assert \"Installing packages\" in c.out\n\n\ndef test_plugin_profile_error_vscstd():\n    c = TestClient()\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_class_attribute(\"languages = 'C'\")})\n    c.run(\"create . -s compiler=msvc -s compiler.version=190 -s compiler.cstd=23\", assert_error=True)\n    assert \"The provided compiler.cstd=23 is not supported by msvc 190. Supported values are: []\" in c.out\n    c.run(\"create . -s compiler=msvc -s compiler.version=193 -s compiler.cstd=23\", assert_error=True)\n    assert \"The provided compiler.cstd=23 is not supported by msvc 193. Supported values are: ['11', '17']\" in c.out\n    c.run(\"create . -s compiler=msvc -s compiler.version=193 -s compiler.cstd=17\")\n    assert \"Installing packages\" in c.out\n"
  },
  {
    "path": "test/integration/extensions/test_profile_plugin.py",
    "content": "import pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.parametrize(\"compiler, version, cppstd, correct\", [\n    (\"gcc\", \"4.1\", \"11\", False),\n    (\"gcc\", \"4.4\", \"11\", True),\n    (\"gcc\", \"4.4\", \"14\", False),\n    (\"gcc\", \"4.4\", \"17\", False),\n    (\"gcc\", \"4.4\", \"20\", False),\n    (\"gcc\", \"4.8\", \"11\", True),\n    (\"gcc\", \"4.8\", \"14\", True),\n    (\"gcc\", \"4.8\", \"17\", False),\n    (\"gcc\", \"4.8\", \"20\", False),\n    (\"gcc\", \"5\", \"17\", True),\n    (\"gcc\", \"5\", \"20\", False),\n    (\"gcc\", \"8\", \"17\", True),\n    (\"gcc\", \"8\", \"20\", True),\n    (\"clang\", \"3.3\", \"11\", True),\n    (\"clang\", \"3.3\", \"14\", False),\n    (\"clang\", \"3.4\", \"14\", True),\n    (\"clang\", \"3.4\", \"17\", False),\n    (\"clang\", \"3.5\", \"17\", True),\n    (\"clang\", \"3.5\", \"20\", False),\n    (\"clang\", \"5.0\", \"20\", False),\n    (\"clang\", \"6.0\", \"20\", True),\n    (\"apple-clang\", \"5.0\", \"98\", True),\n    (\"apple-clang\", \"5.0\", \"11\", True),\n    (\"apple-clang\", \"5.1\", \"14\", True),\n    (\"apple-clang\", \"5.1\", \"17\", False),\n    (\"apple-clang\", \"6.1\", \"17\", True),\n    (\"apple-clang\", \"6.1\", \"20\", False),\n    (\"apple-clang\", \"10.0\", \"20\", True),\n    (\"msvc\", \"170\", \"14\", False),\n    (\"msvc\", \"190\", \"14\", True),\n    (\"msvc\", \"190\", \"20\", False),\n    (\"msvc\", \"191\", \"14\", True),\n    (\"msvc\", \"191\", \"17\", True),\n    (\"msvc\", \"191\", \"20\", False),\n    (\"msvc\", \"193\", \"20\", True)\n])\ndef test_invalid_cppstd(compiler, version, cppstd, correct):\n    c = TestClient()\n    c.save({\"conanfile.py\": GenConanfile()})\n    c.run(\"install . -s compiler={} -s compiler.version={} \"\n          \"-s compiler.cppstd={}\".format(compiler, version, cppstd), assert_error=not correct)\n    if not correct:\n        assert \"ConanException: The provided compiler.cppstd\" in c.out\n"
  },
  {
    "path": "test/integration/extensions/test_profile_plugin_runtime.py",
    "content": "import platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Only windows\")\nclass TestConanSettingsPreprocessor:\n\n    def test_runtime_auto(self):\n        c = TestClient()\n        # Ensure that compiler.runtime is now in the default Win MSVC profile\n        default_profile = c.load_home(\"profiles/default\")\n        assert \"compiler.runtime\" in default_profile\n\n        conanfile = textwrap.dedent(\"\"\"\\\n            from conan import ConanFile\n\n            class HelloConan(ConanFile):\n                name = \"hello0\"\n                version = \"0.1\"\n                settings = \"os\", \"compiler\", \"build_type\"\n\n                def configure(self):\n                    self.output.info(f\"Runtime_type: {self.settings.compiler.runtime_type}\")\n            \"\"\")\n\n        c.save({\"conanfile.py\": conanfile})\n        c.run(\"create .\")\n        assert \"Runtime_type: Release\" in c.out\n        c.run(\"create . -s build_type=Debug\")\n        assert \"Runtime_type: Debug\" in c.out\n\n    def test_runtime_not_present_ok(self):\n        c = TestClient()\n        c.save({\"conanfile.txt\": \"\"})\n        c.run(\"install .\")\n        default_settings = c.load_home(\"settings.yml\")\n        default_settings = default_settings.replace(\"runtime:\", \"# runtime:\")\n        default_settings = default_settings.replace(\"runtime_type:\", \"# runtime_type:\")\n        profile = \"[settings]\\nos=Windows\\ncompiler=msvc\\ncompiler.version=191\"\n        c.save_home({\"settings.yml\": default_settings,\n                     \"profiles/default\": profile})\n        # Ensure the runtime setting is not there anymore\n        c.run('install . -s compiler.runtime=\"dynamic\"', assert_error=True)\n        assert \"'settings.compiler.runtime' doesn't exist for 'msvc'\" in c.out\n\n        # Now install, the preprocessor shouldn't fail nor do anything\n        c.run(\"install .\")\n        assert \"Installing packages\" in c.out\n"
  },
  {
    "path": "test/integration/generators/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/generators/generators_test.py",
    "content": "from conan.test.utils.tools import TestClient\n\n\nclass TestGenerators:\n\n    def test_error(self):\n        client = TestClient()\n        client.save({\"conanfile.txt\": \"[generators]\\nunknown\"})\n        client.run(\"install . --build=*\", assert_error=True)\n        assert \"ERROR: Invalid generator 'unknown'. Available types:\" in client.out\n"
  },
  {
    "path": "test/integration/generators/order_libs_test.py",
    "content": "import platform\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_library_order():\n    #\n    # project -> sdl2_ttf -> freetype ------------> bzip2\n    #             \\             \\----->libpng  -> zlib\n    #              \\------> sdl2----------------->/\n    # Order: sdl2_ttf freetype sdl2 libpng zlib bzip\n\n    c = TestClient()\n\n    def _export(libname, refs=None):\n        conanfile = GenConanfile(libname, \"0.1\").with_package_info(cpp_info={\"libs\": [libname]})\n        for r in refs or []:\n            conanfile.with_requires(f\"{r}/0.1\")\n        c.save({\"conanfile.py\": conanfile}, clean_first=True)\n        c.run(\"export .\")\n\n    _export(\"zlib\")\n    _export(\"bzip2\")\n    _export(\"sdl2\", [\"zlib\"])\n    _export(\"libpng\", [\"zlib\"])\n    _export(\"freetype\", [\"bzip2\", \"libpng\"])\n    _export(\"sdl2_ttf\", [\"freetype\", \"sdl2\"])\n    _export(\"app\", [\"sdl2_ttf\"])\n\n    c.run(\"install . --build missing -g AutotoolsDeps\")\n\n    deps = \"conanautotoolsdeps.bat\" if platform.system() == \"Windows\" else \"conanautotoolsdeps.sh\"\n    autotoolsdeps = c.load(deps)\n    assert '-lsdl2_ttf -lfreetype -lsdl2 -llibpng -lzlib -lbzip2' in autotoolsdeps\n\n\n# TODO: Add a test that manages too system libs\n"
  },
  {
    "path": "test/integration/generators/test_custom_global_generators.py",
    "content": "import os\nimport textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import save\n\n\ndef test_custom_global_generator():\n    c = TestClient()\n    generator = textwrap.dedent(\"\"\"\n        class MyCustomGenerator:\n            def __init__(self, conanfile):\n                self._conanfile = conanfile\n            def generate(self):\n                pkg = self._conanfile.dependencies[\"pkg\"].ref\n                self._conanfile.output.info(f\"DEP: {pkg}!!\")\n        \"\"\")\n    save(os.path.join(c.paths.custom_generators_path, \"mygen.py\"), generator)\n    conanfile = textwrap.dedent(\"\"\"\n        [requires]\n        pkg/0.1\n\n        [generators]\n        MyCustomGenerator\n        \"\"\")\n    c.save({\"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\"),\n            \"conanfile.txt\": conanfile})\n    c.run(\"create pkg\")\n    c.run(\"install .\")\n    assert \"conanfile.txt: Generator 'MyCustomGenerator' calling 'generate()'\" in c.out\n    assert \"conanfile.txt: DEP: pkg/0.1!!\" in c.out\n\n    # By CLI also works\n    conanfile = textwrap.dedent(\"\"\"\n        [requires]\n        pkg/0.1\n        \"\"\")\n    c.save({\"conanfile.txt\": conanfile})\n    c.run(\"install . -g MyCustomGenerator\")\n    assert \"conanfile.txt: Generator 'MyCustomGenerator' calling 'generate()'\" in c.out\n    assert \"conanfile.txt: DEP: pkg/0.1!!\" in c.out\n\n    # In conanfile.py also works\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class MyPkg(ConanFile):\n            requires = \"pkg/0.1\"\n            generators = \"MyCustomGenerator\"\n            \"\"\")\n    c.save({\"conanfile.py\": conanfile}, clean_first=True)\n    c.run(\"install . \")\n    assert \"conanfile.py: Generator 'MyCustomGenerator' calling 'generate()'\" in c.out\n    assert \"conanfile.py: DEP: pkg/0.1!!\" in c.out\n\n\ndef test_custom_global_generator_imports():\n    \"\"\"\n    our custom generator can use python imports\n    \"\"\"\n    c = TestClient()\n    generator = textwrap.dedent(\"\"\"\n        from _myfunc import mygenerate\n\n        class MyCustomGenerator:\n            def __init__(self, conanfile):\n                self._conanfile = conanfile\n            def generate(self):\n                mygenerate(self._conanfile)\n        \"\"\")\n    myaux = textwrap.dedent(\"\"\"\n        def mygenerate(conanfile):\n            conanfile.output.info(\"MYGENERATE WORKS!!\")\n        \"\"\")\n    save(os.path.join(c.paths.custom_generators_path, \"mygen.py\"), generator)\n    save(os.path.join(c.paths.custom_generators_path, \"_myfunc.py\"), myaux)\n\n    c.save({\"conanfile.txt\": \"\"})\n    c.run(\"install . -g MyCustomGenerator\")\n    assert \"conanfile.txt: Generator 'MyCustomGenerator' calling 'generate()'\" in c.out\n    assert \"conanfile.txt: MYGENERATE WORKS!!\" in c.out\n\n\ndef test_custom_global_generator_multiple():\n    \"\"\"\n    multiple custom generators with different names load correctly\n    \"\"\"\n    c = TestClient()\n    for num in range(3):\n        generator = textwrap.dedent(f\"\"\"\n            class MyGenerator{num}:\n                def __init__(self, conanfile):\n                    self._conanfile = conanfile\n                def generate(self):\n                    self._conanfile.output.info(f\"MyGenerator{num}!!\")\n            \"\"\")\n        save(os.path.join(c.paths.custom_generators_path, f\"mygen{num}.py\"), generator)\n    conanfile = textwrap.dedent(\"\"\"\n        [requires]\n        pkg/0.1\n\n        [generators]\n        MyGenerator0\n        MyGenerator1\n        MyGenerator2\n        \"\"\")\n    c.save({\"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\"),\n            \"conanfile.txt\": conanfile})\n    c.run(\"create pkg\")\n    c.run(\"install .\")\n    assert \"conanfile.txt: Generator 'MyGenerator0' calling 'generate()'\" in c.out\n    assert \"conanfile.txt: Generator 'MyGenerator1' calling 'generate()'\" in c.out\n    assert \"conanfile.txt: Generator 'MyGenerator2' calling 'generate()'\" in c.out\n    assert \"conanfile.txt: MyGenerator0!!\" in c.out\n    assert \"conanfile.txt: MyGenerator1!!\" in c.out\n    assert \"conanfile.txt: MyGenerator2!!\" in c.out\n"
  },
  {
    "path": "test/integration/generators/test_generators_from_br.py",
    "content": "import json\nimport textwrap\n\nfrom conan.test.utils.tools import GenConanfile, TestClient\n\n\ndef test_inject_generators_conf():\n    tc = TestClient(light=True)\n    tc.save({\"tool/conanfile.py\": textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class MyGenerator:\n            def __init__(self, conanfile):\n                self.conanfile = conanfile\n\n            def generate(self):\n                self.conanfile.output.info(\"MyGenerator generated\")\n\n        class ToolConan(ConanFile):\n            name = \"tool\"\n            version = \"0.1\"\n\n            def package_info(self):\n                self.generator_info = [\"CMakeToolchain\", MyGenerator]\n        \"\"\")})\n\n    tc.save({\"consumer/conanfile.py\": GenConanfile(\"consumer\", \"0.1\")\n                .with_tool_requires(\"tool/0.1\")\n                .with_class_attribute(\"generators = 'VirtualBuildEnv', 'VirtualRunEnv'\")})\n\n    tc.run(\"create tool\")\n    tc.run(\"create consumer\")\n    assert \"WARN: experimental: Tool-require tool/0.1 adding generators: \" \\\n           \"['CMakeToolchain', 'MyGenerator']\" in tc.out\n    assert \"Generator 'CMakeToolchain' calling 'generate()'\" in tc.out\n    assert \"Generator 'MyGenerator' calling 'generate()'\" in tc.out\n    assert \"Generator 'VirtualBuildEnv' calling 'generate()'\" in tc.out\n    assert \"Generator 'VirtualRunEnv' calling 'generate()'\" in tc.out\n    assert \"CMakeToolchain generated: conan_toolchain.cmake\" in tc.out\n    assert \"MyGenerator generated\" in tc.out\n\n\ndef test_inject_generators_error():\n    c = TestClient(light=True)\n    c.save({\"conanfile.py\": textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class ToolConan(ConanFile):\n            name = \"tool\"\n            version = \"0.1\"\n\n            def package_info(self):\n                self.generator_info = \"CMakeToolchain\"\n        \"\"\")})\n    c.run(\"create .\")\n    c.run(\"install --tool-requires=tool/0.1\", assert_error=True)\n    assert \"ERROR: tool/0.1 'generator_info' must be a list\" in c.out\n\n\ndef test_inject_vars():\n    tc = TestClient(light=True)\n    tc.save({\n        \"tool/envars_generator1.sh\": textwrap.dedent(\"\"\"\n        export VAR1=\"value1\"\n        export PATH=\"$PATH:/additional/path\"\n        \"\"\"),\n        \"tool/envars_generator2.sh\": textwrap.dedent(\"\"\"\n        export VAR2=\"value2\"\n        \"\"\"),\n        \"tool/conanfile.py\": textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.env import create_env_script, register_env_script\n        import os\n\n        class GeneratorSet:\n            def __init__(self, conanfile):\n                self.conanfile = conanfile\n\n            def generate(self):\n                content = 'call envars_generator.sh'\n                name = f\"conantest.sh\"\n                create_env_script(self.conanfile, content, name)\n                register_env_script(self.conanfile, \"tool/envars_generator2.sh\")\n\n        class ToolConan(ConanFile):\n            name = \"tool\"\n            version = \"0.1\"\n\n            def package_info(self):\n                self.generator_info = [GeneratorSet]\n        \"\"\")})\n\n    tc.run(\"create tool\")\n    tc.run(f\"install --tool-requires=tool/0.1\")\n\n    content = tc.load(\"conanbuild.sh\")\n    assert \"conantest.sh\" in content\n    assert \"envars_generator2.sh\" in content\n\n\ndef test_json_serialization_error():\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class MyGenerator:\n            def __init__(self, conanfile):\n                self._conanfile = conanfile\n\n            def generate(self):\n                pass\n\n        class MyToolReq(ConanFile):\n            name = \"mygenerator-tool\"\n            version = \"1.0\"\n\n            def package_info(self):\n                self.generator_info = [MyGenerator]\n        \"\"\")\n\n    c.save({\"tool/conanfile.py\": conanfile})\n    c.run(\"create tool\")\n    c.run(\"install --tool-requires=mygenerator-tool/1.0 --format=json\")\n    graph = json.loads(c.stdout)\n    assert graph[\"graph\"][\"nodes\"][\"0\"][\"generators\"] == [\"MyGenerator\"]\n"
  },
  {
    "path": "test/integration/graph/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/graph/conflict_diamond_test.py",
    "content": "import json\nimport os\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestConflictDiamondTest:\n    def test_version_diamond_conflict(self):\n        \"\"\"\n        test that we obtain a version conflict with a diamond, and that we can fix it by\n        defining an override in the \"game\" consumer\n        game -> engine/1.0 -> math/1.0\n          |---> ai/1.0 -----> math/1.0.1 (conflict)\n        \"\"\"\n        c = TestClient(light=True)\n        c.save({\"math/conanfile.py\": GenConanfile(\"math\"),\n                \"engine/conanfile.py\": GenConanfile(\"engine\", \"1.0\").with_requires(\"math/1.0\"),\n                \"ai/conanfile.py\": GenConanfile(\"ai\", \"1.0\").with_requires(\"math/1.0.1\"),\n                \"game/conanfile.py\": GenConanfile(\"game\", \"1.0\").with_requires(\"engine/1.0\",\n                                                                               \"ai/1.0\"),\n                })\n        c.run(\"create math --version=1.0\")\n        c.run(\"create math --version=1.0.1\")\n        c.run(\"create math --version=1.0.2\")\n        c.run(\"create engine\")\n        c.run(\"create ai\")\n        c.run(\"install game\", assert_error=True)\n        assert \"Version conflict: Conflict between math/1.0.1 and math/1.0 in the graph\" in c.out\n        # This shouldnt error, so we are able to diagnose our dependency graph\n        # The UX still need to be improved, but this is start\n        c.run(\"graph info game --filter=requires\", assert_error=True)\n        assert \"math/1.0\" in c.out\n\n        def _game_conanfile(version, reverse=False):\n            if reverse:\n                \"\"\"\n                 game ---(override)--_> math/newversion\n                    |---> engine/1.0 -> math/1.0\n                    |---> ai/1.0 -----> math/1.0.1 (conflict solved by override)\n                \"\"\"\n                return GenConanfile(\"game\", \"1.0\")\\\n                    .with_requirement(f\"math/{version}\", override=True)\\\n                    .with_requirement(\"engine/1.0\")\\\n                    .with_requirement(\"ai/1.0\")\n            else:\n                \"\"\"\n                game --> engine/1.0 -> math/1.0\n                   |---> ai/1.0 -----> math/1.0.1 (conflict solved by override)\n                   |---(override)--_> math/newversion\n                \"\"\"\n                return GenConanfile(\"game\", \"1.0\").with_requirement(\"engine/1.0\") \\\n                    .with_requirement(\"ai/1.0\") \\\n                    .with_requirement(f\"math/{version}\", override=True)\n\n        for v in (\"1.0\", \"1.0.1\", \"1.0.2\"):\n            c.save({\"game/conanfile.py\": _game_conanfile(v)})\n            c.run(\"install game\")\n            c.assert_overrides({\"math/1.0\": [f\"math/{v}\"],\n                                \"math/1.0.1\": [f\"math/{v}\"]})\n            c.assert_listed_require({f\"math/{v}\": \"Cache\"})\n\n        # Check that order of requirements doesn't affect\n        for v in (\"1.0\", \"1.0.1\", \"1.0.2\"):\n            c.save({\"game/conanfile.py\": _game_conanfile(v, reverse=True)})\n            c.run(\"install game\")\n            c.assert_overrides({\"math/1.0\": [f\"math/{v}\"],\n                                \"math/1.0.1\": [f\"math/{v}\"]})\n            c.assert_listed_require({f\"math/{v}\": \"Cache\"})\n\n        c.run(\"install --requires=engine/1.0  --requires=ai/1.0\", assert_error=True)\n        assert \"Conflict between math/1.0.1 and math/1.0 in the graph\" in c.out\n        assert \"Conflict originates from ai/1.0\" in c.out\n\n\n@pytest.mark.parametrize(\"version_range\", [True, False])\ndef test_conflict_user(version_range):\n    # https://github.com/conan-io/conan/issues/17875\n    v = \"[^1.0]\" if version_range else \"1.0\"\n    c = TestClient(light=True)\n    c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"1.0\"),\n            \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_requires(f\"dep/{v}@user1\"),\n            \"app/conanfile.py\": GenConanfile(\"app\", \"1.0\").with_requires(f\"pkg/{v}@user1\",\n                                                                         f\"dep/{v}@user2\")})\n    c.run(\"create dep --user=user1\")\n    c.run(\"create dep --user=user2\")\n    c.run(\"create pkg --user=user1\")\n    c.run(\"install app\", assert_error=True)\n    assert f\"Version conflict: Conflict between dep/{v}@user1 and dep/{v}@user2\" in c.out\n\n\ndef test_conflict_user_order():\n    # https://github.com/conan-io/conan/issues/17875\n    c = TestClient(light=True)\n    c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"1.0\"),\n            \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_requires(\"dep/1.0@user1\"),\n            \"app/conanfile.py\": GenConanfile(\"app\", \"1.0\").with_requires(\"pkg/1.0@user1\",\n                                                                         \"dep/[>=1.0]@user2\")})\n    c.run(\"create dep --user=user1\")\n    c.run(\"create dep --user=user2\")\n    c.run(\"create pkg --user=user1\")\n    c.run(\"install app\", assert_error=True)\n    assert \"ERROR: Version conflict: Conflict between dep/1.0@user1 and dep/[>=1.0]@user2\" in c.out\n\n\n@pytest.mark.parametrize(\"test\", [True, False])\n@pytest.mark.parametrize(\"order\", [True, False])\nclass TestErrorVisibleFalse:\n\n    def test_subgraph_conflict(self, order, test):\n        #  cli--> pkg1/1.0 -(visible=False) --------------> pkg3/1.0 (conflict)\n        #             \\----> pkg2/1.0 --------------------> pkg3/1.1 (conflict)\n        # This conflict is good, the default dependencies are incompatible in definition\n        tc = TestClient(light=True)\n        pkg1 = GenConanfile(\"pkg1\", \"1.0\")\n        if order:\n            pkg1.with_requirement(\"pkg3/1.0\", visible=False, test=test).with_requirement(\"pkg2/1.0\")\n        else:\n            pkg1.with_requirement(\"pkg2/1.0\").with_requirement(\"pkg3/1.0\", visible=False, test=test)\n        tc.save({\"pkg3/conanfile.py\": GenConanfile(\"pkg3\"),\n                 \"pkg2/conanfile.py\": GenConanfile(\"pkg2\", \"1.0\").with_requirement(\"pkg3/1.1\"),\n                 \"pkg1/conanfile.py\": pkg1})\n        tc.run(\"export pkg3 --version=1.0\")\n        tc.run(\"export pkg3 --version=1.1\")\n        tc.run(\"export pkg2\")\n        # Creating this pkg1 does generate a conflict\n        tc.run(\"export pkg1\")\n        tc.run(\"graph info --requires=pkg1/1.0\", assert_error=True)\n        assert \"ERROR: Version conflict: Conflict between pkg3/1.1 and pkg3/1.0\" in tc.out\n\n    def test_subgraph_conflict_second_level(self, order, test):\n        #  cli--> pkg1/1.0 -(visible=False) ---> gtest/1.0 -> zlib/1.0\n        #             \\----> boost/1.0 ---------------------> zlib/1.1 (conflict)\n        # This conflict is good, the default dependencies are incompatible in definition\n        tc = TestClient(light=True)\n        pkg = GenConanfile(\"pkg1\", \"1.0\")\n        if order:\n            pkg.with_requirement(\"gtest/1.0\", visible=False, test=test).with_requirement(\"boost/1.0\")\n        else:\n            pkg.with_requirement(\"boost/1.0\").with_requirement(\"gtest/1.0\", visible=False, test=test)\n        tc.save({\"zlib/conanfile.py\": GenConanfile(\"zlib\"),\n                 \"boost/conanfile.py\": GenConanfile(\"boost\", \"1.0\").with_requirement(\"zlib/1.1\"),\n                 \"gtest/conanfile.py\": GenConanfile(\"gtest\", \"1.0\").with_requirement(\"zlib/1.0\"),\n                 \"pkg1/conanfile.py\": pkg})\n        tc.run(\"export zlib --version=1.0\")\n        tc.run(\"export zlib --version=1.1\")\n        tc.run(\"export boost\")\n        tc.run(\"export gtest\")\n        # Creating this pkg1 does generate a conflict\n        tc.run(\"export pkg1\")\n        tc.run(\"graph info --requires=pkg1/1.0\", assert_error=True)\n        if order:\n            assert \"ERROR: Version conflict: Conflict between zlib/1.1 and zlib/1.0\" in tc.out\n            assert \"Conflict originates from boost/1.0\" in tc.out\n        else:\n            assert \"ERROR: Version conflict: Conflict between zlib/1.0 and zlib/1.1\" in tc.out\n            assert \"Conflict originates from gtest/1.0\" in tc.out\n\n    def test_subgraph_no_conflict(self, order, test):\n        #  cli--> pkg1/1.0 -(visible=False) --------------> pkg3/1.0 (no conflict)\n        #             \\----> pkg2/1.0 --------------------> pkg3/1.0 (no conflict)\n        # This doesn't conflict, but package topology is affected, converging to a direct dependency\n        # of a visible one\n        #  cli--> pkg1/1.0 -(visible=True) --------------> pkg3/1.0 (no conflict)\n        #             \\----> pkg2/1.0 ----------------------/\n        tc = TestClient(light=True)\n        pkg1 = GenConanfile(\"pkg1\", \"1.0\")\n        if order:\n            pkg1.with_requirement(\"pkg3/1.0\", visible=False, test=test).with_requirement(\"pkg2/1.0\")\n        else:\n            pkg1.with_requirement(\"pkg2/1.0\").with_requirement(\"pkg3/1.0\", visible=False, test=test)\n        tc.save({\"pkg3/conanfile.py\": GenConanfile(\"pkg3\"),\n                 \"pkg2/conanfile.py\": GenConanfile(\"pkg2\", \"1.0\").with_requirement(\"pkg3/1.0\"),\n                 \"pkg1/conanfile.py\": pkg1})\n        tc.run(\"export pkg3 --version=1.0\")\n        tc.run(\"export pkg2\")\n        tc.run(\"export pkg1\")\n\n        tc.run(\"graph info --requires=pkg1/1.0 --format=json\")\n        if not test:\n            assert \"WARN: risk: Packages required both with visible=True and visible=False\" in tc.out\n            assert \"pkg3/1.0: Required by pkg1/1.0\" in tc.out\n        else:\n            assert \"WARN: risk\" not in tc.out\n        graph = json.loads(tc.stdout)\n        assert len(graph[\"graph\"][\"nodes\"]) == 4  # Including the CLI 0-3\n        pkg1 = graph[\"graph\"][\"nodes\"][\"1\"]\n        deps = pkg1[\"dependencies\"]\n        assert len(deps) == 2\n        assert \"pkg1/1.0\" in pkg1[\"ref\"]\n        if order:\n            dep_pkg2 = deps[\"3\"]\n            dep_pkg3 = deps[\"2\"]\n        else:\n            dep_pkg2 = deps[\"2\"]\n            dep_pkg3 = deps[\"3\"]\n        assert dep_pkg2[\"ref\"] == \"pkg2/1.0\"\n        assert dep_pkg2[\"visible\"] is True\n        assert dep_pkg3[\"ref\"] == \"pkg3/1.0\"\n        assert dep_pkg2[\"visible\"] is True\n\n    def test_subgraph_no_conflict_second_level(self, order, test):\n        #  cli--> pkg1/1.0 -(visible=False) ---> gtest/1.0 -> zlib/1.0\n        #             \\----> boost/1.0 ---------------------> zlib/1.0 (noconflict)\n        tc = TestClient(light=True)\n        pkg = GenConanfile(\"pkg1\", \"1.0\")\n        if order:\n            pkg.with_requirement(\"gtest/1.0\", visible=False, test=test).with_requirement(\"boost/1.0\")\n        else:\n            pkg.with_requirement(\"boost/1.0\").with_requirement(\"gtest/1.0\", visible=False, test=test)\n        tc.save({\"zlib/conanfile.py\": GenConanfile(\"zlib\"),\n                 \"boost/conanfile.py\": GenConanfile(\"boost\", \"1.0\").with_requirement(\"zlib/1.0\"),\n                 \"gtest/conanfile.py\": GenConanfile(\"gtest\", \"1.0\").with_requirement(\"zlib/1.0\"),\n                 \"pkg1/conanfile.py\": pkg})\n        tc.run(\"export zlib --version=1.0\")\n        tc.run(\"export boost\")\n        tc.run(\"export gtest\")\n        # Creating this pkg1 does generate a conflict\n        tc.run(\"export pkg1\")\n        tc.run(\"graph info --requires=pkg1/1.0 --format=json\")\n        assert \"WARN: risk: Packages required both with visible=True and visible=False\" not in tc.out\n        graph = json.loads(tc.stdout)\n        assert len(graph[\"graph\"][\"nodes\"]) == 5  # Including the CLI 0-4\n        pkg1 = graph[\"graph\"][\"nodes\"][\"1\"]\n        deps = pkg1[\"dependencies\"]\n        assert len(deps) == 3\n        zlib = deps[\"3\"]\n        assert \"zlib/1.0\" in zlib[\"ref\"]\n        assert zlib[\"visible\"] is True\n\n    def test_transitive_conflict(self, order, test):\n        # cli --------------------------------------------> pkg3/1.1\n        #   \\--> pkg1/1.0 -(visible=False) -> pkg3/1.0 (conflict)\n        #             \\----> pkg2/1.0 --------------------> pkg3/1.1 (no conflict)\n        tc = TestClient(light=True)\n        pkg1 = GenConanfile(\"pkg1\", \"1.0\")\n        if order:\n            pkg1.with_requirement(\"pkg3/1.0\", visible=False, test=test).with_requirement(\"pkg2/1.0\")\n        else:\n            pkg1.with_requirement(\"pkg2/1.0\").with_requirement(\"pkg3/1.0\", visible=False, test=test)\n        tc.save({\"pkg3/conanfile.py\": GenConanfile(\"pkg3\"),\n                 \"pkg2/conanfile.py\": GenConanfile(\"pkg2\", \"1.0\").with_requirement(\"pkg3/1.1\"),\n                 \"pkg1/conanfile.py\": pkg1})\n        tc.run(\"export pkg3 --version=1.0\")\n        tc.run(\"export pkg3 --version=1.1\")\n        tc.run(\"export pkg2\")\n        tc.run(\"export pkg1\")\n        tc.run(\"graph info --requires=pkg3/1.1 --requires=pkg1/1.0 --format=html\", assert_error=True,\n               redirect_stdout=\"graph.html\")\n        # Check that the graph.html is generated\n        assert os.path.exists(os.path.join(tc.current_folder, \"graph.html\"))\n        if order:\n            assert \"ERROR: Version conflict: Conflict between pkg3/1.1 and pkg3/1.0\" in tc.out\n        else:\n            assert \"ERROR: Version conflict: Conflict between pkg3/1.0 and pkg3/1.1\" in tc.out\n        assert \"Conflict originates from pkg1/1.0\" in tc.out\n\n    def test_transitive_conflict_second_level(self, order, test):\n        # cli --------------------------------------------> zlib/1.1\n        #   \\--> pkg1/1.0 -(visible=False) -gtest---------> zlib/1.0 (conflict)\n        #             \\----> boost/1.0 -------------------> zlib/1.1 (no conflict)\n        tc = TestClient(light=True)\n        pkg = GenConanfile(\"pkg1\", \"1.0\")\n        if order:\n            pkg.with_requirement(\"gtest/1.0\", visible=False, test=test).with_requirement(\"boost/1.0\")\n        else:\n            pkg.with_requirement(\"boost/1.0\").with_requirement(\"gtest/1.0\", visible=False, test=test)\n        tc.save({\"zlib/conanfile.py\": GenConanfile(\"zlib\"),\n                 \"gtest/conanfile.py\": GenConanfile(\"gtest\", \"1.0\").with_requirement(\"zlib/1.0\"),\n                 \"boost/conanfile.py\": GenConanfile(\"boost\", \"1.0\").with_requirement(\"zlib/1.1\"),\n                 \"pkg1/conanfile.py\": pkg})\n        tc.run(\"export zlib --version=1.0\")\n        tc.run(\"export zlib --version=1.1\")\n        tc.run(\"export gtest\")\n        tc.run(\"export boost\")\n        tc.run(\"export pkg1\")\n        tc.run(\"graph info --requires=zlib/1.1 --requires=pkg1/1.0 --format=html\", assert_error=True,\n               redirect_stdout=\"graph.html\")\n        # Check that the graph.html is generated\n        assert os.path.exists(os.path.join(tc.current_folder, \"graph.html\"))\n        if order:\n            assert \"ERROR: Version conflict: Conflict between zlib/1.1 and zlib/1.0\" in tc.out\n            assert \"Conflict originates from pkg1/1.0\" in tc.out\n        else:\n            assert \"ERROR: Version conflict: Conflict between zlib/1.0 and zlib/1.1\" in tc.out\n            assert \"Conflict originates from gtest/1.0\" in tc.out\n\n    def test_transitive_version_range_no_conflict(self, order, test):\n        # if in the case above, we use a version-range, we can avoid the conflict\n        tc = TestClient(light=True)\n        pkg1 = GenConanfile(\"pkg1\", \"1.0\")\n        if order:\n            pkg1.with_requirement(\"pkg3/[*]\", visible=False, test=test).with_requirement(\"pkg2/1.0\")\n        else:\n            pkg1.with_requirement(\"pkg2/1.0\").with_requirement(\"pkg3/[*]\", visible=False, test=test)\n        tc.save({\"pkg3/conanfile.py\": GenConanfile(\"pkg3\"),\n                 \"pkg2/conanfile.py\": GenConanfile(\"pkg2\", \"1.0\").with_requirement(\"pkg3/1.1\"),\n                 \"pkg1/conanfile.py\": pkg1})\n        tc.run(\"export pkg3 --version=1.0\")\n        tc.run(\"export pkg3 --version=1.1\")\n        tc.run(\"export pkg2\")\n        # Creating this pkg1 does generate a conflict\n        tc.run(\"export pkg1\")\n        tc.run(\"graph info --requires=pkg3/1.1 --requires=pkg1/1.0 --format=json\")\n        if not test:\n            assert \"WARN: risk: Packages required both with visible=True and visible=False\" in tc.out\n            assert \"pkg3/1.1: Required by pkg1/1.0\" in tc.out\n        else:\n            assert \"WARN: risk\" not in tc.out\n        graph = json.loads(tc.stdout)\n        assert len(graph[\"graph\"][\"nodes\"]) == 4  # This was having an orphan node!!!\n        pkg1 = graph[\"graph\"][\"nodes\"][\"2\"]\n        deps = pkg1[\"dependencies\"]\n        assert len(deps) == 2\n        assert \"pkg1/1.0\" in pkg1[\"ref\"]\n        dep_pkg2 = deps[\"3\"]\n        dep_pkg3 = deps[\"1\"]\n        assert dep_pkg2[\"ref\"] == \"pkg2/1.0\"\n        assert dep_pkg2[\"visible\"] is True\n        assert dep_pkg3[\"ref\"] == \"pkg3/1.1\"\n        assert dep_pkg2[\"visible\"] is True\n\n    def test_transitive_version_range_no_conflict_second_level(self, order, test):\n        # cli --------------------------------------------> zlib/1.1\n        #   \\--> pkg1/1.0 -(visible=False) -gtest---------> zlib/[*] (no conflict, range)\n        #             \\----> boost/1.0 -------------------> zlib/1.1 (no conflict)\n        tc = TestClient(light=True)\n        pkg = GenConanfile(\"pkg1\", \"1.0\")\n        if order:\n            pkg.with_requirement(\"gtest/1.0\", visible=False, test=test).with_requirement(\"boost/1.0\")\n        else:\n            pkg.with_requirement(\"boost/1.0\").with_requirement(\"gtest/1.0\", visible=False, test=test)\n        tc.save({\"zlib/conanfile.py\": GenConanfile(\"zlib\"),\n                 \"gtest/conanfile.py\": GenConanfile(\"gtest\", \"1.0\").with_requirement(\"zlib/[*]\"),\n                 \"boost/conanfile.py\": GenConanfile(\"boost\", \"1.0\").with_requirement(\"zlib/1.1\"),\n                 \"pkg1/conanfile.py\": pkg})\n        tc.run(\"export zlib --version=1.0\")\n        tc.run(\"export zlib --version=1.1\")\n        tc.run(\"export gtest\")\n        tc.run(\"export boost\")\n        tc.run(\"export pkg1\")\n        tc.run(\"graph info --requires=zlib/1.1 --requires=pkg1/1.0 --build=missing\")\n        assert \"pkg1/1.0: WARN: risk: This package has 2 different dependencies\" not in tc.out\n        # This doesn't conflict, but depending on the order, it is possible to have 2 differnet\n        # dependency graphs. If gtest is evaluated first, there will be no diamond, and\n        # gtest->zlib/1.1 will be private, and there will be another branch with another zlib/1.1\n        # node as regular requires.\n        # In both cases, it seems that zlib is not Skipped when it is necessary to build gtest\n\n    def test_transitive_orphans(self, order, test):\n        tc = TestClient(light=True)\n        pkg1 = GenConanfile(\"pkg1\", \"1.0\")\n        if order:\n            pkg1.with_requirement(\"pkg3/[*]\", visible=False, test=test).with_requirement(\"pkg2/1.0\")\n        else:\n            pkg1.with_requirement(\"pkg2/1.0\").with_requirement(\"pkg3/[*]\", visible=False, test=test)\n        tc.save({\"pkg4/conanfile.py\": GenConanfile(\"pkg4\", \"0.1\"),\n                 \"pkg3/conanfile.py\": GenConanfile(\"pkg3\").with_requires(\"pkg4/0.1\"),\n                 \"pkg2/conanfile.py\": GenConanfile(\"pkg2\", \"1.0\").with_requirement(\"pkg3/1.1\"),\n                 \"pkg1/conanfile.py\": pkg1})\n        tc.run(\"export pkg4\")\n        tc.run(\"export pkg3 --version=1.0\")\n        tc.run(\"export pkg3 --version=1.1\")\n        tc.run(\"export pkg2\")\n        # Creating this pkg1 does generate a conflict\n        tc.run(\"export pkg1\")\n\n        tc.run(\"graph info --requires=pkg3/1.1 --requires=pkg1/1.0 --format=json\")\n        if not test:\n            assert \"WARN: risk: Packages required both with visible=True and visible=False\" in tc.out\n            assert \"pkg3/1.1: Required by pkg1/1.0\" in tc.out\n        else:\n            assert \"WARN: risk\" not in tc.out\n        graph = json.loads(tc.stdout)\n        assert len(graph[\"graph\"][\"nodes\"]) == 5  # This was having an orphan node!!!\n        pkg1 = graph[\"graph\"][\"nodes\"][\"3\"]\n        assert \"pkg1/1.0\" in pkg1[\"ref\"]\n        deps = pkg1[\"dependencies\"]\n        assert len(deps) == 3\n        dep_pkg2 = deps[\"4\"]\n        dep_pkg3 = deps[\"1\"]\n        assert dep_pkg2[\"ref\"] == \"pkg2/1.0\"\n        assert dep_pkg2[\"visible\"] is True\n        assert dep_pkg3[\"ref\"] == \"pkg3/1.1\"\n        assert dep_pkg2[\"visible\"] is True\n"
  },
  {
    "path": "test/integration/graph/core/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/graph/core/graph_manager_base.py",
    "content": "import os\nimport textwrap\n\nimport pytest\nimport yaml\n\nfrom conan.api.conan_api import ConanAPI\nfrom conan.internal.cache.cache import PkgCache\nfrom conan.internal.cache.home_paths import HomePaths\nfrom conan.internal.default_settings import default_settings_yml\nfrom conan.internal.model.conf import ConfDefinition\nfrom conan.internal.model.manifest import FileTreeManifest\nfrom conan.internal.model.options import Options\nfrom conan.internal.model.profile import Profile\nfrom conan.api.model import RecipeReference\nfrom conan.internal.model.settings import Settings\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import GenConanfile\nfrom conan.internal.util.dates import revision_timestamp_now\nfrom conan.internal.util.files import save\n\n\nclass GraphManagerTest:\n\n    @pytest.fixture(autouse=True)\n    def setUp(self):\n        cache_folder = temp_folder()\n        cache = PkgCache(cache_folder, ConfDefinition())\n        home = HomePaths(cache_folder)\n        save(os.path.join(home.profiles_path, \"default\"), \"\")\n        save(home.settings_path, \"os: [Windows, Linux]\")\n        self.cache = cache\n        self.cache_folder = cache_folder\n\n    def recipe_cache(self, reference, requires=None, option_shared=None):\n        ref = RecipeReference.loads(reference)\n        conanfile = GenConanfile()\n        if requires:\n            for r in requires:\n                conanfile.with_require(r)\n        if option_shared is not None:\n            conanfile.with_option(\"shared\", [True, False])\n            conanfile.with_default_option(\"shared\", option_shared)\n\n        self._cache_recipe(ref, conanfile)\n\n    def recipe_conanfile(self, reference, conanfile):\n        ref = RecipeReference.loads(reference)\n        self._cache_recipe(ref, conanfile)\n\n    def _cache_recipe(self, ref, test_conanfile):\n        if not isinstance(ref, RecipeReference):\n            ref = RecipeReference.loads(ref)\n        ref.revision = \"123\"\n        ref.timestamp = revision_timestamp_now()\n        recipe_layout = self.cache.create_ref_layout(ref)\n        save(recipe_layout.conanfile(), str(test_conanfile))\n        manifest = FileTreeManifest.create(recipe_layout.export())\n        manifest.save(recipe_layout.export())\n\n    def alias_cache(self, alias, target):\n        ref = RecipeReference.loads(alias)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Alias(ConanFile):\n                alias = \"%s\"\n            \"\"\" % target)\n        self._cache_recipe(ref, conanfile)\n\n    @staticmethod\n    def recipe_consumer(reference=None, requires=None, build_requires=None):\n        path = temp_folder()\n        path = os.path.join(path, \"conanfile.py\")\n        conanfile = GenConanfile()\n        if reference:\n            ref = RecipeReference.loads(reference)\n            conanfile.with_name(ref.name).with_version(ref.version)\n        if requires:\n            for r in requires:\n                conanfile.with_require(r)\n        if build_requires:\n            for r in build_requires:\n                conanfile.with_build_requires(r)\n        save(path, str(conanfile))\n        return path\n\n    @staticmethod\n    def consumer_conanfile(conanfile):\n        path = temp_folder()\n        path = os.path.join(path, \"conanfile.py\")\n        save(path, str(conanfile))\n        return path\n\n    def build_graph(self, content, profile_build_requires=None, install=True, options_build=None):\n        path = temp_folder()\n        path = os.path.join(path, \"conanfile.py\")\n        save(path, str(content))\n        return self.build_consumer(path, profile_build_requires, install,\n                                   options_build=options_build)\n\n    def build_consumer(self, path, profile_build_requires=None, install=True, options_build=None):\n        profile_host = Profile()\n        profile_host.settings[\"os\"] = \"Linux\"\n        profile_build = Profile()\n        profile_build.settings[\"os\"] = \"Windows\"\n        if profile_build_requires:\n            profile_host.tool_requires = profile_build_requires\n        if options_build:\n            profile_build.options = Options(options_values=options_build)\n        cache_settings = Settings(yaml.safe_load(default_settings_yml))\n        profile_host.process_settings(cache_settings)\n        profile_build.process_settings(cache_settings)\n        build_mode = [\"*\"]  # Means build all\n\n        conan_api = ConanAPI(cache_folder=self.cache_folder)\n\n        deps_graph = conan_api.graph.load_graph_consumer(path, None, None, None, None,\n                                                         profile_host, profile_build, None, None,\n                                                         None)\n\n        if install:\n            deps_graph.report_graph_error()\n            conan_api.graph.analyze_binaries(deps_graph, build_mode)\n            conan_api.install.install_binaries(deps_graph)\n\n        return deps_graph\n\n    @staticmethod\n    def _check_node(node, ref, deps=None, dependents=None, settings=None, options=None):\n        dependents = dependents or []\n        deps = deps or []\n\n        conanfile = node.conanfile\n        ref = RecipeReference.loads(str(ref))\n        assert node.ref == ref\n        if conanfile:\n            assert conanfile.name == ref.name\n\n        assert len(node.edges) == len(deps)\n        for d in node.neighbors():\n            assert d in deps\n\n        dependants = node.inverse_neighbors()\n        assert len(dependants) == len(dependents)\n        for d in dependents:\n            assert d in dependants\n\n        if settings is not None:\n            for k, v in settings.items():\n                assert conanfile.settings.get_safe(k) == v\n\n        if options is not None:\n            for k, v in options.items():\n                assert conanfile.options.get_safe(k) == v\n"
  },
  {
    "path": "test/integration/graph/core/graph_manager_test.py",
    "content": "import pytest\n\nfrom conan.internal.graph.graph_error import GraphMissingError, GraphLoopError, GraphConflictError\nfrom conan.errors import ConanException\nfrom test.integration.graph.core.graph_manager_base import GraphManagerTest\nfrom conan.test.utils.tools import GenConanfile\n\n\ndef _check_transitive(node, transitive_deps):\n    values = list(node.transitive_deps.values())\n\n    assert len(values) == len(transitive_deps), f\"{node}: Number of deps don't match \" \\\n                                                f\"\\n{[r.require.ref for r in values]}\" \\\n                                                f\"!=\\n{transitive_deps}\"\n\n    for v1, v2 in zip(values, transitive_deps):\n        assert v1.node is v2[0], f\"{v1.node}!={v2[0]}\"\n        assert v1.require.headers is v2[1], f\"{v1.node}!={v2[0]} headers\"\n        assert v1.require.libs is v2[2], f\"{v1.node}!={v2[0]} libs\"\n        assert v1.require.build is v2[3], f\"{v1.node}!={v2[0]} build\"\n        assert v1.require.run is v2[4], f\"{v1.node}!={v2[0]} run\"\n        assert len(v2) <= 5\n\n\nclass TestLinear(GraphManagerTest):\n    def test_basic(self):\n        deps_graph = self.build_graph(GenConanfile(\"app\", \"0.1\"))\n        assert 1 == len(deps_graph.nodes)\n        node = deps_graph.root\n        self._check_node(node, \"app/0.1\")\n\n    def test_dependency(self):\n        # app -> libb0.1\n        self.recipe_cache(\"libb/0.1\")\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\"])\n        deps_graph = self.build_consumer(consumer)\n\n        assert 2 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libb])\n        self._check_node(libb, \"libb/0.1#123\", deps=[], dependents=[app])\n\n    def test_dependency_missing(self):\n        # app -> libb0.1 (non existing)\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\"])\n        deps_graph = self.build_consumer(consumer, install=False)\n\n        # TODO: Better error handling\n        assert type(deps_graph.error) is GraphMissingError\n\n        assert 1 == len(deps_graph.nodes)\n        app = deps_graph.root\n        self._check_node(app, \"app/0.1\", deps=[])\n\n    def test_transitive(self):\n        # app -> libb0.1 -> liba0.1\n        # By default if packages do not specify anything link=True is propagated run=None (unknown)\n        self.recipe_cache(\"liba/0.1\")\n        self.recipe_cache(\"libb/0.1\", [\"liba/0.1\"])\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libb])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n        # node, headers, lib, build, run\n        _check_transitive(app, [(libb, True, True, False, False),\n                                (liba, True, True, False, False)])\n        _check_transitive(libb, [(liba, True, True, False, False)])\n\n    def test_transitive_propagate_link(self):\n        # app -> libb0.1 -> liba0.1\n        # transitive_link=False will avoid propagating linkage requirement\n        self.recipe_cache(\"liba/0.1\")\n        self.recipe_conanfile(\"libb/0.1\", GenConanfile().with_requirement(\"liba/0.1\",\n                                                                          transitive_libs=False))\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libb])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n        # node, headers, lib, build, run\n        _check_transitive(app, [(libb, True, True, False, False),\n                                (liba, True, False, False, False)])\n        _check_transitive(libb, [(liba, True, True, False, False)])\n\n    def test_transitive_all_static(self):\n        # app -> libb0.1 (static) -> liba0.1 (static)\n        self.recipe_cache(\"liba/0.1\", option_shared=False)\n        self.recipe_cache(\"libb/0.1\", [\"liba/0.1\"], option_shared=False)\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        liba = libb.edges[0].dst\n\n        for r, t in libb.transitive_deps.items():\n            assert r.package_id_mode == \"minor_mode\"\n\n        self._check_node(app, \"app/0.1\", deps=[libb])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n        # node, headers, lib, build, run\n        _check_transitive(app, [(libb, True, True, False, False),\n                                (liba, False, True, False, False)])\n        _check_transitive(libb, [(liba, True, True, False, False)])\n\n    def test_transitive_all_static_transitive_headers(self):\n        # app -> libb0.1 (static) -> liba0.1 (static)\n        self.recipe_cache(\"liba/0.1\", option_shared=False)\n        libb = GenConanfile().with_requirement(\"liba/0.1\", transitive_headers=True)\n        libb.with_shared_option()\n        self.recipe_conanfile(\"libb/0.1\", libb)\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libb])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n        # node, headers, lib, build, run\n        _check_transitive(app, [(libb, True, True, False, False),\n                                (liba, True, True, False, False)])\n        _check_transitive(libb, [(liba, True, True, False, False)])\n\n    def test_transitive_all_shared(self):\n        # app -> libb0.1 (shared)  -> liba0.1 (shared)\n        self.recipe_cache(\"liba/0.1\", option_shared=True)\n        self.recipe_cache(\"libb/0.1\", [\"liba/0.1\"], option_shared=True)\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libb])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n        # node, headers, lib, build, run\n        # Default for app->liba is that it doesn't link, libb shared will isolate symbols by default\n        _check_transitive(app, [(libb, True, True, False, True),\n                                (liba, False, False, False, True)])\n        _check_transitive(libb, [(liba, True, True, False, True)])\n\n    def test_transitive_all_shared_transitive_headers_libs(self):\n        # app -> libb0.1 (shared) -> liba0.1 (shared)\n        self.recipe_cache(\"liba/0.1\", option_shared=True)\n        libb = GenConanfile().with_requirement(\"liba/0.1\", transitive_headers=True,\n                                               transitive_libs=True)\n        libb.with_shared_option(True)\n        self.recipe_conanfile(\"libb/0.1\", libb)\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libb])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n        # node, headers, lib, build, run\n        # Default for app->liba is that it doesn't link, libb shared will isolate symbols by default\n        _check_transitive(app, [(libb, True, True, False, True),\n                                (liba, True, True, False, True)])\n        _check_transitive(libb, [(liba, True, True, False, True)])\n\n    def test_middle_shared_up_static(self):\n        # app -> libb0.1 (shared) -> liba0.1 (static)\n        self.recipe_cache(\"liba/0.1\", option_shared=False)\n        self.recipe_cache(\"libb/0.1\", [\"liba/0.1\"], option_shared=True)\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libb])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n        # node, headers, lib, build, run\n        _check_transitive(app, [(libb, True, True, False, True),\n                                (liba, False, False, False, False)])\n        _check_transitive(libb, [(liba, True, True, False, False)])\n\n    def test_middle_shared_up_static_transitive_headers(self):\n        # app -> libb0.1 (shared) -> liba0.1 (static)\n        self.recipe_cache(\"liba/0.1\", option_shared=False)\n        libb = GenConanfile().with_requirement(\"liba/0.1\", transitive_headers=True)\n        libb.with_shared_option(True)\n        self.recipe_conanfile(\"libb/0.1\", libb)\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libb])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n        # node, headers, lib, build, run\n        _check_transitive(app, [(libb, True, True, False, True),\n                                (liba, True, False, False, False)])\n        _check_transitive(libb, [(liba, True, True, False, False)])\n\n    def test_middle_static_up_shared(self):\n        # app -> libb0.1 (static) -> liba0.1 (shared)\n        self.recipe_cache(\"liba/0.1\", option_shared=True)\n        self.recipe_cache(\"libb/0.1\", [\"liba/0.1\"], option_shared=False)\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libb])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n        # node, headers, lib, build, run\n        _check_transitive(app, [(libb, True, True, False, False),\n                                (liba, False, True, False, True)])\n        _check_transitive(libb, [(liba, True, True, False, True)])\n\n    def test_middle_static_up_shared_transitive_headers(self):\n        # app -> libb0.1 (static) -> liba0.1 (shared)\n        self.recipe_cache(\"liba/0.1\", option_shared=True)\n        libb = GenConanfile().with_requirement(\"liba/0.1\", transitive_headers=True)\n        libb.with_shared_option(False)\n        self.recipe_conanfile(\"libb/0.1\", libb)\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libb])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n        # node, headers, lib, build, run\n        _check_transitive(app, [(libb, True, True, False, False),\n                                (liba, True, True, False, True)])\n        _check_transitive(libb, [(liba, True, True, False, True)])\n\n    def test_private(self):\n        # app -> libb0.1 -(private) -> liba0.1\n        self.recipe_cache(\"liba/0.1\")\n        libb = GenConanfile().with_requirement(\"liba/0.1\", visible=False)\n        self.recipe_conanfile(\"libb/0.1\", libb)\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libb])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n        # node, headers, lib, build, run\n        _check_transitive(app, [(libb, True, True, False, False)])\n        _check_transitive(libb, [(liba, True, True, False, False)])\n\n    def test_generic_library_without_shared_option(self):\n        # app -> libb0.1 -> liba0.1 (library without shared option)\n        self.recipe_conanfile(\"liba/0.1\", GenConanfile().with_package_type(\"library\"))\n        libb = GenConanfile().with_requirement(\"liba/0.1\")\n        self.recipe_conanfile(\"libb/0.1\", libb)\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\"])\n\n        with pytest.raises(ConanException) as exc:\n            self.build_consumer(consumer)\n        assert \"liba/0.1: Package type is 'library', but no 'shared' option declared\" in str(exc)\n\n    def test_build_script_requirement(self):\n        # app -> libb0.1 -br-> liba0.1 (build-scripts)\n        self.recipe_conanfile(\"liba/0.1\", GenConanfile().with_package_type(\"build-scripts\"))\n        self.recipe_conanfile(\"libb/0.1\", GenConanfile().with_tool_requirement(\"liba/0.1\"))\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        liba = libb.edges[0].dst\n\n        # node, headers, lib, build, run\n        _check_transitive(app, [(libb, True, True, False, False)])\n        _check_transitive(libb, [(liba, False, False, True, True)])\n\n    @pytest.mark.parametrize(\"package_type\", [\"application\", \"shared-library\", \"static-library\",\n                             \"header-library\", \"build-scripts\", None])\n    def test_generic_build_require_adjust_run_with_package_type(self, package_type):\n        # app --br-> cmake (app)\n        self.recipe_conanfile(\"cmake/0.1\", GenConanfile().with_package_type(package_type))\n        # build require with run=None by default\n        consumer = self.recipe_consumer(\"app/0.1\", build_requires=[\"cmake/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 2 == len(deps_graph.nodes)\n        app = deps_graph.root\n        cmake = app.edges[0].dst\n\n        # node, headers, lib, build, run\n        run = package_type in (\"application\", \"shared-library\", \"build-scripts\")\n        _check_transitive(app, [(cmake, False, False, True, run)])\n\n    def test_direct_header_only(self):\n        # app -> liba0.1 (header_only)\n        self.recipe_conanfile(\"liba/0.1\", GenConanfile().with_package_type(\"header-library\"))\n        consumer = self.recipe_consumer(\"app/0.1\", [\"liba/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 2 == len(deps_graph.nodes)\n        app = deps_graph.root\n        liba = app.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[liba])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[app])\n\n        # node, headers, lib, build, run\n        _check_transitive(app, [(liba, True, False, False, False)])\n\n    def test_header_only(self):\n        # app -> libb0.1 -> liba0.1 (header_only)\n        self.recipe_conanfile(\"liba/0.1\", GenConanfile().with_package_type(\"header-library\"))\n        libb = GenConanfile().with_requirement(\"liba/0.1\")\n        self.recipe_conanfile(\"libb/0.1\", libb)\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libb])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n        # node, headers, lib, build, run\n        _check_transitive(app, [(libb, True, True, False, False),\n                                (liba, False, False, False, False)])\n        _check_transitive(libb, [(liba, True, False, False, False)])\n\n    def test_header_only_with_transitives(self):\n        # app -> liba0.1(header) -> libb0.1 (static)\n        #             \\-----------> libc0.1 (shared)\n        self.recipe_conanfile(\"libb/0.1\", GenConanfile().with_package_type(\"static-library\"))\n        self.recipe_conanfile(\"libc/0.1\", GenConanfile().with_package_type(\"shared-library\"))\n        self.recipe_conanfile(\"liba/0.1\", GenConanfile().with_package_type(\"header-library\")\n                                                        .with_requires(\"libb/0.1\", \"libc/0.1\"))\n        consumer = self.recipe_consumer(\"app/0.1\", [\"liba/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        liba = app.edges[0].dst\n        libb = liba.edges[0].dst\n        libc = liba.edges[1].dst\n\n        self._check_node(app, \"app/0.1\", deps=[liba])\n        self._check_node(liba, \"liba/0.1#123\", deps=[libb, libc], dependents=[app])\n        self._check_node(libb, \"libb/0.1#123\", dependents=[liba])\n        self._check_node(libc, \"libc/0.1#123\", dependents=[liba])\n\n        # node, headers, lib, build, run\n        _check_transitive(app, [(liba, True, False, False, False),\n                                (libb, True, True, False, False),\n                                (libc, True, True, False, True)])\n        _check_transitive(liba, [(libb, True, True, False, False),\n                                 (libc, True, True, False, True)])\n\n    def test_multiple_header_only_with_transitives(self):\n        # app -> libd0.1(header) -> liba0.1(header) -> libb0.1 (static)\n        #                               \\-----------> libc0.1 (shared)\n        self.recipe_conanfile(\"libb/0.1\", GenConanfile().with_package_type(\"static-library\"))\n        self.recipe_conanfile(\"libc/0.1\", GenConanfile().with_package_type(\"shared-library\"))\n        self.recipe_conanfile(\"liba/0.1\", GenConanfile().with_package_type(\"header-library\")\n                              .with_requires(\"libb/0.1\", \"libc/0.1\"))\n        self.recipe_conanfile(\"libd/0.1\", GenConanfile().with_package_type(\"header-library\")\n                              .with_requires(\"liba/0.1\"))\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libd/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 5 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libd = app.edges[0].dst\n        liba = libd.edges[0].dst\n        libb = liba.edges[0].dst\n        libc = liba.edges[1].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libd])\n        self._check_node(libd, \"libd/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(liba, \"liba/0.1#123\", deps=[libb, libc], dependents=[libd])\n        self._check_node(libb, \"libb/0.1#123\", dependents=[liba])\n        self._check_node(libc, \"libc/0.1#123\", dependents=[liba])\n\n        # node, headers, lib, build, run\n        _check_transitive(app, [(libd, True, False, False, False),\n                                (liba, True, False, False, False),\n                                (libb, True, True, False, False),\n                                (libc, True, True, False, True)])\n        _check_transitive(libd, [(liba, True, False, False, False),\n                                 (libb, True, True, False, False),\n                                 (libc, True, True, False, True)])\n        _check_transitive(liba, [(libb, True, True, False, False),\n                                 (libc, True, True, False, True)])\n\n    def test_static_multiple_header_only_with_transitives(self):\n        # app -> libd0.1(static) -> liba0.1(header) -> libb0.1 (static)\n        #                               \\-----------> libc0.1 (shared)\n        self.recipe_conanfile(\"libb/0.1\", GenConanfile().with_package_type(\"static-library\"))\n        self.recipe_conanfile(\"libc/0.1\", GenConanfile().with_package_type(\"shared-library\"))\n        self.recipe_conanfile(\"liba/0.1\", GenConanfile().with_package_type(\"header-library\")\n                              .with_requires(\"libb/0.1\", \"libc/0.1\"))\n        self.recipe_conanfile(\"libd/0.1\", GenConanfile().with_package_type(\"static-library\")\n                              .with_requires(\"liba/0.1\"))\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libd/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 5 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libd = app.edges[0].dst\n        liba = libd.edges[0].dst\n        libb = liba.edges[0].dst\n        libc = liba.edges[1].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libd])\n        self._check_node(libd, \"libd/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(liba, \"liba/0.1#123\", deps=[libb, libc], dependents=[libd])\n        self._check_node(libb, \"libb/0.1#123\", dependents=[liba])\n        self._check_node(libc, \"libc/0.1#123\", dependents=[liba])\n\n        # node, headers, lib, build, run\n        _check_transitive(app, [(libd, True, True, False, False),\n                                (liba, False, False, False, False),\n                                (libb, False, True, False, False),\n                                (libc, False, True, False, True)])\n        _check_transitive(libd, [(liba, True, False, False, False),\n                                 (libb, True, True, False, False),\n                                 (libc, True, True, False, True)])\n        _check_transitive(liba, [(libb, True, True, False, False),\n                                 (libc, True, True, False, True)])\n\n    def test_multiple_levels_transitive_headers(self):\n        # app -> libcc0.1 -> libb0.1  -> liba0.1\n        self.recipe_cache(\"liba/0.1\")\n        self.recipe_conanfile(\"libb/0.1\", GenConanfile().with_package_type(\"static-library\")\n                                                        .with_requirement(\"liba/0.1\",\n                                                                          transitive_headers=True))\n        self.recipe_conanfile(\"libc/0.1\", GenConanfile().with_package_type(\"static-library\")\n                                                        .with_requirement(\"libb/0.1\",\n                                                                          transitive_headers=True))\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libc/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libc = app.edges[0].dst\n        libb = libc.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libc])\n        self._check_node(libc, \"libc/0.1#123\", deps=[libb], dependents=[app])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[libc])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n        # node, headers, lib, build, run\n        _check_transitive(app, [(libc, True, True, False, False),\n                                (libb, True, True, False, False),\n                                (liba, True, True, False, False)])\n\n\nclass TestLinearFourLevels(GraphManagerTest):\n    def test_default(self):\n        # app -> libc/0.1 -> libb0.1  -> liba0.1\n        self.recipe_conanfile(\"liba/0.1\", GenConanfile())\n        self.recipe_conanfile(\"libb/0.1\", GenConanfile().with_requirement(\"liba/0.1\"))\n        self.recipe_conanfile(\"libc/0.1\", GenConanfile().with_requirement(\"libb/0.1\"))\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libc/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libc = app.edges[0].dst\n        libb = libc.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libc])\n        self._check_node(libc, \"libc/0.1#123\", deps=[libb], dependents=[app])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[libc])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n        # node, headers, lib, build, run\n        _check_transitive(app, [(libc, True, True, False, False),\n                                (libb, True, True, False, False),\n                                (liba, True, True, False, False)])\n\n    def test_negate_headers(self):\n        # app -> libc/0.1 -> libb0.1  -(not headers)-> liba0.1\n        # So nobody depends on the headers downstream\n        self.recipe_conanfile(\"liba/0.1\", GenConanfile())\n        self.recipe_conanfile(\"libb/0.1\", GenConanfile().with_requirement(\"liba/0.1\", headers=False))\n        self.recipe_conanfile(\"libc/0.1\", GenConanfile().with_requirement(\"libb/0.1\"))\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libc/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libc = app.edges[0].dst\n        libb = libc.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libc])\n        self._check_node(libc, \"libc/0.1#123\", deps=[libb], dependents=[app])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[libc])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n        # node, headers, lib, build, run\n        _check_transitive(libc, [(libb, True, True, False, False),\n                                 (liba, False, True, False, False)])\n\n        _check_transitive(app, [(libc, True, True, False, False),\n                                (libb, True, True, False, False),\n                                (liba, False, True, False, False)])\n\n    @pytest.mark.parametrize(\"library_type\", [\"static-library\", \"shared-library\"])\n    def test_libraries_transitive_headers(self, library_type):\n        # app -> libc/0.1 -> libb0.1  -> liba0.1\n        # All with transitive_headers, the final application shoud get all headers\n        # https://github.com/conan-io/conan/issues/12504\n        self.recipe_conanfile(\"liba/0.1\", GenConanfile().with_package_type(library_type))\n        self.recipe_conanfile(\"libb/0.1\",\n                              GenConanfile().with_package_type(library_type)\n                                            .with_requirement(\"liba/0.1\", transitive_headers=True))\n        self.recipe_conanfile(\"libc/0.1\",\n                              GenConanfile().with_package_type(library_type)\n                                            .with_requirement(\"libb/0.1\", transitive_headers=True))\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libc/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libc = app.edges[0].dst\n        libb = libc.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libc])\n        self._check_node(libc, \"libc/0.1#123\", deps=[libb], dependents=[app])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[libc])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n        # node, headers, lib, build, run\n        if library_type == \"shared-library\":\n            _check_transitive(app, [(libc, True, True, False, True),\n                                    (libb, True, False, False, True),\n                                    (liba, True, False, False, True)])\n        else:  # Both static and unknown behave the same\n            _check_transitive(app, [(libc, True, True, False, False),\n                                    (libb, True, True, False, False),\n                                    (liba, True, True, False, False)])\n\n    def test_negate_libs(self):\n        # app -> libc/0.1 -> libb0.1  -> liba0.1\n        # even if all are static, we want to disable the propagation of one static lib downstream\n        # because only the headers are used\n        self.recipe_conanfile(\"liba/0.1\", GenConanfile().with_package_type(\"static-library\"))\n        self.recipe_conanfile(\"libb/0.1\",\n                              GenConanfile().with_package_type(\"static-library\")\n                                            .with_requirement(\"liba/0.1\", libs=False))\n        self.recipe_conanfile(\"libc/0.1\",\n                              GenConanfile().with_package_type(\"static-library\")\n                                            .with_requirement(\"libb/0.1\"))\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libc/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libc = app.edges[0].dst\n        libb = libc.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libc])\n        self._check_node(libc, \"libc/0.1#123\", deps=[libb], dependents=[app])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[libc])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n        # node, headers, lib, build, run\n        _check_transitive(libb, [(liba, True, False, False, False)])\n        _check_transitive(libc, [(libb, True, True, False, False),\n                                 (liba, False, False, False, False)])\n\n        _check_transitive(app, [(libc, True, True, False, False),\n                                (libb, False, True, False, False),\n                                (liba, False, False, False, False)])\n\n    def test_disable_transitive_libs(self):\n        # app -> libc/0.1 -> libb0.1  -> liba0.1\n        # even if all are static, we want to disable the propagation of one static lib downstream\n        # Maybe we are re-archiving\n        self.recipe_conanfile(\"liba/0.1\", GenConanfile().with_package_type(\"static-library\"))\n        self.recipe_conanfile(\"libb/0.1\",\n                              GenConanfile().with_package_type(\"static-library\")\n                                            .with_requirement(\"liba/0.1\", transitive_libs=False))\n        self.recipe_conanfile(\"libc/0.1\",\n                              GenConanfile().with_package_type(\"static-library\")\n                                            .with_requirement(\"libb/0.1\"))\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libc/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libc = app.edges[0].dst\n        libb = libc.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libc])\n        self._check_node(libc, \"libc/0.1#123\", deps=[libb], dependents=[app])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[libc])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n        # node, headers, lib, build, run\n        _check_transitive(libb, [(liba, True, True, False, False)])\n        _check_transitive(libc, [(libb, True, True, False, False),\n                                 (liba, False, False, False, False)])\n\n        _check_transitive(app, [(libc, True, True, False, False),\n                                (libb, False, True, False, False),\n                                (liba, False, False, False, False)])\n\n    def test_shared_depends_static_libraries(self):\n        self.recipe_conanfile(\"liba/0.1\", GenConanfile().with_package_type(\"static-library\"))\n        # Emulate a re-packaging, re-archiving static library\n        self.recipe_conanfile(\"libb/0.1\",\n                              GenConanfile().with_package_type(\"shared-library\")\n                                            .with_requirement(\"liba/0.1\"))\n        self.recipe_conanfile(\"libc/0.1\",\n                              GenConanfile().with_package_type(\"static-library\")\n                                            .with_requirement(\"libb/0.1\"))\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libc/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libc = app.edges[0].dst\n        libb = libc.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libc])\n        self._check_node(libc, \"libc/0.1#123\", deps=[libb], dependents=[app])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[libc])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n        # node, headers, lib, build, run\n        _check_transitive(libc, [(libb, True, True, False, True),\n                                 (liba, False, False, False, False)])\n\n        _check_transitive(app, [(libc, True, True, False, False),\n                                (libb, False, True, False, True),\n                                (liba, False, False, False, False)])\n\n    def test_negate_run(self):\n        # app -> libc/0.1 -> libb0.1  -> liba0.1\n        # even if all are shared, we want to disable the propagation of one shared lib downstream\n        # because only the headers are used\n        self.recipe_conanfile(\"liba/0.1\", GenConanfile().with_package_type(\"shared-library\"))\n        self.recipe_conanfile(\"libb/0.1\",\n                              GenConanfile().with_package_type(\"shared-library\")\n                                            .with_requirement(\"liba/0.1\", run=False))\n        self.recipe_conanfile(\"libc/0.1\",\n                              GenConanfile().with_package_type(\"shared-library\")\n                                            .with_requirement(\"libb/0.1\"))\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libc/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libc = app.edges[0].dst\n        libb = libc.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libc])\n        self._check_node(libc, \"libc/0.1#123\", deps=[libb], dependents=[app])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[libc])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n        # node, headers, lib, build, run\n        _check_transitive(libb, [(liba, True, True, False, False)])\n        _check_transitive(libc, [(libb, True, True, False, True),\n                                 (liba, False, False, False, False)])\n\n        _check_transitive(app, [(libc, True, True, False, True),\n                                (libb, False, False, False, True),\n                                (liba, False, False, False, False)])\n\n    def test_force_run(self):\n        # app -> libc/0.1 -> libb0.1  -> liba0.1\n        # even if all are static, there is something in a static lib (files or whatever) that\n        # is necessary at runtime\n        self.recipe_conanfile(\"liba/0.1\", GenConanfile().with_package_type(\"static-library\"))\n        self.recipe_conanfile(\"libb/0.1\",\n                              GenConanfile().with_package_type(\"static-library\")\n                                            .with_requirement(\"liba/0.1\", run=True))\n        self.recipe_conanfile(\"libc/0.1\",\n                              GenConanfile().with_package_type(\"static-library\")\n                                            .with_requirement(\"libb/0.1\"))\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libc/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libc = app.edges[0].dst\n        libb = libc.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libc])\n        self._check_node(libc, \"libc/0.1#123\", deps=[libb], dependents=[app])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[libc])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n        # node, headers, lib, build, run\n        _check_transitive(libb, [(liba, True, True, False, True)])\n        _check_transitive(libc, [(libb, True, True, False, False),\n                                 (liba, False, True, False, True)])\n\n        _check_transitive(app, [(libc, True, True, False, False),\n                                (libb, False, True, False, False),\n                                (liba, False, True, False, True)])\n\n    @pytest.mark.parametrize(\"run\", [True, False])\n    def test_header_only_run(self, run):\n        # app -> libc/0.1 -> libb0.1  -> liba0.1\n        # many header-onlys\n        self.recipe_conanfile(\"liba/0.1\", GenConanfile().with_package_type(\"header-library\"))\n        self.recipe_conanfile(\"libb/0.1\",\n                              GenConanfile().with_package_type(\"header-library\")\n                                            .with_requirement(\"liba/0.1\", run=run))\n        self.recipe_conanfile(\"libc/0.1\",\n                              GenConanfile().with_package_type(\"header-library\")\n                                            .with_requirement(\"libb/0.1\"))\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libc/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libc = app.edges[0].dst\n        libb = libc.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libc])\n        self._check_node(libc, \"libc/0.1#123\", deps=[libb], dependents=[app])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[libc])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n        # node, headers, lib, build, run\n        _check_transitive(libb, [(liba, True, False, False, run)])\n        _check_transitive(libc, [(libb, True, False, False, False),\n                                 (liba, True, False, False, run)])\n\n        _check_transitive(app, [(libc, True, False, False, False),\n                                (libb, True, False, False, False),\n                                (liba, True, False, False, run)])\n\n    def test_intermediate_header_only(self):\n        # app -> libc/0.1 (static) -> libb0.1 (header) -> liba0.1 (static)\n        self.recipe_conanfile(\"liba/0.1\", GenConanfile().with_package_type(\"static-library\"))\n        self.recipe_conanfile(\"libb/0.1\",  GenConanfile().with_package_type(\"header-library\")\n                                                         .with_requirement(\"liba/0.1\"))\n        self.recipe_conanfile(\"libc/0.1\", GenConanfile().with_package_type(\"static-library\")\n                                                        .with_requirement(\"libb/0.1\"))\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libc/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libc = app.edges[0].dst\n        libb = libc.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libc])\n        self._check_node(libc, \"libc/0.1#123\", deps=[libb], dependents=[app])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[libc])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n        # node, headers, lib, build, run\n        _check_transitive(libb, [(liba, True, True, False, False)])\n        _check_transitive(libc, [(libb, True, False, False, False),\n                                 (liba, True, True, False, False)])\n\n        _check_transitive(app, [(libc, True, True, False, False),\n                                (libb, False, False, False, False),\n                                (liba, False, True, False, False)])\n\n    def test_static_propagation_linear(self):\n        # https://github.com/conan-io/conan/issues/16402\n        # app -> libc/0.1 (shared) -> libb0.1 (static) -> liba0.1 (static)\n        # The propagation of traits is correct, it is only the \"skip-binaries\" not able to skip\n        self.recipe_conanfile(\"liba/0.1\", GenConanfile().with_package_type(\"static-library\"))\n        self.recipe_conanfile(\"libb/0.1\",  GenConanfile().with_package_type(\"static-library\")\n                                                         .with_requirement(\"liba/0.1\"))\n        self.recipe_conanfile(\"libc/0.1\", GenConanfile().with_package_type(\"shared-library\")\n                                                        .with_requirement(\"libb/0.1\"))\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libc/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libc = app.edges[0].dst\n        libb = libc.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libc])\n        self._check_node(libc, \"libc/0.1#123\", deps=[libb], dependents=[app])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[libc])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n        # node, headers, lib, build, run\n        _check_transitive(libb, [(liba, True, True, False, False)])\n        _check_transitive(libc, [(libb, True, True, False, False),\n                                 (liba, False, True, False, False)])\n        _check_transitive(app, [(libc, True, True, False, True),\n                                (libb, False, False, False, False),\n                                (liba, False, False, False, False)])\n\n    def test_incorrect_static_propagation_diamond(self):\n        # https://github.com/conan-io/conan/issues/16402\n        # app -> libc/0.1 (shared) -> libb0.1 (static) -> liba0.1 (static)\n        #  \\------------------------------------------------/\n        self.recipe_conanfile(\"liba/0.1\", GenConanfile().with_package_type(\"static-library\"))\n        self.recipe_conanfile(\"libb/0.1\",  GenConanfile().with_package_type(\"static-library\")\n                                                         .with_requirement(\"liba/0.1\"))\n        self.recipe_conanfile(\"libc/0.1\", GenConanfile().with_package_type(\"shared-library\")\n                                                        .with_requirement(\"libb/0.1\"))\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libc/0.1\", \"liba/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libc = app.edges[0].dst\n        libb = libc.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libc, liba])\n        self._check_node(libc, \"libc/0.1#123\", deps=[libb], dependents=[app])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[libc])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb, app])\n\n        # node, headers, lib, build, run\n        _check_transitive(libb, [(liba, True, True, False, False)])\n        _check_transitive(libc, [(libb, True, True, False, False),\n                                 (liba, False, True, False, False)])\n        _check_transitive(app, [(libc, True, True, False, True),\n                                (libb, False, False, False, False),\n                                (liba, True, True, False, False)])\n\n\nclass TestLinearFiveLevelsHeaders(GraphManagerTest):\n    def test_all_header_only(self):\n        # app -> libd/0.1 -> libc/0.1 -> libb0.1  -> liba0.1\n        self.recipe_conanfile(\"liba/0.1\", GenConanfile().with_package_type(\"header-library\"))\n        self.recipe_conanfile(\"libb/0.1\", GenConanfile().with_requirement(\"liba/0.1\")\n                                                        .with_package_type(\"header-library\"))\n        self.recipe_conanfile(\"libc/0.1\", GenConanfile().with_requirement(\"libb/0.1\")\n                                                        .with_package_type(\"header-library\"))\n        self.recipe_conanfile(\"libd/0.1\", GenConanfile().with_requirement(\"libc/0.1\")\n                                                        .with_package_type(\"header-library\"))\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libd/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 5 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libd = app.edges[0].dst\n        libc = libd.edges[0].dst\n        libb = libc.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libd])\n        self._check_node(libd, \"libd/0.1#123\", deps=[libc], dependents=[app])\n        self._check_node(libc, \"libc/0.1#123\", deps=[libb], dependents=[libd])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[libc])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n        # node, headers, lib, build, run\n        _check_transitive(app, [(libd, True, False, False, False),\n                                (libc, True, False, False, False),\n                                (libb, True, False, False, False),\n                                (liba, True, False, False, False)])\n\n    def test_all_header_only_aggregating_libc(self):\n        # libc is copying and pasting the others headers at build time, creating re-distribution\n        # app -> libd/0.1 -> libc/0.1 -(transitive_headers=FALSE)-> libb0.1  -> liba0.1\n        self.recipe_conanfile(\"liba/0.1\", GenConanfile().with_package_type(\"header-library\"))\n        self.recipe_conanfile(\"libb/0.1\", GenConanfile().with_requirement(\"liba/0.1\")\n                                                        .with_package_type(\"header-library\"))\n        self.recipe_conanfile(\"libc/0.1\", GenConanfile().with_requirement(\"libb/0.1\",\n                                                                          transitive_headers=False)\n                                                        .with_package_type(\"header-library\"))\n        self.recipe_conanfile(\"libd/0.1\", GenConanfile().with_requirement(\"libc/0.1\")\n                                                        .with_package_type(\"header-library\"))\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libd/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 5 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libd = app.edges[0].dst\n        libc = libd.edges[0].dst\n        libb = libc.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libd])\n        self._check_node(libd, \"libd/0.1#123\", deps=[libc], dependents=[app])\n        self._check_node(libc, \"libc/0.1#123\", deps=[libb], dependents=[libd])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[libc])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n        # node, headers, lib, build, run\n        _check_transitive(app, [(libd, True, False, False, False),\n                                (libc, True, False, False, False),\n                                (libb, False, False, False, False),\n                                (liba, False, False, False, False)])\n\n    def test_first_header_only(self):\n        # app -> libd/0.1(header) -> libc/0.1 -> libb0.1  -> liba0.1\n        self.recipe_conanfile(\"liba/0.1\", GenConanfile().with_package_type(\"static-library\"))\n        self.recipe_conanfile(\"libb/0.1\", GenConanfile().with_requirement(\"liba/0.1\")\n                                                        .with_package_type(\"static-library\"))\n        self.recipe_conanfile(\"libc/0.1\", GenConanfile().with_requirement(\"libb/0.1\")\n                                                        .with_package_type(\"static-library\"))\n        self.recipe_conanfile(\"libd/0.1\", GenConanfile().with_requirement(\"libc/0.1\")\n                                                        .with_package_type(\"header-library\"))\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libd/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 5 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libd = app.edges[0].dst\n        libc = libd.edges[0].dst\n        libb = libc.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libd])\n        self._check_node(libd, \"libd/0.1#123\", deps=[libc], dependents=[app])\n        self._check_node(libc, \"libc/0.1#123\", deps=[libb], dependents=[libd])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[libc])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n        # node, headers, lib, build, run\n        _check_transitive(app, [(libd, True, False, False, False),\n                                (libc, True, True, False, False),\n                                (libb, False, True, False, False),\n                                (liba, False, True, False, False)])\n\n    def test_first_header_only_transitive_headers_b(self):\n        # app -> libd/0.1(header) -> libc/0.1 -(transitive_headers=T)-> libb0.1  -> liba0.1\n        self.recipe_conanfile(\"liba/0.1\", GenConanfile().with_package_type(\"static-library\"))\n        self.recipe_conanfile(\"libb/0.1\", GenConanfile().with_requirement(\"liba/0.1\")\n                                                        .with_package_type(\"static-library\"))\n        self.recipe_conanfile(\"libc/0.1\", GenConanfile().with_requirement(\"libb/0.1\",\n                                                                          transitive_headers=True)\n                                                        .with_package_type(\"static-library\"))\n        self.recipe_conanfile(\"libd/0.1\", GenConanfile().with_requirement(\"libc/0.1\")\n                                                        .with_package_type(\"header-library\"))\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libd/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 5 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libd = app.edges[0].dst\n        libc = libd.edges[0].dst\n        libb = libc.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libd])\n        self._check_node(libd, \"libd/0.1#123\", deps=[libc], dependents=[app])\n        self._check_node(libc, \"libc/0.1#123\", deps=[libb], dependents=[libd])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[libc])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n        # node, headers, lib, build, run\n        _check_transitive(app, [(libd, True, False, False, False),\n                                (libc, True, True, False, False),\n                                (libb, True, True, False, False),\n                                (liba, False, True, False, False)])\n\n    def test_first_header_only_transitive_headers_b_a(self):\n        # app -> libd/0.1(header) -> libc/0.1 -(transitive_headers=T)-> libb0.1 -(transitive_headers=T)-> liba0.1\n        self.recipe_conanfile(\"liba/0.1\", GenConanfile().with_package_type(\"static-library\"))\n        self.recipe_conanfile(\"libb/0.1\", GenConanfile().with_requirement(\"liba/0.1\",\n                                                                          transitive_headers=True)\n                                                        .with_package_type(\"static-library\"))\n        self.recipe_conanfile(\"libc/0.1\", GenConanfile().with_requirement(\"libb/0.1\",\n                                                                          transitive_headers=True)\n                                                        .with_package_type(\"static-library\"))\n        self.recipe_conanfile(\"libd/0.1\", GenConanfile().with_requirement(\"libc/0.1\")\n                                                        .with_package_type(\"header-library\"))\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libd/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 5 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libd = app.edges[0].dst\n        libc = libd.edges[0].dst\n        libb = libc.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libd])\n        self._check_node(libd, \"libd/0.1#123\", deps=[libc], dependents=[app])\n        self._check_node(libc, \"libc/0.1#123\", deps=[libb], dependents=[libd])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[libc])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n        # node, headers, lib, build, run\n        _check_transitive(app, [(libd, True, False, False, False),\n                                (libc, True, True, False, False),\n                                (libb, True, True, False, False),\n                                (liba, True, True, False, False)])\n\n    def test_first_header_only_reject_libs(self):\n        # Like Libc knows it only uses headers from libb\n        # app -> libd/0.1(header) -> libc/0.1 -(libs=False)-> libb0.1  -> liba0.1\n        self.recipe_conanfile(\"liba/0.1\", GenConanfile().with_package_type(\"static-library\"))\n        self.recipe_conanfile(\"libb/0.1\", GenConanfile().with_requirement(\"liba/0.1\")\n                                                        .with_package_type(\"static-library\"))\n        self.recipe_conanfile(\"libc/0.1\", GenConanfile().with_requirement(\"libb/0.1\", libs=False)\n                                                        .with_package_type(\"static-library\"))\n        self.recipe_conanfile(\"libd/0.1\", GenConanfile().with_requirement(\"libc/0.1\")\n                                                        .with_package_type(\"header-library\"))\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libd/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 5 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libd = app.edges[0].dst\n        libc = libd.edges[0].dst\n        libb = libc.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libd])\n        self._check_node(libd, \"libd/0.1#123\", deps=[libc], dependents=[app])\n        self._check_node(libc, \"libc/0.1#123\", deps=[libb], dependents=[libd])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[libc])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n        # node, headers, lib, build, run\n        _check_transitive(app, [(libd, True, False, False, False),\n                                (libc, True, True, False, False),\n                                (libb, False, False, False, False),\n                                (liba, False, False, False, False)])\n\n    def test_d_b_header_only(self):\n        # app -> libd/0.1(header) -> libc/0.1 -> libb0.1(header)  -> liba0.1\n        self.recipe_conanfile(\"liba/0.1\", GenConanfile().with_package_type(\"static-library\"))\n        self.recipe_conanfile(\"libb/0.1\", GenConanfile().with_requirement(\"liba/0.1\")\n                                                        .with_package_type(\"header-library\"))\n        self.recipe_conanfile(\"libc/0.1\", GenConanfile().with_requirement(\"libb/0.1\")\n                                                        .with_package_type(\"static-library\"))\n        self.recipe_conanfile(\"libd/0.1\", GenConanfile().with_requirement(\"libc/0.1\")\n                                                        .with_package_type(\"header-library\"))\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libd/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 5 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libd = app.edges[0].dst\n        libc = libd.edges[0].dst\n        libb = libc.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libd])\n        self._check_node(libd, \"libd/0.1#123\", deps=[libc], dependents=[app])\n        self._check_node(libc, \"libc/0.1#123\", deps=[libb], dependents=[libd])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[libc])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n        # node, headers, lib, build, run\n        _check_transitive(app, [(libd, True, False, False, False),\n                                (libc, True, True, False, False),\n                                (libb, False, False, False, False),\n                                (liba, False, True, False, False)])\n\n    def test_d_b_header_only_transitive_headers_b(self):\n        # app -> libd/0.1(header) -> libc/0.1 -(transitive_headers=T)-> libb0.1(header)  -> liba0.1\n        self.recipe_conanfile(\"liba/0.1\", GenConanfile().with_package_type(\"static-library\"))\n        self.recipe_conanfile(\"libb/0.1\", GenConanfile().with_requirement(\"liba/0.1\")\n                                                        .with_package_type(\"header-library\"))\n        self.recipe_conanfile(\"libc/0.1\", GenConanfile().with_requirement(\"libb/0.1\",\n                                                                          transitive_headers=True)\n                                                        .with_package_type(\"static-library\"))\n        self.recipe_conanfile(\"libd/0.1\", GenConanfile().with_requirement(\"libc/0.1\")\n                                                        .with_package_type(\"header-library\"))\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libd/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 5 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libd = app.edges[0].dst\n        libc = libd.edges[0].dst\n        libb = libc.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libd])\n        self._check_node(libd, \"libd/0.1#123\", deps=[libc], dependents=[app])\n        self._check_node(libc, \"libc/0.1#123\", deps=[libb], dependents=[libd])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[libc])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n        # node, headers, lib, build, run\n        _check_transitive(app, [(libd, True, False, False, False),\n                                (libc, True, True, False, False),\n                                (libb, True, False, False, False),\n                                (liba, True, True, False, False)])\n\n    def test_visible_transitivity(self):\n        # app -> libd/0.1 -> libc/0.1 -(visible=False)-> libb0.1  -> liba0.1\n        self.recipe_conanfile(\"liba/0.1\", GenConanfile())\n        self.recipe_conanfile(\"libb/0.1\", GenConanfile().with_requirement(\"liba/0.1\"))\n        self.recipe_conanfile(\"libc/0.1\", GenConanfile().with_requirement(\"libb/0.1\",\n                                                                          visible=False))\n        self.recipe_conanfile(\"libd/0.1\", GenConanfile().with_requirement(\"libc/0.1\"))\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libd/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 5 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libd = app.edges[0].dst\n        libc = libd.edges[0].dst\n        libb = libc.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libd])\n        self._check_node(libd, \"libd/0.1#123\", deps=[libc], dependents=[app])\n        self._check_node(libc, \"libc/0.1#123\", deps=[libb], dependents=[libd])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[libc])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n        # node, headers, lib, build, run\n        _check_transitive(app, [(libd, True, True, False, False),\n                                (libc, True, True, False, False)])\n        _check_transitive(libd, [(libc, True, True, False, False)])\n        _check_transitive(libc, [(libb, True, True, False, False),\n                                 (liba, True, True, False, False)])\n\n    def test_visible_build_transitivity(self):\n        # app -> libd/0.1 -> libc/0.1 -(visible=True, build=True)-> libb0.1  -> liba0.1\n        self.recipe_conanfile(\"liba/0.1\", GenConanfile())\n        self.recipe_conanfile(\"libb/0.1\", GenConanfile().with_requirement(\"liba/0.1\"))\n        self.recipe_conanfile(\"libc/0.1\", GenConanfile().with_requirement(\"libb/0.1\", build=True))\n        self.recipe_conanfile(\"libd/0.1\", GenConanfile().with_requirement(\"libc/0.1\"))\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libd/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 5 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libd = app.edges[0].dst\n        libc = libd.edges[0].dst\n        libb = libc.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libd])\n        self._check_node(libd, \"libd/0.1#123\", deps=[libc], dependents=[app])\n        self._check_node(libc, \"libc/0.1#123\", deps=[libb], dependents=[libd])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[libc])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n        # node, headers, lib, build, run\n        _check_transitive(app, [(libd, True, True, False, False),\n                                (libc, True, True, False, False),\n                                (libb, False, False, True, False)])\n        _check_transitive(libd, [(libc, True, True, False, False),\n                                 (libb, False, False, True, False)])\n        _check_transitive(libc, [(libb, True, True, True, False)])\n\n\nclass TestLinearFiveLevelsLibraries(GraphManagerTest):\n    def test_all_static(self):\n        # app -> libd/0.1 -> libc/0.1 -> libb0.1  -> liba0.1\n        self.recipe_conanfile(\"liba/0.1\", GenConanfile().with_package_type(\"static-library\"))\n        self.recipe_conanfile(\"libb/0.1\", GenConanfile().with_requirement(\"liba/0.1\")\n                                                        .with_package_type(\"static-library\"))\n        self.recipe_conanfile(\"libc/0.1\", GenConanfile().with_requirement(\"libb/0.1\")\n                                                        .with_package_type(\"static-library\"))\n        self.recipe_conanfile(\"libd/0.1\", GenConanfile().with_requirement(\"libc/0.1\")\n                                                        .with_package_type(\"static-library\"))\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libd/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 5 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libd = app.edges[0].dst\n        libc = libd.edges[0].dst\n        libb = libc.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libd])\n        self._check_node(libd, \"libd/0.1#123\", deps=[libc], dependents=[app])\n        self._check_node(libc, \"libc/0.1#123\", deps=[libb], dependents=[libd])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[libc])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n        # node, headers, lib, build, run\n        _check_transitive(app, [(libd, True, True, False, False),\n                                (libc, False, True, False, False),\n                                (libb, False, True, False, False),\n                                (liba, False, True, False, False)])\n\n    def test_libc_aggregating_static(self):\n        # Lets think libc is re-linking its dependencies in a single .lib\n        # app -> libd/0.1 -> libc/0.1 -(transitive_libs=False)-> libb0.1  -> liba0.1\n        self.recipe_conanfile(\"liba/0.1\", GenConanfile().with_package_type(\"static-library\"))\n        self.recipe_conanfile(\"libb/0.1\", GenConanfile().with_requirement(\"liba/0.1\")\n                                                        .with_package_type(\"static-library\"))\n        self.recipe_conanfile(\"libc/0.1\", GenConanfile().with_requirement(\"libb/0.1\",\n                                                                          transitive_libs=False)\n                                                        .with_package_type(\"static-library\"))\n        self.recipe_conanfile(\"libd/0.1\", GenConanfile().with_requirement(\"libc/0.1\")\n                                                        .with_package_type(\"static-library\"))\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libd/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 5 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libd = app.edges[0].dst\n        libc = libd.edges[0].dst\n        libb = libc.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libd])\n        self._check_node(libd, \"libd/0.1#123\", deps=[libc], dependents=[app])\n        self._check_node(libc, \"libc/0.1#123\", deps=[libb], dependents=[libd])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[libc])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n        # node, headers, lib, build, run\n        _check_transitive(app, [(libd, True, True, False, False),\n                                (libc, False, True, False, False),\n                                (libb, False, False, False, False),\n                                (liba, False, False, False, False)])\n\n\nclass TestDiamond(GraphManagerTest):\n\n    def test_diamond(self):\n        # app -> libb0.1 -> liba0.1\n        #    \\-> libc0.1 ->/\n        self.recipe_cache(\"liba/0.1\")\n        self.recipe_cache(\"libb/0.1\", [\"liba/0.1\"])\n        self.recipe_cache(\"libc/0.1\", [\"liba/0.1\"])\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\", \"libc/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        libc = app.edges[1].dst\n        liba = libb.edges[0].dst\n\n        # TODO: No Revision??? Because of consumer?\n        self._check_node(app, \"app/0.1\", deps=[libb, libc])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(libc, \"libc/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb, libc])\n\n        _check_transitive(app, [(libb, True, True, False, False),\n                                (libc, True, True, False, False),\n                                (liba, True, True, False, False)])\n\n    @pytest.mark.parametrize(\"order\", [True, False])\n    def test_diamond_additive(self, order):\n        # app -> libb0.1 ---------> liba0.1\n        #    \\-> libc0.1 (run=True)->/\n        self.recipe_cache(\"liba/0.1\")\n        if order:\n            self.recipe_cache(\"libb/0.1\", [\"liba/0.1\"])\n            self.recipe_conanfile(\"libc/0.1\", GenConanfile().with_requirement(\"liba/0.1\", run=True))\n        else:\n            self.recipe_conanfile(\"libb/0.1\", GenConanfile().with_requirement(\"liba/0.1\", run=True))\n            self.recipe_cache(\"libc/0.1\", [\"liba/0.1\"])\n\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\", \"libc/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        libc = app.edges[1].dst\n        liba = libb.edges[0].dst\n\n        # TODO: No Revision??? Because of consumer?\n        self._check_node(app, \"app/0.1\", deps=[libb, libc])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(libc, \"libc/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb, libc])\n\n        _check_transitive(app, [(libb, True, True, False, False),\n                                (libc, True, True, False, False),\n                                (liba, True, True, False, True)])\n\n    def test_half_diamond(self):\n        # app -----------> liba0.1\n        #    \\-> libc0.1 ->/\n        self.recipe_cache(\"liba/0.1\")\n        self.recipe_cache(\"libc/0.1\", [\"liba/0.1\"])\n        consumer = self.recipe_consumer(\"app/0.1\", [\"liba/0.1\", \"libc/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        liba = app.edges[0].dst\n        libc = app.edges[1].dst\n\n        # TODO: No Revision??? Because of consumer?\n        self._check_node(app, \"app/0.1\", deps=[liba, libc])\n        self._check_node(libc, \"libc/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[app, libc])\n\n        # Order seems to be link order\n        _check_transitive(app, [(libc, True, True, False, False),\n                                (liba, True, True, False, False)])\n        # Both requires of app are direct! https://github.com/conan-io/conan/pull/12388\n        for require in app.transitive_deps.keys():\n            assert require.direct is True\n\n    def test_half_diamond_reverse(self):\n        # same as above, just swap order of declaration\n        # app -->libc0.1--> liba0.1\n        #    \\-------------->/\n        self.recipe_cache(\"liba/0.1\")\n        self.recipe_cache(\"libc/0.1\", [\"liba/0.1\"])\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libc/0.1\", \"liba/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libc = app.edges[0].dst\n        liba = app.edges[1].dst\n\n        # TODO: No Revision??? Because of consumer?\n        self._check_node(app, \"app/0.1\", deps=[liba, libc])\n        self._check_node(libc, \"libc/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[app, libc])\n\n        # Order seems to be link order, constant irrespective of declaration order, good\n        _check_transitive(app, [(libc, True, True, False, False),\n                                (liba, True, True, False, False)])\n        # Both requires of app are direct! https://github.com/conan-io/conan/pull/12388\n        for require in app.transitive_deps.keys():\n            assert require.direct is True\n\n    def test_shared_static(self):\n        # app -> libb0.1 (shared) -> liba0.1 (static)\n        #    \\-> libc0.1 (shared) ->/\n        self.recipe_cache(\"liba/0.1\", option_shared=False)\n        self.recipe_cache(\"libb/0.1\", [\"liba/0.1\"], option_shared=True)\n        self.recipe_cache(\"libc/0.1\", [\"liba/0.1\"], option_shared=True)\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\", \"libc/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        libc = app.edges[1].dst\n        liba = libb.edges[0].dst\n        liba1 = libc.edges[0].dst\n\n        assert liba is liba1\n\n        self._check_node(app, \"app/0.1\", deps=[libb, libc])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(libc, \"libc/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb, libc])\n\n        # node, headers, lib, build, run\n        _check_transitive(app, [(libb, True, True, False, True),\n                                (libc, True, True, False, True),\n                                (liba, False, False, False, False)])\n        _check_transitive(libb, [(liba, True, True, False, False)])\n        _check_transitive(libc, [(liba, True, True, False, False)])\n\n    def test_private(self):\n        # app -> libd0.1 -(private)-> libb0.1 -> liba0.1\n        #            \\ ---(private)-> libc0.1 --->/\n        self.recipe_cache(\"liba/0.1\")\n        self.recipe_cache(\"libb/0.1\", [\"liba/0.1\"])\n        self.recipe_cache(\"libc/0.1\", [\"liba/0.1\"])\n        libd = GenConanfile().with_requirement(\"libb/0.1\", visible=False)\n        libd.with_requirement(\"libc/0.1\", visible=False)\n        self.recipe_conanfile(\"libd/0.1\", libd)\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libd/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 5 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libd = app.edges[0].dst\n        libb = libd.edges[0].dst\n        libc = libd.edges[1].dst\n        liba = libb.edges[0].dst\n        liba2 = libc.edges[0].dst\n\n        assert liba is liba2\n\n        self._check_node(app, \"app/0.1\", deps=[libd])\n        self._check_node(libd, \"libd/0.1#123\", deps=[libb, libc], dependents=[app])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[libd])\n        self._check_node(libc, \"libc/0.1#123\", deps=[liba], dependents=[libd])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb, libc])\n\n        # node, headers, lib, build, run\n        _check_transitive(app, [(libd, True, True, False, False)])\n        _check_transitive(libd, [(libb, True, True, False, False),\n                                 (libc, True, True, False, False),\n                                 (liba, True, True, False, False)])\n\n    def test_shared_static_private(self):\n        # app -> libb0.1 (shared) -(private)-> liba0.1 (static)\n        #    \\-> libc0.1 (shared) -> liba0.2 (static)\n        # This private allows to avoid the liba conflict\n        self.recipe_cache(\"liba/0.1\", option_shared=False)\n        self.recipe_cache(\"liba/0.2\", option_shared=False)\n        libb = GenConanfile().with_requirement(\"liba/0.1\", visible=False)\n        libb.with_shared_option(True)\n        self.recipe_conanfile(\"libb/0.1\", libb)\n        self.recipe_cache(\"libc/0.1\", [\"liba/0.2\"], option_shared=True)\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\", \"libc/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 5 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        libc = app.edges[1].dst\n        liba1 = libb.edges[0].dst\n        liba2 = libc.edges[0].dst\n\n        assert liba1 is not liba2\n\n        self._check_node(app, \"app/0.1\", deps=[libb, libc])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba1], dependents=[app])\n        self._check_node(libc, \"libc/0.1#123\", deps=[liba2], dependents=[app])\n        self._check_node(liba1, \"liba/0.1#123\", dependents=[libb])\n        self._check_node(liba2, \"liba/0.2#123\", dependents=[libc])\n\n        # node, headers, lib, build, run\n        _check_transitive(app, [(libb, True, True, False, True),\n                                (libc, True, True, False, True),\n                                (liba2, False, False, False, False)])\n        _check_transitive(libb, [(liba1, True, True, False, False)])\n        _check_transitive(libc, [(liba2, True, True, False, False)])\n\n    def test_diamond_conflict(self):\n        # app -> libb0.1 -> liba0.1\n        #    \\-> libc0.1 -> liba0.2\n        self.recipe_cache(\"liba/0.1\")\n        self.recipe_cache(\"liba/0.2\")\n        self.recipe_cache(\"libb/0.1\", [\"liba/0.1\"])\n        self.recipe_cache(\"libc/0.1\", [\"liba/0.2\"])\n\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\", \"libc/0.1\"])\n        deps_graph = self.build_consumer(consumer, install=False)\n\n        assert type(deps_graph.error) is GraphConflictError\n\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        libc = app.edges[1].dst\n        liba1 = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libb, libc])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba1], dependents=[app])\n        self._check_node(libc, \"libc/0.1#123\", deps=[], dependents=[app])\n        self._check_node(liba1, \"liba/0.1#123\", dependents=[libb])\n\n    def test_shared_conflict_shared(self):\n        # app -> libb0.1 (shared) -> liba0.1 (shared)\n        #    \\-> libc0.1 (shared) -> liba0.2 (shared)\n        self.recipe_cache(\"liba/0.1\", option_shared=True)\n        self.recipe_cache(\"liba/0.2\", option_shared=True)\n        self.recipe_cache(\"libb/0.1\", [\"liba/0.1\"], option_shared=True)\n        self.recipe_cache(\"libc/0.1\", [\"liba/0.2\"], option_shared=True)\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\", \"libc/0.1\"])\n\n        deps_graph = self.build_consumer(consumer, install=False)\n\n        assert type(deps_graph.error) is GraphConflictError\n\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        libc = app.edges[1].dst\n        liba1 = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libb, libc])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba1], dependents=[app])\n        self._check_node(libc, \"libc/0.1#123\", deps=[], dependents=[app])\n        self._check_node(liba1, \"liba/0.1#123\", dependents=[libb])\n\n    def test_private_conflict(self):\n        # app -> libd0.1 -(private)-> libb0.1 -> liba0.1\n        #            \\ ---(private)-> libc0.1 -> liba0.2\n        #\n        # private requires do not avoid conflicts at the node level, only downstream\n        self.recipe_cache(\"liba/0.1\")\n        self.recipe_cache(\"liba/0.2\")\n        self.recipe_cache(\"libb/0.1\", [\"liba/0.1\"])\n        self.recipe_cache(\"libc/0.1\", [\"liba/0.2\"])\n        libd = GenConanfile().with_requirement(\"libb/0.1\", visible=False)\n        libd.with_requirement(\"libc/0.1\", visible=False)\n        self.recipe_conanfile(\"libd/0.1\", libd)\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libd/0.1\"])\n\n        deps_graph = self.build_consumer(consumer, install=False)\n\n        assert type(deps_graph.error) is GraphConflictError\n\n        assert 5 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libd = app.edges[0].dst\n        libb = libd.edges[0].dst\n        libc = libd.edges[1].dst\n        liba1 = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libd])\n        self._check_node(libd, \"libd/0.1#123\", deps=[libb, libc], dependents=[app])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba1], dependents=[libd])\n        self._check_node(libc, \"libc/0.1#123\", deps=[], dependents=[libd])\n        self._check_node(liba1, \"liba/0.1#123\", dependents=[libb])\n\n    def test_diamond_transitive_private(self):\n        # https://github.com/conan-io/conan/issues/13630\n        # libc0.1 ----------> liba0.1 --(private) -> zlib/1.0\n        #      \\-> --(libb---->/\n\n        self.recipe_cache(\"zlib/0.1\")\n        self.recipe_conanfile(\"liba/0.1\", GenConanfile(\"liba\", \"0.1\")\n                              .with_requirement(\"zlib/0.1\", visible=False))\n        self.recipe_cache(\"libb/0.1\", [\"liba/0.1\"])\n        self.recipe_cache(\"libc/0.1\", [\"liba/0.1\", \"libb/0.1\"])\n        consumer = self.consumer_conanfile(GenConanfile(\"libc\", \"0.1\")\n                                           .with_requires(\"liba/0.1\", \"libb/0.1\"))\n        deps_graph = self.build_consumer(consumer)\n\n        assert 4 == len(deps_graph.nodes)\n        libc = deps_graph.root\n        liba = libc.edges[0].dst\n        libb = libc.edges[1].dst\n        liba1 = libb.edges[0].dst\n        zlib = liba.edges[0].dst\n\n        assert liba is liba1\n        # TODO: No Revision??? Because of consumer?\n        self._check_node(libc, \"libc/0.1\", deps=[liba, libb])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[libc])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb, libc], deps=[zlib])\n        self._check_node(zlib, \"zlib/0.1#123\", dependents=[liba])\n\n        _check_transitive(libb, [(liba, True, True, False, False)])\n        _check_transitive(libc, [(libb, True, True, False, False),\n                                 (liba, True, True, False, False)])\n\n    def test_private_transitive_headers_no_conflict(self):\n        # https://github.com/conan-io/conan/issues/15559\n        # app -->liba/0.1 -(private)-> spdlog/0.1(header-only) -> fmt/0.1 (header-only)\n        #   \\ --------------------------------------------------> fmt/0.2\n        self.recipe_conanfile(\"fmt/0.1\",\n                              GenConanfile(\"fmt\", \"0.1\").with_package_type(\"header-library\"))\n        self.recipe_conanfile(\"fmt/0.2\", GenConanfile(\"fmt\", \"0.2\"))\n        self.recipe_conanfile(\"spdlog/0.1\",\n                              GenConanfile(\"spdlog\", \"0.1\").with_package_type(\"header-library\")\n                                                           .with_requires(\"fmt/0.1\"))\n        self.recipe_conanfile(\"liba/0.1\",\n                              GenConanfile(\"liba\", \"0.2\").with_requirement(\"spdlog/0.1\",\n                                                                           visible=False))\n        consumer = self.consumer_conanfile(GenConanfile(\"app\", \"0.1\")\n                                           .with_requires(\"liba/0.1\", \"fmt/0.2\"))\n        deps_graph = self.build_consumer(consumer)\n\n        assert 5 == len(deps_graph.nodes)\n        app = deps_graph.root\n        liba = app.edges[0].dst\n        spdlog = liba.edges[0].dst\n        fmt01 = spdlog.edges[0].dst\n        fmt02 = app.edges[1].dst\n\n        self._check_node(app, \"app/0.1\", deps=[liba, fmt02])\n        self._check_node(liba, \"liba/0.1#123\", deps=[spdlog], dependents=[app])\n        self._check_node(spdlog, \"spdlog/0.1#123\", deps=[fmt01], dependents=[liba])\n        self._check_node(fmt01, \"fmt/0.1#123\", deps=[], dependents=[spdlog])\n        self._check_node(fmt02, \"fmt/0.2#123\", dependents=[app])\n\n        # node, headers, lib, build, run\n        _check_transitive(app, [(liba, True, True, False, False),\n                                (fmt02, True, True, False, False)])\n\n\nclass TestDiamondMultiple(GraphManagerTest):\n\n    def test_consecutive_diamonds(self):\n        # app -> libe0.1 -> libd0.1 -> libb0.1 -> liba0.1\n        #    \\-> libf0.1 ->/    \\-> libc0.1 ->/\n        self.recipe_cache(\"liba/0.1\")\n        self.recipe_cache(\"libb/0.1\", [\"liba/0.1\"])\n        self.recipe_cache(\"libc/0.1\", [\"liba/0.1\"])\n        self.recipe_cache(\"libd/0.1\", [\"libb/0.1\", \"libc/0.1\"])\n        self.recipe_cache(\"libe/0.1\", [\"libd/0.1\"])\n        self.recipe_cache(\"libf/0.1\", [\"libd/0.1\"])\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libe/0.1\", \"libf/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 7 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libe = app.edges[0].dst\n        libf = app.edges[1].dst\n        libd = libe.edges[0].dst\n        libb = libd.edges[0].dst\n        libc = libd.edges[1].dst\n        liba = libc.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libe, libf])\n        self._check_node(libe, \"libe/0.1#123\", deps=[libd], dependents=[app])\n        self._check_node(libf, \"libf/0.1#123\", deps=[libd], dependents=[app])\n        self._check_node(libd, \"libd/0.1#123\", deps=[libb, libc], dependents=[libe, libf])\n        self._check_node(libc, \"libc/0.1#123\", deps=[liba], dependents=[libd])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[libd])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb, libc])\n\n        _check_transitive(app, [(libe, True, True, False, False),\n                                (libf, True, True, False, False),\n                                (libd, True, True, False, False),\n                                (libb, True, True, False, False),\n                                (libc, True, True, False, False),\n                                (liba, True, True, False, False)])\n\n    def test_consecutive_diamonds_private(self):\n        # app -> libe0.1 ---------> libd0.1 ---> libb0.1 ---> liba0.1\n        #    \\-> (private)->libf0.1 ->/    \\-private-> libc0.1 ->/\n        self.recipe_cache(\"liba/0.1\")\n        self.recipe_cache(\"libb/0.1\", [\"liba/0.1\"])\n        self.recipe_cache(\"libc/0.1\", [\"liba/0.1\"])\n        self._cache_recipe(\"libd/0.1\", GenConanfile().with_require(\"libb/0.1\")\n                           .with_requirement(\"libc/0.1\", visible=False))\n        self.recipe_cache(\"libe/0.1\", [\"libd/0.1\"])\n        self.recipe_cache(\"libf/0.1\", [\"libd/0.1\"])\n        consumer = self.consumer_conanfile(GenConanfile(\"app\", \"0.1\").with_require(\"libe/0.1\")\n                                           .with_requirement(\"libf/0.1\", visible=False))\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 7 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libe = app.edges[0].dst\n        libf = app.edges[1].dst\n        libd = libe.edges[0].dst\n        libb = libd.edges[0].dst\n        libc = libd.edges[1].dst\n        liba = libc.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libe, libf])\n        self._check_node(libe, \"libe/0.1#123\", deps=[libd], dependents=[app])\n        self._check_node(libf, \"libf/0.1#123\", deps=[libd], dependents=[app])\n        self._check_node(libd, \"libd/0.1#123\", deps=[libb, libc], dependents=[libe, libf])\n        self._check_node(libc, \"libc/0.1#123\", deps=[liba], dependents=[libd])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[libd])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb, libc])\n\n        # FIXME: In this case the order seems a bit broken\n        _check_transitive(app, [(libe, True, True, False, False),\n                                (libf, True, True, False, False),\n                                (libd, True, True, False, False),\n                                (libb, True, True, False, False),\n                                (liba, True, True, False, False),\n                                ])\n\n    def test_parallel_diamond(self):\n        # app -> libb0.1 -> liba0.1\n        #    \\-> libc0.1 ->/\n        #    \\-> libd0.1 ->/\n        self.recipe_cache(\"liba/0.1\")\n        self.recipe_cache(\"libb/0.1\", [\"liba/0.1\"])\n        self.recipe_cache(\"libc/0.1\", [\"liba/0.1\"])\n        self.recipe_cache(\"libd/0.1\", [\"liba/0.1\"])\n\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\", \"libc/0.1\", \"libd/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 5 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        libc = app.edges[1].dst\n        libd = app.edges[2].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libb, libc, libd])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(libc, \"libc/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(libd, \"libd/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb, libc, libd])\n\n    def test_nested_diamond(self):\n        # app --------> libb0.1 -> liba0.1\n        #    \\--------> libc0.1 ->/\n        #     \\-> libd0.1 ->/\n        self.recipe_cache(\"liba/0.1\")\n        self.recipe_cache(\"libb/0.1\", [\"liba/0.1\"])\n        self.recipe_cache(\"libc/0.1\", [\"liba/0.1\"])\n        self.recipe_cache(\"libd/0.1\", [\"libc/0.1\"])\n\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\", \"libc/0.1\", \"libd/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 5 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        libc = app.edges[1].dst\n        libd = app.edges[2].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libb, libc, libd])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(libc, \"libc/0.1#123\", deps=[liba], dependents=[app, libd])\n        self._check_node(libd, \"libd/0.1#123\", deps=[libc], dependents=[app])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb, libc])\n\n    def test_multiple_transitive(self):\n        # https://github.com/conanio/conan/issues/4720\n        # app -> libb0.1  -> libc0.1 -> libd0.1\n        #    \\--------------->/          /\n        #     \\------------------------>/\n        self.recipe_cache(\"libd/0.1\")\n        self.recipe_cache(\"libc/0.1\", [\"libd/0.1\"])\n        self.recipe_cache(\"libb/0.1\", [\"libc/0.1\"])\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libd/0.1\", \"libc/0.1\", \"libb/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libd = app.edges[0].dst\n        libc = app.edges[1].dst\n        libb = app.edges[2].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libd, libc, libb])\n        self._check_node(libd, \"libd/0.1#123\", dependents=[app, libc])\n        self._check_node(libb, \"libb/0.1#123\", deps=[libc], dependents=[app])\n        self._check_node(libc, \"libc/0.1#123\", deps=[libd], dependents=[app, libb])\n\n    def test_loop(self):\n        # app -> libc0.1 -> libb0.1 -> liba0.1 ->|\n        #             \\<-------------------------|\n        self.recipe_cache(\"liba/0.1\", [\"libc/0.1\"])\n        self.recipe_cache(\"libb/0.1\", [\"liba/0.1\"])\n        self.recipe_cache(\"libc/0.1\", [\"libb/0.1\"])\n\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libc/0.1\"])\n\n        deps_graph = self.build_consumer(consumer, install=False)\n        # TODO: Better error modeling\n        assert type(deps_graph.error) is GraphLoopError\n\n        assert 4 == len(deps_graph.nodes)\n\n        app = deps_graph.root\n        libc = app.edges[0].dst\n        libb = libc.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libc])\n        self._check_node(libc, \"libc/0.1#123\", deps=[libb], dependents=[app])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[libc])\n        self._check_node(liba, \"liba/0.1#123\", deps=[], dependents=[libb])\n\n\nclass TestTransitiveOverridesGraph(GraphManagerTest):\n\n    def test_diamond(self):\n        # app -> libb0.1 -> liba0.2 (overriden to lib0.2)\n        #    \\-> --------- ->/\n        self.recipe_cache(\"liba/0.1\")\n        self.recipe_cache(\"liba/0.2\")\n        self.recipe_cache(\"libb/0.1\", [\"liba/0.1\"])\n        consumer = self.consumer_conanfile(GenConanfile(\"app\", \"0.1\").with_require(\"libb/0.1\")\n                                           .with_requirement(\"liba/0.2\", force=True))\n        deps_graph = self.build_consumer(consumer)\n\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        liba = app.edges[1].dst\n        liba2 = libb.edges[0].dst\n\n        assert liba is liba2\n\n        # TODO: No Revision??? Because of consumer?\n        self._check_node(app, \"app/0.1\", deps=[libb, liba])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(liba, \"liba/0.2#123\", dependents=[libb, app])\n\n    def test_diamond_conflict(self):\n        # app -> libb0.1 -> liba0.2 (overriden to lib0.2)\n        #    \\-> --------- ->/\n        self.recipe_cache(\"liba/0.1\")\n        self.recipe_cache(\"liba/0.2\")\n        self.recipe_cache(\"libb/0.1\", [\"liba/0.1\"])\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\", \"liba/0.2\"])\n\n        deps_graph = self.build_consumer(consumer, install=False)\n        assert deps_graph.error is not False\n        assert type(deps_graph.error) is GraphConflictError\n\n        assert 2 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n\n        # TODO: No Revision??? Because of consumer?\n        self._check_node(app, \"app/0.1\", deps=[libb])\n        self._check_node(libb, \"libb/0.1#123\", deps=[], dependents=[app])\n\n    def test_build_script_no_conflict(self):\n        # app -> libb0.1 -> liba0.1 (build-scripts)\n        #    \\-> libc0.1 -> liba0.2\n        self.recipe_conanfile(\"liba/0.1\", GenConanfile().with_package_type(\"build-scripts\"))\n        self.recipe_conanfile(\"liba/0.2\", GenConanfile())\n        self.recipe_conanfile(\"libb/0.1\",\n                              GenConanfile().with_tool_requirement(\"liba/0.1\", run=False))\n        self.recipe_conanfile(\"libc/0.1\", GenConanfile().with_requirement(\"liba/0.2\"))\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\", \"libc/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 5 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        libc = app.edges[1].dst\n        liba1 = libb.edges[0].dst\n        liba2 = libc.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libb, libc])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba1], dependents=[app])\n        self._check_node(libc, \"libc/0.1#123\", deps=[liba2], dependents=[app])\n        self._check_node(liba1, \"liba/0.1#123\", dependents=[libb])\n        self._check_node(liba2, \"liba/0.2#123\", dependents=[libc])\n\n        # node, headers, lib, build, run\n        _check_transitive(app, [(libb, True, True, False, False),\n                                (libc, True, True, False, False),\n                                (liba2, True, True, False, False)])\n        _check_transitive(libb, [(liba1, False, False, True, False)])\n        _check_transitive(libc, [(liba2, True, True, False, False)])\n\n    def test_diamond_reverse_order(self):\n        # foo ---------------------------------> dep1/2.0\n        #   \\ -> dep2/1.0--(dep1/1.0 overriden)-->/\n        self.recipe_cache(\"dep1/1.0\")\n        self.recipe_cache(\"dep1/2.0\")\n        self.recipe_cache(\"dep2/1.0\", [\"dep1/1.0\"])\n        consumer = self.consumer_conanfile(GenConanfile(\"app\", \"0.1\")\n                                           .with_requirement(\"dep1/2.0\", force=True)\n                                           .with_requirement(\"dep2/1.0\"))\n        deps_graph = self.build_consumer(consumer)\n\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        dep1 = app.edges[0].dst\n        dep2 = app.edges[1].dst\n\n        self._check_node(app, \"app/0.1\", deps=[dep1, dep2])\n        self._check_node(dep1, \"dep1/2.0#123\", deps=[], dependents=[app, dep2])\n        self._check_node(dep2, \"dep2/1.0#123\", deps=[dep1], dependents=[app])\n\n    def test_diamond_reverse_order_conflict(self):\n        # foo ---------------------------------> dep1/2.0\n        #   \\ -> dep2/1.0--(dep1/1.0 overriden)-->/\n        self.recipe_cache(\"dep1/1.0\")\n        self.recipe_cache(\"dep1/2.0\")\n        self.recipe_cache(\"dep2/1.0\", [\"dep1/1.0\"])\n        consumer = self.recipe_consumer(\"app/0.1\", [\"dep1/2.0\", \"dep2/1.0\"])\n        deps_graph = self.build_consumer(consumer, install=False)\n\n        assert type(deps_graph.error) is GraphConflictError\n\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        dep1 = app.edges[0].dst\n        dep2 = app.edges[1].dst\n        self._check_node(app, \"app/0.1\", deps=[dep1, dep2])\n        self._check_node(dep1, \"dep1/2.0#123\", deps=[], dependents=[app])\n        # dep2 no dependency, it was not resolved due to conflict\n        self._check_node(dep2, \"dep2/1.0#123\", deps=[], dependents=[app])\n\n    def test_invisible_not_forced(self):\n        # app -> libb0.1 -(visible=False)----> liba0.1 (NOT forced to lib0.2)\n        #    \\-> -----(force not used)-------> liba0.2\n        self.recipe_cache(\"liba/0.1\")\n        self.recipe_cache(\"liba/0.2\")\n        self.recipe_conanfile(\"libb/0.1\", GenConanfile().with_requirement(\"liba/0.1\",\n                                                                          visible=False))\n        consumer = self.consumer_conanfile(GenConanfile(\"app\", \"0.1\").with_require(\"libb/0.1\")\n                                           .with_requirement(\"liba/0.2\", force=True))\n        deps_graph = self.build_consumer(consumer)\n\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        liba2 = app.edges[1].dst\n        liba = libb.edges[0].dst\n\n        # TODO: No Revision??? Because of consumer?\n        self._check_node(app, \"app/0.1\", deps=[libb, liba2])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n        self._check_node(liba2, \"liba/0.2#123\", dependents=[app])\n\n\nclass TestPureOverride(GraphManagerTest):\n\n    def test_diamond(self):\n        # app -> libb0.1 -> liba0.2 (overriden to lib0.2)\n        #    \\-> ---(override)------ ->/\n        self.recipe_cache(\"liba/0.1\")\n        self.recipe_cache(\"liba/0.2\")\n        self.recipe_cache(\"libb/0.1\", [\"liba/0.1\"])\n        consumer = self.consumer_conanfile(GenConanfile(\"app\", \"0.1\").with_require(\"libb/0.1\")\n                                           .with_requirement(\"liba/0.2\", override=True))\n        deps_graph = self.build_consumer(consumer)\n\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        liba = libb.edges[0].dst\n\n        # TODO: No Revision??? Because of consumer?\n        self._check_node(app, \"app/0.1\", deps=[libb])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(liba, \"liba/0.2#123\", dependents=[libb])\n\n    def test_discarded_override(self):\n        # app ->---(override)------> liba0.2\n        consumer = self.consumer_conanfile(GenConanfile(\"app\", \"0.1\")\n                                           .with_requirement(\"liba/0.2\", override=True))\n        deps_graph = self.build_consumer(consumer)\n\n        assert 1 == len(deps_graph.nodes)\n        app = deps_graph.root\n        # TODO: No Revision??? Because of consumer?\n        self._check_node(app, \"app/0.1\", deps=[])\n\n    def test_invisible_not_overriden(self):\n        # app -> libb0.1 -(visible=False)----> liba0.1 (NOT overriden to lib0.2)\n        #    \\-> -----(override not used)------->/\n        self.recipe_cache(\"liba/0.1\")\n        self.recipe_conanfile(\"libb/0.1\", GenConanfile().with_requirement(\"liba/0.1\",\n                                                                          visible=False))\n        consumer = self.consumer_conanfile(GenConanfile(\"app\", \"0.1\").with_require(\"libb/0.1\")\n                                           .with_requirement(\"liba/0.2\", override=True))\n        deps_graph = self.build_consumer(consumer)\n\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        liba = libb.edges[0].dst\n\n        # TODO: No Revision??? Because of consumer?\n        self._check_node(app, \"app/0.1\", deps=[libb])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n    def test_nested_overrides(self):\n        # app -> libc0.1 ------> libb0.1 ------> liba0.1\n        #  \\          \\-> --(override liba0.2)---->/\n        #   \\-> ---(override liba0.3)------------>/\n        self.recipe_cache(\"liba/0.1\")\n        self.recipe_cache(\"liba/0.2\")\n        self.recipe_cache(\"liba/0.3\")\n        self.recipe_cache(\"libb/0.1\", [\"liba/0.1\"])\n        self.recipe_conanfile(\"libc/0.1\", GenConanfile(\"libc\", \"0.1\")\n                              .with_requirement(\"libb/0.1\")\n                              .with_requirement(\"liba/0.2\", override=True))\n        consumer = self.consumer_conanfile(GenConanfile(\"app\", \"0.1\").with_require(\"libc/0.1\")\n                                           .with_requirement(\"liba/0.3\", override=True))\n        deps_graph = self.build_consumer(consumer)\n\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libc = app.edges[0].dst\n        libb = libc.edges[0].dst\n        liba = libb.edges[0].dst\n\n        # TODO: No Revision??? Because of consumer?\n        self._check_node(app, \"app/0.1\", deps=[libc])\n        self._check_node(libc, \"libc/0.1#123\", deps=[libb], dependents=[app])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[libc])\n        self._check_node(liba, \"liba/0.3#123\", dependents=[libb])\n\n    def test_override_solve_upstream_conflict(self):\n        # app -> libc0.1 ------> libb0.1 ------> liba0.1\n        #  \\          \\-> --(liba0.2 conflict)---->/\n        #   \\-> ---(override liba0.3)------------>/\n        self.recipe_cache(\"liba/0.1\")\n        self.recipe_cache(\"liba/0.2\")\n        self.recipe_cache(\"liba/0.3\")\n        self.recipe_cache(\"libb/0.1\", [\"liba/0.1\"])\n        self.recipe_conanfile(\"libc/0.1\", GenConanfile(\"libc\", \"0.1\")\n                              .with_requires(\"libb/0.1\", \"liba/0.2\"))\n        consumer = self.consumer_conanfile(GenConanfile(\"app\", \"0.1\").with_require(\"libc/0.1\")\n                                           .with_requirement(\"liba/0.3\", override=True))\n        deps_graph = self.build_consumer(consumer)\n\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libc = app.edges[0].dst\n        libb = libc.edges[0].dst\n        liba = libb.edges[0].dst\n\n        # TODO: No Revision??? Because of consumer?\n        self._check_node(app, \"app/0.1\", deps=[libc])\n        self._check_node(libc, \"libc/0.1#123\", deps=[libb, liba], dependents=[app])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[libc])\n        self._check_node(liba, \"liba/0.3#123\", dependents=[libb, libc])\n\n    def test_override_not_used(self):\n        # https://github.com/conan-io/conan/issues/13630\n        # libc0.1 ----------> liba0.1 --(override) -> zlib/1.0\n        #      \\-> --(libb---->/\n\n        self.recipe_conanfile(\"liba/0.1\", GenConanfile(\"liba\", \"0.1\")\n                              .with_requirement(\"zlib/0.1\", override=True))\n        self.recipe_cache(\"libb/0.1\", [\"liba/0.1\"])\n        self.recipe_cache(\"libc/0.1\", [\"liba/0.1\", \"libb/0.1\"])\n        consumer = self.consumer_conanfile(GenConanfile(\"libc\", \"0.1\")\n                                           .with_requires(\"liba/0.1\", \"libb/0.1\"))\n        deps_graph = self.build_consumer(consumer)\n\n        assert 3 == len(deps_graph.nodes)\n        libc = deps_graph.root\n        liba = libc.edges[0].dst\n        libb = libc.edges[1].dst\n        liba1 = libb.edges[0].dst\n\n        assert liba is liba1\n        # TODO: No Revision??? Because of consumer?\n        self._check_node(libc, \"libc/0.1\", deps=[liba, libb])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[libc])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb, libc])\n\n        _check_transitive(libb, [(liba, True, True, False, False)])\n        _check_transitive(libc, [(libb, True, True, False, False),\n                                 (liba, True, True, False, False)])\n\n\nclass TestPackageIDDeductions(GraphManagerTest):\n\n    def test_static_dep_to_shared(self):\n        # project -> app1 -> lib\n        #    \\---- > app2 --/\n\n        self._cache_recipe(\"lib/0.1\", GenConanfile())\n        self._cache_recipe(\"app1/0.1\", GenConanfile().with_requirement(\"lib/0.1\"))\n        self._cache_recipe(\"app2/0.1\", GenConanfile().with_requirement(\"lib/0.1\"))\n\n        deps_graph = self.build_graph(GenConanfile(\"project\", \"0.1\")\n                                      .with_requirement(\"app1/0.1\", headers=False, libs=False,\n                                                        build=False, run=True)\n                                      .with_requirement(\"app2/0.1\", headers=False, libs=False,\n                                                        build=False, run=True)\n                                      )\n\n        assert 4 == len(deps_graph.nodes)\n        project = deps_graph.root\n        app1 = project.edges[0].dst\n        app2 = project.edges[1].dst\n        lib = app1.edges[0].dst\n        lib2 = app2.edges[0].dst\n\n        assert lib is lib2\n\n        self._check_node(project, \"project/0.1@\", deps=[app1, app2], dependents=[])\n        self._check_node(app1, \"app1/0.1#123\", deps=[lib], dependents=[project])\n        self._check_node(app2, \"app2/0.1#123\", deps=[lib], dependents=[project])\n        self._check_node(lib, \"lib/0.1#123\", deps=[], dependents=[app1, app2])\n\n        # node, headers, lib, build, run\n        _check_transitive(project, [(app1, False, False, False, True),\n                                    (app2, False, False, False, True),\n                                    (lib, False, False, False, False)])\n\n\nclass TestProjectApp(GraphManagerTest):\n    \"\"\"\n    Emulating a project that can gather multiple applications and other resources and build a\n    consistent graph, in which dependencies are same versions\n    \"\"\"\n    def test_project_require_transitive(self):\n        # project -> app1 -> lib\n        #    \\---- > app2 --/\n\n        self._cache_recipe(\"lib/0.1\", GenConanfile())\n        self._cache_recipe(\"app1/0.1\", GenConanfile().with_requirement(\"lib/0.1\"))\n        self._cache_recipe(\"app2/0.1\", GenConanfile().with_requirement(\"lib/0.1\"))\n\n        deps_graph = self.build_graph(GenConanfile(\"project\", \"0.1\")\n                                      .with_requirement(\"app1/0.1\", headers=False, libs=False,\n                                                        build=False, run=True)\n                                      .with_requirement(\"app2/0.1\", headers=False, libs=False,\n                                                        build=False, run=True)\n                                      )\n\n        assert 4 == len(deps_graph.nodes)\n        project = deps_graph.root\n        app1 = project.edges[0].dst\n        app2 = project.edges[1].dst\n        lib = app1.edges[0].dst\n        lib2 = app2.edges[0].dst\n\n        assert lib is lib2\n\n        self._check_node(project, \"project/0.1@\", deps=[app1, app2], dependents=[])\n        self._check_node(app1, \"app1/0.1#123\", deps=[lib], dependents=[project])\n        self._check_node(app2, \"app2/0.1#123\", deps=[lib], dependents=[project])\n        self._check_node(lib, \"lib/0.1#123\", deps=[], dependents=[app1, app2])\n\n        # node, headers, lib, build, run\n        _check_transitive(project, [(app1, False, False, False, True),\n                                    (app2, False, False, False, True),\n                                    (lib, False, False, False, False)])\n\n    def test_project_require_transitive_conflict(self):\n        # project -> app1 -> lib/0.1\n        #    \\---- > app2 -> lib/0.2\n\n        self._cache_recipe(\"lib/0.1\", GenConanfile())\n        self._cache_recipe(\"lib/0.2\", GenConanfile())\n        self._cache_recipe(\"app1/0.1\", GenConanfile().with_requirement(\"lib/0.1\"))\n        self._cache_recipe(\"app2/0.1\", GenConanfile().with_requirement(\"lib/0.2\"))\n\n        deps_graph = self.build_graph(GenConanfile(\"project\", \"0.1\")\n                                      .with_requirement(\"app1/0.1\", headers=False, libs=False,\n                                                        build=False, run=True)\n                                      .with_requirement(\"app2/0.1\", headers=False, libs=False,\n                                                        build=False, run=True),\n                                      install=False)\n\n        assert type(deps_graph.error) is GraphConflictError\n\n    def test_project_require_apps_transitive(self):\n        # project -> app1 (app type) -> lib\n        #    \\---- > app2 (app type) --/\n\n        self._cache_recipe(\"lib/0.1\", GenConanfile())\n        self._cache_recipe(\"app1/0.1\", GenConanfile().with_package_type(\"application\").\n                           with_requirement(\"lib/0.1\"))\n        self._cache_recipe(\"app2/0.1\", GenConanfile().with_package_type(\"application\").\n                           with_requirement(\"lib/0.1\"))\n\n        deps_graph = self.build_graph(GenConanfile(\"project\", \"0.1\").with_requires(\"app1/0.1\",\n                                                                                   \"app2/0.1\"))\n\n        assert 4 == len(deps_graph.nodes)\n        project = deps_graph.root\n        app1 = project.edges[0].dst\n        app2 = project.edges[1].dst\n        lib = app1.edges[0].dst\n        lib2 = app2.edges[0].dst\n\n        assert lib is lib2\n\n        self._check_node(project, \"project/0.1@\", deps=[app1, app2], dependents=[])\n        self._check_node(app1, \"app1/0.1#123\", deps=[lib], dependents=[project])\n        self._check_node(app2, \"app2/0.1#123\", deps=[lib], dependents=[project])\n        self._check_node(lib, \"lib/0.1#123\", deps=[], dependents=[app1, app2])\n\n        # node, headers, lib, build, run\n        _check_transitive(project, [(app1, False, False, False, True),\n                                    (app2, False, False, False, True),\n                                    (lib, False, False, False, False)])\n\n    def test_project_require_apps_transitive_conflict(self):\n        # project -> app1 (app type) -> lib/0.1\n        #    \\---- > app2 (app type) -> lib/0.2\n\n        self._cache_recipe(\"lib/0.1\", GenConanfile())\n        self._cache_recipe(\"lib/0.2\", GenConanfile())\n        self._cache_recipe(\"app1/0.1\", GenConanfile().with_package_type(\"application\").\n                           with_requirement(\"lib/0.1\"))\n        self._cache_recipe(\"app2/0.1\", GenConanfile().with_package_type(\"application\").\n                           with_requirement(\"lib/0.2\"))\n\n        deps_graph = self.build_graph(GenConanfile(\"project\", \"0.1\").with_requires(\"app1/0.1\",\n                                                                                   \"app2/0.1\"),\n                                      install=False)\n\n        assert type(deps_graph.error) is GraphConflictError\n\n    def test_project_require_private(self):\n        # project -(!visible)-> app1 -> lib1\n        #    \\----(!visible)- > app2 -> lib2\n        # This doesn't conflict on project, as lib1, lib2 do not include, link or public\n\n        self._cache_recipe(\"lib/0.1\", GenConanfile())\n        self._cache_recipe(\"lib/0.2\", GenConanfile())\n        self._cache_recipe(\"app1/0.1\", GenConanfile().with_requirement(\"lib/0.1\"))\n        self._cache_recipe(\"app2/0.1\", GenConanfile().with_requirement(\"lib/0.2\"))\n\n        deps_graph = self.build_graph(GenConanfile(\"project\", \"0.1\")\n                                      .with_requirement(\"app1/0.1\", headers=False, libs=False,\n                                                        build=False, run=True, visible=False)\n                                      .with_requirement(\"app2/0.1\", headers=False, libs=False,\n                                                        build=False, run=True, visible=False)\n                                      )\n\n        assert 5 == len(deps_graph.nodes)\n        project = deps_graph.root\n        app1 = project.edges[0].dst\n        app2 = project.edges[1].dst\n        lib1 = app1.edges[0].dst\n        lib2 = app2.edges[0].dst\n\n        assert lib1 is not lib2\n\n        self._check_node(project, \"project/0.1@\", deps=[app1, app2], dependents=[])\n        self._check_node(app1, \"app1/0.1#123\", deps=[lib1], dependents=[project])\n        self._check_node(app2, \"app2/0.1#123\", deps=[lib2], dependents=[project])\n        self._check_node(lib1, \"lib/0.1#123\", deps=[], dependents=[app1])\n        self._check_node(lib2, \"lib/0.2#123\", deps=[], dependents=[app2])\n\n        # node, headers, lib, build, run\n        _check_transitive(project, [(app1, False, False, False, True),\n                                    (lib1, False, False, False, False),\n                                    (app2, False, False, False, True),\n                                    (lib2, False, False, False, False)])\n"
  },
  {
    "path": "test/integration/graph/core/test_alias.py",
    "content": "from conan.internal.graph.graph_builder import DepsGraphBuilder\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom test.integration.graph.core.graph_manager_base import GraphManagerTest\nfrom test.integration.graph.core.graph_manager_test import _check_transitive\nfrom conan.test.utils.tools import TestClient\n\nDepsGraphBuilder.ALLOW_ALIAS = True\n\n\nclass TestAlias(GraphManagerTest):\n\n    def test_basic(self):\n        # app -> liba/latest -(alias)-> liba/0.1\n        self.recipe_cache(\"liba/0.1\")\n        self.alias_cache(\"liba/latest\", \"liba/0.1\")\n\n        consumer = self.recipe_consumer(\"app/0.1\", [\"liba/(latest)\"])\n        deps_graph = self.build_consumer(consumer)\n\n        assert 2 == len(deps_graph.nodes)\n        app = deps_graph.root\n        liba = app.edges[0].dst\n\n        self._check_node(liba, \"liba/0.1#123\", dependents=[app])\n        self._check_node(app, \"app/0.1\", deps=[liba])\n\n    def test_alias_diamond(self):\n        # app -> ----------------------------------> liba/0.1\n        #   \\ -> libb/0.1 -> liba/latest -(alias) ----->/\n        self.recipe_cache(\"liba/0.1\")\n        self.alias_cache(\"liba/latest\", \"liba/0.1\")\n        self.recipe_cache(\"libb/0.1\", requires=[\"liba/(latest)\"])\n        consumer = self.recipe_consumer(\"app/0.1\", [\"liba/0.1\", \"libb/0.1\"])\n        deps_graph = self.build_consumer(consumer)\n\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        liba = app.edges[0].dst\n        libb = app.edges[1].dst\n\n        self._check_node(liba, \"liba/0.1#123\", dependents=[app, libb])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(app, \"app/0.1\", deps=[liba, libb])\n\n        # node, include, link, build, run\n        # It seems they are in link order\n        _check_transitive(app, [(libb, True, True, False, False),\n                                (liba, True, True, False, False)])\n        _check_transitive(libb, [(liba, True, True, False, False)])\n\n    def test_two_alias_diamond(self):\n        # https://github.com/conan-io/conan/issues/3353\n        # app -> liba/latest -(alias) --------------------------------------> liba/0.1\n        #   \\ -> libb/latest -(alias) -> libb/0.1 -> liba/latest -(alias) ----->/\n\n        self.recipe_cache(\"liba/0.1\")\n        self.alias_cache(\"liba/latest\", \"liba/0.1\")\n        self.recipe_cache(\"libb/0.1\", requires=[\"liba/(latest)\"])\n        self.alias_cache(\"libb/latest\", \"libb/0.1\")\n\n        consumer = self.recipe_consumer(\"app/0.1\", [\"liba/(latest)\", \"libb/(latest)\"])\n        deps_graph = self.build_consumer(consumer)\n\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        liba = app.edges[0].dst\n        libb = app.edges[1].dst\n\n        self._check_node(liba, \"liba/0.1#123\", dependents=[app, libb])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(app, \"app/0.1\", deps=[liba, libb])\n\n        # node, include, link, build, run\n        # Seems reverse order\n        _check_transitive(app, [(libb, True, True, False, False),\n                                (liba, True, True, False, False)])\n        _check_transitive(libb, [(liba, True, True, False, False)])\n\n    def test_full_two_branches_diamond(self):\n        # https://github.com/conan-io/conan/issues/3353\n        # app -> libb/latest -(alias) -> libb/0.1 -> liba/latest -(alias) ----> liba/0.1\n        #   \\ -> libc/latest -(alias) -> libc/0.1 -> liba/latest -(alias) ----->/\n\n        self.recipe_cache(\"liba/0.1\")\n        self.alias_cache(\"liba/latest\", \"liba/0.1\")\n        self.recipe_cache(\"libb/0.1\", requires=[\"liba/(latest)\"])\n        self.recipe_cache(\"libc/0.1\", requires=[\"liba/(latest)\"])\n        self.alias_cache(\"libb/latest\", \"libb/0.1\")\n        self.alias_cache(\"libc/latest\", \"libc/0.1\")\n\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/(latest)\", \"libc/(latest)\"])\n        deps_graph = self.build_consumer(consumer)\n\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        libc = app.edges[1].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb, libc])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(libc, \"libc/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(app, \"app/0.1\", deps=[libb, libc])\n\n        # node, include, link, build, run\n        _check_transitive(app, [(libb, True, True, False, False),\n                                (libc, True, True, False, False),\n                                (liba, True, True, False, False)])\n        _check_transitive(libb, [(liba, True, True, False, False)])\n\n    def test_alias_bug(self):\n        # https://github.com/conan-io/conan/issues/2252\n        # app -> libb/0.1 -> liba/latest -(alias)->liba/0.1\n        #   \\ -> libc/0.1 ----/\n        self.recipe_cache(\"liba/0.1\")\n        self.alias_cache(\"liba/latest\", \"liba/0.1\")\n        self.recipe_cache(\"libb/0.1\", requires=[\"liba/(latest)\"])\n        self.recipe_cache(\"libc/0.1\", requires=[\"liba/(latest)\"])\n\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\", \"libc/0.1\"])\n        deps_graph = self.build_consumer(consumer)\n\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        libc = app.edges[1].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb, libc])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(libc, \"libc/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(app, \"app/0.1\", deps=[libb, libc])\n\n        # node, include, link, build, run\n        _check_transitive(app, [(libb, True, True, False, False),\n                                (libc, True, True, False, False),\n                                (liba, True, True, False, False)])\n        _check_transitive(libb, [(liba, True, True, False, False)])\n\n    def test_alias_tansitive(self):\n        # app -> liba/giga -(alias)->-> liba/mega -(alias)-> liba/latest -(alias)->liba/0.1\n\n        self.recipe_cache(\"liba/0.1\")\n        self.alias_cache(\"liba/latest\", \"liba/0.1\")\n        self.alias_cache(\"liba/mega\", \"liba/(latest)\")\n        self.alias_cache(\"liba/giga\", \"liba/(mega)\")\n\n        consumer = self.recipe_consumer(\"app/0.1\", [\"liba/(giga)\"])\n        deps_graph = self.build_consumer(consumer)\n\n        assert 2 == len(deps_graph.nodes)\n        app = deps_graph.root\n        liba = app.edges[0].dst\n\n        self._check_node(liba, \"liba/0.1#123\", dependents=[app])\n        self._check_node(app, \"app/0.1\", deps=[liba])\n\n        # node, include, link, build, run\n        _check_transitive(app, [(liba, True, True, False, False)])\n\n\nclass TestAliasBuildRequires(GraphManagerTest):\n\n    def test_non_conflicting_alias(self):\n        # https://github.com/conan-io/conan/issues/5468\n        # libc ----> libb -------------------> liba/0.1\n        #   \\-(build)-> liba/latest -(alias)-> liba/0.2\n        self.recipe_cache(\"liba/0.1\")\n        self.recipe_cache(\"liba/0.2\")\n        self.alias_cache(\"liba/latest\", \"liba/0.2\")\n        self.recipe_cache(\"libb/0.1\", [\"liba/0.1\"])\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\"], build_requires=[\"liba/(latest)\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        liba_build = app.edges[1].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n        self._check_node(liba_build, \"liba/0.2#123\", dependents=[app])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(app, \"app/0.1\", deps=[libb, liba_build])\n\n\ndef test_mixing_aliases_and_fix_versions():\n    # cd/1.0 -----------------------------> cb/latest -(alias)-> cb/1.0 -> ca/1.0\n    #   \\-----> cc/latest -(alias)-> cc/1.0 ->/                             /\n    #                                    \\------ ca/latest -(alias)------->/\n    client = TestClient(light=True)\n\n    client.save({\"conanfile.py\": GenConanfile(\"ca\", \"1.0\")})\n    client.run(\"create . \")\n    client.alias(\"ca/latest@\",  \"ca/1.0@\")\n\n    client.save({\"conanfile.py\": GenConanfile(\"cb\", \"1.0\").with_requirement(\"ca/1.0@\")})\n    client.run(\"create . --name=cb --version=1.0\")\n    client.alias(\"cb/latest@\",  \"cb/1.0@\")\n\n    client.save({\"conanfile.py\": GenConanfile(\"cc\", \"1.0\")\n                .with_requirement(\"cb/(latest)\")\n                .with_requirement(\"ca/(latest)\")})\n    client.run(\"create . \")\n    client.alias(\"cc/latest@\",  \"cc/1.0@\")\n\n    client.save({\"conanfile.py\": GenConanfile(\"cd\", \"1.0\")\n                .with_requirement(\"cb/(latest)\")\n                .with_requirement(\"cc/(latest)\")})\n    client.run(\"create . \")\n"
  },
  {
    "path": "test/integration/graph/core/test_auto_package_type.py",
    "content": "import textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\nsimple = \"\"\"\nfrom conan import ConanFile\nclass Pkg(ConanFile):\n    options = {\"shared\": [True, False],\n               \"header_only\": [True, False]}\n\"\"\"\n\npkg_type = \"\"\"\nfrom conan import ConanFile\nclass Pkg(ConanFile):\n    package_type = \"library\"\n    options = {\"shared\": [True, False],\n               \"header_only\": [True, False]}\n\"\"\"\n\nremove = \"\"\"\nfrom conan import ConanFile\nclass Pkg(ConanFile):\n    package_type = \"library\"\n    options = {\"shared\": [True, False],\n               \"header_only\": [True, False]}\n    def configure(self):\n        if self.options.header_only:\n            self.options.rm_safe(\"shared\")\n\"\"\"\n\n\n@pytest.mark.parametrize(\"conanfile\", [simple, pkg_type, remove])\ndef test_auto_package_type(conanfile):\n    c = TestClient(light=True)\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"graph info . --filter package_type\")\n    assert \"package_type: static-library\" in c.out\n    c.run(\"graph info . --filter package_type -o shared=True\")\n    assert \"The package_type will have precedence over the options\" not in c.out\n    assert \"package_type: shared-library\" in c.out\n    c.run(\"graph info . --filter package_type -o shared=True -o header_only=False\")\n    assert \"package_type: shared-library\" in c.out\n    c.run(\"graph info . --filter package_type -o header_only=True\")\n    assert \"package_type: header-library\" in c.out\n    c.run(\"graph info . --filter package_type -o header_only=True -o shared=False\")\n    assert \"package_type: header-library\" in c.out\n\n\ndef test_package_type_and_header_library():\n    \"\"\" Show that forcing a package_type and header_only=True does not change the package_type\"\"\"\n    tc = TestClient(light=True)\n    tc.save({\"conanfile.py\": textwrap.dedent(\"\"\"\n    from conan import ConanFile\n\n    class Pkg(ConanFile):\n        package_type = \"static-library\"\n        options = {\"header_only\": [True, False]}\n\n    \"\"\")})\n    tc.run(\"graph info . --filter package_type -o &:header_only=False\")\n    assert \"package_type: static-library\" in tc.out\n    assert \"The package_type will have precedence over the options\" in tc.out\n    tc.run(\"graph info . --filter package_type -o &:header_only=True\")\n    assert \"package_type: static-library\" in tc.out\n    assert \"The package_type will have precedence over the options\" in tc.out\n"
  },
  {
    "path": "test/integration/graph/core/test_build_require_invalid.py",
    "content": "import textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient, NO_SETTINGS_PACKAGE_ID\n\n\nclass TestInvalidConfiguration:\n    \"\"\"\n    ConanInvalidConfiguration without a binary fall backs, result in errors\n    \"\"\"\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.errors import ConanInvalidConfiguration\n\n        class Conan(ConanFile):\n            settings = \"os\"\n\n            def validate(self):\n                if self.info.settings.os == \"Windows\":\n                    raise ConanInvalidConfiguration(\"Package does not work in Windows!\")\n       \"\"\")\n    linux_package_id = \"9a4eb3c8701508aa9458b1a73d0633783ecc2270\"\n    invalid = \"Invalid\"\n\n    @pytest.fixture(scope=\"class\")\n    def client(self):\n        client = TestClient()\n        client.save({\"pkg/conanfile.py\": self.conanfile})\n        client.run(\"create pkg --name=pkg --version=0.1 -s os=Linux\")\n        return client\n\n    def test_invalid(self, client):\n        conanfile_consumer = GenConanfile().with_requires(\"pkg/0.1\").with_settings(\"os\")\n        client.save({\"consumer/conanfile.py\": conanfile_consumer})\n        client.run(\"install consumer -s os=Windows\", assert_error=True)\n        assert \"pkg/0.1: Invalid: Package does not work in Windows!\" in client.out\n\n    def test_invalid_info(self, client):\n        \"\"\"\n        the conan info command does not raise, but it outputs info\n        \"\"\"\n        conanfile_consumer = GenConanfile().with_requires(\"pkg/0.1\").with_settings(\"os\")\n        client.save({\"consumer/conanfile.py\": conanfile_consumer})\n        client.run(\"graph info consumer -s os=Windows\")\n        assert \"binary: Invalid\" in client.out\n\n    def test_valid(self, client):\n        conanfile_consumer = GenConanfile().with_requires(\"pkg/0.1\").with_settings(\"os\")\n        client.save({\"consumer/conanfile.py\": conanfile_consumer})\n        client.run(\"install consumer -s os=Linux\")\n        client.assert_listed_binary({\"pkg/0.1\": (self.linux_package_id, \"Cache\")})\n        assert \"pkg/0.1: Already installed!\" in client.out\n\n    def test_invalid_build_require(self, client):\n        conanfile_consumer = GenConanfile().with_tool_requires(\"pkg/0.1\").with_settings(\"os\")\n        client.save({\"consumer/conanfile.py\": conanfile_consumer})\n        client.run(\"install consumer -s:h os=Windows -s:b os=Windows\", assert_error=True)\n        assert \"pkg/0.1: Invalid: Package does not work in Windows!\" in client.out\n\n    def test_valid_build_require_two_profiles(self, client):\n        conanfile_consumer = GenConanfile().with_tool_requires(\"pkg/0.1\").with_settings(\"os\")\n        client.save({\"consumer/conanfile.py\": conanfile_consumer})\n        client.run(\"install consumer -s:b os=Linux -s:h os=Windows\")\n        client.assert_listed_binary({\"pkg/0.1\": (self.linux_package_id, \"Cache\")}, build=True)\n        assert \"pkg/0.1: Already installed!\" in client.out\n\n\nclass TestErrorConfiguration(TestInvalidConfiguration):\n    \"\"\"\n    A configuration error is unsolvable, even if a binary exists\n    \"\"\"\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.errors import ConanInvalidConfiguration\n\n        class Conan(ConanFile):\n            settings = \"os\"\n\n            def validate(self):\n                if self.info.settings.os == \"Windows\":\n                    raise ConanInvalidConfiguration(\"Package does not work in Windows!\")\n\n            def package_id(self):\n                del self.info.settings.os\n        \"\"\")\n    linux_package_id = NO_SETTINGS_PACKAGE_ID\n    invalid = \"ConfigurationError\"\n\n\nclass TestErrorConfigurationCompatible(TestInvalidConfiguration):\n    \"\"\"\n    A configuration error is unsolvable, even if a binary exists\n    \"\"\"\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.errors import ConanInvalidConfiguration\n\n        class Conan(ConanFile):\n            settings = \"os\"\n\n            def validate(self):\n                if self.info.settings.os == \"Windows\":\n                    raise ConanInvalidConfiguration(\"Package does not work in Windows!\")\n\n            def compatibility(self):\n               if self.settings.os == \"Windows\":\n                   return [{\"settings\": [(\"os\", \"Linux\")]}]\n        \"\"\")\n    linux_package_id = \"9a4eb3c8701508aa9458b1a73d0633783ecc2270\"\n    invalid = \"ConfigurationError\"\n\n\nclass TestInvalidBuildPackageID:\n    \"\"\"\n    ConanInvalidBuildConfiguration will not block if setting is removed from package_id\n    \"\"\"\n    conanfile = textwrap.dedent(\"\"\"\n       from conan import ConanFile\n       from conan.errors import ConanInvalidConfiguration\n\n       class Conan(ConanFile):\n           settings = \"os\"\n\n           def validate_build(self):\n               if self.settings.os == \"Windows\":\n                   raise ConanInvalidConfiguration(\"Package does not work in Windows!\")\n\n           def package_id(self):\n               del self.info.settings.os\n        \"\"\")\n    linux_package_id = NO_SETTINGS_PACKAGE_ID\n    windows_package_id = NO_SETTINGS_PACKAGE_ID\n\n    @pytest.fixture(scope=\"class\")\n    def client(self):\n        client = TestClient()\n        client.save({\"pkg/conanfile.py\": self.conanfile})\n        client.run(\"create pkg --name=pkg --version=0.1 -s os=Linux\")\n        return client\n\n    def test_valid(self, client):\n        conanfile_consumer = GenConanfile().with_requires(\"pkg/0.1\").with_settings(\"os\")\n        client.save({\"consumer/conanfile.py\": conanfile_consumer})\n        client.run(\"install consumer -s os=Windows\")\n        client.assert_listed_binary({\"pkg/0.1\": (self.linux_package_id, \"Cache\")})\n        assert \"pkg/0.1: Already installed!\" in client.out\n\n        client.run(\"install consumer -s os=Linux\")\n        client.assert_listed_binary({\"pkg/0.1\": (self.linux_package_id, \"Cache\")})\n        assert \"pkg/0.1: Already installed!\" in client.out\n\n    def test_invalid_try_build(self, client):\n        conanfile_consumer = GenConanfile().with_requires(\"pkg/0.1\").with_settings(\"os\")\n        client.save({\"consumer/conanfile.py\": conanfile_consumer})\n        client.run(\"install consumer -s os=Windows --build='*'\", assert_error=True)\n        # Only when trying to build, it will try to build the Windows one\n        client.assert_listed_binary({\"pkg/0.1\": (self.windows_package_id, \"Invalid\")})\n        assert \"Package does not work in Windows!\" in client.out\n\n    def test_valid_build_require_two_profiles(self, client):\n        conanfile_consumer = GenConanfile().with_tool_requires(\"pkg/0.1\").with_settings(\"os\")\n        client.save({\"consumer/conanfile.py\": conanfile_consumer})\n        client.run(\"install consumer -s:b os=Linux -s:h os=Windows\")\n        client.assert_listed_binary({\"pkg/0.1\": (self.linux_package_id, \"Cache\")}, build=True)\n        assert \"pkg/0.1: Already installed!\" in client.out\n\n        client.run(\"install consumer -s:b os=Windows -s:h os=Windows\")\n        client.assert_listed_binary({\"pkg/0.1\": (self.linux_package_id, \"Cache\")}, build=True)\n        assert \"pkg/0.1: Already installed!\" in client.out\n\n\nclass TestInvalidBuildCompatible(TestInvalidBuildPackageID):\n    \"\"\"\n    ConanInvalidBuildConfiguration will not block if compatible_packages fallback\n    \"\"\"\n    conanfile = textwrap.dedent(\"\"\"\n       from conan import ConanFile\n       from conan.errors import ConanInvalidConfiguration\n\n       class Conan(ConanFile):\n           settings = \"os\"\n\n           def validate_build(self):\n               if self.settings.os == \"Windows\":\n                   raise ConanInvalidConfiguration(\"Package does not work in Windows!\")\n\n           def compatibility(self):\n               if self.settings.os == \"Windows\":\n                   return [{\"settings\": [(\"os\", \"Linux\")]}]\n       \"\"\")\n    linux_package_id = \"9a4eb3c8701508aa9458b1a73d0633783ecc2270\"\n    windows_package_id = \"ebec3dc6d7f6b907b3ada0c3d3cdc83613a2b715\"\n"
  },
  {
    "path": "test/integration/graph/core/test_build_requires.py",
    "content": "import textwrap\n\nimport pytest\n\nfrom conan.internal.graph.graph_error import GraphConflictError, GraphLoopError\nfrom conan.api.model import RecipeReference\nfrom test.integration.graph.core.graph_manager_base import GraphManagerTest\nfrom conan.test.utils.tools import GenConanfile, NO_SETTINGS_PACKAGE_ID, TestClient\n\n\ndef _check_transitive(node, transitive_deps):\n    values = list(node.transitive_deps.values())\n\n    assert len(values) == len(transitive_deps), f\"{node}:{len(values)} != {len(transitive_deps)}\"\n\n    for v1, v2 in zip(values, transitive_deps):\n        # asserts were difficult to debug\n        if v1.node is not v2[0]: raise Exception(f\"{v1.node}!={v2[0]}\")\n        if v1.require.headers is not v2[1]: raise Exception(f\"{v1.node}!={v2[0]} headers\")\n        if v1.require.libs is not v2[2]: raise Exception(f\"{v1.node}!={v2[0]} libs\")\n        if v1.require.build is not v2[3]: raise Exception(f\"{v1.node}!={v2[0]} build\")\n        if v1.require.run is not v2[4]: raise Exception(f\"{v1.node}!={v2[0]} run\")\n        if len(v2) >= 6:\n            if v1.require.test is not v2[5]: raise Exception(f\"{v1.node}!={v2[0]} test\")\n\n\nclass TestBuildRequiresGraph(GraphManagerTest):\n\n    @pytest.mark.parametrize(\"build_require\", [\"recipe\", \"profile\"])\n    def test_basic(self, build_require):\n        # app -(br)-> cmake\n        self._cache_recipe(\"cmake/0.1\", GenConanfile())\n        if build_require == \"recipe\":\n            profile_build_requires = None\n            conanfile = GenConanfile(\"app\", \"0.1\").with_tool_requires(\"cmake/0.1\")\n        else:\n            profile_build_requires = {\"*\": [RecipeReference.loads(\"cmake/0.1\")]}\n            conanfile = GenConanfile(\"app\", \"0.1\")\n\n        deps_graph = self.build_graph(conanfile, profile_build_requires=profile_build_requires,\n                                      install=False)\n\n        # Build requires always apply to the consumer\n        assert 2 == len(deps_graph.nodes)\n        app = deps_graph.root\n        cmake = app.edges[0].dst\n\n        self._check_node(app, \"app/0.1@\", deps=[cmake], dependents=[])\n        self._check_node(cmake, \"cmake/0.1#123\", deps=[], dependents=[app])\n\n    def test_lib_build_require(self):\n        # app -> lib -(br)-> cmake\n        self._cache_recipe(\"cmake/0.1\", GenConanfile())\n        self._cache_recipe(\"lib/0.1\", GenConanfile().with_tool_requires(\"cmake/0.1\"))\n        deps_graph = self.build_graph(GenConanfile(\"app\", \"0.1\").with_require(\"lib/0.1\"))\n\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        lib = app.edges[0].dst\n        cmake = lib.edges[0].dst\n\n        self._check_node(app, \"app/0.1@\", deps=[lib], dependents=[])\n        self._check_node(lib, \"lib/0.1#123\", deps=[cmake], dependents=[app])\n        self._check_node(cmake, \"cmake/0.1#123\", deps=[], dependents=[lib])\n\n        # node, include, link, build, run\n        _check_transitive(app, [(lib, True, True, False, False)])\n        _check_transitive(lib, [(cmake, False, False, True, True)])\n\n    @pytest.mark.parametrize(\"cmakelib_type\", [\"shared\", \"static\", \"notrun\", \"run\"])\n    def test_build_require_transitive(self, cmakelib_type):\n        # app -> lib -(br)-> cmake -> cmakelib (cmakelib_type)\n\n        if cmakelib_type in (\"notrun\", \"run\"):  # Unknown\n            cmakelib = GenConanfile().with_settings(\"os\")\n        else:\n            cmakelib = GenConanfile().with_settings(\"os\").\\\n                with_shared_option(cmakelib_type == \"shared\")\n        run = True if cmakelib_type == \"run\" else None  # Not necessary to specify\n\n        self._cache_recipe(\"cmakelib/0.1\", cmakelib)\n        self._cache_recipe(\"cmake/0.1\", GenConanfile().with_settings(\"os\").\n                           with_requirement(\"cmakelib/0.1\", run=run))\n        self._cache_recipe(\"lib/0.1\", GenConanfile().with_settings(\"os\").\n                           with_tool_requires(\"cmake/0.1\"))\n        deps_graph = self.build_graph(GenConanfile(\"app\", \"0.1\").with_settings(\"os\").\n                                      with_require(\"lib/0.1\"))\n\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        lib = app.edges[0].dst\n        cmake = lib.edges[0].dst\n        cmakelib = cmake.edges[0].dst\n\n        self._check_node(app, \"app/0.1@\", deps=[lib], dependents=[], settings={\"os\": \"Linux\"})\n        self._check_node(lib, \"lib/0.1#123\", deps=[cmake], dependents=[app],\n                         settings={\"os\": \"Linux\"})\n        self._check_node(cmake, \"cmake/0.1#123\", deps=[cmakelib], dependents=[lib],\n                         settings={\"os\": \"Windows\"})\n        self._check_node(cmakelib, \"cmakelib/0.1#123\", deps=[], dependents=[cmake],\n                         settings={\"os\": \"Windows\"})\n\n        # node, include, link, build, run\n        _check_transitive(app, [(lib, True, True, False, False)])\n\n        if cmakelib_type in (\"static\", \"notrun\"):\n            _check_transitive(lib, [(cmake, False, False, True, True)])\n        else:\n            _check_transitive(lib, [(cmake, False, False, True, True),\n                                    (cmakelib, False, False, True, True)])\n\n    def test_build_require_bootstrap(self):\n        # app -> lib -(br)-> cmake/2 -(br)-> cmake/1\n        self._cache_recipe(\"cmake/0.1\", GenConanfile())\n        self._cache_recipe(\"cmake/0.2\", GenConanfile().with_tool_requires(\"cmake/0.1\"))\n        self._cache_recipe(\"lib/0.1\", GenConanfile().with_tool_requires(\"cmake/0.2\"))\n        deps_graph = self.build_graph(GenConanfile(\"app\", \"0.1\").with_require(\"lib/0.1\"))\n\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        lib = app.edges[0].dst\n        cmake2 = lib.edges[0].dst\n        cmake1 = cmake2.edges[0].dst\n\n        self._check_node(app, \"app/0.1@\", deps=[lib], dependents=[])\n        self._check_node(lib, \"lib/0.1#123\", deps=[cmake2], dependents=[app])\n        self._check_node(cmake2, \"cmake/0.2#123\", deps=[cmake1], dependents=[lib])\n        self._check_node(cmake1, \"cmake/0.1#123\", deps=[], dependents=[cmake2])\n\n        # node, include, link, build, run\n        _check_transitive(app, [(lib, True, True, False, False)])\n        _check_transitive(lib, [(cmake2, False, False, True, True)])\n        _check_transitive(cmake2, [(cmake1, False, False, True, True)])\n\n    def test_build_require_private(self):\n        # app -> lib -(br)-> cmake -(private)-> zlib\n        self._cache_recipe(\"zlib/0.1\", GenConanfile())\n        self._cache_recipe(\"cmake/0.1\", GenConanfile().with_requirement(\"zlib/0.1\", visible=False))\n        self._cache_recipe(\"lib/0.1\", GenConanfile().with_tool_requires(\"cmake/0.1\"))\n        deps_graph = self.build_graph(GenConanfile(\"app\", \"0.1\").with_require(\"lib/0.1\"))\n\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        lib = app.edges[0].dst\n        cmake = lib.edges[0].dst\n        zlib = cmake.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[lib], dependents=[])\n        self._check_node(lib, \"lib/0.1#123\", deps=[cmake], dependents=[app])\n        self._check_node(cmake, \"cmake/0.1#123\", deps=[zlib], dependents=[lib])\n        self._check_node(zlib, \"zlib/0.1#123\", deps=[], dependents=[cmake])\n\n        # node, include, link, build, run\n        _check_transitive(app, [(lib, True, True, False, False)])\n        _check_transitive(lib, [(cmake, False, False, True, True)])\n        _check_transitive(cmake, [(zlib, True, True, False, False)])\n\n\nclass TestBuildRequiresTransitivityDiamond(GraphManagerTest):\n\n    def test_build_require_transitive_static(self):\n        # app -> lib -(br)-> cmake -> zlib1 (static)\n        #          \\--(br)-> mingw -> zlib2 (static)\n        self._cache_recipe(\"zlib/0.1\", GenConanfile().with_shared_option(False))\n        self._cache_recipe(\"zlib/0.2\", GenConanfile().with_shared_option(False))\n        self._cache_recipe(\"cmake/0.1\", GenConanfile().with_require(\"zlib/0.1\"))\n        self._cache_recipe(\"mingw/0.1\", GenConanfile().with_require(\"zlib/0.2\"))\n        self._cache_recipe(\"lib/0.1\", GenConanfile().with_tool_requires(\"cmake/0.1\", \"mingw/0.1\"))\n        deps_graph = self.build_graph(GenConanfile(\"app\", \"0.1\").with_require(\"lib/0.1\"))\n\n        assert 6 == len(deps_graph.nodes)\n        app = deps_graph.root\n        lib = app.edges[0].dst\n        cmake = lib.edges[0].dst\n        mingw = lib.edges[1].dst\n        zlib1 = cmake.edges[0].dst\n        zlib2 = mingw.edges[0].dst\n\n        self._check_node(app, \"app/0.1@\", deps=[lib], dependents=[])\n        self._check_node(lib, \"lib/0.1#123\", deps=[cmake, mingw], dependents=[app])\n        self._check_node(cmake, \"cmake/0.1#123\", deps=[zlib1], dependents=[lib])\n        self._check_node(zlib1, \"zlib/0.1#123\", deps=[], dependents=[cmake])\n        self._check_node(mingw, \"mingw/0.1#123\", deps=[zlib2], dependents=[lib])\n        self._check_node(zlib2, \"zlib/0.2#123\", deps=[], dependents=[mingw])\n\n        # node, include, link, build, run\n        _check_transitive(app, [(lib, True, True, False, False)])\n        _check_transitive(lib, [(cmake, False, False, True, True),\n                                (mingw, False, False, True, True)])\n\n    def test_build_require_transitive_shared(self):\n        # app -> lib -(br)-> cmake -> zlib1 (shared)\n        #          \\--(br)-> mingw -> zlib2 (shared) -> SHOULD CONFLICT\n        self._cache_recipe(\"zlib/0.1\", GenConanfile().with_shared_option(True))\n        self._cache_recipe(\"zlib/0.2\", GenConanfile().with_shared_option(True))\n        self._cache_recipe(\"cmake/0.1\", GenConanfile().with_require(\"zlib/0.1\"))\n        self._cache_recipe(\"mingw/0.1\", GenConanfile().with_require(\"zlib/0.2\"))\n        self._cache_recipe(\"lib/0.1\", GenConanfile().with_tool_requires(\"cmake/0.1\", \"mingw/0.1\"))\n        deps_graph = self.build_graph(GenConanfile(\"app\", \"0.1\").with_require(\"lib/0.1\"),\n                                      install=False)\n\n        assert type(deps_graph.error) is GraphConflictError\n        out = str(deps_graph.error)\n        assert \"Version conflict: Conflict between zlib/0.2 and zlib/0.1 in the graph.\" in out\n        assert \"Conflict originates from lib/0.1\" in out\n\n        assert 6 == len(deps_graph.nodes)\n        app = deps_graph.root\n        lib = app.edges[0].dst\n        cmake = lib.edges[0].dst\n        mingw = lib.edges[1].dst\n        zlib1 = cmake.edges[0].dst\n        zlib2 = mingw.edges[0].dst\n\n        assert zlib1 is not zlib2\n\n        self._check_node(app, \"app/0.1@\", deps=[lib], dependents=[])\n        self._check_node(lib, \"lib/0.1#123\", deps=[cmake, mingw], dependents=[app])\n        self._check_node(cmake, \"cmake/0.1#123\", deps=[zlib1], dependents=[lib])\n        self._check_node(zlib1, \"zlib/0.1#123\", deps=[], dependents=[cmake])\n        self._check_node(mingw, \"mingw/0.1#123\", deps=[zlib2], dependents=[lib])\n        self._check_node(zlib2, \"zlib/0.2#123\", deps=[], dependents=[mingw])\n\n    def test_build_require_conflict(self):\n        # https://github.com/conan-io/conan/issues/4931\n        # cheetah -> gazelle -> grass/0.1\n        #    \\--(br)----------> grass/0.2\n\n        self._cache_recipe(\"grass/0.1\", GenConanfile())\n        self._cache_recipe(\"grass/0.2\", GenConanfile())\n        self._cache_recipe(\"gazelle/0.1\", GenConanfile().with_require(\"grass/0.1\"))\n\n        deps_graph = self.build_graph(GenConanfile(\"cheetah\", \"0.1\")\n                                      .with_require(\"gazelle/0.1\")\n                                      .with_tool_requires(\"grass/0.2\"))\n\n        assert 4 == len(deps_graph.nodes)\n        cheetah = deps_graph.root\n        gazelle = cheetah.edges[0].dst\n        grass2 = cheetah.edges[1].dst\n        grass1 = gazelle.edges[0].dst\n        self._check_node(cheetah, \"cheetah/0.1\", deps=[gazelle, grass2])\n        self._check_node(gazelle, \"gazelle/0.1#123\", deps=[grass1], dependents=[cheetah])\n        self._check_node(grass1, \"grass/0.1#123\", deps=[], dependents=[gazelle])\n        self._check_node(grass2, \"grass/0.2#123\", dependents=[cheetah])\n\n\nclass TestBuildRequiresVisible(GraphManagerTest):\n\n    def test_visible_build(self):\n        self._cache_recipe(\"liba/0.1\", GenConanfile())\n        self._cache_recipe(\"libb/0.1\", GenConanfile().with_requirement(\"liba/0.1\", build=True))\n        self._cache_recipe(\"libc/0.1\", GenConanfile().with_requirement(\"libb/0.1\", visible=False))\n        deps_graph = self.build_graph(GenConanfile(\"app\", \"0.1\").with_require(\"libc/0.1\"))\n\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libc = app.edges[0].dst\n        libb = libc.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1@\", deps=[libc], dependents=[])\n        self._check_node(libc, \"libc/0.1#123\", deps=[libb], dependents=[app])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[libc])\n        self._check_node(liba, \"liba/0.1#123\", deps=[], dependents=[libb])\n\n        # node, include, link, build, run\n        _check_transitive(app, [(libc, True, True, False, False)])\n        _check_transitive(libc, [(libb, True, True, False, False),\n                                 (liba, False, False, True, False)])  # liba is build & visible!\n        _check_transitive(libb, [(liba, True, True, True, False)])\n\n\nclass TestTestRequire(GraphManagerTest):\n\n    def test_basic(self):\n        # app -(tr)-> gtest\n        self._cache_recipe(\"gtest/0.1\", GenConanfile())\n        conanfile = GenConanfile(\"app\", \"0.1\").with_test_requires(\"gtest/0.1\")\n\n        deps_graph = self.build_graph(conanfile)\n\n        # Build requires always apply to the consumer\n        assert 2 == len(deps_graph.nodes)\n        app = deps_graph.root\n        gtest = app.edges[0].dst\n\n        self._check_node(app, \"app/0.1@\", deps=[gtest], dependents=[])\n        self._check_node(gtest, \"gtest/0.1#123\", deps=[], dependents=[app])\n\n        # node, include, link, build, run, test\n        _check_transitive(app, [(gtest, True, True, False, False, True)])\n\n    def test_lib_build_require(self):\n        # app -> lib -(tr)-> gtest\n        self._cache_recipe(\"gtest/0.1\", GenConanfile())\n        self._cache_recipe(\"lib/0.1\", GenConanfile().with_test_requires(\"gtest/0.1\"))\n        deps_graph = self.build_graph(GenConanfile(\"app\", \"0.1\").with_require(\"lib/0.1\"))\n\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        lib = app.edges[0].dst\n        gtest = lib.edges[0].dst\n\n        self._check_node(app, \"app/0.1@\", deps=[lib], dependents=[])\n        self._check_node(lib, \"lib/0.1#123\", deps=[gtest], dependents=[app])\n        self._check_node(gtest, \"gtest/0.1#123\", deps=[], dependents=[lib])\n\n        # node, include, link, build, run\n        _check_transitive(app, [(lib, True, True, False, False)])\n        _check_transitive(lib, [(gtest, True, True, False, False)])\n\n    def test_lib_build_require_transitive(self):\n        # app -> lib -(tr)-> gtest\n        self._cache_recipe(\"gtest/0.1\", GenConanfile())\n        self._cache_recipe(\"lib/0.1\", GenConanfile().with_test_requires(\"gtest/0.1\"))\n        deps_graph = self.build_graph(GenConanfile(\"app\", \"0.1\").with_require(\"lib/0.1\"))\n\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        lib = app.edges[0].dst\n        gtest = lib.edges[0].dst\n\n        self._check_node(app, \"app/0.1@\", deps=[lib], dependents=[])\n        self._check_node(lib, \"lib/0.1#123\", deps=[gtest], dependents=[app])\n        self._check_node(gtest, \"gtest/0.1#123\", deps=[], dependents=[lib])\n\n        # node, include, link, build, run\n        _check_transitive(app, [(lib, True, True, False, False)])\n        _check_transitive(lib, [(gtest, True, True, False, False)])\n\n    @pytest.mark.parametrize(\"gtestlib_type\", [\"shared\", \"static\", \"notrun\", \"run\"])\n    def test_test_require_transitive(self, gtestlib_type):\n        # app -> lib -(tr)-> gtest -> gtestlib (gtestlib_type)\n\n        if gtestlib_type in (\"notrun\", \"run\"):  # Unknown\n            gtestlib = GenConanfile().with_settings(\"os\")\n        else:\n            gtestlib = GenConanfile().with_settings(\"os\"). \\\n                with_shared_option(gtestlib_type == \"shared\")\n        run = True if gtestlib_type == \"run\" else None  # Not necessary to specify\n\n        self._cache_recipe(\"gtestlib/0.1\", gtestlib)\n        self._cache_recipe(\"gtest/0.1\", GenConanfile().with_settings(\"os\").\n                           with_requirement(\"gtestlib/0.1\", run=run))\n        self._cache_recipe(\"lib/0.1\", GenConanfile().with_settings(\"os\").\n                           with_test_requires(\"gtest/0.1\"))\n        deps_graph = self.build_graph(GenConanfile(\"app\", \"0.1\").with_settings(\"os\").\n                                      with_require(\"lib/0.1\"))\n\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        lib = app.edges[0].dst\n        gtest = lib.edges[0].dst\n        gtestlib = gtest.edges[0].dst\n\n        self._check_node(app, \"app/0.1@\", deps=[lib], dependents=[], settings={\"os\": \"Linux\"})\n        self._check_node(lib, \"lib/0.1#123\", deps=[gtest], dependents=[app],\n                         settings={\"os\": \"Linux\"})\n        self._check_node(gtest, \"gtest/0.1#123\", deps=[gtestlib], dependents=[lib],\n                         settings={\"os\": \"Linux\"})\n        self._check_node(gtestlib, \"gtestlib/0.1#123\", deps=[], dependents=[gtest],\n                         settings={\"os\": \"Linux\"})\n\n        # node, include, link, build, run\n        _check_transitive(app, [(lib, True, True, False, False)])  # TODO: Check run=None\n\n        if gtestlib_type in (\"shared\", \"run\"):\n            _check_transitive(lib, [(gtest, True, True, False, False),\n                                    (gtestlib, True, True, False, True)])\n        elif gtestlib_type == \"static\":\n            _check_transitive(lib, [(gtest, True, True, False, False),\n                                    (gtestlib, True, True, False, False)])\n        elif gtestlib_type == \"notrun\":\n            _check_transitive(lib, [(gtest, True, True, False, False),\n                                    (gtestlib, True, True, False, False)])\n\n    def test_trait_aggregated(self):\n        # app -> lib -(tr)-> gtest -> zlib\n        #         \\-------------------/\n        # If zlib is in the host context, a dependency for host, better test=False trait\n        self._cache_recipe(\"zlib/0.1\", GenConanfile())\n        self._cache_recipe(\"gtest/0.1\", GenConanfile().with_requires(\"zlib/0.1\"))\n        self._cache_recipe(\"lib/0.1\", GenConanfile().with_test_requires(\"gtest/0.1\")\n                                                    .with_requires(\"zlib/0.1\"))\n        deps_graph = self.build_graph(GenConanfile(\"app\", \"0.1\").with_require(\"lib/0.1\"))\n\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        lib = app.edges[0].dst\n        gtest = lib.edges[1].dst\n        zlib = gtest.edges[0].dst\n        zlib2 = lib.edges[0].dst\n        assert zlib is zlib2\n\n        self._check_node(app, \"app/0.1@\", deps=[lib], dependents=[])\n        self._check_node(lib, \"lib/0.1#123\", deps=[zlib, gtest], dependents=[app])\n        self._check_node(gtest, \"gtest/0.1#123\", deps=[zlib], dependents=[lib])\n        self._check_node(zlib, \"zlib/0.1#123\", deps=[], dependents=[gtest, lib])\n\n        # node, include, link, build, run\n        _check_transitive(app, [(lib, True, True, False, False),\n                                (zlib, True, True, False, False, False)])\n        _check_transitive(lib, [(gtest, True, True, False, False),\n                                (zlib, True, True, False, False, False)])\n\n    def test_test_require_loop(self):\n        # https://github.com/conan-io/conan/issues/15412\n        self._cache_recipe(\"gtest/1.11\", GenConanfile())\n        self._cache_recipe(\"abseil/1.0\", GenConanfile().with_test_requires(\"gtest/[>=1 <1.14]\"))\n        self._cache_recipe(\"gtest/1.14\", GenConanfile().with_requires(\"abseil/1.0\"))\n        deps_graph = self.build_graph(GenConanfile(\"opencv\", \"1.0\").with_test_requires(\"gtest/1.14\"))\n\n        assert 4 == len(deps_graph.nodes)\n        opencv = deps_graph.root\n        gtest14 = opencv.edges[0].dst\n        abseil = gtest14.edges[0].dst\n        gtest11 = abseil.edges[0].dst\n\n        self._check_node(opencv, \"opencv/1.0@\", deps=[gtest14], dependents=[])\n        self._check_node(gtest14, \"gtest/1.14#123\", deps=[abseil], dependents=[opencv])\n        self._check_node(abseil, \"abseil/1.0#123\", deps=[gtest11], dependents=[gtest14])\n        self._check_node(gtest11, \"gtest/1.11#123\", deps=[], dependents=[abseil])\n\n\nclass TestTestRequiresProblemsShared(GraphManagerTest):\n\n    def _check_graph(self, deps_graph, reverse):\n        assert 3 == len(deps_graph.nodes)\n        lib_c = deps_graph.root\n        if not reverse:\n            lib_a = lib_c.edges[0].dst\n            util = lib_a.edges[0].dst\n            util2 = lib_c.edges[1].dst\n        else:\n            util = lib_c.edges[0].dst\n            lib_a = lib_c.edges[1].dst\n            util2 = lib_a.edges[0].dst\n        assert util is util2\n\n        self._check_node(lib_c, \"lib_c/0.1@\", deps=[lib_a, util], dependents=[])\n        self._check_node(lib_a, \"lib_a/0.1#123\", deps=[util], dependents=[lib_c])\n        self._check_node(util, \"util/0.1#123\", deps=[], dependents=[lib_a, lib_c])\n\n        # node, include, link, build, run\n        _check_transitive(lib_c, [(lib_a, True, True, False, True),\n                                  (util, True, True, False, True)])\n\n    @pytest.mark.parametrize(\"reverse\", [True, False])\n    def test_fixed_versions(self, reverse):\n        #  lib_c -(tr)-> lib_a -0.1--> util\n        #    \\--------(tr)----0.1------/\n        # if versions exactly match, it shouldn't be an issue\n        self._cache_recipe(\"util/0.1\", GenConanfile().with_package_type(\"shared-library\"))\n        self._cache_recipe(\"lib_a/0.1\", GenConanfile().with_requires(\"util/0.1\")\n                                                      .with_package_type(\"shared-library\"))\n        deps = (\"lib_a/0.1\", \"util/0.1\") if not reverse else (\"util/0.1\", \"lib_a/0.1\")\n        deps_graph = self.build_graph(GenConanfile(\"lib_c\", \"0.1\").with_test_requires(*deps))\n        self._check_graph(deps_graph, reverse)\n\n    @pytest.mark.parametrize(\"reverse\", [True, False])\n    def test_fixed_versions_conflict(self, reverse):\n        #  lib_c -(tr)-> lib_a -0.1--> util\n        #    \\--------(tr)----0.2------/\n        # This should be a a conflict of versions\n        self._cache_recipe(\"util/0.1\", GenConanfile().with_package_type(\"shared-library\"))\n        self._cache_recipe(\"util/0.2\", GenConanfile().with_package_type(\"shared-library\"))\n        self._cache_recipe(\"lib_a/0.1\", GenConanfile().with_requires(\"util/0.1\")\n                                                      .with_package_type(\"shared-library\"))\n        deps = (\"lib_a/0.1\", \"util/0.2\") if not reverse else (\"util/0.2\", \"lib_a/0.1\")\n        conanfile = GenConanfile(\"lib_c\", \"0.1\").with_test_requires(*deps)\n        deps_graph = self.build_graph(conanfile, install=False)\n        assert type(deps_graph.error) is GraphConflictError\n\n    @pytest.mark.parametrize(\"reverse\", [True, False])\n    def test_fixed_versions_hybrid(self, reverse):\n        #  lib_c -----> lib_a--0.1--> util\n        #    \\--------(tr)----0.1------/\n        # mixing requires + test_requires, should work\n        self._cache_recipe(\"util/0.1\", GenConanfile().with_package_type(\"shared-library\"))\n        self._cache_recipe(\"util/0.2\", GenConanfile().with_package_type(\"shared-library\"))\n        self._cache_recipe(\"lib_a/0.1\", GenConanfile().with_requires(\"util/0.1\")\n                                                      .with_package_type(\"shared-library\"))\n        conanfile = GenConanfile(\"lib_c\", \"0.1\")\n        if not reverse:\n            conanfile = conanfile.with_requires(\"lib_a/0.1\").with_test_requires(\"util/0.1\")\n        else:\n            conanfile = conanfile.with_test_requires(\"lib_a/0.1\").with_requires(\"util/0.1\")\n        deps_graph = self.build_graph(conanfile)\n        self._check_graph(deps_graph, reverse=reverse)\n\n    @pytest.mark.parametrize(\"reverse\", [True, False])\n    def test_fixed_versions_hybrid_conflict(self, reverse):\n        #  lib_c -----> lib_a--0.1---> util\n        #    \\--------(tr)----0.2------/\n        # Same as above, but mixing regular requires with test_requires\n        self._cache_recipe(\"util/0.1\", GenConanfile().with_package_type(\"shared-library\"))\n        self._cache_recipe(\"util/0.2\", GenConanfile().with_package_type(\"shared-library\"))\n        self._cache_recipe(\"lib_a/0.1\", GenConanfile().with_requires(\"util/0.1\")\n                                                      .with_package_type(\"shared-library\"))\n        conanfile = GenConanfile(\"lib_c\", \"0.1\")\n        if not reverse:\n            conanfile = conanfile.with_requires(\"lib_a/0.1\").with_test_requires(\"util/0.2\")\n        else:\n            conanfile = conanfile.with_test_requires(\"lib_a/0.1\").with_requires(\"util/0.2\")\n        deps_graph = self.build_graph(conanfile, install=False)\n        assert type(deps_graph.error) is GraphConflictError\n\n    @pytest.mark.parametrize(\"reverse\", [True, False])\n    def test_version_ranges(self, reverse):\n        #  lib_c -(tr)-> lib_a -> util\n        #    \\--------(tr)-------/\n        self._cache_recipe(\"util/0.1\", GenConanfile().with_package_type(\"shared-library\"))\n        self._cache_recipe(\"lib_a/0.1\", GenConanfile().with_requires(\"util/[>=0.1 <1]\")\n                                                      .with_package_type(\"shared-library\"))\n\n        deps = (\"lib_a/[>=0]\", \"util/[>=0]\") if not reverse else (\"util/[>=0]\", \"lib_a/[>=0]\")\n        deps_graph = self.build_graph(GenConanfile(\"lib_c\", \"0.1\").with_test_requires(*deps))\n        self._check_graph(deps_graph, reverse)\n\n    @pytest.mark.parametrize(\"reverse\", [True, False])\n    def test_version_ranges_conflict(self, reverse):\n        #  lib_c -(tr)-> lib_a -> util/0.1\n        #    \\--------(tr)------> util/1.0\n        self._cache_recipe(\"util/0.1\", GenConanfile().with_package_type(\"shared-library\"))\n        self._cache_recipe(\"util/1.0\", GenConanfile().with_package_type(\"shared-library\"))\n        self._cache_recipe(\"lib_a/0.1\", GenConanfile().with_requires(\"util/[>=0.1 <1]\")\n                                                      .with_package_type(\"shared-library\"))\n        deps = (\"lib_a/[>=0]\", \"util/[>=1]\") if not reverse else (\"util/[>=1]\", \"lib_a/[>=0]\")\n        deps_graph = self.build_graph(GenConanfile(\"lib_c\", \"0.1\").with_test_requires(*deps),\n                                      install=False)\n        assert type(deps_graph.error) is GraphConflictError\n\n    @pytest.mark.parametrize(\"reverse\", [True, False])\n    def test_version_ranges_hybrid(self, reverse):\n        #  lib_c ---> lib_a -> util\n        #    \\--------(tr)-------/\n        self._cache_recipe(\"util/0.1\", GenConanfile().with_package_type(\"shared-library\"))\n        self._cache_recipe(\"lib_a/0.1\", GenConanfile().with_requires(\"util/[>=0.1 <1]\")\n                           .with_package_type(\"shared-library\"))\n\n        conanfile = GenConanfile(\"lib_c\", \"0.1\")\n        if not reverse:\n            conanfile = conanfile.with_requires(\"lib_a/[>=0.1]\").with_test_requires(\"util/[>=0.1]\")\n        else:\n            conanfile = conanfile.with_test_requires(\"lib_a/[>=0.1]\").with_requires(\"util/[>=0.1]\")\n        deps_graph = self.build_graph(conanfile)\n        self._check_graph(deps_graph, reverse)\n\n    @pytest.mark.parametrize(\"reverse\", [True, False])\n    def test_version_ranges_hybrid_conflict(self, reverse):\n        #  lib_c -(tr)-> lib_a -> util/0.1\n        #    \\--------(tr)------> util/1.0\n        self._cache_recipe(\"util/0.1\", GenConanfile().with_package_type(\"shared-library\"))\n        self._cache_recipe(\"util/1.0\", GenConanfile().with_package_type(\"shared-library\"))\n        self._cache_recipe(\"lib_a/0.1\", GenConanfile().with_requires(\"util/[>=0.1 <1]\")\n                           .with_package_type(\"shared-library\"))\n        conanfile = GenConanfile(\"lib_c\", \"0.1\")\n        if not reverse:\n            conanfile = conanfile.with_requires(\"lib_a/[>=0.1]\").with_test_requires(\"util/[>=1]\")\n        else:\n            conanfile = conanfile.with_test_requires(\"lib_a/[>=0.1]\").with_requires(\"util/[>=1]\")\n        deps_graph = self.build_graph(conanfile, install=False)\n        assert type(deps_graph.error) is GraphConflictError\n\n\nclass TestBuildRequiresPackageID(GraphManagerTest):\n\n    def test_default_no_affect(self,):\n        # app -> lib -(br)-> cmake\n        self.recipe_conanfile(\"cmake/0.1\", GenConanfile())\n        self.recipe_conanfile(\"lib/0.1\", GenConanfile().with_tool_requires(\"cmake/0.1\"))\n\n        deps_graph = self.build_graph(GenConanfile(\"app\", \"0.1\").with_requires(\"lib/0.1\"))\n\n        # Build requires always apply to the consumer\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        lib = app.edges[0].dst\n        cmake = lib.edges[0].dst\n\n        self._check_node(app, \"app/0.1@\", deps=[lib], dependents=[])\n        self._check_node(lib, \"lib/0.1#123\", deps=[cmake], dependents=[app])\n        assert lib.package_id == NO_SETTINGS_PACKAGE_ID\n        self._check_node(cmake, \"cmake/0.1#123\", deps=[], dependents=[lib])\n\n    def test_minor_mode(self,):\n        # app -> lib -(br)-> cmake\n        self.recipe_conanfile(\"cmake/0.1\", GenConanfile())\n        self.recipe_conanfile(\"lib/0.1\", GenConanfile().\n                              with_tool_requirement(\"cmake/[*]\", package_id_mode=\"minor_mode\"))\n        deps_graph = self.build_graph(GenConanfile(\"app\", \"0.1\").with_requires(\"lib/0.1\"))\n\n        # Build requires always apply to the consumer\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        lib = app.edges[0].dst\n        cmake = lib.edges[0].dst\n\n        self._check_node(app, \"app/0.1@\", deps=[lib], dependents=[])\n        self._check_node(lib, \"lib/0.1#123\", deps=[cmake], dependents=[app])\n        assert lib.package_id == \"6b92478cba14dbdc06d4e991430d3c1c04959d4a\"\n        assert lib.package_id != NO_SETTINGS_PACKAGE_ID\n        self._check_node(cmake, \"cmake/0.1#123\", deps=[], dependents=[lib])\n\n        # Change the dependency to next minor\n        self.recipe_conanfile(\"cmake/0.2\", GenConanfile())\n        deps_graph = self.build_graph(GenConanfile(\"app\", \"0.1\").with_requires(\"lib/0.1\"))\n\n        # Build requires always apply to the consumer\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        lib = app.edges[0].dst\n        assert lib.package_id == \"2813db72897dd13aca2af071efe8ecb116f679ed\"\n        assert lib.package_id != NO_SETTINGS_PACKAGE_ID\n\n\nclass TestPublicBuildRequires(GraphManagerTest):\n\n    def test_simple(self):\n        # app -> lib -(br public)-> cmake\n        self.recipe_conanfile(\"cmake/0.1\", GenConanfile())\n        self.recipe_conanfile(\"lib/0.1\", GenConanfile()\n                              .with_tool_requirement(\"cmake/0.1\", visible=True))\n\n        deps_graph = self.build_graph(GenConanfile(\"app\", \"0.1\").with_requires(\"lib/0.1\"))\n\n        # Build requires always apply to the consumer\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        lib = app.edges[0].dst\n        cmake = lib.edges[0].dst\n\n        self._check_node(app, \"app/0.1@\", deps=[lib], dependents=[])\n        self._check_node(lib, \"lib/0.1#123\", deps=[cmake], dependents=[app])\n        self._check_node(cmake, \"cmake/0.1#123\", deps=[], dependents=[lib])\n\n        # node, include, link, build, run\n        _check_transitive(lib, [(cmake, False, False, True, True)])\n        _check_transitive(app, [(lib, True, True, False, False),\n                                (cmake, False, False, True, True)])\n\n    def test_deep_dependency_tree(self):\n        # app -> liba -> libb-(br public) -> sfun -> libsfun -> libx -> liby -> libz\n        #                    -(normal req) -> libsfun -> libx -> liby -> libz\n        self.recipe_conanfile(\"libz/0.1\", GenConanfile())\n        self.recipe_conanfile(\"liby/0.1\", GenConanfile().with_requirement(\"libz/0.1\", run=True))\n        self.recipe_conanfile(\"libx/0.1\", GenConanfile().with_requirement(\"liby/0.1\", run=True))\n        self.recipe_conanfile(\"libsfun/0.1\", GenConanfile().with_requirement(\"libx/0.1\", run=True))\n        self.recipe_conanfile(\"sfun/0.1\", GenConanfile().with_requirement(\"libsfun/0.1\", run=True))\n        self.recipe_conanfile(\"libb/0.1\", GenConanfile()\n                              .with_tool_requirement(\"sfun/0.1\", visible=True)\n                              .with_requirement(\"libsfun/0.1\", run=True))\n        self.recipe_conanfile(\"liba/0.1\", GenConanfile().with_requirement(\"libb/0.1\", run=True))\n        deps_graph = self.build_graph(GenConanfile(\"app\", \"0.1\").with_requirement(\"liba/0.1\", run=True))\n\n        # Build requires always apply to the consumer\n        assert 8 + 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        liba = app.edges[0].dst\n        libb = liba.edges[0].dst\n        libsfun = libb.edges[0].dst\n        libx = libsfun.edges[0].dst\n        liby = libx.edges[0].dst\n        libz = liby.edges[0].dst\n        sfun = libb.edges[1].dst\n        libsfun_build = sfun.edges[0].dst\n        libx_build = libsfun_build.edges[0].dst\n        liby_build = libx_build.edges[0].dst\n        libz_build = liby_build.edges[0].dst\n\n        # TODO non-build-requires\n\n        self._check_node(app, \"app/0.1@\", deps=[liba], dependents=[])\n        self._check_node(liba, \"liba/0.1#123\", deps=[libb], dependents=[app])\n        self._check_node(libb, \"libb/0.1#123\", deps=[sfun, libsfun], dependents=[liba])\n        self._check_node(sfun, \"sfun/0.1#123\", deps=[libsfun_build], dependents=[libb])\n        self._check_node(libsfun_build, \"libsfun/0.1#123\", deps=[libx_build], dependents=[sfun])\n        self._check_node(libx_build, \"libx/0.1#123\", deps=[liby_build], dependents=[libsfun_build])\n        self._check_node(liby_build, \"liby/0.1#123\", deps=[libz_build], dependents=[libx_build])\n        self._check_node(libz_build, \"libz/0.1#123\", deps=[], dependents=[liby_build])\n\n        # node, include, link, build, run\n        _check_transitive(liby_build, [(libz_build, True, True, False, True)])\n        _check_transitive(libx_build, [(liby_build, True, True, False, True),\n                                       (libz_build, True, True, False, True)])\n        _check_transitive(libsfun_build, [(libx_build, True, True, False, True),\n                                          (liby_build, True, True, False, True),\n                                          (libz_build, True, True, False, True)])\n        _check_transitive(sfun, [(libsfun_build, True, True, False, True),\n                                 (libx_build, True, True, False, True),\n                                 (liby_build, True, True, False, True),\n                                 (libz_build, True, True, False, True)])\n        _check_transitive(libb, [(libsfun, True, True, False, True),\n                                 (libx, True, True, False, True),\n                                 (liby, True, True, False, True),\n                                 (libz, True, True, False, True),\n                                 (sfun, False, False, True, True),\n                                 (libsfun_build, False, False, True, True),\n                                 (libx_build, False, False, True, True),\n                                 (liby_build, False, False, True, True),\n                                 (libz_build, False, False, True, True)])\n        _check_transitive(liba, [(libb, True, True, False, True),\n                                 (libsfun, True, True, False, True),\n                                 (libx, True, True, False, True),\n                                 (liby, True, True, False, True),\n                                 (libz, True, True, False, True),\n                                 (sfun, False, False, True, True),\n                                 (libsfun_build, False, False, True, True),\n                                 (libx_build, False, False, True, True),\n                                 (liby_build, False, False, True, True),\n                                 (libz_build, False, False, True, True)])\n        _check_transitive(app, [(liba, True, True, False, True),\n                                (libb, True, True, False, True),\n                                (libsfun, True, True, False, True),\n                                (libx, True, True, False, True),\n                                (liby, True, True, False, True),\n                                (libz, True, True, False, True),\n                                (sfun, False, False, True, True),\n                                (libsfun_build, False, False, True, True),\n                                (libx_build, False, False, True, True),\n                                (liby_build, False, False, True, True),\n                                (libz_build, False, False, True, True)])\n\n    def test_conflict_diamond(self):\n        # app -> libb -(br public)-> cmake/0.1\n        #   \\--> libc -(br public)-> cmake/0.2\n        self.recipe_conanfile(\"cmake/0.1\", GenConanfile())\n        self.recipe_conanfile(\"cmake/0.2\", GenConanfile())\n        self.recipe_conanfile(\"libb/0.1\",\n                              GenConanfile().with_tool_requirement(\"cmake/0.1\", visible=True))\n        self.recipe_conanfile(\"libc/0.1\",\n                              GenConanfile().with_tool_requirement(\"cmake/0.2\", visible=True))\n\n        deps_graph = self.build_graph(GenConanfile(\"app\", \"0.1\").with_requires(\"libb/0.1\",\n                                                                               \"libc/0.1\"),\n                                      install=False)\n\n        assert type(deps_graph.error) is GraphConflictError\n\n        # Build requires always apply to the consumer\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        libc = app.edges[1].dst\n        cmake1 = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1@\", deps=[libb, libc], dependents=[])\n        self._check_node(libb, \"libb/0.1#123\", deps=[cmake1], dependents=[app])\n        self._check_node(cmake1, \"cmake/0.1#123\", deps=[], dependents=[libb])\n\n    def test_conflict_diamond_two_levels(self):\n        # app -> libd -> libb -(br public)-> cmake/0.1\n        #   \\--> libe -> libc -(br public)-> cmake/0.2\n        self.recipe_conanfile(\"cmake/0.1\", GenConanfile())\n        self.recipe_conanfile(\"cmake/0.2\", GenConanfile())\n        self.recipe_conanfile(\"libb/0.1\",\n                              GenConanfile().with_tool_requirement(\"cmake/0.1\", visible=True))\n        self.recipe_conanfile(\"libc/0.1\",\n                              GenConanfile().with_tool_requirement(\"cmake/0.2\", visible=True))\n        self.recipe_conanfile(\"libd/0.1\", GenConanfile().with_requires(\"libb/0.1\"))\n        self.recipe_conanfile(\"libe/0.1\", GenConanfile().with_requires(\"libc/0.1\"))\n\n        deps_graph = self.build_graph(GenConanfile(\"app\", \"0.1\").with_requires(\"libd/0.1\",\n                                                                               \"libe/0.1\"),\n                                      install=False)\n\n        assert type(deps_graph.error) is GraphConflictError\n\n        # Build requires always apply to the consumer\n        assert 6 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libd = app.edges[0].dst\n        libe = app.edges[1].dst\n        libb = libd.edges[0].dst\n        libc = libe.edges[0].dst\n        cmake1 = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1@\", deps=[libd, libe], dependents=[])\n        self._check_node(libd, \"libd/0.1#123\", deps=[libb], dependents=[app])\n        self._check_node(libe, \"libe/0.1#123\", deps=[libc], dependents=[app])\n        self._check_node(libb, \"libb/0.1#123\", deps=[cmake1], dependents=[libd])\n        self._check_node(libc, \"libc/0.1#123\", deps=[], dependents=[libe])\n        self._check_node(cmake1, \"cmake/0.1#123\", deps=[], dependents=[libb])\n\n    def test_tool_requires(self):\n        # app -> libb -(br public)-> protobuf/0.1\n        #           \\--------------> protobuf/0.2\n        self.recipe_conanfile(\"protobuf/0.1\", GenConanfile())\n        self.recipe_conanfile(\"protobuf/0.2\", GenConanfile())\n        self.recipe_conanfile(\"libb/0.1\",\n                              GenConanfile().with_tool_requirement(\"protobuf/0.1\", visible=True)\n                              .with_require(\"protobuf/0.2\"))\n\n        deps_graph = self.build_graph(GenConanfile(\"app\", \"0.1\").with_requires(\"libb/0.1\"))\n\n        # Build requires always apply to the consumer\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        protobuf_host = libb.edges[0].dst\n        protobuf_build = libb.edges[1].dst\n\n        self._check_node(app, \"app/0.1@\", deps=[libb], dependents=[])\n        self._check_node(libb, \"libb/0.1#123\", deps=[protobuf_host, protobuf_build],\n                         dependents=[app])\n        self._check_node(protobuf_host, \"protobuf/0.2#123\", deps=[], dependents=[libb])\n        self._check_node(protobuf_build, \"protobuf/0.1#123\", deps=[], dependents=[libb])\n\n        # node, headers, lib, build, run\n        _check_transitive(app, [(libb, True, True, False, False),\n                                (protobuf_host, True, True, False, False),\n                                (protobuf_build, False, False, True, True)])\n\n    def test_tool_requires_override(self):\n        # app -> libb -(br public)-> protobuf/0.1\n        #           \\--------------> protobuf/0.2\n        #  \\---(br, override)------> protobuf/0.2\n        self.recipe_conanfile(\"protobuf/0.1\", GenConanfile())\n        self.recipe_conanfile(\"protobuf/0.2\", GenConanfile())\n        self.recipe_conanfile(\"libb/0.1\",\n                              GenConanfile().with_tool_requirement(\"protobuf/0.1\", visible=True)\n                              .with_require(\"protobuf/0.2\"))\n\n        deps_graph = self.build_graph(GenConanfile(\"app\", \"0.1\").with_requires(\"libb/0.1\")\n                                      .with_tool_requirement(\"protobuf/0.2\", override=True))\n\n        # Build requires always apply to the consumer\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        protobuf_host = libb.edges[0].dst\n        protobuf_build = libb.edges[1].dst\n\n        self._check_node(app, \"app/0.1@\", deps=[libb], dependents=[])\n        self._check_node(libb, \"libb/0.1#123\", deps=[protobuf_host, protobuf_build],\n                         dependents=[app])\n        self._check_node(protobuf_host, \"protobuf/0.2#123\", deps=[], dependents=[libb])\n        self._check_node(protobuf_build, \"protobuf/0.2#123\", deps=[], dependents=[libb])\n\n        # node, headers, lib, build, run\n        _check_transitive(app, [(libb, True, True, False, False),\n                                (protobuf_host, True, True, False, False),\n                                (protobuf_build, False, False, True, True)])\n        _check_transitive(libb, [(protobuf_host, True, True, False, False),\n                                 (protobuf_build, False, False, True, True)])\n\n    def test_test_require(self):\n        # app -(tr)-> gtest/0.1\n        # This test should survive in 2.0\n        tool_ref = RecipeReference.loads(\"gtest/0.1\")\n        self._cache_recipe(tool_ref, GenConanfile(\"gtest\", \"0.1\"))\n\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                name = \"app\"\n                version = \"0.1\"\n                def build_requirements(self):\n                    self.test_requires(\"gtest/0.1\")\n            \"\"\")\n        deps_graph = self.build_graph(conanfile)\n\n        # Build requires always apply to the consumer\n        assert 2 == len(deps_graph.nodes)\n        app = deps_graph.root\n        tool = app.edges[0].dst\n\n        self._check_node(app, \"app/0.1@\", deps=[tool], dependents=[])\n        self._check_node(tool, \"gtest/0.1#123\", deps=[], dependents=[app])\n\n\nclass TestLoops(GraphManagerTest):\n\n    def test_direct_loop_error(self):\n        # app -(br)-> cmake/0.1 -(br itself)-> cmake/0.1....\n        # causing an infinite loop\n        self._cache_recipe(\"cmake/0.1\", GenConanfile().with_tool_requires(\"cmake/0.1\"))\n        deps_graph = self.build_graph(GenConanfile(\"app\", \"0.1\").with_build_requires(\"cmake/0.1\"),\n                                      install=False)\n\n        assert type(deps_graph.error) is GraphLoopError\n\n        # Build requires always apply to the consumer\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        tool = app.edges[0].dst\n        tool2 = tool.edges[0].dst\n        tool3 = tool2.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[tool], dependents=[])\n        self._check_node(tool, \"cmake/0.1#123\", deps=[tool2], dependents=[app])\n        self._check_node(tool2, \"cmake/0.1#123\", deps=[tool3], dependents=[tool])\n\n    def test_indirect_loop_error(self):\n        # app -(br)-> gtest/0.1 -(br)-> cmake/0.1 -(br)->gtest/0.1 ....\n        # causing an infinite loop\n        self._cache_recipe(\"gtest/0.1\", GenConanfile().with_tool_requires(\"cmake/0.1\"))\n        self._cache_recipe(\"cmake/0.1\", GenConanfile().with_test_requires(\"gtest/0.1\"))\n\n        deps_graph = self.build_graph(GenConanfile().with_build_requires(\"cmake/0.1\"),\n                                      install=False)\n\n        assert type(deps_graph.error) is GraphLoopError\n\n        # Build requires always apply to the consumer\n        assert 6 == len(deps_graph.nodes)\n        app = deps_graph.root\n        cmake = app.edges[0].dst\n        gtest = cmake.edges[0].dst\n        cmake2 = gtest.edges[0].dst\n        gtest2 = cmake2.edges[0].dst\n        cmake3 = gtest2.edges[0].dst\n\n        assert deps_graph.error.ancestor == cmake\n        assert deps_graph.error.node == cmake3\n\n    def test_infinite_recursion_test(self):\n        \"\"\"Ensure that direct conflicts in a node are properly reported and Conan does not loop\"\"\"\n        tc = TestClient(light=True)\n        tc.save({\"conanfile.py\": GenConanfile(\"app\").with_package_type(\"application\")})\n        tc.run(\"create . --version=1.0 --build-require\")\n        tc.run(\"create . --version=1.1 --build-require\")\n        tc.run(\"graph info --tool-requires=app/1.1 --tool-requires=app/1.0\", assert_error=True)\n        assert \"Duplicated requirement: app/1.0\" in tc.out\n\n\ndef test_tool_requires():\n    \"\"\"Testing temporary tool_requires attribute being \"an alias\" of build_require and\n    introduced to provide a compatible recipe with 2.0. At 2.0, the meaning of a build require being\n    a 'tool' will be a tool_require.\"\"\"\n\n    client = TestClient(light=True)\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"create . --name=tool1 --version=1.0\")\n    client.run(\"create . --name=tool2 --version=1.0\")\n    client.run(\"create . --name=tool3 --version=1.0\")\n    client.run(\"create . --name=tool4 --version=1.0\")\n\n    consumer = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            tool_requires = \"tool2/1.0\"\n            build_requires = \"tool3/1.0\"\n\n            def build_requirements(self):\n                self.tool_requires(\"tool1/1.0\")\n                self.build_requires(\"tool4/1.0\")\n\n            def generate(self):\n                assert len(self.dependencies.build.values()) == 4\n    \"\"\")\n    client.save({\"conanfile.py\": consumer})\n    client.run(\"create . --name=consumer --version=1.0\")\n    client.assert_listed_require({\"tool1/1.0\": \"Cache\",\n                                  \"tool2/1.0\": \"Cache\",\n                                  \"tool3/1.0\": \"Cache\",\n                                  \"tool4/1.0\": \"Cache\"}, build=True)\n\n\nclass TestDuplicateBuildRequires:\n    \"\"\" what happens when you require and tool_require the same dependency\n    \"\"\"\n    # https://github.com/conan-io/conan/issues/11179\n\n    @pytest.fixture()\n    def client(self):\n        client = TestClient()\n        msg = \"self.output.info('This is the binary for OS={}'.format(self.info.settings.os))\"\n        msg2 = \"self.output.info('This is in context={}'.format(self.context))\"\n        client.save({\"conanfile.py\": GenConanfile().with_settings(\"os\").with_package_id(msg)\n                                                                       .with_package_id(msg2)})\n        client.run(\"create . --name=tool1 --version=1.0 -s os=Windows\")\n        client.run(\"create . --name=tool2 --version=1.0 -s os=Windows\")\n        client.run(\"create . --name=tool3 --version=1.0 -s os=Windows\")\n        client.run(\"create . --name=tool4 --version=1.0 -s os=Windows\")\n\n        consumer = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                name = \"consumer\"\n                version = \"1.0\"\n                tool_requires = \"tool2/1.0\"\n                build_requires = \"tool3/1.0\"\n                def requirements(self):\n                    self.requires(\"tool4/1.0\")\n                def build_requirements(self):\n                    self.build_requires(\"tool4/1.0\")\n                    self.tool_requires(\"tool1/1.0\")\n                def generate(self):\n                    host_deps = sorted([d.ref for d, _ in self.dependencies.host.items()])\n                    build_deps = sorted([d.ref for d, _ in self.dependencies.build.items()])\n                    self.output.info(\"HOST DEPS: {}\".format(host_deps))\n                    self.output.info(\"BUILD DEPS: {}\".format(build_deps))\n                    assert len(host_deps) == 1, host_deps\n                    assert len(build_deps) == 4, build_deps\n            \"\"\")\n        client.save({\"conanfile.py\": consumer})\n        return client\n\n    def test_tool_requires_in_test_package(self, client):\n        \"\"\"Test that tool requires can be listed as build and host requirements\"\"\"\n        test = textwrap.dedent(\"\"\"\\\n            from conan import ConanFile\n            class Test(ConanFile):\n                def build_requirements(self):\n                    self.tool_requires(self.tested_reference_str)\n                def test(self):\n                    pass\n        \"\"\")\n\n        client.save({\"test_package/conanfile.py\": test})\n        client.run(\"create . -s:b os=Windows -s:h os=Linux  --build-require\")\n        assert \"This is the binary for OS=Linux\" not in client.out\n        assert \"This is in context=host\" not in client.out\n        client.assert_listed_require({\"consumer/1.0\": \"Cache\"}, build=True)\n        for tool in \"tool1\", \"tool2\", \"tool3\", \"tool4\":\n            client.assert_listed_require({f\"{tool}/1.0\": \"Cache\"}, build=True)\n            assert f\"{tool}/1.0: This is the binary for OS=Windows\" in client.out\n            assert f\"{tool}/1.0: This is in context=build\" in client.out\n\n        assert \"consumer/1.0: HOST DEPS: [tool4/1.0]\" in client.out\n        assert \"consumer/1.0: BUILD DEPS: [tool1/1.0, tool2/1.0, tool3/1.0, tool4/1.0]\" in client.out\n\n    def test_test_requires_in_test_package(self, client):\n        \"\"\"Test that tool requires can be listed as build and host requirements\"\"\"\n        test = textwrap.dedent(\"\"\"\\\n            from conan import ConanFile\n            class Test(ConanFile):\n                def build_requirements(self):\n                    self.test_requires(self.tested_reference_str)\n                def test(self):\n                    pass\n        \"\"\")\n\n        client.save({\"test_package/conanfile.py\": test})\n        client.run(\"create . -s:b os=Windows -s:h os=Linux --build=missing\")\n        for tool in \"tool1\", \"tool2\", \"tool3\", \"tool4\":\n            client.assert_listed_require({f\"{tool}/1.0\": \"Cache\"}, build=True)\n            assert f\"{tool}/1.0: This is the binary for OS=Windows\" in client.out\n            assert f\"{tool}/1.0: This is in context=build\" in client.out\n        client.assert_listed_require({\"consumer/1.0\": \"Cache\",\n                                      \"tool4/1.0\": \"Cache\"})\n        client.assert_listed_binary({\"tool4/1.0\": (\"9a4eb3c8701508aa9458b1a73d0633783ecc2270\",\n                                                   \"Build\")})\n\n        assert \"tool4/1.0: This is the binary for OS=Linux\" in client.out\n        assert \"tool4/1.0: This is in context=host\" in client.out\n\n        assert \"consumer/1.0: HOST DEPS: [tool4/1.0]\" in client.out\n        assert \"consumer/1.0: BUILD DEPS: [tool1/1.0, tool2/1.0, tool3/1.0, tool4/1.0]\" in client.out\n"
  },
  {
    "path": "test/integration/graph/core/test_options.py",
    "content": "from conan.test.assets.genconanfile import GenConanfile\nfrom test.integration.graph.core.graph_manager_base import GraphManagerTest\nfrom test.integration.graph.core.graph_manager_test import _check_transitive\n\n\nclass TestOptions(GraphManagerTest):\n\n    def test_basic(self):\n        # app -> libb0.1 (lib shared=True) -> liba0.1 (default static)\n        # By default if packages do not specify anything link=True is propagated run=None (unknown)\n        self.recipe_cache(\"liba/0.1\", option_shared=False)\n        self.recipe_conanfile(\"libb/0.1\", GenConanfile().with_requires(\"liba/0.1\").\n                              with_default_option(\"liba/*:shared\", True))\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\"])\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libb])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb], options={\"shared\": \"True\"})\n\n        # node, include, link, build, run\n        _check_transitive(app, [(libb, True, True, False, False),\n                                (liba, True, True, False, True)])\n        _check_transitive(libb, [(liba, True, True, False, True)])\n\n    def test_app_override(self):\n        # app (liba static)-> libb0.1 (liba shared) -> liba0.1 (default static)\n        # By default if packages do not specify anything link=True is propagated run=None (unknown)\n        self.recipe_cache(\"liba/0.1\", option_shared=False)\n        self.recipe_conanfile(\"libb/0.1\", GenConanfile().with_requires(\"liba/0.1\").\n                              with_default_option(\"liba/*:shared\", True))\n        consumer = self.consumer_conanfile(GenConanfile(\"app\", \"0.1\").with_requires(\"libb/0.1\").\n                                           with_default_option(\"liba/*:shared\", False))\n\n        deps_graph = self.build_consumer(consumer)\n\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libb])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb], options={\"shared\": \"False\"})\n\n        # node, include, link, build, run\n        _check_transitive(app, [(libb, True, True, False, False),\n                                (liba, True, True, False, False)])\n        _check_transitive(libb, [(liba, True, True, False, False)])\n\n    def test_diamond_no_conflict(self):\n        # app -> libb0.1 ---------------> liba0.1\n        #    \\-> libc0.1 (liba shared) -> liba0.1\n        # Just the first expanded one will prevail\n        self.recipe_cache(\"liba/0.1\", option_shared=False)\n        self.recipe_cache(\"libb/0.1\", [\"liba/0.1\"])\n        self.recipe_conanfile(\"libc/0.1\", GenConanfile().with_requires(\"liba/0.1\").\n                              with_default_option(\"liba*:shared\", True))\n\n        # If we expand first the \"libb\", it will expand to \"liba\" as static (shared=False)\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\", \"libc/0.1\"])\n        deps_graph = self.build_consumer(consumer)\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        libc = app.edges[1].dst\n        liba = libb.edges[0].dst\n        liba2 = libc.edges[0].dst\n        assert liba is liba2\n        self._check_node(app, \"app/0.1\", deps=[libc, libb])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb, libc], options={\"shared\": \"False\"})\n\n        # Changing the order, will make \"liba\" shared=True\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libc/0.1\", \"libb/0.1\"])\n        deps_graph = self.build_consumer(consumer)\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libc = app.edges[0].dst\n        libb = app.edges[1].dst\n        liba = libb.edges[0].dst\n        liba2 = libc.edges[0].dst\n        assert liba is liba2\n        self._check_node(app, \"app/0.1\", deps=[libc, libb])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[app])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb, libc], options={\"shared\": \"True\"})\n\n    def test_diamond_downstream_priority(self):\n        # app(liba:shared) -> libb0.1 ---------------> liba0.1\n        #    \\--------------> libc0.1 (liba shared) -> liba0.1\n        self.recipe_cache(\"liba/0.1\", option_shared=False)\n        self.recipe_cache(\"libb/0.1\", [\"liba/0.1\"])\n        self.recipe_conanfile(\"libc/0.1\", GenConanfile().with_requires(\"liba/0.1\").\n                              with_default_option(\"liba*:shared\", True))\n\n        for shared in True, False:\n            consumer = self.consumer_conanfile(GenConanfile(\"app\", \"0.1\")\n                                               .with_requires(\"libb/0.1\", \"libc/0.1\")\n                                               .with_default_option(\"liba*:shared\", shared))\n            deps_graph = self.build_consumer(consumer)\n\n            assert 4 == len(deps_graph.nodes)\n            app = deps_graph.root\n            libb = app.edges[0].dst\n            libc = app.edges[1].dst\n            liba = libb.edges[0].dst\n            liba2 = libc.edges[0].dst\n            assert liba is liba2\n            self._check_node(app, \"app/0.1\", deps=[libc, libb])\n            self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[app])\n            self._check_node(liba, \"liba/0.1#123\", dependents=[libb, libc],\n                             options={\"shared\": str(shared)})\n\n            # order doesn't matter\n            consumer = self.consumer_conanfile(GenConanfile(\"app\", \"0.1\")\n                                               .with_requires(\"libc/0.1\", \"libb/0.1\")\n                                               .with_default_option(\"liba*:shared\", shared))\n            deps_graph = self.build_consumer(consumer)\n\n            assert 4 == len(deps_graph.nodes)\n            app = deps_graph.root\n            libc = app.edges[0].dst\n            libb = app.edges[1].dst\n            liba = libb.edges[0].dst\n            liba2 = libc.edges[0].dst\n            assert liba is liba2\n            self._check_node(app, \"app/0.1\", deps=[libc, libb])\n            self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[app])\n            self._check_node(liba, \"liba/0.1#123\", dependents=[libb, libc],\n                             options={\"shared\": str(shared)})\n\n\nclass TestBuildRequireOptions(GraphManagerTest):\n    def test_protobuf_different_options_profile(self):\n        # app -> lib ------> protobuf -> zlib (shared)\n        #          \\--(br)-> protobuf -> zlib (static)\n        self._cache_recipe(\"zlib/0.1\", GenConanfile().with_shared_option(True))\n        self._cache_recipe(\"protobuf/0.1\", GenConanfile().with_require(\"zlib/0.1\"))\n        self._cache_recipe(\"lib/0.1\", GenConanfile().with_requires(\"protobuf/0.1\").\n                           with_tool_requires(\"protobuf/0.1\"))\n        deps_graph = self.build_graph(GenConanfile(\"app\", \"0.1\").with_require(\"lib/0.1\"),\n                                      options_build={\"zlib*:shared\": False})\n\n        assert 6 == len(deps_graph.nodes)\n        app = deps_graph.root\n        lib = app.edges[0].dst\n        protobuf_host = lib.edges[0].dst\n        protobuf_build = lib.edges[1].dst\n        zlib_shared = protobuf_host.edges[0].dst\n        zlib_static = protobuf_build.edges[0].dst\n\n        self._check_node(app, \"app/0.1@\", deps=[lib], dependents=[])\n        self._check_node(lib, \"lib/0.1#123\", deps=[protobuf_host, protobuf_build], dependents=[app])\n        self._check_node(protobuf_host, \"protobuf/0.1#123\", deps=[zlib_shared], dependents=[lib])\n        self._check_node(protobuf_build, \"protobuf/0.1#123\", deps=[zlib_static], dependents=[lib])\n        self._check_node(zlib_shared, \"zlib/0.1#123\", deps=[], dependents=[protobuf_host])\n        self._check_node(zlib_static, \"zlib/0.1#123\", deps=[], dependents=[protobuf_build])\n        assert not zlib_static.conanfile.options.shared\n        assert zlib_shared.conanfile.options.shared\n\n        # node, include, link, build, run\n        _check_transitive(app, [(lib, True, True, False, False),\n                                (protobuf_host, True, True, False, False),\n                                (zlib_shared, True, True, False, True)])\n        _check_transitive(lib, [(protobuf_host, True, True, False, False),\n                                (zlib_shared, True, True, False, True),\n                                (protobuf_build, False, False, True, True)])\n"
  },
  {
    "path": "test/integration/graph/core/test_provides.py",
    "content": "import textwrap\n\nimport pytest\n\nfrom conan.internal.graph.graph_error import GraphProvidesError\nfrom test.integration.graph.core.graph_manager_base import GraphManagerTest\nfrom test.integration.graph.core.graph_manager_test import _check_transitive\nfrom conan.test.utils.tools import GenConanfile, TestClient\n\n\nclass TestProvidesTest(GraphManagerTest):\n\n    def test_direct_conflict(self):\n        # app (provides feature)-> libb0.1 (provides feature)\n        self.recipe_conanfile(\"libb/0.1\", GenConanfile().with_provides(\"feature\"))\n        consumer = self.consumer_conanfile(GenConanfile(\"app\", \"0.1\").with_provides(\"feature\").\n                                           with_requires(\"libb/0.1\"))\n        deps_graph = self.build_consumer(consumer, install=False)\n\n        assert type(deps_graph.error) is GraphProvidesError\n\n        assert 2 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libb])\n        self._check_node(libb, \"libb/0.1#123\", deps=[], dependents=[app])\n\n    def test_transitive_conflict(self):\n        # app (provides feature)-> libb0.1 -> libc/0.1 (provides feature)\n        self.recipe_conanfile(\"libc/0.1\", GenConanfile().with_provides(\"feature\"))\n        self.recipe_conanfile(\"libb/0.1\", GenConanfile().with_requires(\"libc/0.1\"))\n        consumer = self.consumer_conanfile(GenConanfile(\"app\", \"0.1\").with_provides(\"feature\").\n                                           with_requires(\"libb/0.1\"))\n        deps_graph = self.build_consumer(consumer, install=False)\n\n        assert type(deps_graph.error) is GraphProvidesError\n\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        libc = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libb])\n        self._check_node(libb, \"libb/0.1#123\", deps=[libc], dependents=[app])\n        self._check_node(libc, \"libc/0.1#123\", deps=[], dependents=[libb])\n\n    @pytest.mark.parametrize(\"private\", [True, False])\n    def test_branches_conflict(self, private):\n        # app -> libb/0.1 (provides feature)\n        #  \\  -> libc/0.1 (provides feature)\n        self.recipe_conanfile(\"libc/0.1\", GenConanfile().with_provides(\"feature\"))\n        self.recipe_conanfile(\"libb/0.1\", GenConanfile().with_provides(\"feature\"))\n        if private:\n            consumer = self.consumer_conanfile(GenConanfile(\"app\", \"0.1\").\n                                               with_requirement(\"libb/0.1\", visible=False).\n                                               with_requirement(\"libc/0.1\", visible=False))\n        else:\n            consumer = self.consumer_conanfile(GenConanfile(\"app\", \"0.1\").\n                                               with_requires(\"libb/0.1\", \"libc/0.1\"))\n        deps_graph = self.build_consumer(consumer, install=False)\n\n        assert type(deps_graph.error) is GraphProvidesError\n\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        libc = app.edges[1].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libb, libc])\n        self._check_node(libb, \"libb/0.1#123\", deps=[], dependents=[app])\n        self._check_node(libc, \"libc/0.1#123\", deps=[], dependents=[app])\n\n    def test_private_no_conflict(self):\n        # app (provides libjpeg) -(private)-> br/v1 -(private)-> br_lib/v1(provides libjpeg)\n        self.recipe_conanfile(\"br_lib/0.1\", GenConanfile().with_provides(\"libjpeg\"))\n        self.recipe_conanfile(\"br/0.1\", GenConanfile().with_requirement(\"br_lib/0.1\", visible=False))\n        path = self.consumer_conanfile(GenConanfile(\"app\", \"0.1\").\n                                       with_requirement(\"br/0.1\", visible=False).\n                                       with_provides(\"libjpeg\"))\n\n        deps_graph = self.build_consumer(path)\n        assert 3 == len(deps_graph.nodes)\n\n        app = deps_graph.root\n        br = app.edges[0].dst\n        br_lib = br.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[br])\n        self._check_node(br, \"br/0.1#123\", deps=[br_lib], dependents=[app])\n        self._check_node(br_lib, \"br_lib/0.1#123\", deps=[], dependents=[br])\n\n        # node, include, link, build, run\n        _check_transitive(app, [(br, True, True, False, False)])\n        _check_transitive(br, [(br_lib, True, True, False, False)])\n\n    def test_diamond_conflict(self):\n        # app -> libb0.1 -> liba0.1\n        #    \\-> libc0.1 -> libd0.2 (provides liba)\n        self.recipe_cache(\"liba/0.1\")\n        self.recipe_conanfile(\"libd/0.2\", GenConanfile().with_provides(\"liba\"))\n        self.recipe_cache(\"libb/0.1\", [\"liba/0.1\"])\n        self.recipe_cache(\"libc/0.1\", [\"libd/0.2\"])\n\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\", \"libc/0.1\"])\n        deps_graph = self.build_consumer(consumer, install=False)\n\n        assert type(deps_graph.error) is GraphProvidesError\n\n        assert 5 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        libc = app.edges[1].dst\n        liba1 = libb.edges[0].dst\n        libd2 = libc.edges[0].dst\n        self._check_node(app, \"app/0.1\", deps=[libb, libc])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba1], dependents=[app])\n        self._check_node(libc, \"libc/0.1#123\", deps=[libd2], dependents=[app])\n\n        self._check_node(liba1, \"liba/0.1#123\", dependents=[libb])\n        # TODO: Conflicted without revision\n        self._check_node(libd2, \"libd/0.2#123\", dependents=[libc])\n\n    def test_loop(self):\n        # app -> libc0.1 -> libb0.1 -> liba0.1 ->|\n        #             \\<------(provides)---------|\n        self.recipe_conanfile(\"liba/0.1\", GenConanfile().with_provides(\"libc\"))\n        self.recipe_cache(\"libb/0.1\", [\"liba/0.1\"])\n        self.recipe_cache(\"libc/0.1\", [\"libb/0.1\"])\n\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libc/0.1\"])\n\n        deps_graph = self.build_consumer(consumer, install=False)\n        assert type(deps_graph.error) is GraphProvidesError\n\n        assert 4 == len(deps_graph.nodes)\n\n        app = deps_graph.root\n        libc = app.edges[0].dst\n        libb = libc.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[libc])\n        self._check_node(libc, \"libc/0.1#123\", deps=[libb], dependents=[app])\n        self._check_node(libb, \"libb/0.1#123\", deps=[liba], dependents=[libc])\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb])\n\n\nclass TestProvidesBuildRequire(GraphManagerTest):\n    def test_build_require_no_conflict(self):\n        # app (provides libjpeg) -(build)-> br/v1 -> br_lib/v1(provides libjpeg)\n        self.recipe_conanfile(\"br_lib/0.1\", GenConanfile().with_provides(\"libjpeg\"))\n        self.recipe_cache(\"br/0.1\", [\"br_lib/0.1\"])\n        path = self.consumer_conanfile(GenConanfile(\"app\", \"0.1\").with_tool_requires(\"br/0.1\").\n                                       with_provides(\"libjpeg\"))\n\n        deps_graph = self.build_consumer(path)\n        assert 3 == len(deps_graph.nodes)\n\n        app = deps_graph.root\n        br = app.edges[0].dst\n        br_lib = br.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[br])\n        self._check_node(br, \"br/0.1#123\", deps=[br_lib], dependents=[app])\n        self._check_node(br_lib, \"br_lib/0.1#123\", deps=[], dependents=[br])\n\n        # node, include, link, build, run\n        _check_transitive(app, [(br, False, False, True, True)])\n        _check_transitive(br, [(br_lib, True, True, False, False)])\n\n    def test_transitive_br_no_conflict(self):\n        # app (provides libjpeg) -> lib/v1 -(br)-> br/v1(provides libjpeg)\n        self.recipe_conanfile(\"br/0.1\", GenConanfile().with_provides(\"libjpeg\"))\n        self.recipe_conanfile(\"lib/0.1\", GenConanfile().with_tool_requires(\"br/0.1\"))\n        path = self.consumer_conanfile(GenConanfile(\"app\", \"0.1\").with_requires(\"lib/0.1\").\n                                       with_provides(\"libjpeg\"))\n\n        deps_graph = self.build_consumer(path)\n        assert 3 == len(deps_graph.nodes)\n\n        app = deps_graph.root\n        lib = app.edges[0].dst\n        br = lib.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[lib])\n        self._check_node(lib, \"lib/0.1#123\", deps=[br], dependents=[app])\n        self._check_node(br, \"br/0.1#123\", deps=[], dependents=[lib])\n\n        # node, include, link, build, run\n        _check_transitive(app, [(lib, True, True, False, False)])\n        _check_transitive(lib, [(br, False, False, True, True)])\n\n    def test_transitive_test_require_conflict(self):\n        # app (provides libjpeg) -(test)-> br/v1 -> br_lib/v1(provides libjpeg)\n        self.recipe_conanfile(\"br_lib/0.1\", GenConanfile().with_provides(\"libjpeg\"))\n        self.recipe_cache(\"br/0.1\", [\"br_lib/0.1\"])\n        path = self.consumer_conanfile(GenConanfile(\"app\", \"0.1\").with_test_requires(\"br/0.1\").\n                                       with_provides(\"libjpeg\"))\n\n        deps_graph = self.build_consumer(path, install=False)\n\n        assert type(deps_graph.error) is GraphProvidesError\n\n        assert 3 == len(deps_graph.nodes)\n\n        app = deps_graph.root\n        br = app.edges[0].dst\n        br_lib = br.edges[0].dst\n\n        self._check_node(app, \"app/0.1\", deps=[br])\n        self._check_node(br, \"br/0.1#123\", deps=[br_lib], dependents=[app])\n        self._check_node(br_lib, \"br_lib/0.1#123\", deps=[], dependents=[br])\n\n    def test_two_br_conflict(self):\n        # app -(build)-> br1/v1 (provides libjpeg)\n        #   \\ -(build)-> br2/v1 (provides libjpeg)\n        self.recipe_conanfile(\"br1/0.1\", GenConanfile().with_provides(\"libjpeg\"))\n        self.recipe_conanfile(\"br2/0.1\", GenConanfile().with_provides(\"libjpeg\"))\n        path = self.consumer_conanfile(GenConanfile(\"app\", \"0.1\")\n                                       .with_tool_requires(\"br1/0.1\", \"br2/0.1\"))\n        deps_graph = self.build_consumer(path, install=False)\n\n        assert type(deps_graph.error) is GraphProvidesError\n\n        assert 3 == len(deps_graph.nodes)\n\n        app = deps_graph.root\n        br1 = app.edges[0].dst\n        br2 = app.edges[1].dst\n\n        self._check_node(app, \"app/0.1\", deps=[br1, br2])\n        self._check_node(br1, \"br1/0.1#123\", deps=[], dependents=[app])\n        self._check_node(br2, \"br2/0.1#123\", deps=[], dependents=[app])\n\n\ndef test_conditional():\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Recipe(ConanFile):\n            requires = 'req/v1'\n            options = {'conflict': [True, False]}\n            default_options = {'conflict': False}\n\n            def configure(self):\n                if self.options.conflict:\n                    self.provides = 'libjpeg'\n\n            def package_info(self):\n                self.info.clear()\n    \"\"\")\n    t = TestClient(light=True)\n    t.save({'requires.py': GenConanfile(\"req\", \"v1\").with_provides(\"libjpeg\"),\n            'app.py': conanfile})\n    t.run(\"create requires.py\")\n    t.run(\"install app.py --name=app --version=version\")\n    t.run(\"install app.py --name=app --version=version -o app/*:conflict=True\", assert_error=True)\n    assert \"ERROR: Provide Conflict: Both 'app/version' and 'req/v1' provide 'libjpeg'\" in t.out\n\n\ndef test_self_build_require():\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\\\n        from conan import ConanFile\n        from conan.tools.build import cross_building\n\n        class Pkg(ConanFile):\n            name = \"grpc\"\n            version = \"0.1\"\n            settings = \"os\"\n            provides = \"grpc-impl\"\n            def build_requirements(self):\n                if cross_building(self):\n                    self.tool_requires(\"grpc/0.1\")\n        \"\"\")\n    c.save({'conanfile.py': conanfile})\n    c.run(\"create . -s os=Windows -s:b os=Windows\")\n    c.assert_listed_binary({\"grpc/0.1\": (\"ebec3dc6d7f6b907b3ada0c3d3cdc83613a2b715\", \"Build\")})\n    c.run(\"create . -s os=Linux -s:b os=Windows --build=missing\")\n    c.assert_listed_binary({\"grpc/0.1\": (\"9a4eb3c8701508aa9458b1a73d0633783ecc2270\", \"Build\")})\n    c.assert_listed_binary({\"grpc/0.1\": (\"ebec3dc6d7f6b907b3ada0c3d3cdc83613a2b715\", \"Cache\")},\n                           build=True)\n\n\ndef test_name_provide_error_message():\n    tc = TestClient(light=True)\n    tc.save({\"libjepg/conanfile.py\": GenConanfile(\"libjpeg\", \"0.1\"),\n             \"mozjpeg/conanfile.py\": GenConanfile(\"mozjpeg\", \"0.1\").with_provides(\"libjpeg\")})\n    tc.run(\"create libjepg\")\n    tc.run(\"create mozjpeg\")\n\n    tc.run(\"graph info --requires=mozjpeg/0.1 --requires=libjpeg/0.1\", assert_error=True)\n    # This used to report that None was provided, but now it reports the name of the provides\n    assert (\"ERROR: Provide Conflict: Both 'libjpeg/0.1' and \"\n            \"'mozjpeg/0.1' provide '['libjpeg']'\") in tc.out\n"
  },
  {
    "path": "test/integration/graph/core/test_version_ranges.py",
    "content": "from collections import OrderedDict\nimport pytest\n\nfrom conan.api.model import Remote\nfrom conan.internal.graph.graph_error import GraphConflictError, GraphMissingError\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom test.integration.graph.core.graph_manager_base import GraphManagerTest\nfrom conan.test.utils.tools import TestClient, TestServer, NO_SETTINGS_PACKAGE_ID\n\n\nclass TestVersionRanges(GraphManagerTest):\n\n    def test_transitive(self):\n        # app -> libb[>0.1]\n        self.recipe_cache(\"libb/0.1\")\n        self.recipe_cache(\"libb/0.2\")\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/[>=0.0]\"])\n        deps_graph = self.build_consumer(consumer)\n\n        assert 2 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n\n        self._check_node(libb, \"libb/0.2#123\", dependents=[app])\n        self._check_node(app, \"app/0.1\", deps=[libb])\n\n    def test_transitive_local_conditions(self):\n        for v in [\"0.1\", \"0.2\", \"0.3\", \"1.1\", \"1.1.2\", \"1.2.1\", \"2.1\", \"2.2.1\"]:\n            self.recipe_cache(f\"libb/{v}\")\n\n        for expr, solution in [(\">0.0\", \"2.2.1\"),\n                               (\">0.1 <1\", \"0.3\"),\n                               (\">0.1 <1||2.1\", \"2.1\"),\n                               (\"\", \"2.2.1\"),\n                               (\"~0\", \"0.3\"),\n                               (\"~1\", \"1.2.1\"),\n                               (\"~1.1\", \"1.1.2\"),\n                               (\"~2\", \"2.2.1\"),\n                               (\"~2.1\", \"2.1\"),\n                               ]:\n            consumer = self.recipe_consumer(\"app/0.1\", [f\"libb/[{expr}]\"])\n            deps_graph = self.build_consumer(consumer)\n            assert 2 == len(deps_graph.nodes)\n            app = deps_graph.root\n            libb = app.edges[0].dst\n\n            self._check_node(libb, f\"libb/{solution}#123\", dependents=[app])\n            self._check_node(app, \"app/0.1\", deps=[libb])\n\n    def test_missing(self):\n        # app -> libb[>0.1] (missing)\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/[>=0.0]\"])\n\n        deps_graph = self.build_consumer(consumer, install=False)\n\n        assert type(deps_graph.error) is GraphMissingError\n\n        assert 1 == len(deps_graph.nodes)\n        app = deps_graph.root\n        self._check_node(app, \"app/0.1\", deps=[])\n\n    def test_userchannel_no_match(self):\n        # app -> libb[>0.1] (missing)\n        self.recipe_cache(\"libb/0.1@user/channel\")\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/[>=0.0]\"])\n\n        deps_graph = self.build_consumer(consumer, install=False)\n\n        assert type(deps_graph.error) is GraphMissingError\n\n        assert 1 == len(deps_graph.nodes)\n        app = deps_graph.root\n\n        self._check_node(app, \"app/0.1\", deps=[])\n\n    def test_required_userchannel_no_match(self):\n        # app -> libb[>0.1] (missing)\n        self.recipe_cache(\"libb/0.1\")\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/[>=0.0]@user/channel\"])\n\n        deps_graph = self.build_consumer(consumer, install=False)\n\n        assert type(deps_graph.error) is GraphMissingError\n\n        assert 1 == len(deps_graph.nodes)\n        app = deps_graph.root\n\n        self._check_node(app, \"app/0.1\", deps=[])\n\n    def test_transitive_out_range(self):\n        # app -> libb[>0.1] (missing)\n        self.recipe_cache(\"libb/0.1\")\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/[>1.0]\"])\n\n        deps_graph = self.build_consumer(consumer, install=False)\n\n        assert type(deps_graph.error) is GraphMissingError\n\n        assert 1 == len(deps_graph.nodes)\n        app = deps_graph.root\n\n        self._check_node(app, \"app/0.1\", deps=[])\n\n\nclass TestVersionRangesDiamond(GraphManagerTest):\n    def test_transitive(self):\n        # app -> libb/0.1 -(range >0)-> liba/0.2\n        #   \\ -> libc/0.1 -(range <1)---/\n        self.recipe_cache(\"liba/0.1\")\n        self.recipe_cache(\"liba/0.2\")\n        self.recipe_cache(\"libb/0.1\", [\"liba/[>=0.0]\"])\n        self.recipe_cache(\"libc/0.1\", [\"liba/[<1.0]\"])\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\", \"libc/0.1\"])\n        deps_graph = self.build_consumer(consumer)\n\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        libc = app.edges[1].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(liba, \"liba/0.2#123\", dependents=[libb, libc], deps=[])\n        self._check_node(libb, \"libb/0.1#123\", dependents=[app], deps=[liba])\n        self._check_node(libc, \"libc/0.1#123\", dependents=[app], deps=[liba])\n        self._check_node(app, \"app/0.1\", deps=[libb, libc])\n\n    def test_transitive_interval(self):\n        # app -> libb/0.1 -(range >0 <0.3)-> liba/0.2\n        #   \\ -> libc/0.1 -(range <1)--------/\n        self.recipe_cache(\"liba/0.1\")\n        self.recipe_cache(\"liba/0.2\")\n        self.recipe_cache(\"liba/0.3\")\n        self.recipe_cache(\"libb/0.1\", [\"liba/[>=0.0 <0.3]\"])\n        self.recipe_cache(\"libc/0.1\", [\"liba/[<1.0]\"])\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\", \"libc/0.1\"])\n        deps_graph = self.build_consumer(consumer)\n\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        libc = app.edges[1].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(liba, \"liba/0.2#123\", dependents=[libb, libc], deps=[])\n        self._check_node(libb, \"libb/0.1#123\", dependents=[app], deps=[liba])\n        self._check_node(libc, \"libc/0.1#123\", dependents=[app], deps=[liba])\n        self._check_node(app, \"app/0.1\", deps=[libb, libc])\n\n    def test_transitive_fixed(self):\n        # app -> libb/0.1 --------> liba/0.1\n        #   \\ -> libc/0.1 -(range <1)---/\n        self.recipe_cache(\"liba/0.1\")\n        self.recipe_cache(\"liba/0.2\")\n        self.recipe_cache(\"libb/0.1\", [\"liba/0.1\"])\n        self.recipe_cache(\"libc/0.1\", [\"liba/[<1.0]\"])\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\", \"libc/0.1\"])\n        deps_graph = self.build_consumer(consumer)\n\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        libc = app.edges[1].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb, libc], deps=[])\n        self._check_node(libb, \"libb/0.1#123\", dependents=[app], deps=[liba])\n        self._check_node(libc, \"libc/0.1#123\", dependents=[app], deps=[liba])\n        self._check_node(app, \"app/0.1\", deps=[libb, libc])\n\n    def test_transitive_conflict(self):\n        # app -> libb/0.1 -(range >0)-> liba/0.2\n        #   \\ -> libc/0.1 -(range >1)---/\n        self.recipe_cache(\"liba/0.2\")\n        self.recipe_cache(\"libb/0.1\", [\"liba/[>=0.0]\"])\n        self.recipe_cache(\"libc/0.1\", [\"liba/[>1.0]\"])\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\", \"libc/0.1\"])\n        deps_graph = self.build_consumer(consumer, install=False)\n\n        assert type(deps_graph.error) is GraphConflictError\n\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        app.enabled_remotes = [Remote(\"foo\", None)]\n        libb = app.edges[0].dst\n        libc = app.edges[1].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(libb, \"libb/0.1#123\", dependents=[app], deps=[liba])\n        self._check_node(libb, \"libb/0.1#123\", dependents=[app], deps=[liba])\n        self._check_node(libc, \"libc/0.1#123\", dependents=[app], deps=[])\n        self._check_node(app, \"app/0.1\", deps=[libb, libc])\n\n    def test_transitive_fixed_conflict(self):\n        # app -> libb/0.1 ---------> liba/0.2\n        #   \\ -> libc/0.1 -(range >1)---/\n        self.recipe_cache(\"liba/0.2\")\n        self.recipe_cache(\"libb/0.1\", [\"liba/[>=0.0]\"])\n        self.recipe_cache(\"libc/0.1\", [\"liba/[>1.0]\"])\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\", \"libc/0.1\"])\n        deps_graph = self.build_consumer(consumer, install=False)\n\n        assert type(deps_graph.error) is GraphConflictError\n\n        assert 4 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        libc = app.edges[1].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(libb, \"libb/0.1#123\", dependents=[app], deps=[liba])\n        self._check_node(libb, \"libb/0.1#123\", dependents=[app], deps=[liba])\n        self._check_node(libc, \"libc/0.1#123\", dependents=[app], deps=[])\n        self._check_node(app, \"app/0.1\", deps=[libb, libc])\n\n\nclass TestVersionRangesOverridesDiamond(GraphManagerTest):\n    def test_transitive(self):\n        # app -> libb/0.1 -(range >0)-> liba/0.2\n        #   \\ ---------------------------/\n        self.recipe_cache(\"liba/0.1\")\n        self.recipe_cache(\"liba/0.2\")\n        self.recipe_cache(\"libb/0.1\", [\"liba/[>=0.0]\"])\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\", \"liba/0.2\"])\n        deps_graph = self.build_consumer(consumer)\n\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(liba, \"liba/0.2#123\", dependents=[libb, app], deps=[])\n        self._check_node(libb, \"libb/0.1#123\", dependents=[app], deps=[liba])\n        self._check_node(app, \"app/0.1\", deps=[libb, liba])\n\n    def test_transitive_overriden(self):\n        # app -> libb/0.1 -(range >0)-> liba/0.1\n        #   \\ ---------liba/0.1-------------/\n        self.recipe_cache(\"liba/0.1\")\n        self.recipe_cache(\"liba/0.2\")\n        self.recipe_cache(\"libb/0.1\", [\"liba/[>=0.0]\"])\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\", \"liba/0.1\"])\n        deps_graph = self.build_consumer(consumer)\n\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb, app], deps=[])\n        self._check_node(libb, \"libb/0.1#123\", dependents=[app], deps=[liba])\n        self._check_node(app, \"app/0.1\", deps=[libb, liba])\n\n    def test_transitive_fixed(self):\n        # app ---> libb/0.1 -----------> liba/0.1\n        #   \\ --------(range<1)----------/\n        self.recipe_cache(\"liba/0.1\")\n        self.recipe_cache(\"liba/0.2\")\n        self.recipe_cache(\"libb/0.1\", [\"liba/0.1\"])\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\", \"liba/[<1.0]\"])\n        deps_graph = self.build_consumer(consumer)\n\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(liba, \"liba/0.1#123\", dependents=[libb, app], deps=[])\n        self._check_node(libb, \"libb/0.1#123\", dependents=[app], deps=[liba])\n        self._check_node(app, \"app/0.1\", deps=[libb, liba])\n\n    def test_transitive_fixed_conflict(self):\n        # app ---> libb/0.1 -----------> liba/0.1\n        #   \\ --------(range>1)----------/\n        self.recipe_cache(\"liba/0.1\")\n        self.recipe_cache(\"liba/1.2\")\n        self.recipe_cache(\"libb/0.1\", [\"liba/0.1\"])\n        consumer = self.recipe_consumer(\"app/0.1\", [\"libb/0.1\", \"liba/[>1.0]\"])\n        deps_graph = self.build_consumer(consumer, install=False)\n\n        assert type(deps_graph.error) is GraphConflictError\n\n        assert 2 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n\n    def test_transitive_fixed_conflict_forced(self):\n        # app ---> libb/0.1 -----------> liba/1.2\n        #   \\ --------(range>1)----------/\n        self.recipe_cache(\"liba/0.1\")\n        self.recipe_cache(\"liba/1.2\")\n        self.recipe_cache(\"libb/0.1\", [\"liba/0.1\"])\n        consumer = self.consumer_conanfile(GenConanfile(\"app\", \"0.1\").with_require(\"libb/0.1\")\n                                           .with_requirement(\"liba/[>1.0]\", force=True))\n        deps_graph = self.build_consumer(consumer, install=False)\n\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(liba, \"liba/1.2#123\", dependents=[libb, app], deps=[])\n        self._check_node(libb, \"libb/0.1#123\", dependents=[app], deps=[liba])\n        self._check_node(app, \"app/0.1\", deps=[libb, liba])\n\n    def test_two_ranges_overriden(self):\n        # app -> libb/0.1 -(range >0)-> liba/0.1\n        #   \\ ---------liba/[<0.3>]-------------/\n        self.recipe_cache(\"liba/0.1\")\n        self.recipe_cache(\"liba/0.2\")\n        self.recipe_cache(\"liba/0.3\")\n        self.recipe_cache(\"libb/0.1\", [\"liba/[>=0.0]\"])\n        consumer = self.consumer_conanfile(GenConanfile(\"app\", \"0.1\").with_require(\"libb/0.1\")\n                                           .with_requirement(\"liba/[<0.4]\"))\n        deps_graph = self.build_consumer(consumer)\n\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(liba, \"liba/0.3#123\", dependents=[libb, app], deps=[])\n        self._check_node(libb, \"libb/0.1#123\", dependents=[app], deps=[liba])\n        self._check_node(app, \"app/0.1\", deps=[libb, liba])\n\n    def test_two_ranges_overriden_no_conflict(self):\n        # app -> libb/0.1 -(range >0)-> liba/0.1\n        #   \\ ---------liba/[<0.3>]-------------/\n        # Conan learned to solve this conflict in 2.0.14\n        self.recipe_cache(\"liba/0.1\")\n        self.recipe_cache(\"liba/0.2\")\n        self.recipe_cache(\"liba/0.3\")\n        self.recipe_cache(\"libb/0.1\", [\"liba/[>=0.0]\"])\n        consumer = self.consumer_conanfile(GenConanfile(\"app\", \"0.1\").with_require(\"libb/0.1\")\n                                           .with_requirement(\"liba/[<0.3]\"))\n        deps_graph = self.build_consumer(consumer, install=False)\n\n        # This is no longer a conflict, and Conan knows that liba/2.0 is a valid joint solution\n\n        assert 3 == len(deps_graph.nodes)\n        app = deps_graph.root\n        libb = app.edges[0].dst\n        liba = libb.edges[0].dst\n\n        self._check_node(liba, \"liba/0.2#123\", dependents=[libb, app], deps=[])\n        self._check_node(libb, \"libb/0.1#123\", dependents=[app], deps=[liba])\n        self._check_node(app, \"app/0.1\", deps=[libb, liba])\n\n\ndef test_mixed_user_channel():\n    # https://github.com/conan-io/conan/issues/7846\n    t = TestClient(default_server_user=True, light=True)\n    t.save({\"conanfile.py\": GenConanfile()})\n    t.run(\"create . --name=pkg --version=1.0\")\n    t.run(\"create . --name=pkg --version=1.1\")\n    t.run(\"create . --name=pkg --version=2.0\")\n    t.run(\"create . --name=pkg --version=1.0 --user=user --channel=testing\")\n    t.run(\"create . --name=pkg --version=1.1 --user=user --channel=testing\")\n    t.run(\"create . --name=pkg --version=2.0 --user=user --channel=testing\")\n    t.run(\"upload * --confirm -r default\")\n    t.run(\"remove * -c\")\n\n    t.run('install --requires=\"pkg/[>0 <2]@\"')\n    t.assert_listed_require({\"pkg/1.1\": \"Downloaded (default)\"})\n    t.run('install --requires=\"pkg/[>0 <2]@user/testing\"')\n    t.assert_listed_require({\"pkg/1.1@user/testing\": \"Downloaded (default)\"})\n\n\ndef test_remote_version_ranges():\n    t = TestClient(default_server_user=True, light=True)\n    t.save({\"conanfile.py\": GenConanfile()})\n    for v in [\"0.1\", \"0.2\", \"0.3\", \"1.1\", \"1.1.2\", \"1.2.1\", \"2.1\", \"2.2.1\"]:\n        t.run(f\"create . --name=dep --version={v}\")\n    t.run(\"upload * --confirm -r default\")\n    # TODO: Deprecate the comma separator for expressions\n    for expr, solution in [(\">0.0\", \"2.2.1\"),\n                           (\">0.1 <1\", \"0.3\"),\n                           (\">0.1 <1||2.1\", \"2.1\"),\n                           (\"\", \"2.2.1\"),\n                           (\"~0\", \"0.3\"),\n                           (\"~1\", \"1.2.1\"),\n                           (\"~1.1\", \"1.1.2\"),\n                           (\"~2\", \"2.2.1\"),\n                           (\"~2.1\", \"2.1\"),\n                           ]:\n        t.run(\"remove * -c\")\n        t.save({\"conanfile.py\": GenConanfile().with_requires(f\"dep/[{expr}]\")})\n        t.run(\"install .\")\n        assert str(t.out).count(\"Not found in local cache, looking in remotes\") == 1\n        t.assert_listed_binary({f\"dep/{solution}\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\",\n                                                    \"Download (default)\")})\n\n\ndef test_different_user_channel_resolved_correctly():\n    server1 = TestServer()\n    server2 = TestServer()\n    servers = OrderedDict([(\"server1\", server1), (\"server2\", server2)])\n\n    client = TestClient(servers=servers, inputs=2*[\"admin\", \"password\"], light=True)\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"create . --name=lib --version=1.0 --user=conan --channel=stable\")\n    client.run(\"create . --name=lib --version=1.0 --user=conan --channel=testing\")\n    client.run(\"upload lib/1.0@conan/stable -r=server1\")\n    client.run(\"upload lib/1.0@conan/testing -r=server2\")\n\n    client2 = TestClient(servers=servers, light=True)\n    client2.run(\"install --requires=lib/[>=1.0]@conan/testing\")\n    assert f\"lib/1.0@conan/testing: Retrieving package {NO_SETTINGS_PACKAGE_ID} \" \\\n           f\"from remote 'server2' \" in client2.out\n\n\ndef test_unknown_options():\n    c = TestClient(light=True)\n    c.save({\"conanfile.py\": GenConanfile(\"lib\", \"2.0\")})\n    c.run(\"create .\")\n\n    c.run(\"graph info --requires=lib/[>1.2,<1.4]\", assert_error=True)\n    assert '\"<1.4\" in version range \">1.2,<1.4\" is not a valid option' in c.out\n\n    c.run(\"graph info --requires=lib/[>1.2,unknown_conf]\")\n    assert 'WARN: Unrecognized version range option \"unknown_conf\" in \">1.2,unknown_conf\"' in c.out\n\n\n@pytest.mark.parametrize(\"version_range,should_warn\", [\n    [\">=0.1, include_prereleases\", False],\n    [\">=0.1, include_prerelease=True\", True],\n    [\">=0.1, include_prerelease=False\", True]\n])\ndef test_bad_options_syntax(version_range, should_warn):\n    \"\"\"We don't error out on bad options, maybe we should,\n    but for now this test ensures we don't change it without realizing\"\"\"\n    tc = TestClient(light=True)\n    tc.save({\"lib/conanfile.py\": GenConanfile(\"lib\", \"1.0\"),\n             \"app/conanfile.py\": GenConanfile(\"app\", \"1.0\").with_requires(f\"lib/[{version_range}]\")})\n    tc.run(\"export lib\")\n    tc.run(\"graph info app/conanfile.py\")\n    if should_warn:\n        assert \"its presence unconditionally enables prereleases\" in tc.out\n    else:\n        assert \"its presence unconditionally enables prereleases\" not in tc.out\n\n\ndef test_empty_version_ranger():\n    tc = TestClient(light=True)\n    tc.save({\"lib/conanfile.py\": GenConanfile(\"lib\", \"1.0\"),\n             \"app/conanfile.py\": GenConanfile(\"app\", \"1.0\").with_requires(\"lib/[]\")})\n    tc.run(\"export lib\")\n    tc.run(\"graph info app\")\n    assert \"lib/[]: lib/1.0\" in tc.out\n    assert \"Empty version range usage is discouraged\" in tc.out\n"
  },
  {
    "path": "test/integration/graph/require_override_test.py",
    "content": "from conan.test.utils.tools import TestClient, GenConanfile\n\n\nclass TestRequireOverride:\n\n    def test_override_user_channel(self):\n        c = TestClient(light=True)\n        c.save({\"dep/conanfile.py\": GenConanfile(),\n                \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_requires(\"dep1/0.1\")\n                                                              .with_requires(\"dep2/0.1@us/chan\"),\n                \"app/conanfile.py\": GenConanfile().with_requires(\"pkg/0.1\")\n                                                  .with_requirement(\"dep1/0.1@us/chan\",\n                                                                    override=True)\n                                                  .with_requirement(\"dep2/0.1\", override=True)})\n        c.run(\"create dep --name=dep1 --version=0.1\")\n        c.run(\"create dep --name=dep1 --version=0.1 --user=us --channel=chan\")\n        c.run(\"create dep --name=dep2 --version=0.1\")\n        c.run(\"create dep --name=dep2 --version=0.1 --user=us --channel=chan\")\n        c.run(\"export pkg\")\n        c.run(\"graph info app\")\n        c.assert_overrides({\"dep1/0.1\": ['dep1/0.1@us/chan'],\n                            \"dep2/0.1@us/chan\": ['dep2/0.1']})\n        c.assert_listed_require({\"dep1/0.1@us/chan\": \"Cache\",\n                                 \"dep2/0.1\": \"Cache\"})\n\n    def test_can_override_even_versions_with_build_metadata(self):\n        # https://github.com/conan-io/conan/issues/5900\n        c = TestClient(light=True)\n        c.save({\"conanfile.py\": GenConanfile(\"lib\")})\n        c.run(\"create . --version=1.0+abc\")\n        c.run(\"create . --version=1.0+xyz\")\n\n        c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_require(\"lib/1.0+abc\")})\n        c.run(\"create .\")\n\n        c.save({\"conanfile.py\": GenConanfile().with_require(\"pkg/1.0\")\n                                              .with_requirement(\"lib/1.0+xyz\", override=True)})\n        c.run(\"graph info .\")\n        c.assert_overrides({\"lib/1.0+abc\": ['lib/1.0+xyz']})\n        c.assert_listed_require({\"lib/1.0+xyz\": \"Cache\",\n                                 \"pkg/1.0\": \"Cache\"})\n\n"
  },
  {
    "path": "test/integration/graph/test_dependencies_visit.py",
    "content": "import textwrap\n\nimport pytest\n\nfrom conan.api.model import RecipeReference\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_dependencies_visit():\n    client = TestClient(light=True)\n    client.save({\"conanfile.py\": GenConanfile().with_shared_option(True)})\n    client.run(\"create . --name=openssl --version=0.1\")\n    client.run(\"create . --name=openssl --version=0.2\")\n    client.save({\"conanfile.py\": GenConanfile().with_requires(\"openssl/0.2\")})\n    client.run(\"create . --name=cmake --version=0.1\")\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            requires = \"openssl/0.1\"\n            build_requires = \"cmake/0.1\"\n\n            def generate(self):\n                dep = self.dependencies[\"openssl\"]\n                self.output.info(\"DefRef: {}!!!\".format(dep.ref.repr_notime()))\n                self.output.info(\"DefPRef: {}!!!\".format(dep.pref.repr_notime()))\n                dep = self.dependencies.build[\"openssl\"]\n                self.output.info(\"DefRefBuild: {}!!!\".format(dep.ref.repr_notime()))\n                self.output.info(\"DefPRefBuild: {}!!!\".format(dep.pref.repr_notime()))\n                for r, d in self.dependencies.build.items():\n                    self.output.info(\"DIRECTBUILD {}: {}\".format(r.direct, d))\n\n                if \"openssl\" in self.dependencies:\n                    self.output.info(\"OpenSSL found in deps\")\n\n                if \"cmake\" in self.dependencies:\n                    self.output.info(\"cmake found in default deps\")\n\n                if \"cmake\" in self.dependencies.build:\n                    self.output.info(\"cmake found in deps.build\")\n\n                if \"badlib\" in self.dependencies:\n                    self.output.info(\"badlib found in deps\")\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n\n    client.run(\"install .\")\n    refs = client.cache.get_latest_recipe_revision(RecipeReference.loads(\"openssl/0.1\"))\n    pkgs = client.cache.get_package_references(refs)\n    prev1 = client.cache.get_latest_package_revision(pkgs[0])\n    assert f\"DefRef: {repr(prev1.ref)}!!!\" in client.out\n    assert f\"DefPRef: {prev1.repr_notime()}!!!\" in client.out\n\n    refs = client.cache.get_latest_recipe_revision(RecipeReference.loads(\"openssl/0.2\"))\n    pkgs = client.cache.get_package_references(refs)\n    prev2 = client.cache.get_latest_package_revision(pkgs[0])\n    assert f\"DefRefBuild: {repr(prev2.ref)}!!!\" in client.out\n    assert f\"DefPRefBuild: {prev2.repr_notime()}!!!\" in client.out\n\n    assert \"conanfile.py: DIRECTBUILD True: cmake/0.1\" in client.out\n    assert \"conanfile.py: DIRECTBUILD False: openssl/0.2\" in client.out\n\n    assert \"OpenSSL found in deps\" in client.out\n    assert \"badlib found in deps\" not in client.out\n\n    assert \"cmake found in default deps\" not in client.out\n    assert \"cmake found in deps.build\" in client.out\n\n\ndef test_dependencies_visit_settings_options():\n    client = TestClient(light=True)\n    client.save({\"conanfile.py\": GenConanfile().with_settings(\"os\").\n                with_option(\"shared\", [True, False]).with_default_option(\"shared\", False)})\n    client.run(\"create . --name=openssl --version=0.1 -s os=Linux\")\n    client.save({\"conanfile.py\": GenConanfile().with_requires(\"openssl/0.1\")})\n    client.run(\"create . --name=pkg --version=0.1  -s os=Linux\")\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            requires = \"pkg/0.1\"\n\n            def generate(self):\n                dep = self.dependencies[\"openssl\"]\n                self.output.info(\"SETTINGS: {}!\".format(dep.settings.os))\n                self.output.info(\"OPTIONS: shared={}!\".format(dep.options.shared))\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"install . -s os=Linux\")\n    assert \"conanfile.py: SETTINGS: Linux!\" in client.out\n    assert \"conanfile.py: OPTIONS: shared=False!\" in client.out\n\n\nasserts = [\n    ('print(\"=>{}\".format(self.dependencies[\"zlib\"].ref))',\n     False, \"=>zlib/0.2\"),\n    ('print(\"=>{}\".format(self.dependencies.build.get(\"zlib\").ref))',\n     False, \"=>zlib/0.1\"),\n    ('print(\"=>{}\".format(self.dependencies.get(\"zlib\", build=True).ref))',\n     False, \"=>zlib/0.1\"),\n    ('print(\"=>{}\".format(self.dependencies.get(\"zlib\", build=False).ref))',\n     False, \"=>zlib/0.2\"),\n    ('print(\"=>{}\".format(self.dependencies.get(\"zlib\", build=True, visible=False).ref))',\n     False, \"=>zlib/0.1\"),\n    ('self.dependencies.get(\"cmake\", build=True)', True,\n     'There are more than one requires matching the specified filters: {\\'build\\': True}\\n'\n     '- cmake/0.1, Traits: build=True, headers=False, libs=False, run=False, visible=False\\n'\n     '- cmake/0.2, Traits: build=True, headers=False, libs=False, run=False, visible=False'\n     ),\n    ('self.dependencies[\"missing\"]', True, \"'missing' not found in the dependency set\"),\n    ('self.output.info(\"Missing in deps: \" + str(\"missing\" in self.dependencies))', False, \"Missing in deps: False\"),\n    ('self.output.info(\"Zlib in deps: \" + str(\"zlib\" in self.dependencies))', False, \"Zlib in deps: True\"),\n    ('self.output.info(\"Zlib in deps.build: \" + str(\"zlib\" in self.dependencies.build))', False, \"Zlib in deps.build: True\"),\n]\n\n\n@pytest.mark.parametrize(\"generates_line, assert_error, output_text\", asserts)\ndef test_cmake_zlib(generates_line, assert_error, output_text):\n    # app (br)---> cmake (0.1) -> zlib/0.1\n    #  \\     ----> zlib/0.2\n    #  \\  (br)---> cmake (0.2)\n    client = TestClient(light=True)\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"create . --name=zlib --version=0.1\")\n    client.run(\"create . --name=zlib --version=0.2\")\n\n    client.save({\"conanfile.py\": GenConanfile().with_tool_requirement(\"zlib/0.1\",\n                                                                      visible=True)})\n    client.run(\"create . --name=cmake --version=0.1\")\n\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"create . --name=cmake --version=0.2\")\n\n    app_conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    class Pkg(ConanFile):\n\n        def requirements(self):\n            self.requires(\"zlib/0.2\")\n            self.requires(\"cmake/0.1\", headers=False, libs=False, visible=False, build=True, run=False)\n            self.requires(\"cmake/0.2\", headers=False, libs=False, visible=False, build=True, run=False)\n\n        def generate(self):\n           {}\n        \"\"\".format(generates_line))\n    client.save({\"conanfile.py\": app_conanfile})\n    client.run(\"create . --name=app --version=1.0\", assert_error=assert_error)\n    assert output_text in client.out\n\n\ndef test_invisible_not_colliding_test_requires():\n    \"\"\"\n    The test_requires are private, so the app can't see them, only the foo and bar\n    :return:\n    \"\"\"\n    # app ---> foo/0.1 --test_require--> gtest/0.1\n    #  \\  ---> bar/0.1 --test_require--> gtest/0.2\n    client = TestClient(light=True)\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"create . --name=gtest --version=0.1\")\n    client.run(\"create . --name=gtest --version=0.2\")\n\n    client.save({\"conanfile.py\": GenConanfile().with_test_requires(\"gtest/0.1\")})\n    client.run(\"create . --name=foo --version=0.1\")\n\n    client.save({\"conanfile.py\": GenConanfile().with_test_requires(\"gtest/0.2\")})\n    client.run(\"create . --name=bar --version=0.1\")\n\n    app_conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    class Pkg(ConanFile):\n\n        def requirements(self):\n            self.requires(\"foo/0.1\")\n            self.requires(\"bar/0.1\")\n\n        def generate(self):\n            print(self.dependencies.get(\"gtest\"))\n        \"\"\")\n    client.save({\"conanfile.py\": app_conanfile})\n    client.run(\"create . --name=app --version=1.0\", assert_error=True)\n    assert \"'gtest' not found in the dependency set\" in client.out\n\n\ndef test_dependencies_visit_build_requires_profile():\n    \"\"\" At validate() time, in Conan 1.X, the build-requires are not available yet, because first\n    the binary package_id is computed, then the build-requires are resolved.\n    It is necessary to avoid in Conan 1.X the caching of the ConanFile.dependencies, because\n    at generate() time it will have all the graph info, including build-requires\n    \"\"\"\n    # https://github.com/conan-io/conan/issues/10304\n    client = TestClient(light=True)\n    client.save({\"conanfile.py\": GenConanfile(\"cmake\", \"0.1\")})\n    client.run(\"create .\")\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n\n            def validate(self):\n                self.output.info(\"VALIDATE DEPS: {}!!!\".format(len(self.dependencies.items())))\n\n            def generate(self):\n                for req, dep in self.dependencies.items():\n                    self.output.info(\"GENERATE REQUIRE: {}!!!\".format(dep.ref))\n                dep = self.dependencies.build[\"cmake\"]\n                self.output.info(\"GENERATE CMAKE: {}!!!\".format(dep.ref))\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile,\n                 \"profile\": \"[tool_requires]\\ncmake/0.1\"})\n    client.run(\"install . -pr:b=default -pr:h=profile --build='*'\")  # Use 2 contexts\n\n    # Validate time, build-requires available\n    assert \"conanfile.py: VALIDATE DEPS: 1!!!\" in client.out\n    # generate time, build-requires already available\n    assert \"conanfile.py: GENERATE REQUIRE: cmake/0.1!!!\" in client.out\n    assert \"conanfile.py: GENERATE CMAKE: cmake/0.1!!!\" in client.out\n\n\ndef test_dependencies_package_type():\n    c = TestClient(light=True)\n    c.save({\"conanfile.py\": GenConanfile(\"lib\", \"0.1\").with_package_type(\"static-library\")})\n    c.run(\"create .\")\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            requires = \"lib/0.1\"\n            def generate(self):\n                is_app = self.dependencies[\"lib\"].package_type == \"static-library\"\n                self.output.info(f\"APP: {is_app}!!\")\n                assert is_app\n                self.dependencies[\"lib\"].package_type == \"not-exist-type\"\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"install .\", assert_error=True)\n    assert \"APP: True!!\" in c.out\n    assert \"conanfile.py: Error in generate() method, line 9\" in c.out\n    assert \"ValueError: 'not-exist-type' is not a valid PackageType\" in c.out\n\n\ndef test_dependency_interface():\n    \"\"\"\n    Quick test for the ConanFileInterface exposed\n    \"\"\"\n    c = TestClient(light=True)\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"dep\"\n            version = \"1.0\"\n            homepage = \"myhome\"\n            url = \"myurl\"\n            license = \"MIT\"\n        \"\"\")\n    user = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class User(ConanFile):\n            requires = \"dep/1.0\"\n            def generate(self):\n                dep = self.dependencies[\"dep\"]\n                self.output.info(\"HOME: {}\".format(dep.homepage))\n                self.output.info(\"URL: {}\".format(dep.url))\n                self.output.info(\"LICENSE: {}\".format(dep.license))\n                self.output.info(\"RECIPE FOLDER: {}\".format(dep.recipe_folder))\n                self.output.info(\"CONANDATA: {}\".format(dep.conan_data))\n                self.output.info(\"RECIPE: {}\".format(dep.recipe))\n\n            \"\"\")\n    c.save({\"dep/conanfile.py\": conanfile,\n            \"dep/conandata.yml\": \"\",\n            \"user/conanfile.py\": user})\n    c.run(\"create dep\")\n    c.run(\"install user\")\n    assert \"conanfile.py: HOME: myhome\" in c.out\n    assert \"conanfile.py: URL: myurl\" in c.out\n    assert \"conanfile.py: LICENSE: MIT\" in c.out\n    assert \"conanfile.py: RECIPE FOLDER:\" in c.out\n    assert \"conanfile.py: CONANDATA: {}\" in c.out\n    assert \"conanfile.py: RECIPE: Cache\" in c.out\n\n\ndef test_dependency_interface_validate():\n    \"\"\"\n    In the validate() method, there is no access to dep.package_folder, because the packages are\n    not there. validate() operates at the graph level, without binaries, before they are installed,\n    and we want to keep it that way\n    https://github.com/conan-io/conan/issues/11959\n    \"\"\"\n    c = TestClient(light=True)\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"dep\"\n            version = \"1.0\"\n            homepage = \"myhome\"\n        \"\"\")\n    user = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        class User(ConanFile):\n            requires = \"dep/1.0\"\n            def validate(self):\n                dep = self.dependencies[\"dep\"]\n                self.output.info(\"HOME: {}\".format(dep.homepage))\n                self.output.info(\"PKG FOLDER: {}\".format(dep.package_folder is None))\n            \"\"\")\n    c.save({\"dep/conanfile.py\": conanfile,\n            \"user/conanfile.py\": user})\n    c.run(\"create dep\")\n    c.run(\"install user\")\n    assert \"conanfile.py: HOME: myhome\" in c.out\n    assert \"conanfile.py: PKG FOLDER: True\" in c.out\n\n\ndef test_validate_visibility():\n    # https://github.com/conan-io/conan/issues/12027\n    c = TestClient(light=True)\n    t1 = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class t1Conan(ConanFile):\n            name = \"t1\"\n            version = \"0.1\"\n            package_type = \"static-library\"\n\n            def package_info(self):\n                self.cpp_info.libs = [\"mylib\"]\n        \"\"\")\n    t2 = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class t2Conan(ConanFile):\n            name = \"t2\"\n            version = \"0.1\"\n            requires = \"t1/0.1\"\n            package_type = \"shared-library\"\n\n            def validate(self):\n                self.output.info(\"VALID: {}\".format(self.dependencies[\"t1\"]))\n        \"\"\")\n    t3 = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class t3Conan(ConanFile):\n            name = \"t3\"\n            version = \"0.1\"\n            requires = \"t2/0.1\"\n            package_type = \"application\"\n\n            def validate(self):\n                self.output.info(\"VALID: {}\".format(self.dependencies[\"t1\"]))\n                self.output.info(\"VALID: {}\".format(self.dependencies[\"t2\"]))\n\n            def generate(self):\n                self.output.info(\"GENERATE: {}\".format(self.dependencies[\"t1\"]))\n                self.output.info(\"GENERATE: {}\".format(self.dependencies[\"t2\"]))\n        \"\"\")\n\n    c.save({\"t1/conanfile.py\": t1,\n            \"t2/conanfile.py\": t2,\n            \"t3/conanfile.py\": t3})\n    c.run(\"create t1\")\n    c.run(\"create t2\")\n    c.run(\"install t3\")\n    assert \"t2/0.1: VALID: t1/0.1\" in c.out\n    assert \"conanfile.py (t3/0.1): VALID: t1/0.1\" in c.out\n    assert \"conanfile.py (t3/0.1): VALID: t2/0.1\" in c.out\n    assert \"conanfile.py (t3/0.1): GENERATE: t1/0.1\" in c.out\n    assert \"conanfile.py (t3/0.1): GENERATE: t2/0.1\" in c.out\n    c.run(\"create t3\")\n    assert \"t2/0.1: VALID: t1/0.1\" in c.out\n    assert \"t3/0.1: VALID: t1/0.1\" in c.out\n    assert \"t3/0.1: VALID: t2/0.1\" in c.out\n    assert \"t3/0.1: GENERATE: t1/0.1\" in c.out\n    assert \"t3/0.1: GENERATE: t2/0.1\" in c.out\n"
  },
  {
    "path": "test/integration/graph/test_divergent_cppstd_build_host.py",
    "content": "import json\nimport textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_divergent_cppstd_build_host():\n\n    c = TestClient()\n\n    conanfile = textwrap.dedent(\"\"\"\n        [requires]\n        waterfall/1.0\n        [tool_requires]\n        rainbow/1.0\n        \"\"\")\n\n    c.save({\"waterfall/conanfile.py\": GenConanfile(\"waterfall\", \"1.0\").with_settings(\"compiler\"),\n            \"rainbow/conanfile.py\": GenConanfile(\"rainbow\", \"1.0\").with_settings(\"compiler\")\n                                                .with_requires(\"waterfall/1.0\"),\n            \"conanfile.txt\": conanfile})\n\n    c.run(\"export waterfall\")\n    c.run(\"export rainbow\")\n    c.run(f\"install . --build=missing -s compiler.cppstd=14 -s:b compiler.cppstd=17 --format=json\",\n          redirect_stdout=\"graph.json\")\n    graph = json.loads(c.load(\"graph.json\"))\n\n    # waterfall is twice in the graph: as a direct host dependency, and an indirect build dependency\n    assert graph['graph']['nodes']['1']['ref'] == \"waterfall/1.0#821e924dcef2f185dd651e6d434f9f95\"\n    assert graph['graph']['nodes']['1']['context'] == \"host\"\n\n    assert graph['graph']['nodes']['3']['ref'] == \"waterfall/1.0#821e924dcef2f185dd651e6d434f9f95\"\n    assert graph['graph']['nodes']['3']['context'] == \"build\"\n\n    # is this the right behaviour?\n    # without the compatibility plugin, we would require two different package_id in the same graph,\n    # but because of compatibility plugin, Conan graph uses a \"compatible\" package_id in the\n    # build context rather than the exact one\n    assert graph['graph']['nodes']['1']['package_id'] == graph['graph']['nodes']['3']['package_id']\n\n"
  },
  {
    "path": "test/integration/graph/test_platform_requires.py",
    "content": "import json\nimport os\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestPlatformRequires:\n    @pytest.mark.parametrize(\"revision\", [\"\", \"#myrev\"])\n    def test_platform_requires(self, revision):\n        client = TestClient(light=True)\n        client.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_requires(\"dep/1.0\"),\n                     \"profile\": f\"[platform_requires]\\ndep/1.0{revision}\"})\n        client.run(\"create . -pr=profile\")\n        assert f\"dep/1.0{revision or '#platform'} - Platform\" in client.out\n\n    def test_platform_requires_non_matching(self):\n        \"\"\" if what is specified in [platform_requires] doesn't match what the recipe requires, then\n        the platform_requires will not be used, and the recipe will use its declared version\n        \"\"\"\n        client = TestClient(light=True)\n        client.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"1.0\"),\n                     \"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_requires(\"dep/1.0\"),\n                     \"profile\": \"[platform_requires]\\ndep/1.1\"})\n        client.run(\"create dep\")\n        client.run(\"create . -pr=profile\")\n        assert \"dep/1.0#6a99f55e933fb6feeb96df134c33af44 - Cache\" in client.out\n\n    @pytest.mark.parametrize(\"revision\", [\"\", \"#myrev\"])\n    def test_platform_requires_range(self, revision):\n        client = TestClient(light=True)\n        client.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_requires(\"dep/[>=1.0]\"),\n                     \"profile\": f\"[platform_requires]\\ndep/1.1{revision}\"})\n        client.run(\"create . -pr=profile\")\n        assert f\"dep/1.1{revision or '#platform'} - Platform\" in client.out\n\n    def test_platform_requires_range_non_matching(self):\n        \"\"\" if what is specified in [platform_requires] doesn't match what the recipe requires, then\n        the platform_requires will not be used, and the recipe will use its declared version\n        \"\"\"\n        client = TestClient(light=True)\n        client.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"1.1\"),\n                     \"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_requires(\"dep/[>=1.0]\"),\n                     \"profile\": \"[platform_requires]\\ndep/0.1\"})\n        client.run(\"create dep\")\n        client.run(\"create . -pr=profile\")\n        assert \"dep/1.1#af79f1e3973b7d174e7465038c3f5f36 - Cache\" in client.out\n\n    def test_platform_requires_no_host(self):\n        \"\"\"\n        platform_requires must not affect tool-requires\n        \"\"\"\n        client = TestClient(light=True)\n        client.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_tool_requires(\"dep/1.0\"),\n                     \"profile\": \"[platform_requires]\\ndep/1.0\"})\n        client.run(\"create . -pr=profile\", assert_error=True)\n        assert \"ERROR: Package 'dep/1.0' not resolved: No remote defined\" in client.out\n\n    def test_platform_requires_build_context(self):\n        \"\"\"\n        platform_requires must work in the build context too\n        \"\"\"\n        client = TestClient(light=True)\n        client.save({\"tool/conanfile.py\": GenConanfile(\"tool\", \"1.0\").with_requires(\"dep/1.0\"),\n                     \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_tool_requires(\"tool/1.0\"),\n                     \"profile\": \"[settings]\\nos=Linux\\n[platform_requires]\\ndep/1.0\"})\n        client.run(\"create tool -pr:b=profile --build-require\")\n        assert \"dep/1.0#platform - Platform\" in client.out\n        client.run(\"create pkg -pr:b=profile\")\n        assert \"dep/1.0#platform - Platform\" in client.out\n\n    def test_graph_info_platform_requires_range(self):\n        \"\"\"\n        graph info doesn't crash\n        \"\"\"\n        client = TestClient(light=True)\n        client.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_requires(\"dep/[>=1.0]\"),\n                     \"profile\": \"[platform_requires]\\ndep/1.1\"})\n        client.run(\"graph info . -pr=profile\")\n        assert \"dep/1.1#platform - Platform\" in client.out\n\n    def test_consumer_resolved_version(self):\n        client = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                requires = \"dep/[>=1.0]\"\n\n                def generate(self):\n                    for r, _ in self.dependencies.items():\n                        self.output.info(f\"DEPENDENCY {r.ref}\")\n                \"\"\")\n        client.save({\"conanfile.py\": conanfile,\n                     \"profile\": \"[platform_requires]\\ndep/1.1\"})\n        client.run(\"install . -pr=profile\")\n        assert \"dep/1.1#platform - Platform\" in client.out\n        assert \"conanfile.py: DEPENDENCY dep/1.1\" in client.out\n\n    @pytest.mark.parametrize(\"revision\", [\"\", \"#rev1\"])\n    def test_consumer_resolved_revision(self, revision):\n        client = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                requires = \"dep/1.1\"\n\n                def generate(self):\n                    for r, _ in self.dependencies.items():\n                        self.output.info(f\"DEPENDENCY {repr(r.ref)}\")\n                \"\"\")\n        client.save({\"conanfile.py\": conanfile,\n                     \"profile\": f\"[platform_requires]\\ndep/1.1{revision}\"})\n        client.run(\"install . -pr=profile\")\n        assert \"dep/1.1 - Platform\" in client.out\n        assert f\"conanfile.py: DEPENDENCY dep/1.1{revision or '#platform'}\" in client.out\n\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n               requires = \"dep/1.1#rev1\"\n\n               def generate(self):\n                   for r, _ in self.dependencies.items():\n                       self.output.info(f\"DEPENDENCY {repr(r.ref)}\")\n               \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"install . -pr=profile\")\n        assert \"dep/1.1 - Platform\" in client.out\n        assert f\"conanfile.py: DEPENDENCY dep/1.1{revision or '#platform'}\" in client.out\n\n    def test_consumer_unresolved_revision(self):\n        \"\"\" if a recipe specifies an exact revision and so does the profile\n        and it doesn't match, it is an error\n        \"\"\"\n        client = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                requires = \"dep/1.1#rev2\"\n\n                def generate(self):\n                    for r, _ in self.dependencies.items():\n                        self.output.info(f\"DEPENDENCY {repr(r.ref)}\")\n                \"\"\")\n        client.save({\"conanfile.py\": conanfile,\n                     \"profile\": \"[platform_requires]\\ndep/1.1#rev1\"})\n        client.run(\"install . -pr=profile\", assert_error=True)\n        assert \"ERROR: Package 'dep/1.1' not resolved\" in client.out\n\n    def test_platform_requires_with_options(self):\n        \"\"\" https://github.com/conan-io/conan/issues/15685\n        \"\"\"\n        client = TestClient(light=True)\n        client.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_requires(\"dep/1.0\"),\n                     \"profile\": \"[platform_requires]\\ndep/1.0\"})\n        client.run(\"create . -pr=profile -o *:myoption=True\")\n        assert \"dep/1.0 - Platform\" in client.out\n\n        conanfile = GenConanfile(\"pkg\", \"1.0\").with_requirement(\"dep/1.0\",\n                                                                options={\"dep/1.0:myoption\": True})\n        client.save({\"conanfile.py\": conanfile,\n                     \"profile\": \"[platform_requires]\\ndep/1.0\"})\n        client.run(\"create . -pr=profile\")  # This crashed before for non-existing options\n        assert \"dep/1.0 - Platform\" in client.out\n\n\nclass TestPlatformTestRequires:\n    def test_platform_requires(self):\n        client = TestClient(light=True)\n        client.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_test_requires(\"dep/1.0\"),\n                     \"profile\": \"[platform_requires]\\ndep/1.0\"})\n        client.run(\"create . -pr=profile\")\n        assert \"dep/1.0 - Platform\" in client.out\n\n\nclass TestPlatformRequiresLock:\n\n    @pytest.mark.parametrize(\"revision\", [\"\", \"#rev1\"])\n    def test_platform_requires_range(self, revision):\n        c = TestClient(light=True)\n        c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_requires(\"dep/[>=1.0]\"),\n                \"profile\": f\"[platform_requires]\\ndep/1.1{revision}\"})\n        c.run(\"lock create . -pr=profile\")\n        assert \"dep/1.1 - Platform\" in c.out\n        lock = json.loads(c.load(\"conan.lock\"))\n        assert lock[\"requires\"] == [f\"dep/1.1{revision or '#platform'}\"]\n\n        c.run(\"install .\", assert_error=True)\n        assert \"Package 'dep/1.1' not resolved: No remote defined\" in c.out\n        c.run(\"install . -pr=profile\")\n        assert f\"dep/1.1{revision or '#platform'} - Platform\" in c.out\n\n        # if the profile points to another version it is an error, not in the lockfile\n        c.save({\"profile\": f\"[platform_requires]\\ndep/1.2{revision}\"})\n        c.run(\"install . -pr=profile\", assert_error=True)\n        assert f\"ERROR: Requirement 'dep/1.2{revision or '#platform'}' not in lockfile\" in c.out\n\n    @pytest.mark.parametrize(\"platform_rev\", [None, \"myrev\"])\n    @pytest.mark.parametrize(\"is_tool_platform\", [True, False])\n    def test_platform_requires_lockfile(self, platform_rev, is_tool_platform):\n        tc = TestClient(light=True)\n        profile_rev = f\"#{platform_rev}\" if platform_rev else \"\"\n        expected_rev = platform_rev if platform_rev else \"platform\"\n        conanfile = GenConanfile(\"pkg\", \"1.0\")\n        if is_tool_platform:\n            conanfile = conanfile.with_tool_requires(\"dep/1.0\")\n        else:\n            conanfile = conanfile.with_requirement(\"dep/1.0\")\n        substitution = \"platform_tool_requires\" if is_tool_platform else \"platform_requires\"\n        tc.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"1.0\"),\n                 \"conanfile.py\": conanfile,\n                 \"profile\": f\"[{substitution}]\\ndep/1.0{profile_rev}\"})\n        tc.run(\"create dep\")\n        created_dep_ref = tc.created_layout().reference.ref\n\n        # The platform revision is correctly captured in the lockfile\n        tc.run(\"lock create --lockfile-out=platform.lock -pr=profile\")\n        assert f\"dep/1.0#{expected_rev}\" in tc.load(\"platform.lock\")\n        tc.run(\"lock create --lockfile-out=real.lock\")\n        assert str(created_dep_ref) in tc.load(\"real.lock\")\n\n        # Not using lockfiles when expanding the graph works as expected\n        tc.run(\"install\")\n        tc.assert_listed_require({str(created_dep_ref): \"Cache\"}, build=is_tool_platform)\n        tc.run(\"install -pr=profile\")\n        tc.assert_listed_require({f\"dep/1.0#{expected_rev}\": \"Platform\"}, build=is_tool_platform)\n\n        # And also with lockfiles, the platform revision is correctly captured in the lockfile\n        tc.run(\"install --lockfile=real.lock\")\n        tc.assert_listed_require({str(created_dep_ref): \"Cache\"}, build=is_tool_platform)\n        tc.run(\"install -pr=profile --lockfile=platform.lock\")\n        tc.assert_listed_require({f\"dep/1.0#{expected_rev}\": \"Platform\"}, build=is_tool_platform)\n\n        tc.run(\"install --lockfile=platform.lock\", assert_error=True)\n        assert \"Package 'dep/1.0' not resolved\" in tc.out\n        tc.run(\"install -pr=profile --lockfile=real.lock\", assert_error=True)\n        assert f\"Requirement 'dep/1.0#{expected_rev}' not in lockfile\" in tc.out\n\n        # Now, what happens if we just merge both lockfiles so we can switch on the fly?\n        # Both can coexist because they have different revisions.\n        # The platform requires does not have a timestamp, so it's never selected outside platform matches\n        tc.run(\"lock merge --lockfile=real.lock --lockfile=platform.lock --lockfile-out=merged.lock\")\n        tc.run(\"install --lockfile=merged.lock\")\n        tc.assert_listed_require({str(created_dep_ref): \"Cache\"}, build=is_tool_platform)\n        tc.run(\"install -pr=profile --lockfile=merged.lock\")\n        tc.assert_listed_require({f\"dep/1.0#{expected_rev}\": \"Platform\"}, build=is_tool_platform)\n\n        # And now, having a lockfile which just has name/version\n        requires = \"build-requires\" if is_tool_platform else \"requires\"\n        tc.run(f\"lock add --{requires}=dep/1.0 --lockfile-out=simple.lock\")\n        tc.run(\"install -pr=profile --lockfile=simple.lock\")\n        tc.assert_listed_require({f\"dep/1.0#{expected_rev}\": \"Platform\"}, build=is_tool_platform)\n\n\nclass TestGenerators:\n    def test_platform_requires_range(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                settings = \"build_type\"\n                requires = \"dep/[>=1.0]\"\n                generators = \"CMakeDeps\", # \"PkgConfigDeps\"\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile,\n                     \"profile\": \"[platform_requires]\\ndep/1.1\"})\n        client.run(\"install . -pr=profile\")\n        assert \"dep/1.1 - Platform\" in client.out\n        assert not os.path.exists(os.path.join(client.current_folder, \"dep-config.cmake\"))\n        assert not os.path.exists(os.path.join(client.current_folder, \"dep.pc\"))\n\n\nclass TestPackageID:\n    \"\"\" if a consumer depends on recipe revision or package_id what happens\n    \"\"\"\n\n    @pytest.mark.parametrize(\"package_id_mode\", [\"recipe_revision_mode\", \"full_package_mode\"])\n    def test_package_id_modes(self, package_id_mode):\n        \"\"\" this test validates that the computation of the downstream consumers package_id\n        doesn't break even if it depends on fields not existing in upstream platform_requires, like package_id\n        \"\"\"\n        client = TestClient(light=True)\n        client.save_home({\"global.conf\": f\"core.package_id:default_unknown_mode={package_id_mode}\"})\n        client.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_requires(\"dep/1.0\"),\n                     \"profile\": \"[platform_requires]\\ndep/1.0\"})\n        client.run(\"create . -pr=profile\")\n        assert \"dep/1.0#platform - Platform\" in client.out\n\n    def test_package_id_explicit_revision(self):\n        \"\"\"\n        Changing the platform_requires revision affects consumers if package_revision_mode=recipe_revision\n        \"\"\"\n        client = TestClient(light=True)\n        client.save_home({\"global.conf\":\n                          \"core.package_id:default_unknown_mode=recipe_revision_mode\"})\n        client.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_requires(\"dep/1.0\"),\n                     \"profile\": \"[platform_requires]\\ndep/1.0#r1\",\n                     \"profile2\": \"[platform_requires]\\ndep/1.0#r2\"})\n        client.run(\"create . -pr=profile\")\n        assert \"dep/1.0#r1 - Platform\" in client.out\n        assert \"pkg/1.0#7ed9bbd2a7c3c4381438c163c93a9f21:\" \\\n               \"d9d32dd13cfc9734becc01287570721cd048ba19 - Build\" in client.out\n\n        client.run(\"create . -pr=profile2\")\n        # pkg gets a new package_id because it is a different revision\n        assert \"dep/1.0#r2 - Platform\" in client.out\n        assert \"pkg/1.0#7ed9bbd2a7c3c4381438c163c93a9f21:\" \\\n               \"2f6bc9cf5015a7210181592d454f36687791a941 - Build\" in client.out\n\n    @pytest.mark.parametrize(\"revision\", [\"\", \"#myrev1\"])\n    def test_package_id_full_package_mode(self, revision):\n        \"\"\"\n        platform_requires do not have settings or package_id, so it is ignored\n        \"\"\"\n        client = TestClient()\n        client.save_home({\"global.conf\": \"core.package_id:default_unknown_mode=full_package_mode\"})\n        client.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_requires(\"dep/1.0\"),\n                     \"profile\": f\"[platform_requires]\\ndep/1.0{revision}\"})\n        client.run(\"create . -pr=profile -s os=Linux\")\n        assert f\"dep/1.0{revision or '#platform'} - Platform\" in client.out\n        assert \"pkg/1.0#7ed9bbd2a7c3c4381438c163c93a9f21:\" \\\n               \"f2cfe57716d0a3320019f058edcd728d3379ab32 - Build\" in client.out\n        # The default revision is not taken into account at all\n        assert f\"pkg/1.0: requires: dep/1.0:da39a3ee5e6b4b0d3255bfef95601890afd80709\" in client.out\n\n        client.run(\"create . -pr=profile -s os=Windows\")\n        # pkg gets exactly same package_id, changing the settings, do not affect plaform package-id\n        assert f\"dep/1.0{revision or '#platform'} - Platform\" in client.out\n        assert \"pkg/1.0#7ed9bbd2a7c3c4381438c163c93a9f21:\" \\\n               \"f2cfe57716d0a3320019f058edcd728d3379ab32 - Build\" in client.out\n\n    @pytest.mark.parametrize(\"revision, package_id\", [\n        (\"\", \"f2cfe57716d0a3320019f058edcd728d3379ab32\"),\n        (\"#myrev1\", \"bc8dc9f0bfb1e1d217f2ba7cccf545cdfdb382f6\")\n    ])\n    def test_package_id_full_mode(self, revision, package_id):\n        \"\"\"\n        platform_requires do not have settings or package_id, so it is ignored\n        \"\"\"\n        client = TestClient()\n        client.save_home({\"global.conf\": \"core.package_id:default_unknown_mode=full_mode\"})\n        client.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_requires(\"dep/1.0\"),\n                     \"profile\": f\"[platform_requires]\\ndep/1.0{revision}\"})\n        client.run(\"create . -pr=profile -s os=Linux\")\n        assert f\"dep/1.0{revision or '#platform'} - Platform\" in client.out\n        assert \"pkg/1.0#7ed9bbd2a7c3c4381438c163c93a9f21:\" \\\n               f\"{package_id} - Build\" in client.out\n        # The default revision is not taken into account for package id calculation,\n        # but if the user defines it, it is\n        assert f\"pkg/1.0: requires: dep/1.0{revision or ''}:da39a3ee5e6b4b0d3255bfef95601890afd80709\" in client.out\n\n        client.run(\"create . -pr=profile -s os=Windows\")\n        # pkg gets exactly same package_id, changing the settings, do not affect plaform package-id\n        assert f\"dep/1.0{revision or '#platform'} - Platform\" in client.out\n        assert \"pkg/1.0#7ed9bbd2a7c3c4381438c163c93a9f21:\" \\\n               f\"{package_id} - Build\" in client.out\n"
  },
  {
    "path": "test/integration/graph/test_pure_runtime_dep.py",
    "content": "from conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_pure_runtime_dep():\n    c = TestClient()\n    c.save({\"tooldep/conanfile.py\": GenConanfile(\"tooldep\", \"0.1\").with_package_file(\"bin/mysh\",\n                                                                                     \"myshared\")\n                                                                  .with_package_type(\"shared-library\"),\n            \"tool/conanfile.py\": GenConanfile(\"tool\", \"0.1\").with_requirement(\"tooldep/0.1\")\n                                                            .with_package_file(\"bin/myexe\", \"exe\"),\n            \"lib/conanfile.py\": GenConanfile(\"lib\", \"0.1\").with_requirement(\"tool/0.1\",\n                                                                            headers=False,\n                                                                            libs=False, run=True),\n            \"consumer/conanfile.py\": GenConanfile().with_settings(\"build_type\", \"os\",\n                                                                  \"compiler\", \"arch\")\n                                                   .with_requires(\"lib/0.1\")})\n\n    c.run(\"create tooldep\")\n    c.run(\"create tool\")\n    c.run(\"create lib\")\n    c.run(\"install consumer -g CMakeDeps\")\n"
  },
  {
    "path": "test/integration/graph/test_remote_resolution.py",
    "content": "import textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_build_requires_ranges():\n    # app -> pkga ----------> pkgb ------------> pkgc\n    #          \\-cmake/[*]     \\ -cmake/1.0        \\-cmake/[*]\n    # The resolution of cmake/[*] is invariant, it will always resolved to cmake/0.5, not\n    # one to cmake/0.5 and the next one to cmake/1.0 because in between there was an explicit\n    # dependency to cmake/1.0\n    client = TestClient(default_server_user=True)\n    client.save({\"conanfile.py\": GenConanfile()})\n\n    client.run(\"create . --name=cmake --version=0.5\")\n    client.run(\"create . --name=cmake --version=1.0\")\n    client.run(\"upload cmake/1.0* -c -r default\")\n    client.run(\"remove cmake/1.0* -c\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            {}\n            tool_requires = \"cmake/{}\"\n            def generate(self):\n                for r, d in self.dependencies.items():\n                    self.output.info(\"REQUIRE {{}}: {{}}\".format(r.ref, d))\n                dep = self.dependencies.build.get(\"cmake\")\n                self.output.info(\"CMAKEVER: {{}}!!\".format(dep.ref.version))\n            \"\"\")\n    client.save({\"pkgc/conanfile.py\": conanfile.format(\"\", \"[*]\"),\n                 \"pkgb/conanfile.py\": conanfile.format(\"requires = 'pkgc/1.0'\", \"1.0\"),\n                 \"pkga/conanfile.py\": conanfile.format(\"requires = 'pkgb/1.0'\", \"[*]\"),\n                 })\n    client.run(\"export pkgc --name=pkgc --version=1.0\")\n    client.run(\"export pkgb --name=pkgb --version=1.0\")\n    client.run(\"export pkga --name=pkga --version=1.0\")\n\n    client.run(\"install --requires=pkga/1.0@ --build=missing\")\n    assert \"pkgc/1.0: REQUIRE cmake/0.5: cmake/0.5\" in client.out\n    assert \"pkgc/1.0: CMAKEVER: 0.5!!\" in client.out\n    assert \"pkgb/1.0: REQUIRE cmake/1.0: cmake/1.0\" in client.out\n    assert \"pkgb/1.0: CMAKEVER: 1.0!!\" in client.out\n    assert \"pkga/1.0: REQUIRE cmake/0.5: cmake/0.5\" in client.out\n    assert \"pkga/1.0: CMAKEVER: 0.5!!\" in client.out\n"
  },
  {
    "path": "test/integration/graph/test_repackaging.py",
    "content": "import re\nimport textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_repackage():\n    # consumer -> repackager -> liba\n    #                  \\------> libb\n    client = TestClient(light=True)\n    client.save({\"conanfile.py\": GenConanfile().with_package_file(\"liba.txt\", \"HelloA!\")})\n    client.run(\"create . --name=liba --version=1.0\")\n    client.save({\"conanfile.py\": GenConanfile().with_package_file(\"libb.txt\", \"HelloB!\")})\n    client.run(\"create . --name=libb --version=1.0 \")\n\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import copy\n        class Pkg(ConanFile):\n            settings = \"os\"\n\n            def requirements(self):\n                self.requires(\"liba/1.0\", headers=True, libs=True, visible=False, run=False)\n                self.requires(\"libb/1.0\", headers=True, libs=True, visible=False, run=False)\n\n            def package(self):\n                for r, d in self.dependencies.items():\n                    copy(self, \"*\", src=d.package_folder,\n                         dst=os.path.join(self.package_folder, r.ref.name))\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=repackager --version=1.0\")\n\n    client.save({\"conanfile.py\": GenConanfile().with_requires(\"repackager/1.0\")}, clean_first=True)\n    client.run(\"install .\")\n    assert re.search(r\"Skipped binaries(\\s*)liba/1.0, libb/1.0\", client.out)\n    assert \"repackager/1.0: Already installed!\" in client.out\n\n\ndef test_repackage_library_self():\n    c = TestClient()\n    c.save({\"conanfile.py\": GenConanfile(\"liba\", \"1.0\").with_package_file(\"a.txt\", \"A1.0!\")})\n    c.run(\"create .\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import copy\n        class Pkg(ConanFile):\n            name = \"liba\"\n            version = \"2.0\"\n\n            def requirements(self):\n                self.requires(\"liba/1.0\", visible=False)\n\n            def package(self):\n                for _, dep in self.dependencies.items():\n                    copy(self, \"*\", src=dep.package_folder, dst=self.package_folder)\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"create .\")\n\n    c.run(\"install --requires=liba/2.0 --deployer=full_deploy\")\n    assert re.search(r\"Skipped binaries(\\s*)liba/1.0\", c.out)\n    assert \"liba/2.0: Already installed!\" in c.out\n    assert c.load(\"full_deploy/host/liba/2.0/a.txt\") == \"A1.0!\"\n\n\ndef test_repackage_library_self_infinite_loop():\n    c = TestClient()\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"liba\"\n            version = \"1.0\"\n\n            def requirements(self):\n                self.requires(\"liba/1.0\", visible=False, headers=False, libs=False, run=False)\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"create .\", assert_error=True)\n    assert \"There is a cycle/loop in the graph\" in c.out\n\n\ndef test_repackage_library_self_multiple():\n    c = TestClient()\n    c.save({\"1/conanfile.py\": GenConanfile(\"liba\", \"1.0\").with_package_file(\"a1.txt\", \"A1.0!\"),\n            \"2/conanfile.py\": GenConanfile(\"liba\", \"2.0\").with_package_file(\"a2.txt\", \"A2.0!\")})\n    c.run(\"create 1\")\n    c.run(\"create 2\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import copy\n        class Pkg(ConanFile):\n            name = \"liba\"\n            version = \"3.0\"\n\n            def requirements(self):\n                # To avoid conflict among liba versions\n                self.requires(\"liba/1.0\", headers=False, libs=False, visible=False)\n                self.requires(\"liba/2.0\", visible=False)\n\n            def package(self):\n                for _, dep in self.dependencies.items():\n                    copy(self, \"*\", src=dep.package_folder, dst=self.package_folder)\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"create .\")\n\n    c.run(\"install --requires=liba/3.0 --deployer=full_deploy\")\n    assert re.search(r\"Skipped binaries(\\s*)liba/1.0, liba/2.0\", c.out)\n    assert \"liba/3.0: Already installed!\" in c.out\n    assert c.load(\"full_deploy/host/liba/3.0/a1.txt\") == \"A1.0!\"\n    assert c.load(\"full_deploy/host/liba/3.0/a2.txt\") == \"A2.0!\"\n\n\ndef test_repackage_library_self_transitive():\n    c = TestClient()\n    c.save({\"a/conanfile.py\": GenConanfile(\"liba\", \"1.0\").with_package_file(\"a1.txt\", \"A1.0!\"),\n            \"b/conanfile.py\": GenConanfile(\"libb\", \"1.0\").with_requires(\"liba/1.0\")})\n    c.run(\"create a\")\n    c.run(\"create b\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import copy\n        class Pkg(ConanFile):\n            name = \"liba\"\n            version = \"3.0\"\n\n            def requirements(self):\n                # libs=True, otherwise transitive liba is skipped\n                self.requires(\"libb/1.0\", headers=False, libs=True, visible=False, run=False)\n\n            def package(self):\n                for _, dep in self.dependencies.items():\n                    copy(self, \"*\", src=dep.package_folder, dst=self.package_folder)\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"create .\")\n\n    c.run(\"install --requires=liba/3.0 --deployer=full_deploy\")\n    assert re.search(r\"Skipped binaries(\\s*)liba/1.0, libb/1.0\", c.out)\n    assert \"liba/3.0: Already installed!\" in c.out\n    assert c.load(\"full_deploy/host/liba/3.0/a1.txt\") == \"A1.0!\"\n"
  },
  {
    "path": "test/integration/graph/test_replace_requires.py",
    "content": "import json\nimport textwrap\n\nimport pytest\n\nfrom conan.api.model import RecipeReference\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.parametrize(\"require, pattern, alternative, pkg\", [\n    # PATTERN VERSIONS\n    # override all dependencies to \"dep\" to a specific version,user and channel)\n    # TODO: This is a version override, is this really wanted?\n    (\"dep/1.3\", \"dep/*\", \"dep/1.1\", \"dep/1.1\"),\n    (\"dep/[>=1.0 <2]\", \"dep/*\", \"dep/1.1\", \"dep/1.1\"),\n    # override all dependencies to \"dep\" to the same version with other user, remove channel)\n    (\"dep/1.3\", \"dep/*\", \"dep/*@system\", \"dep/1.3@system\"),\n    (\"dep/[>=1.0 <2]\", \"dep/*\", \"dep/*@system\", \"dep/1.1@system\"),\n    # override all dependencies to \"dep\" to the same version with other user, same channel)\n    (\"dep/1.3@comp/stable\", \"dep/*@*/*\", \"dep/*@system/*\", \"dep/1.3@system/stable\"),\n    (\"dep/[>=1.0 <2]@comp/stable\", \"dep/*@*/*\", \"dep/*@system/*\", \"dep/1.1@system/stable\"),\n    # EXACT VERSIONS\n    # replace exact dependency version for one in the system\n    (\"dep/1.1\", \"dep/1.1\", \"dep/1.1@system\", \"dep/1.1@system\"),\n    (\"dep/[>=1.0 <2]\", \"dep/1.1\", \"dep/1.1@system\", \"dep/1.1@system\"),\n    (\"dep/[>=1.0 <2]@comp\", \"dep/1.1@*\", \"dep/1.1@*/stable\", \"dep/1.1@comp/stable\"),\n    (\"dep/1.1@comp\", \"dep/1.1@*\", \"dep/1.1@*/stable\", \"dep/1.1@comp/stable\"),\n    # PACKAGE ALTERNATIVES (zlib->zlibng)\n    (\"dep/1.0\", \"dep/*\", \"depng/*\", \"depng/1.0\"),\n    (\"dep/[>=1.0 <2]\", \"dep/*\", \"depng/*\", \"depng/1.1\"),\n    (\"dep/[>=1.0 <2]\", \"dep/1.1\", \"depng/1.2\", \"depng/1.2\"),\n    # NON MATCHING\n    (\"dep/1.3\", \"dep/1.1\", \"dep/1.1@system\", \"dep/1.3\"),\n    (\"dep/1.3\", \"dep/*@comp\", \"dep/*@system\", \"dep/1.3\"),\n    (\"dep/[>=1.0 <2]\", \"dep/2.1\", \"dep/2.1@system\", \"dep/1.1\"),\n    # PATTERN - PATTERN REPLACE\n    (\"dep/[>=1.3 <2]\", \"dep/*\", \"dep/[>=1.0 <1.9]\", \"dep/1.1\"),\n    # DIRECT REPLACE OF PINNED VERSIONS\n    (\"dep/1.3\", \"dep/1.3\", \"dep/1.5\", \"dep/1.5\"),\n])\n@pytest.mark.parametrize(\"tool_require\", [False, True])\nclass TestReplaceRequires:\n    def test_alternative(self, tool_require, require, pattern, alternative, pkg):\n        c = TestClient(light=True)\n        conanfile = GenConanfile().with_tool_requires(require) if tool_require else \\\n            GenConanfile().with_requires(require)\n        profile_tag = \"replace_requires\" if not tool_require else \"replace_tool_requires\"\n        c.save({\"dep/conanfile.py\": GenConanfile(),\n                \"pkg/conanfile.py\": conanfile,\n                \"profile\": f\"[{profile_tag}]\\n{pattern}: {alternative}\"})\n        ref = RecipeReference.loads(pkg)\n        user = f\"--user={ref.user}\" if ref.user else \"\"\n        channel = f\"--channel={ref.channel}\" if ref.channel else \"\"\n        c.run(f\"create dep --name={ref.name} --version={ref.version} {user} {channel}\")\n        rrev = c.exported_recipe_revision()\n        c.run(\"profile show -pr=profile\")\n        assert profile_tag in c.out\n        c.run(\"install pkg -pr=profile\")\n        assert profile_tag in c.out\n        c.assert_listed_require({f\"{pkg}#{rrev}\": \"Cache\"}, build=tool_require)\n\n        # Check lockfile\n        c.run(\"lock create pkg -pr=profile\")\n        lock = c.load(\"pkg/conan.lock\")\n        assert f\"{pkg}#{rrev}\" in lock\n\n        # c.run(\"create dep2 --version=1.2\")\n        # with lockfile\n        c.run(\"install pkg -pr=profile\")\n        c.assert_listed_require({f\"{pkg}#{rrev}\": \"Cache\"}, build=tool_require)\n\n    def test_diamond(self, tool_require, require, pattern, alternative, pkg):\n        c = TestClient(light=True)\n        conanfile = GenConanfile().with_tool_requires(require) if tool_require else \\\n            GenConanfile().with_requires(require)\n        profile_tag = \"replace_requires\" if not tool_require else \"replace_tool_requires\"\n\n        c.save({\"dep/conanfile.py\": GenConanfile(),\n                \"libb/conanfile.py\": conanfile,\n                \"libc/conanfile.py\": conanfile,\n                \"app/conanfile.py\": GenConanfile().with_requires(\"libb/0.1\", \"libc/0.1\"),\n                \"profile\": f\"[{profile_tag}]\\n{pattern}: {alternative}\"})\n        ref = RecipeReference.loads(pkg)\n        user = f\"--user={ref.user}\" if ref.user else \"\"\n        channel = f\"--channel={ref.channel}\" if ref.channel else \"\"\n        c.run(f\"create dep --name={ref.name} --version={ref.version} {user} {channel}\")\n        rrev = c.exported_recipe_revision()\n\n        c.run(\"export libb --name=libb --version=0.1\")\n        c.run(\"export libc --name=libc --version=0.1\")\n\n        c.run(\"install app -pr=profile\", assert_error=True)\n        assert \"ERROR: Missing binary: libb/0.1\" in c.out\n        assert \"ERROR: Missing binary: libc/0.1\" in c.out\n\n        c.run(\"install app -pr=profile --build=missing\")\n        c.assert_listed_require({f\"{pkg}#{rrev}\": \"Cache\"}, build=tool_require)\n\n        # Check lockfile\n        c.run(\"lock create app -pr=profile\")\n        lock = c.load(\"app/conan.lock\")\n        assert f\"{pkg}#{rrev}\" in lock\n\n        # with lockfile\n        c.run(\"install app -pr=profile\")\n        c.assert_listed_require({f\"{pkg}#{rrev}\": \"Cache\"}, build=tool_require)\n\n\n@pytest.mark.parametrize(\"pattern, replace\", [\n    (\"pkg\", \"pkg/0.1\"),\n    (\"pkg/*\", \"pkg\"),\n    (\"pkg/*:pid1\", \"pkg/0.1\"),\n    (\"pkg/*:pid1\", \"pkg/0.1:pid2\"),\n    (\"pkg/*\", \"pkg/0.1:pid2\"),\n    (\":\", \"\"),\n    (\"pkg/version:pid\", \"\"),\n    (\"pkg/version:pid\", \":\")\n])\ndef test_replace_requires_errors(pattern, replace):\n    c = TestClient(light=True)\n    c.save({\"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\"),\n            \"app/conanfile.py\": GenConanfile().with_requires(\"pkg/0.2\"),\n            \"profile\": f\"[replace_requires]\\n{pattern}: {replace}\"})\n    c.run(\"create pkg\")\n    c.run(\"install app -pr=profile\", assert_error=True)\n    assert \"ERROR: Error reading 'profile' profile: Error in [replace_xxx]\" in c.out\n\n\ndef test_replace_requires_invalid_requires_errors():\n    \"\"\"\n    replacing for something incorrect not existing is not an error per-se, it is valid that\n    a recipe requires(\"pkg/2.*\"), and then it will fail because such package doesn't exist\n    \"\"\"\n    c = TestClient(light=True)\n    c.save({\"app/conanfile.py\": GenConanfile().with_requires(\"pkg/0.2\"),\n            \"profile\": f\"[replace_requires]\\npkg/0.2: pkg/2.*\"})\n    c.run(\"install app -pr=profile\", assert_error=True)\n    assert \"pkg/0.2: pkg/2.*\" in c.out  # The replacement happens\n    assert \"ERROR: Package 'pkg/2.*' not resolved\" in c.out\n\n\ndef test_replace_requires_json_format():\n    c = TestClient(light=True)\n    c.save({\"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.2\"),\n            \"app/conanfile.py\": GenConanfile().with_requires(\"pkg/0.1\"),\n            \"profile\": f\"[replace_requires]\\npkg/0.1: pkg/0.2\"})\n    c.run(\"create pkg\")\n    c.run(\"install app -pr=profile --format=json\")\n    assert \"pkg/0.1: pkg/0.2\" in c.out  # The replacement happens\n    graph = json.loads(c.stdout)\n    assert graph[\"graph\"][\"replaced_requires\"] == {\"pkg/0.1\": \"pkg/0.2\"}\n    assert graph[\"graph\"][\"nodes\"][\"0\"][\"dependencies\"][\"1\"][\"ref\"] == \"pkg/0.2\"\n    assert graph[\"graph\"][\"nodes\"][\"0\"][\"dependencies\"][\"1\"][\"require\"] == \"pkg/0.1\"\n\n\ndef test_replace_requires_test_requires():\n    c = TestClient(light=True)\n    c.save({\"gtest/conanfile.py\": GenConanfile(\"gtest\", \"0.2\"),\n            \"app/conanfile.py\": GenConanfile().with_test_requires(\"gtest/0.1\"),\n            \"profile\": f\"[replace_requires]\\ngtest/0.1: gtest/0.2\"})\n    c.run(\"create gtest\")\n    c.run(\"install app -pr=profile\")\n    assert \"gtest/0.1: gtest/0.2\" in c.out  # The replacement happens\n\n\n# We test even replacing by itself, not great, but shouldn't crash\n@pytest.mark.parametrize(\"name, version\", [(\"zlib\", \"0.1\"), (\"zlib\", \"0.2\"), (\"zlib-ng\", \"0.1\")])\ndef test_replace_requires_consumer_references(name, version):\n    c = TestClient()\n    # IMPORTANT: The replacement package must be target-compatible\n    dep = textwrap.dedent(f\"\"\"\n        from conan import ConanFile\n        class ZlibNG(ConanFile):\n            name = \"{name}\"\n            version = \"{version}\"\n            def package_info(self):\n                self.cpp_info.set_property(\"cmake_file_name\", \"ZLIB\")\n                self.cpp_info.set_property(\"cmake_target_name\", \"ZLIB::ZLIB\")\n        \"\"\")\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class App(ConanFile):\n            name = \"app\"\n            version = \"0.1\"\n            settings = \"build_type\"\n            requires = \"zlib/0.1\"\n            generators = \"CMakeDeps\"\n\n            def generate(self):\n                self.output.info(f\"DEP ZLIB generate: {self.dependencies['zlib'].ref.name}!\")\n            def build(self):\n                self.output.info(f\"DEP ZLIB build: {self.dependencies['zlib'].ref.name}!\")\n            def package_info(self):\n                self.output.info(f\"DEP ZLIB package_info: {self.dependencies['zlib'].ref.name}!\")\n                self.cpp_info.requires = [\"zlib::zlib\"]\n        \"\"\")\n    c.save({\"dep/conanfile.py\": dep,\n            \"app/conanfile.py\": conanfile,\n            \"profile\": f\"[replace_requires]\\nzlib/0.1: {name}/{version}\"})\n    c.run(\"create dep\")\n    c.run(\"build app -pr=profile\")\n    assert f\"zlib/0.1: {name}/{version}\" in c.out\n    assert f\"conanfile.py (app/0.1): DEP ZLIB generate: {name}!\" in c.out\n    assert f\"conanfile.py (app/0.1): DEP ZLIB build: {name}!\" in c.out\n    # Check generated CMake code. If the targets are NOT compatible, then the replacement\n    # Cannot happen\n    assert \"find_package(ZLIB)\" in c.out\n    assert \"target_link_libraries(... ZLIB::ZLIB)\" in c.out\n    cmake = c.load(\"app/ZLIBTargets.cmake\")\n    assert \"add_library(ZLIB::ZLIB INTERFACE IMPORTED)\" in cmake\n    c.run(\"create app -pr=profile\")\n    assert f\"zlib/0.1: {name}/{version}\" in c.out\n    assert f\"app/0.1: DEP ZLIB generate: {name}!\" in c.out\n    assert f\"app/0.1: DEP ZLIB build: {name}!\" in c.out\n    if name == \"zlib-ng\":\n        # CMakeDeps can not be used to consume replaced requires for different packages\n        # only CMakeConfigDeps has this capability\n        c.run(\"install --requires=app/0.1 -pr=profile -g CMakeDeps\", assert_error=True)\n\n\ndef test_replace_requires_consumer_references_error_multiple():\n    # https://github.com/conan-io/conan/issues/17407\n    c = TestClient()\n    # IMPORTANT: The replacement package must be target-compatible\n    zlib = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class ZlibNG(ConanFile):\n            name = \"zlib\"\n            version = \"0.2\"\n            def package_info(self):\n                self.cpp_info.set_property(\"cmake_file_name\", \"ZLIB\")\n                self.cpp_info.set_property(\"cmake_target_name\", \"ZLIB::ZLIB\")\n        \"\"\")\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class App(ConanFile):\n            name = \"app\"\n            version = \"0.1\"\n            settings = \"build_type\"\n            requires = \"zlib/0.1\", \"bzip2/0.1\"\n            generators = \"CMakeDeps\"\n\n            def generate(self):\n                self.output.info(f\"DEP ZLIB generate: {self.dependencies['zlib'].ref.name}!\")\n                self.output.info(f\"DEP BZIP2 generate: {self.dependencies['bzip2'].ref.name}!\")\n            def build(self):\n                self.output.info(f\"DEP ZLIB build: {self.dependencies['zlib'].ref.name}!\")\n                self.output.info(f\"DEP BZIP2 build: {self.dependencies['bzip2'].ref.name}!\")\n            def package_info(self):\n                self.output.info(f\"DEP ZLIB package_info: {self.dependencies['zlib'].ref.name}!\")\n                self.cpp_info.requires = [\"zlib::zlib\", \"bzip2::bzip2\"]\n        \"\"\")\n    c.save({\"zlib/conanfile.py\": zlib,\n            \"app/conanfile.py\": conanfile,\n            \"profile\": \"[replace_requires]\\nzlib/0.1: zlib/0.2\\nbzip2/0.1: zlib/0.2\"})\n    c.run(\"create zlib\")\n    c.run(\"build app -pr=profile\")\n    assert \"zlib/0.1: zlib/0.2\" in c.out\n    assert \"conanfile.py (app/0.1): DEP ZLIB generate: zlib!\" in c.out\n    assert \"conanfile.py (app/0.1): DEP ZLIB build: zlib!\" in c.out\n    assert \"conanfile.py (app/0.1): DEP BZIP2 generate: zlib!\" in c.out\n    assert \"conanfile.py (app/0.1): DEP BZIP2 build: zlib!\" in c.out\n    # Check generated CMake code. If the targets are NOT compatible, then the replacement\n    # Cannot happen\n    assert \"find_package(ZLIB)\" in c.out\n    assert \"target_link_libraries(... ZLIB::ZLIB ZLIB::ZLIB)\" in c.out\n    cmake = c.load(\"app/ZLIBTargets.cmake\")\n    assert \"add_library(ZLIB::ZLIB INTERFACE IMPORTED)\" in cmake\n    c.run(\"create app -pr=profile\")\n    assert \"zlib/0.1: zlib/0.2\" in c.out\n    assert \"app/0.1: DEP ZLIB generate: zlib!\" in c.out\n    assert \"app/0.1: DEP ZLIB build: zlib!\" in c.out\n\n\ndef test_replace_requires_consumer_components_options():\n    c = TestClient()\n    # IMPORTANT: The replacement package must be target-compatible\n    zlib_ng = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class ZlibNG(ConanFile):\n            name = \"zlib-ng\"\n            version = \"0.1\"\n            options = {\"compat\": [False, True]}\n            default_options = {\"compat\": False}\n            def package_info(self):\n                self.cpp_info.set_property(\"cmake_file_name\", \"ZLIB\")\n                self.cpp_info.set_property(\"cmake_target_name\", \"ZLIB::ZLIB\")\n                if self.options.compat:\n                    self.cpp_info.components[\"myzlib\"].set_property(\"cmake_target_name\",\n                                                                    \"ZLIB::zmylib\")\n        \"\"\")\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class App(ConanFile):\n            name = \"app\"\n            version = \"0.1\"\n            settings = \"build_type\"\n            requires = \"zlib/0.1\"\n            generators = \"CMakeDeps\"\n\n            def generate(self):\n                self.output.info(f\"DEP ZLIB generate: {self.dependencies['zlib'].ref.name}!\")\n            def build(self):\n                self.output.info(f\"DEP ZLIB build: {self.dependencies['zlib'].ref.name}!\")\n            def package_info(self):\n                self.output.info(f\"zlib in deps?: {'zlib' in self.dependencies}\")\n                self.output.info(f\"zlib-ng in deps?: {'zlib-ng' in self.dependencies}\")\n                self.output.info(f\"DEP ZLIB package_info: {self.dependencies['zlib'].ref.name}!\")\n                self.cpp_info.requires = [\"zlib::myzlib\"]\n        \"\"\")\n    profile = textwrap.dedent(\"\"\"\n        [options]\n        zlib-ng/*:compat=True\n\n        [replace_requires]\n        zlib/0.1: zlib-ng/0.1\n        \"\"\")\n    c.save({\"zlibng/conanfile.py\": zlib_ng,\n            \"app/conanfile.py\": conanfile,\n            \"profile\": profile})\n\n    c.run(\"create zlibng -o *:compat=True\")\n    c.run(\"build app -pr=profile\")\n    assert \"zlib/0.1: zlib-ng/0.1\" in c.out\n    assert \"conanfile.py (app/0.1): DEP ZLIB generate: zlib-ng!\" in c.out\n    assert \"conanfile.py (app/0.1): DEP ZLIB build: zlib-ng!\" in c.out\n    # Check generated CMake code. If the targets are NOT compatible, then the replacement\n    # Cannot happen\n    assert \"find_package(ZLIB)\" in c.out\n    assert \"target_link_libraries(... ZLIB::ZLIB)\" in c.out\n    cmake = c.load(\"app/ZLIBTargets.cmake\")\n    assert \"add_library(ZLIB::ZLIB INTERFACE IMPORTED)\" in cmake\n    cmake = c.load(\"app/ZLIB-Target-none.cmake\")\n    assert \"set_property(TARGET ZLIB::ZLIB APPEND PROPERTY INTERFACE_LINK_LIBRARIES ZLIB::zmylib)\" \\\n           in cmake\n\n    c.run(\"create app -pr=profile\")\n    assert \"zlib/0.1: zlib-ng/0.1\" in c.out\n    assert \"app/0.1: DEP ZLIB generate: zlib-ng!\" in c.out\n    assert \"app/0.1: DEP ZLIB build: zlib-ng!\" in c.out\n    assert \"find_package(ZLIB)\" in c.out\n    assert \"target_link_libraries(... ZLIB::ZLIB)\" in c.out\n    assert \"zlib in deps?: True\" in c.out\n    assert \"zlib-ng in deps?: False\" in c.out\n\n\ndef test_replace_requires_multiple():\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class EpoxyConan(ConanFile):\n            name = \"libepoxy\"\n            version = \"0.1\"\n\n            def requirements(self):\n                self.requires(\"opengl/system\")\n                self.requires(\"egl/system\")\n\n            def generate(self):\n                for r, d in self.dependencies.items():\n                    self.output.info(f\"DEP: {r.ref.name}: {d.ref.name}\")\n\n            def package_info(self):\n                self.cpp_info.requires.append(\"opengl::opengl\")\n                self.cpp_info.requires.append(\"egl::egl\")\n        \"\"\")\n    profile = textwrap.dedent(\"\"\"\n        [replace_requires]\n        opengl/system: libgl/1.0\n        egl/system: libgl/1.0\n        \"\"\")\n    c = TestClient()\n    c.save({\"dep/conanfile.py\": GenConanfile(),\n            \"app/conanfile.py\": conanfile,\n            \"profile\": profile})\n    c.run(\"create dep --name=libgl --version=1.0\")\n    c.run(\"create app -pr=profile\")\n    # There are actually 2 dependencies, pointing to the same node\n    assert \"libepoxy/0.1: DEP: opengl: libgl\" in c.out\n    assert \"libepoxy/0.1: DEP: egl: libgl\" in c.out\n\n\nclass TestReplaceRequiresTransitiveGenerators:\n    \"\"\" Generators are incorrectly managing replace_requires\n    # https://github.com/conan-io/conan/issues/17557\n    \"\"\"\n\n    @pytest.mark.parametrize(\"diamond\", [True, False])\n    def test_no_components(self, diamond):\n        c = TestClient()\n        zlib_ng = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class ZlibNG(ConanFile):\n                name = \"zlib-ng\"\n                version = \"0.1\"\n                package_type = \"static-library\"\n                def package_info(self):\n                    self.cpp_info.libs = [\"zlib\"]\n                    self.cpp_info.type = \"static-library\"\n                    self.cpp_info.location = \"lib/zlib.lib\"\n                    self.cpp_info.set_property(\"cmake_file_name\", \"ZLIB\")\n                    self.cpp_info.set_property(\"cmake_target_name\", \"ZLIB::ZLIB\")\n                    self.cpp_info.set_property(\"pkg_config_name\", \"ZLIB\")\n            \"\"\")\n        openssl = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class openssl(ConanFile):\n                name = \"openssl\"\n                version = \"0.1\"\n                package_type = \"static-library\"\n                requires = \"zlib/0.1\"\n                def package_info(self):\n                    self.cpp_info.libs = [\"crypto\"]\n                    self.cpp_info.type = \"static-library\"\n                    self.cpp_info.location = \"lib/crypto.lib\"\n                    self.cpp_info.requires = [\"zlib::zlib\"]\n            \"\"\")\n        zlib = '\"zlib/0.1\"' if diamond else \"\"\n        conanfile = textwrap.dedent(f\"\"\"\n            from conan import ConanFile\n            class App(ConanFile):\n                name = \"app\"\n                version = \"0.1\"\n                settings = \"build_type\", \"arch\"\n                requires = \"openssl/0.1\", {zlib}\n                package_type = \"application\"\n                generators = \"CMakeConfigDeps\", \"PkgConfigDeps\", \"MSBuildDeps\"\n            \"\"\")\n        profile = textwrap.dedent(\"\"\"\n            [settings]\n            build_type = Release\n            arch=x86_64\n\n            [replace_requires]\n            zlib/0.1: zlib-ng/0.1\n            \"\"\")\n        c.save({\"zlibng/conanfile.py\": zlib_ng,\n                \"openssl/conanfile.py\": openssl,\n                \"app/conanfile.py\": conanfile,\n                \"profile\": profile})\n\n        c.run(\"create zlibng\")\n        c.run(\"create openssl -pr=profile\")\n        c.run(\"install app -pr=profile\")\n        assert \"zlib/0.1: zlib-ng/0.1\" in c.out\n\n        pc_content = c.load(\"app/ZLIB.pc\")\n        assert 'Libs: -L\"${libdir}\" -lzlib' in pc_content\n        pc_content = c.load(\"app/openssl.pc\")\n        assert 'Requires: ZLIB' in pc_content\n\n        cmake = c.load(\"app/ZLIB-Targets-release.cmake\")\n        assert \"add_library(ZLIB::ZLIB STATIC IMPORTED)\" in cmake\n\n        cmake = c.load(\"app/openssl-Targets-release.cmake\")\n        assert \"find_dependency(ZLIB REQUIRED CONFIG)\" in cmake\n        assert \"add_library(openssl::openssl STATIC IMPORTED)\" in cmake\n        assert \"set_property(TARGET openssl::openssl APPEND PROPERTY INTERFACE_LINK_LIBRARIES\\n\" \\\n               '             \"$<$<CONFIG:RELEASE>:ZLIB::ZLIB>\")' in cmake\n\n        # checking MSBuildDeps\n        zlib_ng_props = c.load(\"app/conan_zlib-ng.props\")\n        assert 'Project=\"conan_zlib-ng_release_x64.props\"' in zlib_ng_props\n        props = c.load(\"app/conan_openssl_release_x64.props\")\n        assert \"<Import Condition=\\\"'$(conan_zlib-ng_props_imported)' != 'True'\\\"\" \\\n               \" Project=\\\"conan_zlib-ng.props\\\"/>\" in props\n\n    @pytest.mark.parametrize(\"diamond\", [True, False])\n    def test_openssl_components(self, diamond):\n        c = TestClient()\n        zlib_ng = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class ZlibNG(ConanFile):\n                name = \"zlib-ng\"\n                version = \"0.1\"\n                package_type = \"static-library\"\n                def package_info(self):\n                    self.cpp_info.libs = [\"zlib\"]\n                    self.cpp_info.type = \"static-library\"\n                    self.cpp_info.location = \"lib/zlib.lib\"\n                    self.cpp_info.set_property(\"cmake_file_name\", \"ZLIB\")\n                    self.cpp_info.set_property(\"cmake_target_name\", \"ZLIB::ZLIB\")\n                    self.cpp_info.set_property(\"pkg_config_name\", \"ZLIB\")\n            \"\"\")\n        openssl = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class openssl(ConanFile):\n                name = \"openssl\"\n                version = \"0.1\"\n                package_type = \"static-library\"\n                requires = \"zlib/0.1\"\n                def package_info(self):\n                    self.cpp_info.components[\"crypto\"].libs = [\"crypto\"]\n                    self.cpp_info.components[\"crypto\"].type = \"static-library\"\n                    self.cpp_info.components[\"crypto\"].location = \"lib/crypto.lib\"\n                    self.cpp_info.components[\"crypto\"].requires = [\"zlib::zlib\"]\n            \"\"\")\n        zlib = '\"zlib/0.1\"' if diamond else \"\"\n        conanfile = textwrap.dedent(f\"\"\"\n            from conan import ConanFile\n            class App(ConanFile):\n                name = \"app\"\n                version = \"0.1\"\n                settings = \"build_type\", \"arch\"\n                requires = \"openssl/0.1\", {zlib}\n                package_type = \"application\"\n                generators = \"CMakeConfigDeps\", \"PkgConfigDeps\", \"MSBuildDeps\"\n            \"\"\")\n        profile = textwrap.dedent(\"\"\"\n            [settings]\n            build_type = Release\n            arch=x86_64\n\n            [replace_requires]\n            zlib/0.1: zlib-ng/0.1\n            \"\"\")\n        c.save({\"zlibng/conanfile.py\": zlib_ng,\n                \"openssl/conanfile.py\": openssl,\n                \"app/conanfile.py\": conanfile,\n                \"profile\": profile})\n\n        c.run(\"create zlibng\")\n        c.run(\"create openssl -pr=profile\")\n        c.run(\"install app -pr=profile\")\n        assert \"zlib/0.1: zlib-ng/0.1\" in c.out\n\n        pc_content = c.load(\"app/ZLIB.pc\")\n        assert 'Libs: -L\"${libdir}\" -lzlib' in pc_content\n        pc_content = c.load(\"app/openssl-crypto.pc\")\n        assert 'Requires: ZLIB' in pc_content\n\n        cmake = c.load(\"app/ZLIB-Targets-release.cmake\")\n        assert \"add_library(ZLIB::ZLIB STATIC IMPORTED)\" in cmake\n\n        cmake = c.load(\"app/openssl-Targets-release.cmake\")\n        assert \"find_dependency(ZLIB REQUIRED CONFIG)\" in cmake\n        assert \"add_library(openssl::crypto STATIC IMPORTED)\" in cmake\n        assert \"set_property(TARGET openssl::crypto APPEND PROPERTY INTERFACE_LINK_LIBRARIES\\n\" \\\n               '             \"$<$<CONFIG:RELEASE>:ZLIB::ZLIB>\")' in cmake\n\n        # checking MSBuildDeps\n        zlib_ng_props = c.load(\"app/conan_zlib-ng.props\")\n        assert 'Project=\"conan_zlib-ng_release_x64.props\"' in zlib_ng_props\n\n        props = c.load(\"app/conan_openssl_crypto_release_x64.props\")\n        assert \"<Import Condition=\\\"'$(conan_zlib-ng_props_imported)' != 'True'\\\"\" \\\n               \" Project=\\\"conan_zlib-ng.props\\\"/>\" in props\n\n    @pytest.mark.parametrize(\"diamond\", [True, False])\n    @pytest.mark.parametrize(\"explicit_requires\", [True, False])\n    def test_zlib_components(self, diamond, explicit_requires):\n        c = TestClient()\n        zlib_ng = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class ZlibNG(ConanFile):\n                name = \"zlib-ng\"\n                version = \"0.1\"\n                package_type = \"static-library\"\n                def package_info(self):\n                    self.cpp_info.components[\"myzlib\"].libs = [\"zlib\"]\n                    self.cpp_info.components[\"myzlib\"].type = \"static-library\"\n                    self.cpp_info.components[\"myzlib\"].location = \"lib/zlib.lib\"\n                    self.cpp_info.set_property(\"cmake_file_name\", \"ZLIB\")\n                    self.cpp_info.components[\"myzlib\"].set_property(\"pkg_config_name\", \"ZLIB\")\n                    self.cpp_info.components[\"myzlib\"].set_property(\"cmake_target_name\",\n                                                                    \"ZLIB::ZLIB\")\n            \"\"\")\n        openssl = textwrap.dedent(f\"\"\"\n            from conan import ConanFile\n            class openssl(ConanFile):\n                name = \"openssl\"\n                version = \"0.1\"\n                package_type = \"static-library\"\n                requires = \"zlib/0.1\"\n                def package_info(self):\n                    self.cpp_info.libs = [\"crypto\"]\n                    self.cpp_info.type = \"static-library\"\n                    self.cpp_info.location = \"lib/crypto.lib\"\n                    if {explicit_requires}:\n                        self.cpp_info.requires = [\"zlib::zlib\"]\n            \"\"\")\n        zlib = '\"zlib/0.1\"' if diamond else \"\"\n        conanfile = textwrap.dedent(f\"\"\"\n            from conan import ConanFile\n            class App(ConanFile):\n                name = \"app\"\n                version = \"0.1\"\n                settings = \"build_type\", \"arch\"\n                requires = \"openssl/0.1\", {zlib}\n                package_type = \"application\"\n                generators = \"CMakeConfigDeps\", \"PkgConfigDeps\", \"MSBuildDeps\"\n            \"\"\")\n        profile = textwrap.dedent(\"\"\"\n            [settings]\n            build_type = Release\n            arch = x86_64\n\n            [replace_requires]\n            zlib/0.1: zlib-ng/0.1\n            \"\"\")\n        c.save({\"zlibng/conanfile.py\": zlib_ng,\n                \"openssl/conanfile.py\": openssl,\n                \"app/conanfile.py\": conanfile,\n                \"profile\": profile})\n\n        c.run(\"create zlibng\")\n        c.run(\"create openssl -pr=profile\")\n        c.run(\"install app -pr=profile\")\n        assert \"zlib/0.1: zlib-ng/0.1\" in c.out\n\n        pc_content = c.load(\"app/zlib-ng.pc\")\n        assert 'Requires: ZLIB' in pc_content\n        pc_content = c.load(\"app/ZLIB.pc\")\n        assert 'Libs: -L\"${libdir}\" -lzlib' in pc_content\n        pc_content = c.load(\"app/openssl.pc\")\n        assert 'Requires: zlib-ng' in pc_content\n\n        cmake = c.load(\"app/ZLIB-Targets-release.cmake\")\n        assert \"add_library(ZLIB::ZLIB STATIC IMPORTED)\" in cmake\n\n        cmake = c.load(\"app/openssl-Targets-release.cmake\")\n        assert \"find_dependency(ZLIB REQUIRED CONFIG)\" in cmake\n        assert \"add_library(openssl::openssl STATIC IMPORTED)\" in cmake\n        # It should access the generic zlib-ng target\n        assert \"set_property(TARGET openssl::openssl APPEND PROPERTY INTERFACE_LINK_LIBRARIES\\n\" \\\n               '             \"$<$<CONFIG:RELEASE>:zlib-ng::zlib-ng>\")' in cmake\n\n        # checking MSBuildDeps\n        zlib_ng_props = c.load(\"app/conan_zlib-ng.props\")\n        assert \"<Import Condition=\\\"'$(conan_zlib-ng_myzlib_props_imported)' != 'True'\\\" \" \\\n               \"Project=\\\"conan_zlib-ng_myzlib.props\\\"/\" in zlib_ng_props\n\n        props = c.load(\"app/conan_openssl_release_x64.props\")\n        assert \"<Import Condition=\\\"'$(conan_zlib-ng_props_imported)' != 'True'\\\"\" \\\n               \" Project=\\\"conan_zlib-ng.props\\\"/>\" in props\n\n    @pytest.mark.parametrize(\"diamond\", [True, False])\n    @pytest.mark.parametrize(\"package_requires\", [False, True])\n    def test_both_components(self, diamond, package_requires):\n        c = TestClient()\n        zlib_ng = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class ZlibNG(ConanFile):\n                name = \"zlib-ng\"\n                version = \"0.1\"\n                package_type = \"static-library\"\n                def package_info(self):\n                    self.cpp_info.components[\"myzlib\"].libs = [\"zlib\"]\n                    self.cpp_info.components[\"myzlib\"].type = \"static-library\"\n                    self.cpp_info.components[\"myzlib\"].location = \"lib/zlib.lib\"\n                    self.cpp_info.set_property(\"cmake_file_name\", \"ZLIB\")\n                    self.cpp_info.components[\"myzlib\"].set_property(\"pkg_config_name\", \"ZLIB\")\n                    self.cpp_info.components[\"myzlib\"].set_property(\"cmake_target_name\",\n                                                                    \"ZLIB::ZLIB\")\n            \"\"\")\n        openssl = textwrap.dedent(f\"\"\"\n            from conan import ConanFile\n            class openssl(ConanFile):\n                name = \"openssl\"\n                version = \"0.1\"\n                package_type = \"static-library\"\n                requires = \"zlib/0.1\"\n                def package_info(self):\n                    self.cpp_info.components[\"crypto\"].libs = [\"crypto\"]\n                    self.cpp_info.components[\"crypto\"].type = \"static-library\"\n                    self.cpp_info.components[\"crypto\"].location = \"lib/crypto.lib\"\n                    if {package_requires}:\n                        self.cpp_info.components[\"crypto\"].requires = [\"zlib::zlib\"]\n                    else:\n                        self.cpp_info.components[\"crypto\"].requires = [\"zlib::myzlib\"]\n            \"\"\")\n        zlib = '\"zlib/0.1\"' if diamond else \"\"\n        conanfile = textwrap.dedent(f\"\"\"\n            from conan import ConanFile\n            class App(ConanFile):\n                name = \"app\"\n                version = \"0.1\"\n                settings = \"build_type\", \"arch\"\n                requires = \"openssl/0.1\", {zlib}\n                package_type = \"application\"\n                generators = \"CMakeConfigDeps\", \"PkgConfigDeps\", \"MSBuildDeps\"\n            \"\"\")\n        profile = textwrap.dedent(\"\"\"\n            [settings]\n            build_type = Release\n            arch = x86_64\n\n            [replace_requires]\n            zlib/0.1: zlib-ng/0.1\n            \"\"\")\n        c.save({\"zlibng/conanfile.py\": zlib_ng,\n                \"openssl/conanfile.py\": openssl,\n                \"app/conanfile.py\": conanfile,\n                \"profile\": profile})\n\n        c.run(\"create zlibng\")\n        c.run(\"create openssl -pr=profile\")\n        c.run(\"install app -pr=profile\")\n        assert \"zlib/0.1: zlib-ng/0.1\" in c.out\n\n        pc_content = c.load(\"app/zlib-ng.pc\")\n        assert 'Requires: ZLIB' in pc_content\n        pc_content = c.load(\"app/ZLIB.pc\")\n        assert 'Libs: -L\"${libdir}\" -lzlib' in pc_content\n        pc_content = c.load(\"app/openssl-crypto.pc\")\n        assert f'Requires: {\"zlib-ng\" if package_requires else \"ZLIB\"}' in pc_content\n\n        cmake = c.load(\"app/ZLIB-Targets-release.cmake\")\n        assert \"add_library(ZLIB::ZLIB STATIC IMPORTED)\" in cmake\n\n        cmake = c.load(\"app/openssl-Targets-release.cmake\")\n        assert \"find_dependency(ZLIB REQUIRED CONFIG)\" in cmake\n        assert \"add_library(openssl::crypto STATIC IMPORTED)\" in cmake\n        if package_requires:\n            # The generic package requirement uses the package name zlib-ng\n            assert \"set_property(TARGET openssl::crypto APPEND PROPERTY INTERFACE_LINK_LIBRARIES\\n\" \\\n                   '             \"$<$<CONFIG:RELEASE>:zlib-ng::zlib-ng>\")' in cmake\n        else:\n            assert \"set_property(TARGET openssl::crypto APPEND PROPERTY INTERFACE_LINK_LIBRARIES\\n\" \\\n                   '             \"$<$<CONFIG:RELEASE>:ZLIB::ZLIB>\")' in cmake\n\n        # checking MSBuildDeps\n        zlib_ng_props = c.load(\"app/conan_zlib-ng.props\")\n        assert \"<Import Condition=\\\"'$(conan_zlib-ng_myzlib_props_imported)' != 'True'\\\" \" \\\n               \"Project=\\\"conan_zlib-ng_myzlib.props\\\"/\" in zlib_ng_props\n\n        props = c.load(\"app/conan_openssl_crypto_release_x64.props\")\n        if package_requires:\n            assert \"<Import Condition=\\\"'$(conan_zlib-ng_props_imported)' != 'True'\\\"\" \\\n                   \" Project=\\\"conan_zlib-ng.props\\\"/>\" in props\n        else:\n            assert \"<Import Condition=\\\"'$(conan_zlib-ng_myzlib_props_imported)' != 'True'\\\"\" \\\n                   \" Project=\\\"conan_zlib-ng_myzlib.props\\\"/>\" in props\n\n\n@pytest.mark.parametrize(\"require, pattern, alternative, expected\", [\n     # Version range as pattern\n     # PINNED REQUIRE VERSION\n     (\"dep/1.0\", \"dep/[>=1.0 <2]\", \"dep/1.3\", \"dep/1.3\"),\n     (\"dep/1.0\", \"dep/[>=1.5 <2]\", \"dep/1.3\", False),\n     # RANGE REQUIRE VERSION\n     (\"dep/[>=1.2 <2]\", \"dep/[>=1.0 <2]\", \"dep/1.3\", \"dep/1.3\"),\n     (\"dep/[>=1.0 <1.5]\", \"dep/[>=1.2 <2]\", \"dep/1.3\", \"dep/1.3\"),\n     (\"dep/[>=1.0 <1.5]\", \"dep/[>=1.5 <2]\", \"dep/1.3\", False)\n    ]\n )\ndef test_replace_requires_ranges(require, pattern, alternative, expected):\n    c = TestClient(light=True)\n    c.save({\"dep/conanfile.py\": GenConanfile(\"dep\"),\n            \"app/conanfile.py\": GenConanfile().with_requires(require),\n            \"profile\": f\"[replace_requires]\\n{pattern}: {alternative}\"})\n    c.run(\"create dep --version=1.0\")\n    c.run(\"create dep --version=1.3\")\n    c.run(\"graph info app -pr=profile\")\n    if expected:\n        assert \"Replaced requires\" in c.out\n        assert f\"{require}: {expected}\" in c.out\n    else:\n        assert \"Replaced requires\" not in c.out\n\n\ndef test_host_version_replace():\n    profile = textwrap.dedent(\"\"\"\n    include(default)\n    [replace_requires]\n    pkg/*: pkg/0.1@user/channel\n    \"\"\")\n\n    tc = TestClient(light=True)\n    tc.save({\"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\"),\n             \"conanfile.py\": GenConanfile()\n                .with_requires(\"pkg/0.1@user/channel\")\n                .with_tool_requires(\"pkg/<host_version>\"),\n             \"profile\": profile})\n    tc.run(\"create pkg\")\n    tc.run(\"create pkg --user=user --channel=channel\")\n\n    # We did not track the user/channel, we resolve the version but keep the original user/channel\n    tc.run(\"install -pr=profile\")\n    tc.assert_listed_require({\"pkg/0.1@user/channel#485dad6cb11e2fa99d9afbe44a57a164\": \"Cache\"})\n    tc.assert_listed_require({\"pkg/0.1#485dad6cb11e2fa99d9afbe44a57a164\": \"Cache\"}, build=True)\n\n    # If we want to also match user/channel\n    # Solution 1: Also replace the tool_requires in your profile to use same user/channel\n    tool_profile = profile + \"\\n[replace_tool_requires]\\npkg/*: pkg/<host_version>@user/channel\"\n    tc.save({\"tool_profile\": tool_profile})\n    tc.run(\"install -pr=tool_profile\")\n    tc.assert_listed_require({\"pkg/0.1@user/channel#485dad6cb11e2fa99d9afbe44a57a164\": \"Cache\"})\n    tc.assert_listed_require({\"pkg/0.1@user/channel#485dad6cb11e2fa99d9afbe44a57a164\": \"Cache\"}, build=True)\n\n    # Solution 2: Directly in the requirement\n    tc.save({\"conanfile.py\": GenConanfile()\n                .with_requires(\"pkg/0.1@user/channel\")\n                .with_tool_requires(\"pkg/<host_version>@user/channel\")})\n\n    tc.run(\"install -pr=profile\")\n    tc.assert_listed_require({\"pkg/0.1@user/channel#485dad6cb11e2fa99d9afbe44a57a164\": \"Cache\"})\n    tc.assert_listed_require({\"pkg/0.1@user/channel#485dad6cb11e2fa99d9afbe44a57a164\": \"Cache\"}, build=True)\n"
  },
  {
    "path": "test/integration/graph/test_require_same_pkg_versions.py",
    "content": "import re\nimport textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_require_different_versions():\n    \"\"\" this test demostrates that it is possible to tool_require different versions\n    of the same thing, deactivating run=False (as long as their executables are not called the same)\n\n    https://github.com/conan-io/conan/issues/13521\n    \"\"\"\n    c = TestClient()\n    gcc = textwrap.dedent(r\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import save\n        class Pkg(ConanFile):\n            name = \"gcc\"\n            def package(self):\n                echo = f\"@echo off\\necho MYGCC={self.version}!!\"\n                save(self, os.path.join(self.package_folder, \"bin\", f\"mygcc{self.version}.bat\"), echo)\n                save(self, os.path.join(self.package_folder, \"bin\", f\"mygcc{self.version}.sh\"), echo)\n                os.chmod(os.path.join(self.package_folder, \"bin\", f\"mygcc{self.version}.sh\"), 0o777)\n            \"\"\")\n    wine = textwrap.dedent(\"\"\"\n        import os, platform\n        from conan import ConanFile\n        from conan.tools.files import save, chdir\n        class Pkg(ConanFile):\n            name = \"wine\"\n            version = \"1.0\"\n            def build_requirements(self):\n                self.tool_requires(\"gcc/1.0\", run=False)\n                self.tool_requires(\"gcc/2.0\", run=False)\n\n            def generate(self):\n                gcc1 = self.dependencies.build[\"gcc/1.0\"]\n                assert gcc1.ref.version == \"1.0\"\n                gcc2 = self.dependencies.build[\"gcc/2.0\"]\n                assert gcc2.ref.version == \"2.0\"\n\n            def build(self):\n                ext = \"bat\" if platform.system() == \"Windows\" else \"sh\"\n                self.run(f\"mygcc1.0.{ext}\")\n                self.run(f\"mygcc2.0.{ext}\")\n            \"\"\")\n    c.save({\"gcc/conanfile.py\": gcc,\n            \"wine/conanfile.py\": wine})\n\n    c.run(\"create gcc --version=1.0\")\n    c.run(\"create gcc --version=2.0\")\n\n    c.run(\"build wine --lockfile-out=conan.lock\")\n    assert \"gcc/1.0#3d6110b9e2b90074160fa33b6f0ea968 - Cache\" in c.out\n    assert \"gcc/2.0#3d6110b9e2b90074160fa33b6f0ea968 - Cache\" in c.out\n    assert \"MYGCC=1.0!!\" in c.out\n    assert \"MYGCC=2.0!!\" in c.out\n    lock = c.load(\"wine/conan.lock\")\n    assert \"gcc/1.0#3d6110b9e2b90074160fa33b6f0ea968\" in lock\n    assert \"gcc/2.0#3d6110b9e2b90074160fa33b6f0ea968\" in lock\n\n\ndef test_require_different_versions_profile_override():\n    \"\"\" same as above but what if the profile is the one overriding the version?\n    \"\"\"\n    c = TestClient()\n    gcc = textwrap.dedent(r\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import save\n        class Pkg(ConanFile):\n            name = \"gcc\"\n            def package(self):\n                echo = f\"@echo off\\necho MYGCC={self.version}!!\"\n                save(self, os.path.join(self.package_folder, \"bin\", f\"mygcc{self.version}.bat\"), echo)\n                save(self, os.path.join(self.package_folder, \"bin\", f\"mygcc{self.version}.sh\"), echo)\n                os.chmod(os.path.join(self.package_folder, \"bin\", f\"mygcc{self.version}.sh\"), 0o777)\n            \"\"\")\n    wine = textwrap.dedent(\"\"\"\n        import os, platform\n        from conan import ConanFile\n        from conan.tools.files import save, chdir\n        class Pkg(ConanFile):\n            name = \"wine\"\n            version = \"1.0\"\n            def build_requirements(self):\n                self.tool_requires(\"gcc/1.0\", run=False)\n\n            def build(self):\n                ext = \"bat\" if platform.system() == \"Windows\" else \"sh\"\n                self.run(f\"mygcc1.0.{ext}\")\n                self.run(f\"mygcc2.0.{ext}\")\n            \"\"\")\n    c.save({\"gcc/conanfile.py\": gcc,\n            \"wine/conanfile.py\": wine,\n            \"profile\": \"[tool_requires]\\ngcc/2.0\"})\n\n    c.run(\"create gcc --version=1.0\")\n    c.run(\"create gcc --version=2.0\")\n\n    c.run(\"build wine -pr=profile --lockfile-out=conan.lock\")\n    assert \"gcc/1.0#3d6110b9e2b90074160fa33b6f0ea968 - Cache\" in c.out\n    assert \"gcc/2.0#3d6110b9e2b90074160fa33b6f0ea968 - Cache\" in c.out\n    assert \"MYGCC=1.0!!\" in c.out\n    assert \"MYGCC=2.0!!\" in c.out\n    lock = c.load(\"wine/conan.lock\")\n    assert \"gcc/1.0#3d6110b9e2b90074160fa33b6f0ea968\" in lock\n    assert \"gcc/2.0#3d6110b9e2b90074160fa33b6f0ea968\" in lock\n\n\ndef test_require_different_versions_profile_override_build_script():\n    \"\"\" build-scripts by default do the right thing, because they have run=True\n    (they could be runnable shell scripts)\n    \"\"\"\n    c = TestClient(light=True)\n    buildscripts = GenConanfile(\"buildscripts\").with_package_type(\"build-scripts\")\n    wine = GenConanfile(\"wine\", \"1.0\").with_tool_requirement(\"buildscripts/1.0\")\n    c.save({\"buildscripts/conanfile.py\": buildscripts,\n            \"wine/conanfile.py\": wine,\n            \"profile\": \"[tool_requires]\\nbuildscripts/2.0\"})\n\n    c.run(\"create buildscripts --version=2.0\")\n\n    c.run(\"build wine -pr=profile --lockfile-out=conan.lock\")\n    assert \"buildscripts/1.0\" not in c.out\n    assert \"buildscripts/2.0#fced952ee7aba96f858b70c7d6c9c8d2 - Cache\" in c.out\n    lock = c.load(\"wine/conan.lock\")\n    assert \"buildscripts/1.0\" not in lock\n    assert \"buildscripts/2.0#fced952ee7aba96f858b70c7d6c9c8d2\" in lock\n\n\ndef test_require_different_options():\n    \"\"\" this test demostrates that it is possible to tool_require different options\n    of the same thing, deactivating run=False (as long as their executables are not called the same)\n\n    https://github.com/conan-io/conan/issues/13521\n    \"\"\"\n    c = TestClient()\n    gcc = textwrap.dedent(r\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import save\n        class Pkg(ConanFile):\n            name = \"gcc\"\n            version = \"1.0\"\n            options = {\"myoption\": [1, 2]}\n            def package(self):\n                echo = f\"@echo off\\necho MYGCC={self.options.myoption}!!\"\n                save(self, os.path.join(self.package_folder, \"bin\", f\"mygcc{self.options.myoption}.bat\"), echo)\n                save(self, os.path.join(self.package_folder, \"bin\", f\"mygcc{self.options.myoption}.sh\"), echo)\n                os.chmod(os.path.join(self.package_folder, \"bin\", f\"mygcc{self.options.myoption}.sh\"), 0o777)\n            \"\"\")\n    wine = textwrap.dedent(\"\"\"\n        import os, platform\n        from conan import ConanFile\n        from conan.tools.files import save, chdir\n        class Pkg(ConanFile):\n            name = \"wine\"\n            version = \"1.0\"\n            def build_requirements(self):\n                self.tool_requires(\"gcc/1.0\", run=False, options={\"myoption\": 1})\n                self.tool_requires(\"gcc/1.0\", run=False, options={\"myoption\": 2})\n\n            def generate(self):\n                gcc1 = self.dependencies.build.get(\"gcc\", options={\"myoption\": 1})\n                assert gcc1.options.myoption == \"1\"\n                gcc2 = self.dependencies.build.get(\"gcc\", options={\"myoption\": 2})\n                assert gcc2.options.myoption == \"2\"\n\n            def build(self):\n                ext = \"bat\" if platform.system() == \"Windows\" else \"sh\"\n                self.run(f\"mygcc1.{ext}\")\n                self.run(f\"mygcc2.{ext}\")\n            \"\"\")\n    c.save({\"gcc/conanfile.py\": gcc,\n            \"wine/conanfile.py\": wine})\n\n    c.run(\"create gcc -o myoption=1\")\n    c.run(\"create gcc -o myoption=2\")\n\n    c.run(\"build wine --lockfile-out=conan.lock\")\n    assert \"gcc/1.0#616ce3babcecef39a27806c1a5f4b4ff - Cache\" in c.out\n    assert \"MYGCC=1!!\" in c.out\n    assert \"MYGCC=2!!\" in c.out\n    lock = c.load(\"wine/conan.lock\")\n    # Testing it doesn't crash or anything like that\n    assert \"gcc/1.0#616ce3babcecef39a27806c1a5f4b4ff\" in lock\n\n\ndef test_require_different_versions_transitive():\n    \"\"\"\n    https://github.com/conan-io/conan/issues/18086\n    \"\"\"\n    c = TestClient(default_server_user=True, path_with_spaces=False)\n    qemu = textwrap.dedent(r\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import save\n        class Pkg(ConanFile):\n            name = \"myqemu\"\n            package_type = \"application\"\n\n            def package(self):\n                echo = f\"@echo off\\necho RUNNING {self.name}/{self.version}!!\"\n                save(self, os.path.join(self.package_folder, \"bin\", f\"{self.name}.bat\"), echo)\n                save(self, os.path.join(self.package_folder, \"bin\", f\"{self.name}.sh\"), echo)\n                os.chmod(os.path.join(self.package_folder, \"bin\", f\"{self.name}.sh\"), 0o777)\n            \"\"\")\n    mytool = textwrap.dedent(r\"\"\"\n        import os, platform\n        from conan import ConanFile\n        from conan.tools.files import save, chdir\n        class Pkg(ConanFile):\n            version = \"1.0\"\n            package_type = \"application\"\n\n            def requirements(self):\n                version = \"1.0\" if self.name == \"snippy\" else \"2.0\"\n                self.requires(f\"myqemu/{version}\", visible=False, no_skip=True)\n\n            def package(self):\n                c = f'call \"%1/myqemu.bat\"' if platform.system() == \"Windows\" else f'\"$1/myqemu.sh\"'\n                echo = f\"@echo off\\necho RUNNING {self.name}/{self.version}!!\\n{c}\"\n                save(self, os.path.join(self.package_folder, \"bin\", f\"{self.name}.bat\"), echo)\n                save(self, os.path.join(self.package_folder, \"bin\", f\"{self.name}\"), echo)\n                os.chmod(os.path.join(self.package_folder, \"bin\", f\"{self.name}\"), 0o777)\n\n            def package_info(self):\n                pf = self.dependencies[\"myqemu\"].cpp_info.bindir.replace(\"\\\\\", \"/\")\n                self.conf_info.define_path(f\"user.myorg:{self.name}_qemu\", pf)\n            \"\"\")\n    consumer = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Pkg(ConanFile):\n            name = \"consumer\"\n            version = \"1.0\"\n            def build_requirements(self):\n                self.tool_requires(\"snippy/1.0\")\n                self.tool_requires(\"valgrind/1.0\")\n            def build(self):\n                qemu_snippy = self.conf.get(\"user.myorg:snippy_qemu\")\n                qemu_valgrind = self.conf.get(\"user.myorg:valgrind_qemu\")\n                self.run(f\"valgrind {qemu_valgrind}\")\n                self.run(f'snippy {qemu_snippy}')\n        \"\"\")\n\n    c.save({\"qemu/conanfile.py\": qemu,\n            \"tool/conanfile.py\": mytool,\n            \"consumer/conanfile.py\": consumer})\n\n    c.run(\"create qemu --version=1.0\")\n    c.run(\"create qemu --version=2.0\")\n    c.run(\"create tool --name=snippy\")\n    c.run(\"create tool --name=valgrind\")\n    c.run(\"build consumer\")\n    assert \"RUNNING valgrind/1.0!!\" in c.out\n    assert \"RUNNING myqemu/2.0!!\" in c.out\n    assert \"RUNNING snippy/1.0!!\" in c.out\n    assert \"RUNNING myqemu/1.0!!\" in c.out\n\n    c.run(\"upload * -r=default -c\")\n    # The \"tools.graph:skip_binaries\" shouldn't affect the result, it is never skipped\n    for skip in (\"-c tools.graph:skip_binaries=True\", \"-c tools.graph:skip_binaries=False\", \"\"):\n        c.run(\"remove * -c\")\n        # Re-downloads and it works\n        c.run(f\"build consumer {skip}\")\n        assert \"RUNNING valgrind/1.0!!\" in c.out\n        assert \"RUNNING myqemu/2.0!!\" in c.out\n        assert \"RUNNING snippy/1.0!!\" in c.out\n        assert \"RUNNING myqemu/1.0!!\" in c.out\n\n    c.run(\"create consumer\")\n    c.run(\"upload consumer/1.0 -r=default -c\")\n    c.run(\"remove * -c\")\n    c.run(\"install --requires=consumer/1.0\")\n    assert re.search(r\"Skipped binaries(\\s*)myqemu/1.0, myqemu/2.0, snippy/1.0, valgrind/1.0\", c.out)\n\n\nclass TestTransitiveBuild:\n    # project --(tool-requires)--> wrapper_a -(requires)-> gcc/X\n    #     \\-----(tool-requires)--> wrapper_b -(requires)-> gcc/Y\n    gcc = textwrap.dedent(r\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import save\n        class Pkg(ConanFile):\n            name = \"gcc\"\n            package_type = \"application\"\n            def package(self):\n                echo = f\"@echo off\\necho MYGCC={self.version}!!\"\n                save(self, os.path.join(self.package_folder, \"bin\", \"mygcc.bat\"), echo)\n                save(self, os.path.join(self.package_folder, \"bin\", \"mygcc.sh\"), echo)\n                os.chmod(os.path.join(self.package_folder, \"bin\", \"mygcc.sh\"), 0o777)\n            \"\"\")\n\n    project = textwrap.dedent(\"\"\"\n        import platform\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            def build_requirements(self):\n                self.tool_requires(\"wrappera/1.0\")\n                self.tool_requires(\"wrapperb/1.0\")\n            def build(self):\n                ext = \"bat\" if platform.system() == \"Windows\" else \"sh\"\n            \"\"\")\n\n    def test_require_different_versions_transitive_noconflict(self):\n        \"\"\" Same dependency to gcc/1.0, no conflict\n        \"\"\"\n        c = TestClient()\n        project = r\"self.run(f'mygcc.{ext}')\"\n        c.save({\"gcc/conanfile.py\": self.gcc,\n                \"wrappera/conanfile.py\": GenConanfile(\"wrappera\", \"1.0\").with_requires(\"gcc/1.0\"),\n                \"wrapperb/conanfile.py\": GenConanfile(\"wrapperb\", \"1.0\").with_requires(\"gcc/1.0\"),\n                \"project/conanfile.py\": self.project + textwrap.indent(project, \"        \")})\n\n        c.run(\"create gcc --version=1.0\")\n        c.run(\"create wrappera\")\n        c.run(\"create wrapperb\")\n\n        c.run(\"build project\")\n        assert \"MYGCC=1.0!!\" in c.out\n\n    def test_require_different_versions_transitive_conflict(self):\n        c = TestClient()\n        project = textwrap.dedent(r\"\"\"\n            self.run(f'wrappera.{ext}')\n            self.run(f'wrapperb.{ext}')\n            \"\"\")\n        c.save({\"gcc/conanfile.py\": self.gcc,\n                \"wrappera/conanfile.py\": GenConanfile(\"wrappera\", \"1.0\").with_requires(\"gcc/1.0\"),\n                \"wrapperb/conanfile.py\": GenConanfile(\"wrapperb\", \"1.0\").with_requires(\"gcc/2.0\"),\n                \"project/conanfile.py\": self.project + textwrap.indent(project, \"        \")})\n\n        c.run(\"create gcc --version=1.0\")\n        c.run(\"create gcc --version=2.0\")\n        c.run(\"create wrappera\")\n        c.run(\"create wrapperb\")\n        c.run(\"install project\", assert_error=True)\n        assert \"Version conflict: Conflict between gcc/2.0 and gcc/1.0 in the graph\" in c.out\n\n        # disabling ``run=False`` trait\n        c.save({\"wrapa/conanfile.py\": GenConanfile(\"wrappera\", \"1.0\").with_requirement(\"gcc/1.0\",\n                                                                                       run=False),\n                \"wrapb/conanfile.py\": GenConanfile(\"wrapperb\", \"1.0\").with_requirement(\"gcc/2.0\",\n                                                                                       run=False)})\n        c.run(\"create wrapa\")\n        c.run(\"create wrapb\")\n        c.run(\"install project\")  # Now it works!\n\n        # If the run is not propagated, the consumer must do it explicitly to differentiate:\n        project = textwrap.dedent(r\"\"\"\n            import os, platform\n            from conan import ConanFile\n            from conan.tools.files import save, chdir\n            class Pkg(ConanFile):\n                name = \"project\"\n                version = \"1.0\"\n                def build_requirements(self):\n                    self.tool_requires(\"wrappera/1.0\")\n                    self.tool_requires(\"wrapperb/1.0\")\n                    self.tool_requires(\"gcc/1.0\", run=False)\n                    self.tool_requires(\"gcc/2.0\", run=False)\n                def build(self):\n                    ext = \"bat\" if platform.system() == \"Windows\" else \"sh\"\n                    path_a = self.dependencies.build[\"gcc/1.0\"].cpp_info.bindir\n                    path_b = self.dependencies.build[\"gcc/2.0\"].cpp_info.bindir\n                    self.run(f'\"{path_a}/mygcc.{ext}\"')\n                    self.run(f'\"{path_b}/mygcc.{ext}\"')\n            \"\"\")\n        c.save({\"project/conanfile.py\": project})\n        c.run(\"build project\")\n        assert \"MYGCC=1.0!!\" in c.out\n        assert \"MYGCC=2.0!!\" in c.out\n\n    def test_require_different_versions_transitive_vendored(self):\n        c = TestClient()\n        wrapper = textwrap.dedent(r\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.files import save, copy\n            class Pkg(ConanFile):\n                name = \"{name}\"\n                version = \"1.0\"\n                package_type = \"application\"\n\n                def requirements(self):\n                    self.requires(\"gcc/{gcc_version}\", visible=False, run=False)\n\n                def package(self):\n                    copy(self, \"*\", src=self.dependencies[\"gcc\"].cpp_info.bindir,\n                         dst=os.path.join(self.package_folder, \"bin\"))\n                    echo_bat = f'@echo off\\necho {name}={{self.version}}!!\\ncall \"%~dp0/mygcc.bat\"'\n                    # Trick for cwd in Linux\n                    echo_sh = '@echo off\\necho {name}=1.0!!\\n\"${{0%/*}}/mygcc.sh\\\"'\n                    save(self, os.path.join(self.package_folder, \"bin\", \"{name}.bat\"), echo_bat)\n                    save(self, os.path.join(self.package_folder, \"bin\", \"{name}.sh\"), echo_sh)\n                    os.chmod(os.path.join(self.package_folder, \"bin\", \"{name}.sh\"), 0o777)\n            \"\"\")\n\n        project = textwrap.dedent(r\"\"\"\n            self.run(f'wrappera.{ext}')\n            self.run(f'wrapperb.{ext}')\n            \"\"\")\n        c.save({\"gcc/conanfile.py\": self.gcc,\n                \"wrappera/conanfile.py\": wrapper.format(name=\"wrappera\", gcc_version=\"1.0\"),\n                \"wrapperb/conanfile.py\": wrapper.format(name=\"wrapperb\", gcc_version=\"2.0\"),\n                \"project/conanfile.py\": self.project + textwrap.indent(project, \"        \")})\n\n        c.run(\"create gcc --version=1.0\")\n        c.run(\"create gcc --version=2.0\")\n        c.run(\"create wrappera\")\n        c.run(\"create wrapperb\")\n        c.run(\"build project\")\n        assert \"wrappera=1.0!!\" in c.out\n        assert \"MYGCC=1.0!!\" in c.out\n        assert \"wrapperb=1.0!!\" in c.out\n        assert \"MYGCC=2.0!!\" in c.out\n"
  },
  {
    "path": "test/integration/graph/test_skip_binaries.py",
    "content": "import re\nimport textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient, NO_SETTINGS_PACKAGE_ID\n\n\ndef test_private_skip():\n    # app -> pkg -(private)-> dep\n    client = TestClient(light=True)\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"create . --name=dep --version=1.0\")\n    client.save({\"conanfile.py\": GenConanfile().with_requirement(\"dep/1.0\", visible=False)})\n    client.run(\"create . --name=pkg --version=1.0\")\n    client.run(\"remove dep/1.0:* -c\")  # Dep binary is removed not used at all\n\n    client.save({\"conanfile.py\": GenConanfile().with_requires(\"pkg/1.0\")})\n    client.run(\"create . --name=app --version=1.0 -v\")\n    client.assert_listed_binary({\"dep/1.0\": (NO_SETTINGS_PACKAGE_ID, \"Skip\")})\n\n\ndef test_private_no_skip():\n    # app -> pkg -(private)-> dep\n    client = TestClient(light=True)\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"create . --name=dep --version=1.0\")\n    client.save({\"conanfile.py\": GenConanfile().with_requirement(\"dep/1.0\", visible=False)})\n    client.run(\"create . --name=pkg --version=1.0\")\n\n    # But if we want to build pkg, no skip\n    client.run(\"create . --name=app --version=1.0 --build=app/* --build=pkg/*\")\n    client.assert_listed_binary({\"dep/1.0\": (NO_SETTINGS_PACKAGE_ID, \"Cache\")})\n\n    client.run(\"remove dep/1.0:* -c\")  # Dep binary is removed not used at all\n    client.run(\"create . --name=app --version=1.0 --build=app/* --build=pkg/*\", assert_error=True)\n    client.assert_listed_binary({\"dep/1.0\": (NO_SETTINGS_PACKAGE_ID, \"Missing\")})\n\n\ndef test_consumer_no_skip():\n    # app -(private)-> pkg -> dep\n    client = TestClient(light=True)\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"create . --name=dep --version=1.0\")\n    client.save({\"conanfile.py\": GenConanfile().with_requires(\"dep/1.0\")})\n    client.run(\"create . --name=pkg --version=1.0\")\n    package_id = client.created_package_id(\"pkg/1.0\")\n    client.save({\"conanfile.py\": GenConanfile().with_requirement(\"pkg/1.0\", visible=False)})\n\n    client.run(\"install . \")\n\n    client.assert_listed_binary({f\"dep/1.0\": (NO_SETTINGS_PACKAGE_ID, \"Cache\")})\n    client.assert_listed_binary({f\"pkg/1.0\": (package_id, \"Cache\")})\n\n\ndef test_shared_link_static_skip():\n    # app -> pkg (shared) -> dep (static)\n    client = TestClient(light=True)\n    client.save({\"conanfile.py\": GenConanfile().with_shared_option(False)})\n    client.run(\"create . --name=dep --version=1.0\")\n    package_id = client.created_package_id(\"dep/1.0\")\n    client.save({\"conanfile.py\": GenConanfile().with_requirement(\"dep/1.0\").\n                with_shared_option(True)})\n    client.run(\"create . --name=pkg --version=1.0\")\n    client.run(\"remove dep/1.0:* -c\")  # Dep binary is removed not used at all\n\n    client.save({\"conanfile.py\": GenConanfile().with_requires(\"pkg/1.0\")})\n    client.run(\"create . --name=app --version=1.0 -v\")\n    client.assert_listed_binary({\"dep/1.0\": (package_id, \"Skip\")})\n\n\ndef test_test_requires():\n    # Using a test_requires can be skipped if it is not necessary to build its consumer\n    # app -> pkg (static) -(test_requires)-> gtest (static)\n    client = TestClient(light=True)\n    client.save({\"conanfile.py\": GenConanfile().with_shared_option(False)})\n    client.run(\"create . --name=gtest --version=1.0\")\n    package_id = client.created_package_id(\"gtest/1.0\")\n    client.save({\"conanfile.py\": GenConanfile().with_test_requires(\"gtest/1.0\").\n                with_shared_option(False)})\n    client.run(\"create . --name=pkg --version=1.0\")\n    client.run(\"remove gtest/1.0:* -c\")  # Dep binary is removed not used at all\n\n    client.save({\"conanfile.py\": GenConanfile().with_requires(\"pkg/1.0\")})\n    # Checking list of skipped binaries\n    client.run(\"create . --name=app --version=1.0\")\n    assert re.search(r\"Skipped binaries(\\s*)gtest/1.0\", client.out)\n    # Showing the complete information about the skipped binary\n    client.run(\"create . --name=app --version=1.0 -v\")\n    client.assert_listed_binary({\"gtest/1.0\": (package_id, \"Skip\")}, test=True)\n\n\ndef test_build_scripts_no_skip():\n    c = TestClient(light=True)\n    c.save({\"scripts/conanfile.py\": GenConanfile(\"script\", \"0.1\").with_package_type(\"build-scripts\"),\n            \"app/conanfile.py\": GenConanfile().with_tool_requires(\"script/0.1\")})\n    c.run(\"create scripts\")\n    c.assert_listed_binary({\"script/0.1\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\", \"Build\")},\n                           build=True)\n    c.run(\"install app\")\n    c.assert_listed_binary({\"script/0.1\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\", \"Cache\")},\n                           build=True)\n\n\ndef test_list_skip_printing():\n    \"\"\" make sure that when a package is required in the graph, it is not marked as SKIP, just\n    because some other part of the graph is skipping it. In this case, a tool_require might be\n    necessary for some packages building from soures, but not for others\n    \"\"\"\n    c = TestClient(light=True)\n    c.save({\"tool/conanfile.py\": GenConanfile(\"tool\", \"0.1\"),\n            \"pkga/conanfile.py\": GenConanfile(\"pkga\", \"0.1\").with_tool_requires(\"tool/0.1\"),\n            \"pkgb/conanfile.py\": GenConanfile(\"pkgb\", \"0.1\").with_requires(\"pkga/0.1\")\n                                                            .with_tool_requires(\"tool/0.1\"),\n            \"app/conanfile.py\": GenConanfile().with_requires(\"pkgb/0.1\")})\n    c.run(\"create tool\")\n    c.run(\"create pkga\")\n    c.run(\"create pkgb\")\n    c.run(\"remove pkga:* -c\")\n    c.run(\"install app --build=missing\")\n    c.assert_listed_binary({\"tool/0.1\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\", \"Cache\")},\n                           build=True)\n\n\ndef test_conf_skip():\n    client = TestClient(light=True)\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"create . --name=maths --version=1.0\")\n    client.run(\"create . --name=ai --version=1.0\")\n\n    client.save({\"conanfile.py\": GenConanfile().with_requirement(\"maths/1.0\", visible=False)})\n    client.run(\"create . --name=liba --version=1.0\")\n    client.save({\"conanfile.py\": GenConanfile().with_requirement(\"ai/1.0\", visible=False)})\n    client.run(\"create . --name=libb --version=1.0\")\n\n    client.save({\"conanfile.py\": GenConanfile().with_requires(\"liba/1.0\", \"libb/1.0\")})\n    client.run(\"create . --name=app --version=0.0 -v\")\n    client.assert_listed_binary({\"maths/1.0\": (NO_SETTINGS_PACKAGE_ID, \"Skip\")})\n    client.assert_listed_binary({\"ai/1.0\": (NO_SETTINGS_PACKAGE_ID, \"Skip\")})\n\n    client.run(\"create . --name=app --version=1.0 -v -c *:tools.graph:skip_binaries=False\")\n    client.assert_listed_binary({\"maths/1.0\": (NO_SETTINGS_PACKAGE_ID, \"Cache\")})\n    client.assert_listed_binary({\"ai/1.0\": (NO_SETTINGS_PACKAGE_ID, \"Cache\")})\n\n    client.run(\"create . --name=app --version=2.0 -v -c maths/*:tools.graph:skip_binaries=False\")\n    client.assert_listed_binary({\"maths/1.0\": (NO_SETTINGS_PACKAGE_ID, \"Cache\")})\n    client.assert_listed_binary({\"ai/1.0\": (NO_SETTINGS_PACKAGE_ID, \"Skip\")})\n\n    client.run(\"create . --name=app --version=3.0 -v -c *:tools.graph:skip_binaries=True\")\n    client.assert_listed_binary({\"maths/1.0\": (NO_SETTINGS_PACKAGE_ID, \"Skip\")})\n    client.assert_listed_binary({\"ai/1.0\": (NO_SETTINGS_PACKAGE_ID, \"Skip\")})\n\n\ndef test_skipped_intermediate_header():\n    # app -> libc/0.1 (static) -> libb0.1 (header) -> liba0.1 (static)\n    # This libb0.1 cannot be skipped because it is necessary its lib-config.cmake for transitivity\n    c = TestClient()\n    c.save({\"liba/conanfile.py\": GenConanfile(\"liba\", \"0.1\").with_package_type(\"static-library\")\n                                                            .with_package_info(cpp_info={\"libs\":\n                                                                                         [\"liba\"]}),\n            \"libb/conanfile.py\": GenConanfile(\"libb\", \"0.1\").with_package_type(\"header-library\")\n                                                            .with_requires(\"liba/0.1\"),\n            \"libc/conanfile.py\": GenConanfile(\"libc\", \"0.1\").with_package_type(\"static-library\")\n                                                            .with_requires(\"libb/0.1\"),\n            \"app/conanfile.py\": GenConanfile(\"app\", \"0.1\").with_requires(\"libc/0.1\")\n                                                          .with_settings(\"build_type\")})\n    c.run(\"create liba\")\n    c.run(\"create libb\")\n    c.run(\"create libc\")\n    c.run(\"install app -g CMakeDeps\")\n    c.assert_listed_binary({\"liba/0.1\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\", \"Cache\"),\n                            \"libb/0.1\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\", \"Cache\"),\n                            \"libc/0.1\": (\"0f9f8919daed27aacd18c33199957e8882a87fd7\", \"Cache\")})\n    libc_data = c.load(\"app/libc-release-data.cmake\")\n    assert \"list(APPEND libc_FIND_DEPENDENCY_NAMES libb)\" in libc_data\n    libb_data = c.load(\"app/libb-release-data.cmake\")\n    # libb brings no headers nor libraries\n    assert \"set(libb_INCLUDE_DIRS_RELEASE )\" in libb_data\n    assert \"set(libb_LIBS_RELEASE )\" in libb_data\n    liba_data = c.load(\"app/liba-release-data.cmake\")\n    # liba brings only libraries\n    assert \"set(liba_INCLUDE_DIRS_RELEASE )\" in liba_data\n    assert \"set(liba_LIBS_RELEASE liba)\" in liba_data\n\n\ndef test_skip_visible_build():\n    # https://github.com/conan-io/conan/issues/15346\n    c = TestClient(light=True)\n    c.save({\"liba/conanfile.py\": GenConanfile(\"liba\", \"0.1\"),\n            \"libb/conanfile.py\": GenConanfile(\"libb\", \"0.1\").with_requirement(\"liba/0.1\",\n                                                                              build=True),\n            \"libc/conanfile.py\": GenConanfile(\"libc\", \"0.1\").with_requirement(\"libb/0.1\",\n                                                                              visible=False),\n            \"app/conanfile.py\": GenConanfile(\"app\", \"0.1\").with_requires(\"libc/0.1\")})\n    c.run(\"create liba\")\n    c.run(\"create libb\")\n    c.run(\"create libc\")\n    c.run(\"install app --format=json\")\n    assert re.search(r\"Skipped binaries(\\s*)libb/0.1, liba/0.1\", c.out)\n\n\ndef test_skip_tool_requires_context():\n    c = TestClient()\n    cmake = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class CMake(ConanFile):\n            name = \"cmake\"\n            version = \"1.0\"\n            def package_info(self):\n                self.buildenv_info.define(\"MYVAR\", \"MYVALUE\")\n            \"\"\")\n    gtest = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import load\n        class gtest(ConanFile):\n            name = \"gtest\"\n            version = \"1.0\"\n            settings = \"os\"\n            package_type = \"static-library\"\n            def build(self):\n                env = load(self, \"conanbuildenv.sh\")\n                self.output.info(f\"MYENV: {env}\")\n        \"\"\")\n    c.save({\"cmake/conanfile.py\": cmake,\n            \"gtest/conanfile.py\": gtest,\n            \"lib/conanfile.py\": GenConanfile(\"lib\", \"1.0\").with_package_type(\"static-library\")\n                                                          .with_test_requires(\"gtest/1.0\"),\n            \"app/conanfile.py\": GenConanfile(\"app\", \"1.0\").with_settings(\"os\")\n                                                          .with_requires(\"lib/1.0\"),\n            \"profile\": \"[tool_requires]\\ncmake/[>=1.0]\"})\n\n    c.run(\"create cmake\")\n    c.run(\"create gtest -s:a os=Linux\")\n    c.run(\"create lib -s:a os=Linux\")\n\n    c.run(\"remove gtest:* -c\")\n    c.run(\"install app -s:a os=Linux -pr=profile -c=tools.graph:skip_binaries=False --build=missing\")\n    assert 'export MYVAR=\"MYVALUE\"' in c.out\n    assert \"gtest/1.0: Package '9a4eb3c8701508aa9458b1a73d0633783ecc2270' built\" in c.out\n\n\ndef test_skip_intermediate_header():\n    # https://github.com/conan-io/conan/issues/16402\n    # Libb cannot be skipped in any case, because there is a link order libc->liba necessary\n    # app -> libc/0.1 (static) -> libb0.1 (header) -> liba0.1 (static)\n    #  \\------------------------------------------------/\n    # libb\n    c = TestClient(light=True)\n    c.save({\"liba/conanfile.py\": GenConanfile(\"liba\", \"0.1\").with_package_type(\"static-library\"),\n            \"libb/conanfile.py\": GenConanfile(\"libb\", \"0.1\").with_requirement(\"liba/0.1\")\n                                                            .with_package_type(\"header-library\"),\n            \"libc/conanfile.py\": GenConanfile(\"libc\", \"0.1\").with_requirement(\"libb/0.1\")\n                                                            .with_package_type(\"static-library\"),\n            \"app/conanfile.py\": GenConanfile(\"app\", \"0.1\").with_package_type(\"application\")\n                                                          .with_requires(\"libc/0.1\", \"liba/0.1\")})\n    c.run(\"create liba\")\n    c.run(\"create libb\")\n    c.run(\"create libc\")\n    c.run(\"install app\")\n    assert \"Skipped binaries\" not in c.out\n    assert \"libb/0.1: Already installed!\" in c.out\n    assert \"liba/0.1: Already installed!\" in c.out\n    assert \"libc/0.1: Already installed!\" in c.out\n\n\ndef test_skip_intermediate_static():\n    # https://github.com/conan-io/conan/issues/16402\n    # In this case, libb can be completely skipped, because there is no linkage relationship at all\n    # app -> libc/0.1 (shared) -> libb0.1 (static) -> liba0.1 (static)\n    #  \\------------------------------------------------/\n    # libb\n    c = TestClient(light=True)\n    c.save({\"liba/conanfile.py\": GenConanfile(\"liba\", \"0.1\").with_package_type(\"static-library\"),\n            \"libb/conanfile.py\": GenConanfile(\"libb\", \"0.1\").with_requirement(\"liba/0.1\")\n                                                            .with_package_type(\"static-library\"),\n            \"libc/conanfile.py\": GenConanfile(\"libc\", \"0.1\").with_requirement(\"libb/0.1\")\n                                                            .with_package_type(\"shared-library\"),\n            \"app/conanfile.py\": GenConanfile(\"app\", \"0.1\").with_package_type(\"application\")\n                                                          .with_requires(\"libc/0.1\", \"liba/0.1\")})\n    c.run(\"create liba\")\n    c.run(\"create libb\")\n    c.run(\"create libc\")\n    c.run(\"remove libb:* -c\")  # binary not necessary, can be skipped\n    c.run(\"install app\")\n    assert re.search(r\"Skipped binaries(\\s*)libb/0.1\", c.out)\n    assert \"libb/0.1: Already installed!\" not in c.out\n    assert \"liba/0.1: Already installed!\" in c.out\n    assert \"libc/0.1: Already installed!\" in c.out\n\n\ndef test_skip_intermediate_static_complex():\n    # https://github.com/conan-io/conan/issues/16402\n    #  /----- libh(static)--libi(header)---libj(header)----------\\\n    # app -> libe(shared)->libd(static) -> libc(static) -> libb(static) -> liba(static)\n    #  \\---------libf(static) --libg(header)---------------------------------/\n    # libd and libc can be skipped\n    c = TestClient(light=True)\n    c.save({\"liba/conanfile.py\": GenConanfile(\"liba\", \"0.1\").with_package_type(\"static-library\"),\n            \"libb/conanfile.py\": GenConanfile(\"libb\", \"0.1\").with_requirement(\"liba/0.1\")\n                                                            .with_package_type(\"static-library\"),\n            \"libc/conanfile.py\": GenConanfile(\"libc\", \"0.1\").with_requirement(\"libb/0.1\")\n                                                            .with_package_type(\"static-library\"),\n            \"libd/conanfile.py\": GenConanfile(\"libd\", \"0.1\").with_requirement(\"libc/0.1\")\n                                                            .with_package_type(\"static-library\"),\n            \"libe/conanfile.py\": GenConanfile(\"libe\", \"0.1\").with_requirement(\"libd/0.1\")\n                                                            .with_package_type(\"shared-library\"),\n            \"libg/conanfile.py\": GenConanfile(\"libg\", \"0.1\").with_requirement(\"liba/0.1\")\n                                                            .with_package_type(\"header-library\"),\n            \"libf/conanfile.py\": GenConanfile(\"libf\", \"0.1\").with_requirement(\"libg/0.1\")\n                                                            .with_package_type(\"static-library\"),\n            \"libj/conanfile.py\": GenConanfile(\"libj\", \"0.1\").with_requirement(\"libb/0.1\")\n                                                            .with_package_type(\"header-library\"),\n            \"libi/conanfile.py\": GenConanfile(\"libi\", \"0.1\").with_requirement(\"libj/0.1\")\n                                                            .with_package_type(\"header-library\"),\n            \"libh/conanfile.py\": GenConanfile(\"libh\", \"0.1\").with_requirement(\"libi/0.1\")\n                                                            .with_package_type(\"static-library\"),\n            \"app/conanfile.py\": GenConanfile(\"app\", \"0.1\").with_package_type(\"application\")\n                                                          .with_requires(\"libh/0.1\", \"libe/0.1\",\n                                                                         \"libf/0.1\")\n            })\n    for lib in (\"a\", \"b\", \"c\", \"d\", \"e\", \"j\", \"i\", \"h\", \"g\", \"f\"):\n        c.run(f\"create lib{lib}\")\n\n    c.run(\"remove libd:* -c\")  # binary not necessary, can be skipped\n    c.run(\"remove libc:* -c\")  # binary not necessary, can be skipped\n    c.run(\"install app\")\n    assert re.search(r\"Skipped binaries(\\s*)libc/0.1, libd/0.1\", c.out)\n    assert \"libd/0.1: Already installed!\" not in c.out\n    assert \"libc/0.1: Already installed!\" not in c.out\n    for lib in (\"a\", \"b\", \"e\", \"f\", \"g\", \"h\", \"i\", \"j\"):\n        assert f\"lib{lib}/0.1: Already installed!\" in c.out\n    for lib in (\"c\", \"d\"):\n        assert f\"lib{lib}/0.1: Already installed!\" not in c.out\n"
  },
  {
    "path": "test/integration/graph/test_skip_build.py",
    "content": "import re\nimport textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_graph_skip_build_test():\n    # app -> pkg -(test)-> gtest\n    #         \\---(tool)-> cmake\n    c = TestClient(light=True)\n    pkg = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"1.0\"\n            test_requires = \"gtest/1.0\"\n            tool_requires = \"cmake/1.0\"\n        \"\"\")\n    c.save({\"gtest/conanfile.py\": GenConanfile(\"gtest\", \"1.0\"),\n            \"cmake/conanfile.py\": GenConanfile(\"cmake\", \"1.0\"),\n            \"pkg/conanfile.py\": pkg,\n            \"app/conanfile.py\": GenConanfile(\"app\", \"1.0\").with_requires(\"pkg/1.0\")})\n    c.run(\"create gtest\")\n    c.run(\"create cmake\")\n    c.run(\"create pkg\")\n    c.run(\"create app -c tools.graph:skip_build=True -c tools.graph:skip_test=True\")\n    assert \"cmake\" not in c.out\n    assert \"gtest\" not in c.out\n    c.run(\"create app -c tools.graph:skip_test=True\")\n    assert \"WARN: experimental: Usage of 'tools.graph:skip_test'\" in c.out\n    assert \"WARN: tools.graph:skip_test set, but tools.build:skip_test is not\" in c.out\n    assert \"cmake\" in c.out\n    assert \"gtest\" not in c.out\n    c.run(\"create app -c tools.graph:skip_build=True\")\n    assert \"cmake\" not in c.out\n    assert \"gtest\" in c.out\n\n    c.run(\"install app\")\n    assert \"cmake\" in c.out\n    assert \"gtest\" in c.out\n\n    c.run(\"install app -c tools.graph:skip_build=True -c tools.graph:skip_test=True\")\n    assert \"cmake\" not in c.out\n    assert \"gtest\" not in c.out\n\n    c.run(\"install app -c tools.graph:skip_build=True --build=pkg/*\", assert_error=True)\n    assert \"ERROR: Package pkg/1.0 skipped its test/tool requires with tools.graph:skip_build, \" \\\n           \"but was marked to be built \" in c.out\n\n\ndef test_skip():\n    # https://github.com/conan-io/conan/issues/13439\n    c = TestClient()\n    global_conf = textwrap.dedent(\"\"\"\n        tools.graph:skip_test=True\n        tools.build:skip_test=True\n        \"\"\")\n    c.save_home({\"global.conf\": global_conf})\n    c.save({\"pkga/conanfile.py\": GenConanfile(\"pkga\", \"1.0.0\"),\n            \"pkgb/conanfile.py\": GenConanfile(\"pkgb\", \"1.0.0\").with_test_requires(\"pkga/1.0.0\"),\n            \"pkgc/conanfile.py\": GenConanfile(\"pkgc\", \"1.0.0\").with_test_requires(\"pkgb/1.0.0\")})\n    c.run(\"create pkga\")\n    c.run(\"create pkgb\")\n\n    # Always skipped\n    c.run(\"install pkgc\")\n    # correct, pkga and pkgb are not in the output at all, they have been skipped\n    assert \"pkga\" not in c.out\n    assert \"pkgb\" not in c.out\n\n    # not skipping test-requires\n    c.run(\"install pkgc -c tools.graph:skip_test=False\")\n    # correct, pkga and pkgb are not skipped now\n    assert \"pkga\" in c.out\n    assert \"pkgb\" in c.out\n    # but pkga binary is not really necessary\n    assert re.search(r\"Skipped binaries(\\s*)pkga/1.0.0\", c.out)\n\n    # skipping all but the current one\n    c.run(\"install pkgc -c &:tools.graph:skip_test=False\")\n    # correct, only pkga  is skipped now\n    assert \"pkga\" not in c.out\n    assert \"pkgb\" in c.out\n"
  },
  {
    "path": "test/integration/graph/test_subgraph_reports.py",
    "content": "import json\nimport os\nimport textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\nfrom conan.api.model import RecipeReference\nfrom conan.internal.util.files import load\n\n\ndef _metadata(c, ref):\n    pref = c.get_latest_package_reference(RecipeReference.loads(ref))\n    return c.get_latest_pkg_layout(pref).metadata()\n\n\ndef test_subgraph_reports():\n    c = TestClient()\n    subgraph_hook = textwrap.dedent(\"\"\"\\\n        import os, json\n        from conan.tools.files import save\n        from conan.internal.model.lockfile import Lockfile\n        def post_package(conanfile):\n            subgraph = conanfile.subgraph\n            save(conanfile, os.path.join(conanfile.package_metadata_folder, f\"conangraph.json\"),\n                 json.dumps(subgraph.serialize(), indent=2))\n            save(conanfile, os.path.join(conanfile.package_metadata_folder, f\"conan.lock\"),\n                 Lockfile(subgraph).dumps())\n        \"\"\")\n\n    c.save_home({\"extensions/hooks/subgraph_hook/hook_subgraph.py\": subgraph_hook})\n    c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\"),\n            \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_requirement(\"dep/0.1\"),\n            \"app/conanfile.py\": GenConanfile(\"app\", \"0.1\").with_requirement(\"pkg/0.1\")})\n    c.run(\"export dep\")\n    c.run(\"export pkg\")\n    # app -> pkg -> dep\n    c.run(\"create app --build=missing --format=json\")\n\n    app_graph = json.loads(load(os.path.join(_metadata(c, \"app/0.1\"), \"conangraph.json\")))\n    pkg_graph = json.loads(load(os.path.join(_metadata(c, \"pkg/0.1\"), \"conangraph.json\")))\n    dep_graph = json.loads(load(os.path.join(_metadata(c, \"dep/0.1\"), \"conangraph.json\")))\n\n    app_lock = json.loads(load(os.path.join(_metadata(c, \"app/0.1\"), \"conan.lock\")))\n    pkg_lock = json.loads(load(os.path.join(_metadata(c, \"pkg/0.1\"), \"conan.lock\")))\n    dep_lock = json.loads(load(os.path.join(_metadata(c, \"dep/0.1\"), \"conan.lock\")))\n\n    assert len(app_graph[\"nodes\"]) == len(app_lock[\"requires\"])\n    assert len(pkg_graph[\"nodes\"]) == len(pkg_lock[\"requires\"])\n    assert len(dep_graph[\"nodes\"]) == len(dep_lock[\"requires\"])\n"
  },
  {
    "path": "test/integration/graph/test_system_tools.py",
    "content": "import json\nimport os\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestToolRequires:\n    @pytest.mark.parametrize(\"revision\", [\"\", \"#myrev\"])\n    def test_system_tool_require(self, revision):\n        client = TestClient(light=True)\n        client.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_tool_requires(\"tool/1.0\"),\n                     \"profile\": f\"[platform_tool_requires]\\ntool/1.0{revision}\"})\n        client.run(\"create . -pr=profile\")\n        assert f\"tool/1.0{revision or '#platform'} - Platform\" in client.out\n\n    def test_system_tool_require_non_matching(self):\n        \"\"\" if what is specified in [system_tool_require] doesn't match what the recipe requires, then\n        the system_tool_require will not be used, and the recipe will use its declared version\n        \"\"\"\n        client = TestClient(light=True)\n        client.save({\"tool/conanfile.py\": GenConanfile(\"tool\", \"1.0\"),\n                     \"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_tool_requires(\"tool/1.0\"),\n                     \"profile\": \"[system_tools]\\ntool/1.1\"})\n        client.run(\"create tool\")\n        client.run(\"create . -pr=profile\")\n        assert \"WARN: Profile [system_tools] is deprecated\" in client.out\n        assert \"tool/1.0#60ed6e65eae112df86da7f6d790887fd - Cache\" in client.out\n\n    @pytest.mark.parametrize(\"revision\", [\"\", \"#myrev\"])\n    def test_system_tool_require_range(self, revision):\n        client = TestClient(light=True)\n        client.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_tool_requires(\"tool/[>=1.0]\"),\n                     \"profile\": f\"[platform_tool_requires]\\ntool/1.1{revision}\"})\n        client.run(\"create . -pr=profile\")\n        assert f\"tool/1.1{revision or '#platform'} - Platform\" in client.out\n\n    def test_system_tool_require_range_non_matching(self):\n        \"\"\" if what is specified in [system_tool_require] doesn't match what the recipe requires, then\n        the system_tool_require will not be used, and the recipe will use its declared version\n        \"\"\"\n        client = TestClient(light=True)\n        client.save({\"tool/conanfile.py\": GenConanfile(\"tool\", \"1.1\"),\n                     \"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_tool_requires(\"tool/[>=1.0]\"),\n                     \"profile\": \"[platform_tool_requires]\\ntool/0.1\"})\n        client.run(\"create tool\")\n        client.run(\"create . -pr=profile\")\n        assert \"tool/1.1#888bda2348dd2ddcf5960d0af63b08f7 - Cache\" in client.out\n\n    def test_system_tool_require_no_host(self):\n        \"\"\"\n        system_tools must not affect host context\n        \"\"\"\n        client = TestClient(light=True)\n        client.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_requires(\"tool/1.0\"),\n                     \"profile\": \"[platform_tool_requires]\\ntool/1.0\"})\n        client.run(\"create . -pr=profile\", assert_error=True)\n        assert \"ERROR: Package 'tool/1.0' not resolved: No remote defined\" in client.out\n\n    def test_graph_info_system_tool_require_range(self):\n        \"\"\"\n        graph info doesn't crash\n        \"\"\"\n        client = TestClient(light=True)\n        client.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_tool_requires(\"tool/[>=1.0]\"),\n                     \"profile\": \"[platform_tool_requires]\\ntool/1.1\"})\n        client.run(\"graph info . -pr=profile\")\n        assert \"tool/1.1 - Platform\" in client.out\n\n    def test_consumer_resolved_version(self):\n        client = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                tool_requires = \"tool/[>=1.0]\"\n\n                def generate(self):\n                    for r, _ in self.dependencies.items():\n                        self.output.info(f\"DEPENDENCY {r.ref}\")\n                \"\"\")\n        client.save({\"conanfile.py\": conanfile,\n                     \"profile\": \"[platform_tool_requires]\\ntool/1.1\"})\n        client.run(\"install . -pr=profile\")\n        assert \"tool/1.1#platform - Platform\" in client.out\n        assert \"conanfile.py: DEPENDENCY tool/1.1\" in client.out\n\n    def test_consumer_resolved_revision(self):\n        client = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                tool_requires = \"tool/1.1\"\n\n                def generate(self):\n                    for r, _ in self.dependencies.items():\n                        self.output.info(f\"DEPENDENCY {repr(r.ref)}\")\n                \"\"\")\n        client.save({\"conanfile.py\": conanfile,\n                     \"profile\": \"[platform_tool_requires]\\ntool/1.1#rev1\"})\n        client.run(\"install . -pr=profile\")\n        assert \"tool/1.1 - Platform\" in client.out\n        assert \"conanfile.py: DEPENDENCY tool/1.1#rev1\" in client.out\n\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n               tool_requires = \"tool/1.1#rev1\"\n\n               def generate(self):\n                   for r, _ in self.dependencies.items():\n                       self.output.info(f\"DEPENDENCY {repr(r.ref)}\")\n               \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"install . -pr=profile\")\n        assert \"tool/1.1#rev1 - Platform\" in client.out\n        assert \"conanfile.py: DEPENDENCY tool/1.1#rev1\" in client.out\n\n    def test_consumer_unresolved_revision(self):\n        \"\"\" if a recipe specifies an exact revision and so does the profiñe\n        and it doesn't match, it is an error\n        \"\"\"\n        client = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                tool_requires = \"tool/1.1#rev2\"\n\n                def generate(self):\n                    for r, _ in self.dependencies.items():\n                        self.output.info(f\"DEPENDENCY {repr(r.ref)}\")\n                \"\"\")\n        client.save({\"conanfile.py\": conanfile,\n                     \"profile\": \"[platform_tool_requires]\\ntool/1.1#rev1\"})\n        client.run(\"install . -pr=profile\", assert_error=True)\n        assert \"ERROR: Package 'tool/1.1' not resolved\" in client.out\n\n    def test_require_build_context(self):\n        \"\"\" https://github.com/conan-io/conan/issues/15659\n        app -> libcurl --(tool-require)--> libtool -> automake -> autoconf\n                                             \\\\--(br)-> automake -> autoconf\n        \"\"\"\n        c = TestClient(light=True)\n        c.save({\"autoconf/conanfile.py\": GenConanfile(\"autoconf\", \"0.1\"),\n                \"automake/conanfile.py\": GenConanfile(\"automake\", \"0.1\").with_requires(\"autoconf/0.1\"),\n                \"libtool/conanfile.py\": GenConanfile(\"libtool\", \"0.1\").with_requires(\"automake/0.1\")\n                                                                      .with_tool_requires(\"automake/0.1\"),\n                \"libcurl/conanfile.py\": GenConanfile(\"libcurl\", \"0.1\").with_tool_requires(\"libtool/0.1\"),\n                \"app/conanfile.py\": GenConanfile().with_requires(\"libcurl/0.1\"),\n                \"profile_build\": \"[settings]\\nos=Linux\\n[platform_tool_requires]\\nautomake/0.1\"})\n        c.run(\"create autoconf\")\n        c.run(\"create automake\")\n        c.run(\"export libtool\")\n        c.run(\"export libcurl\")\n        c.run(\"install app -pr:b=profile_build --build=missing\")\n        assert \"Install finished successfully\" in c.out\n\n    def test_platform_requires_error(self):\n        \"\"\"\n        https://github.com/conan-io/conan/issues/19745\n        \"\"\"\n        c = TestClient(light=True)\n        profile = textwrap.dedent(\"\"\"\\\n            include(default)\n\n            [platform_tool_requires]\n            cmake/[*]\n            \"\"\")\n        c.save({\"conanfile.py\": GenConanfile(\"catch2\").with_tool_requires(\"cmake/[*]\"),\n                \"profile\": profile})\n\n        c.run(\"create  --version=3.6.0 -pr=profile\", assert_error=True)\n        assert \"AssertionError\" not in c.out\n        assert (\"ERROR: Error reading 'profile' profile: Profile [platform_requires]/\"\n                \"[platform_tool_requires] must be exact versions, \"\n                \"not version ranges: [cmake/[*]]\") in c.out\n\n\nclass TestToolRequiresLock:\n\n    @pytest.mark.parametrize(\"revision\", [\"\", \"#myrev\"])\n    def test_system_tool_require_range(self, revision):\n        c = TestClient(light=True)\n        c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_tool_requires(\"tool/[>=1.0]\"),\n                \"profile\": f\"[platform_tool_requires]\\ntool/1.1{revision}\"})\n        c.run(\"lock create . -pr=profile\")\n        assert \"tool/1.1 - Platform\" in c.out\n        lock = json.loads(c.load(\"conan.lock\"))\n        assert lock[\"build_requires\"] == [f\"tool/1.1{revision or '#platform'}\"]\n\n        c.run(\"install .\", assert_error=True)\n        assert \"Package 'tool/1.1' not resolved: No remote defined\" in c.out\n        c.run(\"install . -pr=profile\")\n        assert f\"tool/1.1{revision or '#platform'} - Platform\" in c.out\n\n        # even if we create a version within the range, it will error if not matching the profile\n        c.save({\"tool/conanfile.py\": GenConanfile(\"tool\", \"1.1\")})\n        c.run(\"create tool\")\n        # if the profile points to another version it is an error, not in the lockfile\n        c.save({\"profile\": f\"[platform_tool_requires]\\ntool/1.2{revision}\"})\n        c.run(\"install . -pr=profile\", assert_error=True)\n        assert f\"ERROR: Requirement 'tool/1.2{revision or '#platform'}' not in lockfile\" in c.out\n\n        # if we relax the lockfile, we can still resolve to the platform_tool_requires\n        # specified by the profile\n        c.run(\"install . -pr=profile --lockfile-partial\")\n        assert f\"tool/1.2{revision or '#platform'} - Platform\" in c.out\n\n\nclass TestGenerators:\n    def test_system_tool_require_range(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.cmake import CMakeDeps\n            from conan.tools.gnu import PkgConfigDeps\n\n            class Pkg(ConanFile):\n                settings = \"build_type\"\n                tool_requires = \"tool/[>=1.0]\"\n                def generate(self):\n                    deps = CMakeDeps(self)\n                    deps.build_context_activated = [\"tool\"]\n                    deps.generate()\n                    deps = PkgConfigDeps(self)\n                    deps.build_context_activated = [\"tool\"]\n                    deps.generate()\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile,\n                     \"profile\": \"[platform_tool_requires]\\ntool/1.1\"})\n        client.run(\"install . -pr=profile\")\n        assert \"tool/1.1 - Platform\" in client.out\n        assert not os.path.exists(os.path.join(client.current_folder, \"tool-config.cmake\"))\n        assert not os.path.exists(os.path.join(client.current_folder, \"tool.pc\"))\n\n\nclass TestPackageID:\n    \"\"\" if a consumer depends on recipe revision or package_id what happens\n    \"\"\"\n\n    @pytest.mark.parametrize(\"package_id_mode\", [\"recipe_revision_mode\", \"full_package_mode\"])\n    def test_package_id_modes(self, package_id_mode):\n        \"\"\" this test validates that the computation of the downstream consumers package_id\n        doesnt break even if it depends on fields not existing in upstream system_tool_require, like revision\n        or package_id\n        \"\"\"\n        client = TestClient(light=True)\n        client.save_home({\"global.conf\": f\"core.package_id:default_build_mode={package_id_mode}\"})\n        client.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_tool_requires(\"dep/1.0\"),\n                     \"profile\": \"[platform_tool_requires]\\ndep/1.0\"})\n        client.run(\"create . -pr=profile\")\n        assert \"dep/1.0 - Platform\" in client.out\n\n    def test_package_id_explicit_revision(self):\n        \"\"\"\n        Changing the system_tool_require revision affects consumers if package_revision_mode=recipe_revision\n        \"\"\"\n        client = TestClient(light=True)\n        client.save_home({\"global.conf\": \"core.package_id:default_build_mode=recipe_revision_mode\"})\n        client.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_tool_requires(\"dep/1.0\"),\n                     \"profile\": \"[platform_tool_requires]\\ndep/1.0#r1\",\n                     \"profile2\": \"[platform_tool_requires]\\ndep/1.0#r2\"})\n        client.run(\"create . -pr=profile\")\n        assert \"dep/1.0#r1 - Platform\" in client.out\n        assert \"pkg/1.0#27a56f09310cf1237629bae4104fe5bd:\" \\\n               \"ea0e320d94b4b70fcb3efbabf9ab871542f8f696 - Build\" in client.out\n\n        client.run(\"create . -pr=profile2\")\n        # pkg gets a new package_id because it is a different revision\n        assert \"dep/1.0#r2 - Platform\" in client.out\n        assert \"pkg/1.0#27a56f09310cf1237629bae4104fe5bd:\" \\\n               \"334882884da082740e5a002a0b6fdb509a280159 - Build\" in client.out\n"
  },
  {
    "path": "test/integration/graph/test_test_requires.py",
    "content": "import textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestTestRequiresDiamond:\n    def test_test_requires_linear(self):\n        c = TestClient(light=True)\n        c.save({\"zlib/conanfile.py\": GenConanfile(\"zlib\", \"1.0\"),\n                \"gtest/conanfile.py\": GenConanfile(\"gtest\", \"1.0\").with_requires(\"zlib/1.0\"),\n                \"engine/conanfile.py\": GenConanfile(\"engine\", \"1.0\").with_test_requires(\"gtest/1.0\")\n                })\n        c.run(\"create zlib\")\n        c.run(\"create gtest\")\n        c.run(\"install engine\")\n        c.assert_listed_require({\"gtest/1.0\": \"Cache\",\n                                 \"zlib/1.0\": \"Cache\"}, test=True)\n\n    def test_test_requires_half_diamond(self):\n        c = TestClient(light=True)\n        c.save({\"zlib/conanfile.py\": GenConanfile(\"zlib\", \"1.0\"),\n                \"gtest/conanfile.py\": GenConanfile(\"gtest\", \"1.0\").with_requires(\"zlib/1.0\"),\n                \"engine/conanfile.py\": GenConanfile(\"engine\", \"1.0\").with_requires(\"zlib/1.0\")\n                                                                    .with_test_requires(\"gtest/1.0\")\n                })\n        c.run(\"create zlib\")\n        c.run(\"create gtest\")\n        c.run(\"install engine\")\n        c.assert_listed_require({\"zlib/1.0\": \"Cache\"})\n        c.assert_listed_require({\"gtest/1.0\": \"Cache\"}, test=True)\n\n    def test_test_requires_half_diamond_change_order(self):\n        engine = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                def requirements(self):\n                    # Best practice is to declare test_requires in the build_requirements() method,\n                    # but this ensures it is also possible to declare them in requirements(),\n                    # as has historically been allowed.\n                    self.test_requires(\"gtest/1.0\")\n                    self.requires(\"zlib/1.0\")\n            \"\"\")\n        c = TestClient(light=True)\n        c.save({\"zlib/conanfile.py\": GenConanfile(\"zlib\", \"1.0\"),\n                \"gtest/conanfile.py\": GenConanfile(\"gtest\", \"1.0\").with_requires(\"zlib/1.0\"),\n                \"engine/conanfile.py\": engine\n                })\n        c.run(\"create zlib\")\n        c.run(\"create gtest\")\n        c.run(\"install engine\")\n        c.assert_listed_require({\"zlib/1.0\": \"Cache\"})\n        c.assert_listed_require({\"gtest/1.0\": \"Cache\"}, test=True)\n\n    def test_test_requires_diamond(self):\n        c = TestClient(light=True)\n        c.save({\"zlib/conanfile.py\": GenConanfile(\"zlib\", \"1.0\"),\n                \"gtest/conanfile.py\": GenConanfile(\"gtest\", \"1.0\").with_requires(\"zlib/1.0\"),\n                \"engine/conanfile.py\": GenConanfile(\"engine\", \"1.0\").with_requires(\"zlib/1.0\"),\n                \"game/conanfile.py\": GenConanfile().with_requires(\"engine/1.0\")\n                                                   .with_test_requires(\"gtest/1.0\")\n                })\n        c.run(\"create zlib\")\n        c.run(\"create gtest\")\n        c.run(\"create engine\")\n        c.run(\"install game\")\n        c.assert_listed_require({\"zlib/1.0\": \"Cache\",\n                                 \"engine/1.0\": \"Cache\"})\n        c.assert_listed_require({\"gtest/1.0\": \"Cache\"}, test=True)\n\n    def test_test_requires_diamond_change_order(self):\n        c = TestClient(light=True)\n        game = textwrap.dedent(\"\"\"\n           from conan import ConanFile\n           class Pkg(ConanFile):\n               def build_requirements(self):\n                   self.test_requires(\"gtest/1.0\")\n               def requirements(self):\n                   self.requires(\"engine/1.0\")\n           \"\"\")\n        c.save({\"zlib/conanfile.py\": GenConanfile(\"zlib\", \"1.0\"),\n                \"gtest/conanfile.py\": GenConanfile(\"gtest\", \"1.0\").with_requires(\"zlib/1.0\"),\n                \"engine/conanfile.py\": GenConanfile(\"engine\", \"1.0\").with_requires(\"zlib/1.0\"),\n                \"game/conanfile.py\": game\n                })\n        c.run(\"create zlib\")\n        c.run(\"create gtest\")\n        c.run(\"create engine\")\n        c.run(\"install game\")\n        c.assert_listed_require({\"zlib/1.0\": \"Cache\",\n                                 \"engine/1.0\": \"Cache\"})\n        c.assert_listed_require({\"gtest/1.0\": \"Cache\"}, test=True)\n\n    def test_test_requires_conflict_force(self):\n        c = TestClient(light=True)\n        game = textwrap.dedent(\"\"\"\n           from conan import ConanFile\n           class Pkg(ConanFile):\n               def build_requirements(self):\n                   self.test_requires(\"gtest/1.0\", force=True)\n                   self.test_requires(\"rapidcheck/1.0\")\n           \"\"\")\n        c.save({\"gtest/conanfile.py\": GenConanfile(\"gtest\"),\n                \"rapidcheck/conanfile.py\":\n                    GenConanfile(\"rapidcheck\", \"1.0\").with_requires(\"gtest/1.1\"),\n                \"game/conanfile.py\": game\n                })\n        c.run(\"create gtest --version=1.0\")\n        c.run(\"create gtest --version=1.1\")\n        c.run(\"create rapidcheck\")\n        c.run(\"install game\")\n        c.assert_listed_require({\"gtest/1.0\": \"Cache\"}, test=True)\n        c.assert_overrides({\"gtest/1.1\": [\"gtest/1.0\"]})\n\n\ndef test_require_options():\n    c = TestClient(light=True)\n    gtest = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Gtest(ConanFile):\n            name = \"gtest\"\n            version = \"1.0\"\n            options = {\"myoption\": [1, 2, 3]}\n            default_options = {\"myoption\": 1}\n            def package_info(self):\n                self.output.info(f\"MYOPTION: {self.options.myoption}\")\n        \"\"\")\n    engine = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Engine(ConanFile):\n            name = \"engine\"\n            version = \"1.0\"\n            def build_requirements(self):\n                self.test_requires(\"gtest/1.0\", options={\"myoption\": \"2\"})\n        \"\"\")\n    c.save({\"gtest/conanfile.py\": gtest,\n            \"engine/conanfile.py\": engine})\n    c.run(\"create gtest\")\n    c.run(\"create gtest -o gtest*:myoption=2\")\n    c.run(\"create gtest -o gtest*:myoption=3\")\n    c.run(\"create engine\")\n    assert \"gtest/1.0: MYOPTION: 2\" in c.out\n    c.run(\"create engine -o gtest*:myoption=3\")\n    assert \"gtest/1.0: MYOPTION: 3\" in c.out\n\n\ndef test_requires_components():\n    \"\"\" this test used to fail with \"gtest\" not required by components\n    It is important to have at least 1 external ``requires`` because with\n    no requires at all it doesn't fail.\n    https://github.com/conan-io/conan/issues/13187\n    \"\"\"\n    c = TestClient(light=True)\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class MyLib(ConanFile):\n            name = \"mylib\"\n            version = \"0.1\"\n\n            requires = \"openssl/1.1\"\n            test_requires = \"gtest/1.0\"\n\n            def package_info(self):\n                self.cpp_info.components[\"mylib\"].requires = [\"openssl::openssl\"]\n        \"\"\")\n    c.save({\"gtest/conanfile.py\": GenConanfile(\"gtest\", \"1.0\"),\n            \"openssl/conanfile.py\": GenConanfile(\"openssl\", \"1.1\"),\n            \"pkg/conanfile.py\": conanfile})\n    c.run(\"create gtest\")\n    c.run(\"create openssl\")\n    c.run(\"create pkg\")\n    # This NO LONGER FAILS\n    c.assert_listed_require({\"gtest/1.0\": \"Cache\"}, test=True)\n\n\ndef test_requires_transitive_diamond_components():\n    \"\"\"\n    libc -----> libb ----> liba\n     |-(test-requires)----/\n    https://github.com/conan-io/conan/issues/13892\n    \"\"\"\n    c = TestClient(light=True)\n    libc = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class LibC(ConanFile):\n            name = \"libc\"\n            version = \"0.1\"\n            requires = \"libb/1.0\"\n            test_requires = \"liba/1.0\"\n            def package_info(self):\n                 self.cpp_info.components[\"comp\"].libs = [\"libc\"]\n                 self.cpp_info.components[\"comp\"].requires.append(\"libb::libb\")\n        \"\"\")\n    c.save({\"liba/conanfile.py\": GenConanfile(\"liba\", \"1.0\"),\n            \"libb/conanfile.py\": GenConanfile(\"libb\", \"1.0\").with_requires(\"liba/1.0\"),\n            \"libc/conanfile.py\": libc})\n    c.run(\"create liba\")\n    c.run(\"create libb\")\n    c.run(\"create libc\")\n    # This used to crash due to component not defined to liba\n    assert \"libc/0.1: Created package\" in c.out\n\n\ndef test_requires_transitive_diamond_components_order():\n    \"\"\"\n    like the above, but in different order\n     libc  --(test-requires)---> liba\n       |-----> libb -----------/\n    libc->liba => test=False, direct=True, is_test=True\n    direct_dependencies (components check) => False\n    https://github.com/conan-io/conan/issues/17164\n    \"\"\"\n    c = TestClient(light=True)\n    libc = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class LibC(ConanFile):\n            name = \"libc\"\n            version = \"0.1\"\n\n            def build_requirements(self):\n                self.test_requires(\"liba/1.0\")\n            def requirements(self):\n                self.requires(\"libb/1.0\")\n\n            def package_info(self):\n                 self.cpp_info.components[\"comp\"].libs = [\"libc\"]\n                 self.cpp_info.components[\"comp\"].requires.append(\"libb::libb\")\n        \"\"\")\n    c.save({\"liba/conanfile.py\": GenConanfile(\"liba\", \"1.0\"),\n            \"libb/conanfile.py\": GenConanfile(\"libb\", \"1.0\").with_requires(\"liba/1.0\"),\n            \"libc/conanfile.py\": libc})\n    c.run(\"create liba\")\n    c.run(\"create libb\")\n    c.run(\"create libc\")\n    # This used to crash due to component not defined to liba\n    assert \"libc/0.1: Created package\" in c.out\n\n\ndef test_wrong_requirement_test_requires():\n    \"\"\" https://github.com/conan-io/conan/issues/17312\n\n    app --------> etas --------------> enum\n      \\\\-->hwinfo-/---(test_requires)---/\n       \\\\-----------------------------/\n\n    app->enum => test=False, direct=True, is_test=True\n    direct_dependencies (components check) => True\n    \"\"\"\n    c = TestClient(light=True)\n    app = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"app\"\n            version = \"0.1\"\n            requires = \"etas/0.1\", \"enum/0.1\", \"hwinfo/0.1\"\n\n            def generate(self):\n                for r, d in self.dependencies.items():\n                    assert not (r.direct and r.is_test)\n\n            def package_info(self):\n                self.cpp_info.requires = [\"etas::etas\", \"enum::enum\", \"hwinfo::hwinfo\"]\n            \"\"\")\n    files = {\n        \"enum/conanfile.py\": GenConanfile(\"enum\", \"0.1\"),\n        \"etas/conanfile.py\": GenConanfile(\"etas\", \"0.1\").with_requirement(\"enum/0.1\"),\n        \"hwinfo/conanfile.py\": GenConanfile(\"hwinfo\", \"0.1\").with_requirement(\"etas/0.1\")\n                                                            .with_test_requires(\"enum/0.1\"),\n        \"app/conanfile.py\": app,\n    }\n    c.save(files)\n    c.run(\"create enum\")\n    c.run(\"create etas\")\n    c.run(\"create hwinfo\")\n    # The assert in generate() doesnt fail\n    c.run(\"install app\")\n    # the package_info() doesn't fail\n    c.run(\"create app\")\n\n\ndef test_test_requires_options():\n    \"\"\" the default_options = {} values also propagate to ``test_requires()`` \"\"\"\n    c = TestClient(light=True)\n    c.save({\"test/conanfile.py\": GenConanfile(\"test\", \"0.1\").with_option(\"myoption\", [1, 2, 3]),\n            \"consumer/conanfile.py\": GenConanfile().with_test_requires(\"test/0.1\")\n                                                   .with_default_option(\"test/*:myoption\", \"2\")})\n    c.run(\"create test -o myoption=2\")\n    c.assert_listed_binary({\"test/0.1\": (\"a3cb1345b8297bfdffea4ef4bb1b2694c54d1d69\", \"Build\")})\n\n    c.run(\"install consumer\")\n    c.assert_listed_require({\"test/0.1\": \"Cache\"}, test=True)\n    c.assert_listed_binary({\"test/0.1\": (\"a3cb1345b8297bfdffea4ef4bb1b2694c54d1d69\", \"Cache\")},\n                           test=True)\n\n\ndef test_invisible_requires_options():\n    \"\"\" the default_options = {} values also propagate to ``requires(visible=False)`` \"\"\"\n    c = TestClient(light=True)\n    c.save({\"test/conanfile.py\": GenConanfile(\"test\", \"0.1\").with_option(\"myoption\", [1, 2, 3]),\n            \"consumer/conanfile.py\": GenConanfile().with_requirement(\"test/0.1\", visible=False)\n                                                   .with_default_option(\"test/*:myoption\", \"2\")})\n    c.run(\"create test -o myoption=2\")\n    c.assert_listed_binary({\"test/0.1\": (\"a3cb1345b8297bfdffea4ef4bb1b2694c54d1d69\", \"Build\")})\n\n    c.run(\"install consumer\")\n    c.assert_listed_require({\"test/0.1\": \"Cache\"})\n    c.assert_listed_binary({\"test/0.1\": (\"a3cb1345b8297bfdffea4ef4bb1b2694c54d1d69\", \"Cache\")})\n"
  },
  {
    "path": "test/integration/graph/test_validate_build.py",
    "content": "import json\nimport textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_basic_validate_build_test():\n\n    t = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    from conan.errors import ConanInvalidConfiguration\n\n    class myConan(ConanFile):\n        name = \"foo\"\n        version = \"1.0\"\n        settings = \"os\", \"arch\", \"compiler\"\n\n        def validate_build(self):\n            if self.settings.compiler == \"gcc\":\n                raise ConanInvalidConfiguration(\"This doesn't build in GCC\")\n\n        def package_id(self):\n            del self.info.settings.compiler\n    \"\"\")\n\n    settings_gcc = \"-s compiler=gcc -s compiler.libcxx=libstdc++11 -s compiler.version=11\"\n    settings_clang = \"-s compiler=clang -s compiler.libcxx=libc++ -s compiler.version=8\"\n\n    t.save({\"conanfile.py\": conanfile})\n    t.run(f\"create . {settings_gcc}\", assert_error=True)\n\n    assert \"foo/1.0: Cannot build for this configuration: This doesn't build in GCC\" in t.out\n\n    t.run(f\"create . {settings_clang}\")\n\n    # Now with GCC again, but now we have the binary, we don't need to build, so it doesn't fail\n    t.run(f\"create . {settings_gcc} --build missing\")\n    assert \"foo/1.0: Already installed!\" in t.out\n\n    # But if I force the build... it will fail\n    t.run(f\"create . {settings_gcc} \", assert_error=True)\n    assert \"foo/1.0: Cannot build for this configuration: This doesn't build in GCC\" in t.out\n\n    # What happens with a conan info?\n    t.run(f\"graph info --requires=foo/1.0 {settings_gcc} --format=json\", redirect_stdout=\"myjson\")\n    myjson = json.loads(t.load(\"myjson\"))[\"graph\"][\"nodes\"]\n    assert myjson[\"1\"][\"invalid_build\"] == \"This doesn't build in GCC\"\n\n    t.run(f\"graph info --requires=foo/1.0 {settings_clang} --format=json\", redirect_stdout=\"myjson\")\n    myjson = json.loads(t.load(\"myjson\"))[\"graph\"][\"nodes\"]\n    assert myjson[\"1\"][\"invalid_build\"] is False\n\n\ndef test_with_options_validate_build_test():\n    t = TestClient(light=True)\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    from conan.errors import ConanInvalidConfiguration\n\n    class myConan(ConanFile):\n        name = \"foo\"\n        version = \"1.0\"\n        options = {\"my_option\": [True, False]}\n        default_options = {\"my_option\": True}\n\n        def validate_build(self):\n            if not self.options.my_option:\n                raise ConanInvalidConfiguration(\"This doesn't build with False option\")\n\n    \"\"\")\n    t.save({\"conanfile.py\": conanfile})\n    t.run(\"export .\")\n    consumer = GenConanfile().with_require(\"foo/1.0\").with_name(\"consumer\").with_version(\"1.0\")\n    t.save({\"consumer.py\": consumer})\n    t.run(\"create consumer.py --build missing -o foo/*:my_option=False\", assert_error=True)\n    assert \"foo/1.0: Cannot build for this configuration: This doesn't build \" \\\n           \"with False option\" in t.out\n\n    t.run(\"create consumer.py --build missing -o foo/*:my_option=True\")\n\n\ndef test_basic_validate_build_command_build():\n    \"\"\" the \"conan build\" command should fail for a validate_build() too\n    https://github.com/conan-io/conan/issues/12571\n    \"\"\"\n    t = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.errors import ConanInvalidConfiguration\n\n        class myConan(ConanFile):\n            settings = \"os\"\n\n            def validate_build(self):\n                if self.settings.os == \"Windows\":\n                    raise ConanInvalidConfiguration(\"This doesn't build in Windows\")\n        \"\"\")\n\n    t.save({\"conanfile.py\": conanfile})\n    t.run(f\"build . -s os=Windows\", assert_error=True)\n    assert \"ERROR: conanfile.py: Cannot build for this configuration: \" \\\n           \"This doesn't build in Windows\" in t.out\n    t.run(\"build . -s os=Linux\")\n    # It doesn't fail\n"
  },
  {
    "path": "test/integration/graph/ux/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/graph/ux/loop_detection_test.py",
    "content": "import textwrap\n\nfrom conan.test.utils.tools import TestClient, GenConanfile\n\n\nclass TestLoopDetection:\n\n    def test_transitive_loop(self):\n        client = TestClient(light=True)\n        client.save({\n            'pkg1.py': GenConanfile().with_require('pkg2/0.1@lasote/stable'),\n            'pkg2.py': GenConanfile().with_require('pkg3/0.1@lasote/stable'),\n            'pkg3.py': GenConanfile().with_require('pkg1/0.1@lasote/stable'),\n        })\n        client.run('export pkg1.py --name=pkg1 --version=0.1 --user=lasote --channel=stable')\n        client.run('export pkg2.py --name=pkg2 --version=0.1 --user=lasote --channel=stable')\n        client.run('export pkg3.py --name=pkg3 --version=0.1 --user=lasote --channel=stable')\n\n        client.run(\"install --requires=pkg3/0.1@lasote/stable --build='*'\", assert_error=True)\n        # TODO: Complete with better diagnostics\n        assert \"ERROR: There is a cycle/loop in the graph\" in client.out\n\n    def test_self_loop(self):\n        client = TestClient(light=True)\n        client.save({'pkg1.py': GenConanfile().with_require('pkg1/0.1@lasote/stable'), })\n        client.run('export pkg1.py --name=pkg1 --version=0.1 --user=lasote --channel=stable')\n        client.run(\"install --requires=pkg1/0.1@lasote/stable --build='*'\", assert_error=True)\n        assert \"ERROR: There is a cycle/loop in the graph\" in client.out\n\n\ndef test_install_order_infinite_loop():\n    c = TestClient(light=True)\n    c.save({\"fmt/conanfile.py\": GenConanfile(\"fmt\", \"1.0\"),\n            \"tool/conanfile.py\": GenConanfile(\"tool\", \"1.0\").with_requires(\"fmt/1.0\"),\n            \"tool_profile\": \"[tool_requires]\\n!tool/*: tool/1.0\"})\n    c.run(\"export fmt\")\n    c.run(\"export tool\")\n    c.run(\"install tool -pr:h=tool_profile -b=missing\",\n          assert_error=True)\n    assert \"ERROR: There is a loop in the graph\" in c.out\n    assert \"fmt/1.0 (Build) -> ['tool/1.0']\" in c.out\n    assert \"tool/1.0 (Build) -> ['fmt/1.0']\" in c.out\n\n    # Graph build-order fails in the same way\n    c.run(\"graph build-order tool -pr:h=tool_profile -b=missing\",\n          assert_error=True)\n    assert \"ERROR: There is a loop in the graph\" in c.out\n    assert \"fmt/1.0 (Build) -> ['tool/1.0']\" in c.out\n    assert \"tool/1.0 (Build) -> ['fmt/1.0']\" in c.out\n\n    c.run(\"graph build-order tool -pr:h=tool_profile --order-by=configuration -b=missing\",\n          assert_error=True)\n    assert \"ERROR: There is a loop in the graph\" in c.out\n    assert \"fmt/1.0:da39a3ee5e6b4b0d3255bfef95601890afd80709 (Build) -> \" \\\n           \"['tool/1.0:044d18636d2b7da86d3aa46a2aabf1400db525b1']\" in c.out\n    assert \"tool/1.0:044d18636d2b7da86d3aa46a2aabf1400db525b1 (Build) -> \" \\\n           \"['fmt/1.0:da39a3ee5e6b4b0d3255bfef95601890afd80709']\" in c.out\n\n\ndef test_build_require_undetected_loop():\n    c = TestClient(light=True)\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class DemoRecipe(ConanFile):\n            name = \"test\"\n            version = \"1.0\"\n\n            def requirements(self):\n                self.requires(\"cmake/3.31.6\", build=True)\n\n            def build_requirements(self):\n                self.tool_requires(\"cmake/3.31.6\", options={\n                    \"bad\": True # this doesn't need to be a valid option\n                })\n\n            def generate(self):\n                self.output.info(f\"NUM DEPS: {len(self.dependencies.items())}\")\n        \"\"\")\n    c.save({\"cmake/conanfile.py\": GenConanfile(\"cmake\", \"3.31.6\").with_shared_option(True),\n            \"app/conanfile.py\": conanfile})\n\n    c.run(\"create cmake\")\n    c.run(\"install app\")\n    # It doesn't hang, and it sees correctly just 1 dependency\n    assert \"conanfile.py (test/1.0): NUM DEPS: 1\" in c.out\n"
  },
  {
    "path": "test/integration/graph/version_ranges/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/graph/version_ranges/test_version_range_conf.py",
    "content": "from conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_version_range_conf_nonexplicit_expression():\n    tc = TestClient(light=True)\n\n    tc.save({\"base/conanfile.py\": GenConanfile(\"base\")})\n    tc.run(\"create base/conanfile.py --version=1.5.1\")\n    tc.run(\"create base/conanfile.py --version=2.5.0-pre\")\n\n    tc.save({\"v1/conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_requires(\"base/[>1 <2]\"),\n             \"v2/conanfile.py\": GenConanfile(\"pkg\", \"2.0\").with_requires(\"base/[>2 <3]\")})\n\n    tc.save_home({\"global.conf\": \"core.version_ranges:resolve_prereleases=False\"})\n    tc.run(\"create v1/conanfile.py\")\n    assert \"base/[>1 <2]: base/1.5.1\" in tc.out\n    tc.run(\"create v2/conanfile.py\", assert_error=True)\n    assert \"Package 'base/[>2 <3]' not resolved\" in tc.out\n\n    tc.save_home({\"global.conf\": \"core.version_ranges:resolve_prereleases=True\"})\n    tc.run(\"create v1/conanfile.py\")\n    assert \"base/[>1 <2]: base/1.5.1\" in tc.out\n    tc.run(\"create v2/conanfile.py\")\n    assert \"base/[>2 <3]: base/2.5.0-pre\" in tc.out\n\n    tc.save_home({\"global.conf\": \"core.version_ranges:resolve_prereleases=None\"})\n    tc.run(\"create v1/conanfile.py\")\n    assert \"base/[>1 <2]: base/1.5.1\" in tc.out\n\n    tc.run(\"create v2/conanfile.py\", assert_error=True)\n    assert \"Package 'base/[>2 <3]' not resolved\" in tc.out\n\n\ndef test_version_range_conf_explicit_expression():\n    tc = TestClient(light=True)\n\n    tc.save({\"base/conanfile.py\": GenConanfile(\"base\")})\n    tc.run(\"create base/conanfile.py --version=1.5.1\")\n    tc.run(\"create base/conanfile.py --version=2.5.0-pre\")\n\n    tc.save({\"v1/conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_requires(\"base/[>1 <2, include_prerelease]\"),\n             \"v2/conanfile.py\": GenConanfile(\"pkg\", \"2.0\").with_requires(\"base/[>2 <3, include_prerelease]\")})\n\n    tc.save_home({\"global.conf\": \"core.version_ranges:resolve_prereleases=False\"})\n    tc.run(\"create v1/conanfile.py\")\n    assert \"base/[>1 <2, include_prerelease]: base/1.5.1\" in tc.out\n    tc.run(\"create v2/conanfile.py\", assert_error=True)\n    assert \"Package 'base/[>2 <3, include_prerelease]' not resolved\" in tc.out\n\n    tc.save_home({\"global.conf\": \"core.version_ranges:resolve_prereleases=True\"})\n    tc.run(\"create v1/conanfile.py\")\n    assert \"base/[>1 <2, include_prerelease]: base/1.5.1\" in tc.out\n    tc.run(\"create v2/conanfile.py\")\n    assert \"base/[>2 <3, include_prerelease]: base/2.5.0-pre\" in tc.out\n\n    tc.save_home({\"global.conf\": \"core.version_ranges:resolve_prereleases=None\"})\n    tc.run(\"create v1/conanfile.py\")\n    assert \"base/[>1 <2, include_prerelease]: base/1.5.1\" in tc.out\n    tc.run(\"create v2/conanfile.py\")\n    assert \"base/[>2 <3, include_prerelease]: base/2.5.0-pre\" in tc.out\n"
  },
  {
    "path": "test/integration/graph/version_ranges/version_range_override_test.py",
    "content": "import json\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient, GenConanfile\n\n\nclass TestVersionRangeOverride:\n\n    @pytest.fixture(autouse=True)\n    def _setup(self):\n        self.t = TestClient(light=True)\n        self.t.save({\"libb/conanfile.py\": GenConanfile(),\n                     \"libc/conanfile.py\":\n                         GenConanfile().with_require(\"libb/[<=2.0]@user/channel\")})\n        self.t.run(\"export libb --name=libb --version=1.0 --user=user --channel=channel\")\n        self.t.run(\"export libb --name=libb --version=2.0 --user=user --channel=channel\")\n        self.t.run(\"export libb --name=libb --version=3.0 --user=user --channel=channel\")\n        self.t.run(\"export libc --name=libc --version=1.0 --user=user --channel=channel\")\n\n    def test(self):\n        # Use the version range\n        self.t.save({\"conanfile.py\": GenConanfile().with_require(\"libc/1.0@user/channel\")})\n        self.t.run(\"graph info . --filter requires\")\n        assert \"libb/2.0@user/channel\" in self.t.out\n\n    def test_override_with_fixed_version(self):\n        # Override upstream version range with a fixed version\n        self.t.save({\"conanfile.py\": GenConanfile().with_requirement(\"libb/3.0@user/channel\",\n                                                                     override=True)\n                                                   .with_require(\"libc/1.0@user/channel\")})\n        self.t.run(\"graph info . --filter requires\")\n        self.t.assert_overrides({'libb/[<=2.0]@user/channel': ['libb/3.0@user/channel']})\n        assert \"libb/3.0@user/channel#\" in self.t.out\n\n    def test_override_using_version_range(self):\n        # Override upstream version range with a different (narrower) version range\n        self.t.save({\"conanfile.py\": GenConanfile().with_requirement(\"libb/[<2.x]@user/channel\",\n                                                                     override=True)\n                                                   .with_require(\"libc/1.0@user/channel\")})\n        self.t.run(\"graph info . --filter requires\")\n        self.t.assert_overrides({'libb/[<=2.0]@user/channel': ['libb/[<2.x]@user/channel']})\n        assert \"libb/2.0@user/channel\" in self.t.out\n\n    def test_override_version_range_outside(self):\n        # Override upstream version range with a different (non intersecting) version range\n        self.t.save({\"conanfile.py\": GenConanfile().with_requirement(\"libb/[>2.x]@user/channel\",\n                                                                     override=True)\n                                                   .with_require(\"libc/1.0@user/channel\")})\n        self.t.run(\"graph info . --filter requires\")\n        self.t.assert_overrides({'libb/[<=2.0]@user/channel': ['libb/[>2.x]@user/channel']})\n        assert \"libb/3.0@user/channel\" in self.t.out\n\n\nclass TestVersionRangeOverrideFail:\n\n    def test_override(self):\n        \"\"\"\n        pkga -> ros_perception  -> ros_core\n           \\\\-----> pkgb  -----------/\n        \"\"\"\n        # https://github.com/conan-io/conan/issues/8071\n        t = TestClient(light=True)\n        t.save({\"conanfile.py\": GenConanfile()})\n        t.run(\"create . --name=ros_core --version=1.1.4 --user=3rdparty --channel=unstable\")\n        t.run(\"create . --name=ros_core --version=pr-53 --user=3rdparty --channel=snapshot\")\n        t.save({\"conanfile.py\": GenConanfile().with_requires(\"ros_core/1.1.4@3rdparty/unstable\")})\n        t.run(\"create . --name=ros_perception --version=1.1.4 --user=3rdparty --channel=unstable\")\n        t.run(\"create . --name=ros_perception --version=pr-53 --user=3rdparty --channel=snapshot\")\n        t.save({\"conanfile.py\": GenConanfile().with_requires(\"ros_core/[~1.1]@3rdparty/unstable\")})\n        t.run(\"create . --name=pkgb --version=0.1 --user=common --channel=unstable\")\n        t.save({\"conanfile.py\": GenConanfile(\"pkga\", \"0.1\").with_requires(\n            \"ros_perception/[~1.1]@3rdparty/unstable\",\n            \"pkgb/[~0]@common/unstable\")})\n        t.run(\"create . \")\n        assert \"ros_core/1.1.4@3rdparty/unstable\" in t.out\n        assert \"ros_perception/1.1.4@3rdparty/unstable\" in t.out\n        assert \"snapshot\" not in t.out\n\n        t.save({\"conanfile.py\": GenConanfile(\"pkga\", \"0.1\")\n               .with_require(\"pkgb/[~0]@common/unstable\")\n               .with_require(\"ros_perception/pr-53@3rdparty/snapshot\")\n               .with_requirement(\"ros_core/pr-53@3rdparty/snapshot\", override=True)})\n\n        t.run(\"create .  --build=missing --build=pkga\")\n        assert \"ros_core/pr-53@3rdparty/snapshot\" in t.out\n        assert \"ros_perception/pr-53@3rdparty/snapshot\" in t.out\n\n        # Override only the upstream without overriding the direct one\n        t.save({\"conanfile.py\": GenConanfile(\"pkga\", \"0.1\")\n               .with_require(\"pkgb/[~0]@common/unstable\")\n               .with_require(\"ros_perception/[~1.1]@3rdparty/unstable\")\n               .with_requirement(\"ros_core/pr-53@3rdparty/snapshot\", force=True)})\n\n        t.run(\"create .  --build=missing --build=pkga\")\n        assert \"ros_core/pr-53@3rdparty/snapshot\" in t.out\n        assert \"ros_perception/1.1.4@3rdparty/unstable\" in t.out\n\n        # Check information got by graph info\n        t.run(\"graph info . --format json\")\n        info = json.loads(t.stdout)\n        expected_overrides = {\n            \"ros_core/[~1.1]@3rdparty/unstable\": [\n                \"ros_core/pr-53@3rdparty/snapshot\"\n            ],\n            \"ros_core/1.1.4@3rdparty/unstable\": [\n                \"ros_core/pr-53@3rdparty/snapshot\"\n            ]\n        }\n        assert info['graph'][\"overrides\"] == expected_overrides\n        expected_resolved_ranges = {\n            \"pkgb/[~0]@common/unstable\": \"pkgb/0.1@common/unstable\",\n            \"ros_perception/[~1.1]@3rdparty/unstable\": \"ros_perception/1.1.4@3rdparty/unstable\"\n        }\n        assert info['graph'][\"resolved_ranges\"] == expected_resolved_ranges\n"
  },
  {
    "path": "test/integration/graph/version_ranges/version_ranges_cached_test.py",
    "content": "from collections import OrderedDict\n\nimport pytest\nfrom unittest.mock import patch\n\nfrom conan.internal.rest.remote_manager import RemoteManager\nfrom conan.api.model import RecipeReference\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient, TestServer\n\n\nclass TestVersionRangesCache:\n\n    @pytest.fixture(autouse=True)\n    def _setup(self):\n        self.counters = {\"server0\": 0, \"server1\": 0}\n\n    def _mocked_search_recipes(self, remote, pattern, ignorecase=True):\n        packages = {\n            \"server0\": [RecipeReference.loads(\"liba/1.0.0\"),\n                        RecipeReference.loads(\"liba/1.1.0\")],\n            \"server1\": [RecipeReference.loads(\"liba/2.0.0\"),\n                        RecipeReference.loads(\"liba/2.1.0\")]\n        }\n        self.counters[remote.name] = self.counters[remote.name] + 1\n        return packages[remote.name]\n\n    def test_version_ranges_cached(self):\n        servers = OrderedDict()\n        for index in range(2):\n            servers[f\"server{index}\"] = TestServer([(\"*/*@*/*\", \"*\")], [(\"*/*@*/*\", \"*\")],\n                                                   users={\"user\": \"password\"})\n\n        client = TestClient(light=True, servers=servers, inputs=[\"user\", \"password\", \"user\", \"password\"])\n\n        # server0 does not satisfy range\n        # server1 does\n\n        for minor in range(2):\n            client.save({\"conanfile.py\": GenConanfile(\"liba\", f\"1.{minor}.0\")})\n            client.run(\"create .\")\n            client.run(f\"upload liba/1.{minor}.0 -r server0 -c\")\n\n        for minor in range(2):\n            client.save({\"conanfile.py\": GenConanfile(\"liba\", f\"2.{minor}.0\")})\n            client.run(\"create .\")\n            client.run(f\"upload liba/2.{minor}.0 -r server1 -c\")\n\n        client.run(\"remove * -c\")\n\n        client.save({\"conanfile.py\": GenConanfile(\"libb\", \"1.0\").with_require(\"liba/[>=2.0]\")})\n        client.run(\"create .\")\n\n        client.save({\"conanfile.py\": GenConanfile(\"libc\", \"1.0\").with_require(\"liba/[>=2.0]\")})\n        client.run(\"create .\")\n\n        client.save({\"conanfile.py\": GenConanfile(\"consumer\", \"1.0\")\n                    .with_requires(\"libb/1.0\", \"libc/1.0\")})\n\n        # should call only once to server0\n        self.counters[\"server0\"] = 0\n        self.counters[\"server1\"] = 0\n        with patch.object(RemoteManager, \"search_recipes\", new=self._mocked_search_recipes):\n            client.run(\"create . --update\")\n            assert self.counters[\"server0\"] == 1\n            assert self.counters[\"server1\"] == 1\n\n\nclass TestVersionRangesDiamond:\n\n    def test_caching_errors(self):\n        # https://github.com/conan-io/conan/issues/6110\n        c = TestClient(light=True, default_server_user=True)\n        c.save({\"conanfile.py\": GenConanfile(\"zlib\")})\n        c.run(\"create . --version=1.0\")\n        c.run(\"create . --version=1.1\")\n        c.save({\"conanfile.py\": GenConanfile(\"poco\", \"1.0\").with_requires(\"zlib/1.0\")})\n        c.run(\"create .\")\n        c.save({\"conanfile.py\": GenConanfile(\"boost\", \"1.0\").with_requires(\"zlib/[*]\")})\n        c.run(\"create .\")\n\n        c.run(\"upload * -c -r=default\")\n        c.run(\"remove * -c\")\n        c.save({\"conanfile.py\": GenConanfile().with_requires(\"poco/1.0\", \"boost/1.0\")})\n        c.run(\"install .\")  # Ok, no conflict\n        c.run(\"install . --update\")  # Fails due to conflict\n\n\ndef test_prefer_cache_version():\n    \"\"\" the latest version whenever it is\n    https://github.com/conan-io/conan/issues/6544\n    \"\"\"\n    c = TestClient(light=True, default_server_user=True)\n    c.save({\"pkg/conanfile.py\": GenConanfile(\"pkg\"),\n            \"consumer/conanfile.py\": GenConanfile().with_requires(\"pkg/[*]\")})\n    c.run(\"create pkg --version=1.0\")\n    c.run(\"upload * -c -r=default\")\n    c.run(\"install consumer\")\n    c.run(\"create pkg --version=1.1\")\n    c.run(\"install consumer --update\")\n    assert \"pkg/1.1\" in c.out\n    assert \"pkg/1.0\" not in c.out\n"
  },
  {
    "path": "test/integration/graph/version_ranges/version_ranges_diamond_test.py",
    "content": "from collections import OrderedDict\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient, TestServer\n\n\nclass TestVersionRangesUpdatingTest:\n\n    def test_update_remote(self):\n        # https://github.com/conan-io/conan/issues/5333\n        client = TestClient(light=True, default_server_user=True)\n        client.save({\"conanfile.py\": GenConanfile(\"boost\")})\n        client.run(\"create . --version=1.69.0\")\n        client.run(\"create . --version=1.70.0\")\n        client.run(\"upload * -r=default --confirm\")\n        client.run(\"remove * -c\")\n\n        client.save({\"conanfile.txt\": \"[requires]\\nboost/[*]\"}, clean_first=True)\n        client.run(\"install .\")\n        assert \"boost/1.70\" in client.out\n        assert \"boost/1.69\" not in client.out\n\n        client.run(\"install .\")\n        assert \"boost/1.70\" in client.out\n        assert \"boost/1.69\" not in client.out\n\n        client.run(\"install . --update\")\n        assert \"boost/1.70\" in client.out\n        assert \"boost/1.69\" not in client.out\n\n    def test_update(self):\n        client = TestClient(light=True, default_server_user=True)\n\n        client.save({\"pkg/conanfile.py\": GenConanfile(\"pkg\"),\n                     \"app/conanfile.py\": GenConanfile().with_requirement(\"pkg/[~1]\")})\n        client.run(\"create pkg --version=1.1\")\n        client.run(\"create pkg --version=1.2\")\n        client.run(\"upload * -r=default --confirm\")\n        client.run(\"remove pkg/1.2* -c\")\n\n        client.run(\"install app\")\n        # Resolves to local package\n        assert \"pkg/1.1\" in client.out\n        assert \"pkg/1.2\" not in client.out\n\n        client.run(\"install app --update\")\n        # Resolves to remote package\n        assert \"pkg/1.1\" not in client.out\n        assert \"pkg/1.2\" in client.out\n\n        # newer in cache that in remotes and updating, should resolve the cache one\n        client.run(\"create pkg --version=1.3\")\n        client.run(\"install app --update\")\n        assert \"pkg/1.2\" not in client.out\n        assert \"pkg/1.3\" in client.out\n        client.run(\"remove pkg/1.3* -c\")\n\n        # removes remote\n        client.run(\"remove pkg* -r=default -c\")\n        # Resolves to local package\n        client.run(\"install app\")\n        assert \"pkg/1.1\" not in client.out\n        assert \"pkg/1.2\" in client.out\n\n        client.run(\"install app --update\")\n        assert \"pkg/1.1\" not in client.out\n        assert \"pkg/1.2\" in client.out\n\n\nclass TestVersionRangesMultiRemote:\n\n    def test_multi_remote(self):\n        servers = OrderedDict()\n        servers[\"default\"] = TestServer()\n        servers[\"other\"] = TestServer()\n        client = TestClient(light=True, servers=servers, inputs=2*[\"admin\", \"password\"])\n        client.save({\"hello0/conanfile.py\": GenConanfile(\"hello0\"),\n                     \"hello1/conanfile.py\": GenConanfile(\"hello1\").with_requires(\"hello0/[*]\")})\n        client.run(\"export hello0 --version=0.1\")\n        client.run(\"export hello0 --version=0.2\")\n        client.run(\"upload * -r=default -c\")\n        client.run(\"export hello0 --version=0.3\")\n        client.run(\"upload hello0/0.3 -r=other -c\")\n        client.run('remove \"hello0/*\" -c')\n\n        client.run(\"install hello1 --build missing -r=default\")\n        assert \"hello0/0.2\" in client.out\n        assert \"hello0/0.3\" not in client.out\n        client.run(\"remove hello0/* -c\")\n        client.run(\"install hello1 --build missing -r=other\")\n        assert \"hello0/0.2\" not in client.out\n        assert \"hello0/0.3\" in client.out\n"
  },
  {
    "path": "test/integration/layout/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/layout/devflow_test.py",
    "content": "import os\nimport textwrap\n\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import load, mkdir\n\nconanfile = '''\nfrom conan import ConanFile\nfrom conan.tools.files import save, load\nfrom conan.tools.files import copy\nimport os\n\nclass ConanFileToolsTest(ConanFile):\n    name = \"pkg\"\n    version = \"0.1\"\n    exports_sources = \"*\"\n\n    def layout(self):\n        self.folders.build = \"../build\"\n        self.folders.source = \".\"\n\n    def build(self):\n        self.output.info(\"Source files: %s\" % load(self, os.path.join(self.source_folder, \"file.h\")))\n        save(self, \"myartifact.lib\", \"artifact contents!\")\n        save(self, \"subdir/myartifact2.lib\", \"artifact2 contents!\")\n\n    def package(self):\n        copy(self, \"*.h\", self.source_folder, self.package_folder)\n        copy(self, \"*.lib\", self.build_folder, self.package_folder)\n'''\n\n\nclass TestDevInSourceFlow:\n\n    @staticmethod\n    def _assert_pkg(folder):\n        assert sorted(['file.h', 'myartifact.lib', 'subdir', 'conaninfo.txt',\n                       'conanmanifest.txt']) == sorted(os.listdir(folder))\n        assert load(os.path.join(folder, \"myartifact.lib\")) == \"artifact contents!\"\n        assert load(os.path.join(folder, \"subdir/myartifact2.lib\")) == \"artifact2 contents!\"\n\n    def test_parallel_folders(self):\n        client = TestClient(light=True)\n        repo_folder = os.path.join(client.current_folder, \"recipe\")\n        build_folder = os.path.join(client.current_folder, \"build\")\n        mkdir(repo_folder)\n        mkdir(build_folder)\n\n        client.current_folder = repo_folder  # equivalent to git clone recipe\n        client.save({\"conanfile.py\": conanfile,\n                     \"file.h\": \"file_h_contents!\"})\n\n        client.current_folder = build_folder\n        client.run(\"install ../recipe\")\n        client.run(\"build ../recipe\")\n        client.current_folder = repo_folder\n        client.run(\"export . --user=lasote --channel=testing\")\n        client.run(\"export-pkg . --name=pkg --version=0.1 --user=lasote --channel=testing\")\n\n        cache_package_folder = client.created_layout().package()\n        self._assert_pkg(cache_package_folder)\n\n    def test_insource_build(self):\n        client = TestClient(light=True)\n        repo_folder = client.current_folder\n        package_folder = os.path.join(client.current_folder, \"pkg\")\n        mkdir(package_folder)\n        client.save({\"conanfile.py\": conanfile,\n                     \"file.h\": \"file_h_contents!\"})\n\n        client.run(\"install .\")\n        client.run(\"build .\")\n        client.current_folder = repo_folder\n        client.run(\"export . --user=lasote --channel=testing\")\n        client.run(\"export-pkg . --name=pkg --version=0.1 --user=lasote --channel=testing\")\n\n        cache_package_folder = client.created_layout().package()\n        self._assert_pkg(cache_package_folder)\n\n    def test_child_build(self):\n        client = TestClient(light=True)\n        build_folder = os.path.join(client.current_folder, \"build\")\n        mkdir(build_folder)\n        package_folder = os.path.join(build_folder, \"package\")\n        mkdir(package_folder)\n        client.save({\"conanfile.py\": conanfile,\n                     \"file.h\": \"file_h_contents!\"})\n\n        client.current_folder = build_folder\n        client.run(\"install ..\")\n        client.run(\"build ..\")\n        client.run(\"export-pkg .. --name=pkg --version=0.1 --user=lasote --channel=testing\")\n\n        cache_package_folder = client.created_layout().package()\n        self._assert_pkg(cache_package_folder)\n\n\nconanfile_out = '''\nfrom conan import ConanFile\nfrom conan.tools.files import save, load\nfrom conan.tools.files import copy\nimport os\n\nclass ConanFileToolsTest(ConanFile):\n    name = \"pkg\"\n    version = \"0.1\"\n\n    def source(self):\n        save(self, os.path.join(self.source_folder, \"file.h\"), \"file_h_contents!\")\n\n    def build(self):\n        self.output.info(\"Source files: %s\" % load(self, os.path.join(self.source_folder, \"file.h\")))\n        save(self, \"myartifact.lib\", \"artifact contents!\")\n\n    def package(self):\n        copy(self, \"*.h\", self.source_folder, self.package_folder)\n        copy(self, \"*.lib\", self.build_folder, self.package_folder)\n'''\n\n\nclass TestDevOutSourceFlow:\n\n    @staticmethod\n    def _assert_pkg(folder):\n        assert sorted(['file.h', 'myartifact.lib', 'conaninfo.txt', 'conanmanifest.txt']) == \\\n                         sorted(os.listdir(folder))\n\n    def test_parallel_folders(self):\n        client = TestClient(light=True)\n        repo_folder = os.path.join(client.current_folder, \"recipe\")\n        src_folder = os.path.join(client.current_folder, \"src\")\n        build_folder = os.path.join(client.current_folder, \"build\")\n        mkdir(repo_folder)\n        mkdir(src_folder)\n        mkdir(build_folder)\n        client.current_folder = repo_folder  # equivalent to git clone recipe\n        conanfile_final = conanfile_out + \"\"\"\n    def layout(self):\n        self.folders.build = \"../build\"\n        self.folders.source = \"../src\"\n        \"\"\"\n        client.save({\"conanfile.py\": conanfile_final})\n\n        client.current_folder = build_folder\n        client.run(\"install ../recipe\")\n        client.current_folder = src_folder  # FIXME: Source layout not working\n        client.run(\"source ../recipe\")\n\n        client.current_folder = build_folder\n        client.run(\"build ../recipe\")\n        client.current_folder = repo_folder\n        client.run(\"export . --user=lasote --channel=testing\")\n        client.run(\"export-pkg . --name=pkg --version=0.1 --user=lasote --channel=testing\")\n\n        cache_package_folder = client.created_layout().package()\n        self._assert_pkg(cache_package_folder)\n\n    def test_insource_build(self):\n        client = TestClient(light=True)\n        repo_folder = client.current_folder\n        client.save({\"conanfile.py\": conanfile_out})\n\n        client.run(\"install .\")\n        client.run(\"source .\")\n        client.run(\"build . \")\n\n        client.current_folder = repo_folder\n        client.run(\"export . --user=lasote --channel=testing\")\n        client.run(\"export-pkg . --name=pkg --version=0.1 --user=lasote --channel=testing\")\n\n        cache_package_folder = client.created_layout().package()\n        self._assert_pkg(cache_package_folder)\n\n    def test_child_build(self):\n        client = TestClient(light=True)\n        repo_folder = client.current_folder\n        build_folder = os.path.join(client.current_folder, \"build\")\n        mkdir(build_folder)\n        conanfile_final = conanfile_out + \"\"\"\n    def layout(self):\n        self.folders.build = \"build\"\n        \"\"\"\n        client.save({\"conanfile.py\": conanfile_final})\n\n        client.current_folder = build_folder\n        client.run(\"install ..\")\n        client.current_folder = repo_folder  # FIXME: Source layout not working\n        client.run(\"source .\")\n        client.current_folder = build_folder\n        client.run(\"build ..\")\n        client.current_folder = repo_folder\n\n        client.run(\"export-pkg . --name=pkg --version=0.1 --user=lasote --channel=testing\")\n\n        cache_package_folder = client.created_layout().package()\n        self._assert_pkg(cache_package_folder)\n\n\ndef test_error_build_file():\n    c = TestClient(light=True)\n    conanfile_error = textwrap.dedent(r\"\"\"\n        from conan import ConanFile\n        class Test(ConanFile):\n            def layout(self):\n                self.folders.build = \"build\"\n        \"\"\")\n\n    c.save({\"conanfile.py\": conanfile_error,\n            \"build\": \"# Some existing BUILD file like bazel\"})\n    c.run(\"build . \", assert_error=True)\n    assert \"ERROR: conanfile.py: Failed to create build folder, there is already a file\" in c.out\n"
  },
  {
    "path": "test/integration/layout/export_folder_variable_test.py",
    "content": "import textwrap\n\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestExportFoldersAvailability:\n\n    def test_export_sources_folder_availability_local_methods(self):\n        conanfile = textwrap.dedent('''\n        import os\n        from conan import ConanFile\n\n        class ConanLib(ConanFile):\n\n            def layout(self):\n                self.folders.source = \"MY_SOURCE\"\n\n            def generate(self):\n                assert os.path.exists(self.export_sources_folder)\n\n            def export(self):\n                assert self.export_sources_folder is None\n\n            def export_sources(self):\n                assert os.path.exists(self.export_sources_folder)\n\n            def source(self):\n                assert os.path.exists(self.export_sources_folder)\n\n            def build(self):\n                assert os.path.exists(self.export_sources_folder)\n\n            def package(self):\n                assert os.path.exists(self.export_sources_folder)\n\n        ''')\n        client = TestClient()\n        client.save({\"conanfile.py\": conanfile})\n\n        client.run(\"export . --name foo --version 1.0\")\n        client.run(\"install .\")\n        client.run(\"source .\")\n        client.run(\"build .\")\n\n    def test_export_folder_availability_local_methods(self):\n        conanfile = textwrap.dedent('''\n        import os\n        from conan import ConanFile\n\n        class ConanLib(ConanFile):\n\n            def layout(self):\n                self.folders.source = \"MY_SOURCE\"\n\n            def generate(self):\n                assert os.path.exists(self.export_sources_folder)\n\n            def export_sources(self):\n                # We need it available for the post_export hook so it is available\n                assert os.path.exists(self.export_folder)\n\n            def export(self):\n                assert os.path.exists(self.export_folder)\n\n            def source(self):\n                assert os.path.exists(self.export_sources_folder)\n\n            def build(self):\n                assert os.path.exists(self.export_sources_folder)\n\n            def package(self):\n                assert os.path.exists(self.export_sources_folder)\n\n        ''')\n        client = TestClient()\n        client.save({\"conanfile.py\": conanfile})\n\n        client.run(\"export . --name foo --version 1.0\")\n        client.run(\"install .\")\n        client.run(\"source .\")\n        client.run(\"build .\")\n\n    def test_export_folder_availability_create(self):\n        conanfile = textwrap.dedent('''\n        import os\n        from conan import ConanFile\n\n        class ConanLib(ConanFile):\n\n            def layout(self):\n                self.folders.source = \"MY_SOURCE\"\n\n            def generate(self):\n                assert self.export_folder is None\n\n            def export(self):\n                assert os.path.exists(self.export_folder)\n\n            def export_sources(self):\n                # We need it available for the post_export hook so it is available\n                assert os.path.exists(self.export_folder)\n\n            def source(self):\n                assert self.export_folder is None\n\n            def build(self):\n                assert self.export_folder is None\n\n            def package(self):\n                assert self.export_folder is None\n\n        ''')\n        client = TestClient()\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --name foo --version 1.0\")\n\n    def test_export_sources_folder_availability_create(self):\n        conanfile = textwrap.dedent('''\n        import os\n        from conan import ConanFile\n\n        class ConanLib(ConanFile):\n\n            def layout(self):\n                self.folders.source = \"MY_SOURCE\"\n\n            def generate(self):\n                assert os.path.exists(self.export_sources_folder)\n\n            def export(self):\n                assert self.export_sources_folder is None\n\n            def export_sources(self):\n                assert os.path.exists(self.export_sources_folder)\n\n            def source(self):\n                assert os.path.exists(self.export_sources_folder)\n\n            def build(self):\n                assert os.path.exists(self.export_sources_folder)\n\n            def package(self):\n                assert os.path.exists(self.export_sources_folder)\n\n        ''')\n        client = TestClient()\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --name foo --version 1.0\")\n"
  },
  {
    "path": "test/integration/layout/test_cmake_build_folder.py",
    "content": "import os\nimport re\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.parametrize(\"cmd\", [\"install\", \"build\"])\ndef test_cmake_layout_build_folder(cmd):\n    \"\"\" testing the tools.cmake.cmake_layout:build_folder config for\n    both build and install commands\n    \"\"\"\n    c = TestClient()\n    abs_build = temp_folder()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import cmake_layout\n\n        class HelloTestConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"CMakeToolchain\"\n            def layout(self):\n                cmake_layout(self, generator=\"Ninja\")  # Ninja so same in all OSs, single-config\n        \"\"\")\n\n    c.save({\"conanfile.py\": conanfile})\n    c.run(f'{cmd} . -c tools.cmake.cmake_layout:build_folder=\"{abs_build}\"')\n    assert os.path.exists(os.path.join(abs_build, \"Release\", \"generators\", \"conan_toolchain.cmake\"))\n    assert not os.path.exists(os.path.join(c.current_folder, \"build\"))\n\n    # Make sure that a non-existing folder will not fail and will be created\n    new_folder = os.path.join(temp_folder(), \"my build\")\n    c.run(f'{cmd} . -c tools.cmake.cmake_layout:build_folder=\"{new_folder}\"')\n    assert os.path.exists(os.path.join(new_folder, \"Release\", \"generators\", \"conan_toolchain.cmake\"))\n    assert not os.path.exists(os.path.join(c.current_folder, \"build\"))\n\n    # Just in case we check that local build folder would be created if no arg is provided\n    c.run('build . ')\n    assert os.path.exists(os.path.join(c.current_folder, \"build\"))\n\n\n@pytest.mark.parametrize(\"cmd\", [\"install\", \"build\"])\ndef test_cmake_layout_build_folder_relative(cmd):\n    \"\"\" Same as above, but with a relative folder, which is relative to the conanfile\n    \"\"\"\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import cmake_layout\n\n        class HelloTestConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"CMakeToolchain\"\n            def layout(self):\n                cmake_layout(self, generator=\"Ninja\")  # Ninja so same in all OSs, single-config\n        \"\"\")\n\n    c.save({\"pkg/conanfile.py\": conanfile})\n    c.run(f'{cmd} pkg -c tools.cmake.cmake_layout:build_folder=mybuild')\n    abs_build = os.path.join(c.current_folder, \"pkg\", \"mybuild\")\n    assert os.path.exists(os.path.join(abs_build, \"Release\", \"generators\", \"conan_toolchain.cmake\"))\n    assert not os.path.exists(os.path.join(c.current_folder, \"pkg\", \"build\"))\n\n    # relative path, pointing to a sibling folder\n    c.run(f'{cmd} pkg -c tools.cmake.cmake_layout:build_folder=../mybuild')\n    abs_build = os.path.join(c.current_folder, \"mybuild\")\n    assert os.path.exists(os.path.join(abs_build, \"Release\", \"generators\", \"conan_toolchain.cmake\"))\n    assert not os.path.exists(os.path.join(c.current_folder, \"build\"))\n\n    # Just in case we check that local build folder would be created if no arg is provided\n    c.run('build pkg ')\n    assert os.path.exists(os.path.join(c.current_folder, \"pkg\", \"build\"))\n\n\ndef test_test_cmake_layout_build_folder_test_package():\n    \"\"\" relocate the test_package temporary build folders to elsewhere\n    \"\"\"\n    c = TestClient()\n    abs_build = temp_folder()\n    test_conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import cmake_layout\n\n        class HelloTestConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"CMakeToolchain\"\n\n            def requirements(self):\n                self.requires(self.tested_reference_str)\n\n            def layout(self):\n                cmake_layout(self, generator=\"Ninja\")\n\n            def test(self):\n                pass\n        \"\"\")\n\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\"),\n            \"test_package/conanfile.py\": test_conanfile})\n    c.run(f'create . -c tools.cmake.cmake_layout:test_folder=\"{abs_build}\" '\n          '-c tools.cmake.cmake_layout:build_folder_vars=[]')\n    # Even if build_folder_vars=[] the \"Release\" folder is added always\n    assert os.path.exists(os.path.join(abs_build, \"Release\", \"generators\", \"conan_toolchain.cmake\"))\n    assert not os.path.exists(os.path.join(c.current_folder, \"test_package\", \"build\"))\n\n    c.run(f'create . -c tools.cmake.cmake_layout:build_folder_vars=[]')\n    assert os.path.exists(os.path.join(c.current_folder, \"test_package\", \"build\"))\n\n\ndef test_test_cmake_layout_build_folder_test_package_temp():\n    \"\"\" using always the same test_package build_folder will cause collisions.\n    We need a mechanism to relocate, still provide unique folders for each build\n    \"\"\"\n    c = TestClient()\n    test_conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import cmake_layout\n\n        class HelloTestConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"CMakeToolchain\"\n\n            def requirements(self):\n                self.requires(self.tested_reference_str)\n\n            def layout(self):\n                cmake_layout(self)\n\n            def test(self):\n                pass\n        \"\"\")\n\n    profile = textwrap.dedent(\"\"\"\n        include(default)\n        [conf]\n        tools.cmake.cmake_layout:test_folder=$TMP\n        tools.cmake.cmake_layout:build_folder_vars=[]\n        \"\"\")\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\"),\n            \"test_package/conanfile.py\": test_conanfile,\n            \"profile\": profile})\n    c.run(f'create . -pr=profile')\n    build_folder = re.search(r\"Test package build folder: (\\S+)\", str(c.out)).group(1)\n    assert os.path.exists(os.path.join(build_folder, \"generators\", \"conan_toolchain.cmake\"))\n    assert not os.path.exists(os.path.join(c.current_folder, \"test_package\", \"build\"))\n\n    c.run(f'test test_package pkg/0.1 -pr=profile')\n    build_folder = re.search(r\"Test package build folder: (\\S+)\", str(c.out)).group(1)\n    assert os.path.exists(os.path.join(build_folder, \"generators\", \"conan_toolchain.cmake\"))\n    assert not os.path.exists(os.path.join(c.current_folder, \"test_package\", \"build\"))\n\n    c.run(f'create . -c tools.cmake.cmake_layout:build_folder_vars=[]')\n    assert os.path.exists(os.path.join(c.current_folder, \"test_package\", \"build\"))\n\n\ndef test_cmake_layout_build_folder_editable():\n    \"\"\" testing how it works with editables. Layout\n    code\n      pkga  # editable add .\n      pkgb  # editable add .\n      app   # install -c build_folder=\"../../mybuild -c build_folder_vars=\"['self.name']\"\n        pkga-release-data.cmake\n           pkga_PACKAGE_FOLDER_RELEASE = /abs/path/to/code/pkga\n           pkga_INCLUDE_DIRS_RELEASE   = ${pkga_PACKAGE_FOLDER_RELEASE}/include\n           pkga_LIB_DIRS_RELEASE =       /abs/path/to/mybuild/pkga/Release\n    mybuild\n      pkga/Release/\n      pkgb/Release/\n    \"\"\"\n    c = TestClient()\n    base_folder = temp_folder()\n    c.current_folder = os.path.join(base_folder, \"code\").replace(\"\\\\\", \"/\")\n    project_build_folder = os.path.join(base_folder, \"mybuild\").replace(\"\\\\\", \"/\")\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import cmake_layout\n\n        class Pkg(ConanFile):\n            name = \"{name}\"\n            version = \"0.1\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"CMakeToolchain\"\n            def layout(self):\n                cmake_layout(self, generator=\"Ninja\")  # Ninja so same in all OSs, single-config\n        \"\"\")\n\n    c.save({\"pkga/conanfile.py\": conanfile.format(name=\"pkga\"),\n            \"pkgb/conanfile.py\": conanfile.format(name=\"pkgb\"),\n            \"app/conanfile.py\": GenConanfile().with_requires(\"pkga/0.1\", \"pkgb/0.1\")\n                                              .with_settings(\"build_type\")\n                                              .with_generator(\"CMakeDeps\")})\n\n    c.run(\"editable add pkga\")\n    c.run(\"editable add pkgb\")\n    conf = f'-c tools.cmake.cmake_layout:build_folder=\"../../mybuild\" ' \\\n           '-c tools.cmake.cmake_layout:build_folder_vars=\"[\\'self.name\\']\"'\n    c.run(f'install app {conf} --build=editable')\n\n    data = c.load(\"app/pkga-release-data.cmake\")\n\n    # The package is the ``code/pkga`` folder\n    assert f'pkga_PACKAGE_FOLDER_RELEASE \"{c.current_folder}/pkga\"' in data\n    # This is an absolute path, not relative, as it is not inside the package\n    assert f'set(pkga_LIB_DIRS_RELEASE \"{project_build_folder}/pkga/Release' in data\n    data = c.load(\"app/pkgb-release-data.cmake\")\n    assert f'set(pkgb_LIB_DIRS_RELEASE \"{project_build_folder}/pkgb/Release' in data\n\n    assert os.path.exists(os.path.join(project_build_folder, \"pkga\", \"Release\", \"generators\",\n                                       \"conan_toolchain.cmake\"))\n    assert os.path.exists(os.path.join(project_build_folder, \"pkgb\", \"Release\", \"generators\",\n                                       \"conan_toolchain.cmake\"))\n\n\ndef test_cmake_layout_editable_output_folder():\n    \"\"\" testing how it works with editables, but --output-folder\n    code\n      pkga  # editable add . --output-folder = ../mybuild\n      pkgb  # editable add . --output-folder = ../mybuild\n      app   # install  -c build_folder_vars=\"['self.name']\"\n        pkga-release-data.cmake\n           pkga_PACKAGE_FOLDER_RELEASE = /abs/path/to/mybuild\n           pkga_INCLUDE_DIRS_RELEASE   = /abs/path/to/code/pkga/include\n           pkga_LIB_DIRS_RELEASE =       pkga_PACKAGE_FOLDER_RELEASE/build/pkga/Release\n    mybuild\n      build\n        pkga/Release/\n        pkgb/Release/\n    \"\"\"\n    c = TestClient()\n    base_folder = temp_folder()\n    c.current_folder = os.path.join(base_folder, \"code\")\n    project_build_folder = os.path.join(base_folder, \"mybuild\").replace(\"\\\\\", \"/\")\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import cmake_layout\n\n        class Pkg(ConanFile):\n            name = \"{name}\"\n            version = \"0.1\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"CMakeToolchain\"\n            def layout(self):\n                cmake_layout(self, generator=\"Ninja\")  # Ninja so same in all OSs, single-config\n        \"\"\")\n\n    c.save({\"pkga/conanfile.py\": conanfile.format(name=\"pkga\"),\n            \"pkgb/conanfile.py\": conanfile.format(name=\"pkgb\"),\n            \"app/conanfile.py\": GenConanfile().with_requires(\"pkga/0.1\", \"pkgb/0.1\")\n           .with_settings(\"build_type\")\n           .with_generator(\"CMakeDeps\")})\n\n    c.run(f'editable add pkga --output-folder=\"../mybuild\"')\n    c.run(f'editable add pkgb --output-folder=\"../mybuild\"')\n    conf = f'-c tools.cmake.cmake_layout:build_folder_vars=\"[\\'self.name\\']\"'\n    c.run(f'install app {conf} --build=editable')\n\n    data = c.load(\"app/pkga-release-data.cmake\")\n    assert f'set(pkga_PACKAGE_FOLDER_RELEASE \"{project_build_folder}\")' in data\n    # Thse folders are relative to the package\n    assert 'pkga_LIB_DIRS_RELEASE \"${pkga_PACKAGE_FOLDER_RELEASE}/build/pkga/Release' in data\n    data = c.load(\"app/pkgb-release-data.cmake\")\n    assert 'pkgb_LIB_DIRS_RELEASE \"${pkgb_PACKAGE_FOLDER_RELEASE}/build/pkgb/Release' in data\n\n    assert os.path.exists(os.path.join(project_build_folder, \"build\", \"pkga\", \"Release\",\n                                       \"generators\", \"conan_toolchain.cmake\"))\n    assert os.path.exists(os.path.join(project_build_folder, \"build\", \"pkgb\", \"Release\",\n                                       \"generators\", \"conan_toolchain.cmake\"))\n"
  },
  {
    "path": "test/integration/layout/test_layout_generate.py",
    "content": "import os\nimport textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_layout_generate():\n    \"\"\" Trying to leverage the layout knowledge at generate() time and put some files\n    in the bindirs folders where executables will be built, like some dll from other\n    dependencies.\n    https://github.com/conan-io/conan/issues/12003\n    \"\"\"\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import save, load\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"1.0\"\n            def layout(self):\n                self.folders.build = \"mybuild\"\n                self.folders.generators = \"mybuild/generators\"\n                self.cpp.build.bindirs = [\"bin\"]\n                self.cpp.build.libdirs = [\"lib\"]\n                self.cpp.build.includedirs = [\"include\"]\n            def generate(self):\n                f = os.path.join(self.build_folder, self.cpp.build.bindir, \"myfile.txt\")\n                save(self, f, \"mybin!!!\")\n                f = os.path.join(self.build_folder, self.cpp.build.libdir, \"myfile.txt\")\n                save(self, f, \"mylib!!!\")\n                f = os.path.join(self.build_folder, self.cpp.build.includedir, \"myfile.txt\")\n                save(self, f, \"myinclude!!!\")\n\n            def build(self):\n                self.output.info(load(self, os.path.join(self.cpp.build.libdir, \"myfile.txt\")))\n                self.output.info(load(self, os.path.join(self.cpp.build.bindir, \"myfile.txt\")))\n                self.output.info(load(self, os.path.join(self.cpp.build.includedir, \"myfile.txt\")))\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"create . \")\n    assert \"pkg/1.0: mybin!!!\" in c.out\n    assert \"pkg/1.0: mylib!!!\" in c.out\n    assert \"pkg/1.0: myinclude!!!\" in c.out\n    c.run(\"install .\")\n    assert os.path.exists(os.path.join(c.current_folder, \"mybuild\", \"bin\", \"myfile.txt\"))\n    assert os.path.exists(os.path.join(c.current_folder, \"mybuild\", \"lib\", \"myfile.txt\"))\n    assert os.path.exists(os.path.join(c.current_folder, \"mybuild\", \"include\", \"myfile.txt\"))\n\n\ndef test_generate_source_folder():\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.cmake import cmake_layout\n\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n            def layout(self):\n                cmake_layout(self)\n\n            def generate(self):\n                self.output.info(\"PKG_CONFIG_PATH {}!\".format(os.path.exists(self.source_folder)))\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"install .\")\n    assert \"PKG_CONFIG_PATH True!\" in c.out\n\n\ndef test_generate_source_folder_test_package():\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.cmake import cmake_layout\n\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n            def requirements(self):\n                self.requires(self.tested_reference_str)\n\n            def layout(self):\n                cmake_layout(self)\n\n            def generate(self):\n                self.output.info(\"PKG_CONFIG_PATH {}!\".format(os.path.exists(self.source_folder)))\n\n            def test(self):\n                pass\n        \"\"\")\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\"),\n            \"test_package/conanfile.py\": conanfile})\n    c.run(\"create .\")\n    assert \"PKG_CONFIG_PATH True!\" in c.out\n\n\ndef test_generate_build_folder_test_package():\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.cmake import cmake_layout\n\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n            def requirements(self):\n                self.requires(self.tested_reference_str)\n\n            def layout(self):\n                cmake_layout(self)\n\n            def generate(self):\n                self.output.info(f\"build_folder in test_package: {bool(self.build_folder)}\")\n\n            def test(self):\n                pass\n        \"\"\")\n\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\"),\n            \"test_package/conanfile.py\": conanfile})\n    c.run(\"create .\")\n    assert f\"build_folder in test_package: True\" in c.out\n\n\nclass TestCustomTestPackage:\n    def test_custom_test_package(self):\n        c = TestClient(light=True)\n        conanfile = GenConanfile(\"pkg\", \"0.1\").with_class_attribute('test_package_folder=\"mytest\"')\n        c.save({\"conanfile.py\": conanfile,\n                \"mytest/conanfile.py\": GenConanfile().with_test(\"self.output.info('MYTEST!')\"),\n                \"mytest2/conanfile.py\": GenConanfile().with_test(\"self.output.info('MYTEST2!')\")})\n        c.run(\"create .\")\n        assert \"MYTEST!\" in c.out\n        c.run(\"create . -tf=mytest2\")\n        assert \"MYTEST2!\" in c.out\n\n    def test_custom_test_package_subfolder(self):\n        c = TestClient(light=True)\n        conanfile = GenConanfile(\"pkg\", \"0.1\").with_class_attribute('test_package_folder=\"my/test\"')\n        c.save({\"pkg/conanfile.py\": conanfile,\n                \"pkg/my/test/conanfile.py\": GenConanfile().with_test(\"self.output.info('MYTEST!')\")})\n        c.run(\"create pkg\")\n        assert \"MYTEST!\" in c.out\n\n    def test_custom_test_package_sibling(self):\n        c = TestClient(light=True)\n        conanfile = GenConanfile(\"pkg\", \"0.1\").with_class_attribute(\n            'test_package_folder=\"../my/test\"')\n        c.save({\"pkg/conan/conanfile.py\": conanfile,\n                \"pkg/my/test/conanfile.py\": GenConanfile().with_test(\"self.output.info('MYTEST!')\")})\n        c.run(\"create pkg/conan\")\n        assert \"MYTEST!\" in c.out\n\n    def test_custom_test_package_export_pkg(self):\n        c = TestClient(light=True)\n        conanfile = GenConanfile(\"pkg\", \"0.1\").with_class_attribute('test_package_folder=\"mytest\"')\n        c.save({\"pkg/conanfile.py\": conanfile,\n                \"pkg/mytest/conanfile.py\": GenConanfile().with_test(\"self.output.info('MYTEST!')\")})\n        c.run(\"export-pkg pkg\")\n        assert \"MYTEST!\" in c.out\n"
  },
  {
    "path": "test/integration/layout/test_layout_paths.py",
    "content": "import os\nimport textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_editable_layout_paths():\n    # https://github.com/conan-io/conan/issues/12521\n    # https://github.com/conan-io/conan/issues/12839\n    c = TestClient()\n    dep = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import save\n        class Dep(ConanFile):\n            name = \"dep\"\n            version = \"0.1\"\n            def layout(self):\n                self.cpp.source.includedirs = [\"include\"]\n            \"\"\")\n    c.save({\"dep/conanfile.py\": dep,\n            \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_settings(\"build_type\", \"arch\")\n                                                          .with_requires(\"dep/0.1\")\n                                                          .with_generator(\"CMakeDeps\")\n                                                          .with_generator(\"PkgConfigDeps\")\n                                                          .with_generator(\"XcodeDeps\")})\n    c.run(\"editable add dep\")\n    c.run(\"install pkg -s arch=x86_64\")\n    # It doesn't crash anymore\n\n    assert \"dep/0.1:da39a3ee5e6b4b0d3255bfef95601890afd80709 - Editable\" in c.out\n    data = c.load(f\"pkg/dep-release-x86_64-data.cmake\")\n\n    assert 'set(dep_INCLUDE_DIRS_RELEASE \"${dep_PACKAGE_FOLDER_RELEASE}/include\")' in data\n    pc = c.load(\"pkg/dep.pc\")\n    assert \"includedir=${prefix}/include\" in pc\n    xcode = c.load(\"pkg/conan_dep_dep_release_x86_64.xcconfig\")\n    dep_path = os.path.join(c.current_folder, \"dep\")\n    assert f\"PACKAGE_ROOT_dep[config=Release][arch=x86_64][sdk=*] = {dep_path}\" in xcode\n\n\ndef test_layout_paths_normalized():\n    # make sure the paths doesn't end with trailing \".\", and they are identical to the cwd\n    c = TestClient()\n    dep = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n\n        class Dep(ConanFile):\n            name = \"dep\"\n            version = \"0.1\"\n            def layout(self):\n                self.folders.source = \".\"\n                self.folders.build = \".\"\n                self.folders.generators = \".\"\n\n            def build(self):\n                assert os.getcwd() == self.source_folder\n                assert os.getcwd() == self.build_folder\n                assert os.getcwd() == self.generators_folder\n\n            \"\"\")\n    c.save({\"conanfile.py\": dep})\n    c.run(\"build .\")\n    # It doesn't assert in the build()\n"
  },
  {
    "path": "test/integration/layout/test_legacy_cpp_info_and_layout.py",
    "content": "import textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\n\n# TODO: This test does not make sense for Conan v2. Please, remove/skip it in that case.\n@pytest.mark.parametrize(\"declare_layout\", [True, False])\ndef test_legacy_deps_cpp_info_deps_version_using_or_not_layout(declare_layout):\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n\n    class HelloConan(ConanFile):\n        name = \"hello\"\n        version = \"1.0\"\n        {}\n        def package_info(self):\n            self.cpp_info.libs = [\"hello\"]\n    \"\"\".format(\"def layout(self):pass\" if declare_layout else \"\"))\n    test_conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n\n    class HelloTestConan(ConanFile):\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n        def requirements(self):\n            self.requires(self.tested_reference_str)\n\n        def generate(self):\n            self.output.info(self.dependencies[\"hello\"].ref.version)\n\n        def test(self):\n            pass\n    \"\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile, \"test_package/conanfile.py\": test_conanfile})\n    client.run(\"create .\")\n    assert \"hello/1.0 (test package): 1.0\" in client.out\n"
  },
  {
    "path": "test/integration/lockfile/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/lockfile/test_ci.py",
    "content": "import json\nimport textwrap\n\nimport pytest\n\nfrom conan.api.model import RecipeReference\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\nconanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    from conan.tools.files import load, copy\n    import os\n    class Pkg(ConanFile):\n        settings = \"os\"\n        {requires}\n        exports_sources = \"myfile.txt\"\n\n        def generate(self):\n            # Simulate an \"imports\"\n            for dep in self.dependencies.values():\n                dest_folder = os.path.join(self.build_folder, dep.ref.name)\n                copy(self, \"myfile.txt\", dep.package_folder, dest_folder)\n\n        def package(self):\n            # Copy the ones from the dependencies\n            copied = copy(self, \"*myfile.txt\", self.build_folder, self.package_folder, keep_path=True)\n            # Copy the exported one\n            copied = copy(self, \"myfile.txt\", self.source_folder, self.package_folder)\n            assert len(copied) == 1\n\n        def package_info(self):\n            self.output.info(\"SELF OS: %s!!\" % self.settings.os)\n            self.output.info(\"SELF FILE: %s\"\n                % load(self, os.path.join(self.package_folder, \"myfile.txt\")))\n            for d in os.listdir(self.package_folder):\n                p = os.path.join(self.package_folder, d, \"myfile.txt\")\n                if os.path.isfile(p):\n                    self.output.info(\"DEP FILE %s: %s\" % (d, load(self, p)))\n        \"\"\")\n\n\npkgawin_01_id = \"ebec3dc6d7f6b907b3ada0c3d3cdc83613a2b715\"\npkganix_01_id = \"9a4eb3c8701508aa9458b1a73d0633783ecc2270\"\npkgb_01_id = \"65becc9bdccee92972f365ae4f742dd4b046d1e0\"\npkgb_012_id = \"c753def4818cdc538183046f6149134eb4be7a32\"\npkgc_01_id = \"2a23b96aea3b4787fcd1816182e8a403349b0815\"\npkgapp_01_id = \"f8e4cc2232dff5983eeb2e7403b9c2dc755be44f\"\n\n\n@pytest.fixture()\ndef client_setup():\n    c = TestClient(light=True)\n    pkb_requirements = \"\"\"\n    def requirements(self):\n        if self.settings.os == \"Windows\":\n            self.requires(\"pkgawin/[>0.0 <1.0]\")\n        else:\n            self.requires(\"pkganix/[>0.0 <1.0]\")\n    \"\"\"\n    files = {\n        \"pkga/conanfile.py\": conanfile.format(requires=\"\"),\n        \"pkga/myfile.txt\": \"HelloA\",\n        \"pkgj/conanfile.py\": conanfile.format(requires=\"\"),\n        \"pkgj/myfile.txt\": \"HelloJ\",\n        \"pkgb/conanfile.py\": conanfile.format(requires=pkb_requirements),\n        \"pkgb/myfile.txt\": \"HelloB\",\n        \"pkgc/conanfile.py\": conanfile.format(requires='requires=\"pkgb/[>0.0 <1.0]\"'),\n        \"pkgc/myfile.txt\": \"HelloC\",\n        \"app1/conanfile.py\": conanfile.format(requires='requires=\"pkgc/[>0.0 <1.0]\"'),\n        \"app1/myfile.txt\": \"App1\",\n    }\n    c.save(files)\n\n    c.run(\"create pkga --name=pkgawin --version=0.1 -s os=Windows\")\n    c.run(\"create pkga --name=pkganix --version=0.1 -s os=Linux\")\n    c.run(\"create pkgb --name=pkgb --version=0.1 -s os=Windows\")\n    c.run(\"create pkgc --name=pkgc --version=0.1 -s os=Windows\")\n    c.run(\"create app1 --name=app1 --version=0.1 -s os=Windows\")\n    assert \"app1/0.1: SELF FILE: App1\" in c.out\n    assert \"app1/0.1: DEP FILE pkgawin: HelloA\" in c.out\n    assert \"app1/0.1: DEP FILE pkgb: HelloB\" in c.out\n    assert \"app1/0.1: DEP FILE pkgc: HelloC\" in c.out\n    return c\n\n\ndef test_single_config_centralized(client_setup):\n    \"\"\" app1 -> pkgc/0.1 -> pkgb/0.1 -> pkgawin/0.1 or pkganix/0.1\n    all version-ranges [>0 <1.0]\n    lock app1.lock to lock graph including pkgawin/0.1 and pkganix/0.1\n    changes in pkgawin/0.2 and pkganix/0.2 are excluded by lockfile\n    a change in pkgb produces a new pkgb/0.2 that we want to test if works in app1 lockfile\n    the app1 can be built in a single node, including all necessary dependencies\n    the final lockfile will include pkgb/0.2, and not pkgb/0.1\n    \"\"\"\n    c = client_setup\n    # capture the initial lockfile of our product\n    c.run(\"lock create --requires=app1/0.1@  --lockfile-out=app1.lock -s os=Windows\")\n\n    # Do an unrelated change in A, should not be used, this is not the change we are testing\n    c.save({\"pkga/myfile.txt\": \"ByeA World!!\",\n            \"pkgb/myfile.txt\": \"ByeB World!!\",\n            \"pkgc/myfile.txt\": \"ByeC World!!\"})\n    c.run(\"export pkga --name=pkgawin --version=0.2\")  # this will never be used\n    c.run(\"export pkgc --name=pkgc --version=0.2\")  # this will never be used\n\n    # Test that pkgb/0.2 works\n    c.run(\"create pkgb --name=pkgb --version=0.2 -s os=Windows \"\n          \"--lockfile=app1.lock --lockfile-out=app1_b_changed.lock\")\n    assert \"pkgb/0.2: DEP FILE pkgawin: HelloA\" in c.out\n\n    # Now lets build the application, to see everything ok\n    c.run(\"install --requires=app1/0.1@  --lockfile=app1_b_changed.lock \"\n          \"--lockfile-out=app1_b_integrated.lock \"\n          \"--build=missing  -s os=Windows\")\n    c.assert_listed_binary({\"pkgawin/0.1\": (pkgawin_01_id, \"Cache\"),\n                            \"pkgb/0.2\": (pkgb_01_id, \"Cache\"),\n                            \"pkgc/0.1\": (pkgc_01_id, \"Build\"),\n                            \"app1/0.1\": (pkgapp_01_id, \"Build\")})\n    assert \"pkgb/0.2\" in c.out\n    assert \"pkgb/0.1\" not in c.out\n    assert \"app1/0.1: DEP FILE pkgawin: HelloA\" in c.out\n    assert \"app1/0.1: DEP FILE pkgb: ByeB World!!\" in c.out\n\n    # All good! We can get rid of the now unused pkgb/0.1 version in the lockfile\n    c.run(\"lock create --requires=app1/0.1@ --lockfile=app1_b_integrated.lock \"\n          \"--lockfile-out=app1_clean.lock -s os=Windows --lockfile-clean\")\n    app1_clean = c.load(\"app1_clean.lock\")\n    assert \"pkgb/0.2\" in app1_clean\n    assert \"pkgb/0.1\" not in app1_clean\n\n\ndef test_single_config_centralized_out_range(client_setup):\n    \"\"\" same scenario as \"test_single_config_centralized()\"\n    But pkgb/0.1 change version is bumped to pkgb/1.0, which doesn't fit in the consumers\n    version range, so it is not used.\n    Nothing to build in the app1, and the final lockfile doesn't change at all\n    \"\"\"\n    c = client_setup\n    c.run(\"lock create --requires=app1/0.1@ --lockfile-out=app1.lock -s os=Windows\")\n\n    # Do an unrelated change in A, should not be used, this is not the change we are testing\n    c.save({\"pkga/myfile.txt\": \"ByeA World!!\"})\n    c.run(\"create pkga --name=pkgawin --version=0.2 -s os=Windows\")\n\n    # Do a change in B, this is the change that we want to test\n    c.save({\"pkgb/myfile.txt\": \"ByeB World!!\"})\n\n    # Test that pkgb/1.0 works (but it is out of valid range!)\n    c.run(\"create pkgb --name=pkgb --version=1.0 -s os=Windows \"\n          \"--lockfile=app1.lock --lockfile-out=app1_b_changed.lock\")\n    assert \"pkgb/1.0: DEP FILE pkgawin: HelloA\" in c.out\n\n    # Now lets build the application, to see everything ok\n    c.run(\"install --requires=app1/0.1@  --lockfile=app1_b_changed.lock \"\n          \"--lockfile-out=app1_b_integrated.lock \"\n          \"--build=missing  -s os=Windows\")\n    # Nothing changed, the change is outside the range, app1 not affected!!\n    c.assert_listed_binary({\"pkgawin/0.1\": (pkgawin_01_id, \"Cache\"),\n                            \"pkgb/0.1\": (pkgb_01_id, \"Cache\"),\n                            \"pkgc/0.1\": (\"3b0c170cc929d4a1916489ce2dbb881fdad07f2e\", \"Cache\"),\n                            \"app1/0.1\": (\"3b0234ea72056ce9a0eb06584b4be6d73089e0e2\", \"Cache\")})\n    assert \"pkgb/0.2\" not in c.out\n    assert \"app1/0.1: DEP FILE pkgawin: HelloA\" in c.out\n    assert \"app1/0.1: DEP FILE pkgb: HelloB\" in c.out\n\n    # All good! We can get rid of the now unused pkgb/1.0 version in the lockfile\n    c.run(\"lock create --requires=app1/0.1@ --lockfile=app1_b_integrated.lock \"\n          \"--lockfile-out=app1_clean.lock -s os=Windows --lockfile-clean\")\n    app1_clean = c.load(\"app1_clean.lock\")\n    assert \"pkgb/0.1\" in app1_clean\n    assert \"pkgb/1.0\" not in app1_clean\n\n\ndef test_single_config_centralized_change_dep(client_setup):\n    \"\"\" same scenario as \"test_single_config_centralized()\".\n    But pkgb/0.1 change version is bumped to pkgb/0.2, and changes dependency from pkgA=>pkgJ\n    \"\"\"\n    c = client_setup\n    c.run(\"lock create --requires=app1/0.1@ --lockfile-out=app1.lock -s os=Windows\")\n\n    # Do an unrelated change in A, should not be used, this is not the change we are testing\n    c.save({\"pkga/myfile.txt\": \"ByeA World!!\"})\n    c.run(\"create pkga --name=pkgawin --version=0.2 -s os=Windows\")\n\n    # Build new package alternative J\n    c.run(\"create pkgj --name=pkgj --version=0.1 -s os=Windows\")\n\n    # Do a change in B, this is the change that we want to test\n    c.save({\"pkgb/conanfile.py\": conanfile.format(requires='requires=\"pkgj/[>0.0 <1.0]\"'),\n            \"pkgb/myfile.txt\": \"ByeB World!!\"})\n\n    # Test that pkgb/0.2 works\n    c.run(\"create pkgb --name=pkgb --version=0.2 -s os=Windows \"\n          \"--lockfile=app1.lock --lockfile-out=app1_b_changed.lock --lockfile-partial\")\n    assert \"pkgb/0.2: DEP FILE pkgj: HelloJ\" in c.out\n    # Build new package alternative J, it won't be included, already locked in this create\n    c.run(\"create pkgj --name=pkgj --version=0.2 -s os=Windows\")\n\n    # Now lets build the application, to see everything ok\n    c.run(\"install --requires=app1/0.1@  --lockfile=app1_b_changed.lock \"\n          \"--lockfile-out=app1_b_integrated.lock \"\n          \"--build=missing  -s os=Windows\")\n    assert \"pkga/\" not in c.out\n    c.assert_listed_binary({\"pkgj/0.1\": (pkgawin_01_id, \"Cache\"),\n                            \"pkgb/0.2\": (\"79caa65bc5877c4ada84a2b454775f47a5045d59\", \"Cache\"),\n                            \"pkgc/0.1\": (\"67e4e9b17f41a4c71ff449eb29eb716b8f83767b\", \"Build\"),\n                            \"app1/0.1\": (\"f7eb3b81ac34ddecd04301afad031ee078c5ab3c\", \"Build\")})\n    assert \"app1/0.1: DEP FILE pkgj: HelloJ\" in c.out\n    assert \"app1/0.1: DEP FILE pkgb: ByeB World!!\" in c.out\n\n    # All good! We can get rid of the now unused pkgb/1.0 version in the lockfile\n    c.run(\"lock create --requires=app1/0.1@ --lockfile=app1_b_integrated.lock \"\n          \"--lockfile-out=app1_clean.lock -s os=Windows --lockfile-clean\")\n    app1_clean = c.load(\"app1_clean.lock\")\n    assert \"pkgj/0.1\" in app1_clean\n    assert \"pkgb/0.2\" in app1_clean\n    assert \"pkgb/0.1\" not in app1_clean\n\n\ndef test_multi_config_centralized(client_setup):\n    \"\"\" same scenario as above, but now we want to manage 2 configurations Windows & Linux\n    When pkgB is changed, it is built for both, and produces app1_win.lock and app2_linux.lock\n    With those, app1 can be built in a single node for both configurations. After building\n    app1, the 2 lockfiles can be cleaned (removing the old pkgb/0.1, leaving pkgb/0.2 in the lock)\n    The 2 final lockfiles can be \"merged\" in a single one for next iteration\n    \"\"\"\n    c = client_setup\n    # capture the initial lockfile of our product\n    c.run(\"lock create --requires=app1/0.1@ --lockfile-out=app1.lock -s os=Windows\")\n    c.run(\"lock create --requires=app1/0.1@ --lockfile=app1.lock --lockfile-out=app1.lock \"\n          \"-s os=Linux\")\n\n    # Do an unrelated change in A, should not be used, this is not the change we are testing\n    c.save({\"pkga/myfile.txt\": \"ByeA World!!\"})\n    c.run(\"create pkga --name=pkgawin --version=0.2 -s os=Windows\")\n    c.run(\"create pkga --name=pkganix --version=0.2 -s os=Linux\")\n\n    # Do a change in B, this is the change that we want to test\n    c.save({\"pkgb/myfile.txt\": \"ByeB World!!\"})\n\n    # Test that pkgb/0.2 works\n    c.run(\"create pkgb --name=pkgb --version=0.2 -s os=Windows \"\n          \"--lockfile=app1.lock --lockfile-out=app1_win.lock\")\n    assert \"pkgb/0.2: DEP FILE pkgawin: HelloA\" in c.out\n    c.run(\"create pkgb --name=pkgb --version=0.2 -s os=Linux \"\n          \"--lockfile=app1.lock --lockfile-out=app1_nix.lock\")\n    assert \"pkgb/0.2: DEP FILE pkganix: HelloA\" in c.out\n\n    # Now lets build the application, to see everything ok\n    c.run(\"install --requires=app1/0.1@  --lockfile=app1_win.lock --lockfile-out=app1_win.lock \"\n          \"--build=missing  -s os=Windows\")\n    c.assert_listed_binary({\"pkgawin/0.1\": (pkgawin_01_id, \"Cache\"),\n                            \"pkgb/0.2\": (pkgb_01_id, \"Cache\"),\n                            \"pkgc/0.1\": (pkgc_01_id, \"Build\"),\n                            \"app1/0.1\": (pkgapp_01_id, \"Build\")})\n    assert \"pkgb/0.2\" in c.out\n    assert \"pkgb/0.1\" not in c.out\n    assert \"app1/0.1: DEP FILE pkgawin: HelloA\" in c.out\n    assert \"app1/0.1: DEP FILE pkgb: ByeB World!!\" in c.out\n\n    # Now lets build the application, to see everything ok\n    c.run(\"install --requires=app1/0.1@  --lockfile=app1_nix.lock --lockfile-out=app1_nix.lock \"\n          \"--build=missing  -s os=Linux\")\n    c.assert_listed_binary({\"pkganix/0.1\": (pkganix_01_id, \"Cache\"),\n                            \"pkgb/0.2\": (pkgb_012_id, \"Cache\"),\n                            \"pkgc/0.1\": (\"2a4113733176ffbce61bbcb4dd0e76ecc162439c\", \"Build\"),\n                            \"app1/0.1\": (\"6c198f82674d988b90eed54b52a494a5bbf09c41\", \"Build\")})\n    assert \"pkgb/0.2\" in c.out\n    assert \"pkgb/0.1\" not in c.out\n    assert \"app1/0.1: DEP FILE pkganix: HelloA\" in c.out\n    assert \"app1/0.1: DEP FILE pkgb: ByeB World!!\" in c.out\n\n    # All good! We can get rid of the now unused pkgb/0.1 version in the lockfile\n    c.run(\"lock create --requires=app1/0.1@ --lockfile=app1_win.lock \"\n          \"--lockfile-out=app1_win.lock -s os=Windows --lockfile-clean\")\n    app1_clean = c.load(\"app1_win.lock\")\n    assert \"pkgawin/0.1\" in app1_clean\n    assert \"pkgb/0.2\" in app1_clean\n    assert \"pkgb/0.1\" not in app1_clean\n    assert \"pkgawin/0.2\" not in app1_clean\n    assert \"pkganix/0.2\" not in app1_clean\n    c.run(\"lock create --requires=app1/0.1@ --lockfile=app1_nix.lock \"\n          \"--lockfile-out=app1_nix.lock -s os=Linux --lockfile-clean\")\n    app1_clean = c.load(\"app1_nix.lock\")\n    assert \"pkganix/0.1\" in app1_clean\n    assert \"pkgb/0.2\" in app1_clean\n    assert \"pkgb/0.1\" not in app1_clean\n    assert \"pkgawin/0.2\" not in app1_clean\n    assert \"pkganix/0.2\" not in app1_clean\n\n    # Finally, merge the 2 clean lockfiles, for keeping just 1 for next iteration\n    c.run(\"lock merge --lockfile=app1_win.lock --lockfile=app1_nix.lock \"\n          \"--lockfile-out=app1_final.lock\")\n    app1_clean = c.load(\"app1_final.lock\")\n    assert \"pkgawin/0.1\" in app1_clean\n    assert \"pkganix/0.1\" in app1_clean\n    assert \"pkgb/0.2\" in app1_clean\n    assert \"pkgb/0.1\" not in app1_clean\n    assert \"pkgawin/0.2\" not in app1_clean\n    assert \"pkganix/0.2\" not in app1_clean\n\n\ndef test_single_config_decentralized(client_setup):\n    \"\"\" same scenario as \"test_single_config_centralized()\", but distributing the build in\n    different build servers, using the \"build-order\"\n    \"\"\"\n    c = client_setup\n    # capture the initial lockfile of our product\n    c.run(\"lock create --requires=app1/0.1@  --lockfile-out=app1.lock -s os=Windows\")\n\n    # Do an unrelated change in A, should not be used, this is not the change we are testing\n    c.save({\"pkga/myfile.txt\": \"ByeA World!!\"})\n    c.run(\"create pkga --name=pkgawin --version=0.2 -s os=Windows\")\n\n    # Do a change in B, this is the change that we want to test\n    c.save({\"pkgb/myfile.txt\": \"ByeB World!!\"})\n\n    # Test that pkgb/0.2 works\n    c.run(\"create pkgb --name=pkgb --version=0.2 -s os=Windows \"\n          \"--lockfile=app1.lock --lockfile-out=app1_b_changed.lock\")\n    assert \"pkgb/0.2: DEP FILE pkgawin: HelloA\" in c.out\n\n    # Now lets build the application, to see everything ok\n    c.run(\"graph build-order --requires=app1/0.1@ --lockfile=app1_b_changed.lock \"\n          \"--build=missing --format=json -s os=Windows\", redirect_stdout=\"build_order.json\")\n    json_file = c.load(\"build_order.json\")\n\n    to_build = json.loads(json_file)\n    level0 = to_build[0]\n    assert len(level0) == 1\n    pkgawin = level0[0]\n    assert pkgawin[\"ref\"] == \"pkgawin/0.1#2f297d19d9ee4827caf97071de449a54\"\n    assert pkgawin[\"packages\"][0][0][\"binary\"] == \"Cache\"\n    level1 = to_build[1]\n    assert len(level1) == 1\n    pkgb = level1[0]\n    assert pkgb[\"ref\"] == \"pkgb/0.2#476b31358d78b3f04c68c4770bd6a79c\"\n    assert pkgb[\"packages\"][0][0][\"binary\"] == \"Cache\"\n\n    for level in to_build:\n        for elem in level:\n            ref = RecipeReference.loads(elem[\"ref\"])\n            for package in elem[\"packages\"][0]:  # assumes no dependencies between packages\n                binary = package[\"binary\"]\n                package_id = package[\"package_id\"]\n                if binary != \"Build\":\n                    continue\n                build_args = package[\"build_args\"]\n                c.run(f\"install {build_args} --lockfile=app1_b_changed.lock -s os=Windows\")\n\n                c.assert_listed_binary(\n                    {str(ref): (package_id, \"Build\"),\n                     \"pkgawin/0.1\": (pkgawin_01_id, \"Cache\"),\n                     \"pkgb/0.2\": (pkgb_01_id, \"Cache\")})\n                assert \"pkgb/0.2\" in c.out\n                assert \"pkgb/0.1\" not in c.out\n                assert \"DEP FILE pkgawin: HelloA\" in c.out\n                assert \"DEP FILE pkgb: ByeB World!!\" in c.out\n\n    # Just to make sure that the for-loops have been executed\n    assert \"app1/0.1: DEP FILE pkgb: ByeB World!!\" in c.out\n\n\ndef test_multi_config_decentralized(client_setup):\n    \"\"\" same scenario as \"test_multi_config_centralized()\", but distributing the build in\n    different build servers, using the \"build-order\"\n    \"\"\"\n    c = client_setup\n    # capture the initial lockfile of our product\n    c.run(\"lock create --requires=app1/0.1@ --lockfile-out=app1.lock -s os=Windows\")\n    c.run(\"lock create --requires=app1/0.1@ --lockfile=app1.lock --lockfile-out=app1.lock \"\n          \"-s os=Linux\")\n\n    # Do an unrelated change in A, should not be used, this is not the change we are testing\n    c.save({\"pkga/myfile.txt\": \"ByeA World!!\"})\n    c.run(\"create pkga --name=pkgawin --version=0.2 -s os=Windows\")\n    c.run(\"create pkga --name=pkganix --version=0.2 -s os=Linux\")\n\n    # Do a change in B, this is the change that we want to test\n    c.save({\"pkgb/myfile.txt\": \"ByeB World!!\"})\n\n    # Test that pkgb/0.2 works\n    c.run(\"create pkgb --name=pkgb --version=0.2 -s os=Windows \"\n          \"--lockfile=app1.lock --lockfile-out=app1_win.lock\")\n    assert \"pkgb/0.2: DEP FILE pkgawin: HelloA\" in c.out\n    c.run(\"create pkgb --name=pkgb --version=0.2 -s os=Linux \"\n          \"--lockfile=app1.lock --lockfile-out=app1_nix.lock\")\n    assert \"pkgb/0.2: DEP FILE pkganix: HelloA\" in c.out\n\n    # Now lets build the application, to see everything ok, for all the configs\n    c.run(\"graph build-order --requires=app1/0.1@ --lockfile=app1_win.lock \"\n          \"--build=missing --format=json -s os=Windows\", redirect_stdout=\"app1_win.json\")\n    c.run(\"graph build-order --requires=app1/0.1@ --lockfile=app1_nix.lock \"\n          \"--build=missing --format=json -s os=Linux\", redirect_stdout=\"app1_nix.json\")\n    c.run(\"graph build-order-merge --file=app1_win.json --file=app1_nix.json\"\n          \" --format=json\", redirect_stdout=\"build_order.json\")\n\n    json_file = c.load(\"build_order.json\")\n    to_build = json.loads(json_file)\n    level0 = to_build[0]\n    assert len(level0) == 2\n    pkgawin = level0[0]\n    assert pkgawin[\"ref\"] == \"pkgawin/0.1#2f297d19d9ee4827caf97071de449a54\"\n    assert pkgawin[\"packages\"][0][0][\"binary\"] == \"Cache\"\n    pkgawin = level0[1]\n    assert pkgawin[\"ref\"] == \"pkganix/0.1#2f297d19d9ee4827caf97071de449a54\"\n    assert pkgawin[\"packages\"][0][0][\"binary\"] == \"Cache\"\n    level1 = to_build[1]\n    assert len(level1) == 1\n    pkgb = level1[0]\n    assert pkgb[\"ref\"] == \"pkgb/0.2#476b31358d78b3f04c68c4770bd6a79c\"\n    assert pkgb[\"packages\"][0][0][\"binary\"] == \"Cache\"\n\n    for level in to_build:\n        for elem in level:\n            ref = elem[\"ref\"]\n            ref_without_rev = ref.split(\"#\")[0]\n            for package in elem[\"packages\"][0]:  # Assumes no dependencies between packages\n                binary = package[\"binary\"]\n                package_id = package[\"package_id\"]\n                if binary != \"Build\":\n                    continue\n                # TODO: The options are completely missing\n                filenames = package[\"filenames\"]\n                lockfile = filenames[0] + \".lock\"\n                the_os = \"Windows\" if \"win\" in lockfile else \"Linux\"\n                c.run(\"install --requires=%s --build=%s --lockfile=%s -s os=%s\"\n                      % (ref, ref, lockfile, the_os))\n                c.assert_listed_binary({ref_without_rev: (package_id, \"Build\")})\n\n                if the_os == \"Windows\":\n                    c.assert_listed_binary(\n                        {\"pkgawin/0.1\": (pkgawin_01_id, \"Cache\"),\n                         \"pkgb/0.2\": (pkgb_01_id, \"Cache\")})\n                    assert \"pkgb/0.2\" in c.out\n                    assert \"pkgb/0.1\" not in c.out\n                    assert \"DEP FILE pkgawin: HelloA\" in c.out\n                    assert \"DEP FILE pkgb: ByeB World!!\" in c.out\n                else:\n                    c.assert_listed_binary(\n                        {\"pkganix/0.1\": (pkganix_01_id, \"Cache\"),\n                         \"pkgb/0.2\": (pkgb_012_id, \"Cache\")})\n                    assert \"pkgb/0.2\" in c.out\n                    assert \"pkgb/0.1\" not in c.out\n                    assert \"DEP FILE pkganix: HelloA\" in c.out\n                    assert \"DEP FILE pkgb: ByeB World!!\" in c.out\n\n    # Just to make sure that the for-loops have been executed\n    assert \"app1/0.1: DEP FILE pkgb: ByeB World!!\" in c.out\n\n\ndef test_single_config_decentralized_overrides():\n    r\"\"\" same scenario as \"test_single_config_centralized()\", but distributing the build in\n    different build servers, using the \"build-order\"\n    Now with overrides\n\n    pkga -> toola/1.0 -> toolb/1.0 -> toolc/1.0\n                \\------override-----> toolc/2.0\n    pkgb -> toola/2.0 -> toolb/1.0 -> toolc/1.0\n                \\------override-----> toolc/3.0\n    pkgc -> toola/3.0 -> toolb/1.0 -> toolc/1.0\n    \"\"\"\n    c = TestClient()\n    c.save({\"toolc/conanfile.py\": GenConanfile(\"toolc\"),\n            \"toolb/conanfile.py\": GenConanfile(\"toolb\").with_requires(\"toolc/1.0\"),\n            \"toola/conanfile.py\": GenConanfile(\"toola\", \"1.0\").with_requirement(\"toolb/1.0\")\n                                                              .with_requirement(\"toolc/2.0\",\n                                                                                override=True),\n            \"toola2/conanfile.py\": GenConanfile(\"toola\", \"2.0\").with_requirement(\"toolb/1.0\")\n                                                               .with_requirement(\"toolc/3.0\",\n                                                                                 override=True),\n            \"toola3/conanfile.py\": GenConanfile(\"toola\", \"3.0\").with_requirement(\"toolb/1.0\"),\n            \"pkga/conanfile.py\": GenConanfile(\"pkga\", \"1.0\").with_tool_requires(\"toola/1.0\"),\n            \"pkgb/conanfile.py\": GenConanfile(\"pkgb\", \"1.0\").with_requires(\"pkga/1.0\")\n                                                            .with_tool_requires(\"toola/2.0\"),\n            \"pkgc/conanfile.py\": GenConanfile(\"pkgc\", \"1.0\").with_requires(\"pkgb/1.0\")\n                                                            .with_tool_requires(\"toola/3.0\"),\n            })\n    c.run(\"export toolc --version=1.0\")\n    c.run(\"export toolc --version=2.0\")\n    c.run(\"export toolc --version=3.0\")\n\n    c.run(\"export toolb --version=1.0\")\n\n    c.run(\"export toola\")\n    c.run(\"export toola2\")\n    c.run(\"export toola3\")\n\n    c.run(\"export pkga\")\n    c.run(\"export pkgb\")\n    c.run(\"lock create pkgc\")\n    lock = json.loads(c.load(\"pkgc/conan.lock\"))\n    requires = \"\\n\".join(lock[\"build_requires\"])\n    assert \"toolc/3.0\" in requires\n    assert \"toolc/2.0\" in requires\n    assert \"toolc/1.0\" in requires\n    assert len(lock[\"overrides\"]) == 1\n    assert set(lock[\"overrides\"][\"toolc/1.0\"]) == {\"toolc/3.0\", \"toolc/2.0\", None}\n\n    c.run(\"graph build-order pkgc --lockfile=pkgc/conan.lock --format=json --build=missing\")\n    to_build = json.loads(c.stdout)\n    for level in to_build:\n        for elem in level:\n            for package in elem[\"packages\"][0]:  # assumes no dependencies between packages\n                binary = package[\"binary\"]\n                assert binary == \"Build\"  # All nodes in this case have to be built\n                build_args = package[\"build_args\"]\n                c.run(f\"install {build_args} --lockfile=pkgc/conan.lock\")\n\n    c.run(\"install pkgc --lockfile=pkgc/conan.lock\")\n    # All works, all binaries exist now\n    assert \"pkga/1.0: Already installed!\" in c.out\n    assert \"pkgb/1.0: Already installed!\" in c.out\n"
  },
  {
    "path": "test/integration/lockfile/test_ci_overrides.py",
    "content": "import json\n\nimport pytest\n\nfrom conan.api.model import RecipeReference\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_graph_build_order_override_error():\n    \"\"\"\n    libc -> libb -> liba -> zlib/1.2\n              |--------------/\n      |-----override------> zlib/1.3\n    \"\"\"\n    c = TestClient(light=True)\n    c.save({\"zlib/conanfile.py\": GenConanfile(\"zlib\"),\n            \"liba/conanfile.py\": GenConanfile(\"liba\", \"0.1\").with_requires(\"zlib/1.0\"),\n            \"libb/conanfile.py\": GenConanfile(\"libb\", \"0.1\").with_requires(\"liba/0.1\", \"zlib/2.0\"),\n            \"libc/conanfile.py\": GenConanfile(\"libc\", \"0.1\").with_requirement(\"libb/0.1\")\n                                                            .with_requirement(\"zlib/3.0\",\n                                                                              override=True)\n            })\n    c.run(\"export zlib --version=2.0\")\n    c.run(\"export zlib --version=3.0\")\n    c.run(\"export liba\")\n    c.run(\"export libb\")\n    c.run(\"export libc\")\n    c.run(\"graph info --requires=libc/0.1 --lockfile-out=output.lock\")\n\n    c.run(\"graph build-order --requires=libc/0.1 --lockfile=output.lock --order-by=configuration \"\n          \"--build=missing --format=json\")\n\n    to_build = json.loads(c.stdout)\n    for level in to_build[\"order\"]:\n        for package in level:\n            binary = package[\"binary\"]\n            assert binary == \"Build\"  # All nodes in this case have to be built\n            build_args = package[\"build_args\"]\n            c.run(f\"install {build_args} --lockfile=output.lock\")\n            ref = RecipeReference.loads(package[\"ref\"])\n            assert f\"{ref}: Building from source\"\n\n    c.run(\"install --requires=libc/0.1 --lockfile=output.lock\")\n    # All works, all binaries exist now\n    assert \"zlib/3.0: Already installed!\" in c.out\n    assert \"liba/0.1: Already installed!\" in c.out\n    assert \"libb/0.1: Already installed!\" in c.out\n    assert \"libc/0.1: Already installed!\" in c.out\n\n\n@pytest.mark.parametrize(\"replace_pattern\", [\"*\", \"3.0\"])\ndef test_graph_build_order_override_replace_requires(replace_pattern):\n    \"\"\"\n    libc -> libb -> liba -> zlib/1.2\n              |--------------/\n      |-----override------> zlib/1.3\n\n    replace_requires zlib -> zlib/system\n    \"\"\"\n    c = TestClient(light=True)\n    c.save({\"zlib/conanfile.py\": GenConanfile(\"zlib\"),\n            \"liba/conanfile.py\": GenConanfile(\"liba\", \"0.1\").with_requires(\"zlib/1.0\"),\n            \"libb/conanfile.py\": GenConanfile(\"libb\", \"0.1\").with_requires(\"liba/0.1\", \"zlib/2.0\"),\n            \"libc/conanfile.py\": GenConanfile(\"libc\", \"0.1\").with_requirement(\"libb/0.1\")\n                                                            .with_requirement(\"zlib/3.0\",\n                                                                              override=True),\n            \"profile\": f\"[replace_requires]\\nzlib/{replace_pattern}: zlib/system\"\n            })\n    c.run(\"export zlib --version=2.0\")\n    c.run(\"export zlib --version=3.0\")\n    c.run(\"export zlib --version=system\")\n    c.run(\"export liba\")\n    c.run(\"export libb\")\n    c.run(\"export libc\")\n    c.run(\"lock create --requires=libc/0.1 --lockfile-out=output.lock -pr=profile\")\n\n    c.run(\"graph build-order --requires=libc/0.1 --lockfile=output.lock --order-by=configuration \"\n          \"--build=missing -pr=profile --format=json\")\n\n    to_build = json.loads(c.stdout)\n    for level in to_build[\"order\"]:\n        for package in level:\n            binary = package[\"binary\"]\n            assert binary == \"Build\"  # All nodes in this case have to be built\n            build_args = package[\"build_args\"]\n            c.run(f\"install {build_args} --lockfile=output.lock -pr=profile\")\n            ref = RecipeReference.loads(package[\"ref\"])\n            assert f\"{ref}: Building from source\"\n\n    c.run(\"install --requires=libc/0.1 --lockfile=output.lock -pr=profile\")\n    # All works, all binaries exist now\n    assert \"zlib/system: Already installed!\" in c.out\n    assert \"liba/0.1: Already installed!\" in c.out\n    assert \"libb/0.1: Already installed!\" in c.out\n    assert \"libc/0.1: Already installed!\" in c.out\n\n\ndef test_single_config_decentralized_overrides():\n    r\"\"\" same scenario as \"test_single_config_centralized()\", but distributing the build in\n    different build servers, using the \"build-order\"\n    Now with overrides\n\n    pkga -> toola/1.0 -> toolb/1.0 -> toolc/1.0\n                \\------override-----> toolc/2.0\n    pkgb -> toola/2.0 -> toolb/1.0 -> toolc/1.0\n                \\------override-----> toolc/3.0\n    pkgc -> toola/3.0 -> toolb/1.0 -> toolc/1.0\n    \"\"\"\n    c = TestClient(light=True)\n    c.save({\"toolc/conanfile.py\": GenConanfile(\"toolc\"),\n            \"toolb/conanfile.py\": GenConanfile(\"toolb\").with_requires(\"toolc/1.0\"),\n            \"toola/conanfile.py\": GenConanfile(\"toola\", \"1.0\").with_requirement(\"toolb/1.0\")\n                                                              .with_requirement(\"toolc/2.0\",\n                                                                                override=True),\n            \"toola2/conanfile.py\": GenConanfile(\"toola\", \"2.0\").with_requirement(\"toolb/1.0\")\n                                                               .with_requirement(\"toolc/3.0\",\n                                                                                 override=True),\n            \"toola3/conanfile.py\": GenConanfile(\"toola\", \"3.0\").with_requirement(\"toolb/1.0\"),\n            \"pkga/conanfile.py\": GenConanfile(\"pkga\", \"1.0\").with_tool_requires(\"toola/1.0\"),\n            \"pkgb/conanfile.py\": GenConanfile(\"pkgb\", \"1.0\").with_requires(\"pkga/1.0\")\n                                                            .with_tool_requires(\"toola/2.0\"),\n            \"pkgc/conanfile.py\": GenConanfile(\"pkgc\", \"1.0\").with_requires(\"pkgb/1.0\")\n                                                            .with_tool_requires(\"toola/3.0\"),\n            })\n    c.run(\"export toolc --version=1.0\")\n    c.run(\"export toolc --version=2.0\")\n    c.run(\"export toolc --version=3.0\")\n\n    c.run(\"export toolb --version=1.0\")\n\n    c.run(\"export toola\")\n    c.run(\"export toola2\")\n    c.run(\"export toola3\")\n\n    c.run(\"export pkga\")\n    c.run(\"export pkgb\")\n    c.run(\"lock create pkgc\")\n    lock = json.loads(c.load(\"pkgc/conan.lock\"))\n    requires = \"\\n\".join(lock[\"build_requires\"])\n    assert \"toolc/3.0\" in requires\n    assert \"toolc/2.0\" in requires\n    assert \"toolc/1.0\" in requires\n    assert len(lock[\"overrides\"]) == 1\n    assert set(lock[\"overrides\"][\"toolc/1.0\"]) == {\"toolc/3.0\", \"toolc/2.0\", None}\n\n    c.run(\"graph build-order pkgc --lockfile=pkgc/conan.lock --format=json --build=missing\")\n    to_build = json.loads(c.stdout)\n    for level in to_build:\n        for elem in level:\n            for package in elem[\"packages\"][0]:  # assumes no dependencies between packages\n                binary = package[\"binary\"]\n                assert binary == \"Build\"  # All nodes in this case have to be built\n                build_args = package[\"build_args\"]\n                c.run(f\"install {build_args} --lockfile=pkgc/conan.lock\")\n\n    c.run(\"install pkgc --lockfile=pkgc/conan.lock\")\n    # All works, all binaries exist now\n    assert \"pkga/1.0: Already installed!\" in c.out\n    assert \"pkgb/1.0: Already installed!\" in c.out\n\n\ndef test_single_config_decentralized_overrides_nested():\n    r\"\"\" same scenario as \"test_single_config_centralized()\", but distributing the build in\n    different build servers, using the \"build-order\"\n    Now with overrides\n\n    pkga -> toola/1.0 -> libb/1.0 -> libc/1.0 -> libd/1.0 -> libe/1.0 -> libf/1.0\n               \\                          \\-----------override---------> libf/2.0\n                \\--------------------override--------------------------> libf/3.0\n    \"\"\"\n    c = TestClient(light=True)\n    c.save({\"libf/conanfile.py\": GenConanfile(\"libf\"),\n            \"libe/conanfile.py\": GenConanfile(\"libe\", \"1.0\").with_requires(\"libf/1.0\"),\n            \"libd/conanfile.py\": GenConanfile(\"libd\", \"1.0\").with_requires(\"libe/1.0\"),\n            \"libc/conanfile.py\": GenConanfile(\"libc\", \"1.0\").with_requirement(\"libd/1.0\")\n                                                            .with_requirement(\"libf/2.0\",\n                                                                              override=True),\n            \"libb/conanfile.py\": GenConanfile(\"libb\", \"1.0\").with_requires(\"libc/1.0\"),\n            \"toola/conanfile.py\": GenConanfile(\"toola\", \"1.0\").with_requirement(\"libb/1.0\")\n                                                              .with_requirement(\"libf/3.0\",\n                                                                                override=True),\n            \"pkga/conanfile.py\": GenConanfile(\"pkga\", \"1.0\").with_tool_requires(\"toola/1.0\"),\n            })\n\n    c.run(\"export libf --version=3.0\")\n    c.run(\"export libe\")\n    c.run(\"export libd\")\n    c.run(\"export libc\")\n    c.run(\"export libb\")\n    c.run(\"export toola\")\n\n    c.run(\"lock create pkga\")\n    lock = json.loads(c.load(\"pkga/conan.lock\"))\n    assert lock[\"overrides\"] == {\"libf/1.0\": [\"libf/3.0\"],\n                                 \"libf/2.0\": [\"libf/3.0\"]}\n\n    c.run(\"graph build-order pkga --lockfile=pkga/conan.lock --format=json --build=missing\")\n    to_build = json.loads(c.stdout)\n    for level in to_build:\n        for elem in level:\n            ref = elem[\"ref\"]\n            if \"libc\" in ref:\n                pass\n            for package in elem[\"packages\"][0]:  # assumes no dependencies between packages\n                binary = package[\"binary\"]\n                assert binary == \"Build\"  # All nodes in this case have to be built\n                build_args = package[\"build_args\"]\n                c.run(f\"install {build_args} --lockfile=pkga/conan.lock\")\n\n    c.run(\"install pkga --lockfile=pkga/conan.lock\")\n    # All works, all binaries exist now\n    assert \"Install finished successfully\" in c.out\n\n\n@pytest.mark.parametrize(\"forced\", [False, True])\ndef test_single_config_decentralized_overrides_multi(forced):\n    r\"\"\" same scenario as \"test_single_config_centralized()\", but distributing the build in\n    different build servers, using the \"build-order\"\n    Now with overrides\n\n    pkga -> toola/1.0 -> libb/1.0 -> libc/1.0 -> libd/1.0 -> libe/1.0 -> libf/1.0\n      |         \\                          \\-----------override--------> libf/2.0\n      |          \\--------------------override-------------------------> libf/3.0\n    pkgb -> toola/1.1 -> libb/1.0 -> libc/1.0 -> libd/1.0 -> libe/1.0 -> libf/1.0\n      |         \\                          \\-----------override--------> libf/2.0\n      |          \\--------------------override-------------------------> libf/4.0\n    pkgc -> toola/1.2 -> libb/1.0 -> libc/1.0 -> libd/1.0 -> libe/1.0 -> libf/1.0\n                                           \\-----------override--------> libf/2.0\n    \"\"\"\n    override, force = (True, False) if not forced else (False, True)\n    c = TestClient(light=True)\n    c.save({\"libf/conanfile.py\": GenConanfile(\"libf\"),\n            \"libe/conanfile.py\": GenConanfile(\"libe\", \"1.0\").with_requires(\"libf/1.0\"),\n            \"libd/conanfile.py\": GenConanfile(\"libd\", \"1.0\").with_requires(\"libe/1.0\"),\n            \"libc/conanfile.py\": GenConanfile(\"libc\", \"1.0\").with_requirement(\"libd/1.0\")\n                                                            .with_requirement(\"libf/2.0\",\n                                                                              override=override,\n                                                                              force=force),\n            \"libb/conanfile.py\": GenConanfile(\"libb\", \"1.0\").with_requires(\"libc/1.0\"),\n            \"toola/conanfile.py\": GenConanfile(\"toola\", \"1.0\").with_requirement(\"libb/1.0\")\n                                                              .with_requirement(\"libf/3.0\",\n                                                                                override=override,\n                                                                                force=force),\n            \"toola1/conanfile.py\": GenConanfile(\"toola\", \"1.1\").with_requirement(\"libb/1.0\")\n                                                               .with_requirement(\"libf/4.0\",\n                                                                                 override=override,\n                                                                                 force=force),\n            \"toola2/conanfile.py\": GenConanfile(\"toola\", \"1.2\").with_requirement(\"libb/1.0\"),\n            \"pkga/conanfile.py\": GenConanfile(\"pkga\", \"1.0\").with_tool_requires(\"toola/1.0\"),\n            \"pkgb/conanfile.py\": GenConanfile(\"pkgb\", \"1.0\").with_requires(\"pkga/1.0\")\n                                                            .with_tool_requires(\"toola/1.1\"),\n            \"pkgc/conanfile.py\": GenConanfile(\"pkgc\", \"1.0\").with_requires(\"pkgb/1.0\")\n                                                            .with_tool_requires(\"toola/1.2\"),\n            })\n\n    c.run(\"export libf --version=2.0\")\n    c.run(\"export libf --version=3.0\")\n    c.run(\"export libf --version=4.0\")\n    c.run(\"export libe\")\n    c.run(\"export libd\")\n    c.run(\"export libc\")\n    c.run(\"export libb\")\n\n    c.run(\"export toola\")\n    c.run(\"export toola1\")\n    c.run(\"export toola2\")\n\n    c.run(\"export pkga\")\n    c.run(\"export pkgb\")\n    c.run(\"lock create pkgc\")\n    lock = json.loads(c.load(\"pkgc/conan.lock\"))\n    assert len(lock[\"overrides\"]) == 2\n    assert set(lock[\"overrides\"][\"libf/1.0\"]) == {\"libf/4.0\", \"libf/2.0\", \"libf/3.0\"}\n\n    if forced:  # When forced, there is one libf/2.0 that is not overriden\n        assert set(lock[\"overrides\"][\"libf/2.0\"]) == {\"libf/4.0\", \"libf/3.0\", None}\n    else:\n        assert set(lock[\"overrides\"][\"libf/2.0\"]) == {\"libf/4.0\", \"libf/3.0\"}\n\n    c.run(\"graph build-order pkgc --lockfile=pkgc/conan.lock --format=json --build=missing\")\n    to_build = json.loads(c.stdout)\n    for level in to_build:\n        for elem in level:\n            ref = elem[\"ref\"]\n            if \"libc\" in ref:\n                pass\n            for package in elem[\"packages\"][0]:  # assumes no dependencies between packages\n                binary = package[\"binary\"]\n                assert binary == \"Build\"  # All nodes in this case have to be built\n                build_args = package[\"build_args\"]\n                c.run(f\"install {build_args} --lockfile=pkgc/conan.lock\")\n\n    c.run(\"install pkgc --lockfile=pkgc/conan.lock\")\n    # All works, all binaries exist now\n    assert \"pkga/1.0: Already installed!\" in c.out\n    assert \"pkgb/1.0: Already installed!\" in c.out\n\n\n@pytest.mark.parametrize(\"replace_pattern\", [\"*\", \"1.0\", \"2.0\", \"3.0\", \"4.0\"])\n@pytest.mark.parametrize(\"forced\", [False, True])\ndef test_single_config_decentralized_overrides_multi_replace_requires(replace_pattern, forced):\n    r\"\"\" same scenario as \"test_single_config_centralized()\", but distributing the build in\n    different build servers, using the \"build-order\"\n    Now with overrides\n\n    pkga -> toola/1.0 -> libb/1.0 -> libc/1.0 -> libd/1.0 -> libe/1.0 -> libf/1.0\n      |         \\                          \\-----------override--------> libf/2.0\n      |          \\--------------------override-------------------------> libf/3.0\n    pkgb -> toola/1.1 -> libb/1.0 -> libc/1.0 -> libd/1.0 -> libe/1.0 -> libf/1.0\n      |         \\                          \\-----------override--------> libf/2.0\n      |          \\--------------------override-------------------------> libf/4.0\n    pkgc -> toola/1.2 -> libb/1.0 -> libc/1.0 -> libd/1.0 -> libe/1.0 -> libf/1.0\n                                           \\-----------override--------> libf/2.0\n    \"\"\"\n    override, force = (True, False) if not forced else (False, True)\n    c = TestClient(light=True)\n    c.save({\"libf/conanfile.py\": GenConanfile(\"libf\"),\n            \"libe/conanfile.py\": GenConanfile(\"libe\", \"1.0\").with_requires(\"libf/1.0\"),\n            \"libd/conanfile.py\": GenConanfile(\"libd\", \"1.0\").with_requires(\"libe/1.0\"),\n            \"libc/conanfile.py\": GenConanfile(\"libc\", \"1.0\").with_requirement(\"libd/1.0\")\n                                                            .with_requirement(\"libf/2.0\",\n                                                                              override=override,\n                                                                              force=force),\n            \"libb/conanfile.py\": GenConanfile(\"libb\", \"1.0\").with_requires(\"libc/1.0\"),\n            \"toola/conanfile.py\": GenConanfile(\"toola\", \"1.0\").with_requirement(\"libb/1.0\")\n                                                              .with_requirement(\"libf/3.0\",\n                                                                                override=override,\n                                                                                force=force),\n            \"toola1/conanfile.py\": GenConanfile(\"toola\", \"1.1\").with_requirement(\"libb/1.0\")\n                                                               .with_requirement(\"libf/4.0\",\n                                                                                 override=override,\n                                                                                 force=force),\n            \"toola2/conanfile.py\": GenConanfile(\"toola\", \"1.2\").with_requirement(\"libb/1.0\"),\n            \"pkga/conanfile.py\": GenConanfile(\"pkga\", \"1.0\").with_tool_requires(\"toola/1.0\"),\n            \"pkgb/conanfile.py\": GenConanfile(\"pkgb\", \"1.0\").with_requires(\"pkga/1.0\")\n                                                            .with_tool_requires(\"toola/1.1\"),\n            \"pkgc/conanfile.py\": GenConanfile(\"pkgc\", \"1.0\").with_requires(\"pkgb/1.0\")\n                                                            .with_tool_requires(\"toola/1.2\"),\n            \"profile\": f\"include(default)\\n[replace_requires]\\nlibf/{replace_pattern}: libf/system\"\n            })\n\n    c.run(\"export libf --version=2.0\")\n    c.run(\"export libf --version=3.0\")\n    c.run(\"export libf --version=4.0\")\n    c.run(\"export libf --version=system\")\n    c.run(\"export libe\")\n    c.run(\"export libd\")\n    c.run(\"export libc\")\n    c.run(\"export libb\")\n\n    c.run(\"export toola\")\n    c.run(\"export toola1\")\n    c.run(\"export toola2\")\n\n    c.run(\"export pkga\")\n    c.run(\"export pkgb\")\n    c.run(\"lock create pkgc -pr:b=profile\")\n\n    # overrides will be different everytime, just checking that things can be built\n    c.run(\"graph build-order pkgc --lockfile=pkgc/conan.lock --format=json -pr:b=profile \"\n          \"--build=missing\")\n\n    to_build = json.loads(c.stdout)\n    for level in to_build:\n        for elem in level:\n            ref = elem[\"ref\"]\n            if \"libc\" in ref:\n                pass\n            for package in elem[\"packages\"][0]:  # assumes no dependencies between packages\n                binary = package[\"binary\"]\n                assert binary == \"Build\"  # All nodes in this case have to be built\n                build_args = package[\"build_args\"]\n                c.run(f\"install {build_args} --lockfile=pkgc/conan.lock -pr:b=profile\")\n\n    c.run(\"install pkgc --lockfile=pkgc/conan.lock -pr:b=profile\")\n    # All works, all binaries exist now\n    assert \"pkga/1.0: Already installed!\" in c.out\n    assert \"pkgb/1.0: Already installed!\" in c.out\n    if replace_pattern == \"1.0\":  # These will overriden by downstream\n        assert \"libf/system#7fb6d926dabeb955bcea1cafedf953c8 - Cache\" not in c.out\n    else:\n        assert \"libf/system#7fb6d926dabeb955bcea1cafedf953c8 - Cache\" in c.out\n"
  },
  {
    "path": "test/integration/lockfile/test_ci_revisions.py",
    "content": "import json\nimport textwrap\n\nimport pytest\n\nfrom conan.api.model import RecipeReference\nfrom conan.test.utils.tools import TestClient\n\nconanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    from conan.tools.files import load, copy\n    import os\n    class Pkg(ConanFile):\n        settings = \"os\"\n        {requires}\n        exports_sources = \"myfile.txt\"\n\n        def generate(self):\n            # Simulate an \"imports\"\n            for dep in self.dependencies.values():\n                dest_folder = os.path.join(self.build_folder, dep.ref.name)\n                copy(self, \"myfile.txt\", dep.package_folder, dest_folder)\n\n        def package(self):\n            # Copy the ones from the dependencies\n            copied = copy(self, \"*myfile.txt\", self.build_folder, self.package_folder, keep_path=True)\n            # Copy the exported one\n            copied = copy(self, \"myfile.txt\", self.source_folder, self.package_folder)\n            assert len(copied) == 1\n\n        def package_info(self):\n            self.output.info(\"SELF OS: %s!!\" % self.settings.os)\n            self.output.info(\"SELF FILE: %s\"\n                % load(self, os.path.join(self.package_folder, \"myfile.txt\")))\n            for d in os.listdir(self.package_folder):\n                p = os.path.join(self.package_folder, d, \"myfile.txt\")\n                if os.path.isfile(p):\n                    self.output.info(\"DEP FILE %s: %s\" % (d, load(self, p)))\n        \"\"\")\n\npkgawin_01_id = \"ebec3dc6d7f6b907b3ada0c3d3cdc83613a2b715\"\npkganix_01_id = \"9a4eb3c8701508aa9458b1a73d0633783ecc2270\"\npkgb_01_id = \"cee4c64978063c49773213b9c8f6b631c612a00b\"\npkgb_012_id = \"6b6343eeb8ffeb498b809bca9853fceb7dd0c078\"\npkgc_01_id = \"1bc0312cddbd3c076e666b84af9cc5ac3d263719\"\npkgapp_01_id = \"dda63a9bddbbe704d4858d67156d5dad0361dc19\"\n\n\n@pytest.fixture()\ndef client_setup():\n    c = TestClient(light=True)\n    c.save_home({\"global.conf\": \"core.package_id:default_unknown_mode=recipe_revision_mode\"})\n    pkb_requirements = \"\"\"\n    def requirements(self):\n        if self.settings.os == \"Windows\":\n            self.requires(\"pkgawin/0.1\")\n        else:\n            self.requires(\"pkganix/0.1\")\n    \"\"\"\n    files = {\n        \"pkga/conanfile.py\": conanfile.format(requires=\"\"),\n        \"pkga/myfile.txt\": \"HelloA\",\n        \"pkgj/conanfile.py\": conanfile.format(requires=\"\"),\n        \"pkgj/myfile.txt\": \"HelloJ\",\n        \"pkgb/conanfile.py\": conanfile.format(requires=pkb_requirements),\n        \"pkgb/myfile.txt\": \"HelloB\",\n        \"pkgc/conanfile.py\": conanfile.format(requires='requires=\"pkgb/0.1\"'),\n        \"pkgc/myfile.txt\": \"HelloC\",\n        \"app1/conanfile.py\": conanfile.format(requires='requires=\"pkgc/0.1\"'),\n        \"app1/myfile.txt\": \"App1\",\n    }\n    c.save(files)\n\n    c.run(\"create pkga --name=pkgawin --version=0.1 -s os=Windows\")\n    c.run(\"create pkga --name=pkganix --version=0.1 -s os=Linux\")\n    c.run(\"create pkgb --name=pkgb --version=0.1 -s os=Windows\")\n    c.run(\"create pkgc --name=pkgc --version=0.1 -s os=Windows\")\n    c.run(\"create app1 --name=app1 --version=0.1 -s os=Windows\")\n    assert \"app1/0.1: SELF FILE: App1\" in c.out\n    assert \"app1/0.1: DEP FILE pkgawin: HelloA\" in c.out\n    assert \"app1/0.1: DEP FILE pkgb: HelloB\" in c.out\n    assert \"app1/0.1: DEP FILE pkgc: HelloC\" in c.out\n    return c\n\n\ndef test_single_config_centralized(client_setup):\n    \"\"\" app1 -> pkgc/0.1 -> pkgb/0.1 -> pkgawin/0.1 or pkganix/0.1\n    all versions are \"0.1\" exact (without pinning revision)\n    lock app1.lock to lock graph including pkgawin/0.1#rev1 and pkganix/0.1#rev1\n    changes in pkgawin/0.1#rev2 and pkganix/0.1#rev2 are excluded by lockfile\n    a change in pkgb produces a new pkgb/0.1#rev2 that we want to test if works in app1 lockfile\n    the app1 can be built in a single node, including all necessary dependencies\n    the final lockfile will include pkgb/0.1#rev2, and not pkgb/0.1#rev1\n    \"\"\"\n    c = client_setup\n    # capture the initial lockfile of our product\n    c.run(\"lock create --requires=app1/0.1@  --lockfile-out=app1.lock -s os=Windows\")\n    app1_lock = c.load(\"app1.lock\")\n    assert \"pkgb/0.1#d03e920d532beeeb198cd886095bcca1\" in app1_lock\n    # Do an unrelated change in A, should not be used, this is not the change we are testing\n    c.save({\"pkga/myfile.txt\": \"ByeA World!!\"})\n    c.run(\"create pkga --name=pkgawin --version=0.1 -s os=Windows\")\n\n    # Do a change in B, this is the change that we want to test\n    c.save({\"pkgb/myfile.txt\": \"ByeB World!!\"})\n\n    # Test that pkgb/0.1 new revision works\n    c.run(\"create pkgb --name=pkgb --version=0.1 -s os=Windows \"\n          \"--lockfile=app1.lock --lockfile-out=app1_b_changed.lock\")\n    assert \"pkgb/0.1: DEP FILE pkgawin: HelloA\" in c.out\n\n    # Now lets build the application, to see everything ok\n    c.run(\"install --requires=app1/0.1@  --lockfile=app1_b_changed.lock \"\n          \"--lockfile-out=app1_b_integrated.lock \"\n          \"--build=missing  -s os=Windows\")\n    c.assert_listed_binary({\"pkgawin/0.1\": (pkgawin_01_id, \"Cache\"),\n                            \"pkgb/0.1\": (pkgb_01_id, \"Cache\"),\n                            \"pkgc/0.1\": (pkgc_01_id, \"Build\"),\n                            \"app1/0.1\": (pkgapp_01_id, \"Build\")})\n    assert \"app1/0.1: DEP FILE pkgawin: HelloA\" in c.out\n    assert \"app1/0.1: DEP FILE pkgb: ByeB World!!\" in c.out\n\n    # All good! We can get rid of the now unused pkgb/0.1 version in the lockfile\n    c.run(\"lock create --requires=app1/0.1@ --lockfile=app1_b_integrated.lock \"\n          \"--lockfile-out=app1_clean.lock -s os=Windows --lockfile-clean\")\n    app1_clean = c.load(\"app1_clean.lock\")\n    assert \"pkgb/0.1#d03e920d532beeeb198cd886095bcca1\" not in app1_clean\n    assert \"pkgb/0.1#bb12977c3353d7633b34d55a926fe58c\" in app1_clean\n\n\ndef test_single_config_centralized_out_range(client_setup):\n    \"\"\" same scenario as \"test_single_config_centralized()\"\n    but pkgc pin the exact revision of pkgb/0.1#rev1\n    But pkgb/0.1 change produces pkgb/0.1#rev2, which doesn't match the pinned revisions rev1\n    Nothing to build in the app1, and the final lockfile doesn't change at all\n    \"\"\"\n    # Out of range in revisions means a pinned revision, new revision will not match\n    c = client_setup\n    c.save({\"pkgc/conanfile.py\":\n            conanfile.format(requires='requires=\"pkgb/0.1#d03e920d532beeeb198cd886095bcca1\"')})\n    c.run(\"create pkgc --name=pkgc --version=0.1 -s os=Windows\")\n    c.run(\"create app1 --name=app1 --version=0.1 -s os=Windows --build=missing\")\n    c.run(\"lock create --requires=app1/0.1@ --lockfile-out=app1.lock -s os=Windows\")\n    app1_lock = c.load(\"app1.lock\")\n    assert \"pkgb/0.1#d03e920d532beeeb198cd886095bcca1\" in app1_lock\n\n    # Do an unrelated change in A, should not be used, this is not the change we are testing\n    c.save({\"pkga/myfile.txt\": \"ByeA World!!\"})\n    c.run(\"create pkga --name=pkgawin --version=0.1 -s os=Windows\")\n\n    # Do a change in B, this is the change that we want to test\n    c.save({\"pkgb/myfile.txt\": \"ByeB World!!\"})\n\n    # Test that pkgb/1.0 works (but it is not matching the pinned revision)\n    c.run(\"create pkgb --name=pkgb --version=0.1 -s os=Windows \"\n          \"--lockfile=app1.lock --lockfile-out=app1_b_changed.lock\")\n    assert \"pkgb/0.1: DEP FILE pkgawin: HelloA\" in c.out\n    app1_b_changed = c.load(\"app1_b_changed.lock\")\n    assert \"pkgb/0.1#bb12977c3353d7633b34d55a926fe58c\" in app1_b_changed\n    assert \"pkgb/0.1#d03e920d532beeeb198cd886095bcca1\" in app1_b_changed\n\n    # Now lets build the application, to see everything ok\n    c.run(\"install --requires=app1/0.1@  --lockfile=app1_b_changed.lock \"\n          \"--lockfile-out=app1_b_integrated.lock \"\n          \"--build=missing  -s os=Windows\")\n    # Nothing changed, the change is outside the range, app1 not affected!!\n    c.assert_listed_binary({\"pkgawin/0.1\": (pkgawin_01_id, \"Cache\"),\n                            \"pkgb/0.1\": (pkgb_01_id, \"Cache\"),\n                            \"pkgc/0.1\": (\"7dc09fd93c15a010373b013c3a44fc94fc9d3226\", \"Cache\"),\n                            \"app1/0.1\": (\"96324a4bf6d4bba4f697919a435eca6d746c2d18\", \"Cache\")})\n    assert \"app1/0.1: DEP FILE pkgawin: HelloA\" in c.out\n    assert \"app1/0.1: DEP FILE pkgb: HelloB\" in c.out\n\n    # All good! We can get rid of the now unused pkgb/1.0 version in the lockfile\n    c.run(\"lock create --requires=app1/0.1@ --lockfile=app1_b_integrated.lock \"\n          \"--lockfile-out=app1_clean.lock -s os=Windows --lockfile-clean\")\n    app1_clean = c.load(\"app1_clean.lock\")\n    assert \"pkgb/0.1#d03e920d532beeeb198cd886095bcca1\" in app1_clean\n    assert \"pkgb/0.1#504bc7152c72b49c99a6f16733fb2ff6\" not in app1_clean\n\n\ndef test_single_config_centralized_change_dep(client_setup):\n    \"\"\" same scenario as \"test_single_config_centralized()\".\n    But pkgb/0.1 change producing pkgb/0.1#rev2, and changes dependency from pkgA=>pkgJ\n    \"\"\"\n    c = client_setup\n    c.run(\"lock create --requires=app1/0.1@ --lockfile-out=app1.lock -s os=Windows\")\n\n    # Do an unrelated change in A, should not be used, this is not the change we are testing\n    c.save({\"pkga/myfile.txt\": \"ByeA World!!\"})\n    c.run(\"create pkga --name=pkgawin --version=0.1 -s os=Windows\")\n\n    # Build new package alternative J\n    c.run(\"create pkgj --name=pkgj --version=0.1 -s os=Windows\")\n\n    # Do a change in B, this is the change that we want to test, remove pkgA, replace with pkgJ\n    c.save({\"pkgb/conanfile.py\": conanfile.format(requires='requires=\"pkgj/0.1\"'),\n            \"pkgb/myfile.txt\": \"ByeB World!!\"})\n\n    # Test that pkgb/0.1 new revision works\n    c.run(\"create pkgb --name=pkgb --version=0.1 -s os=Windows --lockfile-partial \"\n          \"--lockfile=app1.lock --lockfile-out=app1_b_changed.lock\")\n    assert \"pkgb/0.1: DEP FILE pkgj: HelloJ\" in c.out\n    # Build new package alternative J, it won't be included, already locked in this create\n    c.run(\"create pkgj --name=pkgj --version=0.1 -s os=Windows\")\n\n    # Now lets build the application, to see everything ok\n    c.run(\"install --requires=app1/0.1@  --lockfile=app1_b_changed.lock \"\n          \"--lockfile-out=app1_b_integrated.lock \"\n          \"--build=missing  -s os=Windows\")\n    assert \"pkga/\" not in c.out\n    c.assert_listed_binary({\"pkgj/0.1\": (pkgawin_01_id, \"Cache\"),\n                            \"pkgb/0.1\": (\"6142fb85ccd4e94afad85a8d01a87234eefa5600\", \"Cache\"),\n                            \"pkgc/0.1\": (\"93cfcbc8109eedf4211558258ff5a844fdb62cca\", \"Build\"),\n                            \"app1/0.1\": (\"eb241e40d370e1e1b0fd516aff6ffff72de1e37d\", \"Build\")})\n    assert \"app1/0.1: DEP FILE pkgj: HelloJ\" in c.out\n    assert \"app1/0.1: DEP FILE pkgb: ByeB World!!\" in c.out\n\n    # All good! We can get rid of the now unused pkgb/1.0 version in the lockfile\n    c.run(\"lock create --requires=app1/0.1@ --lockfile=app1_b_integrated.lock \"\n          \"--lockfile-out=app1_clean.lock -s os=Windows --lockfile-clean\")\n    app1_clean = c.load(\"app1_clean.lock\")\n    assert \"pkgj/0.1\" in app1_clean\n    assert \"pkgb/0.1\" in app1_clean\n    assert \"pkga\" not in app1_clean\n\n\ndef test_multi_config_centralized(client_setup):\n    \"\"\" same scenario as above, but now we want to manage 2 configurations Windows & Linux\n    When pkgB is changed, it is built for both, and produces app1_win.lock and app2_linux.lock\n    With those, app1 can be built in a single node for both configurations. After building\n    app1, the 2 lockfiles can be cleaned (removing the old pkgb/0.1#rev1, leaving pkgb/0.1#rev2\n    in the lock)\n    The 2 final lockfiles can be \"merged\" in a single one for next iteration\n    \"\"\"\n    c = client_setup\n    # capture the initial lockfile of our product\n    c.run(\"lock create --requires=app1/0.1@ --lockfile-out=app1.lock -s os=Windows\")\n    c.run(\"lock create --requires=app1/0.1@ --lockfile=app1.lock --lockfile-out=app1.lock \"\n          \"-s os=Linux\")\n    app1_lock = c.load(\"app1.lock\")\n    assert \"pkgb/0.1#d03e920d532beeeb198cd886095bcca1\" in app1_lock\n    assert \"pkgawin/0.1#2f297d19d9ee4827caf97071de449a54\" in app1_lock\n    assert \"pkganix/0.1#2f297d19d9ee4827caf97071de449a54\" in app1_lock\n\n    # Do an unrelated change in A, should not be used, this is not the change we are testing\n    c.save({\"pkga/myfile.txt\": \"ByeA World!!\"})\n    c.run(\"create pkga --name=pkgawin --version=0.1 -s os=Windows\")\n    c.run(\"create pkga --name=pkganix --version=0.1 -s os=Linux\")\n\n    # Do a change in B, this is the change that we want to test\n    c.save({\"pkgb/myfile.txt\": \"ByeB World!!\"})\n\n    # Test that pkgb/0.1 works\n    c.run(\"create pkgb --name=pkgb --version=0.1 -s os=Windows \"\n          \"--lockfile=app1.lock --lockfile-out=app1_win.lock\")\n    assert \"pkgb/0.1: DEP FILE pkgawin: HelloA\" in c.out\n    c.run(\"create pkgb --name=pkgb --version=0.1 -s os=Linux \"\n          \"--lockfile=app1.lock --lockfile-out=app1_nix.lock\")\n    assert \"pkgb/0.1: DEP FILE pkganix: HelloA\" in c.out\n\n    # Now lets build the application in Windows, to see everything ok\n    c.run(\"install --requires=app1/0.1@  --lockfile=app1_win.lock --lockfile-out=app1_win.lock \"\n          \"--build=missing  -s os=Windows\")\n    c.assert_listed_binary({\"pkgawin/0.1\": (pkgawin_01_id, \"Cache\"),\n                            \"pkgb/0.1\": (pkgb_01_id, \"Cache\"),\n                            \"pkgc/0.1\": (pkgc_01_id, \"Build\"),\n                            \"app1/0.1\": (pkgapp_01_id, \"Build\")})\n    assert \"app1/0.1: DEP FILE pkgawin: HelloA\" in c.out\n    assert \"app1/0.1: DEP FILE pkgb: ByeB World!!\" in c.out\n\n    # Now lets build the application in Linux, to see everything ok\n    c.run(\"install --requires=app1/0.1@  --lockfile=app1_nix.lock --lockfile-out=app1_nix.lock \"\n          \"--build=missing  -s os=Linux\")\n    c.assert_listed_binary({\"pkganix/0.1\": (pkganix_01_id, \"Cache\"),\n                            \"pkgb/0.1\": (pkgb_012_id, \"Cache\"),\n                            \"pkgc/0.1\": (\"62b3834a578b45bb303925e1e9cfe0dd9908486e\", \"Build\"),\n                            \"app1/0.1\": (\"6a589308a14c21c9082620be4a63240017665e38\", \"Build\")})\n\n    assert \"app1/0.1: DEP FILE pkganix: HelloA\" in c.out\n    assert \"app1/0.1: DEP FILE pkgb: ByeB World!!\" in c.out\n\n    # All good! We can get rid of the now unused pkgb/0.1 version in the lockfile\n    c.run(\"lock create --requires=app1/0.1@ --lockfile=app1_win.lock \"\n          \"--lockfile-out=app1_win.lock -s os=Windows --lockfile-clean\")\n    c.run(\"lock create --requires=app1/0.1@ --lockfile=app1_nix.lock \"\n          \"--lockfile-out=app1_nix.lock -s os=Linux --lockfile-clean\")\n\n    # Finally, merge the 2 clean lockfiles, for keeping just 1 for next iteration\n    c.run(\"lock merge --lockfile=app1_win.lock --lockfile=app1_nix.lock \"\n          \"--lockfile-out=app1_final.lock\")\n    app1_clean = c.load(\"app1_final.lock\")\n    assert \"pkgb/0.1#d03e920d532beeeb198cd886095bcca1\" not in app1_clean\n    assert \"pkgawin/0.1#2f297d19d9ee4827caf97071de449a54\" in app1_clean\n    assert \"pkganix/0.1#2f297d19d9ee4827caf97071de449a54\" in app1_clean\n\n\ndef test_single_config_decentralized(client_setup):\n    \"\"\" same scenario as \"test_single_config_centralized()\", but distributing the build in\n    different build servers, using the \"build-order\"\n    \"\"\"\n    c = client_setup\n    # capture the initial lockfile of our product\n    c.run(\"lock create --requires=app1/0.1@  --lockfile-out=app1.lock -s os=Windows\")\n    app1_lock = c.load(\"app1.lock\")\n    assert \"pkgb/0.1#d03e920d532beeeb198cd886095bcca1\" in app1_lock\n\n    # Do an unrelated change in A, should not be used, this is not the change we are testing\n    c.save({\"pkga/myfile.txt\": \"ByeA World!!\"})\n    c.run(\"create pkga --name=pkgawin --version=0.1 -s os=Windows\")\n\n    # Do a change in B, this is the change that we want to test\n    c.save({\"pkgb/myfile.txt\": \"ByeB World!!\"})\n\n    # Test that pkgb/0.1 works\n    c.run(\"create pkgb --name=pkgb --version=0.1 -s os=Windows \"\n          \"--lockfile=app1.lock --lockfile-out=app1_b_changed.lock\")\n    assert \"pkgb/0.1: DEP FILE pkgawin: HelloA\" in c.out\n\n    # Now lets build the application, to see everything ok\n    c.run(\"graph build-order --requires=app1/0.1@ --lockfile=app1_b_changed.lock \"\n          \"--build=missing --format=json -s os=Windows\", redirect_stdout=\"build_order.json\")\n    json_file = c.load(\"build_order.json\")\n    to_build = json.loads(json_file)\n    level0 = to_build[0]\n    assert len(level0) == 1\n    pkgawin = level0[0]\n    assert pkgawin[\"ref\"] == \"pkgawin/0.1#2f297d19d9ee4827caf97071de449a54\"\n    assert pkgawin[\"packages\"][0][0][\"binary\"] == \"Cache\"\n    level1 = to_build[1]\n    assert len(level1) == 1\n    pkgb = level1[0]\n    assert pkgb[\"ref\"] == \"pkgb/0.1#bb12977c3353d7633b34d55a926fe58c\"\n    assert pkgb[\"packages\"][0][0][\"binary\"] == \"Cache\"\n\n    for level in to_build:\n        for elem in level:\n            ref = RecipeReference.loads(elem[\"ref\"])\n            for package in elem[\"packages\"][0]:  # Assumes no dependencies between packages\n                binary = package[\"binary\"]\n                package_id = package[\"package_id\"]\n                if binary != \"Build\":\n                    continue\n                # TODO: The options are completely missing\n                c.run(\n                    \"install --requires=%s@ --build=%s@ --lockfile=app1_b_changed.lock  -s os=Windows\"\n                    % (ref, ref))\n                c.assert_listed_binary(\n                    {str(ref): (package_id, \"Build\"),\n                     \"pkgawin/0.1\": (pkgawin_01_id, \"Cache\"),\n                     \"pkgb/0.1\": (pkgb_01_id, \"Cache\")})\n                assert \"DEP FILE pkgawin: HelloA\" in c.out\n                assert \"DEP FILE pkgb: ByeB World!!\" in c.out\n\n    # Just to make sure that the for-loops have been executed\n    assert \"app1/0.1: DEP FILE pkgb: ByeB World!!\" in c.out\n\n\ndef test_multi_config_decentralized(client_setup):\n    \"\"\" same scenario as \"test_multi_config_centralized()\", but distributing the build in\n    different build servers, using the \"build-order\"\n    \"\"\"\n    c = client_setup\n    # capture the initial lockfile of our product\n    c.run(\"lock create --requires=app1/0.1@ --lockfile-out=app1.lock -s os=Windows\")\n    c.run(\"lock create --requires=app1/0.1@ --lockfile=app1.lock --lockfile-out=app1.lock \"\n          \"-s os=Linux\")\n\n    # Do an unrelated change in A, should not be used, this is not the change we are testing\n    c.save({\"pkga/myfile.txt\": \"ByeA World!!\"})\n    c.run(\"create pkga --name=pkgawin --version=0.1 -s os=Windows\")\n    c.run(\"create pkga --name=pkganix --version=0.1 -s os=Linux\")\n\n    # Do a change in B, this is the change that we want to test\n    c.save({\"pkgb/myfile.txt\": \"ByeB World!!\"})\n\n    # Test that pkgb/0.1 new revision works\n    c.run(\"create pkgb --name=pkgb --version=0.1 -s os=Windows \"\n          \"--lockfile=app1.lock --lockfile-out=app1_win.lock\")\n    assert \"pkgb/0.1: DEP FILE pkgawin: HelloA\" in c.out\n    c.run(\"create pkgb --name=pkgb --version=0.1 -s os=Linux \"\n          \"--lockfile=app1.lock --lockfile-out=app1_nix.lock\")\n    assert \"pkgb/0.1: DEP FILE pkganix: HelloA\" in c.out\n\n    # Now lets build the application, to see everything ok, for all the configs\n    c.run(\"graph build-order --requires=app1/0.1@ --lockfile=app1_win.lock \"\n          \"--build=missing --format=json -s os=Windows\", redirect_stdout=\"app1_win.json\")\n    c.run(\"graph build-order --requires=app1/0.1@ --lockfile=app1_nix.lock \"\n          \"--build=missing --format=json -s os=Linux\", redirect_stdout=\"app1_nix.json\")\n    c.run(\"graph build-order-merge --file=app1_win.json --file=app1_nix.json\"\n          \" --format=json\", redirect_stdout=\"build_order.json\")\n\n    json_file = c.load(\"build_order.json\")\n    to_build = json.loads(json_file)\n    level0 = to_build[0]\n    assert len(level0) == 2\n    pkgawin = level0[0]\n    assert pkgawin[\"ref\"] == \"pkgawin/0.1#2f297d19d9ee4827caf97071de449a54\"\n    assert pkgawin[\"packages\"][0][0][\"binary\"] == \"Cache\"\n    pkgawin = level0[1]\n    assert pkgawin[\"ref\"] == \"pkganix/0.1#2f297d19d9ee4827caf97071de449a54\"\n    assert pkgawin[\"packages\"][0][0][\"binary\"] == \"Cache\"\n    level1 = to_build[1]\n    assert len(level1) == 1\n    pkgb = level1[0]\n    assert pkgb[\"ref\"] == \"pkgb/0.1#bb12977c3353d7633b34d55a926fe58c\"\n    assert pkgb[\"packages\"][0][0][\"binary\"] == \"Cache\"\n\n    for level in to_build:\n        for elem in level:\n            ref = elem[\"ref\"]\n            ref_without_rev = ref.split(\"#\")[0]\n            if \"@\" not in ref:\n                ref = ref.replace(\"#\", \"@#\")\n            for package in elem[\"packages\"][0]:  # Assumes no dependencies between packages\n                binary = package[\"binary\"]\n                package_id = package[\"package_id\"]\n                if binary != \"Build\":\n                    continue\n                # TODO: The options are completely missing\n                filenames = package[\"filenames\"]\n                lockfile = filenames[0] + \".lock\"\n                the_os = \"Windows\" if \"win\" in lockfile else \"Linux\"\n                c.run(\"install --requires=%s --build=%s --lockfile=%s -s os=%s\"\n                      % (ref, ref, lockfile, the_os))\n                c.assert_listed_binary({str(ref_without_rev): (package_id, \"Build\")})\n\n                if the_os == \"Windows\":\n                    c.assert_listed_binary(\n                        {\"pkgawin/0.1\": (pkgawin_01_id, \"Cache\"),\n                         \"pkgb/0.1\": (pkgb_01_id, \"Cache\")})\n                    assert \"DEP FILE pkgawin: HelloA\" in c.out\n                    assert \"DEP FILE pkgb: ByeB World!!\" in c.out\n                else:\n                    c.assert_listed_binary(\n                        {\"pkganix/0.1\": (pkganix_01_id, \"Cache\"),\n                         \"pkgb/0.1\": (pkgb_012_id, \"Cache\")})\n                    assert \"DEP FILE pkganix: HelloA\" in c.out\n                    assert \"DEP FILE pkgb: ByeB World!!\" in c.out\n\n    # Just to make sure that the for-loops have been executed\n    assert \"app1/0.1: DEP FILE pkgb: ByeB World!!\" in c.out\n"
  },
  {
    "path": "test/integration/lockfile/test_compatibility.py",
    "content": "import textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_lockfile_compatibility():\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"1.0\"\n            settings = \"build_type\"\n            def compatibility(self):\n                if self.settings.build_type == \"Release\":\n                    return [ {\"settings\": [(\"build_type\", None)]}, ]\n            \"\"\")\n    c.save({\"conanfile.py\": conanfile,\n            \"profile\": \"\"})\n    c.run(\"create . -pr=profile\")\n    c.save({\"conanfile.py\": GenConanfile().with_requires(\"pkg/1.0\")})\n    c.run(\"install .\")\n    assert \"pkg/1.0: Main binary package 'efa83b160a55b033c4ea706ddb980cd708e3ba1b' missing\" in c.out\n    assert \"Found compatible package 'da39a3ee5e6b4b0d3255bfef95601890afd80709'\" in c.out\n\n    c.run(\"lock create conanfile.py\")\n    assert \"pkg/1.0: Main binary package 'efa83b160a55b033c4ea706ddb980cd708e3ba1b' missing\" in c.out\n    assert \"Found compatible package 'da39a3ee5e6b4b0d3255bfef95601890afd80709'\" in c.out\n\n    c.run(\"lock create conanfile.py --lockfile=conan.lock\")\n    assert \"pkg/1.0: Main binary package 'efa83b160a55b033c4ea706ddb980cd708e3ba1b' missing\" in c.out\n    assert \"Found compatible package 'da39a3ee5e6b4b0d3255bfef95601890afd80709'\" in c.out\n\n    c.run(\"install . --lockfile=conan.lock\")\n    c.assert_listed_binary({\"pkg/1.0\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\", \"Cache\")})\n"
  },
  {
    "path": "test/integration/lockfile/test_graph_overrides.py",
    "content": "import json\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.parametrize(\"override, force\", [(True, False), (False, True)])\ndef test_overrides_half_diamond(override, force):\n    r\"\"\"\n    pkgc -----> pkgb/0.1 --> pkga/0.1\n       \\--(override/force)-->pkga/0.2\n    \"\"\"\n    c = TestClient(light=True)\n    c.save({\"pkga/conanfile.py\": GenConanfile(\"pkga\"),\n            \"pkgb/conanfile.py\": GenConanfile(\"pkgb\", \"0.1\").with_requires(\"pkga/0.1\"),\n            \"pkgc/conanfile.py\": GenConanfile(\"pkgc\", \"0.1\").with_requirement(\"pkgb/0.1\")\n                                                            .with_requirement(\"pkga/0.2\",\n                                                                              override=override,\n                                                                              force=force)\n            })\n    c.run(\"create pkga --version=0.1\")\n    c.run(\"create pkga --version=0.2\")\n    c.run(\"create pkgb\")\n    c.run(\"lock create pkgc\")\n    lock = json.loads(c.load(\"pkgc/conan.lock\"))\n    requires = \"\\n\".join(lock[\"requires\"])\n    assert \"pkga/0.2\" in requires\n    assert \"pkga/0.1\" not in requires\n    c.run(\"graph info pkgc --lockfile=pkgc/conan.lock --format=json\")\n    dependencies = json.loads(c.stdout)[\"graph\"][\"nodes\"][\"0\"][\"dependencies\"]\n    assert \"pkga/0.2\" in str(dependencies)\n    assert \"pkga/0.1\" not in str(dependencies)\n    # apply the lockfile to pkgb, should it lock to pkga/0.2\n    c.run(\"graph info pkgb --lockfile=pkgc/conan.lock --format=json\")\n    dependencies = json.loads(c.stdout)[\"graph\"][\"nodes\"][\"0\"][\"dependencies\"]\n    assert \"pkga/0.2\" == dependencies[\"1\"][\"ref\"]\n    assert \"pkga/0.1\" == dependencies[\"1\"][\"require\"]\n\n\n@pytest.mark.parametrize(\"override, force\", [(True, False), (False, True)])\ndef test_overrides_half_diamond_ranges(override, force):\n    r\"\"\"\n       pkgc -----> pkgb/0.1 --> pkga/[>0.1 <0.2]\n          \\--(override/force)-->pkga/0.2\n    \"\"\"\n    c = TestClient(light=True)\n    c.save({\"pkga/conanfile.py\": GenConanfile(\"pkga\"),\n            \"pkgb/conanfile.py\": GenConanfile(\"pkgb\", \"0.1\").with_requires(\"pkga/[>=0.1 <0.2]\"),\n            \"pkgc/conanfile.py\": GenConanfile(\"pkgc\", \"0.1\").with_requirement(\"pkgb/0.1\")\n                                                            .with_requirement(\"pkga/0.2\",\n                                                                              override=override,\n                                                                              force=force)\n            })\n    c.run(\"create pkga --version=0.1\")\n    c.run(\"create pkga --version=0.2\")\n    c.run(\"create pkgb\")\n    assert \"pkga/0.2\" not in c.out\n    assert \"pkga/0.1\" in c.out\n    c.run(\"lock create pkgc\")\n    lock = c.load(\"pkgc/conan.lock\")\n    assert \"pkga/0.2\" in lock\n    assert \"pkga/0.1\" not in lock\n    c.run(\"graph info pkgc --lockfile=pkgc/conan.lock\")\n    assert \"pkga/0.2\" in c.out\n    assert \"pkga/0.1\" not in c.out\n    c.run(\"graph info pkgb --lockfile=pkgc/conan.lock\")\n    # should work\n\n\n@pytest.mark.parametrize(\"override, force\", [(True, False), (False, True)])\ndef test_overrides_half_diamond_ranges_inverted(override, force):\n    r\"\"\" the override is defining the lower bound of the range\n\n       pkgc -----> pkgb/0.1 --> pkga/[>=0.1]\n          \\--(override/force)-->pkga/0.1\n    \"\"\"\n    c = TestClient(light=True)\n    c.save({\"pkga/conanfile.py\": GenConanfile(\"pkga\"),\n            \"pkgb/conanfile.py\": GenConanfile(\"pkgb\", \"0.1\").with_requires(\"pkga/[>=0.1]\"),\n            \"pkgc/conanfile.py\": GenConanfile(\"pkgc\", \"0.1\").with_requirement(\"pkgb/0.1\")\n                                                            .with_requirement(\"pkga/0.1\",\n                                                                              override=override,\n                                                                              force=force)\n            })\n    c.run(\"create pkga --version=0.1\")\n    c.run(\"create pkga --version=0.2\")\n    c.run(\"create pkgb\")\n    assert \"pkga/0.2\" in c.out\n    assert \"pkga/0.1\" not in c.out\n    c.run(\"lock create pkgc\")\n    lock = c.load(\"pkgc/conan.lock\")\n    assert \"pkga/0.1\" in lock\n    assert \"pkga/0.2\" not in lock\n    c.run(\"graph info pkgc --lockfile=pkgc/conan.lock\")\n    assert \"pkga/0.1\" in c.out\n    assert \"pkga/0.2\" not in c.out\n    c.run(\"graph info pkgb --lockfile=pkgc/conan.lock\")\n    # should work\n\n\n@pytest.mark.parametrize(\"override, force\", [(True, False), (False, True)])\ndef test_overrides_diamond(override, force):\n    r\"\"\"\n    pkgd -----> pkgb/0.1 --> pkga/0.1\n       \\------> pkgc/0.1 --> pkga/0.2\n       \\--(override/force)-->pkga/0.3\n    \"\"\"\n    c = TestClient(light=True)\n    c.save({\"pkga/conanfile.py\": GenConanfile(\"pkga\"),\n            \"pkgb/conanfile.py\": GenConanfile(\"pkgb\", \"0.1\").with_requires(\"pkga/0.1\"),\n            \"pkgc/conanfile.py\": GenConanfile(\"pkgc\", \"0.1\").with_requires(\"pkga/0.2\"),\n            \"pkgd/conanfile.py\": GenConanfile(\"pkgd\", \"0.1\").with_requirement(\"pkgb/0.1\")\n                                                            .with_requirement(\"pkgc/0.1\")\n                                                            .with_requirement(\"pkga/0.3\",\n                                                                              override=override,\n                                                                              force=force)\n            })\n    c.run(\"create pkga --version=0.1\")\n    c.run(\"create pkga --version=0.2\")\n    c.run(\"create pkga --version=0.3\")\n    c.run(\"create pkgb\")\n    c.run(\"create pkgc\")\n    c.run(\"lock create pkgd\")\n    lock = json.loads(c.load(\"pkgd/conan.lock\"))\n    requires = \"\\n\".join(lock[\"requires\"])\n    assert \"pkga/0.3\" in requires\n    assert \"pkga/0.2\" not in requires\n    assert \"pkga/0.1\" not in requires\n    c.run(\"graph info pkgd --lockfile=pkgd/conan.lock --format=json\")\n    json_graph = json.loads(c.stdout)\n    deps = json_graph[\"graph\"][\"nodes\"][\"0\"][\"dependencies\"]\n    assert \"pkga/0.3\" in str(deps)\n    assert \"pkga/0.2\" not in str(deps)\n    assert \"pkga/0.1\" not in str(deps)\n    # Redundant assert, but checking \"overrides\" summary\n    overrides = json_graph['graph'][\"overrides\"]\n    assert len(overrides) == 2\n    assert overrides['pkga/0.1'] == ['pkga/0.3']\n    assert overrides['pkga/0.2'] == ['pkga/0.3']\n\n    # apply the lockfile to pkgb, should it lock to pkga/0.3\n    c.run(\"graph info pkgb --lockfile=pkgd/conan.lock --format=json\")\n    json_graph = json.loads(c.stdout)\n    deps = json_graph[\"graph\"][\"nodes\"][\"0\"][\"dependencies\"]\n    assert \"pkga/0.3\" == deps[\"1\"][\"ref\"]\n    assert \"pkga/0.1\" == deps[\"1\"][\"require\"]\n    # Redundant assert, but checking \"overrides\" summary\n    overrides = json_graph['graph'][\"overrides\"]\n    assert len(overrides) == 1\n    assert overrides[\"pkga/0.1\"] == [\"pkga/0.3\"]\n\n\n@pytest.mark.parametrize(\"override, force\", [(True, False), (False, True)])\ndef test_overrides_diamond_ranges(override, force):\n    r\"\"\"\n    pkgd -----> pkgb/0.1 --> pkga/[>=0.1 <0.2]\n       \\------> pkgc/0.1 --> pkga/[>=0.2 <0.3]\n       \\--(override/force)-->pkga/0.3\n    \"\"\"\n    c = TestClient(light=True)\n    c.save({\"pkga/conanfile.py\": GenConanfile(\"pkga\"),\n            \"pkgb/conanfile.py\": GenConanfile(\"pkgb\", \"0.1\").with_requires(\"pkga/[>=0.1 <0.2]\"),\n            \"pkgc/conanfile.py\": GenConanfile(\"pkgc\", \"0.1\").with_requires(\"pkga/[>=0.2 <0.3]\"),\n            \"pkgd/conanfile.py\": GenConanfile(\"pkgd\", \"0.1\").with_requirement(\"pkgb/0.1\")\n                                                            .with_requirement(\"pkgc/0.1\")\n                                                            .with_requirement(\"pkga/0.3\",\n                                                                              override=override,\n                                                                              force=force)\n            })\n    c.run(\"create pkga --version=0.1\")\n    c.run(\"create pkga --version=0.2\")\n    c.run(\"create pkga --version=0.3\")\n    c.run(\"create pkgb\")\n    c.run(\"create pkgc\")\n    c.run(\"lock create pkgd\")\n    lock = json.loads(c.load(\"pkgd/conan.lock\"))\n    requires = \"\\n\".join(lock[\"requires\"])\n    assert \"pkga/0.3\" in requires\n    assert \"pkga/0.2\" not in requires\n    assert \"pkga/0.1\" not in requires\n    c.run(\"graph info pkgd --lockfile=pkgd/conan.lock --format=json\")\n    dependencies = json.loads(c.stdout)[\"graph\"][\"nodes\"][\"0\"][\"dependencies\"]\n    assert \"pkga/0.3\" in str(dependencies)\n    assert \"pkga/0.2\" not in str(dependencies)\n    assert \"pkga/0.1\" not in str(dependencies)\n    # apply the lockfile to pkgb, should it lock to pkga/0.3\n    c.run(\"graph info pkgb --lockfile=pkgd/conan.lock --format=json\")\n    dependencies = json.loads(c.stdout)[\"graph\"][\"nodes\"][\"0\"][\"dependencies\"]\n    assert \"pkga/0.3\" in str(dependencies)\n    assert \"pkga/0.2\" not in str(dependencies)\n    assert \"pkga/0.1\" not in str(dependencies)\n\n\n@pytest.mark.parametrize(\"override1, force1\", [(True, False), (False, True)])\n@pytest.mark.parametrize(\"override2, force2\", [(True, False), (False, True)])\ndef test_overrides_multiple(override1, force1, override2, force2):\n    r\"\"\"\n    pkgd/0.1 -> pkgc/0.1 -> pkgb/0.1 -> pkga/0.1\n      \\           \\--override---------> pkga/0.2\n       \\---override-------------------> pkga/0.3\n    \"\"\"\n    c = TestClient(light=True)\n    c.save({\"pkga/conanfile.py\": GenConanfile(\"pkga\"),\n            \"pkgb/conanfile.py\": GenConanfile(\"pkgb\", \"0.1\").with_requires(\"pkga/0.1\"),\n            \"pkgc/conanfile.py\": GenConanfile(\"pkgc\", \"0.1\").with_requirement(\"pkgb/0.1\")\n                                                            .with_requirement(\"pkga/0.2\",\n                                                                              override=override1,\n                                                                              force=force1),\n            \"pkgd/conanfile.py\": GenConanfile(\"pkgd\", \"0.1\").with_requirement(\"pkgc/0.1\")\n                                                            .with_requirement(\"pkga/0.3\",\n                                                                              override=override2,\n                                                                              force=force2)\n            })\n    c.run(\"create pkga --version=0.1\")\n    c.run(\"create pkga --version=0.2\")\n    c.run(\"create pkga --version=0.3\")\n    c.run(\"create pkgb\")\n    c.run(\"create pkgc --build=missing\")\n    c.run(\"lock create pkgd\")\n    lock = json.loads(c.load(\"pkgd/conan.lock\"))\n    requires = \"\\n\".join(lock[\"requires\"])\n    assert \"pkga/0.3\" in requires\n    assert \"pkga/0.2\" not in requires\n    assert \"pkga/0.1\" not in requires\n    c.run(\"graph info pkgd --lockfile=pkgd/conan.lock\")\n    assert \"pkga/0.3\" in c.out\n    assert \"pkga/0.2#\" not in c.out\n    assert \"pkga/0.1#\" not in c.out  # appears in override information\n    c.run(\"graph info pkgb --lockfile=pkgd/conan.lock\")\n    # should work\n\n\ndef test_graph_different_overrides():\n    r\"\"\"\n    pkga -> toola/0.1 -> toolb/0.1 -> toolc/0.1\n                \\------override-----> toolc/0.2\n    pkgb -> toola/0.2 -> toolb/0.2 -> toolc/0.1\n                \\------override-----> toolc/0.3\n    pkgc -> toola/0.3 -> toolb/0.3 -> toolc/0.1\n    \"\"\"\n    c = TestClient(light=True)\n    c.save({\"toolc/conanfile.py\": GenConanfile(\"toolc\"),\n            \"toolb/conanfile.py\": GenConanfile(\"toolb\").with_requires(\"toolc/0.1\"),\n            \"toola/conanfile.py\": GenConanfile(\"toola\", \"0.1\").with_requirement(\"toolb/0.1\")\n                                                              .with_requirement(\"toolc/0.2\",\n                                                                                override=True),\n            \"toola2/conanfile.py\": GenConanfile(\"toola\", \"0.2\").with_requirement(\"toolb/0.2\")\n                                                               .with_requirement(\"toolc/0.3\",\n                                                                                 override=True),\n            \"toola3/conanfile.py\": GenConanfile(\"toola\", \"0.3\").with_requirement(\"toolb/0.3\"),\n            \"pkga/conanfile.py\": GenConanfile(\"pkga\", \"0.1\").with_tool_requires(\"toola/0.1\"),\n            \"pkgb/conanfile.py\": GenConanfile(\"pkgb\", \"0.1\").with_requires(\"pkga/0.1\")\n                                                            .with_tool_requires(\"toola/0.2\"),\n            \"pkgc/conanfile.py\": GenConanfile(\"pkgc\", \"0.1\").with_requires(\"pkgb/0.1\")\n                                                            .with_tool_requires(\"toola/0.3\"),\n            })\n    c.run(\"create toolc --version=0.1\")\n    c.run(\"create toolc --version=0.2\")\n    c.run(\"create toolc --version=0.3\")\n\n    c.run(\"create toolb --version=0.1\")\n    c.run(\"create toolb --version=0.2\")\n    c.run(\"create toolb --version=0.3\")\n\n    c.run(\"create toola --build=missing\")\n    c.run(\"create toola2 --build=missing\")\n    c.run(\"create toola3 --build=missing\")\n\n    c.run(\"create pkga\")\n    c.run(\"create pkgb\")\n    c.run(\"lock create pkgc\")\n    lock = json.loads(c.load(\"pkgc/conan.lock\"))\n    requires = \"\\n\".join(lock[\"build_requires\"])\n    assert \"toolc/0.3\" in requires\n    assert \"toolc/0.2\" in requires\n    assert \"toolc/0.1\" in requires\n\n    c.run(\"graph info toolb --build-require --version=0.1 --lockfile=pkgc/conan.lock --format=json\")\n    # defaults to the non overriden\n    c.assert_listed_require({\"toolc/0.1\": \"Cache\"}, build=True)\n    # TODO: Solve it with build-order or manual overrides for the other packages\n\n\n@pytest.mark.parametrize(\"override, force\", [(True, False), (False, True)])\ndef test_introduced_conflict(override, force):\n    \"\"\"\n    Using --lockfile-partial we can evaluate and introduce a new conflict\n    pkgd -----> pkgb/[*] --> pkga/[>=0.1 <0.2]\n    \"\"\"\n    c = TestClient(light=True)\n    c.save({\"pkga/conanfile.py\": GenConanfile(\"pkga\"),\n            \"pkgb/conanfile.py\": GenConanfile(\"pkgb\").with_requires(\"pkga/[>=0.1 <0.2]\"),\n            \"pkgc/conanfile.py\": GenConanfile(\"pkgc\", \"0.1\").with_requires(\"pkga/[>=0.2 <0.3]\"),\n            \"pkgd/conanfile.py\": GenConanfile(\"pkgd\", \"0.1\").with_requirement(\"pkgb/[*]\")\n            })\n    c.run(\"create pkga --version=0.1\")\n    c.run(\"create pkga --version=0.2\")\n    c.run(\"create pkga --version=0.3\")\n    c.run(\"create pkgb --version=0.1\")\n    c.run(\"create pkgc\")\n    c.run(\"lock create pkgd\")\n    lock = json.loads(c.load(\"pkgd/conan.lock\"))\n    requires = \"\\n\".join(lock[\"requires\"])\n    assert \"pkga/0.1\" in requires\n    assert \"pkga/0.2\" not in requires\n    assert \"pkga/0.3\" not in requires\n    # This will not be used thanks to the lockfile\n    c.run(\"create pkgb --version=0.2\")\n\n    \"\"\"\n    This change in pkgd introduce a conflict\n        Using --lockfile-partial we can evaluate and introduce a new conflict\n        pkgd -----> pkgb/[*] --> pkga/[>=0.1 <0.2]\n          |-------> pkgc/0.1 --> pkga/[>=0.2 <0.3]\n    \"\"\"\n    c.save({\"pkgd/conanfile.py\": GenConanfile(\"pkgd\", \"0.1\").with_requirement(\"pkgb/0.1\")\n                                                            .with_requirement(\"pkgc/0.1\")\n            })\n\n    c.run(\"graph info pkgd --lockfile=pkgd/conan.lock --lockfile-partial\", assert_error=True)\n    assert \"Version conflict: Conflict between pkga/[>=0.2 <0.3] and pkga/0.1 in the graph\" in c.out\n    # Resolve the conflict with an override or force\n    c.save({\"pkgd/conanfile.py\": GenConanfile(\"pkgd\", \"0.1\").with_requirement(\"pkgb/0.1\")\n                                                            .with_requirement(\"pkgc/0.1\")\n                                                            .with_requirement(\"pkga/0.3\",\n                                                                              override=override,\n                                                                              force=force)\n            })\n    c.run(\"graph info pkgd --lockfile=pkgd/conan.lock --lockfile-partial \"\n          \"--lockfile-out=pkgd/conan2.lock --lockfile-clean\")\n    assert \"pkgb/0.2\" not in c.out\n    assert \"pkgb/0.1\" in c.out\n    lock = json.loads(c.load(\"pkgd/conan2.lock\"))\n    requires = \"\\n\".join(lock[\"requires\"])\n    assert \"pkga/0.3\" in requires\n    assert \"pkga/0.1\" not in requires\n    assert \"pkga/0.2\" not in requires\n    assert \"pkgb/0.2\" not in requires\n\n\ndef test_command_line_lockfile_overrides():\n    \"\"\"\n    --lockfile-overrides cannot be abused to inject new overrides, only existing ones\n    \"\"\"\n    c = TestClient(light=True)\n    c.save({\n            \"pkga/conanfile.py\": GenConanfile(\"pkga\"),\n            \"pkgb/conanfile.py\": GenConanfile(\"pkgb\", \"0.1\").with_requires(\"pkga/0.1\"),\n            \"pkgc/conanfile.py\": GenConanfile(\"pkgc\", \"0.1\").with_requires(\"pkgb/0.1\"),\n            })\n\n    c.run(\"create pkga --version=0.1\")\n    c.run(\"create pkga --version=0.2\")\n    c.run(\"create pkgb\")\n    c.run('install pkgc --lockfile-overrides=\"{\\'pkga/0.1\\': [\\'pkga/0.2\\']}\"', assert_error=True)\n    assert \"Cannot define overrides without a lockfile\" in c.out\n    c.run('lock create pkgc')\n    c.run('install pkgc --lockfile-overrides=\"{\\'pkga/0.1\\': [\\'pkga/0.2\\']}\"')\n    # From https://github.com/conan-io/conan/issues/19738 it is simply ignored\n    # Not a hard \"protection\" error, still users can't inject a dependency to pkga/0.2 if not\n    # in the lockfile already\n    assert \"pka/0.2\" not in c.out\n    assert \"pkga/0.1\" in c.out\n\n\ndef test_consecutive_installs():\n    c = TestClient(light=True)\n    c.save({\n        \"pkga/conanfile.py\": GenConanfile(\"pkga\"),\n        \"pkgb/conanfile.py\": GenConanfile(\"pkgb\", \"0.1\").with_requires(\"pkga/0.1\"),\n        \"pkgc/conanfile.py\": GenConanfile(\"pkgc\", \"0.1\").with_requires(\"pkgb/0.1\")\n                                                        .with_requirement(\"pkga/0.2\", override=True),\n    })\n    c.run(\"export pkga --version=0.1\")\n    c.run(\"export pkga --version=0.2\")\n    c.run(\"export pkgb\")\n    c.run(\"install pkgc --build=missing --lockfile-out=conan.lock\")\n    c.assert_overrides({\"pkga/0.1\": [\"pkga/0.2\"]})\n    # This used to crash when overrides were not managed\n    c.run(\"install pkgc --build=missing --lockfile=conan.lock --lockfile-out=conan.lock\")\n    c.assert_overrides({\"pkga/0.1\": [\"pkga/0.2\"]})\n\n\nclass TestOverrideContextError:\n    # https://github.com/conan-io/conan/issues/19738\n    def test_error_lockfile_override_build_require(self):\n        # The override that comes from the host context is breaking the build locking\n        c = TestClient(light=True)\n        c.save({\"abseil/conanfile.py\": GenConanfile(\"abseil\"),\n                \"protobuf/conanfile.py\": GenConanfile(\"protobuf\", \"0.1\").with_requires(\"abseil/[*]\"),\n                \"app/conanfile.py\": GenConanfile(\"pkgd\", \"0.1\").with_requirement(\"protobuf/0.1\")\n                                                               .with_requirement(\"abseil/0.1\",\n                                                                                 override=True)\n                                                               .with_tool_requires(\"protobuf/0.1\")\n                })\n        c.run(\"create abseil --version=0.1\")\n        c.run(\"create abseil --version=0.2\")\n        c.run(\"create protobuf\")\n        c.run(\"lock create app\")\n        c.run(\"install app --build=missing --lockfile=app/conan.lock\")\n        # It doesnt fail\n\n    def test_error_lockfile_override_build_require_build(self):\n        # Same as the above, but now the override is in the \"build\" context, affecting the\n        # host one that shouldn't be overriden\n        c = TestClient(light=True)\n        c.save({\"pkga/conanfile.py\": GenConanfile(\"pkga\"),\n                \"pkgb/conanfile.py\": GenConanfile(\"pkgb\", \"0.1\").with_requires(\"pkga/[*]\"),\n                \"toolb/conanfile.py\": GenConanfile(\"toolb\", \"0.1\").with_requirement(\"pkgb/0.1\")\n                                                                  .with_requirement(\"pkga/0.1\",\n                                                                                    override=True),\n                \"app/conanfile.py\": GenConanfile(\"pkgd\", \"0.1\").with_requirement(\"pkgb/0.1\")\n                                                               .with_tool_requires(\"toolb/0.1\")\n                })\n        c.run(\"create pkga --version=0.1\")\n        c.run(\"create pkga --version=0.2\")\n        c.run(\"create pkgb\")\n        c.run(\"create toolb --build=missing\")\n        c.run(\"lock create app\")\n        c.run(\"install app --lockfile=app/conan.lock\")\n        # It doesnt fail\n"
  },
  {
    "path": "test/integration/lockfile/test_lock_alias.py",
    "content": "import os\n\nimport pytest\n\nfrom conan.internal.graph.graph_builder import DepsGraphBuilder\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\nDepsGraphBuilder.ALLOW_ALIAS = True\n\n\n@pytest.mark.parametrize(\"requires\", [\"requires\", \"tool_requires\"])\ndef test_conanfile_txt_deps_ranges(requires):\n    \"\"\"\n    conanfile.txt locking it dependencies (with version ranges) using alias\n    \"\"\"\n    client = TestClient(light=True)\n    client.save({\"pkg/conanfile.py\": GenConanfile(\"pkg\"),\n                 \"consumer/conanfile.txt\": f\"[{requires}]\\npkg/(latest)\"})\n    client.run(\"create pkg --version=0.1\")\n    client.run(\"create pkg --version=0.2\")\n    with client.chdir(\"alias\"):\n        client.run(\"new alias -d name=pkg -d version=latest -d target=0.1\")\n        client.run(\"export .\")\n    client.run(\"lock create consumer/conanfile.txt\")\n    assert \"pkg/0.1\" in client.out\n    assert '\"pkg/latest\": \"pkg/0.1\"' in client.load(\"consumer/conan.lock\")\n\n    # Change the alias\n    with client.chdir(\"alias\"):\n        client.run(\"new alias -d name=pkg -d version=latest -d target=0.2 -f\")\n        client.run(\"export .\")\n    client.run(\"install consumer/conanfile.txt\")  # use conan.lock by default\n    assert \"pkg/0.1\" in client.out\n    assert \"pkg/0.2\" not in client.out\n\n    os.remove(os.path.join(client.current_folder, \"consumer/conan.lock\"))\n    client.run(\"install consumer/conanfile.txt\")\n    assert \"pkg/0.2\" in client.out\n    assert \"pkg/0.1\" not in client.out\n\n\n@pytest.mark.parametrize(\"requires\", [\"requires\", \"tool_requires\"])\ndef test_conanfile_txt_deps_ranges_lock_revisions(requires):\n    \"\"\"\n    conanfile.txt locking it dependencies (with version ranges)\n    \"\"\"\n    client = TestClient(light=True)\n    client.save({\"pkg/conanfile.py\": GenConanfile(\"pkg\"),\n                 \"consumer/conanfile.txt\": f\"[{requires}]\\npkg/(latest)\"})\n    client.run(\"create pkg --version=0.1\")\n    client.assert_listed_require({\"pkg/0.1#a9ec2e5fbb166568d4670a9cd1ef4b26\": \"Cache\"})\n    client.run(\"create pkg --version=0.2\")\n    with client.chdir(\"alias\"):\n        client.run(\"new alias -d name=pkg -d version=latest -d target=0.1\")\n        client.run(\"export .\")\n    client.run(\"lock create consumer/conanfile.txt\")\n    assert \"pkg/0.1#a9ec2e5fbb166568d4670a9cd1ef4b26\" in client.out\n    assert '\"pkg/latest\": \"pkg/0.1\"' in client.load(\"consumer/conan.lock\")\n\n    # Create a new revision\n    client.save({\"pkg/conanfile.py\": GenConanfile(\"pkg\").with_class_attribute(\"potato=42\")})\n    client.run(\"create pkg --version=0.1\")\n    client.assert_listed_require({\"pkg/0.1#8d60cd02b0b4aa8fe8b3cae32944c61b\": \"Cache\"})\n    client.run(\"install consumer/conanfile.txt\")  # use conan.lock by default\n    assert \"pkg/0.1#a9ec2e5fbb166568d4670a9cd1ef4b26\" in client.out\n    assert \"pkg/0.1#8d60cd02b0b4aa8fe8b3cae32944c61b\" not in client.out\n\n    os.remove(os.path.join(client.current_folder, \"consumer/conan.lock\"))\n    client.run(\"install consumer/conanfile.txt\")\n    assert \"pkg/0.1#a9ec2e5fbb166568d4670a9cd1ef4b26\" not in client.out\n    assert \"pkg/0.1#8d60cd02b0b4aa8fe8b3cae32944c61b\" in client.out\n"
  },
  {
    "path": "test/integration/lockfile/test_lock_build_requires.py",
    "content": "import json\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_lock_build_tool_requires():\n    c = TestClient(light=True)\n    c.save({\"common/conanfile.py\": GenConanfile(\"common\", \"1.0\").with_settings(\"os\"),\n            \"tool/conanfile.py\": GenConanfile(\"tool\", \"1.0\").with_settings(\"os\")\n                                                            .with_requires(\"common/1.0\"),\n            \"lib/conanfile.py\": GenConanfile(\"lib\", \"1.0\").with_settings(\"os\")\n                                                          .with_requires(\"tool/1.0\"),\n            \"consumer/conanfile.py\":\n                GenConanfile(\"consumer\", \"1.0\").with_settings(\"os\")\n                                               .with_requires(\"lib/1.0\")\n                                               .with_build_requires(\"tool/1.0\")})\n    c.run(\"export common\")\n    c.run(\"export tool\")\n    c.run(\"export lib\")\n    # cross compile Linux->Windows\n    c.run(\"lock create consumer/conanfile.py -s:h os=Linux -s:b os=Windows --build=*\")\n    c.run(\"install --tool-requires=tool/1.0 --build=missing --lockfile=consumer/conan.lock \"\n          \"-s:h os=Linux -s:b os=Windows\")\n    c.assert_listed_binary({\"tool/1.0\": (\"78ba71aef65089d6e3244756171f9f37d5a76223\", \"Build\"),\n                            \"common/1.0\": (\"ebec3dc6d7f6b907b3ada0c3d3cdc83613a2b715\", \"Build\")},\n                           build=True)\n\n\ndef test_lock_buildrequires_create():\n    c = TestClient(light=True)\n    c.save({\"conanfile.py\": GenConanfile(\"tool\", \"0.1\")})\n    c.run(\"create .  --build-require --lockfile-out=conan.lock\")\n    lock = json.loads(c.load(\"conan.lock\"))\n    assert \"tool/0.1#2d65f1b4af1ce59028f96adbfe7ed5a2\" in lock[\"build_requires\"][0]\n\n\ndef test_lock_buildrequires_export():\n    c = TestClient(light=True)\n    c.save({\"conanfile.py\": GenConanfile(\"tool\", \"0.1\")})\n    c.run(\"export . --build-require --lockfile-out=conan.lock\")\n    lock = json.loads(c.load(\"conan.lock\"))\n    assert \"tool/0.1#2d65f1b4af1ce59028f96adbfe7ed5a2\" in lock[\"build_requires\"][0]\n\n\ndef test_lock_buildrequires_create_transitive():\n    c = TestClient(light=True)\n    c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\"),\n            \"tool/conanfile.py\": GenConanfile(\"tool\", \"0.1\").with_requires(\"dep/0.1\")})\n    c.run(\"create dep\")\n    c.run(\"create tool --build-require --lockfile-out=conan.lock\")\n    lock = json.loads(c.load(\"conan.lock\"))\n    assert \"tool/0.1#e4f0da4d9097c4da0725ea25b8bf83c8\" in lock[\"build_requires\"][0]\n    assert \"dep/0.1#f8c2264d0b32a4c33f251fe2944bb642\" in lock[\"build_requires\"][1]\n\n\ndef test_lock_create_build_require_transitive():\n    \"\"\" cross compiling from Windows to Linux\n    \"\"\"\n    c = TestClient(light=True)\n    dep = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Dep(ConanFile):\n            name = \"dep\"\n            settings = \"os\"\n            def package_id(self):\n                self.output.info(f\"MYOS:{self.info.settings.os}!!\")\n                self.output.info(f\"TARGET:{self.settings_target.os}!!\")\n            \"\"\")\n    tool = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Tool(ConanFile):\n           name = \"tool\"\n           version = \"0.1\"\n           requires = \"dep/[*]\"\n           settings = \"os\"\n           def generate(self):\n               self.output.info(f\"MYOS-GEN:{self.info.settings.os}!!\")\n               self.output.info(f\"TARGET-GEN:{self.settings_target.os}!!\")\n           def package_id(self):\n               self.output.info(f\"MYOS:{self.info.settings.os}!!\")\n               self.output.info(f\"TARGET:{self.settings_target.os}!!\")\n           \"\"\")\n    c.save({\"dep/conanfile.py\": dep,\n            \"tool/conanfile.py\": tool})\n    c.run(\"create dep --build-require --version=0.1 -s:b os=Windows -s:h os=Linux\")\n    assert \"dep/0.1: MYOS:Windows!!\" in c.out\n    assert \"dep/0.1: TARGET:Linux!!\" in c.out\n\n    # The lockfile should contain dep in build-requires\n    c.run(\"lock create tool --build-require -s:b os=Windows -s:h os=Linux\")\n    assert \"dep/0.1: MYOS:Windows!!\" in c.out\n    assert \"dep/0.1: TARGET:Linux!!\" in c.out\n    lock = json.loads(c.load(\"tool/conan.lock\"))\n    assert \"dep/0.1\" in lock[\"build_requires\"][0]\n\n    # Now try to apply it in  graph info, even if a new 0.2 verion si there\n    c.run(\"create dep --build-require --version=0.2 -s:b os=Windows -s:h os=Linux\")\n    assert \"dep/0.2: MYOS:Windows!!\" in c.out\n    assert \"dep/0.2: TARGET:Linux!!\" in c.out\n\n    c.run(\"graph info tool --build-require -s:b os=Windows -s:h os=Linux\")\n    c.assert_listed_require({\"dep/0.1\": \"Cache\"}, build=True)\n    assert \"dep/0.1: MYOS:Windows!!\" in c.out\n    assert \"dep/0.1: TARGET:Linux!!\" in c.out\n    assert \"conanfile.py (tool/0.1): MYOS:Windows!!\" in c.out\n    assert \"conanfile.py (tool/0.1): TARGET:Linux!!\" in c.out\n    assert \"context: build\" in c.out\n    assert \"context: host\" not in c.out\n\n    c.run(\"install tool --build-require -s:b os=Windows -s:h os=Linux\")\n    c.assert_listed_require({\"dep/0.1\": \"Cache\"}, build=True)\n    assert \"dep/0.1: MYOS:Windows!!\" in c.out\n    assert \"dep/0.1: TARGET:Linux!!\" in c.out\n    assert \"conanfile.py (tool/0.1): MYOS:Windows!!\" in c.out\n    assert \"conanfile.py (tool/0.1): TARGET:Linux!!\" in c.out\n    assert \"conanfile.py (tool/0.1): MYOS-GEN:Windows!!\" in c.out\n    assert \"conanfile.py (tool/0.1): TARGET-GEN:Linux!!\" in c.out\n\n\nclass TestTransitiveBuildRequires:\n    @pytest.fixture()\n    def client(self):\n        # https://github.com/conan-io/conan/issues/13899\n        client = TestClient(light=True)\n        client.save({\"zlib/conanfile.py\": GenConanfile(\"zlib\", \"1.0\"),\n                     \"cmake/conanfile.py\": GenConanfile(\"cmake\", \"1.0\").with_requires(\"zlib/1.0\"),\n                     \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_build_requires(\"cmake/1.0\"),\n                     \"consumer/conanfile.py\": GenConanfile().with_requires(\"pkg/[>=1.0]\"),\n                     })\n\n        client.run(\"export zlib\")\n        client.run(\"export cmake\")\n        client.run(\"export pkg\")\n        client.run(\"lock create consumer/conanfile.py -pr:b=default --build=* \"\n                   \"--lockfile-out=conan.lock\")\n        return client\n\n    def test_transitive_build_require(self, client):\n        # This used to crash, not anymore with the fix\n        client.run(\"install consumer/conanfile.py --build=missing --lockfile=conan.lock\")\n        assert \"zlib/1.0: Created package\" in client.out\n        assert \"cmake/1.0: Created package\" in client.out\n        assert \"pkg/1.0: Created package\" in client.out\n\n    def test_transitive_build_require_intermediate(self, client):\n        # This used to crash, not anymore with the fix\n        client.run(\"install pkg/conanfile.py --build=missing --lockfile=conan.lock\")\n        assert \"zlib/1.0: Created package\" in client.out\n        assert \"cmake/1.0: Created package\" in client.out\n"
  },
  {
    "path": "test/integration/lockfile/test_lock_merge.py",
    "content": "import textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.parametrize(\"requires\", [\"requires\", \"tool_requires\"])\ndef test_merge_alias(requires):\n    \"\"\"\n    basic lockfile merging including alias\n    \"\"\"\n    c = TestClient()\n    app = textwrap.dedent(f\"\"\"\n        from conan import ConanFile\n        class App(ConanFile):\n            settings = \"build_type\"\n            def requirements(self):\n                if self.settings.build_type == \"Debug\":\n                    self.{requires}(\"pkg/(alias_debug)\")\n                else:\n                    self.{requires}(\"pkg/(alias_release)\")\n        \"\"\")\n    c.save({\"pkg/conanfile.py\": GenConanfile(\"pkg\"),\n            \"alias_release/conanfile.py\": GenConanfile(\"pkg\", \"alias_release\").with_class_attribute(\n                \"alias = 'pkg/0.1'\"),\n            \"alias_debug/conanfile.py\": GenConanfile(\"pkg\", \"alias_debug\").with_class_attribute(\n                \"alias = 'pkg/0.2'\"),\n            \"app/conanfile.py\": app})\n    c.run(\"create pkg --version=0.1\")\n    c.run(\"create pkg --version=0.2\")\n    c.run(\"export alias_release\")\n    c.run(\"export alias_debug\")\n    c.run(\"lock create app -s build_type=Release --lockfile-out=release.lock\")\n    c.run(\"lock create app -s build_type=Debug --lockfile-out=debug.lock\")\n\n    c.run(\"lock merge --lockfile=release.lock --lockfile=debug.lock --lockfile-out=conan.lock\")\n\n    # Update alias, won't be used\n    c.save({\"alias_release/conanfile.py\": GenConanfile(\"pkg\", \"alias_release\").with_class_attribute(\n                \"alias = 'pkg/0.3'\"),\n            \"alias_debug/conanfile.py\": GenConanfile(\"pkg\", \"alias_debug\").with_class_attribute(\n                \"alias = 'pkg/0.4'\")})\n    c.run(\"export alias_release\")\n    c.run(\"export alias_debug\")\n\n    # Merged one can resolve both aliased without issues\n    c.run(\"install app -s build_type=Release --lockfile=conan.lock\")\n    is_build_requires = requires == \"tool_requires\"\n    c.assert_listed_require({\"pkg/0.1\": \"Cache\"}, build=is_build_requires)\n    c.run(\"install app -s build_type=Debug --lockfile=conan.lock\")\n    c.assert_listed_require({\"pkg/0.2\": \"Cache\"}, build=is_build_requires)\n\n    # without lockfiles it would be pointing to the new (unexistent) ones\n    c.run(\"install app -s build_type=Release\", assert_error=True)\n    assert \"ERROR: Package 'pkg/0.3' not resolved\" in c.out\n    c.run(\"install app -s build_type=Debug\", assert_error=True)\n    assert \"ERROR: Package 'pkg/0.4' not resolved\" in c.out\n"
  },
  {
    "path": "test/integration/lockfile/test_lock_packages.py",
    "content": "import os\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient, NO_SETTINGS_PACKAGE_ID\nfrom conan.test.utils.env import environment_update\n\n\n@pytest.mark.parametrize(\"requires\", [\"requires\", \"tool_requires\"])\ndef test_lock_packages(requires):\n    \"\"\"\n    Check that package revisions can be locked too\n    NOTE: They are still not used! only to check that it is possible to store them\n          And that the lockfile is still usable\n    \"\"\"\n    client = TestClient(light=True)\n    client.save({\"pkg/conanfile.py\": GenConanfile().with_package_file(\"file.txt\", env_var=\"MYVAR\"),\n                 \"consumer/conanfile.txt\": f\"[{requires}]\\npkg/[>0.0]\"})\n    with environment_update({\"MYVAR\": \"MYVALUE\"}):\n        client.run(\"create pkg --name=pkg --version=0.1\")\n    prev = client.created_package_revision(\"pkg/0.1\")\n\n    client.run(\"lock create consumer/conanfile.txt --lockfile-packages\")\n    assert \"ERROR: The --lockfile-packages arg is private and shouldn't be used\" in client.out\n    assert \"pkg/0.1#\" in client.out\n    lock = client.load(\"consumer/conan.lock\")\n    assert NO_SETTINGS_PACKAGE_ID in lock\n\n    with environment_update({\"MYVAR\": \"MYVALUE2\"}):\n        client.run(\"create pkg --name=pkg --version=0.1\")\n    prev2 = client.created_package_revision(\"pkg/0.1\")\n    assert prev2 != prev\n\n    client.run(\"install consumer/conanfile.txt\")\n    assert prev in client.out\n    assert prev2 not in client.out\n\n    os.remove(os.path.join(client.current_folder, \"consumer/conan.lock\"))\n    client.run(\"install consumer/conanfile.txt\")\n    assert prev2 in client.out\n    assert prev not in client.out\n"
  },
  {
    "path": "test/integration/lockfile/test_lock_pyrequires.py",
    "content": "import json\nimport os\nimport textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import load\n\n\ndef test_transitive_py_requires():\n    # https://github.com/conan-io/conan/issues/5529\n    client = TestClient(light=True)\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class PackageInfo(ConanFile):\n            python_requires = \"dep/[>0.0]@user/channel\"\n        \"\"\")\n    consumer = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class MyConanfileBase(ConanFile):\n            python_requires = \"pkg/0.1@user/channel\"\n        \"\"\")\n    client.save({\"dep/conanfile.py\": GenConanfile(),\n                 \"pkg/conanfile.py\": conanfile,\n                 \"consumer/conanfile.py\": consumer})\n\n    client.run(\"export dep --name=dep --version=0.1 --user=user --channel=channel\")\n    client.run(\"export pkg --name=pkg --version=0.1 --user=user --channel=channel\")\n    client.run(\"lock create consumer/conanfile.py\")\n\n    client.run(\"export dep --name=dep --version=0.2 --user=user --channel=channel\")\n\n    client.run(\"install consumer/conanfile.py\")\n    assert \"dep/0.1@user/channel\" in client.out\n    assert \"dep/0.2\" not in client.out\n\n    os.remove(os.path.join(client.current_folder, \"consumer/conan.lock\"))\n    client.run(\"install consumer/conanfile.py\")\n    assert \"dep/0.2@user/channel\" in client.out\n    assert \"dep/0.1\" not in client.out\n\n\ndef test_transitive_matching_ranges():\n    client = TestClient(light=True)\n    tool = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class PackageInfo(ConanFile):\n            python_requires = \"dep/{}\"\n        \"\"\")\n    pkg = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class MyConanfileBase(ConanFile):\n            python_requires = \"tool/{}\"\n            def configure(self):\n                for k, p in self.python_requires.items():\n                    self.output.info(\"%s: %s!!\" % (k, p.ref))\n        \"\"\")\n    client.save({\"dep/conanfile.py\": GenConanfile(),\n                 \"tool1/conanfile.py\": tool.format(\"[<0.2]\"),\n                 \"tool2/conanfile.py\": tool.format(\"[>0.0]\"),\n                 \"pkga/conanfile.py\": pkg.format(\"[<0.2]\"),\n                 \"pkgb/conanfile.py\": pkg.format(\"[>0.0]\"),\n                 \"app/conanfile.py\": GenConanfile().with_requires(\"pkga/[*]\", \"pkgb/[*]\")})\n\n    client.run(\"export dep --name=dep --version=0.1\")\n    client.run(\"export dep --name=dep --version=0.2\")\n    client.run(\"export tool1 --name=tool --version=0.1\")\n    client.run(\"export tool2 --name=tool --version=0.2\")\n    client.run(\"create pkga --name=pkga --version=0.1\")\n    client.run(\"create pkgb --name=pkgb --version=0.1\")\n    client.run(\"lock create app/conanfile.py --lockfile-out=app.lock\")\n\n    client.run(\"export dep --name=dep --version=0.2\")\n    client.run(\"export tool2 --name=tool --version=0.3\")\n    client.run(\"create pkga --name=pkga --version=0.2\")\n    client.run(\"create pkgb --name=pkgb --version=0.2\")\n\n    client.run(\"install app/conanfile.py --lockfile=app.lock\")\n    assert \"pkga/0.1: tool: tool/0.1!!\" in client.out\n    assert \"pkga/0.1: dep: dep/0.1!!\" in client.out\n    assert \"pkgb/0.1: tool: tool/0.2!!\" in client.out\n    assert \"pkgb/0.1: dep: dep/0.2!!\" in client.out\n\n    client.run(\"install app/conanfile.py\")\n    assert \"pkga/0.2: tool: tool/0.1!!\" in client.out\n    assert \"pkga/0.2: dep: dep/0.1!!\" in client.out\n    assert \"pkgb/0.2: tool: tool/0.3!!\" in client.out\n    assert \"pkgb/0.2: dep: dep/0.2!!\" in client.out\n\n\ndef test_lock_pyrequires_prereleases():\n    tc = TestClient(light=True)\n    tc.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"1.0-0.1\"),\n             \"app/conanfile.py\": GenConanfile(\"app\", \"1.0\").with_python_requires(\"dep/[>=0]\")})\n    tc.run(\"export dep\")\n    dep_rrev = tc.exported_recipe_revision()\n    tc.run(\"lock create app --lockfile-out=app.lock\", assert_error=True)\n    # Makes sense, prereleases are not active\n    assert (\"Version range '>=0' from requirement 'dep/[>=0]' required by \"\n            \"'python_requires' could not be resolved\") in tc.out\n\n    tc.save_home({\"global.conf\": \"core.version_ranges:resolve_prereleases=True\"})\n    # This used to crash even with the conf activated\n    tc.run(\"lock create app --lockfile-out=app.lock\")\n    data = json.loads(load(os.path.join(tc.current_folder, \"app.lock\")))\n    assert data[\"python_requires\"][0].startswith(f\"dep/1.0-0.1#{dep_rrev}\")\n\n\ndef test_lock_pyrequires_create():\n    c = TestClient(light=True)\n    c.save({\"conanfile.py\": GenConanfile(\"tool\", \"0.1\").with_package_type(\"python-require\")})\n    c.run(\"create .  --lockfile-out=conan.lock\")\n    lock = json.loads(c.load(\"conan.lock\"))\n    assert \"tool/0.1#7835890f1e86b3f7fc6d76b4e3c43cb1\" in lock[\"python_requires\"][0]\n\n\ndef test_lock_pyrequires_export():\n    c = TestClient(light=True)\n    c.save({\"conanfile.py\": GenConanfile(\"tool\", \"0.1\").with_package_type(\"python-require\")})\n    c.run(\"export .  --lockfile-out=conan.lock\")\n    lock = json.loads(c.load(\"conan.lock\"))\n    assert \"tool/0.1#7835890f1e86b3f7fc6d76b4e3c43cb1\" in lock[\"python_requires\"][0]\n\n\ndef test_lock_pyrequires_export_transitive():\n    c = TestClient(light=True)\n    c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\").with_package_type(\"python-require\"),\n            \"tool/conanfile.py\": GenConanfile(\"tool\", \"0.1\").with_package_type(\"python-require\")\n                                                            .with_python_requires(\"dep/0.1\")})\n    c.run(\"export dep\")\n    c.run(\"export tool --lockfile-out=conan.lock\")\n    lock = json.loads(c.load(\"conan.lock\"))\n    assert \"tool/0.1#c0008d3fcf07f7a690dd16bf6c171cec\" in lock[\"python_requires\"][0]\n    assert \"dep/0.1#5d31586a2a4355d68898875dc591009a\" in lock[\"python_requires\"][1]\n\n\ndef test_lock_export_transitive_pyrequire():\n    c = TestClient(light=True)\n    c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\").with_package_type(\"python-require\"),\n            \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_python_requires(\"dep/0.1\")})\n    c.run(\"export dep\")\n    c.run(\"export pkg --lockfile-out=conan.lock\")\n    lock = json.loads(c.load(\"conan.lock\"))\n    assert \"pkg/0.1#dfd6bc1becb3915043a671111860baee\" in lock[\"requires\"][0]\n    assert \"dep/0.1#5d31586a2a4355d68898875dc591009a\" in lock[\"python_requires\"][0]\n\n\ndef test_pyrequires_test_package_lockfile_error():\n    # https://github.com/conan-io/conan/issues/19340\n    c = TestClient(light=True)\n    c.save({\"utils/conanfile.py\": GenConanfile(\"utils\").with_package_type(\"python-require\"),\n            \"bar/conanfile.py\": GenConanfile(\"bar\", \"8.0\").with_python_requires(\"utils/[^1]\"),\n            \"bar/test_package/conanfile.py\": GenConanfile().with_test(\"pass\")\n                                                           .with_python_requires(\"utils/[^1]\"),\n            \"foo/conanfile.py\": GenConanfile(\"foo\", \"1.0\").with_requires(\"bar/[*]\")\n                                                          .with_python_requires(\"utils/1.7.1\")})\n\n    c.run(\"create utils --version=1.7.1\")\n    c.run(\"create utils --version=1.8.0\")\n    c.run(\"create bar --lockfile-out=bar.lock\")\n    c.run(\"create foo\", assert_error=True)\n    assert \"Missing prebuilt package for 'bar/8.0'\" in c.out\n\n    c.run(\"create foo --lockfile=bar.lock --lockfile-partial --lockfile-out=foo.lock\")\n    c.assert_listed_require({\"utils/1.7.1\": \"Cache\",\n                             \"utils/1.8.0\": \"Cache\"}, python=True)\n    lock = json.loads(c.load(\"foo.lock\"))\n    assert \"utils/1.8.0\" in lock[\"python_requires\"][0]\n    assert \"utils/1.7.1\" in lock[\"python_requires\"][1]\n\n    # The lockfile works, because the fixed version is an older one, and the lock can have\n    # both, the range resolves to 1.8.0, and the fixed resolves to 1.7.1\n    # This lockfile can be used with same results\n    c.run(\"create foo --lockfile=foo.lock\")\n    c.assert_listed_require({\"utils/1.7.1\": \"Cache\",\n                             \"utils/1.8.0\": \"Cache\"}, python=True)\n\n\ndef test_pyrequires_test_package_lockfile_error_forward():\n    # https://github.com/conan-io/conan/issues/19340\n    c = TestClient(light=True)\n    c.save({\"utils/conanfile.py\": GenConanfile(\"utils\").with_package_type(\"python-require\"),\n            \"bar/conanfile.py\": GenConanfile(\"bar\", \"8.0\").with_python_requires(\"utils/[^1]\"),\n            \"bar/test_package/conanfile.py\": GenConanfile().with_test(\"pass\")\n                                                           .with_python_requires(\"utils/[^1]\"),\n            \"foo/conanfile.py\": GenConanfile(\"foo\", \"1.0\").with_requires(\"bar/[*]\")\n                                                          .with_python_requires(\"utils/1.9.0\")})\n\n    # bar binary is built with utils/1.8.0\n    c.run(\"create utils --version=1.8.0\")\n    c.run(\"create bar --lockfile-out=bar.lock\")\n    c.assert_listed_require({\"utils/1.8.0\": \"Cache\"}, python=True)\n    lock = json.loads(c.load(\"bar.lock\"))\n    assert \"utils/1.8.0\" in lock[\"python_requires\"][0]\n\n    # now a new utils/1.9.0 is out, so the regular consumption of bar will fail with missing binary\n    # this will happen even if foo doesn't declare python-requires\n    c.run(\"create utils --version=1.9.0\")\n    c.run(\"create foo\", assert_error=True)\n    assert \"Missing prebuilt package for 'bar/8.0'\" in c.out\n    c.assert_listed_require({\"utils/1.9.0\": \"Cache\"}, python=True)\n\n    # If we try to force bar strict dependencies with lockfile, it will fail, as expected\n    c.run(\"create foo --lockfile=bar.lock\", assert_error=True)\n    assert \"Requirement 'utils/1.9.0' not in lockfile 'python_requires'\" in c.out\n\n    # we can relax the lockfile, and it will be able to resolve,\n    # but it will still fail with missing binary for bar\n    c.run(\"create foo --lockfile=bar.lock --lockfile-partial\", assert_error=True)\n    assert \"Missing prebuilt package for 'bar/8.0'\" in c.out\n\n    c.run(\"create foo --lockfile=bar.lock --lockfile-partial --build=missing \"\n          \"--lockfile-out=foo.lock\")\n    c.assert_listed_require({\"utils/1.9.0\": \"Cache\"}, python=True)\n    assert \"utils/1.8.0\" not in c.out\n\n    # This build is reproducible with this lockfile\n    c.run(\"create foo --lockfile=foo.lock\")\n    c.assert_listed_require({\"utils/1.9.0\": \"Cache\"}, python=True)\n    assert \"utils/1.8.0\" not in c.out\n"
  },
  {
    "path": "test/integration/lockfile/test_lock_pyrequires_revisions.py",
    "content": "import os\nimport textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_transitive_py_requires_revisions():\n    # https://github.com/conan-io/conan/issues/5529\n    client = TestClient(light=True)\n    python_req = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        some_var = {}\n        class PackageInfo(ConanFile):\n            pass\n        \"\"\")\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class PackageInfo(ConanFile):\n            python_requires = \"dep/0.1@user/channel\"\n        \"\"\")\n    consumer = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class MyConanfileBase(ConanFile):\n            python_requires = \"pkg/0.1@user/channel\"\n            def generate(self):\n                self.output.info(\"VAR={}!!!\".format(self.python_requires[\"dep\"].module.some_var))\n        \"\"\")\n    client.save({\"dep/conanfile.py\": python_req.format(\"42\"),\n                 \"pkg/conanfile.py\": conanfile,\n                 \"consumer/conanfile.py\": consumer})\n\n    client.run(\"export dep --name=dep --version=0.1 --user=user --channel=channel\")\n    client.run(\"export pkg --name=pkg --version=0.1 --user=user --channel=channel\")\n    client.run(\"lock create consumer/conanfile.py\")\n\n    client.save({\"dep/conanfile.py\": python_req.format(\"123\")})\n    client.run(\"export dep --name=dep --version=0.1 --user=user --channel=channel\")\n\n    client.run(\"install consumer/conanfile.py\")\n    assert \"conanfile.py: VAR=42!!!\" in client.out\n\n    os.remove(os.path.join(client.current_folder, \"consumer/conan.lock\"))\n    client.run(\"install consumer/conanfile.py\")\n    assert \"conanfile.py: VAR=123!!!\" in client.out\n\n\ndef test_transitive_matching_revisions():\n    client = TestClient(light=True)\n    dep = textwrap.dedent(\"\"\"\n       from conan import ConanFile\n       some_var = {}\n       class PackageInfo(ConanFile):\n           pass\n       \"\"\")\n    tool = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class PackageInfo(ConanFile):\n            python_requires = \"dep/{}\"\n            def package_id(self):\n                self.output.info(\"VAR={{}}!!!\".format(self.python_requires[\"dep\"].module.some_var))\n        \"\"\")\n    pkg = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class MyConanfileBase(ConanFile):\n            python_requires = \"{}/0.1\"\n            def package_id(self):\n                self.output.info(\"VAR={{}}!!!\".format(self.python_requires[\"dep\"].module.some_var))\n        \"\"\")\n    client.save({\"dep/conanfile.py\": dep.format(42),\n                 \"toola/conanfile.py\": tool.format(\"0.1\"),\n                 \"toolb/conanfile.py\": tool.format(\"0.2\"),\n                 \"pkga/conanfile.py\": pkg.format(\"toola\"),\n                 \"pkgb/conanfile.py\": pkg.format(\"toolb\"),\n                 \"app/conanfile.py\": GenConanfile().with_requires(\"pkga/0.1\", \"pkgb/0.1\")})\n\n    client.run(\"export dep --name=dep --version=0.1\")\n    client.run(\"export dep --name=dep --version=0.2\")\n    client.run(\"export toola --name=toola --version=0.1\")\n    client.run(\"export toolb --name=toolb --version=0.1\")\n    client.run(\"create pkga --name=pkga --version=0.1\")\n    client.run(\"create pkgb --name=pkgb --version=0.1\")\n    client.run(\"lock create app/conanfile.py --lockfile-out=app.lock\")\n\n    client.save({\"dep/conanfile.py\": dep.format(123)})\n    client.run(\"export dep --name=dep --version=0.1\")\n    client.run(\"export dep --name=dep --version=0.2\")\n\n    client.run(\"install app/conanfile.py --lockfile=app.lock\")\n    assert \"pkga/0.1: VAR=42!!!\" in client.out\n    assert \"pkgb/0.1: VAR=42!!!\" in client.out\n    assert \"VAR=123\" not in client.out\n\n    client.run(\"install app/conanfile.py\")\n    assert \"pkga/0.1: VAR=123!!!\" in client.out\n    assert \"pkgb/0.1: VAR=123!!!\" in client.out\n    assert \"VAR=42\" not in client.out\n"
  },
  {
    "path": "test/integration/lockfile/test_lock_requires.py",
    "content": "import json\nimport os\nimport textwrap\nimport time\n\nimport pytest\n\nfrom conan.api.model import RecipeReference\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.parametrize(\"requires\", [\"requires\", \"tool_requires\"])\ndef test_conanfile_txt_deps_ranges(requires):\n    \"\"\"\n    conanfile.txt locking it dependencies (with version ranges)\n    \"\"\"\n    client = TestClient(light=True)\n    client.save({\"pkg/conanfile.py\": GenConanfile(),\n                 \"consumer/conanfile.txt\": f\"[{requires}]\\npkg/[>0.0]@user/testing\"})\n    client.run(\"create pkg --name=pkg --version=0.1 --user=user --channel=testing\")\n    client.run(\"lock create consumer/conanfile.txt\")\n    assert \"pkg/0.1@user/testing#\" in client.out\n\n    client.run(\"create pkg --name=pkg --version=0.2 --user=user --channel=testing\")\n\n    client.run(\"install consumer/conanfile.txt\")\n    assert \"pkg/0.1@user/testing#\" in client.out\n    assert \"pkg/0.2\" not in client.out\n\n    os.remove(os.path.join(client.current_folder, \"consumer/conan.lock\"))\n    client.run(\"install consumer/conanfile.txt\")\n    assert \"pkg/0.2@user/testing#\" in client.out\n    assert \"pkg/0.1\" not in client.out\n\n\n@pytest.mark.parametrize(\"command\", [\"install\", \"create\", \"graph info\", \"export-pkg\"])\ndef test_lockfile_out(command):\n    # Check that lockfile out is generated for different commands\n    c = TestClient(light=True)\n    c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\"),\n            \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_requires(\"dep/[*]\")})\n    c.run(\"create dep\")\n    c.run(f\"{command} pkg --lockfile-out=conan.lock\")\n    lock = c.load(\"conan.lock\")\n    assert \"dep/0.1\" in lock\n\n\ndef test_lockfile_out_export():\n    # Check that lockfile out is generated for \"conan export\"\n    c = TestClient(light=True)\n    c.save({\"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n    c.run(\"export pkg --lockfile-out=conan.lock\")\n    lock = c.load(\"conan.lock\")\n    assert \"pkg/0.1\" in lock\n\n\n@pytest.mark.parametrize(\"requires\", [\"requires\", \"tool_requires\"])\ndef test_conanfile_txt_deps_ranges_transitive(requires):\n    \"\"\"\n    conanfile.txt locking it dependencies and its transitive dependencies (with version ranges)\n    \"\"\"\n    client = TestClient(light=True)\n    client.save({\"dep/conanfile.py\": GenConanfile(),\n                 \"pkg/conanfile.py\": GenConanfile().with_requires(\"dep/[>0.0]@user/testing\"),\n                 \"consumer/conanfile.txt\": f\"[{requires}]\\npkg/[>0.0]@user/testing\"})\n    client.run(\"create dep --name=dep --version=0.1 --user=user --channel=testing\")\n    client.run(\"create pkg --name=pkg --version=0.1 --user=user --channel=testing\")\n\n    client.run(\"lock create consumer/conanfile.txt\")\n    assert \"dep/0.1@user/testing#\" in client.out\n    assert \"pkg/0.1@user/testing#\" in client.out\n\n    client.run(\"create dep --name=dep --version=0.2 --user=user --channel=testing\")\n\n    client.run(\"install consumer/conanfile.txt\")\n    assert \"dep/0.1@user/testing#\" in client.out\n    assert \"dep/0.2\" not in client.out\n\n    os.remove(os.path.join(client.current_folder, \"consumer/conan.lock\"))\n    client.run(\"install consumer/conanfile.txt\", assert_error=True)\n    assert \"dep/0.2@user/testing#\" in client.out\n    assert \"dep/0.1\" not in client.out\n\n\n@pytest.mark.parametrize(\"requires\", [\"requires\", \"tool_requires\"])\ndef test_conanfile_txt_strict(requires):\n    \"\"\"\n    conanfile.txt locking it dependencies (with version ranges)\n    \"\"\"\n    client = TestClient(light=True)\n    client.save({\"pkg/conanfile.py\": GenConanfile(),\n                 \"consumer/conanfile.txt\": f\"[{requires}]\\npkg/[>0.0]@user/testing\"})\n    client.run(\"create pkg --name=pkg --version=0.1 --user=user --channel=testing\")\n    client.run(\"lock create consumer/conanfile.txt\")\n    assert \"pkg/0.1@user/testing#\" in client.out\n\n    client.run(\"create pkg --name=pkg --version=0.2 --user=user --channel=testing\")\n    client.run(\"create pkg --name=pkg --version=1.2 --user=user --channel=testing\")\n\n    # Not strict mode works\n    client.save({\"consumer/conanfile.txt\": f\"[{requires}]\\npkg/[>1.0]@user/testing\"})\n\n    client.run(\"install consumer/conanfile.txt\", assert_error=True)\n    kind = \"build_requires\" if requires == \"tool_requires\" else \"requires\"\n    assert f\"Requirement 'pkg/[>1.0]@user/testing' not in lockfile '{kind}'\" in client.out\n\n    client.run(\"install consumer/conanfile.txt --lockfile-partial\")\n    assert \"pkg/1.2@user/testing\" in client.out\n    assert \"pkg/1.2\" not in client.load(\"consumer/conan.lock\")\n\n    # test it is possible to capture new changes too, when not strict, mutating the lockfile\n    client.run(\"install consumer/conanfile.txt --lockfile-partial --lockfile-out=conan.lock\")\n    assert \"pkg/1.2@user/testing\" in client.out\n    lock = client.load(\"conan.lock\")\n    assert \"pkg/1.2\" in lock\n    assert \"pkg/0.1\" in lock  # both versions are locked now\n    # clean legacy versions\n    client.run(\"lock create consumer/conanfile.txt --lockfile-out=conan.lock --lockfile-clean\")\n    lock = client.load(\"conan.lock\")\n    assert \"pkg/1.2\" in lock\n    assert \"pkg/0.1\" not in lock\n\n\n@pytest.mark.parametrize(\"requires\", [\"requires\", \"tool_requires\"])\ndef test_conditional_os(requires):\n    \"\"\"\n    conanfile.txt can lock conditional dependencies (conditional on OS for example),\n    with consecutive calls to \"conan lock create\", augmenting the lockfile\n    \"\"\"\n    client = TestClient(light=True)\n\n    pkg_conanfile = textwrap.dedent(f\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            settings = \"os\"\n            def requirements(self):\n                if self.settings.os == \"Windows\":\n                    self.requires(\"win/[>0.0]\")\n                else:\n                    self.requires(\"nix/[>0.0]\")\n        \"\"\")\n    client.save({\"dep/conanfile.py\": GenConanfile(),\n                 \"pkg/conanfile.py\": pkg_conanfile,\n                 \"consumer/conanfile.txt\": f\"[{requires}]\\npkg/0.1\"})\n    client.run(\"create dep --name=win --version=0.1\")\n    client.run(\"create dep --name=nix --version=0.1\")\n\n    client.run(\"create pkg --name=pkg --version=0.1 -s os=Windows\")\n    client.run(\"create pkg --name=pkg --version=0.1 -s os=Linux\")\n\n    client.run(\"lock create consumer/conanfile.txt  --lockfile-out=consumer.lock -s os=Windows\"\n               \" -s:b os=Windows\")\n    assert \"win/0.1#\" in client.out\n    assert \"pkg/0.1#\" in client.out\n    client.run(\"lock create consumer/conanfile.txt  --lockfile=consumer.lock \"\n               \"--lockfile-out=consumer.lock -s os=Linux -s:b os=Linux\")\n    assert \"nix/0.1#\" in client.out\n    assert \"pkg/0.1#\" in client.out\n\n    # New dependencies will not be used if using the lockfile\n    client.run(\"create dep --name=win --version=0.2\")\n    client.run(\"create dep --name=nix --version=0.2\")\n    client.run(\"create pkg --name=pkg --version=0.1 -s os=Windows\")\n    client.run(\"create pkg --name=pkg --version=0.1 -s os=Linux\")\n\n    client.run(\"install consumer --lockfile=consumer.lock -s os=Windows -s:b os=Windows\")\n    assert \"win/0.1#\" in client.out\n    assert \"win/0.2\" not in client.out\n    client.run(\"install consumer -s os=Windows -s:b os=Windows\")\n    assert \"win/0.2#\" in client.out\n    assert \"win/0.1\" not in client.out\n    assert \"nix/0.1\" not in client.out\n\n    client.run(\"install consumer --lockfile=consumer.lock -s os=Linux -s:b os=Linux\")\n    assert \"nix/0.1#\" in client.out\n    assert \"nix/0.2\" not in client.out\n    client.run(\"install consumer -s os=Linux -s:b os=Linux\")\n    assert \"nix/0.2#\" in client.out\n    assert \"nix/0.1\" not in client.out\n    assert \"win/\" not in client.out\n\n\n@pytest.mark.parametrize(\"requires\", [\"requires\", \"tool_requires\"])\ndef test_conditional_same_package(requires):\n    # What happens when a conditional requires different versions of the same package?\n    client = TestClient(light=True)\n\n    pkg_conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            settings = \"os\"\n            def requirements(self):\n                if self.settings.os == \"Windows\":\n                    self.requires(\"dep/0.1\")\n                else:\n                    self.requires(\"dep/0.2\")\n        \"\"\")\n    client.save({\"dep/conanfile.py\": GenConanfile(),\n                 \"pkg/conanfile.py\": pkg_conanfile,\n                 \"consumer/conanfile.txt\": f\"[{requires}]\\npkg/0.1\"})\n    client.run(\"create dep --name=dep --version=0.1\")\n    client.run(\"create dep --name=dep --version=0.2\")\n\n    client.run(\"create pkg --name=pkg --version=0.1 -s os=Windows\")\n    client.run(\"create pkg --name=pkg --version=0.1 -s os=Linux\")\n\n    client.run(\"lock create consumer/conanfile.txt  --lockfile-out=conan.lock -s os=Windows\"\n               \" -s:b os=Windows\")\n    assert \"dep/0.1#\" in client.out\n    assert \"dep/0.2\" not in client.out\n    client.run(\"lock create consumer/conanfile.txt  --lockfile=conan.lock \"\n               \"--lockfile-out=conan.lock -s os=Linux -s:b os=Linux\")\n    assert \"dep/0.2#\" in client.out\n    assert \"dep/0.1\" not in client.out\n\n    client.run(\"install consumer --lockfile=conan.lock --lockfile-out=win.lock -s os=Windows\"\n               \" -s:b os=Windows\")\n    assert \"dep/0.1#\" in client.out\n    assert \"dep/0.2\" not in client.out\n\n    client.run(\"install consumer --lockfile=conan.lock --lockfile-out=linux.lock -s os=Linux\"\n               \" -s:b os=Linux\")\n    assert \"dep/0.2#\" in client.out\n    assert \"dep/0.1\" not in client.out\n\n\n@pytest.mark.parametrize(\"requires\", [\"requires\", \"build_requires\"])\ndef test_conditional_incompatible_range(requires):\n    client = TestClient(light=True)\n\n    pkg_conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            settings = \"os\"\n            def requirements(self):\n                if self.settings.os == \"Windows\":\n                    self.requires(\"dep/[<1.0]\")\n                else:\n                    self.requires(\"dep/[>=1.0]\")\n        \"\"\")\n    client.save({\"dep/conanfile.py\": GenConanfile(),\n                 \"pkg/conanfile.py\": pkg_conanfile,\n                 \"consumer/conanfile.txt\": \"[requires]\\npkg/0.1\"})\n    client.run(\"create dep --name=dep --version=0.1\")\n    client.run(\"create dep --name=dep --version=1.1\")\n\n    client.run(\"create pkg --name=pkg --version=0.1 -s os=Windows\")\n    client.run(\"create pkg --name=pkg --version=0.1 -s os=Linux\")\n\n    client.run(\"lock create consumer/conanfile.txt  --lockfile-out=conan.lock -s os=Windows\"\n               \" -s:b os=Windows\")\n    assert \"dep/0.1#\" in client.out\n    assert \"dep/1.1\" not in client.out\n    # The previous lock was locking dep/0.1. This new lock will not use dep/0.1 as it is outside\n    # of its range, can't lock to it and will depend on dep/1.1. Both dep/0.1 for Windows and\n    # dep/1.1 for Linux now coexist in the lock\n    client.run(\"lock create consumer/conanfile.txt  --lockfile=conan.lock \"\n               \"--lockfile-out=conan.lock -s os=Linux -s:b os=Linux\")\n    assert \"dep/1.1#\" in client.out\n    assert \"dep/0.1\" not in client.out\n    lock = client.load(\"conan.lock\")\n    assert \"dep/0.1\" in lock\n    assert \"dep/1.1\" in lock\n\n    # These will not be used, lock will avoid them\n    client.run(\"create dep --name=dep --version=0.2\")\n    client.run(\"create dep --name=dep --version=1.2\")\n\n    client.run(\"install consumer --lockfile=conan.lock --lockfile-out=win.lock -s os=Windows\"\n               \" -s:b os=Windows\")\n    assert \"dep/0.1#\" in client.out\n    assert \"dep/1.1\" not in client.out\n\n    client.run(\"install consumer --lockfile=conan.lock --lockfile-out=linux.lock -s os=Linux\"\n               \" -s:b os=Linux\")\n    assert \"dep/1.1#\" in client.out\n    assert \"dep/0.1\" not in client.out\n\n\n@pytest.mark.parametrize(\"requires\", [\"requires\", \"tool_requires\"])\ndef test_conditional_compatible_range(requires):\n    client = TestClient(light=True)\n\n    pkg_conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            settings = \"os\"\n            def requirements(self):\n                if self.settings.os == \"Windows\":\n                    self.requires(\"dep/[<0.2]\")\n                else:\n                    self.requires(\"dep/[>0.0]\")\n        \"\"\")\n    client.save({\"dep/conanfile.py\": GenConanfile(),\n                 \"pkg/conanfile.py\": pkg_conanfile,\n                 \"consumer/conanfile.txt\": f\"[{requires}]\\npkg/0.1\"})\n    client.run(\"create dep --name=dep --version=0.1\")\n    client.run(\"create dep --name=dep --version=0.2\")\n\n    client.run(\"create pkg --name=pkg --version=0.1 -s os=Windows\")\n    client.run(\"create pkg --name=pkg --version=0.1 -s os=Linux\")\n\n    client.run(\"lock create consumer/conanfile.txt  --lockfile-out=conan.lock -s os=Linux\"\n               \" -s:b os=Linux\")\n    assert \"dep/0.2#\" in client.out\n    assert \"dep/0.1\" not in client.out\n    client.run(\"lock create consumer/conanfile.txt  --lockfile=conan.lock \"\n               \"--lockfile-out=conan.lock -s os=Windows -s:b os=Windows\")\n    assert \"dep/0.1#\" in client.out\n    assert \"dep/0.2\" not in client.out\n\n    # These will not be used, lock will avoid them\n    client.run(\"create dep --name=dep --version=0.1.1\")\n    client.run(\"create dep --name=dep --version=0.3\")\n\n    client.run(\"install consumer --lockfile=conan.lock --lockfile-out=win.lock -s os=Windows\"\n               \" -s:b os=Windows\")\n    assert \"dep/0.1#\" in client.out\n    assert \"dep/0.2\" not in client.out\n    assert \"dep/0.1.1\" not in client.out\n\n    client.run(\"install consumer --lockfile=conan.lock --lockfile-out=linux.lock -s os=Linux \"\n               \" -s:b os=Linux\")\n    assert \"dep/0.2#\" in client.out\n    assert \"dep/0.1\" not in client.out\n    assert \"dep/0.3\" not in client.out\n\n\ndef test_partial_lockfile():\n    \"\"\"\n    make sure that a partial lockfile can be applied anywhere downstream without issues,\n    as lockfiles by default are not strict\n    \"\"\"\n    c = TestClient(light=True)\n    c.save({\"pkga/conanfile.py\": GenConanfile(\"pkga\"),\n            \"pkgb/conanfile.py\": GenConanfile(\"pkgb\", \"0.1\").with_requires(\"pkga/[*]\"),\n            \"pkgc/conanfile.py\": GenConanfile(\"pkgc\", \"0.1\").with_requires(\"pkgb/[*]\"),\n            \"app/conanfile.py\": GenConanfile(\"app\", \"0.1\").with_requires(\"pkgc/[*]\")})\n    c.run(\"create pkga --version=0.1\")\n    c.run(\"lock create pkgb --lockfile-out=b.lock\")\n    c.run(\"create pkga --version=0.2\")\n    c.run(\"create pkgb --lockfile=b.lock\")\n    assert \"pkga/0.1\" in c.out\n    assert \"pkga/0.2\" not in c.out\n    c.run(\"install pkgc --lockfile=b.lock --lockfile-partial\")\n    assert \"pkga/0.1\" in c.out\n    assert \"pkga/0.2\" not in c.out\n    c.run(\"create pkgc  --lockfile=b.lock --lockfile-partial\")\n    assert \"pkga/0.1\" in c.out\n    assert \"pkga/0.2\" not in c.out\n    c.run(\"create app --lockfile=b.lock --lockfile-partial\")\n    assert \"pkga/0.1\" in c.out\n    assert \"pkga/0.2\" not in c.out\n    c.run(\"create app --lockfile=b.lock\", assert_error=True)\n    assert \"ERROR: Requirement 'pkgc/[*]' not in lockfile\" in c.out\n\n\ndef test_ux_defaults():\n    # Make sure the when explicit ``--lockfile`` argument, the file must exist, even if is conan.lock\n    c = TestClient(light=True)\n    c.save({\"conanfile.txt\": \"\"})\n    c.run(\"install . --lockfile=conan.lock\", assert_error=True)\n    assert \"ERROR: Lockfile doesn't exist\" in c.out\n\n\nclass TestLockTestPackage:\n\n    @pytest.fixture()\n    def client(self):\n        c = TestClient()\n        test_package = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class TestPackageConan(ConanFile):\n                settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n                def build_requirements(self):\n                    self.tool_requires(\"cmake/[*]\")\n                def requirements(self):\n                    self.requires(self.tested_reference_str)\n                def test(self):\n                    print(\"package tested\")\n            \"\"\")\n\n        c.save({\"cmake/conanfile.py\": GenConanfile(\"cmake\"),\n                \"dep/conanfile.py\": GenConanfile(\"dep\"),\n                \"app/conanfile.py\": GenConanfile(\"app\", \"1.0\").with_requires(\"dep/[*]\"),\n                \"app/test_package/conanfile.py\": test_package})\n\n        c.run(\"create cmake --version=1.0\")\n        c.run(\"create dep --version=1.0\")\n        return c\n\n    def test_lock_tool_requires_test(self, client):\n        # https://github.com/conan-io/conan/issues/11763\n        c = client\n        with c.chdir(\"app\"):\n            c.run(\"lock create\")\n            lock = c.load(\"conan.lock\")\n            assert \"cmake/1.0\" not in lock\n            assert \"dep/1.0\" in lock\n            c.run(\"lock create test_package --lockfile=conan.lock --lockfile-out=conan.lock\")\n            lock = c.load(\"conan.lock\")\n            assert \"cmake/1.0\" in lock\n            assert \"dep/1.0\" in lock\n\n        c.run(\"create cmake --version=2.0\")\n        c.run(\"create dep --version=2.0\")\n        with c.chdir(\"app\"):\n            c.run(\"create . --lockfile=conan.lock\")\n            assert \"cmake/1.0\" in c.out\n            assert \"dep/1.0\" in c.out\n            assert \"cmake/2.0\" not in c.out\n            assert \"dep/2.0\" not in c.out\n            assert \"package tested\" in c.out\n\n    def test_partial_approach(self, client):\n        \"\"\" do not include it in the lockfile, but apply it partially, so the tool_require is\n        free, will freely upgrade\n        \"\"\"\n        c = client\n        # https://github.com/conan-io/conan/issues/11763\n        with c.chdir(\"app\"):\n            c.run(\"lock create .\")\n            lock = c.load(\"conan.lock\")\n            assert \"cmake/1.0\" not in lock\n            assert \"dep/1.0\" in lock\n\n        c.run(\"create cmake --version=2.0\")\n        c.run(\"create dep --version=2.0\")\n        with c.chdir(\"app\"):\n            c.run(\"create . --lockfile=conan.lock --lockfile-partial\")\n            assert \"cmake/2.0\" in c.out  # because it is in test_package and not locked\n            assert \"dep/1.0\" in c.out\n            assert \"cmake/1.0\" not in c.out\n            assert \"dep/2.0\" not in c.out\n            assert \"package tested\" in c.out\n\n        # or to be more guaranteed\n        with c.chdir(\"app\"):\n            c.run(\"create . --lockfile=conan.lock -tf=\\\"\\\"\")\n            assert \"cmake\" not in c.out\n            assert \"dep/1.0\" in c.out\n            assert \"dep/2.0\" not in c.out\n            assert \"package tested\" not in c.out\n\n            c.run(\"test test_package app/1.0 --lockfile=conan.lock --lockfile-partial\")\n            assert \"cmake/1.0\" not in c.out\n            assert \"cmake/2.0\" in c.out\n            assert \"dep/1.0\" in c.out\n            assert \"dep/2.0\" not in c.out\n            assert \"package tested\" in c.out\n\n    def test_create_lock_tool_requires_test(self, client):\n        \"\"\" same as above, but the full lockfile including the \"test_package\" can be\n        obtained with a \"conan test\"\n        \"\"\"\n        c = client\n        with c.chdir(\"app\"):\n            c.run(\"create . --lockfile-out=conan.lock -tf=\")\n            lock = c.load(\"conan.lock\")\n            assert \"cmake/1.0\" not in lock\n            assert \"dep/1.0\" in lock\n            c.run(\"test test_package app/1.0 --lockfile-partial --lockfile=conan.lock \"\n                  \"--lockfile-out=conan.lock\")\n            lock = c.load(\"conan.lock\")\n            assert \"cmake/1.0\" in lock\n            assert \"dep/1.0\" in lock\n\n        c.run(\"create cmake --version=2.0\")\n        c.run(\"create dep --version=2.0\")\n        with c.chdir(\"app\"):\n            c.run(\"create . --lockfile=conan.lock\")\n            assert \"cmake/1.0\" in c.out\n            assert \"dep/1.0\" in c.out\n            assert \"cmake/2.0\" not in c.out\n            assert \"dep/2.0\" not in c.out\n            assert \"package tested\" in c.out\n\n    def test_test_package_lockfile(self):\n        c = TestClient(light=True)\n        test = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class TestBasicConanfile(ConanFile):\n                def requirements(self):\n                    self.requires(self.tested_reference_str)\n                    self.requires(\"pkga/1.0\")\n                def test(self):\n                    pass\n            \"\"\")\n        c.save({\"pkga/conanfile.py\": GenConanfile(\"pkga\", \"1.0\"),\n                \"pkgb/conanfile.py\": GenConanfile(\"pkgb\", \"1.0\"),\n                \"pkgb/test_package/conanfile.py\": test})\n        c.run(\"create pkga\")\n        c.run(\"lock create pkgb\")\n\n        # alternative 1, relax lockfile\n        c.run(\"create pkgb --lockfile-partial\")\n\n        # alternative 2, do not run test_package with same lockfile\n        c.run(\"create pkgb --test-folder=\")\n        # the test_package can be tested later, so the lockfile-partial only affects the test_package\n        c.run(\"test pkgb/test_package pkgb/1.0 --lockfile=pkgb/conan.lock --lockfile-partial\")\n        assert \"Using lockfile:\" in c.out\n\n        # alternative 3, create the lockfile in the test_package\n        c.run(\"lock create pkgb/test_package --lockfile=pkgb/conan.lock \"\n              \"--lockfile-out=pkgb/test_package/conan.lock\")\n        lockfile = c.load(\"pkgb/test_package/conan.lock\")\n        assert \"pkga/1.0\" in lockfile\n        c.run(\"test pkgb/test_package pkgb/1.0 --lockfile=pkgb/test_package/conan.lock \"\n              \"--lockfile-partial\")\n\n        # alternative 4, add the test_package dependencies to the main lockfile\n        c.run(\"lock create pkgb/test_package --lockfile=pkgb/conan.lock \"\n              \"--lockfile-out=pkgb/conan.lock\")\n        lockfile = c.load(\"pkgb/conan.lock\")\n        assert \"pkga/1.0\" in lockfile\n        c.run(\"create pkgb --lockfile=pkgb/conan.lock\")\n\n\nclass TestErrorDuplicates:\n    def test_error_duplicates(self):\n        \"\"\" the problem is having 2 different, almost identical requires that will point to the same\n        thing, with different traits and not colliding.\n        Lockfiles do a ``require.ref`` update and that alters some dictionaries iteration, producing\n        an infinite loop and blocking\n        \"\"\"\n        c = TestClient(light=True)\n        pkg = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                def requirements(self):\n                    self.requires(\"dep/0.1#f8c2264d0b32a4c33f251fe2944bb642\", headers=False, libs=False,\n                                visible=False)\n                    self.requires(\"dep/0.1\", headers=True, libs=False, visible=False)\n                \"\"\")\n        c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\"),\n                \"pkg/conanfile.py\": pkg})\n        c.run(\"create dep --lockfile-out=conan.lock\")\n        c.run(\"create pkg\", assert_error=True)\n        assert \"Duplicated requirement: dep/0.1\" in c.out\n        c.run(\"create pkg --lockfile=conan.lock\", assert_error=True)\n        assert \"Duplicated requirement: dep/0.1\" in c.out\n\n    def test_error_duplicates_reverse(self):\n        \"\"\" Same as above, but order requires changed\n        \"\"\"\n        c = TestClient(light=True)\n        pkg = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                def requirements(self):\n                    self.requires(\"dep/0.1\", headers=True, libs=False, visible=False)\n                    self.requires(\"dep/0.1#f8c2264d0b32a4c33f251fe2944bb642\", headers=False, libs=False,\n                                visible=False)\n                \"\"\")\n        c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\"),\n                \"pkg/conanfile.py\": pkg})\n        c.run(\"create dep --lockfile-out=conan.lock\")\n        c.run(\"create pkg\", assert_error=True)\n        assert \"Duplicated requirement: dep/0.1\" in c.out\n        c.run(\"create pkg --lockfile=conan.lock\", assert_error=True)\n        assert \"Duplicated requirement: dep/0.1\" in c.out\n\n    def test_error_duplicates_revisions(self):\n        \"\"\" 2 different revisions can be added without conflict, if they are not visible and not\n        other conflicting traits\n        \"\"\"\n        c = TestClient(light=True)\n        pkg = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                def requirements(self):\n                    self.requires(\"dep/0.1#f8c2264d0b32a4c33f251fe2944bb642\", headers=False,\n                                  libs=False, visible=False)\n                    self.requires(\"dep/0.1#7b91e6100797b8b012eb3cdc5544800b\", headers=True,\n                                  libs=False, visible=False)\n                \"\"\")\n        c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\"),\n                \"dep2/conanfile.py\": GenConanfile(\"dep\", \"0.1\").with_class_attribute(\"potato=42\"),\n                \"pkg/conanfile.py\": pkg})\n        c.run(\"create dep --lockfile-out=conan.lock\")\n        c.run(\"create dep2 --lockfile=conan.lock --lockfile-out=conan.lock\")\n\n        c.run(\"create pkg\")\n        assert \"dep/0.1#f8c2264d0b32a4c33f251fe2944bb642 - Cache\" in c.out\n        assert \"dep/0.1#7b91e6100797b8b012eb3cdc5544800b - Cache\" in c.out\n        c.run(\"create pkg --lockfile=conan.lock\")\n        assert \"dep/0.1#f8c2264d0b32a4c33f251fe2944bb642 - Cache\" in c.out\n        assert \"dep/0.1#7b91e6100797b8b012eb3cdc5544800b - Cache\" in c.out\n\n\ndef test_revision_timestamp():\n    \"\"\"\n    https://github.com/conan-io/conan/issues/14108\n    \"\"\"\n    c = TestClient(default_server_user=True)\n\n    c.save({\"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n    # revision 0\n    c.run(\"export pkg\")\n    c.save({\"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_class_attribute(\"_my=1\")})\n    # revision 1\n    c.run(\"export pkg\")\n    rrev = c.exported_recipe_revision()\n    c.run(\"upload *#* -r=default -c\")\n    c.save({\"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_class_attribute(\"_my=2\")})\n    # revision 2\n    time.sleep(1)\n    c.run(\"export pkg\")\n    latest_rrev = c.exported_recipe_revision()\n    c.run(\"upload * -r=default -c\")\n    c.run(\"remove * -c\")\n    c.run(\"list *#* -r=default --format=json\")\n    list_json = json.loads(c.stdout)\n    server_timestamp = list_json[\"default\"][\"pkg/0.1\"][\"revisions\"][latest_rrev][\"timestamp\"]\n\n    time.sleep(2)\n    ref = RecipeReference.loads(f\"pkg/0.1#{rrev}\")\n    # we force the lock to include the 2nd revision\n    c.save({\"conanfile.txt\": f\"[requires]\\n{repr(ref)}\"}, clean_first=True)\n\n    c.run(\"lock create .\")\n    lock = c.load(\"conan.lock\")\n    lock = json.loads(lock)\n    locked_ref = RecipeReference.loads(lock[\"requires\"][0])\n    assert locked_ref == ref\n    assert locked_ref.timestamp and locked_ref.timestamp != server_timestamp\n\n\nclass TestLockfileUpdate:\n    \"\"\"\n    Check that --update works\n    \"\"\"\n\n    @pytest.mark.parametrize(\"requires\", [\"requires\", \"tool_requires\"])\n    def test_conanfile_txt_deps_ranges(self, requires):\n        \"\"\"\n        conanfile.txt locking it dependencies (with version ranges)\n        \"\"\"\n        c = TestClient(default_server_user=True)\n        c.save({\"pkg/conanfile.py\": GenConanfile(\"pkg\"),\n                \"consumer/conanfile.txt\": f\"[{requires}]\\npkg/[>0.0]\"})\n        c.run(\"create pkg --version=0.1\")\n        c.run(\"create pkg --version=0.2\")\n        c.run(\"upload pkg/0.2 -r=default -c\")\n        c.run(\"remove pkg/0.2 -c\")\n        c.run(\"list *\")\n        assert \"pkg/0.2\" not in c.out\n        c.run(\"lock create consumer/conanfile.txt --update\")\n        assert \"pkg/0.1\" not in c.out\n        assert \"pkg/0.2\" in c.out\n        lock = c.load(\"consumer/conan.lock\")\n        assert \"pkg/0.1\" not in lock\n        assert \"pkg/0.2\" in lock\n\n\ndef test_error_test_explicit():\n    # https://github.com/conan-io/conan/issues/14833\n    client = TestClient(light=True)\n    test = GenConanfile().with_test(\"pass\")\n    client.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\"),\n                 \"test_package/conanfile.py\": test})\n    client.run(\"lock create conanfile.py --lockfile-out=my.lock\")\n    client.run(\"create . --lockfile=my.lock\")\n\n\ndef test_lock_error_create():\n    # https://github.com/conan-io/conan/issues/15801\n    c = TestClient(light=True)\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_package_type(\"build-scripts\")})\n    c.run(\"lock create . -u --lockfile-out=none.lock\")\n    lock = json.loads(c.load(\"none.lock\"))\n    assert lock[\"requires\"] == []\n    assert lock[\"build_requires\"] == []\n    c.run(\"create . --lockfile=none.lock --lockfile-out=none_updated.lock\")\n    # It doesn't crash, it used to\n    lock = json.loads(c.load(\"none_updated.lock\"))\n    assert lock[\"requires\"] == []\n    assert len(lock[\"build_requires\"]) == 1\n    assert \"pkg/0.1#4e9dba5c3041ba4c87724486afdb7eb4\" in lock[\"build_requires\"][0]\n\n\ndef test_lock_error():\n    # https://github.com/conan-io/conan/issues/17363\n    c = TestClient()\n    transitive_dep = textwrap.dedent(\"\"\"\n        # recipes/transitive_dep/conanfile.py\n        from conan import ConanFile\n\n        class TransitiveDepConan(ConanFile):\n            name = \"transitive_dep\"\n            version = \"2.0.0\"\n            settings = \"build_type\"\n            \"\"\")\n    build_tool = textwrap.dedent(\"\"\"\n        # recipes/build_tool/conanfile.py\n        from conan import ConanFile\n\n        class BuildToolConan(ConanFile):\n            name = \"build_tool\"\n            version = \"1.0.0\"\n            settings = \"build_type\"\n\n            def requirements(self):\n                self.requires(\"transitive_dep/2.0.0\")\n        \"\"\")\n    build_tool_test = textwrap.dedent(\"\"\"\n        # recipes/build_tool/test_package/conanfile.py\n        from conan import ConanFile\n\n        class TestPackageConan(ConanFile):\n            settings = \"build_type\"\n\n            def requirements(self):\n                self.requires(self.tested_reference_str)\n\n            def test(self):\n                pass\n        \"\"\")\n    runtime_dep = textwrap.dedent(\"\"\"\n        # recipes/runtime_dep/conanfile.py\n        from conan import ConanFile\n\n        class RuntimeDepConan(ConanFile):\n            name = \"runtime_dep\"\n            version = \"1.2.3\"\n            settings = \"build_type\"\n\n            def build_requirements(self):\n                self.tool_requires(\"build_tool/1.0.0\")\n        \"\"\")\n    consumer = textwrap.dedent(\"\"\"\n        # recipes/consumer/conanfile.py\n        from conan import ConanFile\n\n        class ConsumerConan(ConanFile):\n            name = \"consumer\"\n            version = \"0.0.1\"\n            settings = \"build_type\"\n\n            def requirements(self):\n                self.requires(\"runtime_dep/1.2.3\")\n        \"\"\")\n    c.save({\"recipes/transitive_dep/conanfile.py\": transitive_dep,\n            \"recipes/build_tool/conanfile.py\": build_tool,\n            \"recipes/build_tool/test_package/conanfile.py\": build_tool_test,\n            \"recipes/runtime_dep/conanfile.py\": runtime_dep,\n            \"recipes/consumer/conanfile.py\": consumer,\n            })\n    c.run(\"export recipes/transitive_dep\")\n    c.run(\"export recipes/build_tool\")\n    c.run(\"export recipes/runtime_dep\")\n\n    settings = \"-s:b build_type=Release -s:h build_type=Debug\"\n    c.run(f\"lock create recipes/consumer --no-remote {settings}\")\n\n    c.run(f\"graph build-order recipes/consumer {settings} --build=missing --order-by=configuration \"\n          \"--reduce  --format=json\", redirect_stdout=\"build_order.json\")\n    assert \"Using lockfile:\" in c.out\n\n    ref = \"transitive_dep/2.0.0\"\n    c.run(f\"install --tool-requires={ref} {settings} --build={ref} \"\n          \"--lockfile=recipes/consumer/conan.lock \")\n    # The test of ``trantisive_dep`` doesn't have the test_package\n\n    ref = \"build_tool/1.0.0\"\n    c.run(f\"install --tool-requires={ref} {settings} --build={ref} \"\n          \"--lockfile=recipes/consumer/conan.lock \")\n\n    ref = \"runtime_dep/1.2.3\"\n    c.run(f\"install --requires={ref} {settings} --build={ref} \"\n          \"--lockfile=recipes/consumer/conan.lock \")\n\n"
  },
  {
    "path": "test/integration/lockfile/test_lock_requires_revisions.py",
    "content": "import textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.parametrize(\"requires\", [\"requires\", \"tool_requires\"])\ndef test_conanfile_txt_deps_revisions(requires):\n    \"\"\"\n    conanfile.txt locking it dependencies (with revisions)\n    \"\"\"\n    client = TestClient(light=True)\n    client.save({\"pkg/conanfile.py\": GenConanfile().with_package_id(\"self.output.info('REV1!!!!')\"),\n                 \"consumer/conanfile.txt\": f\"[{requires}]\\npkg/0.1@user/testing\"})\n    client.run(\"create pkg --name=pkg --version=0.1 --user=user --channel=testing\")\n    assert \"REV1!!!\" in client.out\n    client.run(\"lock create consumer/conanfile.txt  --lockfile-out=consumer.lock\")\n    assert \"pkg/0.1@user/testing#\" in client.out\n\n    client.save({\"pkg/conanfile.py\": GenConanfile().with_package_id(\"self.output.info('REV2!!!!')\")})\n    client.run(\"create pkg --name=pkg --version=0.1 --user=user --channel=testing\")\n    assert \"REV2!!!\" in client.out\n\n    client.run(\"install consumer/conanfile.txt --lockfile=consumer.lock\")\n    assert \"REV1!!!\" in client.out\n    assert \"REV2!!!\" not in client.out\n    client.run(\"install consumer/conanfile.txt\")\n    assert \"REV2!!!\" in client.out\n    assert \"REV1!!!\" not in client.out\n\n\n@pytest.mark.parametrize(\"requires\", [\"requires\", \"tool_requires\"])\n@pytest.mark.parametrize(\"req_version\", [\"0.1\", \"[>=0.0]\"])\ndef test_conanfile_txt_deps_revisions_transitive(requires, req_version):\n    \"\"\"\n    conanfile.txt locking it dependencies and its transitive dependencies (with revisions)\n    \"\"\"\n    client = TestClient(light=True)\n    client.save({\"dep/conanfile.py\": GenConanfile().with_package_id(\"self.output.info('REV1!!!!')\"),\n                 \"pkg/conanfile.py\": GenConanfile().with_requires(f\"dep/{req_version}@user/testing\"),\n                 \"consumer/conanfile.txt\": f\"[{requires}]\\npkg/{req_version}@user/testing\"})\n    client.run(\"create dep --name=dep --version=0.1 --user=user --channel=testing\")\n    assert \"REV1!!!\" in client.out\n    client.run(\"create pkg --name=pkg --version=0.1 --user=user --channel=testing\")\n\n    client.run(\"lock create consumer/conanfile.txt  --lockfile-out=consumer.lock\")\n    assert \"dep/0.1@user/testing#\" in client.out\n    assert \"pkg/0.1@user/testing#\" in client.out\n\n    client.save({\"dep/conanfile.py\": GenConanfile().with_package_id(\"self.output.info('REV2!!!!')\")})\n    client.run(\"create dep --name=dep --version=0.1 --user=user --channel=testing\")\n    assert \"REV2!!!\" in client.out\n\n    client.run(\"install consumer/conanfile.txt --lockfile=consumer.lock\")\n    assert \"REV1!!!\" in client.out\n    assert \"REV2!!!\" not in client.out\n    client.run(\"list dep/0.1@user/testing#*\")\n    client.run(\"install consumer/conanfile.txt\")\n    assert \"REV2!!!\" in client.out\n    assert \"REV1!!!\" not in client.out\n\n\n@pytest.mark.parametrize(\"requires\", [\"requires\", \"tool_requires\"])\ndef test_conanfile_txt_strict_revisions(requires):\n    \"\"\"\n    conanfile.txt locking it dependencies (with version ranges)\n    \"\"\"\n    client = TestClient(light=True)\n    client.save({\"pkg/conanfile.py\": GenConanfile().with_package_id(\"self.output.info('REV1!!!!')\"),\n                 \"consumer/conanfile.txt\": f\"[{requires}]\\npkg/0.1@user/testing\"})\n    client.run(\"create pkg --name=pkg --version=0.1 --user=user --channel=testing\")\n    client.run(\"lock create consumer/conanfile.txt\")\n    assert \"pkg/0.1@user/testing#\" in client.out\n\n    client.save({\"pkg/conanfile.py\": GenConanfile().with_package_id(\"self.output.info('REV2!!!!')\")})\n    client.run(\"create pkg --name=pkg --version=0.1 --user=user --channel=testing\")\n    rrev = client.exported_recipe_revision()\n\n    # Not strict mode works\n    client.save({\"consumer/conanfile.txt\": f\"[{requires}]\\npkg/0.1@user/testing#{rrev}\"})\n\n    client.run(\"install consumer/conanfile.txt\", assert_error=True)\n    assert f\"Requirement 'pkg/0.1@user/testing#{rrev}' not in lockfile\" in client.out\n\n\n@pytest.mark.parametrize(\"requires\", [\"requires\", \"tool_requires\"])\ndef test_conditional_os(requires):\n    \"\"\"\n    conanfile.txt can lock conditional dependencies (conditional on OS for example),\n    with consecutive calls to \"conan lock create\", augmenting the lockfile\n    \"\"\"\n    client = TestClient(light=True)\n\n    pkg_conanfile = textwrap.dedent(f\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            settings = \"os\"\n            def requirements(self):\n                if self.settings.os == \"Windows\":\n                    self.requires(\"win/0.1\")\n                else:\n                    self.requires(\"nix/0.1\")\n        \"\"\")\n\n    client.save({\"dep/conanfile.py\": GenConanfile().with_package_id(\"self.output.info('REV1!!!!')\"),\n                 \"pkg/conanfile.py\": pkg_conanfile,\n                 \"consumer/conanfile.txt\": f\"[{requires}]\\npkg/0.1\"})\n    client.run(\"create dep --name=win --version=0.1\")\n    client.run(\"create dep --name=nix --version=0.1\")\n\n    client.run(\"create pkg --name=pkg --version=0.1 -s os=Windows\")\n    client.run(\"create pkg --name=pkg --version=0.1 -s os=Linux\")\n\n    client.run(\"lock create consumer/conanfile.txt  --lockfile-out=consumer.lock -s os=Windows\"\n               \" -s:b os=Windows\")\n    assert \"win/0.1#\" in client.out\n    assert \"pkg/0.1#\" in client.out\n    client.run(\"lock create consumer/conanfile.txt  --lockfile=consumer.lock \"\n               \"--lockfile-out=consumer.lock -s os=Linux -s:b os=Linux\")\n    assert \"nix/0.1#\" in client.out\n    assert \"pkg/0.1#\" in client.out\n\n    # New dependencies will not be used if using the lockfile\n    client.save({\"dep/conanfile.py\": GenConanfile().with_package_id(\"self.output.info('REV2!!!!')\")})\n    client.run(\"create dep --name=win --version=0.1\")\n    client.run(\"create dep --name=nix --version=0.1\")\n    client.run(\"create pkg --name=pkg --version=0.1 -s os=Windows\")\n    client.run(\"create pkg --name=pkg --version=0.1 -s os=Linux\")\n\n    client.run(\"install consumer --lockfile=consumer.lock -s os=Windows -s:b os=Windows\")\n    assert \"REV1!!!\" in client.out\n    assert \"REV2!!!\" not in client.out\n    assert \"nix/0.1\" not in client.out\n    client.run(\"install consumer -s os=Windows -s:b os=Windows\")\n    assert \"REV2!!!\" in client.out\n    assert \"REV1!!!\" not in client.out\n    assert \"nix/0.1\" not in client.out\n\n    client.run(\"install consumer --lockfile=consumer.lock -s os=Linux -s:b os=Linux\")\n    assert \"REV1!!!\" in client.out\n    assert \"REV2!!!\" not in client.out\n    assert \"win/0.1\" not in client.out\n    client.run(\"install consumer -s os=Linux -s:b os=Linux\")\n    assert \"REV2!!!\" in client.out\n    assert \"REV1!!!\" not in client.out\n    assert \"win/0.1\" not in client.out\n\n\n@pytest.mark.parametrize(\"requires\", [\"requires\", \"tool_requires\"])\ndef test_conditional_same_package_revisions(requires):\n    # What happens when a conditional requires different versions of the same package?\n    client = TestClient(light=True)\n\n    pkg_conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            settings = \"os\"\n            def requirements(self):\n                if self.settings.os == \"Windows\":\n                    self.requires(\"dep/0.1#{}\")\n                else:\n                    self.requires(\"dep/0.1#{}\")\n        \"\"\")\n    client.save({\"dep1/conanfile.py\": GenConanfile().with_package_id(\"self.output.info('REV1!!!!')\"),\n                 \"dep2/conanfile.py\": GenConanfile().with_package_id(\"self.output.info('REV2!!!!')\"),\n                 \"pkg/conanfile.py\": pkg_conanfile,\n                 \"consumer/conanfile.txt\": f\"[{requires}]\\npkg/0.1\"})\n    client.run(\"create dep1 --name=dep --version=0.1\")\n    rrev1 = client.exported_recipe_revision()\n    client.run(\"create dep2 --name=dep --version=0.1\")\n    rrev2 = client.exported_recipe_revision()\n    client.save({\"pkg/conanfile.py\": pkg_conanfile.format(rrev1, rrev2)})\n\n    client.run(\"create pkg --name=pkg --version=0.1 -s os=Windows\")\n    client.run(\"create pkg --name=pkg --version=0.1 -s os=Linux\")\n\n    client.run(\"lock create consumer/conanfile.txt  --lockfile-out=conan.lock -s os=Windows\"\n               \" -s:b os=Windows\")\n    assert \"REV1!!!\" in client.out\n    assert \"REV2!!!\" not in client.out\n    client.run(\"lock create consumer/conanfile.txt  --lockfile=conan.lock \"\n               \"--lockfile-out=conan.lock -s os=Linux -s:b os=Linux\")\n    assert \"REV2!!!\" in client.out\n    assert \"REV1!!!\" not in client.out\n\n    client.run(\"install consumer --lockfile=conan.lock --lockfile-out=win.lock -s os=Windows\"\n               \" -s:b os=Windows\")\n    assert \"REV1!!!\" in client.out\n    assert \"REV2!!!\" not in client.out\n\n    client.run(\"install consumer --lockfile=conan.lock --lockfile-out=linux.lock -s os=Linux\"\n               \" -s:b os=Linux\")\n    assert \"REV2!!!\" in client.out\n    assert \"REV1!!!\" not in client.out\n"
  },
  {
    "path": "test/integration/lockfile/test_options.py",
    "content": "import json\nimport textwrap\n\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_options():\n    \"\"\" lockfiles no longer contains option or any other configuration information. Instead\n    the ``graph build-order`` applying a lockfile will return the necessary options to build\n    it in order\n    \"\"\"\n    client = TestClient(light=True)\n    ffmpeg = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class FfmpegConan(ConanFile):\n            options = {\"variation\": [\"standard\", \"nano\"]}\n            default_options = {\"variation\": \"standard\"}\n\n            def build(self):\n                self.output.info(\"Variation %s!!\" % self.options.variation)\n        \"\"\")\n\n    variant = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Meta(ConanFile):\n            requires = \"ffmpeg/1.0\"\n            default_options = {\"ffmpeg/1.0:variation\": \"nano\"}\n        \"\"\")\n\n    client.save({\"ffmepg/conanfile.py\": ffmpeg,\n                 \"variant/conanfile.py\": variant})\n    client.run(\"export ffmepg --name=ffmpeg --version=1.0\")\n    client.run(\"export variant --name=nano --version=1.0\")\n    client.run(\"lock create --requires=nano/1.0@ --build=*\")\n    client.run(\"graph build-order --requires=nano/1.0@ \"\n               \"--lockfile-out=conan.lock --build=missing \"\n               \"--format=json\", redirect_stdout=\"build_order.json\")\n\n    json_file = client.load(\"build_order.json\")\n    to_build = json.loads(json_file)\n    ffmpeg = to_build[0][0]\n    ref = ffmpeg[\"ref\"]\n    options = \" \".join(f\"-o {option}\" for option in ffmpeg[\"packages\"][0][0][\"options\"])\n\n    cmd = \"install --requires={} --build={} {}\".format(ref, ref, options)\n    client.run(cmd)\n    assert \"ffmpeg/1.0: Variation nano!!\" in client.out\n"
  },
  {
    "path": "test/integration/lockfile/test_user_overrides.py",
    "content": "import json\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_user_overrides():\n    \"\"\" Show that it is possible to add things to lockfiles, to pre-lock things explicitly from\n    user side\n    \"\"\"\n    c = TestClient(light=True)\n    c.save({\"math/conanfile.py\": GenConanfile(\"math\"),\n            \"engine/conanfile.py\": GenConanfile(\"engine\", \"1.0\").with_requires(\"math/[*]\"),\n            \"game/conanfile.py\": GenConanfile(\"game\", \"1.0\").with_requires(\"engine/[*]\")})\n\n    c.run(\"export math --version=1.0\")\n    c.run(\"export math --version=1.1\")\n    c.run(\"export math --version=1.2\")\n    c.run(\"export engine\")\n\n    c.run(\"graph info game\")\n    assert \"math/1.2\" in c.out\n    assert \"math/1.0\" not in c.out\n\n    c.run(\"lock add --requires=math/1.0 --requires=unrelated/2.0\")\n    c.run(\"graph info game --lockfile=conan.lock --lockfile-out=new.lock --lockfile-partial\")\n    assert \"math/1.0\" in c.out\n    assert \"math/1.2\" not in c.out\n    # The resulting lockfile contains the full revision now\n    new_lock = c.load(\"new.lock\")\n    assert \"math/1.0#8e1a7a5ce869d8c54ae3d33468fd657\" in new_lock\n\n    # Repeat for 1.1\n    c.run(\"lock add --requires=math/1.1 --requires=unrelated/2.0\")\n    c.run(\"graph info game --lockfile=conan.lock --lockfile-partial --lockfile-out=new.lock\")\n    assert \"math/1.1\" in c.out\n    assert \"math/1.0\" not in c.out\n    # The resulting lockfile contains the full revision now\n    new_lock = c.load(\"new.lock\")\n    assert \"math/1.1#8e1a7a5ce869d8c54ae3d33468fd657\" in new_lock\n\n\ndef test_user_build_overrides():\n    \"\"\" Test that it is possible to lock also build-requries\n    \"\"\"\n    c = TestClient(light=True)\n    c.save({\"cmake/conanfile.py\": GenConanfile(\"cmake\"),\n            \"engine/conanfile.py\": GenConanfile(\"engine\", \"1.0\").with_build_requires(\"cmake/[*]\")})\n\n    c.run(\"export cmake --version=1.0\")\n    c.run(\"export cmake --version=1.1\")\n    c.run(\"export cmake --version=1.2\")\n\n    c.run(\"graph info engine\")\n    assert \"cmake/1.2\" in c.out\n    assert \"cmake/1.0\" not in c.out\n\n    c.run(\"lock add --build-requires=cmake/1.0\")\n    c.run(\"graph info engine --lockfile=conan.lock --lockfile-out=new.lock --lockfile-partial\")\n    assert \"cmake/1.0\" in c.out\n    assert \"cmake/1.2\" not in c.out\n    # The resulting lockfile contains the full revision now\n    new_lock = c.load(\"new.lock\")\n    assert \"cmake/1.0\" in new_lock\n\n    # Repeat for 1.1\n    c.run(\"lock add --build-requires=cmake/1.1 --lockfile-out=conan.lock\")\n    c.run(\"graph info engine --lockfile=conan.lock --lockfile-out=new.lock --lockfile-partial\")\n    assert \"cmake/1.1\" in c.out\n    assert \"cmake/1.0\" not in c.out\n    # The resulting lockfile contains the full revision now\n    new_lock = c.load(\"new.lock\")\n    assert \"cmake/1.1\" in new_lock\n\n\ndef test_user_python_overrides():\n    \"\"\" Test that it is possible to lock also python-requries\n    \"\"\"\n    c = TestClient(light=True)\n    c.save({\"pytool/conanfile.py\": GenConanfile(\"pytool\"),\n            \"engine/conanfile.py\": GenConanfile(\"engine\", \"1.0\").with_python_requires(\"pytool/[*]\")})\n\n    c.run(\"export pytool --version=1.0\")\n    c.run(\"export pytool --version=1.1\")\n    c.run(\"export pytool --version=1.2\")\n\n    c.run(\"graph info engine\")\n    assert \"pytool/1.2\" in c.out\n    assert \"pytool/1.0\" not in c.out\n\n    c.run(\"lock add --python-requires=pytool/1.0 --lockfile-out=conan.lock\")\n    c.run(\"graph info engine --lockfile=conan.lock --lockfile-out=new.lock\")\n    assert \"pytool/1.0\" in c.out\n    assert \"pytool/1.2\" not in c.out\n    # The resulting lockfile contains the full revision now\n    new_lock = c.load(\"new.lock\")\n    assert \"pytool/1.0\" in new_lock\n\n    # Repeat for 1.1\n    c.run(\"lock add --python-requires=pytool/1.1 --lockfile-out=conan.lock\")\n    c.run(\"graph info engine --lockfile=conan.lock --lockfile-out=new.lock\")\n    assert \"pytool/1.1\" in c.out\n    assert \"pytool/1.0\" not in c.out\n    # The resulting lockfile contains the full revision now\n    new_lock = c.load(\"new.lock\")\n    assert \"pytool/1.1\" in new_lock\n\n\ndef test_config_overrides():\n    \"\"\" Test that it is possible to lock also config-requires\n    \"\"\"\n    c = TestClient(light=True)\n    c.run(\"lock add --config-requires=config/1.0\")\n    assert json.loads(c.load(\"conan.lock\"))[\"config_requires\"] == [\"config/1.0\"]\n    c.run(\"lock remove --config-requires=config/1.0\")\n    assert json.loads(c.load(\"conan.lock\"))[\"config_requires\"] == []\n\n\ndef test_add_revisions():\n    \"\"\" Is it possible to add revisions explicitly too\n    \"\"\"\n    c = TestClient(light=True)\n    c.save({\"math/conanfile.py\": GenConanfile(\"math\"),\n            \"engine/conanfile.py\": GenConanfile(\"engine\", \"1.0\").with_requires(\"math/[*]\"),\n            \"game/conanfile.py\": GenConanfile(\"game\", \"1.0\").with_requires(\"engine/[*]\")})\n\n    c.run(\"export math --version=1.0\")\n    rev0 = c.exported_recipe_revision()\n    c.save({\"math/conanfile.py\": GenConanfile(\"math\").with_build_msg(\"New rev1\")})\n    c.run(\"export math --version=1.0\")\n    rev1 = c.exported_recipe_revision()\n    c.save({\"math/conanfile.py\": GenConanfile(\"math\").with_build_msg(\"New rev2\")})\n    c.run(\"export math --version=1.0\")\n    rev2 = c.exported_recipe_revision()\n\n    c.run(\"export engine\")\n    c.run(\"graph info game\")\n    assert f\"math/1.0#{rev2}\" in c.out\n    assert f\"math/1.0#{rev1}\" not in c.out\n\n    # without revision, it will resolve to latest\n    c.run(\"lock add --requires=math/1.0 --requires=unrelated/2.0\")\n    c.run(\"graph info game --lockfile=conan.lock --lockfile-out=new.lock --lockfile-partial\")\n    assert f\"math/1.0#{rev2}\" in c.out\n    assert f\"math/1.0#{rev1}\" not in c.out\n    assert f\"math/1.0#{rev0}\" not in c.out\n    # The resulting lockfile contains the full revision now\n    new_lock = c.load(\"new.lock\")\n    assert f\"math/1.0#{rev2}\" in new_lock\n    assert f\"math/1.0#{rev1}\" not in new_lock\n    assert f\"math/1.0#{rev0}\" not in c.out\n\n    # with revision, it will resolve to that revision\n    c.run(f\"lock add --requires=math/1.0#{rev1} --requires=unrelated/2.0\")\n    c.run(\"graph info game --lockfile=conan.lock --lockfile-out=new.lock --lockfile-partial\")\n    assert f\"math/1.0#{rev1}\" in c.out\n    assert f\"math/1.0#{rev2}\" not in c.out\n    assert f\"math/1.0#{rev0}\" not in c.out\n    # The resulting lockfile contains the full revision now\n    new_lock = c.load(\"new.lock\")\n    assert f\"math/1.0#{rev1}\" in new_lock\n    assert f\"math/1.0#{rev2}\" not in new_lock\n    assert f\"math/1.0#{rev0}\" not in c.out\n\n\ndef test_add_multiple_revisions():\n    \"\"\" What if we add multiple revisions, mix with and without revisions, with and without\n    timestamps and it will not crash\n    \"\"\"\n    c = TestClient(light=True)\n    # without revision, it will resolve to latest\n    c.run(\"lock add --requires=math/1.0#rev1\")\n    new_lock = c.load(\"conan.lock\")\n    assert \"math/1.0#rev1\" in new_lock\n\n    c.run(\"lock add --requires=math/1.0#rev2\")\n    new_lock = json.loads(c.load(\"conan.lock\"))\n    assert [\"math/1.0#rev2\", \"math/1.0#rev1\"] == new_lock[\"requires\"]\n    c.run(\"lock add --requires=math/1.0#rev0\")\n    new_lock = json.loads(c.load(\"conan.lock\"))\n    assert ['math/1.0#rev2', 'math/1.0#rev1', 'math/1.0#rev0'] == new_lock[\"requires\"]\n    c.run(\"lock add --requires=math/1.0#revx%0.0\")\n    new_lock = json.loads(c.load(\"conan.lock\"))\n    assert ['math/1.0#revx%0.0', 'math/1.0#rev2', 'math/1.0#rev1', 'math/1.0#rev0'] == \\\n           new_lock[\"requires\"]\n\n    c.save({\"conanfile.txt\": \"\"})\n    c.run(\"install . --lockfile=conan.lock\")  # Just check that it doesn't crash\n    c.run(\"install . --lockfile=conan.lock --lockfile-out=new.lock\")\n    new_lock = json.loads(c.load(\"conan.lock\"))\n    assert ['math/1.0#revx%0.0', 'math/1.0#rev2', 'math/1.0#rev1', 'math/1.0#rev0'] == \\\n           new_lock[\"requires\"]\n\n    # add without revision at all, will give us an error, as it doesn't make sense\n    c.run(\"lock add --requires=math/1.0\", assert_error=True)\n    assert \"Cannot add math/1.0 to lockfile, already exists\" in c.out\n    new_lock = json.loads(c.load(\"conan.lock\"))\n    assert ['math/1.0#revx%0.0', 'math/1.0#rev2', 'math/1.0#rev1', 'math/1.0#rev0'] == \\\n           new_lock[\"requires\"]\n\n\ndef test_timestamps_are_updated():\n    \"\"\" When ``conan lock add`` adds a revision with a timestamp, or without it, it will be\n    updated in the lockfile-out to the resolved new timestamp\n    \"\"\"\n    c = TestClient(light=True)\n    c.save({\"conanfile.txt\": \"[requires]\\nmath/1.0\",\n            \"math/conanfile.py\": GenConanfile(\"math\", \"1.0\")})\n    c.run(\"create math\")\n    rev = c.exported_recipe_revision()\n    # Create a new lockfile, wipe the previous\n    c.run(f\"lock add --lockfile=\\\"\\\" --requires=math/1.0#{rev}%0.123\")\n    c.run(\"install . --lockfile=conan.lock --lockfile-out=conan.lock\")\n    assert f\" math/1.0#{rev} - Cache\" in c.out\n    new_lock = c.load(\"conan.lock\")\n    assert \"%0.123\" not in new_lock\n\n\ndef test_lock_add_error():\n    # https://github.com/conan-io/conan/issues/14465\n    c = TestClient(light=True)\n    c.run(f\"lock add --requires=math/1.0:pid1\", assert_error=True)\n    assert \"ERROR: Invalid recipe reference 'math/1.0:pid1' is a package reference\" in c.out\n\n\nclass TestLockRemove:\n    @pytest.mark.parametrize(\"args, removed\", [\n        (\"--requires=math/*\", [\"math\"]),\n        (\"--requires=math/2.0\", []),\n        (\"--build-requires=cmake/1.0\", [\"cmake\"]),\n        # Not valid (\"--build-requires=*\", [\"cmake\", \"ninja\"]),\n        (\"--build-requires=*/*\", [\"cmake\", \"ninja\"]),  # But this is valid\n        (\"--python-requires=mytool/*\", [\"mytool\"]),\n        (\"--python-requires=*tool/*\", [\"mytool\", \"othertool\"]),\n        # With version ranges\n        ('--requires=\"math/[>=1.0 <2]\"', [\"math\"]),\n        ('--requires=\"math/[>1.0]\"', []),\n        ('--requires=\"*/[>=1.0 <2]\"', [\"math\", \"engine\"])\n    ])\n    def test_lock_remove(self, args, removed):\n        c = TestClient(light=True)\n        lock = textwrap.dedent(\"\"\"\\\n            {\n                \"version\": \"0.5\",\n                \"requires\": [\n                    \"math/1.0#85d927a4a067a531b1a9c7619522c015%1702683583.3411012\",\n                    \"math/1.0#12345%1702683584.3411012\",\n                    \"engine/1.0#fd2b006646a54397c16a1478ac4111ac%1702683583.3544693\"\n                ],\n                \"build_requires\": [\n                    \"cmake/1.0#85d927a4a067a531b1a9c7619522c015%1702683583.3411012\",\n                    \"ninja/1.0#fd2b006646a54397c16a1478ac4111ac%1702683583.3544693\"\n                ],\n                \"python_requires\": [\n                    \"mytool/1.0#85d927a4a067a531b1a9c7619522c015%1702683583.3411012\",\n                    \"othertool/1.0#fd2b006646a54397c16a1478ac4111ac%1702683583.3544693\"\n                ]\n            }\n            \"\"\")\n        c.save({\"conan.lock\": lock})\n        c.run(f\"lock remove {args}\")\n        lock = c.load(\"conan.lock\")\n        for remove in removed:\n            assert remove not in lock\n        for pkg in {\"math\", \"engine\", \"cmake\", \"ninja\", \"mytool\", \"othertool\"}.difference(removed):\n            assert pkg in lock\n\n    @pytest.mark.parametrize(\"args, removed\", [\n        (\"--requires=math/1.0#12345*\", [\"math/1.0#123456789abcdef\"]),\n        (\"--requires=math/1.0#*\", [\"math/1.0#123456789abcdef\",\n                                   \"math/1.0#85d927a4a067a531b1a9c7619522c015\"]),\n    ])\n    def test_lock_remove_revisions(self, args, removed):\n        c = TestClient(light=True)\n        lock = textwrap.dedent(\"\"\"\\\n            {\n                \"version\": \"0.5\",\n                \"requires\": [\n                    \"math/1.0#123456789abcdef%1702683584.3411012\",\n                    \"math/1.0#85d927a4a067a531b1a9c7619522c015%1702683583.3411012\",\n                    \"engine/1.0#fd2b006646a54397c16a1478ac4111ac%1702683583.3544693\"\n                ]\n            }\n            \"\"\")\n        c.save({\"conan.lock\": lock})\n        c.run(f\"lock remove {args}\")\n        lock = c.load(\"conan.lock\")\n        for remove in removed:\n            assert remove not in lock\n        for pkg in {\"math/1.0#123456789abcdef\",\n                    \"math/1.0#85d927a4a067a531b1a9c7619522c015\",\n                    \"engine/1.0#fd2b006646a54397c16a1478ac4111ac\"}.difference(removed):\n            assert pkg in lock\n\n    @pytest.mark.parametrize(\"args, removed\", [\n        (\"--requires=*/*@team\", [\"pkg/1.0@team\"]),\n        (\"--requires=*/*@team*\", [\"pkg/1.0@team\", \"math/2.0@team/stable\"]),\n        (\"--requires=*/*@user\", [\"math/1.0@user\", \"other/1.0@user\"]),\n        (\"--requires=*/*@\", [\"engine/1.0\"]),  # Remove those without user\n        # with version ranges\n        (\"--requires=math/[*]@user\", [\"math/1.0@user\"]),\n        (\"--requires=math/[*]@team*\", [\"math/2.0@team/stable\"]),\n    ])\n    def test_lock_remove_user_channel(self, args, removed):\n        c = TestClient(light=True)\n        lock = textwrap.dedent(\"\"\"\\\n            {\n                \"version\": \"0.5\",\n                \"requires\": [\n                    \"math/1.0@user#123456789abcdef%1702683584.3411012\",\n                    \"math/2.0@team/stable#123456789abcdef%1702683584.3411012\",\n                    \"other/1.0@user#85d927a4a067a531b1a9c7619522c015%1702683583.3411012\",\n                    \"pkg/1.0@team#85d927a4a067a531b1a9c7619522c015%1702683583.3411012\",\n                    \"engine/1.0#fd2b006646a54397c16a1478ac4111ac%1702683583.3544693\"\n                ]\n            }\n            \"\"\")\n        c.save({\"conan.lock\": lock})\n        c.run(f\"lock remove {args}\")\n        lock = c.load(\"conan.lock\")\n        for remove in removed:\n            assert remove not in lock\n        rest = {\"math/1.0@user\", \"math/2.0@team/stable\",\n                \"other/1.0@user\", \"pkg/1.0@team\", \"engine/1.0\"}.difference(removed)\n        for pkg in rest:\n            assert pkg in lock\n\n\nclass TestLockUpdate:\n    @pytest.mark.parametrize(\"kind, old, new\", [\n        (\"requires\", \"math/1.0\", \"math/1.1\"),\n        (\"build-requires\", \"cmake/1.0\", \"cmake/1.1\"),\n        (\"python-requires\", \"mytool/1.0\", \"mytool/1.1\"),\n    ])\n    def test_lock_update(self, kind, old, new):\n        c = TestClient(light=True)\n        lock = textwrap.dedent(\"\"\"\\\n            {\n                \"version\": \"0.5\",\n                \"requires\": [\n                    \"math/1.0#85d927a4a067a531b1a9c7619522c015%1702683583.3411012\",\n                    \"math/1.0#12345%1702683584.3411012\",\n                    \"engine/1.0#fd2b006646a54397c16a1478ac4111ac%1702683583.3544693\"\n                ],\n                \"build_requires\": [\n                    \"cmake/1.0#85d927a4a067a531b1a9c7619522c015%1702683583.3411012\",\n                    \"ninja/1.0#fd2b006646a54397c16a1478ac4111ac%1702683583.3544693\"\n                ],\n                \"python_requires\": [\n                    \"mytool/1.0#85d927a4a067a531b1a9c7619522c015%1702683583.3411012\",\n                    \"othertool/1.0#fd2b006646a54397c16a1478ac4111ac%1702683583.3544693\"\n                ]\n            }\n            \"\"\")\n        c.save({\"conan.lock\": lock})\n        c.run(f\"lock update --{kind}={new}\")\n        lock = c.load(\"conan.lock\")\n        assert old not in lock\n        assert new in lock\n\n\nclass TestLockUpgrade:\n    @pytest.mark.parametrize(\"kind, pkg, old, new\", [\n        (\"requires\", \"math\", \"math/1.0\", \"math/1.1\"),\n        (\"build-requires\", \"cmake\", \"cmake/1.0\", \"cmake/1.1\"),  # TODO there isn't a --build-requires\n        # (\"python-requires\", \"mytool\", \"mytool/1.0\", \"mytool/1.1\"), # TODO nor a --python-requires\n    ])\n    def test_lock_upgrade(self, kind, pkg, old, new):\n        c = TestClient(light=True)\n        c.save({f\"{pkg}/conanfile.py\": GenConanfile(pkg)})\n\n        c.run(f\"export {pkg} --version=1.0\")\n        rev0 = c.exported_recipe_revision()\n        kind_create = \"tool-requires\" if \"build-requires\" == kind else kind\n        c.run(f\"lock create --{kind_create}={pkg}/[*]\")\n        lock = c.load(\"conan.lock\")\n        assert f\"{old}#{rev0}\" in lock\n\n        c.run(f\"export {pkg} --version=1.1\")\n        rev1 = c.exported_recipe_revision()\n        c.run(f\"lock upgrade --{kind_create}={pkg}/[*] --update-{kind}={pkg}/[*]\")\n        lock = c.load(\"conan.lock\")\n        assert f\"{old}#{rev0}\" not in lock\n        assert f\"{new}#{rev1}\" in lock\n\n    def test_lock_upgrade_path(self):\n        c = TestClient(light=True)\n        c.save({\"liba/conanfile.py\": GenConanfile(\"liba\"),\n                \"libb/conanfile.py\": GenConanfile(\"libb\"),\n                \"libc/conanfile.py\": GenConanfile(\"libc\"),\n                \"libd/conanfile.py\": GenConanfile(\"libd\")})\n        c.run(f\"export liba --version=1.0\")\n        c.run(f\"export libb --version=1.0\")\n        c.run(f\"export libc --version=1.0\")\n        c.run(f\"export libd --version=1.0\")\n        c.save(\n            {\n                f\"conanfile.py\": GenConanfile()\n                .with_requires(f\"liba/[>=1.0 <2]\")\n                .with_requires(\"libb/[<1.2]\")\n                .with_tool_requires(\"libc/[>=1.0]\")\n                .with_python_requires(\"libd/[>=1.0 <1.2]\")\n            }\n        )\n\n        c.run(\"lock create .\")\n        lock = c.load(\"conan.lock\")\n        assert \"liba/1.0\" in lock\n        assert \"libb/1.0\" in lock\n        assert \"libc/1.0\" in lock\n        assert \"libd/1.0\" in lock\n\n        # Check versions are updated accordingly\n        c.run(f\"export liba --version=1.9\")\n        c.run(f\"export libb --version=1.1\")\n        c.run(f\"export libb --version=1.2\")\n        c.run(f\"export libc --version=1.1\")\n        c.run(f\"export libd --version=1.1\")\n        c.run(\"lock upgrade . --update-requires=liba/1.0 --update-requires=libb/[*] --update-build-requires=libc/[*] --update-python-requires=libd/1.0\")\n        lock = c.load(\"conan.lock\")\n        assert \"liba/1.9\" in lock\n        assert \"libb/1.1\" in lock\n        assert \"libc/1.1\" in lock\n        assert \"libd/1.1\" in lock\n\n        # Check version conanfile version range is respected\n        c.run(f\"export libd --version=1.2\")\n        c.run(\"lock upgrade . --update-python-requires=libd/*\")\n        lock = c.load(\"conan.lock\")\n        assert \"libd/1.1\" in lock\n        assert \"libd/1.2\" not in lock\n\n    def test_lock_upgrade_new_requirement(self):\n        c = TestClient(light=True)\n        c.save({\"liba/conanfile.py\": GenConanfile(\"liba\").with_requires(\"libb/1.0\"),\n                \"libb/conanfile.py\": GenConanfile(\"libb\").with_requires(\"libc/1.0\"),\n                \"libc/conanfile.py\": GenConanfile(\"libc\"),\n                \"libd/conanfile.py\": GenConanfile(\"libd\")})\n        c.run(f\"export liba --version=1.0\")\n        c.run(f\"export libb --version=1.0\")\n        c.run(f\"export libc --version=1.0\")\n        c.run(f\"export libd --version=1.0\")\n        c.save({f\"conanfile.py\": GenConanfile().with_requires(f\"liba/[>=1.0 <2]\")})\n        c.run(\"lock create .\")\n\n        c.save({\"libb/conanfile.py\": GenConanfile(\"libb\").with_requires(\"libd/1.0\")})\n        c.run(f\"export libb --version=2.0\")\n        c.run(\"lock upgrade --requires='libb/[>=2]' --update-requires='libb/*'\")\n        lock = c.load(\"conan.lock\")\n        assert \"libb/2.0\" in lock\n        assert \"libd/1.0\" in lock\n        assert \"libc/1.0\" in lock  # TODO: libc should be removed from lockfile? It is not required anymore...\n\n    def test_config_upgrade(self):\n        \"\"\" Test that it is possible to lock also config-requires\n        \"\"\"\n        c = TestClient(light=True)\n\n        c.save({\"config/conanfile.py\": GenConanfile(\"config\").with_package_type(\"configuration\"),\n                \"conanfile.py\": GenConanfile(\"pkg\", \"1.0\")})\n        c.run(\"create config --version=1.0\")\n        c.run(\"create config --version=2.0\")\n        c.run(\"config install-pkg config/1.0 --lockfile-out=conan.lock\")\n\n        def _check(refs):\n            reqs = json.loads(c.load(\"conan.lock\"))[\"config_requires\"]\n            for a, b in zip(refs, reqs):\n                assert a in b\n\n        def _check_cache(refs):\n            reqs = json.loads(c.load_home(\"config_version.json\"))[\"config_version\"]\n            for a, b in zip(refs, reqs):\n                assert a in b\n\n        _check([\"config/1.0\"])\n        _check_cache([\"config/1.0\"])\n\n        c.run(\"lock upgrade-config --requires=config/[*] --update-config-requires=config/*\")\n        _check([\"config/2.0\"])\n        _check_cache([\"config/1.0\"])\n\n        c.run(\"config install-pkg config/1.0 --lockfile=conan.lock\", assert_error=True)\n        assert \"ERROR: Requirement 'config/1.0' not in lockfile 'config_requires'\" in c.out\n        c.run(\"config install-pkg config/2.0 --lockfile=conan.lock\")\n        _check([\"config/2.0\"])\n        _check_cache([\"config/2.0\"])\n\n        # Force downgrade\n        c.run(\"config install-pkg config/1.0 --lockfile= --lockfile-out=conan.lock\")\n        _check([\"config/1.0\"])\n        _check_cache([\"config/1.0\"])\n\n        c.save({\"conanconfig.yml\": \"packages:\\n    - config/[*]\"})\n        c.run(\"lock upgrade-config . --update-config-requires=config/1.0\")\n        _check([\"config/2.0\"])\n        _check_cache([\"config/1.0\"])\n        c.run(\"config install-pkg . --lockfile=conan.lock\")\n        _check_cache([\"config/2.0\"])\n"
  },
  {
    "path": "test/integration/metadata/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/metadata/test_metadata_collect.py",
    "content": "import os\nimport shutil\nimport textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import save\n\n\ncollect = '''\\\nimport os, shutil, fnmatch\nfrom conan.errors import ConanException\nfrom conan.cli.command import conan_command\nfrom conan.api.output import ConanOutput\nfrom conan.cli import make_abs_path\nfrom conan.cli.args import common_graph_args, validate_common_graph_args\nfrom conan.cli.printers import print_profiles\nfrom conan.cli.printers.graph import print_graph_packages, print_graph_basic\n# TODO, fix private API\nfrom conan.internal.graph.install_graph import InstallGraph\n\n\n@conan_command(group=\"Metadata\")\ndef collect(conan_api, parser, *args):\n    \"\"\"\n    command to advanced metadata\n    \"\"\"\n    common_graph_args(parser)\n    parser.add_argument(\"-m\", \"--metadata\", action='append',\n                        help='Download the metadata matching the pattern, even if the package is '\n                             'already in the cache and not downloaded')\n    parser.add_argument(\"-mr\", \"--metadata-remote\", help='Download the metadata from this remote')\n    parser.add_argument(\"-of\", \"--output-folder\", help='The root output folder for metadata')\n    parser.add_argument(\"--build-require\", action='store_true', default=False,\n                        help='Whether the provided path is a build-require')\n    args = parser.parse_args(*args)\n    validate_common_graph_args(args)\n\n    # basic paths\n    cwd = os.getcwd()\n    path = conan_api.local.get_conanfile_path(args.path, cwd, py=None) if args.path else None\n    output_folder = (make_abs_path(args.output_folder, cwd) if args.output_folder\n                     else os.path.join(cwd, \"metadata\"))\n\n    # Basic collaborators: remotes, lockfile, profiles\n    remotes = conan_api.remotes.list(args.remote) if not args.no_remote else []\n    lockfile = conan_api.lockfile.get_lockfile(lockfile=args.lockfile, conanfile_path=path, cwd=cwd,\n                                               partial=args.lockfile_partial)\n    profile_host, profile_build = conan_api.profiles.get_profiles_from_args(args)\n    print_profiles(profile_host, profile_build)\n\n    # Graph computation (without installation of binaries)\n    gapi = conan_api.graph\n    if path:\n        deps_graph = gapi.load_graph_consumer(path, args.name, args.version, args.user, args.channel,\n                                              profile_host, profile_build, lockfile, remotes,\n                                              args.update, is_build_require=args.build_require)\n    else:\n        deps_graph = gapi.load_graph_requires(args.requires, args.tool_requires, profile_host,\n                                              profile_build, lockfile, remotes, args.update)\n    print_graph_basic(deps_graph)\n    deps_graph.report_graph_error()\n    gapi.analyze_binaries(deps_graph, args.build, remotes, update=args.update, lockfile=lockfile)\n    print_graph_packages(deps_graph)\n\n    # Installation of binaries and consumer generators\n    conan_api.install.install_binaries(deps_graph=deps_graph, remotes=remotes)\n\n    # Downloading metadata\n    metadata = args.metadata if args.metadata else [\"*\"]\n    # TODO: This InstallGraph API is EXPERIMENTAL and will change in future versions\n    install_graph = InstallGraph(deps_graph)\n    install_order = install_graph.install_order(flat=True)\n\n    if args.metadata_remote:\n        out = ConanOutput()\n        out.title(f\"Downloading metadata from {args.metadata_remote}\")\n        remote = conan_api.remotes.get(args.metadata_remote)\n\n        for install_reference in install_order:\n            if install_reference.ref.revision is None:  # Is an editable/system, do not download\n                continue\n            try:\n                conan_api.download.recipe(install_reference.ref, remote, metadata)\n            except ConanException as e:\n                out.warning(f\"Recipe {install_reference.ref} not found in remote: {e}\")\n                continue\n            for package in install_reference.packages.values():\n                try:\n                    conan_api.download.package(package.pref, remote, metadata)\n                except ConanException as e:\n                    out.warning(f\"Package {package.pref} not found in remote: {e}\")\n\n    # Copying and collecting metadata from all packages into local copy\n    def _copy_metadata(src, dst):\n        for root, subfolders, files in os.walk(src):\n            relative_path = os.path.relpath(root, src)\n            for f in files:\n                relative_name = os.path.normpath(os.path.join(relative_path, f))\n                if any(fnmatch.fnmatch(relative_name, m) for m in metadata):\n                    os.makedirs(os.path.dirname(os.path.join(dst, relative_name)), exist_ok=True)\n                    shutil.copy2(os.path.join(src, relative_name), os.path.join(dst, relative_name))\n\n    for install_reference in install_order:\n        conanfile = install_reference.node.conanfile\n        if conanfile.recipe_metadata_folder is None:\n            continue\n        folder = os.path.join(output_folder, conanfile.ref.name, str(conanfile.ref.version))\n        if os.path.exists(folder):\n            conanfile.output.warning(f\"Folder for {conanfile} already exist, removing it: {folder}\")\n            shutil.rmtree(folder)\n        conanfile.output.info(f\"Copying recipe metadata from {conanfile.recipe_metadata_folder}\")\n        _copy_metadata(conanfile.recipe_metadata_folder, os.path.join(folder, \"recipe\"))\n        for package in install_reference.packages.values():\n            pkg_metadata_folder = package.conanfile.package_metadata_folder\n            conanfile.output.info(f\"Copying package metadata from {pkg_metadata_folder}\")\n            _copy_metadata(pkg_metadata_folder, os.path.join(folder, \"package\"))\n'''\n\n\ndef test_custom_command_collect_no_metadata():\n    c = TestClient(default_server_user=True)\n    command_file_path = os.path.join(c.cache_folder, 'extensions',\n                                     'commands', 'metadata', 'cmd_collect.py')\n    save(command_file_path, collect)\n    c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\"),\n            \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_requires(\"dep/0.1\")})\n    c.run(\"create dep\")\n    c.run(\"create pkg\")\n    c.run(\"metadata:collect --requires=pkg/0.1 --metadata=* --metadata-remote=default\")\n    # It does nothing, but it doesn't crash\n\n    c.run(\"upload * -r=default -c\")\n    c.run(\"metadata:collect --requires=pkg/0.1 --metadata=* --metadata-remote=default\")\n    # It does nothing, but it doesn't crash\n\n    c.run(\"editable add dep\")\n    c.run(\"metadata:collect --requires=pkg/0.1 --metadata=* --metadata-remote=default\")\n    # It does nothing, but it doesn't crash\n\n\nconanfile = textwrap.dedent(\"\"\"\n    import os\n    from conan import ConanFile\n    from conan.tools.files import save, copy\n\n    class Pkg(ConanFile):\n        name = \"{name}\"\n        version = \"0.1\"\n        {requires}\n\n        def layout(self):\n            self.folders.build = \"build\"\n\n        def source(self):\n            save(self, os.path.join(self.recipe_metadata_folder, \"logs\", \"src.log\"),\n                 f\"srclog {{self.name}}!!\")\n\n        def build(self):\n            save(self, \"mylogs.txt\", f\"some logs {{self.name}}!!!\")\n            copy(self, \"mylogs.txt\", src=self.build_folder,\n                 dst=os.path.join(self.package_metadata_folder, \"logs\"))\n    \"\"\")\n\n\ndef test_custom_command_collect():\n    c = TestClient(default_server_user=True)\n    command_file_path = os.path.join(c.cache_folder, 'extensions',\n                                     'commands', 'metadata', 'cmd_collect.py')\n    save(command_file_path, collect)\n    c.save({\"dep/conanfile.py\": conanfile.format(name=\"dep\",\n                                                 requires=\"tool_requires = 'tool/0.1'\"),\n            \"pkg/conanfile.py\": conanfile.format(name=\"pkg\", requires='requires = \"dep/0.1\"'),\n            \"profile\": \"[platform_tool_requires]\\ntool/0.1\"})\n    c.run(\"create dep -pr=profile\")\n    c.run(\"create pkg -pr=profile\")\n    c.run(\"metadata:collect --requires=pkg/0.1 --metadata=* --metadata-remote=default -pr=profile\")\n    assert \"srclog dep!!\" in c.load(\"metadata/dep/0.1/recipe/logs/src.log\")\n    assert \"some logs dep!!!\" in c.load(\"metadata/dep/0.1/package/logs/mylogs.txt\")\n    assert \"srclog pkg!!\" in c.load(\"metadata/pkg/0.1/recipe/logs/src.log\")\n    assert \"some logs pkg!!!\" in c.load(\"metadata/pkg/0.1/package/logs/mylogs.txt\")\n\n    shutil.rmtree(os.path.join(c.current_folder, \"metadata\"))\n\n    c.run(\"upload * -r=default -c\")\n    c.run(\"remove * -c\")\n    c.run(\"metadata:collect --requires=pkg/0.1 --metadata=* --metadata-remote=default -pr=profile\")\n    assert \"srclog dep!!\" in c.load(\"metadata/dep/0.1/recipe/logs/src.log\")\n    assert \"some logs dep!!!\" in c.load(\"metadata/dep/0.1/package/logs/mylogs.txt\")\n    assert \"srclog pkg!!\" in c.load(\"metadata/pkg/0.1/recipe/logs/src.log\")\n    assert \"some logs pkg!!!\" in c.load(\"metadata/pkg/0.1/package/logs/mylogs.txt\")\n\n    shutil.rmtree(os.path.join(c.current_folder, \"metadata\"))\n    c.run(\"editable add dep\")\n    c.run(\"source dep\")\n    c.run(\"build dep -pr=profile\")\n    c.run(\"metadata:collect --requires=pkg/0.1 --metadata=* --metadata-remote=default -pr=profile\")\n    assert \"srclog dep!!\" in c.load(\"metadata/dep/0.1/recipe/logs/src.log\")\n    assert \"some logs dep!!!\" in c.load(\"metadata/dep/0.1/package/logs/mylogs.txt\")\n    assert \"srclog pkg!!\" in c.load(\"metadata/pkg/0.1/recipe/logs/src.log\")\n    assert \"some logs pkg!!!\" in c.load(\"metadata/pkg/0.1/package/logs/mylogs.txt\")\n"
  },
  {
    "path": "test/integration/metadata/test_metadata_commands.py",
    "content": "import os\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient, NO_SETTINGS_PACKAGE_ID\nfrom conan.internal.util.files import save, load\n\n\nclass TestMetadataCommands:\n\n    @pytest.fixture\n    def create_conan_pkg(self):\n        client = TestClient(default_server_user=True, light=True)\n        client.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n        client.run(\"create .\")\n        pid = client.created_package_id(\"pkg/0.1\")\n        return client, pid\n\n    @staticmethod\n    def save_metadata_file(client, pkg_ref, filename=\"somefile.log\", content=None):\n        client.run(f\"cache path {pkg_ref} --folder=metadata\")\n        metadata_path = str(client.stdout).strip()\n        myfile = os.path.join(metadata_path, \"logs\", filename)\n        save(myfile, f\"{content or str(pkg_ref)}!!!!\")\n        return metadata_path, myfile\n\n    def test_upload(self, create_conan_pkg):\n        c, pid = create_conan_pkg\n\n        # Add some metadata\n        self.save_metadata_file(c, \"pkg/0.1\", \"mylogs.txt\")\n        self.save_metadata_file(c, f\"pkg/0.1:{pid}\", \"mybuildlogs.txt\")\n        # Now upload everything\n        c.run(\"upload * -c -r=default\")\n        assert \"pkg/0.1: Recipe metadata: 1 files\" in c.out\n        assert \"pkg/0.1:da39a3ee5e6b4b0d3255bfef95601890afd80709: Package metadata: 1 files\" in c.out\n\n        # Add new files to the metadata\n        self.save_metadata_file(c, \"pkg/0.1\", \"mylogs2.txt\")\n        self.save_metadata_file(c, f\"pkg/0.1:{pid}\", \"mybuildlogs2.txt\")\n        # Upload the metadata, even if the revisions exist in the server\n        # adding the new metadata logs files\n        c.run(\"upload * -c -r=default --metadata=*\")\n        assert \"pkg/0.1: Recipe metadata: 2 files\" in c.out\n        assert \"pkg/0.1:da39a3ee5e6b4b0d3255bfef95601890afd80709: Package metadata: 2 files\" in c.out\n\n        c.run(\"remove * -c\")\n        c.run(\"install --requires=pkg/0.1\")  # wont install metadata by default\n        c.run(\"cache path pkg/0.1 --folder=metadata\")\n        metadata_path = str(c.stdout).strip()\n        assert os.listdir(metadata_path) == []\n        c.run(f\"cache path pkg/0.1:{pid} --folder=metadata\")\n        metadata_path = str(c.stdout).strip()\n        assert os.listdir(metadata_path) == []\n\n        # Forcing the download of the metadata of cache-existing things with the \"download\" command\n        c.run(\"download pkg/0.1 -r=default --metadata=*\")\n        c.run(f\"cache path pkg/0.1 --folder=metadata\")\n        metadata_path = str(c.stdout).strip()\n        c.run(f\"cache path pkg/0.1:{pid} --folder=metadata\")\n        pkg_metadata_path = str(c.stdout).strip()\n        for f in \"logs/mylogs.txt\", \"logs/mylogs2.txt\":\n            assert os.path.isfile(os.path.join(metadata_path, f))\n        for f in \"logs/mybuildlogs.txt\", \"logs/mybuildlogs2.txt\":\n            assert os.path.isfile(os.path.join(pkg_metadata_path, f))\n\n    def test_update_contents(self):\n        c = TestClient(default_server_user=True, light=True)\n        c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n        c.run(\"export .\")\n\n        # Add some metadata\n        _, myfile = self.save_metadata_file(c, \"pkg/0.1\", \"mylogs.txt\")\n\n        # Now upload everything\n        c.run(\"upload * -c -r=default\")\n        assert \"pkg/0.1: Recipe metadata: 1 files\" in c.out\n\n        # Update the metadata\n        save(myfile, \"mylogs2!!!!\")\n        # Upload the metadata, even if the revisions exist in the server\n        # adding the new metadata logs files\n        c.run(\"upload * -c -r=default --metadata=*\")\n        assert \"pkg/0.1: Recipe metadata: 1 files\" in c.out\n\n        c.run(\"remove * -c\")\n        c.run(\"download pkg/0.1 -r=default --metadata=*\")\n        c.run(\"cache path pkg/0.1 --folder=metadata\")\n        metadata_path = str(c.stdout).strip()\n\n        content = load(os.path.join(metadata_path, \"logs\", \"mylogs.txt\"))\n        assert \"mylogs2!!!!\" in content\n\n    def test_append_contents(self):\n        # I can add extra files to metadata without necessarily downloading it first\n        c = TestClient(default_server_user=True, light=True)\n        c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n        c.run(\"create .\")\n        pkgid = \"da39a3ee5e6b4b0d3255bfef95601890afd80709\"\n        # Add some metadata\n        self.save_metadata_file(c, \"pkg/0.1\", \"mylogs.txt\", content=\"mylogs\")\n        self.save_metadata_file(c, f\"pkg/0.1:{pkgid}\", \"mybin.txt\", content=\"mybin\")\n\n        # Now upload everything\n        c.run(\"upload * -c -r=default\")\n        assert \"pkg/0.1: Recipe metadata: 1 files\" in c.out\n\n        c2 = TestClient(servers=c.servers, light=True, inputs=[\"admin\", \"password\"])\n        c2.run(\"install --requires=pkg/0.1\")\n        self.save_metadata_file(c2, \"pkg/0.1\", \"mylogs2.txt\", content=\"mylogs2\")\n        self.save_metadata_file(c2, f\"pkg/0.1:{pkgid}\", \"mybin2.txt\", content=\"mybin2\")\n        c2.run(\"upload * -c -r=default --metadata=*\")\n        assert \"pkg/0.1: Recipe metadata: 1 files\" in c2.out\n\n        c.run(\"remove * -c\")\n        c.run(\"download pkg/0.1 -r=default --metadata=*\")\n\n        c.run(\"cache path pkg/0.1 --folder=metadata\")\n        metadata_path = str(c.stdout).strip()\n        assert \"mylogs!!!!\" in load(os.path.join(metadata_path, \"logs\", \"mylogs.txt\"))\n        assert \"mylogs2!!!!\" in load(os.path.join(metadata_path, \"logs\", \"mylogs2.txt\"))\n\n        c.run(f\"cache path pkg/0.1:{pkgid} --folder=metadata\")\n        metadata_path = str(c.stdout).strip()\n        assert \"mybin!!!!\" in load(os.path.join(metadata_path, \"logs\", \"mybin.txt\"))\n        assert \"mybin2!!!!\" in load(os.path.join(metadata_path, \"logs\", \"mybin2.txt\"))\n\n    def test_overwrite_server_contents(self):\n        # I can overwrite server contents\n        c = TestClient(default_server_user=True, light=True)\n        c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n        c.run(\"create .\")\n        pkgid = \"da39a3ee5e6b4b0d3255bfef95601890afd80709\"\n        # Add some metadata\n        self.save_metadata_file(c, \"pkg/0.1\", \"mylogs.txt\", content=\"mylogs\")\n        self.save_metadata_file(c, f\"pkg/0.1:{pkgid}\", \"mybin.txt\", content=\"mybin\")\n\n        # Now upload everything\n        c.run(\"upload * -c -r=default\")\n        assert \"pkg/0.1: Recipe metadata: 1 files\" in c.out\n\n        c2 = TestClient(servers=c.servers, light=True, inputs=[\"admin\", \"password\"])\n        c2.run(\"install --requires=pkg/0.1\")\n        self.save_metadata_file(c2, \"pkg/0.1\", \"mylogs.txt\", content=\"mylogs2\")\n        self.save_metadata_file(c2, f\"pkg/0.1:{pkgid}\", \"mybin.txt\", content=\"mybin2\")\n        c2.run(\"upload * -c -r=default --metadata=*\")\n        assert \"pkg/0.1: Recipe metadata: 1 files\" in c2.out\n\n        c.run(\"remove * -c\")\n        c.run(\"download pkg/0.1 -r=default --metadata=*\")\n\n        c.run(\"cache path pkg/0.1 --folder=metadata\")\n        metadata_path = str(c.stdout).strip()\n        assert \"mylogs2!!!!\" in load(os.path.join(metadata_path, \"logs\", \"mylogs.txt\"))\n\n        c.run(f\"cache path pkg/0.1:{pkgid} --folder=metadata\")\n        metadata_path = str(c.stdout).strip()\n        assert \"mybin2!!!!\" in load(os.path.join(metadata_path, \"logs\", \"mybin.txt\"))\n\n    def test_folder_exist(self, create_conan_pkg):\n        \"\"\" so we can cp -R to the metadata folder, having to create the folder in the cache\n        is weird\n        \"\"\"\n        c, _ = create_conan_pkg\n        c.run(\"cache path pkg/0.1 --folder=metadata\")\n        metadata_path = str(c.stdout).strip()\n        assert os.path.isdir(metadata_path)\n        c.run(f\"cache path pkg/0.1:{NO_SETTINGS_PACKAGE_ID} --folder=metadata\")\n        pkg_metadata_path = str(c.stdout).strip()\n        assert os.path.isdir(pkg_metadata_path)\n\n    def test_direct_download_redownload(self, create_conan_pkg):\n        \"\"\" When we directly download things, without \"conan install\" first, it is also able\n        to fetch the requested metadata\n\n        Also, re-downloading same thing shouldn't fail\n        \"\"\"\n        c, pid = create_conan_pkg\n\n        # Add some metadata\n        metadata_path, _ = self.save_metadata_file(c, \"pkg/0.1\", \"mylogs.txt\")\n        self.save_metadata_file(c, f\"pkg/0.1:{pid}\", \"mybuildlogs.txt\")\n\n        # Now upload everything\n        c.run(\"upload * -c -r=default\")\n        assert \"pkg/0.1: Recipe metadata: 1 files\" in c.out\n        assert \"pkg/0.1:da39a3ee5e6b4b0d3255bfef95601890afd80709: Package metadata: 1 files\" in c.out\n\n        c.run(\"remove * -c\")\n\n        # Forcing the download of the metadata of cache-existing things with the \"download\" command\n        c.run(\"download pkg/0.1 -r=default --metadata=*\")\n        assert os.path.isfile(os.path.join(metadata_path, \"logs\", \"mylogs.txt\"))\n        c.run(f\"cache path pkg/0.1:{pid} --folder=metadata\")\n        pkg_metadata_path = str(c.stdout).strip()\n        assert os.path.isfile(os.path.join(pkg_metadata_path, \"logs\", \"mybuildlogs.txt\"))\n\n        # Re-download shouldn't fail\n        c.run(\"download pkg/0.1 -r=default --metadata=*\")\n        assert os.path.isfile(os.path.join(metadata_path, \"logs\", \"mylogs.txt\"))\n        c.run(f\"cache path pkg/0.1:{pid} --folder=metadata\")\n        pkg_metadata_path = str(c.stdout).strip()\n        assert os.path.isfile(os.path.join(pkg_metadata_path, \"logs\", \"mybuildlogs.txt\"))\n\n    def test_no_download_cached(self, create_conan_pkg):\n        \"\"\" as the metadata can change, no checksum, no revision, cannot be cached\n        \"\"\"\n        c, pid = create_conan_pkg\n\n        # Add some metadata\n        _, myrecipefile = self.save_metadata_file(c, \"pkg/0.1\", \"mylogs.txt\")\n        _, mypkgfile = self.save_metadata_file(c, f\"pkg/0.1:{pid}\", \"mybuildlogs.txt\")\n\n        # Now upload everything\n        c.run(\"upload * -c -r=default\")\n        assert \"pkg/0.1: Recipe metadata: 1 files\" in c.out\n        assert \"pkg/0.1:da39a3ee5e6b4b0d3255bfef95601890afd80709: Package metadata: 1 files\" in c.out\n\n        c2 = TestClient(servers=c.servers, light=True)\n        tmp_folder = temp_folder()\n        # MOST important part: activate cache\n        c2.save_home({\"global.conf\": f\"core.download:download_cache={tmp_folder}\\n\"})\n\n        # download package and metadata\n        c2.run(\"download pkg/0.1 -r=default --metadata=*\")\n        c2.run(\"cache path pkg/0.1 --folder=metadata\")\n        c2_metadata_path = str(c2.stdout).strip()\n        mylogs = load(os.path.join(c2_metadata_path, \"logs\", \"mylogs.txt\"))\n        assert \"pkg/0.1!!!!\" in mylogs\n        c2.run(f\"cache path pkg/0.1:{pid} --folder=metadata\")\n        c2_pkg_metadata_path = str(c2.stdout).strip()\n        mybuildlogs = load(os.path.join(c2_pkg_metadata_path, \"logs\", \"mybuildlogs.txt\"))\n        assert f\"pkg/0.1:{pid}!!!!\" in mybuildlogs\n\n        # Now the other client will update the metadata\n        save(myrecipefile, \"mylogs2!!!!\")\n        save(mypkgfile, \"mybuildlogs2!!!!\")\n        c.run(\"upload * -c -r=default --metadata=*\")\n        assert \"pkg/0.1: Recipe metadata: 1 files\" in c.out\n        assert \"pkg/0.1:da39a3ee5e6b4b0d3255bfef95601890afd80709: Package metadata: 1 files\" in c.out\n\n        # re-download of metadata in c2\n        c2.run(\"remove * -c\")  # to make sure the download cache works\n        c2.run(\"download pkg/0.1 -r=default --metadata=*\")\n        mylogs = load(os.path.join(c2_metadata_path, \"logs\", \"mylogs.txt\"))\n        assert \"mylogs2!!!!\" in mylogs\n        mybuildlogs = load(os.path.join(c2_pkg_metadata_path, \"logs\", \"mybuildlogs.txt\"))\n        assert \"mybuildlogs2!!!!\" in mybuildlogs\n\n    def test_upload_ignored_metadata(self, create_conan_pkg):\n        \"\"\"\n        Upload command should ignore metadata files when passing --metadata=\"\"\n        \"\"\"\n        client, pid = create_conan_pkg\n\n        self.save_metadata_file(client, \"pkg/0.1\")\n        self.save_metadata_file(client, f\"pkg/0.1:{pid}\")\n\n        client.run('upload * --confirm --remote=default --metadata=\"\"')\n        assert \"Recipe metadata\" not in client.out\n        assert \"Package metadata\" not in client.out\n\n    def test_upload_ignored_metadata_with_pattern(self, create_conan_pkg):\n        \"\"\"\n        Upload command should fail when passing --metadata=\"\" and a pattern\n        \"\"\"\n        client = TestClient(default_server_user=True, light=True)\n        client.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n        client.run(\"export .\")\n\n        client.run('upload * --confirm --remote=default --metadata=\"\" --metadata=\"logs/*\"',\n                   assert_error=True)\n        assert \"ERROR: Empty string and patterns can not be mixed for metadata.\" in client.out\n"
  },
  {
    "path": "test/integration/metadata/test_metadata_deploy.py",
    "content": "import os.path\nimport textwrap\nfrom collections import OrderedDict\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient, TestServer\n\n\nclass TestMetadataDeploy:\n    \"\"\" prove we can gather metadata too with a deployer\"\"\"\n\n    @pytest.fixture\n    def client(self):\n        conanfile = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.files import save, copy\n\n            class Pkg(ConanFile):\n                version = \"0.1\"\n\n                def source(self):\n                    save(self, os.path.join(self.recipe_metadata_folder, \"logs\", \"src.log\"),\n                         f\"srclog {self.name}!!!\")\n\n                def build(self):\n                    save(self, \"mylogs.txt\", f\"some logs {self.name}!!!\")\n                    copy(self, \"mylogs.txt\", src=self.build_folder,\n                         dst=os.path.join(self.package_metadata_folder, \"logs\"))\n            \"\"\")\n        deploy = textwrap.dedent(\"\"\"\n            import os, shutil\n\n            def deploy(graph, output_folder, **kwargs):\n                conanfile = graph.root.conanfile\n                for r, d in conanfile.dependencies.items():\n                    if not os.listdir(d.package_metadata_folder):\n                        continue\n                    shutil.copytree(d.package_metadata_folder, os.path.join(output_folder, \"pkgs\",\n                                                                            d.ref.name))\n                    shutil.copytree(d.recipe_metadata_folder, os.path.join(output_folder, \"recipes\",\n                                                                             d.ref.name))\n           \"\"\")\n\n        servers = OrderedDict([(\"default\", TestServer()), (\"remote2\", TestServer())])\n        c = TestClient(servers=servers, inputs=2 * [\"admin\", \"password\"], light=True)\n        c.save({\"conanfile.py\": conanfile,\n                \"deploy.py\": deploy})\n        c.run(\"create . --name=pkg1\")\n        c.run(\"create . --name=pkg2\")\n        return c\n\n    def test_cache(self, client):\n        c = client\n        c.run(\"install --requires=pkg1/0.1 --requires=pkg2/0.1 --deployer=deploy\")\n        assert \"some logs pkg1!!!\" in c.load(\"pkgs/pkg1/logs/mylogs.txt\")\n        assert \"some logs pkg2!!!\" in c.load(\"pkgs/pkg2/logs/mylogs.txt\")\n        assert \"srclog pkg1!!!\" in c.load(\"recipes/pkg1/logs/src.log\")\n        assert \"srclog pkg2!!!\" in c.load(\"recipes/pkg2/logs/src.log\")\n\n    def test_remote(self, client):\n        # But the remote story is more complex, metadata is not retrieved by default\n        c = client\n        c.run(\"upload * -c -r=default\")\n        c.run(\"remove * -c\")\n        # First install without metadata\n        c.run(\"install --requires=pkg1/0.1 --requires=pkg2/0.1\")\n        # So this will not deploy metadata\n        c.run(\"install --requires=pkg1/0.1 --requires=pkg2/0.1 --deployer=deploy -f=json\",\n              redirect_stdout=\"graph.json\")\n        assert not os.path.exists(os.path.join(c.current_folder, \"pkgs\"))\n\n        # We can obtain the pkg-list for the graph, then \"find-remote\" and download the metadata\n        c.run(\"list -g=graph.json -f=json\", redirect_stdout=\"mylist.json\")\n        c.run(\"pkglist find-remote mylist.json -f=json\", redirect_stdout=\"pkg_remotes.json\")\n        c.run(\"download --list=pkg_remotes.json -r=default --metadata=*\")\n\n        # Now we will have the metadata in cache and we can deploy it\n        c.run(\"install --requires=pkg1/0.1 --requires=pkg2/0.1 --deployer=deploy\")\n        assert \"some logs pkg1!!!\" in c.load(\"pkgs/pkg1/logs/mylogs.txt\")\n        assert \"some logs pkg2!!!\" in c.load(\"pkgs/pkg2/logs/mylogs.txt\")\n        assert \"srclog pkg1!!!\" in c.load(\"recipes/pkg1/logs/src.log\")\n        assert \"srclog pkg2!!!\" in c.load(\"recipes/pkg2/logs/src.log\")\n\n    def test_multi_remote(self, client):\n        # But the remote story is more complex, metadata is not retrieved by default,\n        # we need to iterate the remotes if data coming from multiple remotes\n        c = client\n        c.run(\"upload pkg1* -c -r=default\")\n        c.run(\"upload pkg2* -c -r=remote2\")\n        c.run(\"remove * -c\")\n        # First install without metadata\n        c.run(\"install --requires=pkg1/0.1 --requires=pkg2/0.1\")\n        # So this will not deploy metadata\n        c.run(\"install --requires=pkg1/0.1 --requires=pkg2/0.1 --deployer=deploy -f=json\",\n              redirect_stdout=\"graph.json\")\n        assert not os.path.exists(os.path.join(c.current_folder, \"pkgs\"))\n\n        # We can obtain the pkg-list for the graph, then \"find-remote\" and download the metadata\n        c.run(\"list -g=graph.json -f=json\", redirect_stdout=\"mylist.json\")\n        c.run(\"pkglist find-remote mylist.json -f=json\", redirect_stdout=\"pkg_remotes.json\")\n        # we need to ITERATE the remotes\n        c.run(\"download --list=pkg_remotes.json -r=default --metadata=*\")\n        c.run(\"download --list=pkg_remotes.json -r=remote2 --metadata=*\")\n\n        # Now we will have the metadata in cache and we can deploy it\n        c.run(\"install --requires=pkg1/0.1 --requires=pkg2/0.1 --deployer=deploy\")\n        assert \"some logs pkg1!!!\" in c.load(\"pkgs/pkg1/logs/mylogs.txt\")\n        assert \"some logs pkg2!!!\" in c.load(\"pkgs/pkg2/logs/mylogs.txt\")\n        assert \"srclog pkg1!!!\" in c.load(\"recipes/pkg1/logs/src.log\")\n        assert \"srclog pkg2!!!\" in c.load(\"recipes/pkg2/logs/src.log\")\n"
  },
  {
    "path": "test/integration/metadata/test_metadata_logs.py",
    "content": "import os\nimport textwrap\n\nimport pytest\n\nfrom conan.api.model import RecipeReference\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import load, save\n\n\nclass TestRecipeMetadataLogs:\n\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import save, copy\n\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n\n            def export(self):\n                copy(self, \"*.log\", src=self.recipe_folder,\n                dst=os.path.join(self.recipe_metadata_folder, \"logs\"))\n\n            def layout(self):\n                self.folders.build = \"mybuild\"\n                self.folders.generators = \"mybuild/generators\"\n\n            def source(self):\n                save(self, os.path.join(self.recipe_metadata_folder, \"logs\", \"src.log\"), \"srclog!!\")\n\n            def build(self):\n                save(self, \"mylogs.txt\", \"some logs!!!\")\n                copy(self, \"mylogs.txt\", src=self.build_folder,\n                dst=os.path.join(self.package_metadata_folder, \"logs\"))\n        \"\"\")\n\n    def test_metadata_logs(self):\n        c = TestClient(default_server_user=True)\n        c.save({\"conanfile.py\": self.conanfile,\n                \"file.log\": \"log contents!\"})\n        c.run(\"create .\")\n        # Test local cache looks good\n        ref = RecipeReference.loads(\"pkg/0.1\")\n        ref_layout = c.get_latest_ref_layout(ref)\n        assert os.listdir(ref_layout.metadata()) == [\"logs\"]\n        assert set(os.listdir(os.path.join(ref_layout.metadata(), \"logs\"))) == {\"file.log\",\n                                                                                \"src.log\"}\n        assert load(os.path.join(ref_layout.metadata(), \"logs\", \"file.log\")) == \"log contents!\"\n        assert load(os.path.join(ref_layout.metadata(), \"logs\", \"src.log\")) == \"srclog!!\"\n\n        pref = c.get_latest_package_reference(ref)\n        pref_layout = c.get_latest_pkg_layout(pref)\n        assert os.listdir(pref_layout.metadata()) == [\"logs\"]\n        assert os.listdir(os.path.join(pref_layout.metadata(), \"logs\")) == [\"mylogs.txt\"]\n        assert load(os.path.join(pref_layout.metadata(), \"logs\", \"mylogs.txt\")) == \"some logs!!!\"\n\n    def test_metadata_logs_local(self):\n        c = TestClient(default_server_user=True)\n        c.save({\"conanfile.py\": self.conanfile,\n                \"file.log\": \"log contents!\"})\n        c.run(\"source .\")\n        assert c.load(\"metadata/logs/src.log\") == \"srclog!!\"\n        c.run(\"build .\")\n        assert c.load(\"mybuild/metadata/logs/mylogs.txt\") == \"some logs!!!\"\n\n    def test_download_pkg_list_from_graph(self):\n        c = TestClient(default_server_user=True)\n        c.save({\"conanfile.py\": self.conanfile,\n                \"file.log\": \"log contents!\"})\n        c.run(\"create .\")\n        c.run(\"upload * -r=default -c\")\n        c.run(\"remove * -c\")\n        #  IMPORTANT: NECESSARY to force the download to gather the full package_list\n        # TODO: Check the case how to download metadata for already installed in cache packages\n        c.run(\"install --requires=pkg/0.1 --format=json\", redirect_stdout=\"graph.json\")\n        c.run(\"list --graph=graph.json --format=json\", redirect_stdout=\"pkglist.json\")\n        # This list will contain both \"Local Cache\" and \"default\" origins, because it was downloaded\n        c.run(\"download --list=pkglist.json -r=default --metadata=*\")\n\n        ref = RecipeReference.loads(\"pkg/0.1\")\n        pref = c.get_latest_package_reference(ref)\n        pref_layout = c.get_latest_pkg_layout(pref)\n        assert os.listdir(pref_layout.metadata()) == [\"logs\"]\n        assert os.listdir(os.path.join(pref_layout.metadata(), \"logs\")) == [\"mylogs.txt\"]\n        assert load(os.path.join(pref_layout.metadata(), \"logs\", \"mylogs.txt\")) == \"some logs!!!\"\n\n    def test_metadata_folder_exist(self):\n        \"\"\" make sure the folders exists\n        so recipe don't have to create it for running bulk copies calling self.run(cp -R)\n        \"\"\"\n        conanfile = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n\n                def export(self):\n                    assert os.path.exists(self.recipe_metadata_folder)\n\n                def source(self):\n                    assert os.path.exists(self.recipe_metadata_folder)\n\n                def build(self):\n                    assert os.path.exists(self.package_metadata_folder)\n            \"\"\")\n        c = TestClient(default_server_user=True)\n        c.save({\"conanfile.py\": conanfile})\n        c.run(\"create .\")\n        c.run(\"upload * -r=default -c\")\n        c.run(\"remove * -c\")\n        c.run(\"install --requires=pkg/0.1 --build=*\")\n        # If nothing fail, all good, all folder existed, assert passed\n\n\nclass TestHooksMetadataLogs:\n\n    @pytest.fixture()\n    def _client(self):\n        c = TestClient(default_server_user=True)\n        my_hook = textwrap.dedent(\"\"\"\\\n            import os\n            from conan.tools.files import copy\n\n            def post_export(conanfile):\n                conanfile.output.info(\"post_export\")\n                copy(conanfile, \"*.log\", src=conanfile.recipe_folder,\n                     dst=os.path.join(conanfile.recipe_metadata_folder, \"logs\"))\n\n            def post_source(conanfile):\n                conanfile.output.info(\"post_source\")\n                copy(conanfile, \"*\", src=os.path.join(conanfile.source_folder, \"logs\"),\n                     dst=os.path.join(conanfile.recipe_metadata_folder, \"logs\"))\n\n            def post_build(conanfile):\n                conanfile.output.info(\"post_build\")\n                copy(conanfile, \"*\", src=os.path.join(conanfile.build_folder, \"logs\"),\n                     dst=os.path.join(conanfile.package_metadata_folder, \"logs\"))\n            \"\"\")\n        hook_path = os.path.join(c.paths.hooks_path, \"my_hook\", \"hook_my_hook.py\")\n        save(hook_path, my_hook)\n        conanfile = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.files import save, copy\n\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                no_copy_source = True\n\n                def layout(self):\n                    self.folders.build = \"mybuild\"\n                    self.folders.generators = \"mybuild/generators\"\n\n                def source(self):\n                    save(self, \"logs/src.log\", \"srclog!!\")\n\n                def build(self):\n                    save(self, \"logs/mylogs.txt\", \"some logs!!!\")\n            \"\"\")\n        c.save({\"conanfile.py\": conanfile,\n                \"file.log\": \"log contents!\"})\n        return c\n\n    def test_metadata_logs_hook(self, _client):\n        c = _client\n        c.run(\"create .\")\n        # Test local cache looks good\n        ref = RecipeReference.loads(\"pkg/0.1\")\n        ref_layout = c.get_latest_ref_layout(ref)\n        assert os.listdir(ref_layout.metadata()) == [\"logs\"]\n        assert set(os.listdir(os.path.join(ref_layout.metadata(), \"logs\"))) == {\"file.log\",\n                                                                                \"src.log\"}\n        assert load(os.path.join(ref_layout.metadata(), \"logs\", \"file.log\")) == \"log contents!\"\n        assert load(os.path.join(ref_layout.metadata(), \"logs\", \"src.log\")) == \"srclog!!\"\n\n        pref = c.get_latest_package_reference(ref)\n        pref_layout = c.get_latest_pkg_layout(pref)\n        assert os.listdir(pref_layout.metadata()) == [\"logs\"]\n        assert os.listdir(os.path.join(pref_layout.metadata(), \"logs\")) == [\"mylogs.txt\"]\n        assert load(os.path.join(pref_layout.metadata(), \"logs\", \"mylogs.txt\")) == \"some logs!!!\"\n\n    def test_metadata_logs_local(self, _client):\n        c = _client\n        c.run(\"source .\")\n        assert c.load(\"metadata/logs/src.log\") == \"srclog!!\"\n        c.run(\"build .\")\n        assert c.load(\"mybuild/metadata/logs/mylogs.txt\") == \"some logs!!!\"\n\n\ndef test_metadata_export_pkg():\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import save, copy\n\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n\n            def build(self):\n                save(self, \"mylogs.txt\", \"some logs!!!\")\n                copy(self, \"mylogs.txt\", src=self.build_folder,\n                     dst=os.path.join(self.package_metadata_folder, \"logs\"))\n\n            def package(self):\n                copy(self, \"*\", src=os.path.join(self.build_folder, \"metadata\"),\n                     dst=self.package_metadata_folder)\n        \"\"\")\n\n    c = TestClient()\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"build .\")\n    c.run(\"export-pkg .\")\n    # Test local cache looks good\n    pkg_layout = c.created_layout()\n    assert os.listdir(pkg_layout.metadata()) == [\"logs\"]\n    assert os.listdir(os.path.join(pkg_layout.metadata(), \"logs\")) == [\"mylogs.txt\"]\n    assert load(os.path.join(pkg_layout.metadata(), \"logs\", \"mylogs.txt\")) == \"some logs!!!\"\n"
  },
  {
    "path": "test/integration/metadata/test_metadata_test_package.py",
    "content": "import os\nimport shutil\nimport textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import save\n\n\nclass TestMetadataTestPackage:\n    \"\"\" It is possible to store the test_package itself in the recipe metadata and recover it\n    later to execute it\n    \"\"\"\n\n    def test_round_trip_with_hook(self):\n        c = TestClient(default_server_user=True)\n        # TODO: Better strategy for storing clean test_package, zipping it, etc\n        my_hook = textwrap.dedent(\"\"\"\\\n            import os\n            from conan.tools.files import copy\n\n            def post_export(conanfile):\n               conanfile.output.info(\"Storing test_package\")\n               folder = os.path.join(conanfile.recipe_folder, \"test_package\")\n               copy(conanfile, \"*\", src=folder,\n                    dst=os.path.join(conanfile.recipe_metadata_folder, \"test_package\"))\n            \"\"\")\n        hook_path = os.path.join(c.paths.hooks_path, \"my_hook\", \"hook_my_hook.py\")\n        save(hook_path, my_hook)\n        c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\"),\n                \"test_package/conanfile.py\": GenConanfile().with_test(\"pass\")})\n        c.run(\"create .\")\n        assert \"Testing the package\" in c.out\n\n        # Now upload and remove everything\n        c.run(\"upload * -c -r=default\")\n        assert \"pkg/0.1: Recipe metadata: 1 files\" in c.out\n        c.run(\"remove * -c\")\n\n        c.run(\"install --requires=pkg/0.1 -r=default\")\n        # Recovery of the test package\n        # TODO: Discuss if we want better UX, in a single step or something like that\n        # Forcing the download of the metadata of cache-existing things with the \"download\" command\n        c.run(\"download pkg/0.1 -r=default --metadata=test_package*\")\n        c.run(\"cache path pkg/0.1 --folder=metadata\")\n        metadata_path = str(c.stdout).strip()\n        shutil.copytree(metadata_path, os.path.join(c.current_folder, \"metadata\"))\n\n        # Execute the test_package\n        c.run(\"test metadata/test_package pkg/0.1\")\n        assert \"pkg/0.1 (test package): Running test()\" in c.out\n"
  },
  {
    "path": "test/integration/options/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/options/options_test.py",
    "content": "import textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient, GenConanfile\n\n\nclass TestOptions:\n\n    def test_general_scope_options_test_package(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                options = {\"shared\": [\"1\", \"2\"]}\n                def configure(self):\n                    self.output.info(\"BUILD SHARED: %s\" % self.options.shared)\n            \"\"\")\n        test = GenConanfile().with_test(\"pass\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --name=pkg --version=0.1 --user=user --channel=testing -o *:shared=1\")\n        assert \"pkg/0.1@user/testing: BUILD SHARED: 1\" in client.out\n        client.run(\"create . --name=pkg --version=0.1 --user=user --channel=testing -o shared=2\")\n        assert 'legacy: Unscoped option definition is ambiguous' in client.out\n        assert \"pkg/0.1@user/testing: BUILD SHARED: 2\" in client.out\n        # With test_package\n        client.save({\"conanfile.py\": conanfile,\n                     \"test_package/conanfile.py\": test})\n        client.run(\"create . --name=pkg --version=0.1 --user=user --channel=testing -o *:shared=1\")\n        assert \"pkg/0.1@user/testing: BUILD SHARED: 1\" in client.out\n        client.run(\"create . --name=pkg --version=0.1 --user=user --channel=testing -o pkg*:shared=2\")\n        assert \"pkg/0.1@user/testing: BUILD SHARED: 2\" in client.out\n        client.run(\"create . --name=pkg --version=0.1 --user=user --channel=testing -o shared=1\")\n        assert \"pkg/0.1@user/testing: BUILD SHARED: 1\" in client.out\n\n    def test_general_scope_options_test_package_notdefined(self):\n        client = TestClient()\n        conanfile = GenConanfile()\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --name=pkg --version=0.1 --user=user --channel=testing -o *:shared=True\")\n        assert \"pkg/0.1@user/testing: Forced build from source\" in client.out\n        client.run(\"create . --name=pkg --version=0.1 --user=user --channel=testing -o shared=False\", assert_error=True)\n        assert \"option 'shared' doesn't exist\" in client.out\n        # With test_package\n        client.save({\"conanfile.py\": conanfile,\n                     \"test_package/conanfile.py\": GenConanfile().with_test(\"pass\")})\n        client.run(\"create . --name=pkg --version=0.1 --user=user --channel=testing -o *:shared=True\")\n        assert \"pkg/0.1@user/testing: Forced build from source\" in client.out\n        assert \"Testing the package: Building\" in client.out\n\n    def test_general_scope_priorities(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                options = {\"shared\": [\"1\", \"2\", \"3\"], \"other\": [4, 5, 6]}\n                def configure(self):\n                    self.output.info(\"BUILD SHARED: %s OTHER: %s\"\n                                     % (self.options.shared, self.options.other))\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        # Consumer has priority\n        client.run(\"create . --name=pkg --version=0.1 -o *:shared=1 -o shared=2 -o p*:other=4\")\n        assert \"pkg/0.1: BUILD SHARED: 2 OTHER: 4\" in client.out\n        # Consumer has priority over pattern, even if the pattern specifies the package name\n        client.run(\"create . --name=pkg --version=0.1 -o *:shared=1 -o pkg/*:shared=2 -o shared=3 -o p*:other=4\")\n        assert \"pkg/0.1: BUILD SHARED: 3 OTHER: 4\" in client.out\n        client.run(\"create . --name=pkg --version=0.1 -o pkg/0.1:shared=2 -o p*:other=4 -o pk*:other=5\")\n        assert \"pkg/0.1: BUILD SHARED: 2 OTHER: 5\" in client.out\n\n        # With test_package\n        client.save({\"conanfile.py\": conanfile,\n                     \"test_package/conanfile.py\": GenConanfile().with_test(\"pass\")})\n        # Sorted (longest, alphabetical) patterns, have priority\n        client.run(\"create . --name=pkg --version=0.1 -o *:shared=1 -o pkg/0.1:shared=2 -o other=4\")\n        assert \"pkg/0.1: BUILD SHARED: 2 OTHER: 4\" in client.out\n        client.run(\"create . --name=pkg --version=0.1 -o pk*:shared=2 -o p*:shared=1 -o pkg/0.1:other=5\")\n        assert \"pkg/0.1: BUILD SHARED: 1 OTHER: 5\" in client.out\n        client.run(\"create . --name=pkg --version=0.1 -o pk*:shared=2 -o p*:shared=1 -o pkg/0.1:other=5 -o *g*:other=6\")\n        assert \"pkg/0.1: BUILD SHARED: 1 OTHER: 6\" in client.out\n\n    def test_parsing(self):\n        client = TestClient()\n        conanfile = '''\nfrom conan import ConanFile\nclass EqualerrorConan(ConanFile):\n    name = \"equal\"\n    version = \"1.0.0\"\n    options = {\"opt\": [\"ANY\"]}\n    default_options = {\"opt\": \"b=c\"}\n\n    def build(self):\n        self.output.warning(\"OPTION %s\" % self.options.opt)\n'''\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"export . --user=user --channel=testing\")\n        conanfile = '''\n[requires]\nequal/1.0.0@user/testing\n[options]\nequal/1.0.0@user/testing:opt=a=b\n'''\n        client.save({\"conanfile.txt\": conanfile}, clean_first=True)\n        client.run(\"install . --build=missing\")\n        assert \"OPTION a=b\" in client.out\n\n    def test_general_scope_options(self):\n        # https://github.com/conan-io/conan/issues/2538\n        client = TestClient()\n        conanfile_liba = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class LibA(ConanFile):\n                options = {\"shared\": [True, False]}\n\n                def configure(self):\n                    self.output.info(\"shared=%s\" % self.options.shared)\n                \"\"\")\n        client.save({\"conanfile.py\": conanfile_liba})\n        client.run(\"create . --name=liba --version=0.1 --user=danimtb --channel=testing -o *:shared=True\")\n        assert \"liba/0.1@danimtb/testing: shared=True\" in client.out\n\n        conanfile_libb = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class LibB(ConanFile):\n                options = {\"shared\": [True, False]}\n                requires = \"liba/0.1@danimtb/testing\"\n\n                def configure(self):\n                    self.options[\"*\"].shared = self.options.shared\n                    self.output.info(\"shared=%s\" % self.options.shared)\n                \"\"\")\n\n        for without_configure_line in [True, False]:\n            if without_configure_line:\n                conanfile = conanfile_libb.replace(\"self.options[\", \"#\")\n            else:\n                conanfile = conanfile_libb\n            client.save({\"conanfile.py\": conanfile})\n\n            # Test info\n            client.run(\"graph info . -o *:shared=True\")\n            assert \"conanfile.py: shared=True\" in client.out\n            assert \"liba/0.1@danimtb/testing: shared=True\" in client.out\n            # Test create\n            client.run(\"create . --name=libb --version=0.1 --user=danimtb --channel=testing -o *:shared=True\")\n            assert \"libb/0.1@danimtb/testing: shared=True\" in client.out\n            assert \"liba/0.1@danimtb/testing: shared=True\" in client.out\n            # Test install\n            client.run(\"install . -o *:shared=True\")\n            assert \"conanfile.py: shared=True\" in client.out\n            assert \"liba/0.1@danimtb/testing: shared=True\" in client.out\n\n    def test_define_nested_option_not_freeze(self):\n        c = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                options = {\"without_stacktrace\": [True, False],\n                           \"with_stacktrace_backtrace\": [True, False]}\n                default_options = {\"without_stacktrace\": True}\n                def configure(self):\n                    if self.options.without_stacktrace:\n                        del self.options.with_stacktrace_backtrace\n                    else:\n                        self.options.with_stacktrace_backtrace = True\n\n                def build(self):\n                    s = self.options.without_stacktrace\n                    self.output.info(\"without_stacktrace: {}\".format(s))\n\n                    if \"with_stacktrace_backtrace\" in self.options:\n                        ss = self.options.get_safe(\"with_stacktrace_backtrace\")\n                        self.output.info(\"with_stacktrace_backtrace: {}\".format(ss))\n                    else:\n                        self.output.info(\"with_stacktrace_backtrace success deleted!\")\n            \"\"\")\n        c.save({\"conanfile.py\": conanfile})\n        c.run(\"create . --name=pkg --version=0.1\")\n        assert \"pkg/0.1: without_stacktrace: True\" in c.out\n        assert \"pkg/0.1: with_stacktrace_backtrace success deleted!\" in c.out\n        c.run(\"create . --name=pkg --version=0.1 -o pkg*:without_stacktrace=False\")\n        assert \"pkg/0.1: without_stacktrace: False\" in c.out\n        assert \"pkg/0.1: with_stacktrace_backtrace: True\" in c.out\n\n    def test_del_options_configure(self):\n        \"\"\"\n        this test was failing because Options was protecting against removal of options with\n        already assigned values. This has been relaxed, to make possible this case\n        \"\"\"\n        c = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                options = {\n                    \"shared\": [True, False],\n                    \"fPIC\": [True, False],\n                }\n                default_options = {\n                    \"shared\": False,\n                    \"fPIC\": True,\n                }\n                def configure(self):\n                    if self.options.shared:\n                        del self.options.fPIC\n            \"\"\")\n        c.save({\"conanfile.py\": conanfile})\n        c.run(\"create . --name=pkg --version=0.1\")\n        c.save({\"conanfile.py\": GenConanfile(\"consumer\", \"1.0\").with_requirement(\"pkg/0.1\")},\n               clean_first=True)\n        c.run(\"install . -o pkg*:shared=True --build=missing\")\n        assert \"pkg/0.1\" in c.out  # Real test is the above doesn't crash\n\n    def test_any(self):\n        c = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class EqualerrorConan(ConanFile):\n                name = \"equal\"\n                version = \"1.0.0\"\n                options = {\"opt\": \"ANY\"}\n                default_options = {\"opt\": \"b=c\"}\n\n                def generate(self):\n                    self.output.warning(\"OPTION %s\" % self.options.opt)\n            \"\"\")\n        c.save({\"conanfile.py\": conanfile})\n        c.run(\"install .\", assert_error=True)\n        assert \"Error while initializing options. 'b=c' is not a valid 'options.opt' value.\" in c.out\n        assert \"Possible values are ['A', 'N', 'Y']\" in c.out\n\n\nclass TestOptionsPriorities:\n    # https://github.com/conan-io/conan/issues/11571\n\n    @pytest.fixture\n    def _client(self):\n        lib1 = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class Lib1Conan(ConanFile):\n                name = \"lib1\"\n                version = \"1.0\"\n                options = {\"foobar\": [True, False]}\n                default_options = {\"foobar\": False}\n            \"\"\")\n        lib2 = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class Lib2Conan(ConanFile):\n                name = \"lib2\"\n                version = \"1.0\"\n                options = {\"logic_for_foobar\": [True, False]}\n                default_options = {\"logic_for_foobar\": False}\n\n                def requirements(self):\n                    self.requires(\"lib1/1.0\")\n\n                def configure(self):\n                    self.options[\"lib1/*\"].foobar = self.options.logic_for_foobar\n            \"\"\")\n        c = TestClient()\n\n        c.save({\"lib1/conanfile.py\": lib1,\n                \"lib2/conanfile.py\": lib2})\n\n        c.run(\"create lib1 -o lib1/*:foobar=True\")\n        c.run(\"create lib1 -o lib1/*:foobar=False\")\n        c.run(\"create lib2 -o lib2/*:logic_for_foobar=True\")\n        c.run(\"create lib2 -o lib2/*:logic_for_foobar=False\")\n        return c\n\n    @staticmethod\n    def _app(lib1, lib2, configure):\n        app = textwrap.dedent(\"\"\"\n           from conan import ConanFile\n\n           class App(ConanFile):\n\n              def requirements(self):\n                  self.requires(\"{}/1.0\")\n                  self.requires(\"{}/1.0\")\n\n              def {}(self):\n                  self.options[\"lib2/*\"].logic_for_foobar = True\n                  self.options[\"lib1/*\"].foobar = False\n\n              def generate(self):\n                  self.output.info(\"LIB1 FOOBAR: {{}}\".format(\n                                                 self.dependencies[\"lib1\"].options.foobar))\n                  self.output.info(\"LIB2 LOGIC: {{}}\".format(\n                                              self.dependencies[\"lib2\"].options.logic_for_foobar))\n           \"\"\")\n        return app.format(lib1, lib2, configure)\n\n    def test_profile_priority(self, _client):\n        c = _client\n        c.save({\"app/conanfile.py\": self._app(\"lib1\", \"lib2\", \"not_configure\")})\n        # This order works, because lib1 is expanded first, it takes foobar=False\n        c.run(\"install app -o lib2*:logic_for_foobar=True -o lib1*:foobar=False\")\n        assert \"conanfile.py: LIB1 FOOBAR: False\" in c.out\n        assert \"conanfile.py: LIB2 LOGIC: True\" in c.out\n\n        # Now swap order\n        c.save({\"app/conanfile.py\": self._app(\"lib2\", \"lib1\", \"not_configure\")})\n        c.run(\"install app -o lib2*:logic_for_foobar=True -o lib1*:foobar=False\")\n        assert \"conanfile.py: LIB1 FOOBAR: False\" in c.out\n        assert \"conanfile.py: LIB2 LOGIC: True\" in c.out\n\n    def test_lib1_priority(self, _client):\n        c = _client\n        c.save({\"app/conanfile.py\": self._app(\"lib1\", \"lib2\", \"not_configure\")})\n        # This order works, because lib1 is expanded first, it takes foobar=False\n        c.run(\"install app\")\n        assert \"conanfile.py: LIB1 FOOBAR: False\" in c.out\n        assert \"conanfile.py: LIB2 LOGIC: False\" in c.out\n        c.run(\"install app -o lib1*:foobar=True\")\n        assert \"conanfile.py: LIB1 FOOBAR: True\" in c.out\n        assert \"conanfile.py: LIB2 LOGIC: False\" in c.out\n        c.run(\"install app -o lib2*:logic_for_foobar=True\")\n        assert \"conanfile.py: LIB1 FOOBAR: False\" in c.out\n        assert \"conanfile.py: LIB2 LOGIC: True\" in c.out\n\n    def test_lib2_priority(self, _client):\n        c = _client\n        c.save({\"app/conanfile.py\": self._app(\"lib2\", \"lib1\", \"not_configure\")})\n        # This order works, because lib1 is expanded first, it takes foobar=False\n        c.run(\"install app\")\n        assert \"conanfile.py: LIB1 FOOBAR: False\" in c.out\n        assert \"conanfile.py: LIB2 LOGIC: False\" in c.out\n        c.run(\"install app -o lib1*:foobar=True\")\n        assert \"conanfile.py: LIB1 FOOBAR: True\" in c.out\n        assert \"conanfile.py: LIB2 LOGIC: False\" in c.out\n        c.run(\"install app -o lib2*:logic_for_foobar=True\")\n        assert \"conanfile.py: LIB1 FOOBAR: True\" in c.out\n        assert \"conanfile.py: LIB2 LOGIC: True\" in c.out\n\n    def test_consumer_configure_priority(self, _client):\n        c = _client\n        c.save({\"app/conanfile.py\": self._app(\"lib1\", \"lib2\", \"configure\")})\n        c.run(\"install app\")\n        assert \"conanfile.py: LIB1 FOOBAR: False\" in c.out\n        assert \"conanfile.py: LIB2 LOGIC: True\" in c.out\n\n        # Now swap order\n        c.save({\"app/conanfile.py\": self._app(\"lib1\", \"lib2\", \"configure\")})\n        c.run(\"install app\")\n        assert \"conanfile.py: LIB1 FOOBAR: False\" in c.out\n        assert \"conanfile.py: LIB2 LOGIC: True\" in c.out\n\n\ndef test_configurable_default_options():\n    # https://github.com/conan-io/conan/issues/11487\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            settings = \"os\"\n            options = {\"backend\": [1, 2, 3]}\n            def config_options(self):\n                if self.settings.os == \"Windows\":\n                    self.options.backend = 2\n                else:\n                    self.options.backend = 3\n            def package_info(self):\n                self.output.info(\"Package with option:{}!\".format(self.options.backend))\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"create . -s os=Windows\")\n    assert \"pkg/0.1: Package with option:2!\" in c.out\n    c.run(\"create . -s os=Windows -o pkg*:backend=3\")\n    assert \"pkg/0.1: Package with option:3!\" in c.out\n    c.run(\"create . -s os=Linux\")\n    assert \"pkg/0.1: Package with option:3!\" in c.out\n    c.run(\"create . -s os=Windows -o pkg*:backend=1\")\n    assert \"pkg/0.1: Package with option:1!\" in c.out\n\n    consumer = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"consumer\"\n            version = \"0.1\"\n            requires = \"pkg/0.1\"\n            def configure(self):\n                self.options[\"pkg*\"].backend = 1\n        \"\"\")\n    c.save({\"conanfile.py\": consumer})\n    c.run(\"install . -s os=Windows\")\n    assert \"pkg/0.1: Package with option:1!\" in c.out\n    c.run(\"create . -s os=Windows\")\n    assert \"pkg/0.1: Package with option:1!\" in c.out\n\n    # This fails in Conan 1.X\n    c.run(\"create . -s os=Windows -o pkg*:backend=3\")\n    assert \"pkg/0.1: Package with option:3!\" in c.out\n\n\nclass TestMultipleOptionsPatterns:\n    \"\"\"\n    https://github.com/conan-io/conan/issues/13240\n    \"\"\"\n\n    dep = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n           version = \"1.0\"\n           options = {\"shared\": [True, False]}\n           default_options = {\"shared\": False}\n           def package_info(self):\n               self.output.info(f\"SHARED: {self.options.shared}!!\")\n        \"\"\")\n\n    def test_multiple_options_patterns_cli(self):\n        \"\"\"\n        https://github.com/conan-io/conan/issues/13240\n        \"\"\"\n        c = TestClient()\n        consumer = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n              settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n\n              def requirements(self):\n                  self.requires(\"dep1/1.0\")\n                  self.requires(\"dep2/1.0\")\n                  self.requires(\"dep3/1.0\")\n                  self.requires(\"dep4/1.0\")\n            \"\"\")\n        c.save({\"dep/conanfile.py\": self.dep,\n                \"pkg/conanfile.py\": consumer})\n        for d in (1, 2, 3, 4):\n            c.run(f\"export dep --name dep{d}\")\n\n        # match in order left to right\n        c.run('install pkg -o *:shared=True -o dep1*:shared=False -o dep2*:shared=False -b missing')\n        assert \"dep1/1.0: SHARED: False!!\" in c.out\n        assert \"dep2/1.0: SHARED: False!!\" in c.out\n        assert \"dep3/1.0: SHARED: True!!\" in c.out\n        assert \"dep4/1.0: SHARED: True!!\" in c.out\n\n        # All match in order, left to right\n        c.run('install pkg -o dep1*:shared=False -o dep2*:shared=False -o *:shared=True -b missing')\n        assert \"dep1/1.0: SHARED: True!!\" in c.out\n        assert \"dep2/1.0: SHARED: True!!\" in c.out\n        assert \"dep3/1.0: SHARED: True!!\" in c.out\n        assert \"dep4/1.0: SHARED: True!!\" in c.out\n\n    def test_multiple_options_patterns(self):\n        c = TestClient()\n        configure_consumer = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n\n                def requirements(self):\n                    self.requires(\"dep1/1.0\")\n                    self.requires(\"dep2/1.0\")\n                    self.requires(\"dep3/1.0\")\n                    self.requires(\"dep4/1.0\")\n\n                def configure(self):\n                    self.options[\"*\"].shared = True\n                    # Without * also works, equivalent to dep1/*\n                    self.options[\"dep1\"].shared = False\n                    self.options[\"dep2*\"].shared = False\n            \"\"\")\n        c.save({\"dep/conanfile.py\": self.dep,\n                \"pkg/conanfile.py\": configure_consumer})\n        for d in (1, 2, 3, 4):\n            c.run(f\"export dep --name dep{d}\")\n\n        c.run(\"install pkg --build=missing\")\n        assert \"dep1/1.0: SHARED: False!!\" in c.out\n        assert \"dep2/1.0: SHARED: False!!\" in c.out\n        assert \"dep3/1.0: SHARED: True!!\" in c.out\n        assert \"dep4/1.0: SHARED: True!!\" in c.out\n\n    def test_multiple_options_patterns_order(self):\n        c = TestClient()\n        configure_consumer = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n\n                def requirements(self):\n                    self.requires(\"dep1/1.0\")\n                    self.requires(\"dep2/1.0\")\n                    self.requires(\"dep3/1.0\")\n                    self.requires(\"dep4/1.0\")\n\n                def configure(self):\n                    self.options[\"dep1*\"].shared = False\n                    self.options[\"dep2*\"].shared = False\n                    self.options[\"*\"].shared = True\n            \"\"\")\n        c.save({\"dep/conanfile.py\": self.dep,\n                \"pkg/conanfile.py\": configure_consumer})\n        for d in (1, 2, 3, 4):\n            c.run(f\"export dep --name dep{d}\")\n\n        c.run(\"install pkg --build=missing\")\n        assert \"dep1/1.0: SHARED: True!!\" in c.out\n        assert \"dep2/1.0: SHARED: True!!\" in c.out\n        assert \"dep3/1.0: SHARED: True!!\" in c.out\n        assert \"dep4/1.0: SHARED: True!!\" in c.out\n\n    def test_pattern_version_range_warn(self):\n        c = TestClient(light=True)\n        profile = textwrap.dedent(\"\"\"\n        include(default)\n\n        [tool_requires]\n        fmt/[*]:cmake/3.31.0\n\n        [options]\n        fmt/[*]:shared=True\n\n        [settings]\n        fmt/[*]:compiler.cppstd=17\n        \"\"\")\n        c.save({\n            \"profile\": profile,\n            \"conanfile.py\": GenConanfile(\"fmt\", \"1.0\")})\n        c.run(\"create -pr=profile\")\n        assert \"WARN: risk: Settings pattern fmt/[*] contains a version range\" in c.out\n        assert \"WARN: risk: Options pattern fmt/[*] contains a version range\" in c.out\n        assert \"WARN: risk: Tool requires pattern fmt/[*] contains a version range\" in c.out\n\n    def test_pattern_version_range_wrong_split(self):\n        c = TestClient(light=True)\n        c.save({\"conanfile.py\": GenConanfile(\"foo\", \"1.0\")})\n        c.run(\"create -o=foo/[>=1]:shared=True\", assert_error=True)\n        # We split by the first =, so this version range we can't catch and warn before it breaks\n        assert \"option 'foo/[>' doesn't exist\" in c.out\n\n\nclass TestTransitiveOptionsShared:\n    \"\"\"\n    https://github.com/conan-io/conan/issues/13854\n    \"\"\"\n    @pytest.fixture()\n    def client(self):\n        c = TestClient()\n        c.save({\"toollib/conanfile.py\": GenConanfile(\"toollib\", \"0.1\").with_shared_option(False),\n                \"tool/conanfile.py\": GenConanfile(\"tool\", \"0.1\").with_shared_option(False)\n                                                                .with_requires(\"toollib/0.1\"),\n                \"dep2/conanfile.py\": GenConanfile(\"dep2\", \"0.1\").with_shared_option(False)\n                                                                .with_tool_requires(\"tool/0.1\"),\n                \"dep1/conanfile.py\": GenConanfile(\"dep1\", \"0.1\").with_shared_option(False)\n                                                                .with_requires(\"dep2/0.1\"),\n                \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_shared_option(False)\n                                                              .with_requires(\"dep1/0.1\"),\n                \"app/conanfile.txt\": \"[requires]\\npkg/0.1\"})\n        c.run(\"export toollib\")\n        c.run(\"export tool\")\n        c.run(\"export dep2\")\n        c.run(\"export dep1\")\n        c.run(\"export pkg\")\n        return c\n\n    @staticmethod\n    def check(client):\n        # tools and libs in build context do not get propagated the options\n        for dep in (\"toollib\", \"tool\"):\n            client.run(f\"list {dep}/*:*\")\n            assert \"shared: False\" in client.out\n        # But the whole host context does\n        for dep in (\"dep1\", \"dep2\", \"pkg\"):\n            client.run(f\"list {dep}/*:*\")\n            assert \"shared: True\" in client.out\n\n    def test_transitive_options_shared_cli(self, client):\n        client.run(\"install app --build=missing -o *:shared=True\")\n        self.check(client)\n\n    def test_transitive_options_shared_profile(self, client):\n        client.save({\"profile\": \"[options]\\n*:shared=True\"})\n        client.run(\"install app --build=missing -pr=profile\")\n        self.check(client)\n\n    def test_transitive_options_conanfile_txt(self, client):\n        client.save({\"app/conanfile.txt\": \"[requires]\\npkg/0.1\\n[options]\\n*:shared=True\\n\"})\n        client.run(\"install app --build=missing\")\n        self.check(client)\n\n    def test_transitive_options_conanfile_py(self, client):\n        client.save({\"app/conanfile.py\": GenConanfile().with_requires(\"pkg/0.1\")\n                                                       .with_default_option(\"*:shared\", True)})\n        client.run(\"install app/conanfile.py --build=missing\")\n        self.check(client)\n\n    def test_transitive_options_conanfile_py_create(self, client):\n        conanfile = GenConanfile(\"app\", \"0.1\").with_requires(\"pkg/0.1\") \\\n                                              .with_default_option(\"*:shared\", True)\n        client.save({\"app/conanfile.py\": conanfile})\n        client.run(\"create app --build=missing\")\n        self.check(client)\n\n\ndef test_options_no_user_channel_patterns():\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\\\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            options = {\"myoption\": [1, 2, 3]}\n            def configure(self):\n                self.output.info(f\"MYOPTION: {self.options.myoption}\")\n            \"\"\")\n    c.save({\"dep/conanfile.py\": conanfile,\n            \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_requires(\"dep1/0.1\", \"dep2/0.1@user\",\n                                                                         \"dep3/0.1@user/channel\")})\n    c.run(\"export dep --name=dep1 --version=0.1\")\n    c.run(\"export dep --name=dep2 --version=0.1 --user=user\")\n    c.run(\"export dep --name=dep3 --version=0.1 --user=user --channel=channel\")\n\n    c.run(\"graph info pkg -o *:myoption=3 -o *@:myoption=1\")\n    assert \"dep1/0.1: MYOPTION: 1\" in c.out\n    assert \"dep2/0.1@user: MYOPTION: 3\" in c.out\n    assert \"dep3/0.1@user/channel: MYOPTION: 3\" in c.out\n\n    # Recall that order is also important latest matching pattern wins\n    c.run(\"graph info pkg -o *@:myoption=1 -o *:myoption=1\")\n    assert \"dep1/0.1: MYOPTION: 1\" in c.out\n    assert \"dep2/0.1@user: MYOPTION: 1\" in c.out\n    assert \"dep3/0.1@user/channel: MYOPTION: 1\" in c.out\n\n    # This is a bit weird negation approach, but it works = all packages that have user channel\n    c.run(\"graph info pkg -o *:myoption=3 -o ~*@:myoption=1\")\n    assert \"dep1/0.1: MYOPTION: 3\" in c.out\n    assert \"dep2/0.1@user: MYOPTION: 1\" in c.out\n    assert \"dep3/0.1@user/channel: MYOPTION: 1\" in c.out\n\n    # Which is identical to '~*@' == '*@*'\n    c.run(\"graph info pkg -o *:myoption=3 -o *@*:myoption=1\")\n    assert \"dep1/0.1: MYOPTION: 3\" in c.out\n    assert \"dep2/0.1@user: MYOPTION: 1\" in c.out\n    assert \"dep3/0.1@user/channel: MYOPTION: 1\" in c.out\n\n\ndef test_package_options_negate_patterns():\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Dep(ConanFile):\n            version = \"0.1\"\n            options = {\"myoption\": [1, 2, 3]}\n            def build(self):\n                self.output.info(f\"MYOPTION={self.options.myoption}!!!\")\n            \"\"\")\n    c.save({\"dep/conanfile.py\": conanfile,\n            \"pkg/conanfile.py\": GenConanfile().with_requires(\"dep1/0.1\", \"dep2/0.1\", \"dep3/0.1\")})\n    c.run(\"export dep --name=dep1\")\n    c.run(\"export dep --name=dep2\")\n    c.run(\"export dep --name=dep3\")\n\n    c.run(\"install pkg --build=* -o *:myoption=1 -o ~dep1/*:myoption=2\")\n    assert \"dep1/0.1: MYOPTION=1!!!\" in c.out\n    assert \"dep2/0.1: MYOPTION=2!!!\" in c.out\n    assert \"dep3/0.1: MYOPTION=2!!!\" in c.out\n\n    # Order does matter for options with *:myoption patter, evaluates last\n    c.run(\"install pkg --build=* -o ~dep1/*:myoption=2 -o *:myoption=1\")\n    assert \"dep1/0.1: MYOPTION=1!!!\" in c.out\n    assert \"dep2/0.1: MYOPTION=1!!!\" in c.out\n    assert \"dep3/0.1: MYOPTION=1!!!\" in c.out\n\n    # dep3 comes later, works\n    c.run(\"install pkg --build=* -o *:myoption=1 -o ~dep1/*:myoption=2 -o dep3/*:myoption=3\")\n    assert \"dep1/0.1: MYOPTION=1!!!\" in c.out\n    assert \"dep2/0.1: MYOPTION=2!!!\" in c.out\n    assert \"dep3/0.1: MYOPTION=3!!!\" in c.out\n\n    # dep3 comes first, then last !dep1 pattern prevails\n    c.run(\"install pkg --build=* -o *:myoption=1 -o dep3/*:myoption=3 -o ~dep1/*:myoption=2\")\n    assert \"dep1/0.1: MYOPTION=1!!!\" in c.out\n    assert \"dep2/0.1: MYOPTION=2!!!\" in c.out\n    assert \"dep3/0.1: MYOPTION=2!!!\" in c.out\n\n\nclass TestTransitiveOptionsSharedInvisible:\n    \"\"\"\n    https://github.com/conan-io/conan/issues/13854\n    When a requirement is visible=False\n    \"\"\"\n    @pytest.fixture()\n    def client(self):\n        c = TestClient()\n        c.save({\"dep2/conanfile.py\": GenConanfile(\"dep2\", \"0.1\").with_shared_option(False),\n                \"dep1/conanfile.py\": GenConanfile(\"dep1\", \"0.1\").with_shared_option(False)\n                                                                .with_requirement(\"dep2/0.1\",\n                                                                                  visible=False),\n                \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_shared_option(False)\n                                                              .with_requires(\"dep1/0.1\"),\n                \"app/conanfile.txt\": \"[requires]\\npkg/0.1\"})\n        c.run(\"export dep2\")\n        c.run(\"export dep1\")\n        c.run(\"export pkg\")\n        return c\n\n    @staticmethod\n    def check(client, value):\n        for dep in (\"dep1\", \"pkg\"):\n            client.run(f\"list {dep}/*:*\")\n            assert f\"shared: True\" in client.out\n\n        # dep2 cannot be affected from downstream conanfile consumers options, only from profile\n        client.run(f\"list dep2/*:*\")\n        assert f\"shared: {value}\" in client.out\n\n    def test_transitive_options_shared_cli(self, client):\n        client.run(\"install app --build=missing -o *:shared=True\")\n        self.check(client, True)\n\n    def test_transitive_options_shared_profile(self, client):\n        client.save({\"profile\": \"[options]\\n*:shared=True\"})\n        client.run(\"install app --build=missing -pr=profile\")\n        self.check(client, True)\n\n    def test_transitive_options_conanfile_txt(self, client):\n        client.save({\"app/conanfile.txt\": \"[requires]\\npkg/0.1\\n[options]\\n*:shared=True\\n\"})\n        client.run(\"install app --build=missing\")\n        self.check(client, False)\n\n    def test_transitive_options_conanfile_py(self, client):\n        client.save({\"app/conanfile.py\": GenConanfile().with_requires(\"pkg/0.1\")\n                                                       .with_default_option(\"*:shared\", True)})\n        client.run(\"install app/conanfile.py --build=missing\")\n        self.check(client, False)\n\n    def test_transitive_options_conanfile_py_create(self, client):\n        conanfile = GenConanfile(\"app\", \"0.1\").with_requires(\"pkg/0.1\") \\\n                                              .with_default_option(\"*:shared\", True)\n        client.save({\"app/conanfile.py\": conanfile})\n        client.run(\"create app --build=missing\")\n        self.check(client, False)\n\n\nclass TestImportantOptions:\n    @pytest.mark.parametrize(\"pkg\", [\"liba\", \"libb\", \"app\"])\n    def test_important_options(self, pkg):\n        c = TestClient()\n\n        liba = GenConanfile(\"liba\", \"0.1\").with_option(\"myoption\", [1, 2, 3])\n        libb = GenConanfile(\"libb\", \"0.1\").with_requires(\"liba/0.1\")\n        app = GenConanfile().with_requires(\"libb/0.1\")\n        if pkg == \"liba\":\n            liba.with_default_option(\"myoption!\", 2)\n        elif pkg == \"libb\":\n            libb.with_default_option(\"*:myoption!\", 2)\n        elif pkg == \"app\":\n            app.with_default_option(\"*:myoption!\", 2)\n        package_id = textwrap.dedent(\"\"\"\n            def package_id(self):\n                self.output.info(f\"MYOPTION: {self.info.options.myoption}\")\n            \"\"\")\n        liba = str(liba) + textwrap.indent(package_id, \"    \")\n\n        c.save({\"liba/conanfile.py\": liba,\n                \"libb/conanfile.py\": libb,\n                \"app/conanfile.py\": app})\n        c.run(\"export liba\")\n        c.run(\"export libb\")\n\n        c.run(\"graph info app -o *:myoption=3\")\n        assert \"liba/0.1: MYOPTION: 2\" in c.out\n\n        # And the profile can always important-override the option\n        c.run(\"graph info app -o *:myoption!=3\")\n        assert \"liba/0.1: MYOPTION: 3\" in c.out\n\n    def test_profile_shows_important(self):\n        c = TestClient()\n        c.run(\"profile show  -o *:myoption!=3\")\n        assert \"*:myoption!=3\" in c.out\n\n    def test_important_options_recipe_priority(self):\n        c = TestClient()\n\n        liba = GenConanfile(\"liba\", \"0.1\").with_option(\"myoption\", [1, 2, 3, 4])\\\n                                          .with_default_option(\"myoption!\", 1)\n        libb = GenConanfile(\"libb\", \"0.1\").with_requires(\"liba/0.1\")\\\n                                          .with_default_option(\"*:myoption!\", 2)\n        app = GenConanfile().with_requires(\"libb/0.1\").with_default_option(\"*:myoption!\", 3)\n\n        package_id = textwrap.dedent(\"\"\"\n            def package_id(self):\n                self.output.info(f\"MYOPTION: {self.info.options.myoption}\")\n            \"\"\")\n        liba = str(liba) + textwrap.indent(package_id, \"    \")\n\n        c.save({\"liba/conanfile.py\": liba,\n                \"libb/conanfile.py\": libb,\n                \"app/conanfile.py\": app})\n        c.run(\"export liba\")\n        c.run(\"export libb\")\n\n        c.run(\"graph info app\")\n        assert \"liba/0.1: MYOPTION: 3\" in c.out\n\n        c.run(\"graph info app -o *:myoption!=4\")\n        assert \"liba/0.1: MYOPTION: 4\" in c.out\n\n    def test_important_options_recipe_priority_conditional(self):\n        c = TestClient()\n\n        liba = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Lib(ConanFile):\n                name = \"liba\"\n                version = \"0.1\"\n                settings = \"os\"\n                options = {\"myoption\": [1, 2, 3]}\n\n                def config_options(self):\n                    if self.settings.os == \"Windows\":\n                        setattr(self.options, \"myoption!\", 2)\n\n                def package_id(self):\n                    self.output.info(f\"MYOPTION: {self.info.options.myoption}\")\n            \"\"\")\n\n        c.save({\"liba/conanfile.py\": liba,\n                \"app/conanfile.py\": GenConanfile().with_requires(\"liba/0.1\")})\n        c.run(\"export liba\")\n\n        c.run(\"graph info app -s os=Linux -o *:myoption=3\")\n        assert \"liba/0.1: MYOPTION: 3\" in c.out\n        c.run(\"graph info app -s os=Linux -o *:myoption=2\")\n        assert \"liba/0.1: MYOPTION: 2\" in c.out\n        c.run(\"graph info app -s os=Linux -o *:myoption=1\")\n        assert \"liba/0.1: MYOPTION: 1\" in c.out\n\n        c.run(\"graph info app -s os=Windows -o *:myoption=3\")\n        assert \"liba/0.1: MYOPTION: 2\" in c.out\n        c.run(\"graph info app -s os=Windows -o *:myoption=2\")\n        assert \"liba/0.1: MYOPTION: 2\" in c.out\n        c.run(\"graph info app -s os=Windows -o *:myoption=1\")\n        assert \"liba/0.1: MYOPTION: 2\" in c.out\n\n    def test_wrong_option_syntax_no_trace(self):\n        tc = TestClient(light=True)\n        tc.save({\"conanfile.py\": GenConanfile().with_option(\"myoption\", [1, 2, 3])})\n        tc.run('create . -o=\"&:myoption\"', assert_error=True)\n        assert \"ValueError\" not in tc.out\n        assert \"Error while parsing option\" in tc.out\n\n\nclass TestConflictOptionsWarnings:\n\n    @pytest.mark.parametrize(\"important\", [True, False])\n    def test_options_warnings(self, important):\n        c = TestClient()\n        liba = GenConanfile(\"liba\", \"0.1\").with_option(\"myoption\", [1, 2, 3], default=1)\n        libb = GenConanfile(\"libb\", \"0.1\").with_requires(\"liba/0.1\")\n        if important:\n            libc = GenConanfile(\"libc\", \"0.1\").with_requirement(\"liba/0.1\") \\\n                                              .with_default_option(\"liba*:myoption!\", 2)\n        else:\n            libc = GenConanfile(\"libc\", \"0.1\").with_requirement(\"liba/0.1\", options={\"myoption\": 2})\n        app = GenConanfile().with_requires(\"libb/0.1\", \"libc/0.1\")\n\n        c.save({\"liba/conanfile.py\": liba,\n                \"libb/conanfile.py\": libb,\n                \"libc/conanfile.py\": libc,\n                \"app/conanfile.py\": app})\n        c.run(\"export liba\")\n        c.run(\"export libb\")\n        c.run(\"export libc\")\n\n        c.run(\"graph info app\")\n        expected = textwrap.dedent(\"\"\"\\\n            Options conflicts\n                liba/0.1:myoption=1 (current value)\n                    libc/0.1->myoption=2\n                It is recommended to define options values in profiles, not in recipes\n            \"\"\")\n        assert expected in c.out\n        assert \"WARN: risk: There are options conflicts in the dependency graph\" in c.out\n\n\ndef test_get_safe_none_option_checks():\n    tc = TestClient(light=True)\n    tc.save({\"conanfile.py\": GenConanfile(\"foo\", \"1.0\")\n            .with_package(\"self.output.info(f'get_safe is None: {self.options.get_safe(\\\"myoption\\\") is None}')\",\n                          \"self.output.info(f'get_safe is not None: {self.options.get_safe(\\\"myoption\\\") is not None}')\",\n                          \"self.output.info(f'get_safe == None: {self.options.get_safe(\\\"myoption\\\") == None}')\",\n                          \"self.output.info(f'get_safe != None: {self.options.get_safe(\\\"myoption\\\") != None}')\")})\n    tc.run(\"create .\")\n    assert \"get_safe is None: True\" in tc.out\n    assert \"get_safe is not None: False\" in tc.out\n    assert \"get_safe == None: True\" in tc.out\n    assert \"get_safe != None: False\" in tc.out\n\n\ndef test_option_apply_version_range():\n    c = TestClient(light=True)\n    c.save({\"conanfile.py\": GenConanfile(\"dep\", \"0.1\").with_shared_option(False)})\n    c.run(\"create -o shared=True\")\n    c.run(\"install --requires=dep/0.1 -o shared=True\")  # This worked without problem\n    c.run(\"install --requires=dep/[*] -o shared=True\")\n    assert \"WARN: risk\" not in c.out\n    # This failed because of dep/[*] not matching pattern, now it works\n    assert \"Install finished successfully\" in c.out\n"
  },
  {
    "path": "test/integration/options/test_configure_options.py",
    "content": "import os\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestConfigureOptions:\n    \"\"\"\n    Test config_options(), configure() and package_id() methods can manage shared, fPIC and\n    header_only options automatically.\n    \"\"\"\n\n    @pytest.mark.parametrize(\"settings_os, shared, fpic, header_only, result\", [\n        [\"Linux\", False, False, False, [False, False, False]],\n        [\"Windows\", False, False, False, [False, None, False]],\n        [\"Windows\", True, False, False, [True, None, False]],\n        [\"Windows\", False, False, True, [None, None, True]],\n        [\"Linux\", False, False, True, [None, None, True]],\n        [\"Linux\", True, True, False, [True, None, False]],\n        [\"Linux\", True, False, False, [True, None, False]],\n        [\"Linux\", True, True, True, [None, None, True]],\n        [\"Linux\", True, True, True, [None, None, True]],\n        [\"Linux\", False, True, False, [False, True, False]],\n        [\"Linux\", False, True, False, [False, True, False]],\n    ])\n    def test_methods_not_defined(self, settings_os, shared, fpic, header_only, result):\n        \"\"\"\n        Test that options are managed automatically when methods config_options and configure are not\n        defined and implements = [\"auto_shared_fpic\", \"auto_header_only\"].\n        Check that header only package gets its unique package ID.\n        \"\"\"\n        client = TestClient()\n        conanfile = textwrap.dedent(f\"\"\"\\\n           from conan import ConanFile\n\n           class Pkg(ConanFile):\n               settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n               options = {{\"shared\": [True, False], \"fPIC\": [True, False], \"header_only\": [True, False]}}\n               default_options = {{\"shared\": {shared}, \"fPIC\": {fpic}, \"header_only\": {header_only}}}\n               implements = [\"auto_shared_fpic\", \"auto_header_only\"]\n\n               def build(self):\n                   shared = self.options.get_safe(\"shared\")\n                   fpic = self.options.get_safe(\"fPIC\")\n                   header_only = self.options.get_safe(\"header_only\")\n                   self.output.info(f\"shared: {{shared}}, fPIC: {{fpic}}, header only: {{header_only}}\")\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(f\"create . --name=pkg --version=0.1 -s os={settings_os}\")\n        result = f\"shared: {result[0]}, fPIC: {result[1]}, header only: {result[2]}\"\n        assert result in client.out\n        if header_only:\n            assert \"Package 'da39a3ee5e6b4b0d3255bfef95601890afd80709' created\" in client.out\n\n    @pytest.mark.parametrize(\"settings_os, shared, fpic, header_only, result\", [\n        [\"Linux\", False, False, False, [False, False, False]],\n        [\"Linux\", False, False, True, [False, False, True]],\n        [\"Linux\", False, True, False, [False, True, False]],\n        [\"Linux\", False, True, True, [False, True, True]],\n        [\"Linux\", True, False, False, [True, False, False]],\n        [\"Linux\", True, False, True, [True, False, True]],\n        [\"Linux\", True, True, False, [True, True, False]],\n        [\"Linux\", True, True, True, [True, True, True]],\n        [\"Windows\", False, False, False, [False, False, False]],\n        [\"Windows\", False, False, True, [False, False, True]],\n        [\"Windows\", False, True, False, [False, True, False]],\n        [\"Windows\", False, True, True, [False, True, True]],\n        [\"Windows\", True, False, False, [True, False, False]],\n        [\"Windows\", True, False, True, [True, False, True]],\n        [\"Windows\", True, True, False, [True, True, False]],\n        [\"Windows\", True, True, True, [True, True, True]],\n    ])\n    def test_optout(self, settings_os, shared, fpic, header_only, result):\n        \"\"\"\n        Test that options are not managed automatically when methods are defined even if implements = [\"auto_shared_fpic\", \"auto_header_only\"]\n        Check that header only package gets its unique package ID.\n        \"\"\"\n        client = TestClient()\n        conanfile = textwrap.dedent(f\"\"\"\\\n           from conan import ConanFile\n\n           class Pkg(ConanFile):\n               settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n               options = {{\"shared\": [True, False], \"fPIC\": [True, False], \"header_only\": [True, False]}}\n               default_options = {{\"shared\": {shared}, \"fPIC\": {fpic}, \"header_only\": {header_only}}}\n               implements = [\"auto_shared_fpic\", \"auto_header_only\"]\n\n               def config_options(self):\n                   pass\n\n               def configure(self):\n                   pass\n\n               def build(self):\n                   shared = self.options.get_safe(\"shared\")\n                   fpic = self.options.get_safe(\"fPIC\")\n                   header_only = self.options.get_safe(\"header_only\")\n                   self.output.info(f\"shared: {{shared}}, fPIC: {{fpic}}, header only: {{header_only}}\")\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(f\"create . --name=pkg --version=0.1 -s os={settings_os}\")\n        result = f\"shared: {result[0]}, fPIC: {result[1]}, header only: {result[2]}\"\n        assert result in client.out\n        if header_only:\n            assert \"Package 'da39a3ee5e6b4b0d3255bfef95601890afd80709' created\" in client.out\n\n    def test_header_package_type_pid(self):\n        \"\"\"\n        Test that we get the pid for header only when package type is set to header-library\n        \"\"\"\n        client = TestClient()\n        conanfile = textwrap.dedent(f\"\"\"\\\n               from conan import ConanFile\n\n               class Pkg(ConanFile):\n                   settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n                   package_type = \"header-library\"\n                   implements = [\"auto_shared_fpic\", \"auto_header_only\"]\n\n                \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(f\"create . --name=pkg --version=0.1\")\n        assert \"Package 'da39a3ee5e6b4b0d3255bfef95601890afd80709' created\" in client.out\n\n\ndef test_config_options_override_behaviour():\n    tc = TestClient(light=True)\n    tc.save({\"conanfile.py\": textwrap.dedent(\"\"\"\n    from conan import ConanFile\n\n    class Pkg(ConanFile):\n        name = \"pkg\"\n        version = \"1.0\"\n\n        options = {\"foo\": [1, 2, 3]}\n        default_options = {\"foo\": 1}\n\n        def config_options(self):\n            self.options.foo = 2\n\n        def build(self):\n            self.output.info(f\"Foo: {self.options.foo}\")\n    \"\"\")})\n\n    tc.run(\"create .\")\n    assert \"Foo: 2\" in tc.out\n\n    tc.run(\"create . -o=&:foo=3\")\n    assert \"Foo: 3\" in tc.out\n\n\ndef test_configure_transitive_option():\n    c = TestClient(light=True)\n    c.save({\"conanfile.py\": GenConanfile(\"zlib\", \"0.1\").with_shared_option(False)})\n    c.run(\"create . -o *:shared=True\")\n\n    boost = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class BoostConan(ConanFile):\n            name = \"boostdbg\"\n            version = \"1.0\"\n            options = {\"shared\": [True, False]}\n            default_options ={\"shared\": False}\n            requires = \"zlib/0.1\"\n\n            def configure(self):\n                self.options[\"zlib/*\"].shared = self.options.shared\n        \"\"\")\n\n    c.save({\"conanfile.py\": boost}, clean_first=True)\n    c.run(\"create .  -o boostdbg/*:shared=True\")\n    # It doesn't fail due to missing binary, as it assigned dependency shared=True\n    pkg_folder = c.created_layout().package()\n    conaninfo = c.load(os.path.join(pkg_folder, \"conaninfo.txt\"))\n    assert \"shared=True\" in conaninfo\n"
  },
  {
    "path": "test/integration/options/test_options_build_requires.py",
    "content": "import textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_build_requires_options_different():\n    # copied from https://github.com/conan-io/conan/pull/9839\n    # This is a test that crashed in 1.X, because of conflicting options\n    client = TestClient()\n\n    conanfile_openssl_1_1_1 = GenConanfile(\"openssl\", \"1.1.1\")\n    conanfile_openssl_3_0_0 = GenConanfile(\"openssl\", \"3.0.0\") \\\n        .with_option(\"no_fips\", [True, False]) \\\n        .with_default_option(\"no_fips\", True)\n    conanfile_cmake = GenConanfile(\"cmake\", \"0.1\") \\\n        .with_requires(\"openssl/1.1.1\")\n    conanfile_consumer = GenConanfile(\"consumer\", \"0.1\") \\\n        .with_build_requires(\"cmake/0.1\") \\\n        .with_requires(\"openssl/3.0.0\")\n\n    client.save({\"openssl_1_1_1.py\": conanfile_openssl_1_1_1,\n                 \"openssl_3_0_0.py\": conanfile_openssl_3_0_0,\n                 \"conanfile_cmake.py\": conanfile_cmake,\n                 \"conanfile.py\": conanfile_consumer})\n\n    client.run(\"create openssl_1_1_1.py\")\n    client.run(\"create openssl_3_0_0.py\")\n    client.run(\"create conanfile_cmake.py\")\n    client.run(\"install conanfile.py\")\n    # This test used to crash, not crashing means ok\n    assert \"openssl/1.1.1\" in client.out\n    assert \"openssl/3.0.0: Already installed!\" in client.out\n    assert \"cmake/0.1: Already installed!\" in client.out\n\n\ndef test_different_options_values_profile():\n    \"\"\"\n    consumer -> protobuf (library)\n        \\\\--(build)-> protobuf (protoc)\n    protobuf by default is a static library (shared=False)\n    The profile or CLI args can select for each one (library and protoc) the \"shared\" value\n    \"\"\"\n    c = TestClient()\n    protobuf = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Proto(ConanFile):\n            options = {\"shared\": [True, False]}\n            default_options = {\"shared\": False}\n\n            def package_info(self):\n                self.output.info(\"MYOPTION: {}-{}\".format(self.context, self.options.shared))\n        \"\"\")\n\n    c.save({\"protobuf/conanfile.py\": protobuf,\n            \"consumer/conanfile.py\": GenConanfile().with_requires(\"protobuf/1.0\")\n           .with_build_requires(\"protobuf/1.0\")})\n\n    c.run(\"create protobuf --name=protobuf --version=1.0\")\n    c.run(\"create protobuf --name=protobuf --version=1.0 -o protobuf/*:shared=True\")\n    c.run(\"install consumer\")\n    assert \"protobuf/1.0: MYOPTION: host-False\" in c.out\n    assert \"protobuf/1.0: MYOPTION: build-False\" in c.out\n    # specifying it in the profile works\n    c.run(\"install consumer -o protobuf/*:shared=True\")\n    assert \"protobuf/1.0: MYOPTION: host-True\" in c.out\n    assert \"protobuf/1.0: MYOPTION: build-False\" in c.out\n    c.run(\"install consumer -o protobuf/*:shared=True -o:b protobuf/*:shared=False\")\n    assert \"protobuf/1.0: MYOPTION: host-True\" in c.out\n    assert \"protobuf/1.0: MYOPTION: build-False\" in c.out\n    c.run(\"install consumer -o protobuf/*:shared=False -o:b protobuf/*:shared=True\")\n    assert \"protobuf/1.0: MYOPTION: host-False\" in c.out\n    assert \"protobuf/1.0: MYOPTION: build-True\" in c.out\n    c.run(\"install consumer -o:b protobuf/*:shared=True\")\n    assert \"protobuf/1.0: MYOPTION: host-False\" in c.out\n    assert \"protobuf/1.0: MYOPTION: build-True\" in c.out\n\n\n@pytest.mark.parametrize(\"scope\", [\"protobuf/*:\", \"\"])\ndef test_different_options_values_recipe(scope):\n    \"\"\"\n    consumer -> protobuf (library)\n        \\\\--(build)-> protobuf (protoc)\n    protobuf by default is a static library (shared=False)\n    The \"consumer\" conanfile.py can use ``self.requires(...,options=)`` to define protobuf:shared\n    \"\"\"\n    c = TestClient()\n    protobuf = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Proto(ConanFile):\n            options = {\"shared\": [True, False]}\n            default_options = {\"shared\": False}\n\n            def package_info(self):\n                self.output.info(\"MYOPTION: {}-{}\".format(self.context, self.options.shared))\n        \"\"\")\n    consumer_recipe = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Consumer(ConanFile):\n            def requirements(self):\n                self.requires(\"protobuf/1.0\", options={{\"{scope}shared\": {host}}})\n            def build_requirements(self):\n                self.build_requires(\"protobuf/1.0\", options={{\"{scope}shared\": {build}}})\n        \"\"\")\n    c.save({\"conanfile.py\": protobuf})\n\n    c.run(\"create . --name=protobuf --version=1.0\")\n    c.run(\"create . --name=protobuf --version=1.0 -o protobuf/*:shared=True\")\n\n    for host, build in ((True, True), (True, False), (False, True), (False, False)):\n        c.save({\"conanfile.py\": consumer_recipe.format(host=host, build=build, scope=scope)})\n        c.run(\"install .\")\n        assert f\"protobuf/1.0: MYOPTION: host-{host}\" in c.out\n        assert f\"protobuf/1.0: MYOPTION: build-{build}\" in c.out\n\n\ndef test_different_options_values_recipe_attributes():\n    \"\"\"\n    consumer -> protobuf (library)\n        \\\\--(build)-> protobuf (protoc)\n    protobuf by default is a static library (shared=False)\n    The \"consumer\" conanfile.py can use ``default_options`` to define protobuf:shared\n    \"\"\"\n    c = TestClient()\n    protobuf = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Proto(ConanFile):\n            options = {\"shared\": [True, False]}\n            default_options = {\"shared\": False}\n\n            def package_info(self):\n                self.output.info(\"MYOPTION: {}-{}\".format(self.context, self.options.shared))\n        \"\"\")\n    c.save({\"conanfile.py\": protobuf})\n    c.run(\"create . --name=protobuf --version=1.0\")\n    c.run(\"create . --name=protobuf --version=1.0 -o protobuf/*:shared=True\")\n\n    consumer_recipe = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Consumer(ConanFile):\n            default_options = {{\"protobuf/*:shared\": {host}}}\n            default_build_options = {{\"protobuf/*:shared\": {build}}}\n            def requirements(self):\n                self.requires(\"protobuf/1.0\")\n            def build_requirements(self):\n                self.build_requires(\"protobuf/1.0\")\n        \"\"\")\n\n    for host, build in ((True, True), (True, False), (False, True), (False, False)):\n        c.save({\"conanfile.py\": consumer_recipe.format(host=host, build=build)})\n        c.run(\"install .\")\n        assert f\"protobuf/1.0: MYOPTION: host-{host}\" in c.out\n        assert f\"protobuf/1.0: MYOPTION: build-{build}\" in c.out\n\n\ndef test_different_options_values_recipe_priority():\n    \"\"\"\n    consumer ---> mypkg ---> protobuf (library)\n                  \\\\--(build)-> protobuf (protoc)\n    protobuf by default is a static library (shared=1)\n    \"consumer\" defines a protobuf:shared=3 value, that must be respected for HOST context\n    But build context, it is assigned by \"mypkg\", and build-require is private\n    \"\"\"\n    c = TestClient()\n    protobuf = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Proto(ConanFile):\n            options = {\"shared\": [1, 2, 3]}\n            default_options = {\"shared\": 1}\n\n            def package_id(self):\n                self.output.info(\"MYOPTION: {}-{}\".format(self.context, self.info.options.shared))\n        \"\"\")\n    my_pkg = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Consumer(ConanFile):\n            def requirements(self):\n                self.requires(\"protobuf/1.0\", options={\"shared\": 2})\n            def build_requirements(self):\n                self.build_requires(\"protobuf/1.0\", options={\"shared\": 2})\n        \"\"\")\n    c.save({\"protobuf/conanfile.py\": protobuf,\n            \"mypkg/conanfile.py\": my_pkg,\n            \"consumer/conanfile.py\": GenConanfile().with_requires(\"mypkg/1.0\")\n           .with_default_option(\"protobuf/*:shared\", 3)})\n\n    c.run(\"create protobuf --name=protobuf --version=1.0 -o protobuf/*:shared=2\")\n    c.run(\"create protobuf --name=protobuf --version=1.0 -o protobuf/*:shared=3\")\n    c.run(\"create mypkg --name=mypkg --version=1.0\")\n\n    c.run(\"install consumer\")\n    assert f\"protobuf/1.0: MYOPTION: host-3\" in c.out\n    assert f\"protobuf/1.0: MYOPTION: build-2\" in c.out\n"
  },
  {
    "path": "test/integration/options/test_package_config_test.py",
    "content": "import pytest\n\nfrom conan.test.utils.tools import TestClient\n\ntest_conanfile = \"\"\"from conan import ConanFile\n\nclass Test(ConanFile):\n    options = {\"shared\": [True, False]}\n    default_options = {\"shared\": False}\n\n    def requirements(self):\n        self.requires(self.tested_reference_str)\n        self.output.info(\"shared (requirements): %s\" % (self.options.shared))\n\n    def configure(self):\n        self.output.info(\"shared (configure): %s\" % (self.options.shared))\n\n    def build(self):\n        self.output.info(\"shared (build): %s\" % (self.options.shared))\n\n    def test(self):\n        self.output.info(\"shared (test): %s\" % (self.options.shared))\n\"\"\"\n\n\ndep = \"\"\"from conan import ConanFile\n\nclass PkgConan(ConanFile):\n    name = \"dep\"\n    version = \"0.1\"\n    options = {\"shared\": [True, False]}\n    default_options = {\"shared\": False}\n\n    def configure(self):\n        self.output.info(\"shared (configure): %s\" % str(self.options.shared))\n\n    def requirements(self):\n        self.output.info(\"shared (requirements): %s\" % str(self.options.shared))\n\n    def build(self):\n        self.output.info(\"shared (build): %s\" % str(self.options.shared))\n\"\"\"\n\n\nconanfile = \"\"\"from conan import ConanFile\n\nclass PkgConan(ConanFile):\n    name = \"pkg\"\n    version = \"0.1\"\n    options = {\"shared\": [True, False]}\n    default_options = {\"shared\": False}\n\n    def configure(self):\n        self.output.info(\"shared (configure): %s\" % str(self.options.shared))\n\n    def requirements(self):\n        self.requires(\"dep/0.1\")\n        self.output.info(\"shared (requirements): %s\" % str(self.options.shared))\n\n    def build(self):\n        self.output.info(\"shared (build): %s\" % str(self.options.shared))\n\"\"\"\n\n\nclass TestPackageOptionsCreate:\n\n    def test_test_package(self):\n        \"\"\" non scoped options will be put in the package scope\n        -o shared=True <=> -o pkg:shared=True\n        \"\"\"\n        c = TestClient()\n        c.save({\"dep/conanfile.py\": dep,\n                \"conanfile.py\": conanfile,\n                \"test_package/conanfile.py\": test_conanfile})\n        c.run(\"export dep\")\n        c.run(\"create . -o shared=True --build=missing\")\n\n        assert \"dep/0.1: shared (configure): False\" in c.out\n        assert \"dep/0.1: shared (requirements): False\" in c.out\n        assert \"dep/0.1: shared (build): False\" in c.out\n\n        assert \"pkg/0.1: shared (configure): True\" in c.out\n        assert \"pkg/0.1: shared (requirements): True\" in c.out\n        assert \"pkg/0.1: shared (build): True\" in c.out\n\n        assert \"pkg/0.1 (test package): shared (configure): False\" in c.out\n        assert \"pkg/0.1 (test package): shared (requirements): False\" in c.out\n        assert \"pkg/0.1 (test package): shared (build): False\" in c.out\n        assert \"pkg/0.1 (test package): shared (test): False\" in c.out\n\n    def test_test_package_all_shared(self):\n        \"\"\"\n        all shared should affect both the package and the test_package\n        \"\"\"\n        c = TestClient()\n        c.save({\"dep/conanfile.py\": dep,\n                \"conanfile.py\": conanfile,\n                \"test_package/conanfile.py\": test_conanfile})\n        c.run(\"export dep\")\n        c.run(\"create . -o *:shared=True --build=missing\")\n\n        assert \"dep/0.1: shared (configure): True\" in c.out\n        assert \"dep/0.1: shared (requirements): True\" in c.out\n        assert \"dep/0.1: shared (build): True\" in c.out\n\n        assert \"pkg/0.1: shared (configure): True\" in c.out\n        assert \"pkg/0.1: shared (requirements): True\" in c.out\n        assert \"pkg/0.1: shared (build): True\" in c.out\n\n        assert \"pkg/0.1 (test package): shared (configure): True\" in c.out\n        assert \"pkg/0.1 (test package): shared (requirements): True\" in c.out\n        assert \"pkg/0.1 (test package): shared (build): True\" in c.out\n        assert \"pkg/0.1 (test package): shared (test): True\" in c.out\n\n    def test_test_package_consumers(self):\n        c = TestClient()\n        c.save({\"dep/conanfile.py\": dep,\n                \"conanfile.py\": conanfile,\n                \"test_package/conanfile.py\": test_conanfile})\n        c.run(\"export dep\")\n        c.run(\"create . -o &:shared=True --build=missing\")\n\n        assert \"dep/0.1: shared (configure): False\" in c.out\n        assert \"dep/0.1: shared (requirements): False\" in c.out\n        assert \"dep/0.1: shared (build): False\" in c.out\n\n        assert \"pkg/0.1: shared (configure): True\" in c.out\n        assert \"pkg/0.1: shared (requirements): True\" in c.out\n        assert \"pkg/0.1: shared (build): True\" in c.out\n\n        assert \"pkg/0.1 (test package): shared (configure): True\" in c.out\n        assert \"pkg/0.1 (test package): shared (requirements): True\" in c.out\n        assert \"pkg/0.1 (test package): shared (build): True\" in c.out\n        assert \"pkg/0.1 (test package): shared (test): True\" in c.out\n\n        c.run(\"install --requires=dep/0.1 -o &:shared=True -b=missing\")\n        assert \"dep/0.1: shared (configure): True\" in c.out\n        assert \"dep/0.1: shared (requirements): True\" in c.out\n        assert \"dep/0.1: shared (build): True\" in c.out\n\n    def test_test_package_non_consumers(self):\n        c = TestClient()\n        c.save({\"dep/conanfile.py\": dep,\n                \"conanfile.py\": conanfile,\n                \"test_package/conanfile.py\": test_conanfile})\n        c.run(\"export dep\")\n        c.run(\"create . -o !&:shared=True --build=missing\")\n\n        assert \"dep/0.1: shared (configure): True\" in c.out\n        assert \"dep/0.1: shared (requirements): True\" in c.out\n        assert \"dep/0.1: shared (build): True\" in c.out\n\n        assert \"pkg/0.1: shared (configure): False\" in c.out\n        assert \"pkg/0.1: shared (requirements): False\" in c.out\n        assert \"pkg/0.1: shared (build): False\" in c.out\n\n        assert \"pkg/0.1 (test package): shared (configure): False\" in c.out\n        assert \"pkg/0.1 (test package): shared (requirements): False\" in c.out\n        assert \"pkg/0.1 (test package): shared (build): False\" in c.out\n        assert \"pkg/0.1 (test package): shared (test): False\" in c.out\n\n    def test_test_package_only(self):\n        c = TestClient()\n        c.save({\"dep/conanfile.py\": dep,\n                \"conanfile.py\": conanfile,\n                \"test_package/conanfile.py\": test_conanfile})\n        c.run(\"export dep\")\n        c.run(\"create . -o &:shared=True -o shared=False --build=missing\")\n\n        assert \"dep/0.1: shared (configure): False\" in c.out\n        assert \"dep/0.1: shared (requirements): False\" in c.out\n        assert \"dep/0.1: shared (build): False\" in c.out\n\n        assert \"pkg/0.1: shared (configure): False\" in c.out\n        assert \"pkg/0.1: shared (requirements): False\" in c.out\n        assert \"pkg/0.1: shared (build): False\" in c.out\n\n        assert \"pkg/0.1 (test package): shared (configure): True\" in c.out\n        assert \"pkg/0.1 (test package): shared (requirements): True\" in c.out\n        assert \"pkg/0.1 (test package): shared (build): True\" in c.out\n        assert \"pkg/0.1 (test package): shared (test): True\" in c.out\n\n\nclass TestPackageOptionsInstall:\n\n    @pytest.mark.parametrize(\"pattern\", [\"\", \"*:\", \"&:\"])\n    def test_test_package(self, pattern):\n        c = TestClient()\n        c.save({\"dep/conanfile.py\": dep,\n                \"conanfile.py\": conanfile})\n        c.run(\"export dep\")\n        c.run(f\"build . -o {pattern}shared=True --build=missing\")\n\n        dep_shared = \"False\" if \"*\" not in pattern else \"True\"\n        assert f\"dep/0.1: shared (configure): {dep_shared}\" in c.out\n        assert f\"dep/0.1: shared (requirements): {dep_shared}\" in c.out\n        assert f\"dep/0.1: shared (build): {dep_shared}\" in c.out\n\n        assert \"conanfile.py (pkg/0.1): shared (configure): True\" in c.out\n        assert \"conanfile.py (pkg/0.1): shared (requirements): True\" in c.out\n        assert \"conanfile.py (pkg/0.1): shared (build): True\" in c.out\n"
  },
  {
    "path": "test/integration/package_id/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/package_id/build_id_test.py",
    "content": "import textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\nconanfile = \"\"\"import os\nfrom conan import ConanFile\n\nclass MyTest(ConanFile):\n    name = \"pkg\"\n    version = \"0.1\"\n    settings = \"os\", \"build_type\"\n    build_policy = \"missing\"\n\n    def build_id(self):\n        if self.settings.os == \"Windows\":\n            self.info_build.settings.build_type = \"Any\"\n\n    def build(self):\n        self.output.info(\"Building my code!\")\n\n    def package(self):\n        self.output.info(\"Packaging %s!\" % self.settings.build_type)\n\"\"\"\n\n\nclass TestBuildIdTest:\n\n    def test_create(self):\n        # Ensure that build_id() works when multiple create calls are made\n        client = TestClient()\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create .  -s os=Windows -s build_type=Release\")\n        assert \"pkg/0.1: Calling build()\" in client.out\n        assert \"Building my code!\" in client.out\n        assert \"Packaging Release!\" in client.out\n        # Debug must not build\n        client.run(\"create .  -s os=Windows -s build_type=Debug\")\n        assert \"pkg/0.1: Calling build()\" not in client.out\n        assert \"Building my code!\" not in client.out\n        assert \"Packaging Debug!\" in client.out\n\n        client.run(\"create . -s os=Linux -s build_type=Release\")\n        assert \"pkg/0.1: Calling build()\" in client.out\n        assert \"Building my code!\" in client.out\n        assert \"Packaging Release!\" in client.out\n        client.run(\"create .  -s os=Linux -s build_type=Debug\")\n        assert \"Building my code!\" in client.out\n        assert \"pkg/0.1: Calling build()\" in client.out\n        assert \"Packaging Debug!\" in client.out\n\n    def test_basic_install(self):\n        client = TestClient()\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"export . \")\n        # Windows Debug\n        client.run('install --requires=pkg/0.1 -s os=Windows -s build_type=Debug')\n        assert \"Building my code!\" in client.out\n        assert \"Packaging Debug!\" in client.out\n\n        # Package Windows Release, it will reuse the previous build\n        client.run('install --requires=pkg/0.1 -s os=Windows -s build_type=Release')\n        assert \"Building my code!\" not in client.out\n        assert \"Packaging Release!\" in client.out\n\n        # Now Linux Debug\n        client.run('install --requires=pkg/0.1 -s os=Linux -s build_type=Debug')\n        assert \"Building my code!\" in client.out\n        assert \"Packaging Debug!\" in client.out\n\n        # Linux Release must build again, as it is not affected by build_id()\n        client.run('install --requires=pkg/0.1 -s os=Linux -s build_type=Release')\n        assert \"Building my code!\" in client.out\n        assert \"Packaging Release!\" in client.out\n\n        # But if the packages are removed, and we change the order, keeps working\n        client.run(\"remove *:* -c\")\n        client.run('install --requires=pkg/0.1 -s os=Windows -s build_type=Release')\n        assert \"Building my code!\" in client.out\n        assert \"Packaging Release!\" in client.out\n\n        client.run('install --requires=pkg/0.1 -s os=Windows -s build_type=Debug')\n        assert \"Building my code!\" not in client.out\n        assert \"Packaging Debug!\" in client.out\n\n    def test_clean_build(self):\n        client = TestClient()\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"export . \")\n        client.run('install --requires=pkg/0.1 -s os=Windows -s build_type=Debug')\n        # Package Windows Release, it will reuse the previous build\n        client.run('install --requires=pkg/0.1 -s os=Windows -s build_type=Release')\n        assert \"Building my code!\" not in client.out\n        assert \"Packaging Release!\" in client.out\n\n        client.run(\"cache clean\")  # packages are still there\n        client.run('install --requires=pkg/0.1 -s os=Windows -s build_type=Debug')\n        assert \"Building my code!\" not in client.out\n        assert \"Packaging Release!\" not in client.out\n        client.run('install --requires=pkg/0.1 -s os=Windows -s build_type=Release')\n        assert \"Building my code!\" not in client.out\n        assert \"Packaging Release!\" not in client.out\n\n        # Lets force the first rebuild, different order Linux first\n        client.run('install --requires=pkg/0.1 -s os=Windows -s build_type=Release --build=pkg*')\n        assert \"Building my code!\" in client.out\n        assert \"Packaging Release!\" in client.out\n\n        client.run('install --requires=pkg/0.1 -s os=Windows -s build_type=Debug --build=pkg*')\n        assert \"Building my code!\" not in client.out\n        assert \"Packaging Debug!\" in client.out\n\n    def test_failed_build(self):\n        # Repeated failed builds keep failing\n        fail_conanfile = textwrap.dedent(\"\"\"\\\n            from conan import ConanFile\n            class MyTest(ConanFile):\n                settings = \"build_type\"\n                def build(self):\n                    raise Exception(\"Failed build!!\")\n            \"\"\")\n        client = TestClient()\n        # NORMAL case, every create fails\n        client.save({\"conanfile.py\": fail_conanfile})\n        client.run(\"create . --name=pkg --version=0.1 \", assert_error=True)\n        assert \"ERROR: pkg/0.1: Error in build() method, line 5\" in client.out\n        client.run(\"create . --name=pkg --version=0.1 \", assert_error=True)\n        assert \"ERROR: pkg/0.1: Error in build() method, line 5\" in client.out\n        # now test with build_id\n        client.save({\"conanfile.py\": fail_conanfile +\n                     \"    def build_id(self): self.info_build.settings.build_type = 'any'\"})\n        client.run(\"create . --name=pkg --version=0.1 \", assert_error=True)\n        assert \"ERROR: pkg/0.1: Error in build() method, line 5\" in client.out\n        client.run(\"create . --name=pkg --version=0.1 \", assert_error=True)\n        assert \"ERROR: pkg/0.1: Error in build() method, line 5\" in client.out\n\n    def test_any_os_arch(self):\n        conanfile_os = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n\n            class MyTest(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                settings = \"os\", \"arch\", \"build_type\", \"compiler\"\n\n                def build_id(self):\n                    self.info_build.settings.build_type = \"AnyValue\"\n                    self.info_build.settings.os = \"AnyValue\"\n                    self.info_build.settings.arch = \"AnyValue\"\n                    self.info_build.settings.compiler = \"AnyValue\"\n\n                def build(self):\n                    self.output.info(\"Building my code!\")\n\n                def package(self):\n                    self.output.info(\"Packaging %s-%s!\" % (self.settings.os, self.settings.arch))\n            \"\"\")\n\n        client = TestClient()\n        client.save({\"conanfile.py\": conanfile_os})\n        client.run(\"create .  -s os=Windows -s arch=x86_64 -s build_type=Release\")\n        assert \"pkg/0.1: Calling build()\" in client.out\n        assert \"Building my code!\" in client.out\n        assert \"Packaging Windows-x86_64!\" in client.out\n        # Others must not build\n        client.run(\"create .  -s os=Linux -s arch=x86 -s build_type=Debug\")\n        assert \"pkg/0.1: Calling build()\" not in client.out\n        assert \"Building my code!\" not in client.out\n        assert \"Packaging Linux-x86!\" in client.out\n\n\ndef test_remove_require():\n    c = TestClient()\n    remove = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"consumer\"\n            version = \"1.0\"\n            requires = \"dep/1.0\"\n            def build_id(self):\n                self.info_build.requires.remove(\"dep\")\n        \"\"\")\n    c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"1.0\"),\n            \"consumer/conanfile.py\": remove})\n    c.run(\"create dep\")\n    c.run(\"create consumer\")\n\n\ndef test_build_id_error():\n    \"\"\"\n    https://github.com/conan-io/conan/issues/14537\n    This was failing because the ``DB get_matching_build_id()`` function was returning all prefs\n    for a given ref, and the order could be by alphabetic package_id, but only the first one really\n    contains the build folder with the artifacts. It was fixed by defining the DB \"build_id\" only\n    for the first reference containing that build_id, not all\n    \"\"\"\n    c = TestClient()\n    myconan = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.scm import Version\n\n        class BuildIdTestConan(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            options = {\"shared\": [True, False]}\n            default_options = {\"shared\": False}\n\n            def build_id(self):\n                self.info_build.settings.build_type = \"Any\"\n                self.info_build.options.shared = \"Any\"\n\n            def package_id(self):\n                compilerVer = Version(str(self.info.settings.compiler.version))\n                if self.info.settings.compiler == \"gcc\":\n                    if compilerVer >= \"7\":\n                        self.info.settings.compiler.version = \"7+\"\n    \"\"\")\n    host_profile = textwrap.dedent(\"\"\"\n        [settings]\n        arch = x86_64\n        build_type = Release\n        compiler = gcc\n        compiler.cppstd = gnu17\n        compiler.libcxx = libstdc++11\n        compiler.version = 8\n        os = Linux\n    \"\"\")\n\n    c.save({\"conanfile.py\": myconan,\n            \"myprofile\": host_profile})\n    c.run(\"create . \"\n          \"-pr:h myprofile -pr:b myprofile \"\n          \"-s build_type=Debug -o pkg/*:shared=True\")\n    c.assert_listed_binary({\"pkg/0.1\": (\"538f60f3919ea9b8ea9e7c63c5948abe44913bec\", \"Build\")})\n    assert \"pkg/0.1: build_id() computed 7d169d0d018d239cff27eb081e3f6575554e05c5\" in c.out\n    c.run(\"create . \"\n          \"-pr:h myprofile -pr:b myprofile \"\n          \"-s build_type=Debug -o pkg/*:shared=False\")\n    c.assert_listed_binary({\"pkg/0.1\": (\"ba41c80b0373ef66e2ca95ed56961153082fbcd9\", \"Build\")})\n    assert \"pkg/0.1: build_id() computed 7d169d0d018d239cff27eb081e3f6575554e05c5\" in c.out\n    assert \"pkg/0.1: Won't be built, using previous build folder as defined in build_id()\" in c.out\n    c.run(\"create . \"\n          \"-pr:h myprofile -pr:b myprofile \"\n          \"-s build_type=Release -o pkg/*:shared=True\")\n    c.assert_listed_binary({\"pkg/0.1\": (\"2eb252449df37d245568e32e5a41d0540db3c6e2\", \"Build\")})\n    assert \"pkg/0.1: build_id() computed 7d169d0d018d239cff27eb081e3f6575554e05c5\" in c.out\n    assert \"pkg/0.1: Won't be built, using previous build folder as defined in build_id()\" in c.out\n    c.run(\"create . \"\n          \"-pr:h myprofile -pr:b myprofile \"\n          \"-s build_type=Release -o pkg/*:shared=False\")\n    c.assert_listed_binary({\"pkg/0.1\": (\"978c5442906f96846ccb201129ba1559071ce4ab\", \"Build\")})\n    assert \"pkg/0.1: build_id() computed 7d169d0d018d239cff27eb081e3f6575554e05c5\" in c.out\n    assert \"pkg/0.1: Won't be built, using previous build folder as defined in build_id()\" in c.out\n"
  },
  {
    "path": "test/integration/package_id/compatible_test.py",
    "content": "import json\nimport textwrap\n\nimport pytest\n\nfrom conan.test.utils.env import environment_update\nfrom conan.test.utils.tools import TestClient, GenConanfile, TestServer\n\n\nclass TestCompatibleIDsTest:\n\n    def test_compatible_setting_no_binary(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n           from conan import ConanFile\n\n           class Pkg(ConanFile):\n               settings = \"os\", \"compiler\"\n               def compatibility(self):\n                    if self.settings.compiler == \"gcc\" and self.settings.compiler.version == \"4.9\":\n                        return [{\"settings\": [(\"compiler.version\", v)]}\n                                for v in (\"4.8\", \"4.7\", \"4.6\")]\n               def package_info(self):\n                   self.output.info(\"PackageInfo!: Gcc version: %s!\"\n                                    % self.settings.compiler.version)\n           \"\"\")\n        profile = textwrap.dedent(\"\"\"\n           [settings]\n           os = Linux\n           compiler=gcc\n           compiler.version=4.9\n           compiler.libcxx=libstdc++\n           \"\"\")\n        client.save({\"conanfile.py\": conanfile,\n                     \"myprofile\": profile})\n        # Create package with gcc 4.8\n        client.run(\"export . --name=pkg --version=0.1 --user=user --channel=stable\")\n        assert (\"pkg/0.1@user/stable: Exported: \"\n                \"pkg/0.1@user/stable#d165eb4bcdd1c894a97d2a212956f5fe\") in client.out\n        client.run(\"export . --name=lib --version=0.1 --user=user --channel=stable\")\n\n        # package can be used with a profile gcc 4.9 falling back to 4.8 binary\n        client.save({\"conanfile.py\": GenConanfile().with_requires(\"pkg/0.1@user/stable\",\n                                                                  \"lib/0.1@user/stable\")})\n        # No fallback\n        client.run(\"install . -pr=myprofile --build=missing -u=lib\")\n        assert \"pkg/0.1@user/stable: PackageInfo!: Gcc version: 4.9!\" in client.out\n        client.assert_listed_binary({\"pkg/0.1@user/stable\":\n                                     (\"1ded27c9546219fbd04d4440e05b2298f8230047\", \"Build\")})\n        assert (\"lib/0.1@user/stable: Compatible configurations not found in cache, \"\n                \"checking servers\") not in client.out\n        assert (\"pkg/0.1@user/stable: Compatible configurations not found in cache, \"\n                \"checking servers\") in client.out\n\n    def test_compatible_setting_no_user_channel(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class Pkg(ConanFile):\n                settings = \"os\", \"compiler\"\n                def compatibility(self):\n                    if self.settings.compiler == \"gcc\" and self.settings.compiler.version == \"4.9\":\n                        return [{\"settings\": [(\"compiler.version\", v)]}\n                                for v in (\"4.8\", \"4.7\", \"4.6\")]\n            \"\"\")\n        profile = textwrap.dedent(\"\"\"\n            [settings]\n            os = Linux\n            compiler=gcc\n            compiler.version=4.9\n            compiler.libcxx=libstdc++\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile,\n                     \"myprofile\": profile})\n\n        # No user/channel\n        client.run(\"create . --name=pkg --version=0.1 -pr=myprofile -s compiler.version=4.8\")\n        package_id = client.created_package_id(\"pkg/0.1\")\n\n        client.save({\"conanfile.py\": GenConanfile().with_require(\"pkg/0.1\")})\n        client.run(\"install . -pr=myprofile\")\n        client.assert_listed_binary({\"pkg/0.1\": (package_id, \"Cache\")})\n        assert \"pkg/0.1: Already installed!\" in client.out\n\n    def test_compatible_option(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class Pkg(ConanFile):\n                options = {\"optimized\": [1, 2, 3]}\n                default_options = {\"optimized\": 1}\n\n                def compatibility(self):\n                    return [{\"options\": [(\"optimized\", v)]}\n                            for v in range(int(self.options.optimized), 0, -1)]\n\n                def package_info(self):\n                    self.output.info(\"PackageInfo!: Option optimized %s!\"\n                                     % self.options.optimized)\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --name=pkg --version=0.1 --user=user --channel=stable\")\n        package_id = client.created_package_id(\"pkg/0.1@user/stable\")\n        assert f\"pkg/0.1@user/stable: Package '{package_id}' created\" in client.out\n\n        client.save({\"conanfile.py\": GenConanfile().with_require(\"pkg/0.1@user/stable\")})\n        client.run(\"install . -o pkg/*:optimized=2 -vv\")\n        # Information messages\n        missing_id = \"0a8157f8083f5ece34828d27fb2bf5373ba26366\"\n        assert \"pkg/0.1@user/stable: PackageInfo!: Option optimized 1!\" in client.out\n        assert (f\"pkg/0.1@user/stable: Compatible package ID {missing_id} \"\n                f\"equal to the default package ID\") in client.out\n        assert f\"pkg/0.1@user/stable: Main binary package '{missing_id}' missing\" in client.out\n        assert f\"Found compatible package '{package_id}'\" in client.out\n        # checking the resulting dependencies\n        client.assert_listed_binary({\"pkg/0.1@user/stable\": (package_id, \"Cache\")})\n        assert \"pkg/0.1@user/stable: Already installed!\" in client.out\n        client.run(\"install . -o pkg/*:optimized=3\")\n        client.assert_listed_binary({\"pkg/0.1@user/stable\": (package_id, \"Cache\")})\n        assert \"pkg/0.1@user/stable: Already installed!\" in client.out\n\n    def test_package_id_consumers(self):\n        # If we fallback to a different binary upstream and we are using a \"package_revision_mode\"\n        # the current package should have a different binary package ID too.\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                settings = \"os\", \"compiler\"\n                def compatibility(self):\n                    return [{\"settings\": [(\"compiler.version\", \"4.8\")]}]\n                def package_info(self):\n                    self.output.info(\"PackageInfo!: Gcc version: %s!\"\n                                     % self.settings.compiler.version)\n            \"\"\")\n        profile = textwrap.dedent(\"\"\"\n            [settings]\n            os = Linux\n            compiler=gcc\n            compiler.version=4.9\n            compiler.libcxx=libstdc++\n            \"\"\")\n        client.save_home({\"global.conf\":\n                          \"core.package_id:default_unknown_mode=recipe_revision_mode\"})\n        client.save({\"conanfile.py\": conanfile,\n                     \"myprofile\": profile})\n        # Create package with gcc 4.8\n        client.run(\"create . --name=pkg --version=0.1 --user=user --channel=stable \"\n                   \"-pr=myprofile -s compiler.version=4.8\")\n        package_id = client.created_package_id(\"pkg/0.1@user/stable\")\n        assert f\"pkg/0.1@user/stable: Package '{package_id}' created\" in client.out\n\n        # package can be used with a profile gcc 4.9 falling back to 4.8 binary\n        client.save({\"conanfile.py\": GenConanfile().with_require(\"pkg/0.1@user/stable\")})\n        client.run(\"create . --name=consumer --version=0.1 --user=user --channel=stable -pr=myprofile\")\n        assert \"pkg/0.1@user/stable: PackageInfo!: Gcc version: 4.8!\" in client.out\n        client.assert_listed_binary({\"pkg/0.1@user/stable\": (package_id, \"Cache\")})\n        assert \"pkg/0.1@user/stable: Already installed!\" in client.out\n        consumer_id = \"96465a24a53766aaac28e270d196db295e2fd22a\"\n        client.assert_listed_binary({\"consumer/0.1@user/stable\": (consumer_id, \"Build\")})\n        assert f\"consumer/0.1@user/stable: Package '{consumer_id}' created\" in client.out\n\n        # Create package with gcc 4.9\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --name=pkg --version=0.1 --user=user --channel=stable -pr=myprofile\")\n        package_id = \"1ded27c9546219fbd04d4440e05b2298f8230047\"\n        assert f\"pkg/0.1@user/stable: Package '{package_id}' created\" in client.out\n\n        # Consume it\n        client.save({\"conanfile.py\": GenConanfile().with_require(\"pkg/0.1@user/stable\")})\n        client.run(\"create . --name=consumer --version=0.1 --user=user --channel=stable -pr=myprofile\")\n        assert \"pkg/0.1@user/stable: PackageInfo!: Gcc version: 4.9!\" in client.out\n        client.assert_listed_binary({\"pkg/0.1@user/stable\": (f\"{package_id}\", \"Cache\")})\n        assert \"pkg/0.1@user/stable: Already installed!\" in client.out\n        consumer_id = \"41bc915fa380e9a046aacbc21256fcb46ad3179d\"\n        client.assert_listed_binary({\"consumer/0.1@user/stable\": (consumer_id, \"Build\")})\n        assert f\"consumer/0.1@user/stable: Package '{consumer_id}' created\" in client.out\n\n    def test_build_missing(self):\n        # https://github.com/conan-io/conan/issues/6133\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class Conan(ConanFile):\n                settings = \"os\"\n\n                def compatibility(self):\n                    if self.settings.os == \"Windows\":\n                        return [{\"settings\": [(\"os\", \"Linux\")]}]\n                \"\"\")\n\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --name=pkg --version=0.1 --user=user --channel=testing -s os=Linux\")\n        package_id = client.created_package_id(\"pkg/0.1@user/testing\")\n        client.save({\"conanfile.py\": GenConanfile().with_require(\"pkg/0.1@user/testing\")})\n        client.run(\"install . -s os=Windows --build=missing\")\n        client.assert_listed_binary({\"pkg/0.1@user/testing\": (package_id, \"Cache\")})\n        assert \"pkg/0.1@user/testing: Already installed!\" in client.out\n\n    def test_compatible_package_python_requires(self):\n        # https://github.com/conan-io/conan/issues/6609\n        client = TestClient()\n        client.save({\"conanfile.py\": GenConanfile()})\n        client.run(\"export . --name=tool --version=0.1\")\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class Conan(ConanFile):\n                settings = \"os\"\n                python_requires = \"tool/0.1\"\n\n                def compatibility(self):\n                    if self.settings.os == \"Windows\":\n                        return [{\"settings\": [(\"os\", \"Linux\")]}]\n                \"\"\")\n\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --name=pkg --version=0.1 --user=user --channel=testing -s os=Linux\")\n        package_id = client.created_package_id(\"pkg/0.1@user/testing\")\n        client.save({\"conanfile.py\": GenConanfile().with_require(\"pkg/0.1@user/testing\")})\n        client.run(\"install . -s os=Windows\")\n        client.assert_listed_binary({\"pkg/0.1@user/testing\": (package_id, \"Cache\")})\n        assert \"pkg/0.1@user/testing: Already installed!\" in client.out\n\n    def test_compatible_lockfile(self):\n        # https://github.com/conan-io/conan/issues/9002\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                settings = \"os\"\n                def compatibility(self):\n                    if self.settings.os == \"Windows\":\n                        return [{\"settings\": [(\"os\", \"Linux\")]}]\n                def package_info(self):\n                    self.output.info(\"PackageInfo!: OS: %s!\" % self.settings.os)\n            \"\"\")\n\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --name=pkg --version=0.1 -s os=Linux\")\n        assert \"pkg/0.1: PackageInfo!: OS: Linux!\" in client.out\n        assert \"pkg/0.1: Package '9a4eb3c8701508aa9458b1a73d0633783ecc2270' built\" in client.out\n\n        client.save({\"conanfile.py\": GenConanfile().with_require(\"pkg/0.1\")})\n        client.run(\"lock create . -s os=Windows --lockfile-out=deps.lock\")\n        client.run(\"install . -s os=Windows --lockfile=deps.lock\")\n        assert \"pkg/0.1: PackageInfo!: OS: Linux!\" in client.out\n        assert \"9a4eb3c8701508aa9458b1a73d0633783ecc2270\" in client.out\n        assert \"pkg/0.1: Already installed!\" in client.out\n\n    def test_compatible_diamond(self):\n        # https://github.com/conan-io/conan/issues/9880\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                {}\n                settings = \"build_type\"\n                def compatibility(self):\n                    if self.settings.build_type == \"Debug\":\n                       return [{{\"settings\": [(\"build_type\", \"Release\")]}}]\n                \"\"\")\n\n        private = \"\"\"def requirements(self):\n        self.requires(\"pkga/0.1\", visible=False)\n        \"\"\"\n        client.save({\"pkga/conanfile.py\": conanfile.format(\"\"),\n                     \"pkgb/conanfile.py\": conanfile.format(private),\n                     \"pkgc/conanfile.py\": conanfile.format('requires = \"pkga/0.1\"'),\n                     \"pkgd/conanfile.py\": conanfile.format('requires = \"pkgb/0.1\", \"pkgc/0.1\"')\n                     })\n        client.run(\"create pkga --name=pkga --version=0.1 -s build_type=Release\")\n        client.run(\"create pkgb --name=pkgb --version=0.1 -s build_type=Release\")\n        client.run(\"create pkgc --name=pkgc --version=0.1 -s build_type=Release\")\n\n        client.run(\"install pkgd -s build_type=Debug\")\n        client.assert_listed_binary({\"pkga/0.1\":\n                                    (\"efa83b160a55b033c4ea706ddb980cd708e3ba1b\", \"Cache\")})\n\n\nclass TestNewCompatibility:\n\n    def test_compatible_setting(self):\n        c = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                settings = \"os\", \"compiler\"\n\n                def compatibility(self):\n                    if self.settings.compiler == \"gcc\" and self.settings.compiler.version == \"4.9\":\n                        return [{\"settings\": [(\"compiler.version\", v)]}\n                                for v in (\"4.8\", \"4.7\", \"4.6\")]\n\n                def package_info(self):\n                    self.output.info(\"PackageInfo!: Gcc version: %s!\"\n                                     % self.settings.compiler.version)\n            \"\"\")\n        profile = textwrap.dedent(\"\"\"\n            [settings]\n            os = Linux\n            compiler=gcc\n            compiler.version=4.9\n            compiler.libcxx=libstdc++\n            \"\"\")\n        c.save({\"conanfile.py\": conanfile,\n                \"myprofile\": profile})\n        # Create package with gcc 4.8\n        c.run(\"create .  -pr=myprofile -s compiler.version=4.8\")\n        package_id = \"c0c95d81351786c6c1103566a27fb1c1f78629ac\"\n        assert f\"pkg/0.1: Package '{package_id}' created\" in c.out\n\n        # package can be used with a profile gcc 4.9 falling back to 4.8 binary\n        c.save({\"conanfile.py\": GenConanfile().with_require(\"pkg/0.1\")})\n        c.run(\"install . -pr=myprofile\")\n        assert \"pkg/0.1: PackageInfo!: Gcc version: 4.8!\" in c.out\n        c.assert_listed_binary({\"pkg/0.1\": (f\"{package_id}\", \"Cache\")})\n        assert \"pkg/0.1: Already installed!\" in c.out\n\n    def test_compatibility_remove_package_id(self):\n        # https://github.com/conan-io/conan/issues/13727\n        c = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class PdfiumConan(ConanFile):\n                name = \"pdfium\"\n                version = \"2020.9\"\n                settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n                build_policy = \"never\"\n\n                def compatibility(self):\n                    result = []\n                    if self.info.settings.build_type == \"Debug\":\n                        result.append({\"settings\": [(\"build_type\", \"Release\")]})\n                    return result\n\n                def package_id(self):\n                    del self.info.settings.compiler.runtime\n                    del self.info.settings.compiler.runtime_type\n            \"\"\")\n        profile = textwrap.dedent(\"\"\"\n            [settings]\n            os = Windows\n            compiler=msvc\n            compiler.version=192\n            compiler.runtime=dynamic\n            build_type=Release\n            arch=x86_64\n            \"\"\")\n        c.save({\"conanfile.py\": conanfile,\n                \"myprofile\": profile})\n        c.run(\"create .  -pr=myprofile\", assert_error=True)\n        assert \"ERROR: This package cannot be created, 'build_policy=never', \" \\\n               \"it can only be 'export-pkg'\" in c.out\n        c.run(\"export-pkg . -pr=myprofile\")\n        c.run(\"list pdfium/2020.9:*\")\n\n        c.run(\"install --requires=pdfium/2020.9 -pr=myprofile -s build_type=Debug\")\n        assert \"Found compatible package\" in c.out\n\n    def test_compatibility_erase_package_id(self):\n        c = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class PdfiumConan(ConanFile):\n                name = \"diligent-core\"\n                version = \"1.0\"\n                settings = \"compiler\"\n                options = {\"foo\": [\"no\"]}\n\n                def package_id(self):\n                    self.info.settings.compiler.runtime = \"foobar\"\n                    self.info.options.foo = \"yes\"\n            \"\"\")\n        profile = textwrap.dedent(\"\"\"\n            [settings]\n            os = Windows\n            compiler=msvc\n            compiler.version=192\n            compiler.runtime=dynamic\n            build_type=Release\n            arch=x86_64\n            \"\"\")\n        c.save({\"conanfile.py\": conanfile,\n                \"myprofile\": profile})\n\n        c.run(\"create . -pr:a=myprofile -s compiler.cppstd=20\")\n        c.run(\"install --requires=diligent-core/1.0 -pr:a=myprofile -s compiler.cppstd=17\")\n        assert \"ERROR: Invalid setting 'foobar' is not a valid 'settings.compiler.runtime' value.\" not in c.out\n\n    def test_compatibility_msvc_and_cppstd(self):\n        \"\"\"msvc 194 would not find compatible packages built with same version but different cppstd\n        due to an issue in the msvc fallback compatibility rule.\"\"\"\n        tc = TestClient()\n        profile = textwrap.dedent(\"\"\"\n                   [settings]\n                   compiler=msvc\n                   compiler.version=194\n                   compiler.runtime=dynamic\n                   \"\"\")\n        tc.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"1.0\").with_setting(\"compiler\"),\n                 \"profile\": profile})\n\n        tc.run(\"create dep -pr=profile -s compiler.cppstd=20\")\n        tc.run(\"install --requires=dep/1.0 -pr=profile -s compiler.cppstd=17\")\n        tc.assert_listed_binary({\"dep/1.0\": (\"b6d26a6bc439b25b434113982791edf9cab4d004\", \"Cache\")})\n\n        tc.run(\"remove * -c\")\n        tc.run(\"create dep -pr=profile -s compiler.version=193 -s compiler.cppstd=20\")\n        tc.run(\"install --requires=dep/1.0 -pr=profile -s compiler.cppstd=17\")\n        assert \"compiler.cppstd=20, compiler.version=193\" in tc.out\n        tc.assert_listed_binary({\"dep/1.0\": (\"535899bb58c3ca7d80a380313d31f4729e735d1c\", \"Cache\")})\n\n\nclass TestCompatibleBuild:\n    def test_build_compatible(self):\n        c = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n           from conan import ConanFile\n           from conan.tools.build import check_min_cppstd\n\n           class Pkg(ConanFile):\n               name = \"pkg\"\n               version = \"0.1\"\n               settings = \"os\", \"compiler\"\n\n               def validate(self):\n                   check_min_cppstd(self, 14)\n            \"\"\")\n        c.save({\"conanfile.py\": conanfile})\n        settings = \"-s os=Windows -s compiler=gcc -s compiler.version=11 \" \\\n                   \"-s compiler.libcxx=libstdc++11 -s compiler.cppstd=11\"\n        c.run(f\"create . {settings}\", assert_error=True)\n        c.assert_listed_binary({\"pkg/0.1\": (\"bb33db23c961978d08dc0cdd6bc786b45b3e5943\", \"Invalid\")})\n        assert \"pkg/0.1: Invalid: Current cppstd (11)\" in c.out\n\n        c.run(f\"create . {settings} --build=compatible:&\")\n        # the one for cppstd=14 is built!!\n        c.assert_listed_binary({\"pkg/0.1\": (\"389803bed06200476fcee1af2023d4e9bfa24ff9\", \"Build\")})\n        c.run(\"list *:*\")\n        assert \"compiler.cppstd: 14\" in c.out\n        c.run(f\"create . {settings} --build=& --build=compatible:&\")\n        # the one for cppstd=14 is built!!\n        c.assert_listed_binary({\"pkg/0.1\": (\"389803bed06200476fcee1af2023d4e9bfa24ff9\", \"Cache\")})\n\n    def test_build_compatible_cant_build(self):\n        # requires c++17 to build, can be consumed with c++14\n        c = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n           from conan import ConanFile\n           from conan.tools.build import check_min_cppstd\n\n           class Pkg(ConanFile):\n               name = \"pkg\"\n               version = \"0.1\"\n               settings = \"os\", \"compiler\"\n\n               def validate(self):\n                   check_min_cppstd(self, 14)\n\n               def validate_build(self):\n                   check_min_cppstd(self, 17)\n            \"\"\")\n        c.save({\"conanfile.py\": conanfile})\n        settings = \"-s os=Windows -s compiler=gcc -s compiler.version=11 \" \\\n                   \"-s compiler.libcxx=libstdc++11  -s compiler.cppstd=11\"\n        c.run(f\"create . {settings}\", assert_error=True)\n        c.assert_listed_binary({\"pkg/0.1\": (\"bb33db23c961978d08dc0cdd6bc786b45b3e5943\", \"Invalid\")})\n        assert \"pkg/0.1: Invalid: Current cppstd (11)\" in c.out\n\n        c.run(f\"create . {settings} --build=missing\", assert_error=True)\n        c.assert_listed_binary({\"pkg/0.1\": (\"bb33db23c961978d08dc0cdd6bc786b45b3e5943\", \"Invalid\")})\n        assert \"pkg/0.1: Invalid: Current cppstd (11)\" in c.out\n\n        c.run(f\"create . {settings} --build=compatible:&\")\n        # the one for cppstd=17 is built!!\n        c.assert_listed_binary({\"pkg/0.1\": (\"58fb8ac6c2dc3e3f837253ce1a6ea59011525866\", \"Build\")})\n        c.run(\"list *:*\")\n        assert \"compiler.cppstd: 17\" in c.out\n\n    def test_build_compatible_cant_build2(self):\n        # requires c++17 to build, can be consumed with c++11\n        c = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n           from conan import ConanFile\n           from conan.tools.build import check_min_cppstd\n\n           class Pkg(ConanFile):\n               name = \"pkg\"\n               version = \"0.1\"\n               settings = \"os\", \"compiler\"\n\n               def validate(self):\n                   check_min_cppstd(self, 11)\n\n               def validate_build(self):\n                   check_min_cppstd(self, 17)\n            \"\"\")\n        c.save({\"conanfile.py\": conanfile})\n        settings = \"-s os=Windows -s compiler=gcc -s compiler.version=11 \" \\\n                   \"-s compiler.libcxx=libstdc++11  -s compiler.cppstd=11\"\n        c.run(f\"create . {settings}\", assert_error=True)\n        c.assert_listed_binary({\"pkg/0.1\": (\"bb33db23c961978d08dc0cdd6bc786b45b3e5943\", \"Invalid\")})\n        assert \"pkg/0.1: Cannot build for this configuration: Current cppstd (11)\" in c.out\n\n        c.run(f\"create . {settings} --build=missing\", assert_error=True)\n        # the one for cppstd=17 is built!!\n        c.assert_listed_binary({\"pkg/0.1\": (\"bb33db23c961978d08dc0cdd6bc786b45b3e5943\", \"Invalid\")})\n        assert \"pkg/0.1: Cannot build for this configuration: Current cppstd (11)\" in c.out\n\n        c.run(f\"create . {settings} --build=compatible:&\")\n        # the one for cppstd=17 is built!!\n        c.assert_listed_binary({\"pkg/0.1\": (\"58fb8ac6c2dc3e3f837253ce1a6ea59011525866\", \"Build\")})\n        c.run(\"list *:*\")\n        assert \"compiler.cppstd: 17\" in c.out\n\n    def test_build_compatible_cant_build_only(self):\n        # requires c++17 to build, but don't specify consumption\n        c = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n           from conan import ConanFile\n           from conan.tools.build import check_min_cppstd\n\n           class Pkg(ConanFile):\n               name = \"pkg\"\n               version = \"0.1\"\n               settings = \"os\", \"compiler\"\n\n               def validate_build(self):\n                   check_min_cppstd(self, 17)\n            \"\"\")\n        c.save({\"conanfile.py\": conanfile})\n        settings = \"-s os=Windows -s compiler=gcc -s compiler.version=11 \" \\\n                   \"-s compiler.libcxx=libstdc++11  -s compiler.cppstd=11\"\n        c.run(f\"create . {settings}\", assert_error=True)\n        c.assert_listed_binary({\"pkg/0.1\": (\"bb33db23c961978d08dc0cdd6bc786b45b3e5943\", \"Invalid\")})\n        assert \"pkg/0.1: Cannot build for this configuration: Current cppstd (11)\" in c.out\n\n        c.run(f\"create . {settings} --build=missing\", assert_error=True)\n        # the one for cppstd=17 is built!!\n        c.assert_listed_binary({\"pkg/0.1\": (\"bb33db23c961978d08dc0cdd6bc786b45b3e5943\", \"Invalid\")})\n        assert \"pkg/0.1: Cannot build for this configuration: Current cppstd (11)\" in c.out\n\n        c.run(f\"create . {settings} --build=compatible:&\")\n        # the one for cppstd=17 is built!!\n        c.assert_listed_binary({\"pkg/0.1\": (\"58fb8ac6c2dc3e3f837253ce1a6ea59011525866\", \"Build\")})\n        c.run(\"list *:*\")\n        assert \"compiler.cppstd: 17\" in c.out\n\n    def test_multi_level_build_compatible(self):\n        c = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n           from conan import ConanFile\n           from conan.tools.build import check_min_cppstd\n\n           class Pkg(ConanFile):\n               name = \"{name}\"\n               version = \"0.1\"\n               settings = \"os\", \"compiler\"\n               {requires}\n\n               def validate(self):\n                   check_min_cppstd(self, {cppstd})\n            \"\"\")\n        c.save({\"liba/conanfile.py\": conanfile.format(name=\"liba\", cppstd=14, requires=\"\"),\n                \"libb/conanfile.py\": conanfile.format(name=\"libb\", cppstd=17,\n                                                      requires='requires=\"liba/0.1\"')})\n        c.run(\"export liba\")\n        c.run(\"export libb\")\n        settings = \"-s os=Windows -s compiler=gcc -s compiler.version=11 \" \\\n                   \"-s compiler.libcxx=libstdc++11 -s compiler.cppstd=11\"\n        c.run(f\"install --requires=libb/0.1 {settings}\", assert_error=True)\n        c.assert_listed_binary({\"liba/0.1\": (\"bb33db23c961978d08dc0cdd6bc786b45b3e5943\", \"Invalid\"),\n                                \"libb/0.1\": (\"144910d65b27bcbf7d544201f5578555bbd0376e\", \"Invalid\")})\n        assert \"liba/0.1: Invalid: Current cppstd (11)\" in c.out\n        assert \"libb/0.1: Invalid: Current cppstd (11)\" in c.out\n\n        c.run(f\"install --requires=libb/0.1 {settings} --build=compatible\")\n        # the one for cppstd=14 is built!!\n        c.assert_listed_binary({\"liba/0.1\": (\"389803bed06200476fcee1af2023d4e9bfa24ff9\", \"Build\"),\n                                \"libb/0.1\": (\"8f29f49be3ba2b6cbc9fa1e05432ce928b96ae5d\", \"Build\")})\n        c.run(\"list liba:*\")\n        assert \"compiler.cppstd: 14\" in c.out\n        c.run(\"list libb:*\")\n        assert \"compiler.cppstd: 17\" in c.out\n\n    def test_multi_level_build_compatible_build_order(self):\n        c = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n           from conan import ConanFile\n           from conan.tools.build import check_min_cppstd\n\n           class Pkg(ConanFile):\n               name = \"{name}\"\n               version = \"0.1\"\n               settings = \"os\", \"compiler\"\n               {requires}\n\n               def validate_build(self):\n                   check_min_cppstd(self, {cppstd})\n            \"\"\")\n        c.save({\"liba/conanfile.py\": conanfile.format(name=\"liba\", cppstd=14, requires=\"\"),\n                \"libb/conanfile.py\": conanfile.format(name=\"libb\", cppstd=17,\n                                                      requires='requires=\"liba/0.1\"')})\n        c.run(\"export liba\")\n        c.run(\"export libb\")\n        settings = \"-s os=Windows -s compiler=gcc -s compiler.version=11 \" \\\n                   \"-s compiler.libcxx=libstdc++11 -s compiler.cppstd=11\"\n        c.run(f\"graph build-order --requires=libb/0.1 {settings} --format=json\", assert_error=True,\n              redirect_stdout=\"build_order.json\")\n        c.assert_listed_binary({\"liba/0.1\": (\"bb33db23c961978d08dc0cdd6bc786b45b3e5943\", \"Missing\"),\n                                \"libb/0.1\": (\"144910d65b27bcbf7d544201f5578555bbd0376e\", \"Missing\")})\n\n        c.run(f\"graph build-order --requires=libb/0.1 {settings} --build=compatible \"\n              \"--order-by=configuration --format=json\", redirect_stdout=\"build_order.json\")\n        bo = json.loads(c.load(\"build_order.json\"))\n        liba = bo[\"order\"][0][0]\n        assert liba[\"ref\"] == \"liba/0.1#c1459d256a9c2d3c49d149fd7c43310c\"\n        assert liba[\"info\"][\"compatibility_delta\"] == {\"settings\": [[\"compiler.cppstd\", \"14\"]]}\n        assert liba[\"build_args\"] == \"--requires=liba/0.1 --build=compatible:liba/0.1\"\n        # Lets make sure the build works too\n        c.run(f\"install {settings} {liba['build_args']}\")\n        libb = bo[\"order\"][1][0]\n        assert libb[\"ref\"] == \"libb/0.1#62bb167aaa5306d1ac757bb817797f9e\"\n        assert libb[\"info\"][\"compatibility_delta\"] == {\"settings\": [[\"compiler.cppstd\", \"17\"]]}\n        assert libb[\"build_args\"] == \"--requires=libb/0.1 --build=compatible:libb/0.1\"\n        # Lets make sure the build works too\n        c.run(f\"install {settings} {libb['build_args']}\")\n\n        # Now lets make sure that build-order-merge works too\n        c.run(f\"graph build-order --requires=libb/0.1 {settings} -s compiler.version=12 \"\n              \"--build=compatible --order-by=configuration --format=json\",\n              redirect_stdout=\"build_order2.json\")\n\n        c.run(f\"graph build-order-merge --file=build_order.json --file=build_order2.json -f=json\",\n              redirect_stdout=\"build_order_merged.json\")\n        bo = json.loads(c.load(\"build_order_merged.json\"))\n        for pkg_index in (0, 1):\n            liba = bo[\"order\"][0][pkg_index]\n            assert liba[\"ref\"] == \"liba/0.1#c1459d256a9c2d3c49d149fd7c43310c\"\n            assert liba[\"info\"][\"compatibility_delta\"] == {\"settings\": [[\"compiler.cppstd\", \"14\"]]}\n            assert liba[\"build_args\"] == \"--requires=liba/0.1 --build=compatible:liba/0.1\"\n\n        # By recipe also works\n        c.run(\"remove *:* -c\")\n        c.run(f\"graph build-order --requires=libb/0.1 {settings} --build=compatible \"\n              \"--order-by=recipe --format=json\", redirect_stdout=\"build_order.json\")\n        bo = json.loads(c.load(\"build_order.json\"))\n        liba = bo[\"order\"][0][0]\n        assert liba[\"ref\"] == \"liba/0.1#c1459d256a9c2d3c49d149fd7c43310c\"\n        pkga = liba[\"packages\"][0][0]\n        assert pkga[\"info\"][\"compatibility_delta\"] == {\"settings\": [[\"compiler.cppstd\", \"14\"]]}\n        assert pkga[\"build_args\"] == \"--requires=liba/0.1 --build=compatible:liba/0.1\"\n        libb = bo[\"order\"][1][0]\n        assert libb[\"ref\"] == \"libb/0.1#62bb167aaa5306d1ac757bb817797f9e\"\n        pkgb = libb[\"packages\"][0][0]\n        assert pkgb[\"info\"][\"compatibility_delta\"] == {\"settings\": [[\"compiler.cppstd\", \"17\"]]}\n        assert pkgb[\"build_args\"] == \"--requires=libb/0.1 --build=compatible:libb/0.1\"\n\n        # Now lets make sure that build-order-merge works too\n        c.run(f\"graph build-order --requires=libb/0.1 {settings} -s compiler.version=12 \"\n              \"--order-by=recipe --build=compatible --format=json\",\n              redirect_stdout=\"build_order2.json\")\n        c.run(f\"graph build-order-merge --file=build_order.json --file=build_order2.json -f=json\",\n              redirect_stdout=\"build_order_merged.json\")\n        bo = json.loads(c.load(\"build_order_merged.json\"))\n        liba = bo[\"order\"][0][0]\n        assert liba[\"ref\"] == \"liba/0.1#c1459d256a9c2d3c49d149fd7c43310c\"\n        for pkg_index in (0, 1):\n            pkga = liba[\"packages\"][0][pkg_index]\n            assert pkga[\"info\"][\"compatibility_delta\"] == {\"settings\": [[\"compiler.cppstd\", \"14\"]]}\n            assert pkga[\"build_args\"] == \"--requires=liba/0.1 --build=compatible:liba/0.1\"\n\n    @pytest.mark.parametrize(\"validate, validate_build, expected\",\n                             [(\"pass\", \"pass\", 14),\n                              (\"check_min_cppstd(self, 17)\", \"pass\", 17),\n                              (\"pass\", \"check_min_cppstd(self, 20)\", 20),\n                              (\"check_min_cppstd(self, 17)\", \"check_min_cppstd(self, 20)\", 20)])\n    def test_compatible_build_test_package(self, validate, validate_build, expected):\n        \"\"\"\n        This test shows that the --build=compatible does not trigger the build of a dependency\n        twice when there is a \"test_package\"\n        \"\"\"\n        tc = TestClient()\n        conanfile = textwrap.dedent(f\"\"\"\n            from conan import ConanFile\n            from conan.tools.build import check_min_cppstd\n\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                settings = \"compiler\"\n\n                def validate(self):\n                    {validate}\n\n                def validate_build(self):\n                    {validate_build}\n            \"\"\")\n        tc.save({\"conanfile.py\": conanfile,\n                 \"test_package/conanfile.py\": GenConanfile().with_test(\"pass\")})\n\n        tc.run(\"create . -s os=Linux -s compiler=gcc -s compiler.version=13 \"\n               \"-s compiler.libcxx=libstdc++11 -s compiler.cppstd=14 --build=compatible:&\")\n        assert f\"compiler.cppstd={expected}\" in tc.out\n        # Without checking if the compatibles are already in the cache, it will build twice,\n        # once for the package and once for the test_package\n        assert tc.out.count(\"pkg/0.1: Building your package\") == 1\n        tc.run(\"list *:*\")\n        assert f\"compiler.cppstd: {expected}\" in tc.out\n\n    @pytest.mark.parametrize(\"validate, validate_build, expected\",\n                             [(\"check_min_cppstd(self, 17)\", \"pass\", 17),\n                              (\"pass\", \"check_min_cppstd(self, 20)\", 20),\n                              (\"check_min_cppstd(self, 17)\", \"check_min_cppstd(self, 20)\", 20)])\n    def test_compatible_consumer_rebuild(self, validate, validate_build, expected):\n        \"\"\"\n        This test shows that the --build=compatible does not trigger the build of a dependency\n        when it already exists in the cache\n        \"\"\"\n        tc = TestClient()\n        conanfile = textwrap.dedent(f\"\"\"\n            from conan import ConanFile\n            from conan.tools.build import check_min_cppstd\n\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                settings = \"compiler\"\n\n                def validate(self):\n                    {validate}\n\n                def validate_build(self):\n                    {validate_build}\n            \"\"\")\n        tc.save({\"pkg/conanfile.py\": conanfile,\n                 \"app/conanfile.py\": GenConanfile().with_requires(\"pkg/0.1\")})\n\n        settings = (\"-s os=Linux -s compiler=gcc -s compiler.version=13 \"\n                    \"-s compiler.libcxx=libstdc++11\")\n        tc.run(f\"create pkg {settings} -s compiler.cppstd=14 --build=compatible:&\")\n        tc.run(\"list *:*\")\n        assert f\"compiler.cppstd: {expected}\" in tc.out\n\n        if validate == \"pass\":\n            tc.run(f\"install app {settings} -s compiler.cppstd=14\")\n            assert (\"pkg/0.1: Found compatible package '151b937d845d306265254e74d7af81d35b2099fc': \"\n                    \"compiler.cppstd=20\") in tc.out\n        else:\n            tc.run(f\"install app {settings} -s compiler.cppstd=14\", assert_error=True)\n            assert \"pkg/0.1: Invalid: Current cppstd (14) is lower\" in tc.out\n\n        tc.run(f\"install app {settings} -s compiler.cppstd=14 --build=compatible\")\n        assert \"pkg/0.1: Found compatible package\" in tc.out\n\n        # Without checking if the compatibles are already in the cache, it will build twice,\n        # once for the package and once for the test_package\n        assert tc.out.count(\"pkg/0.1: Building your package\") == 0\n\n\ndef test_compatibility_new_setting_forwards_compat():\n    \"\"\" This test tries to reflect the following scenario:\n    - User adds a new setting (libc.version in this case)\n    - This setting is forward compatible\n    How is it solved with compatibility.py? Like this:\n    \"\"\"\n    tc = TestClient()\n    tc.save_home({\"settings_user.yml\": \"libc_version: [1, 2, 3]\"})\n    tc.save({\"conanfile.py\": GenConanfile(\"dep\", \"1.0\").with_settings(\"libc_version\", \"compiler\")})\n    # The extra cppstd and compiler versions are for later demonstrations of combinations of settings\n    # The cppstd=17 and compiler.version=193 are used thought until the last 2 install calls\n    tc.run(\"create . -s=libc_version=2 -s=compiler.cppstd=17\")\n    dep_package_id = tc.created_package_id(\"dep/1.0\")\n    tc.run(\"install --requires=dep/1.0 -s=libc_version=3 -s=compiler.cppstd=17\", assert_error=True)\n    # We can't compile, because the dep is not compatible\n    assert \"Missing prebuilt package for 'dep/1.0'\" in tc.out\n\n    # Let's create a compatibility extensions\n    libc_compat = textwrap.dedent(\"\"\"\n        from conan.tools.scm import Version\n\n        def libc_compat(conanfile):\n            # Do we have the setting?\n            libc_version = conanfile.settings.get_safe(\"libc_version\")\n            if libc_version is None:\n                return []\n            available_libc_versions = conanfile.settings.libc_version.possible_values()\n            ret = []\n            for possible_libc_version in available_libc_versions:\n                if Version(possible_libc_version) < Version(libc_version):\n                    ret.append({\"libc_version\": possible_libc_version})\n            return ret\n        \"\"\")\n    compat = tc.load_home(\"extensions/plugins/compatibility/compatibility.py\")\n    compat = \"from libc_compat import libc_compat\\n\" + compat\n    compat = compat.replace(\"# Append more factors for your custom compatibility rules here\",\n                            \"factors.append(libc_compat(conanfile))\")\n    tc.save_home({\"extensions/plugins/compatibility/libc_compat.py\": libc_compat,\n                  \"extensions/plugins/compatibility/compatibility.py\": compat})\n\n    # Now we try again, this time app will find the compatible dep with libc_version 2\n    tc.run(\"install --requires=dep/1.0 -s=libc_version=3 -s=compiler.cppstd=17\")\n    assert f\"dep/1.0: Found compatible package '{dep_package_id}'\" in tc.out\n\n    # And now we try to create the app with libc_version 1, which is still not compatible\n    tc.run(\"install --requires=dep/1.0 -s=libc_version=1 -s=compiler.cppstd=17\", assert_error=True)\n    assert \"Missing prebuilt package for 'dep/1.0'\" in tc.out\n\n    # Now we try again, this time app will find the compatible dep with libc_version 2\n    # And see how we're also compatible over a different cppstd\n    tc.run(\"install --requires=dep/1.0 -s=libc_version=3 -s=compiler.cppstd=14\")\n    assert f\"dep/1.0: Found compatible package '{dep_package_id}': compiler.cppstd=17, \" \\\n           f\"libc_version=2\" in tc.out\n\n\nclass TestListOnlyCompatibilityOptimization:\n\n    @pytest.fixture()\n    def client(self):\n        tc = TestClient(default_server_user=True, light=True)\n        compiler_settings = textwrap.dedent(\"\"\"\n                compiler:\n                    foo:\n                        version: [1]\n                        cppstd: [7, 11, 14, 17, 20, 23]\"\"\")\n        tc.run(\"version\")\n        tc.save_home({\"settings_user.yml\": compiler_settings})\n        compat = tc.load_home(\"extensions/plugins/compatibility/compatibility.py\")\n        compat = compat.replace(\"cppstd_possible_values = supported_cppstd(conanfile)\",\n                                \"cppstd_possible_values = [7, 11, 14, 17, 20, 23]\")\n        tc.save_home({\"extensions/plugins/compatibility/compatibility.py\": compat})\n        return tc\n\n    @pytest.mark.parametrize(\"update\", [True, False])\n    def test_remote_compatible_package(self, client, update):\n        tc = client\n        update_arg = \"-u\" if update else \"\"\n        compiler_args = \"-s compiler=foo -s compiler.version=1\"\n        tc.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_settings(\"compiler\")})\n        tc.run(f\"create . {compiler_args} -s=compiler.cppstd=14\")\n        std14_id = tc.created_layout().reference.package_id\n        tc.run(f\"create . {compiler_args} -s=compiler.cppstd=17\")\n        std17_id = tc.created_layout().reference.package_id\n        tc.run(f\"create . {compiler_args} -s=compiler.cppstd=20\")\n        std20_id = tc.created_layout().reference.package_id\n\n        tc.run(f\"upload pkg/0.1:{std20_id} -r=default -c\")\n        tc.run(f\"upload pkg/0.1:{std14_id} -r=default -c\")\n        tc.run(f\"upload pkg/0.1:{std17_id} -r=default -c\")\n\n        tc.run(\"remove * -c\")\n        tc.run(f\"install --requires=pkg/0.1 {compiler_args} -s=compiler.cppstd=11 {update_arg} \"\n               \"-cc core.graph:compatibility_mode=optimized\")\n        assert f\"Found compatible package '{std14_id}'\" in tc.out\n\n        tc.run(\"remove * -c\")\n        tc.run(f\"remove pkg/0.1:{std17_id} -r=default -c\")\n        tc.run(f\"install --requires=pkg/0.1 {compiler_args} -s=compiler.cppstd=17 {update_arg} \"\n               \"-cc core.graph:compatibility_mode=optimized\")\n        if not update:\n            assert \"Found 2 compatible configurations in remotes\" in tc.out\n        assert f\"Found compatible package '{std14_id}'\" in tc.out\n\n        tc.run(f\"create . {compiler_args} -s=compiler.cppstd=11\")\n        std11_layout = tc.created_layout()\n        std11_id = tc.created_layout().reference.package_id\n        tc.run(f\"upload pkg/0.1:{std11_id} -r=default -c\")\n        tc.run(\"remove * -c\")\n        tc.run(f\"install --requires=pkg/0.1 {compiler_args} -s=compiler.cppstd=17 -vvv {update_arg} \"\n               \"-cc core.graph:compatibility_mode=optimized\")\n        assert f\"Found compatible package '{std11_id}'\" in tc.out\n        # An HTTP request is made to the server to search for compatible packages\n        if not update:\n            assert \"Found 3 compatible configurations in remotes\" in tc.out\n            assert f\"{std11_layout.reference.ref.revision}/search?list_only=True\" in tc.out\n\n    def test_remote_compatible_package_update_cache(self, client):\n        tc = client\n        compiler_args = \"-s compiler=foo -s compiler.version=1\"\n        tc.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")\n                    .with_settings(\"compiler\")\n                    .with_import(\"import os, time\")\n                    .with_import(\"from conan.tools.files import save\")\n                    .with_package(\"save(self, os.path.join(self.package_folder, 'data.txt'), str(time.time()))\")\n        })\n        tc.run(f\"create . {compiler_args} -s=compiler.cppstd=17\")\n        std17_old_ref = tc.created_layout().reference\n        std17_id = std17_old_ref.package_id\n        tc.run(f\"create . {compiler_args} -s=compiler.cppstd=17\")\n        std17_new_ref = tc.created_layout().reference\n        assert std17_old_ref.revision != std17_new_ref.revision\n\n        tc.run(f\"upload pkg/0.1:{std17_id}#latest -r=default -c\")\n        tc.run(f\"remove pkg/0.1:{std17_id}#latest -c\")\n\n        tc.run(f\"install --requires=pkg/0.1 {compiler_args} -s=compiler.cppstd=11 -r=default -u \"\n               \"-cc core.graph:compatibility_mode=optimized\")\n        assert \"Current package revision is older than the remote one \"\n        assert f\"Found compatible package '{std17_id}'\" in tc.out\n        assert std17_old_ref.revision not in tc.out\n        assert std17_new_ref.revision in tc.out\n\n        tc.run(\"remove * -c\")\n        tc.run(\"remove * -r=default -c\")\n\n        tc.run(f\"create . {compiler_args} -s=compiler.cppstd=20\")\n        std20_old_ref = tc.created_layout().reference\n        std20_id = std20_old_ref.package_id\n        tc.run(f\"create . {compiler_args} -s=compiler.cppstd=20\")\n        std20_new_ref = tc.created_layout().reference\n        assert std20_old_ref.revision != std20_new_ref.revision\n\n        tc.run(f\"upload pkg/0.1:{std20_id}#* -r=default -c\")\n        tc.run(f\"remove pkg/0.1:{std20_id} -c\")\n\n        tc.run(f\"install --requires=pkg/0.1 {compiler_args} -s=compiler.cppstd=11 -r=default -u \"\n               \"-cc core.graph:compatibility_mode=optimized\")\n        assert f\"Found compatible package '{std20_id}'\" in tc.out\n        assert std20_old_ref.revision not in tc.out\n        assert std20_new_ref.revision in tc.out\n\n    @pytest.mark.parametrize(\"enable\", [True, False])\n    @pytest.mark.parametrize(\"from_remote\", [True, False])\n    def test_message_if_not_enabled(self, enable, from_remote):\n        tc = TestClient(default_server_user=True)\n        tc.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_settings(\"compiler\")})\n        tc.run(\"create . -s=compiler.cppstd=17\")\n        if from_remote:\n            tc.run(\"upload * -r=default -c\")\n            tc.run(\"remove * -c\")\n        arg = \"-cc core.graph:compatibility_mode=optimized\" if enable else \"\"\n        tc.run(f\"install --requires=pkg/0.1 -s=compiler.cppstd=14 {arg}\")\n        if not enable and from_remote:\n            assert \"A new experimental approach for binary compatibility detection is available\" in tc.out\n        else:\n            assert \"A new experimental approach for binary compatibility detection is available\" not in tc.out\n\n    @pytest.mark.parametrize(\"from_remote\", [True, False])\n    @pytest.mark.parametrize(\"update\", [True, False])\n    def test_compatibility_different_settings_per_context(self, from_remote, update):\n        tc = TestClient(default_server_user=True)\n        tc.save({\"protobuf/conanfile.py\": GenConanfile(\"protobuf\", \"1.0\")\n                .with_settings(\"compiler\"),\n                 \"conanfile.py\": GenConanfile(\"consumer\", \"1.0\")\n                .with_require(\"protobuf/1.0\")\n                .with_tool_requires(\"protobuf/1.0\")\n                 })\n        tc.run(\"create protobuf -s=compiler.cppstd=14\")\n        if from_remote:\n            tc.run(\"upload * -r=default -c\")\n            tc.run(\"remove * -c\")\n        update_arg = \"--update\" if update else \"\"\n        tc.run(\n            f\"install . -s=compiler.cppstd=14 -s:b=compiler.cppstd=17 --build=missing {update_arg} \"\n            \"-cc core.graph:compatibility_mode=optimized\")\n\n    @pytest.mark.parametrize(\"update\", [True, False])\n    def test_compatibility_different_settings_per_context_prevs(self, update):\n        tc = TestClient(default_server_user=True)\n        proto = GenConanfile(\"protobuf\", \"1.0\").with_settings(\"compiler\")\n        proto.with_package_file(\"file.txt\", env_var=\"MY_VAR\")\n        consumer = GenConanfile().with_requires(\"protobuf/1.0\").with_tool_requires(\"protobuf/1.0\")\n        tc.save({\"protobuf/conanfile.py\": proto,\n                 \"conanfile.py\": consumer})\n\n        settings = \"-s:a compiler=gcc -s:a compiler.version=9 -s:a compiler.libcxx=libstdc++\"\n        with environment_update({\"MY_VAR\": \"value\"}):\n            tc.run(f\"create protobuf {settings} -s=compiler.cppstd=14\")\n        tc.run(\"upload * -r=default -c\")\n\n        tc2 = TestClient(servers=tc.servers)\n        tc2.save({\"conanfile.py\": consumer})\n        update_arg = \"--update\" if update else \"\"\n        tc2.run(f\"install . {settings} -s=compiler.cppstd=14 -s:b=compiler.cppstd=17 {update_arg} \"\n                \"-cc core.graph:compatibility_mode=optimized\")\n        tc2.assert_listed_binary({\"protobuf/1.0\": (\"36d978cbb4dc35906d0fd438732d5e17cd1e388d\",\n                                                   \"Download (default)\")})\n\n        with environment_update({\"MY_VAR\": \"value2\"}):\n            tc.run(f\"create protobuf {settings} -s=compiler.cppstd=14\")\n        tc.run(\"upload * -r=default -c\")\n        tc2.run(f\"install . {settings} -s=compiler.cppstd=14 -s:b=compiler.cppstd=17 {update_arg} \"\n                \"-cc core.graph:compatibility_mode=optimized\")\n        origin = \"Cache\" if not update else \"Update (default)\"\n        tc2.assert_listed_binary({\"protobuf/1.0\": (\"36d978cbb4dc35906d0fd438732d5e17cd1e388d\",\n                                                   origin)})\n\n    def test_multi_remote(self):\n        # https://github.com/conan-io/conan/issues/19342\n        c = TestClient(servers={\"r1\": TestServer(), \"r2\": TestServer()},\n                       inputs=[\"admin\", \"password\"] * 2)\n\n        c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_settings(\"compiler\")})\n        c.run(f\"create . -s=compiler.cppstd=14\")\n\n        c.run(f\"upload * -r=r1 -c\")\n        c.run(f\"upload * -r=r2 -c\")\n        c.run(\"remove * -c\")\n        c.run(f\"install --requires=pkg/0.1 -s=compiler.cppstd=17 \"\n              \"-cc core.graph:compatibility_mode=optimized\")\n        # It doesn't crash\n        assert \"pkg/0.1: Found 1 compatible configurations in remotes\" in c.out\n\n\ndef test_compatibility_remove_cppstd():\n    \"\"\" This test tries to reflect the following scenario:\n    - User recently added compiler.cppstd to their settings\n    - But up until now, no package was built with that setting\n    - At the user's own risk, we can tell Conan to accept packages built without that setting\n    \"\"\"\n    tc = TestClient()\n    profile = textwrap.dedent(\"\"\"\n        [settings]\n        compiler=gcc\n        compiler.version=11\n        compiler.libcxx=libstdc++11\n        \"\"\")\n    tc.save({\"conanfile.py\": GenConanfile(\"dep\", \"1.0\").with_settings(\"compiler\"),\n             \"profile\": profile})\n    tc.run(\"create . -pr=profile\")\n    dep_package_id = tc.created_package_id(\"dep/1.0\")\n    tc.run(\"install --requires=dep/1.0 -pr=profile -s=compiler.cppstd=17\", assert_error=True)\n    # We can't compile, because the dep is not compatible, it's looking for a package with cppstd\n    assert \"Missing prebuilt package for 'dep/1.0'\" in tc.out\n\n    # Let's create a compatibility extensions\n    no_cppstd_compat = textwrap.dedent(\"\"\"\n        from conan.tools.scm import Version\n\n        def no_cppstd_compat(conanfile):\n            # Do we have the setting?\n            cppstd_version = conanfile.settings.get_safe(\"compiler.cppstd\")\n            if cppstd_version is None:\n                return []\n            return [{\"compiler.cppstd\": None}]\n        \"\"\")\n    compat = tc.load_home(\"extensions/plugins/compatibility/compatibility.py\")\n    compat = \"from no_cppstd_compat import no_cppstd_compat\\n\" + compat\n    compat = compat.replace(\"# Append more factors for your custom compatibility rules here\",\n                            \"factors.append(no_cppstd_compat(conanfile))\")\n    tc.save_home({\"extensions/plugins/compatibility/no_cppstd_compat.py\": no_cppstd_compat,\n                  \"extensions/plugins/compatibility/compatibility.py\": compat})\n\n    # Now we try again, this time app will find the compatible dep without cppstd\n    tc.run(\"install --requires=dep/1.0 -pr=profile -s=compiler.cppstd=17\")\n    assert f\"dep/1.0: Found compatible package '{dep_package_id}'\" in tc.out\n\n\ndef test_compatible_setting():\n    c = TestClient()\n    profile = textwrap.dedent(\"\"\"\n        [settings]\n        os = Linux\n        compiler=gcc\n        compiler.version=11\n        compiler.libcxx=libstdc++\n        \"\"\")\n    pkg = GenConanfile(version=\"0.1\").with_settings(\"os\", \"compiler\").with_tool_requires(\"tool/0.1\")\n    c.save({\"tool/conanfile.py\": GenConanfile(\"tool\", \"0.1\").with_settings(\"os\", \"compiler\"),\n            \"pkg/conanfile.py\": pkg,\n            \"profile\": profile})\n\n    c.run(\"export tool\")\n    c.run(\"export pkg --name=pkga\")\n    c.run(\"export pkg --name=pkgb\")\n    c.run(\"export pkg --name=pkgc\")\n\n    c.run(\"install --requires=pkga/0.1 --requires=pkgb/0.1 --requires=pkgc/0.1 \"\n          \"-pr:a=profile -s:a compiler.cppstd=17 --build=pkg*\", assert_error=True)\n    assert str(c.out).count(\"tool/0.1: Main binary package \"\n                            \"'e297d0212cdeb8744c601b0e5ea294e62a74582f' missing\") == 1\n"
  },
  {
    "path": "test/integration/package_id/package_id_and_confs_test.py",
    "content": "import textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import GenConanfile, TestClient, NO_SETTINGS_PACKAGE_ID\n\nPKG_ID_NO_CONF = \"ebec3dc6d7f6b907b3ada0c3d3cdc83613a2b715\"\nPKG_ID_1 = \"89d32f25195a77f4ae2e77414b870781853bdbc1\"\nPKG_ID_2 = \"7f9ed92704709f56ecc7b133322479caf3ffd7ad\"\nPKG_ID_3 = \"a9f917f3bad3b48b5bceae70214764274ccd6337\"\nPKG_ID_USER_1 = \"571b5dae13b37a78c1993842739bd475879092ea\"\nPKG_ID_USER_2 = \"54a394d26f9c35add86f20ac02cacc3c7e18f02c\"\nPKG_ID_USER_3 = \"54a394d26f9c35add86f20ac02cacc3c7e18f02c\"\n\n\n@pytest.mark.parametrize(\"package_id_confs, package_id\", [\n    ('[]', PKG_ID_NO_CONF),\n    ('[\"user.fake:no_existing_conf\"]', PKG_ID_NO_CONF),\n    ('[\"tools.build:cxxflags\", \"tools.build:cflags\"]', PKG_ID_1),\n    ('[\"tools.build:defines\"]', PKG_ID_2),\n    ('[\"tools.build:cxxflags\", \"tools.build:sharedlinkflags\"]', PKG_ID_3),\n    ('[\"user.foo:value\"]', PKG_ID_USER_1),\n    ('[\"user.foo:value\", \"user.bar:value\"]', PKG_ID_USER_2),\n    ('[\"user.*\"]', PKG_ID_USER_3),\n])\ndef test_package_id_including_confs(package_id_confs, package_id):\n    client = TestClient()\n    profile = textwrap.dedent(f\"\"\"\n    include(default)\n    [conf]\n    tools.info.package_id:confs={package_id_confs}\n    tools.build:cxxflags=[\"--flag1\", \"--flag2\"]\n    tools.build:cflags+=[\"--flag3\", \"--flag4\"]\n    tools.build:sharedlinkflags=+[\"--flag5\", \"--flag6\"]\n    tools.build:exelinkflags=[\"--flag7\", \"--flag8\"]\n    tools.build:defines=[\"D1\", \"D2\"]\n\n    user.foo:value=1\n    user.bar:value=2\n    \"\"\")\n    client.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_settings(\"os\"),\n                 \"profile\": profile})\n    client.run('create . -s os=Windows -pr profile')\n    client.assert_listed_binary({\"pkg/0.1\": (package_id, \"Build\")})\n\n\nPKG_ID_4 = \"9b334fc314f2f2ce26e5280901eabcdd7b3f55a6\"\nPKG_ID_5 = \"5510413d2e6186662cb473fb16ce0a18a3f9e98f\"\n\n\n@pytest.mark.parametrize(\"cxx_flags, package_id\", [\n    ('[]', PKG_ID_NO_CONF),\n    ('[\"--flag1\", \"--flag2\"]', PKG_ID_4),\n    ('[\"--flag3\", \"--flag4\"]', PKG_ID_5),\n])\ndef test_same_package_id_configurations_but_changing_values(cxx_flags, package_id):\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            settings = \"os\"\n        \"\"\")\n    profile = textwrap.dedent(f\"\"\"\n    include(default)\n    [conf]\n    tools.info.package_id:confs=[\"tools.build:cxxflags\"]\n    tools.build:cxxflags={cxx_flags}\n    tools.build:cflags+=[\"--flag3\", \"--flag4\"]\n    tools.build:sharedlinkflags=+[\"--flag5\", \"--flag6\"]\n    tools.build:exelinkflags=[\"--flag7\", \"--flag8\"]\n    tools.build:defines=[\"D1\", \"D2\"]\n    \"\"\")\n    client.save({\"conanfile.py\": conanfile, \"profile\": profile})\n    client.run('create . --name=pkg --version=0.1 -s os=Windows -pr profile')\n    client.assert_listed_binary({\"pkg/0.1\": (package_id, \"Build\")})\n\n\ndef test_package_id_confs_header_only():\n    \"\"\"\n    The tools.info.package_id:confs cannot affect header-only libraries\n    and any other library that does ``self.info.clear()`` in ``package_id()`` method\n    \"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            package_type = \"header-library\"\n            implements = [\"auto_header_only\"]\n        \"\"\")\n    profile = textwrap.dedent(f\"\"\"\n        include(default)\n        [conf]\n        tools.info.package_id:confs=[\"tools.build:cxxflags\"]\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile, \"profile\": profile})\n    client.run('create . --name=pkg --version=0.1 -pr profile -c tools.build:cxxflags=[\"--flag1\"]')\n    client.assert_listed_binary({\"pkg/0.1\": (NO_SETTINGS_PACKAGE_ID, \"Build\")})\n    client.run(\"list *:*\")\n    assert \"tools.build:cxxflags\" not in client.out\n    client.run('create . --name=pkg --version=0.1 -pr profile -c tools.build:cxxflags=[\"--flag2\"]')\n    client.assert_listed_binary({\"pkg/0.1\": (NO_SETTINGS_PACKAGE_ID, \"Build\")})\n    client.run(\"list *:*\")\n    assert \"tools.build:cxxflags\" not in client.out\n\n\ndef test_conf_pkg_id_user_pattern_not_defined():\n    tc = TestClient(light=True)\n    tc.save({\"lib/conanfile.py\": GenConanfile(\"lib\", \"1.0\")})\n    tc.save_home({\"global.conf\": \"tools.info.package_id:confs=['user.*']\"})\n\n    # This used to break the build because `user.*` conf was not valid\n    tc.run(\"create lib\")\n    assert \"lib/1.0: Package 'da39a3ee5e6b4b0d3255bfef95601890afd80709' created\" in tc.out\n\n\n@pytest.mark.parametrize(\"conf,pkgconf\", [\n    (\"user.foo:value=1\\nuser.bar:value=2\", \"['user.foo:value', 'user.bar:value']\"),\n    (\"user.foo:value=1\\nuser.bar:value=2\", \"['user.bar:value', 'user.foo:value']\"),\n    (\"user.bar:value=2\\nuser.foo:value=1\", \"['user.foo:value', 'user.bar:value']\"),\n    (\"user.bar:value=2\\nuser.foo:value=1\", \"['user.bar:value', 'user.foo:value']\"),\n])\ndef test_package_id_order(conf, pkgconf):\n    \"\"\"Ensure the order of the definitions in the conf file does not affect the package_id\"\"\"\n    tc = TestClient(light=True)\n    tc.save({\"profile\": f\"[conf]\\ntools.info.package_id:confs={pkgconf}\\n\" +\n                        conf,\n             \"conanfile.py\": GenConanfile(\"pkg\", \"1.0\")})\n    tc.run(\"create . -pr=profile\")\n    # They should all have the same pkg id - note that this did not happen before 2.0.17\n    tc.assert_listed_binary({\"pkg/1.0\": (\"43227c40b8725e89d30a9f97c0652629933a3685\", \"Build\")})\n"
  },
  {
    "path": "test/integration/package_id/package_id_modes_test.py",
    "content": "import textwrap\n\nfrom conan.test.utils.tools import GenConanfile, TestClient\n\n\ndef test_basic_default_modes_unknown():\n    c = TestClient()\n    c.save({\"matrix/conanfile.py\": GenConanfile(\"matrix\"),\n            \"engine/conanfile.py\": GenConanfile(\"engine\", \"1.0\").with_requires(\"matrix/[*]\")})\n    c.run(\"create matrix --version=1.0\")\n    c.run(\"create engine\")\n    package_id = c.created_package_id(\"engine/1.0\")\n\n    # Using a patch version doesn't kick a engine rebuild\n    c.run(\"create matrix --version=1.0.1\")\n    c.run(\"create engine --build=missing\")\n    c.assert_listed_require({\"matrix/1.0.1\": \"Cache\"})\n    c.assert_listed_binary({\"engine/1.0\": (package_id, \"Cache\")})\n\n    # same with minor version will not need rebuild\n    c.run(\"create matrix --version=1.1.0\")\n    c.run(\"create engine --build=missing\")\n    c.assert_listed_require({\"matrix/1.1.0\": \"Cache\"})\n    c.assert_listed_binary({\"engine/1.0\": (package_id, \"Cache\")})\n\n    # Major will require re-build\n    # TODO: Reconsider this default\n    c.run(\"create matrix --version=2.0.0\")\n    c.run(\"create engine --build=missing\")\n    c.assert_listed_require({\"matrix/2.0.0\": \"Cache\"})\n    c.assert_listed_binary({\"engine/1.0\": (\"805fafebc9f7769a90dafb8c008578c6aa7f5d86\", \"Build\")})\n\n\ndef test_basic_default_modes_application():\n    \"\"\"\n    if the consumer package is a declared \"package_type = \"application\"\" recipe_revision_mode will\n    be used\n    \"\"\"\n    c = TestClient()\n    c.save({\"matrix/conanfile.py\": GenConanfile(\"matrix\"),\n            \"engine/conanfile.py\": GenConanfile(\"engine\", \"1.0\").with_requires(\"matrix/[*]\")\n                                                                .with_package_type(\"application\")})\n    c.run(\"create matrix --version=1.0\")\n    c.run(\"create engine\")\n    package_id = c.created_package_id(\"engine/1.0\")\n\n    # Using a patch version requires a rebuild\n    c.run(\"create matrix --version=1.0.1\")\n    c.run(\"create engine --build=missing\")\n    c.assert_listed_require({\"matrix/1.0.1\": \"Cache\"})\n    new_package_id = \"efe870a1b1b4fe60e55aa6e2d17436665404370f\"\n    assert new_package_id != package_id\n    c.assert_listed_binary({\"engine/1.0\": (new_package_id, \"Build\")})\n\n\nclass TestDepDefinedMode:\n    def test_dep_defined(self):\n        c = TestClient()\n        dep = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Dep(ConanFile):\n                name = \"dep\"\n                package_type = \"static-library\"\n                package_id_embed_mode = \"major_mode\"\n                package_id_non_embed_mode = \"major_mode\"\n            \"\"\")\n        c.save({\"dep/conanfile.py\": dep,\n                \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_requires(\"dep/[*]\")\n                                                              .with_shared_option(False)})\n        c.run(\"create dep --version=0.1\")\n        c.run(\"create pkg\")\n        c.assert_listed_binary({\"pkg/0.1\": (\"66a9e6a31e63f77952fd72744d0d5da07970f42e\", \"Build\")})\n        c.run(\"create pkg -o pkg/*:shared=True\")\n        c.assert_listed_binary({\"pkg/0.1\": (\"5a5828e18eef6a86813b01d4f5a83ea7d87d1139\", \"Build\")})\n\n        # using dep 0.2, still same, because dependency chose \"major_mode\"\n        c.run(\"create dep --version=0.2\")\n        c.run(\"create pkg\")\n        c.assert_listed_binary({\"pkg/0.1\": (\"66a9e6a31e63f77952fd72744d0d5da07970f42e\", \"Build\")})\n        c.run(\"create pkg -o pkg/*:shared=True\")\n        c.assert_listed_binary({\"pkg/0.1\": (\"5a5828e18eef6a86813b01d4f5a83ea7d87d1139\", \"Build\")})\n\n    def test_dep_tool_require_defined(self):\n        c = TestClient()\n        dep = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Dep(ConanFile):\n                name = \"dep\"\n                package_type = \"application\"\n                build_mode = \"minor_mode\"\n            \"\"\")\n        c.save({\"dep/conanfile.py\": dep,\n                \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_tool_requires(\"dep/[*]\")})\n        c.run(\"create dep --version=0.1\")\n        c.run(\"create pkg\")\n        c.assert_listed_binary({\"pkg/0.1\": (\"fcf70699eb821f51cd4f3e228341ac4f405ad220\", \"Build\")})\n\n        # using dep 0.2, still same, because dependency chose \"minor\"\n        c.run(\"create dep --version=0.1.1\")\n        c.run(\"create pkg\")\n        c.assert_listed_binary({\"pkg/0.1\": (\"fcf70699eb821f51cd4f3e228341ac4f405ad220\", \"Build\")})\n\n        # using dep 0.2, still same, because dependency chose \"minor\"\n        c.run(\"create dep --version=0.2\")\n        c.run(\"create pkg\")\n        c.assert_listed_binary({\"pkg/0.1\": (\"56934f87c11792e356423e081c7cd490f3c1fbe0\", \"Build\")})\n\n    def test_dep_python_require_defined(self):\n        c = TestClient()\n        dep = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Dep(ConanFile):\n                name = \"dep\"\n                package_type = \"python-require\"\n                package_id_python_mode = \"major_mode\"\n            \"\"\")\n        c.save({\"dep/conanfile.py\": dep,\n                \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_python_requires(\"dep/[*]\")})\n        c.run(\"create dep --version=0.1\")\n        c.run(\"create pkg\")\n        c.assert_listed_binary({\"pkg/0.1\": (\"331c17383dcdf37f79bc2b86fa55ac56afdc6fec\", \"Build\")})\n\n        # using dep 0.2, still same, because dependency chose \"major\"\n        c.run(\"create dep --version=0.1.1\")\n        c.run(\"create pkg\")\n        c.assert_listed_binary({\"pkg/0.1\": (\"331c17383dcdf37f79bc2b86fa55ac56afdc6fec\", \"Build\")})\n\n        # using dep 0.2, still same, because dependency chose \"major\"\n        c.run(\"create dep --version=0.2\")\n        c.run(\"create pkg\")\n        c.assert_listed_binary({\"pkg/0.1\": (\"331c17383dcdf37f79bc2b86fa55ac56afdc6fec\", \"Build\")})\n        c.run(\"list *:*\")\n        assert \"dep/0.Y.Z\" in c.out\n\n        # using dep 0.2, new package_id, because dependency chose \"major\"\n        c.run(\"create dep --version=1.0\")\n        c.run(\"create pkg\")\n        c.assert_listed_binary({\"pkg/0.1\": (\"9b015e30b768df0217ffa2c270f60227c998e609\", \"Build\")})\n        c.run(\"list *:*\")\n        assert \"dep/1.Y.Z\" in c.out\n"
  },
  {
    "path": "test/integration/package_id/package_id_requires_modes_test.py",
    "content": "import textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient, GenConanfile\n\n\nclass TestPackageIDRequirementsModes:\n\n    @pytest.mark.parametrize(\"mode, accepted_version, rejected_version, pattern\",\n                             [(\"unrelated_mode\", \"2.0\", \"\", \"\"),\n                              (\"patch_mode\", \"1.0.0.1\", \"1.0.1\", \"1.0.1\"),\n                              (\"minor_mode\", \"1.0.1\", \"1.2\", \"1.2.Z\"),\n                              (\"major_mode\", \"1.5\", \"2.0\", \"2.Y.Z\"),\n                              (\"semver_mode\", \"1.5\", \"2.0\", \"2.Y.Z\"),\n                              (\"full_mode\", \"1.0\", \"1.0.0.1\", \"1.0.0.1\")])\n    def test(self, mode, accepted_version, rejected_version, pattern):\n        c = TestClient()\n        package_id_text = f'self.info.requires[\"dep\"].{mode}()'\n        c.save({\"dep/conanfile.py\": GenConanfile(\"dep\"),\n                \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_requires(\"dep/[*]\")\n                                                              .with_package_id(package_id_text)})\n        c.run(\"create dep --version=1.0\")\n        pkgid = c.created_package_id(\"dep/1.0\")\n        c.run(\"create pkg\")\n        c.run(f\"create dep --version={accepted_version}\")\n        c.run(\"install --requires=pkg/0.1\")  # binary existing\n        c.assert_listed_binary({f\"dep/{accepted_version}\": (pkgid, \"Cache\")})\n        if rejected_version:\n            c.run(f\"create dep --version={rejected_version}\")\n            c.run(\"install --requires=pkg/0.1\", assert_error=True)  # binary missing\n            assert \"ERROR: Missing prebuilt package for 'pkg/0.1'\" in c.out\n            assert f\"dep/{pattern}\" in c.out\n\n\n@pytest.mark.parametrize(\"mode, pkg_id\",\n                         [(\"unrelated_mode\", \"da39a3ee5e6b4b0d3255bfef95601890afd80709\"),\n                          (\"semver_mode\", \"13b9e753af3958dd1b2d4b3f935b04b8fb6b6760\"),\n                          (\"patch_mode\", \"38d7a3ec6a09165ab3e5306f81c539a2e0a784bd\"),\n                          (\"minor_mode\", \"a5e7ad26ccf4a5049090976846da1c6ed165cced\"),\n                          (\"major_mode\", \"6ac597ffb99c3747ed78699f206dc1041537a8df\"),\n                          # This is equal to semver_mode for 0.X.Y.Z..\n                          (\"full_version_mode\", \"13b9e753af3958dd1b2d4b3f935b04b8fb6b6760\"),\n                          (\"full_recipe_mode\", \"13b9e753af3958dd1b2d4b3f935b04b8fb6b6760\"),\n                          (\"full_package_mode\", \"19906d8a245d9f466d7d7f697c666222a9854a1a\"),\n                          (\"revision_mode\", \"ae5b9eeb74880aeb1cfa3db7f84c007a05ce3a76\"),\n                          (\"full_mode\", \"d1b2a9538cd69363b4bae7e66c9f900b8f4c58bb\")])\ndef test_modes(mode, pkg_id):\n    c = TestClient(light=True)\n    package_id_text = f'self.info.requires.{mode}()'\n    c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1.1.1\").with_settings(\"os\"),\n            \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_requires(\"dep/[*]\")\n                                                          .with_package_id(package_id_text)})\n    c.run(\"create dep -s os=Linux\")\n    c.run(\"create pkg -s os=Linux\")\n    pkgid = c.created_package_id(\"pkg/0.1\")\n    assert pkgid == pkg_id\n\n\nclass TestPackageIDError:\n\n    def test_transitive_multi_mode_package_id(self):\n        # https://github.com/conan-io/conan/issues/6942\n        client = TestClient()\n        client.save({\"conanfile.py\": GenConanfile()})\n        client.run(\"export . --name=dep1 --version=1.0 --user=user --channel=testing\")\n        client.save({\"conanfile.py\": GenConanfile().with_require(\"dep1/1.0@user/testing\")})\n        client.run(\"export . --name=dep2 --version=1.0 --user=user --channel=testing\")\n\n        pkg_revision_mode = \"self.info.requires.recipe_revision_mode()\"\n        client.save({\"conanfile.py\": GenConanfile().with_require(\"dep1/1.0@user/testing\")\n                                                   .with_package_id(pkg_revision_mode)})\n        client.run(\"export . --name=dep3 --version=1.0 --user=user --channel=testing\")\n\n        client.save({\"conanfile.py\": GenConanfile().with_require(\"dep2/1.0@user/testing\")\n                                                   .with_require(\"dep3/1.0@user/testing\")})\n        client.run('create . --name=consumer --version=1.0 --user=user --channel=testing --build=*')\n        assert \"consumer/1.0@user/testing: Created\" in client.out\n\n    def test_transitive_multi_mode2_package_id(self):\n        # https://github.com/conan-io/conan/issues/6942\n        client = TestClient()\n        # This is mandatory, otherwise it doesn't work\n        client.save({\"conanfile.py\": GenConanfile()})\n        client.run(\"export . --name=dep1 --version=1.0 --user=user --channel=testing\")\n\n        pkg_revision_mode = \"self.info.requires.full_version_mode()\"\n        package_id_print = \"self.output.info('PkgNames: %s' % sorted(self.info.requires.pkg_names))\"\n        client.save({\"conanfile.py\": GenConanfile().with_require(\"dep1/1.0@user/testing\")\n                    .with_package_id(pkg_revision_mode)\n                    .with_package_id(package_id_print)})\n        client.run(\"export . --name=dep2 --version=1.0 --user=user --channel=testing\")\n\n        consumer = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Consumer(ConanFile):\n                requires = \"dep2/1.0@user/testing\"\n                def package_id(self):\n                    self.output.info(\"PKGNAMES: %s\" % sorted(self.info.requires.pkg_names))\n                \"\"\")\n        client.save({\"conanfile.py\": consumer})\n        client.run('create . --name=consumer --version=1.0 --user=user --channel=testing --build=*')\n        assert \"dep2/1.0@user/testing: PkgNames: ['dep1']\" in client.out\n        assert \"consumer/1.0@user/testing: PKGNAMES: ['dep1', 'dep2']\" in client.out\n        assert \"consumer/1.0@user/testing: Created\" in client.out\n\n    def test_transitive_multi_mode_build_requires(self):\n        # https://github.com/conan-io/conan/issues/6942\n        client = TestClient()\n        client.save({\"conanfile.py\": GenConanfile()})\n        client.run(\"export . --name=dep1 --version=1.0 --user=user --channel=testing\")\n        client.run(\"create . --name=tool --version=1.0 --user=user --channel=testing\")\n\n        pkg_revision_mode = \"self.info.requires.full_version_mode()\"\n        package_id_print = \"self.output.info('PkgNames: %s' % sorted(self.info.requires.pkg_names))\"\n        client.save({\"conanfile.py\": GenConanfile().with_require(\"dep1/1.0@user/testing\")\n                    .with_tool_requires(\"tool/1.0@user/testing\")\n                    .with_package_id(pkg_revision_mode)\n                    .with_package_id(package_id_print)})\n        client.run(\"export . --name=dep2 --version=1.0 --user=user --channel=testing\")\n\n        consumer = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Consumer(ConanFile):\n                requires = \"dep2/1.0@user/testing\"\n                build_requires = \"tool/1.0@user/testing\"\n                def package_id(self):\n                    self.output.info(\"PKGNAMES: %s\" % sorted(self.info.requires.pkg_names))\n                \"\"\")\n        client.save({\"conanfile.py\": consumer})\n        client.run('create . --name=consumer --version=1.0 --user=user --channel=testing --build=*')\n        assert \"dep2/1.0@user/testing: PkgNames: ['dep1']\" in client.out\n        assert \"consumer/1.0@user/testing: PKGNAMES: ['dep1', 'dep2']\" in client.out\n        assert \"consumer/1.0@user/testing: Created\" in client.out\n\n\nclass TestRequirementPackageId:\n    \"\"\" defining requires(..., package_id_mode)\n    \"\"\"\n\n    @pytest.mark.parametrize(\"mode, pattern\",\n                             [(\"patch_mode\", \"1.2.3\"),\n                              (\"minor_mode\", \"1.2.Z\"),\n                              (\"major_mode\",  \"1.Y.Z\")])\n    def test(self, mode, pattern):\n        c = TestClient(light=True)\n        pkg = GenConanfile(\"pkg\", \"0.1\").with_requirement(\"dep/1.2.3\", package_id_mode=mode)\n        c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"1.2.3\"),\n                \"pkg/conanfile.py\": pkg})\n        c.run(\"create dep\")\n        c.run(\"create pkg\")\n        c.run(\"list pkg:*\")\n        assert f\"dep/{pattern}\" in c.out\n\n    def test_wrong_mode(self):\n        c = TestClient(light=True)\n        pkg = GenConanfile(\"pkg\", \"0.1\").with_requirement(\"dep/1.2.3\", package_id_mode=\"nothing\")\n        c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"1.2.3\"),\n                \"pkg/conanfile.py\": pkg})\n        c.run(\"create dep\")\n        c.run(\"create pkg\", assert_error=True)\n        assert \"ERROR: require dep/1.2.3 package_id_mode='nothing' is not a known package_id_mode\" \\\n               in c.out\n\n    @pytest.mark.parametrize(\"mode, pattern\",\n                             [(\"patch_mode\", \"1.2.3\"),\n                              (\"minor_mode\", \"1.2.Z\"),\n                              (\"major_mode\", \"1.Y.Z\")])\n    def test_half_diamond(self, mode, pattern):\n        # pkg -> libb -> liba\n        #  \\----(mode)----/\n        c = TestClient(light=True)\n        pkg = GenConanfile(\"pkg\", \"0.1\").with_requirement(\"liba/1.2.3\", package_id_mode=mode)\\\n                                        .with_requirement(\"libb/1.2.3\")\n        c.save({\"liba/conanfile.py\": GenConanfile(\"liba\", \"1.2.3\"),\n                \"libb/conanfile.py\": GenConanfile(\"libb\", \"1.2.3\").with_requires(\"liba/1.2.3\"),\n                \"pkg/conanfile.py\": pkg})\n        c.run(\"create liba\")\n        c.run(\"create libb\")\n        c.run(\"create pkg\")\n        c.run(\"list pkg:*\")\n        assert f\"liba/{pattern}\" in c.out\n        # reverse order also works the same\n        pkg = GenConanfile(\"pkg\", \"0.1\").with_requirement(\"libb/1.2.3\")\\\n                                        .with_requirement(\"liba/1.2.3\", package_id_mode=mode)\n        c.save({\"pkg/conanfile.py\": pkg})\n        c.run(\"create pkg\")\n        c.run(\"list pkg:*\")\n        assert f\"liba/{pattern}\" in c.out\n\n    @pytest.mark.parametrize(\"mode, pattern\",\n                             [(\"patch_mode\", \"1.2.3\"),\n                              (\"minor_mode\", \"1.2.Z\"),\n                              (\"major_mode\", \"1.Y.Z\")])\n    def test_half_diamond_conflict(self, mode, pattern):\n        # pkg -> libb --(mode)-> liba\n        #  \\----(mode)-----------/\n        # The libb->liba mode is not propagated down to pkg, so it doesn't really conflict\n        c = TestClient(light=True)\n        pkg = GenConanfile(\"pkg\", \"0.1\").with_requirement(\"liba/1.2.3\", package_id_mode=mode) \\\n            .with_requirement(\"libb/1.2.3\")\n        libb = GenConanfile(\"libb\", \"1.2.3\").with_requirement(\"liba/1.2.3\",\n                                                              package_id_mode=\"patch_mode\")\n        c.save({\"liba/conanfile.py\": GenConanfile(\"liba\", \"1.2.3\"),\n                \"libb/conanfile.py\": libb,\n                \"pkg/conanfile.py\": pkg})\n        c.run(\"create liba\")\n        c.run(\"create libb\")\n        c.run(\"create pkg\")\n        c.run(\"list pkg:*\")\n        assert f\"liba/{pattern}\" in c.out\n        # reverse order also works the same\n        pkg = GenConanfile(\"pkg\", \"0.1\").with_requirement(\"libb/1.2.3\") \\\n            .with_requirement(\"liba/1.2.3\", package_id_mode=mode)\n        c.save({\"pkg/conanfile.py\": pkg})\n        c.run(\"create pkg\")\n        c.run(\"list pkg:*\")\n        assert f\"liba/{pattern}\" in c.out\n"
  },
  {
    "path": "test/integration/package_id/package_id_test.py",
    "content": "import textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import NO_SETTINGS_PACKAGE_ID, TestClient\nfrom conan.internal.util.files import save\n\n\ndef test_double_package_id_call():\n    # https://github.com/conan-io/conan/issues/3085\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class TestConan(ConanFile):\n            settings = \"os\", \"arch\"\n\n            def package_id(self):\n                self.output.info(\"Calling package_id()\")\n        \"\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=pkg --version=0.1 --user=user --channel=testing\")\n    out = str(client.out)\n    assert 1 == out.count(\"pkg/0.1@user/testing: Calling package_id()\")\n\n\ndef test_remove_option_setting():\n    # https://github.com/conan-io/conan/issues/2826\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class TestConan(ConanFile):\n            settings = \"os\"\n            options = {\"opt\": [True, False]}\n            default_options = {\"opt\": False}\n\n            def package_id(self):\n                self.output.info(\"OPTION OPT=%s\" % self.info.options.opt)\n                del self.info.settings.os\n                del self.info.options.opt\n        \"\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=pkg --version=0.1 --user=user --channel=testing -s os=Windows\")\n    assert \"pkg/0.1@user/testing: OPTION OPT=False\" in client.out\n    assert \"pkg/0.1@user/testing: Package '%s' created\" % NO_SETTINGS_PACKAGE_ID in client.out\n    client.run(\"create . --name=pkg --version=0.1 --user=user --channel=testing -s os=Linux -o pkg/*:opt=True\")\n    assert \"pkg/0.1@user/testing: OPTION OPT=True\" in client.out\n    assert \"pkg/0.1@user/testing: Package '%s' created\" % NO_SETTINGS_PACKAGE_ID in client.out\n\n\ndef test_value_parse():\n    # https://github.com/conan-io/conan/issues/2816\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class TestConan(ConanFile):\n            name = \"test\"\n            version = \"0.1\"\n            settings = \"os\", \"arch\", \"build_type\"\n\n            def package_id(self):\n                self.info.settings.arch = \"kk=kk\"\n                self.info.settings.os = \"yy=yy\"\n        \"\"\")\n\n    client = TestClient(default_server_user=True)\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . \")\n    client.run(\"list *:*\")\n    assert \"arch: kk=kk\" in client.out\n    client.run(\"upload * -r default -c\")\n    client.run(\"list *:* -r=default\")\n    assert \"arch: kk=kk\" in client.out\n    client.run(\"remove * -c\")\n    client.run(\"install --requires=test/0.1\")\n    client.run(\"list *:*\")\n    assert \"arch: kk=kk\" in client.out\n\n\ndef test_option_in():\n    # https://github.com/conan-io/conan/issues/7299\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class TestConan(ConanFile):\n            options = {\"fpic\": [True, False]}\n            default_options = {\"fpic\": True}\n            def package_id(self):\n                if \"fpic\" in self.info.options:\n                    self.output.info(\"fpic is an option!!!\")\n                if \"fpic\" in self.info.options:  # Not documented\n                    self.output.info(\"fpic is an info.option!!!\")\n                if \"other\" not in self.info.options:\n                    self.output.info(\"other is not an option!!!\")\n                if \"other\" not in self.info.options:  # Not documented\n                    self.output.info(\"other is not an info.option!!!\")\n                try:\n                    self.options.whatever\n                except Exception as e:\n                    self.output.error(\"OPTIONS: %s\" % e)\n                try:\n                    self.info.options.whatever\n                except Exception as e:\n                    self.output.error(\"INFO: %s\" % e)\n\n        \"\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=pkg --version=0.1 --user=user --channel=testing\")\n    assert \"fpic is an option!!!\" in client.out\n    assert \"fpic is an info.option!!!\" in client.out\n    assert \"other is not an option!!!\" in client.out\n    assert \"other is not an info.option!!!\" in client.out\n    assert \"OPTIONS: 'self.options' access in 'package_id()' method is forbidden\" in client.out\n    assert \"ERROR: INFO: option 'whatever' doesn't exist\" in client.out\n\n\ndef test_build_type_remove_windows():\n    # https://github.com/conan-io/conan/issues/7603\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            def package_id(self):\n                if self.info.settings.os == \"Windows\" and self.info.settings.compiler == \"msvc\":\n                   del self.info.settings.build_type\n                   del self.info.settings.compiler.runtime\n                   del self.info.settings.compiler.runtime_type\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run('create . --name=pkg --version=0.1 -s os=Windows -s compiler=msvc -s arch=x86_64 '\n               '-s compiler.version=190 -s build_type=Release -s compiler.runtime=dynamic')\n    package_id = \"6a98270da6641cc6668b83daf547d67451910cf0\"\n    client.assert_listed_binary({\"pkg/0.1\": (package_id, \"Build\")})\n    client.run('install --requires=pkg/0.1@ -s os=Windows -s compiler=msvc -s arch=x86_64 '\n               '-s compiler.version=190 -s build_type=Debug -s compiler.runtime=dynamic')\n    client.assert_listed_binary({\"pkg/0.1\": (package_id, \"Cache\")})\n\n\ndef test_package_id_requires_info():\n    \"\"\" if we dont restrict ``package_id()`` to use only ``self.info`` it will do nothing and fail\n    if we ``del self.settings.arch`` instead of ``del self.info.settings.arch``\n    https://github.com/conan-io/conan/issues/12693\n    \"\"\"\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class TestConan(ConanFile):\n            settings = \"os\", \"arch\"\n\n            def package_id(self):\n                if self.info.settings.os == \"Windows\":\n                    del self.info.settings.arch\n        \"\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=pkg --version=0.1 -s os=Windows -s arch=armv8\")\n    client.assert_listed_binary({\"pkg/0.1\": (\"ebec3dc6d7f6b907b3ada0c3d3cdc83613a2b715\", \"Build\")})\n    client.run(\"create . --name=pkg --version=0.1 -s os=Windows -s arch=x86_64\")\n    client.assert_listed_binary({\"pkg/0.1\": (\"ebec3dc6d7f6b907b3ada0c3d3cdc83613a2b715\", \"Build\")})\n\n\ndef test_package_id_validate_settings():\n    \"\"\" ``self.info`` has no validation, as it allows to be mutated\n    \"\"\"\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class TestConan(ConanFile):\n            settings = \"os\", \"arch\"\n\n            def package_id(self):\n                if self.info.settings.os == \"DONT_EXIST\":\n                    del self.info.settings.arch\n        \"\"\")\n    c = TestClient()\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"create . --name=pkg --version=0.1\")\n    # It used to fail,\n\n\nclass TestBuildRequiresHeaderOnly:\n    def test_header_only(self):\n        c = TestClient(light=True)\n        save(c.paths.global_conf_path, \"core.package_id:default_build_mode=minor_mode\")\n        pkg = textwrap.dedent(\"\"\"\\\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                tool_requires = \"tool/[*]\"\n                def package_id(self):\n                    self.info.clear()\n                \"\"\")\n        c.save({\"tool/conanfile.py\": GenConanfile(\"tool\"),\n                \"pkg/conanfile.py\": pkg})\n        c.run(\"create tool --version=1.0\")\n        c.run(\"create pkg\")\n        pkgid = c.created_package_id(\"pkg/0.1\")\n        c.run(\"create tool --version=1.2\")\n        c.run(\"install --requires=pkg/0.1\")\n        c.assert_listed_binary({\"pkg/0.1\": (pkgid, \"Cache\")})\n\n    def test_header_only_implements(self):\n        c = TestClient(light=True)\n        save(c.paths.global_conf_path, \"core.package_id:default_build_mode=minor_mode\")\n        pkg = textwrap.dedent(\"\"\"\\\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                tool_requires = \"tool/[*]\"\n                package_type = \"header-library\"\n                implements = [\"auto_header_only\"]\n                \"\"\")\n        c.save({\"tool/conanfile.py\": GenConanfile(\"tool\"),\n                \"pkg/conanfile.py\": pkg})\n        c.run(\"create tool --version=1.0\")\n        c.run(\"create pkg\")\n        pkgid = c.created_package_id(\"pkg/0.1\")\n        c.run(\"create tool --version=1.2\")\n        c.run(\"install --requires=pkg/0.1\")\n        c.assert_listed_binary({\"pkg/0.1\": (pkgid, \"Cache\")})\n\n\ndef test_explicit_implements():\n    c = TestClient()\n    pkg = textwrap.dedent(\"\"\"\\\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            settings = \"os\"\n            options = {\"header_only\": [True, False]}\n\n            def package_id(self):\n                if self.package_type == \"header-library\":\n                    self.info.clear()\n             \"\"\")\n    c.save({\"conanfile.py\": pkg})\n    c.run(\"create . -s os=Windows -o *:header_only=True\")\n    pkgid = c.created_package_id(\"pkg/0.1\")\n    c.run(\"create . -s os=Linux -o *:header_only=True\")\n    pkgid2 = c.created_package_id(\"pkg/0.1\")\n    assert pkgid == pkgid2\n\n    c.run(\"create . -s os=Windows -o *:header_only=False\")\n    pkgid3 = c.created_package_id(\"pkg/0.1\")\n    assert pkgid3 != pkgid\n    c.run(\"create . -s os=Linux -o *:header_only=False\")\n    pkgid4 = c.created_package_id(\"pkg/0.1\")\n    assert pkgid4 != pkgid\n    assert pkgid3 != pkgid4\n"
  },
  {
    "path": "test/integration/package_id/python_requires_package_id_test.py",
    "content": "import textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient, GenConanfile\n\n\nPKG_ID_1 = \"47b42eaf657374a3d040394f03961b66c53bda5e\"\nPKG_ID_2 = \"8b7006bf91e5b52cc1ac24a7a4d9c326ee954bb2\"\n\n\nclass TestPythonRequiresPackageID:\n\n    @pytest.fixture(autouse=True)\n    def set_up(self):\n        client = TestClient()\n        client.save({\"conanfile.py\": GenConanfile()})\n        client.run(\"export . --name=tool --version=1.1.1\")\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                python_requires =\"tool/[*]\"\n            \"\"\")\n        client2 = TestClient(cache_folder=client.cache_folder)\n        client2.save({\"conanfile.py\": conanfile})\n        self.client = client\n        self.client2 = client2\n\n    def test_default(self):\n        self.client2.run(\"create . --name=pkg --version=0.1\")\n        assert \"tool/1.1.1\" in self.client2.out\n        pkg_id = \"170e82ef3a6bf0bbcda5033467ab9d7805b11d0b\"\n        self.client2.assert_listed_binary({\"pkg/0.1\": (pkg_id, \"Build\")})\n\n        self.client.run(\"export . --name=tool --version=1.1.2\")\n        self.client2.run(\"create . --name=pkg --version=0.1\")\n        assert \"tool/1.1.2\" in self.client2.out\n        self.client2.assert_listed_binary({\"pkg/0.1\": (pkg_id,\n                                                       \"Build\")})\n\n        # With a minor change, it fires a rebuild\n        self.client.run(\"export . --name=tool --version=1.2.0\")\n        self.client2.run(\"create . --name=pkg --version=0.1\")\n        assert \"tool/1.2.0\" in self.client2.out\n        self.client2.assert_listed_binary({\"pkg/0.1\": (\"5eb1e7ea93fdd67fe3c3b166d240844648ba2b7a\",\n                                                       \"Build\")})\n\n    def test_change_mode_conf(self):\n        # change the policy in conan.conf\n        self.client2.save_home({\"global.conf\": \"core.package_id:default_python_mode=patch_mode\"})\n        self.client2.run(\"create . --name=pkg --version=0.1\")\n        assert \"tool/1.1.1\" in self.client2.out\n        self.client2.assert_listed_binary({\"pkg/0.1\": (PKG_ID_1, \"Build\")})\n\n        # with a patch change, new ID\n        self.client.run(\"export . --name=tool --version=1.1.2\")\n        self.client2.run(\"create . --name=pkg --version=0.1\")\n        assert \"tool/1.1.2\" in self.client2.out\n        self.client2.assert_listed_binary({\"pkg/0.1\": (PKG_ID_2, \"Build\")})\n\n    def test_unrelated_conf(self):\n        # change the policy in conan.conf\n        self.client2.save_home({\"global.conf\": \"core.package_id:default_python_mode=unrelated_mode\"})\n        self.client2.run(\"create . --name=pkg --version=0.1\")\n        assert \"tool/1.1.1\" in self.client2.out\n        pkg_id = \"da39a3ee5e6b4b0d3255bfef95601890afd80709\"\n        self.client2.assert_listed_binary({\"pkg/0.1\": (pkg_id, \"Build\")})\n\n        # with any change the package id doesn't change\n        self.client.run(\"export . --name=tool --version=1.1.2\")\n        self.client2.run(\"create . --name=pkg --version=0.1 --build missing\")\n        assert \"tool/1.1.2\" in self.client2.out\n        self.client2.assert_listed_binary({\"pkg/0.1\": (pkg_id, \"Cache\")})\n\n    def test_change_mode_package_id(self):\n        # change the policy in package_id\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                python_requires =\"tool/[*]\"\n                def package_id(self):\n                    self.info.python_requires.patch_mode()\n            \"\"\")\n        self.client2.save({\"conanfile.py\": conanfile})\n        self.client2.run(\"create . --name=pkg --version=0.1\")\n        assert \"tool/1.1.1\" in self.client2.out\n        self.client2.assert_listed_binary({\"pkg/0.1\": (PKG_ID_1, \"Build\")})\n\n        # with a patch change, new ID\n        self.client.run(\"export . --name=tool --version=1.1.2\")\n        self.client2.run(\"create . --name=pkg --version=0.1\")\n        assert \"tool/1.1.2\" in self.client2.out\n        self.client2.assert_listed_binary({\"pkg/0.1\": (PKG_ID_2, \"Build\")})\n\n\ndef test_python_requires_for_build_requires():\n    client = TestClient()\n    client.save_home({\"global.conf\": \"core.package_id:default_python_mode=full_version_mode\"})\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"create . --name=tool --version=1.1.1\")\n\n    client2 = TestClient(cache_folder=client.cache_folder)\n    client2.save({\"conanfile.py\": GenConanfile().with_python_requires(\"tool/[>=0.0]\"),\n                 \"myprofile\": \"[tool_requires]\\ntool/[>=0.0]\\n\"})\n\n    client2.run(\"create . --name=pkg --version=0.1 -pr=myprofile\")\n    assert \"tool/1.1.1\" in client2.out\n    assert f\"pkg/0.1: Package '{PKG_ID_1}' created\" in client2.out\n\n    client.run(\"create . --name=tool --version=1.1.2\")\n    client2.run(\"install --requires=pkg/0.1@ -pr=myprofile\", assert_error=True)\n    assert f\"ERROR: Missing binary: pkg/0.1:{PKG_ID_2}\" in client2.out\n    assert \"tool/1.1.2\" in client2.out\n    assert \"tool/1.1.1\" not in client2.out\n\n    client2.run(\"create . --name=pkg --version=0.1 -pr=myprofile\")\n    # assert \"pkg/0.1: Applying build-requirement: tool/1.1.2\", client2.out)\n    assert f\"pkg/0.1: Package '{PKG_ID_2}' created\" in client2.out\n\n\nclass TestPythonRequiresHeaderOnly:\n    def test_header_only(self):\n        c = TestClient(light=True)\n        pkg = textwrap.dedent(\"\"\"\\\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                python_requires = \"tool/[*]\"\n                def package_id(self):\n                    self.info.clear()\n                \"\"\")\n        c.save({\"tool/conanfile.py\": GenConanfile(\"tool\"),\n                \"pkg/conanfile.py\": pkg})\n        c.run(\"create tool --version=1.0\")\n        c.run(\"create pkg\")\n        pkgid = c.created_package_id(\"pkg/0.1\")\n        c.run(\"create tool --version=1.2\")\n        c.run(\"install --requires=pkg/0.1\")\n        c.assert_listed_binary({\"pkg/0.1\": (pkgid, \"Cache\")})\n\n    def test_header_only_implements(self):\n        c = TestClient(light=True)\n        pkg = textwrap.dedent(\"\"\"\\\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                python_requires = \"tool/[*]\"\n                package_type = \"header-library\"\n                implements = [\"auto_header_only\"]\n                \"\"\")\n        c.save({\"tool/conanfile.py\": GenConanfile(\"tool\"),\n                \"pkg/conanfile.py\": pkg})\n        c.run(\"create tool --version=1.0\")\n        c.run(\"create pkg\")\n        pkgid = c.created_package_id(\"pkg/0.1\")\n        c.run(\"create tool --version=1.2\")\n        c.run(\"install --requires=pkg/0.1\")\n        c.assert_listed_binary({\"pkg/0.1\": (pkgid, \"Cache\")})\n\n\n@pytest.mark.parametrize(\"mode, pkg_id\",\n                         [(\"unrelated_mode\", \"da39a3ee5e6b4b0d3255bfef95601890afd80709\"),\n                          (\"semver_mode\", \"1f0070b00ccebfec93dc90854a163c7af229f587\"),\n                          (\"patch_mode\", \"b9ca872dfd5b48f5f1f69d66f0950fc35469d0cd\"),\n                          (\"minor_mode\", \"c53bd9e48dd09ceeaa1bb425830490d8b243e39c\"),\n                          (\"major_mode\", \"331c17383dcdf37f79bc2b86fa55ac56afdc6fec\"),\n                          (\"full_version_mode\", \"1f0070b00ccebfec93dc90854a163c7af229f587\"),\n                          (\"full_recipe_mode\", \"1f0070b00ccebfec93dc90854a163c7af229f587\"),\n                          # Doesn't make much sense, but was doable, not worth removing it\n                          (\"full_package_mode\", \"1f0070b00ccebfec93dc90854a163c7af229f587\"),\n                          (\"revision_mode\", \"0071dd0296afa0db533e21f924273485c87f0d32\"),\n                          (\"full_mode\", \"0071dd0296afa0db533e21f924273485c87f0d32\")])\ndef test_modes(mode, pkg_id):\n    c = TestClient(light=True)\n    c.save_home({\"global.conf\": f\"core.package_id:default_python_mode={mode}\"})\n    c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1.1.1\"),\n            \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_python_requires(\"dep/[*]\")})\n    c.run(\"create dep\")\n    c.run(\"create pkg\")\n    pkgid = c.created_package_id(\"pkg/0.1\")\n    assert pkgid == pkg_id\n\n\n@pytest.mark.parametrize(\"mode, pkg_id\",\n                         [(\"unrelated_mode\", \"da39a3ee5e6b4b0d3255bfef95601890afd80709\"),\n                          (\"semver_mode\", \"1f0070b00ccebfec93dc90854a163c7af229f587\"),\n                          (\"patch_mode\", \"b9ca872dfd5b48f5f1f69d66f0950fc35469d0cd\"),\n                          (\"minor_mode\", \"c53bd9e48dd09ceeaa1bb425830490d8b243e39c\"),\n                          (\"major_mode\", \"331c17383dcdf37f79bc2b86fa55ac56afdc6fec\"),\n                          (\"full_version_mode\", \"1f0070b00ccebfec93dc90854a163c7af229f587\"),\n                          (\"full_recipe_mode\", \"1f0070b00ccebfec93dc90854a163c7af229f587\"),\n                          (\"revision_mode\", \"0071dd0296afa0db533e21f924273485c87f0d32\"),\n                          (\"full_mode\", \"0071dd0296afa0db533e21f924273485c87f0d32\")])\ndef test_modes_recipe(mode, pkg_id):\n    c = TestClient(light=True)\n\n    conanfile = textwrap.dedent(f\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            python_requires =\"dep/[*]\"\n            def package_id(self):\n                self.info.python_requires.{mode}()\n        \"\"\")\n    c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1.1.1\"),\n            \"pkg/conanfile.py\": conanfile})\n    c.run(\"create dep\")\n    c.run(\"create pkg\")\n    c.assert_listed_binary({\"pkg/0.1\": (pkg_id, \"Build\")})\n"
  },
  {
    "path": "test/integration/package_id/test_cache_compatibles.py",
    "content": "import os\nimport re\nimport textwrap\n\nimport pytest\n\nfrom conan.internal.cache.home_paths import HomePaths\nfrom conan.test.utils.tools import TestClient, GenConanfile\n\n\nclass TestCacheCompatibles:\n    @pytest.fixture()\n    def client(self):\n        client = TestClient()\n        debug_compat = textwrap.dedent(\"\"\"\\\n            def debug_compat(conanfile):\n                result = []\n                if conanfile.settings.build_type == \"Debug\":\n                    result.append({\"settings\": [(\"build_type\", \"Release\")]})\n                return result\n            \"\"\")\n        compatibles = textwrap.dedent(\"\"\"\\\n            from debug_compat import debug_compat\n            def compatibility(conanfile):\n                if conanfile.name != \"dep\":\n                    return\n                return debug_compat(conanfile)\n            \"\"\")\n        client.save_home({\"extensions/plugins/compatibility/compatibility.py\": compatibles,\n                          \"extensions/plugins/compatibility/debug_compat.py\": debug_compat})\n        return client\n\n    def test_compatible_build_type(self, client):\n        client.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\").with_setting(\"build_type\"),\n                     \"consumer/conanfile.py\": GenConanfile().with_requires(\"dep/0.1\")})\n\n        client.run(\"create dep -s build_type=Release\")\n        package_id = client.created_package_id(\"dep/0.1\")\n\n        client.run(\"install consumer -s build_type=Debug\")\n        assert \"dep/0.1: Main binary package '9e186f6d94c008b544af1569d1a6368d8339efc5' missing\"\\\n               in client.out\n        assert f\"Found compatible package '{package_id}'\" in client.out\n\n    def test_compatible_recipe_reference(self, client):\n        \"\"\" check that the recipe name can be used to filter\n        \"\"\"\n        client.save({\"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_setting(\"build_type\"),\n                     \"consumer/conanfile.py\": GenConanfile().with_requires(\"pkg/0.1\")})\n\n        client.run(\"create pkg -s build_type=Release\")\n\n        # The compatibility doesn't fire for package \"pkg\"\n        client.run(\"install consumer -s build_type=Debug\", assert_error=True)\n        assert \"ERROR: Missing binary\" in client.out\n\n\ndef test_cppstd():\n    client = TestClient()\n    compatibles = textwrap.dedent(\"\"\"\\\n        def compatibility(conanfile):\n            cppstd = conanfile.settings.get_safe(\"compiler.cppstd\")\n            if not cppstd:\n                return\n\n            result = []\n            for cppstd in [\"11\", \"14\", \"17\", \"20\"]:\n                result.append({\"settings\": [(\"compiler.cppstd\", cppstd)]})\n\n            if conanfile.settings.build_type == \"Debug\":\n                for cppstd in [\"11\", \"14\", \"17\", \"20\"]:\n                    result.append({\"settings\": [(\"compiler.cppstd\", cppstd),\n                                                (\"build_type\", \"Release\")]})\n            return result\n        \"\"\")\n    client.save_home({\"extensions/plugins/compatibility/compatibility.py\": compatibles})\n\n    conanfile = GenConanfile(\"dep\", \"0.1\").with_settings(\"compiler\", \"build_type\")\n    client.save({\"dep/conanfile.py\": conanfile,\n                 \"consumer/conanfile.py\": GenConanfile().with_requires(\"dep/0.1\")})\n\n    base_settings = \"-s compiler=gcc -s compiler.version=7 -s compiler.libcxx=libstdc++11\"\n    client.run(f\"create dep {base_settings} -s build_type=Release -s compiler.cppstd=14\")\n    package_id = client.created_package_id(\"dep/0.1\")\n\n    client.run(f\"install consumer {base_settings} -s compiler.cppstd=17\")\n    assert \"dep/0.1: Checking 3 compatible configurations\" in client.out\n    assert \"dep/0.1: Main binary package 'ec174bec4a5ee2d44d3e33d9f4fdacd9b65a6772' missing\" \\\n           in client.out\n    assert f\"Found compatible package '{package_id}'\" in client.out\n\n    client.run(f\"install consumer {base_settings} -s build_type=Debug -s compiler.cppstd=17\")\n    assert \"dep/0.1: Main binary package '94758b7bbcb365aaf355913b35431c0da6ed6da5' missing\" \\\n           in client.out\n    assert f\"Found compatible package '{package_id}'\" in client.out\n\n\ndef test_cppstd_validated():\n    \"\"\" this test proves that 1 only configuration, the latest one, is tested and compatible,\n    because the ``valiate()`` method is rejecting all cppstd<20\n    \"\"\"\n    client = TestClient()\n    compatibles = textwrap.dedent(\"\"\"\\\n        def compatibility(conanfile):\n            return [{\"settings\": [(\"compiler.cppstd\", v)]} for v in (\"11\", \"14\", \"17\", \"20\")]\n        \"\"\")\n    client.save_home({\"extensions/plugins/compatibility/compatibility.py\": compatibles})\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.build import check_min_cppstd\n        class Pkg(ConanFile):\n            name = \"dep\"\n            version = \"0.1\"\n            settings = \"compiler\"\n            def validate(self):\n                check_min_cppstd(self, \"20\")\n        \"\"\")\n\n    client.save({\"dep/conanfile.py\": conanfile,\n                 \"consumer/conanfile.py\": GenConanfile().with_requires(\"dep/0.1\")})\n\n    base_settings = \"-s compiler=gcc -s compiler.version=8 -s compiler.libcxx=libstdc++11\"\n    client.run(f\"create dep {base_settings} -s compiler.cppstd=20\")\n\n    client.run(f\"install consumer {base_settings} -s compiler.cppstd=17\", assert_error=True)\n    assert \"dep/0.1: Invalid: Current cppstd (17) is lower than the required C++ standard (20).\" \\\n           in client.out\n\n\ndef test_cppstd_server():\n    \"\"\" this test proves the order, first from cache\n    \"\"\"\n    c = TestClient(default_server_user=True)\n    compatibles = textwrap.dedent(\"\"\"\\\n        def compatibility(conanfile):\n            return [{\"settings\": [(\"compiler.cppstd\", v)]} for v in (\"11\", \"14\", \"17\", \"20\")]\n        \"\"\")\n    c.save_home({\"extensions/plugins/compatibility/compatibility.py\": compatibles})\n\n    conanfile = GenConanfile(\"dep\", \"0.1\").with_settings(\"compiler\")\n    c.save({\"dep/conanfile.py\": conanfile,\n            \"consumer/conanfile.py\": GenConanfile().with_requires(\"dep/0.1\")})\n\n    base_settings = \"-s compiler=gcc -s compiler.version=8 -s compiler.libcxx=libstdc++11\"\n    c.run(f\"create dep {base_settings} -s compiler.cppstd=20\")\n    c.run(\"upload * -r=default -c\")\n    c.run(\"remove * -c\")\n\n    c.run(f\"install consumer {base_settings} -s compiler.cppstd=17\")\n    assert \"dep/0.1: Checking 3 compatible configurations\" in c.out\n    assert \"dep/0.1: Compatible configurations not found in cache, checking servers\" in c.out\n    assert \"dep/0.1: Main binary package '6179018ccb6b15e6443829bf3640e25f2718b931' missing\" \\\n           in c.out\n    assert \"Found compatible package '326c500588d969f55133fdda29506ef61ef03eee': \" \\\n           \"compiler.cppstd=20\" in c.out\n    c.assert_listed_binary({\"dep/0.1\": (\"326c500588d969f55133fdda29506ef61ef03eee\",\n                                        \"Download (default)\")})\n    # second time, not download, already in cache\n    c.run(f\"install consumer {base_settings} -s compiler.cppstd=17\")\n    assert \"dep/0.1: Checking 3 compatible configurations\" in c.out\n    assert \"dep/0.1: Compatible configurations not found in cache, checking servers\" not in c.out\n    assert \"dep/0.1: Main binary package '6179018ccb6b15e6443829bf3640e25f2718b931' missing\" in c.out\n    assert \"Found compatible package '326c500588d969f55133fdda29506ef61ef03eee': \" \\\n           \"compiler.cppstd=20\" in c.out\n    c.assert_listed_binary({\"dep/0.1\": (\"326c500588d969f55133fdda29506ef61ef03eee\", \"Cache\")})\n\n    # update checks in servers\n    c2 = TestClient(servers=c.servers, inputs=[\"admin\", \"password\"])\n    c2.save({\"dep/conanfile.py\": conanfile})\n    c2.run(f\"create dep {base_settings} -s compiler.cppstd=14\")\n    c2.run(\"upload * -r=default -c\")\n\n    c.run(f\"install consumer {base_settings} -s compiler.cppstd=17 --update\")\n    assert \"dep/0.1: Checking 3 compatible configurations\" in c.out\n    assert \"dep/0.1: Compatible configurations not found in cache, checking servers\" not in c.out\n    assert \"dep/0.1: Main binary package '6179018ccb6b15e6443829bf3640e25f2718b931' missing\" in c.out\n    assert \"Found compatible package 'ce92fac7c26ace631e30875ddbb3a58a190eb601': \" \\\n           \"compiler.cppstd=14\" in c.out\n    c.assert_listed_binary({\"dep/0.1\": (\"ce92fac7c26ace631e30875ddbb3a58a190eb601\",\n                                        \"Download (default)\")})\n\n    # Now what happens if we have it in cache already\n    c.run(f\"install consumer {base_settings} -s compiler.cppstd=17 --update\")\n    assert \"dep/0.1: Checking 3 compatible configurations\" in c.out\n    assert \"dep/0.1: Main binary package '6179018ccb6b15e6443829bf3640e25f2718b931' missing\" in c.out\n    assert \"Found compatible package 'ce92fac7c26ace631e30875ddbb3a58a190eb601': \" \\\n           \"compiler.cppstd=14\" in c.out\n    c.assert_listed_binary({\"dep/0.1\": (\"ce92fac7c26ace631e30875ddbb3a58a190eb601\",\n                                        \"Cache\")})\n\n\nclass TestDefaultCompat:\n\n    def test_default_cppstd_compatibility(self):\n        c = TestClient()\n        c.save_home({\"profiles/default\": \"\"})\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                name = \"mylib\"\n                version = \"1.0\"\n                package_type = \"library\"\n                options = {\"shared\": [True, False]}\n                default_options = {\"shared\": False}\n                settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            \"\"\")\n        c.save({\"conanfile.py\": conanfile, \"profile_build\": \"[settings]\\nos=Windows\\narch=x86_64\"})\n        os_ = \"Windows\"\n        build_type = \"Release\"\n        arch = \"x86_64\"\n        compiler = \"msvc\"\n        version = \"191\"\n        cppstd = \"17\"\n        runtime = \"dynamic\"\n        c.run(f\"create . -s os={os_} -s arch={arch} -s build_type={build_type} \"\n              f\"-s compiler={compiler} \"\n              f\"-s compiler.version={version} -s compiler.cppstd={cppstd} \"\n              f\"-s compiler.runtime={runtime} -pr:b=profile_build\")\n        package_id1 = c.created_package_id(\"mylib/1.0\")\n\n        # Try to install with cppstd 14, it will find cppstd 17 as compatible\n        c.run(f\"install --requires=mylib/1.0@ -s os={os_} -s arch={arch} -s build_type={build_type} \"\n              f\"-s compiler={compiler} \"\n              f\"-s compiler.version={version} -s compiler.cppstd=14 \"\n              f\"-s compiler.runtime={runtime} -pr:b=profile_build\")\n        assert \"mylib/1.0: Main binary package 'e340edd75790e7156c595edebd3d98b10a2e091e' missing.\"\\\n               f\"Using compatible package '{package_id1}'\"\n\n    def test_fail_with_options_deleted(self):\n        \"\"\"\n        This test used to fail with \"ConanException: option 'with_fmt_alias' doesn't exist\",\n        because it was removed by the package_id()\n        \"\"\"\n        c = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                name = \"mylib\"\n                version = \"1.0\"\n\n                options = {\"with_fmt_alias\": [True, False]}\n                default_options = {\"with_fmt_alias\": False}\n\n                settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n\n                def package_id(self):\n                    del self.info.options.with_fmt_alias\n\n                def package_info(self):\n                    self.output.warning(\"WITH_FMT_ALIAS={}\".format(self.options.with_fmt_alias))\n            \"\"\")\n        c.save({\"conanfile.py\": conanfile})\n\n        c.run(\"create . -s compiler.cppstd=14\")\n\n        c.run(\"create . --build=missing -s compiler.cppstd=17\")\n        assert \"mylib/1.0: Main binary package\" in c.out\n        assert \"Found compatible package\" in c.out\n        assert \"Possible options are ['shared', 'header_only']\" not in c.out\n        assert \"mylib/1.0: WARN: WITH_FMT_ALIAS=False\" in c.out\n\n    def test_header_only_build_missing(self):\n        \"\"\"\n        this test failed with self.settings.compiler setting didn't exist\n        \"\"\"\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class SumConan(ConanFile):\n                name = \"sum\"\n                version = \"0.1\"\n                settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n                def build(self):\n                    self.output.warning(\"My compiler is '{}'\".format(self.settings.compiler))\n                def package_id(self):\n                    self.info.clear()\n        \"\"\")\n\n        client = TestClient()\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . -s compiler.cppstd=17 --build missing\")\n        client.assert_listed_binary({\"sum/0.1\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\",\n                                                 \"Build\")})\n        # Just check that it works and doesn't fail\n        assert \"Installing packages\" in client.out\n        client.run(\"create . -s compiler.cppstd=14 --build missing\")\n        # Now it will not build, as package exist\n        client.assert_listed_binary({\"sum/0.1\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\",\n                                                 \"Cache\")})\n        assert \"Installing packages\" in client.out\n\n    def test_check_min_cppstd(self):\n        \"\"\" test that the check_min_cppstd works fine wiht compatibility, as it is based\n        on ``conanfile.info.settings`` not ``conanfile.settings``\n        \"\"\"\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.build import check_min_cppstd, valid_min_cppstd\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n                def validate(self):\n                    check_min_cppstd(self, \"17\", False)\n                    self.output.info(\"valid standard!!\")\n                def package_info(self):\n                    self.output.info(\"CPPSTD: {}\".format(self.settings.compiler.cppstd))\n            \"\"\")\n\n        c = TestClient()\n        c.save({\"conanfile.py\": conanfile})\n        settings = \"-s compiler=gcc -s compiler.version=9 -s compiler.libcxx=libstdc++11\"\n        c.run(f\"create .  {settings} -s compiler.cppstd=17\")\n        assert \"pkg/0.1: valid standard!!\" in c.out\n        assert \"pkg/0.1: CPPSTD: 17\" in c.out\n        c.run(f\"install {settings} --requires=pkg/0.1 -s compiler.cppstd=14\", assert_error=True)\n        assert \"pkg/0.1: Invalid: Current cppstd (14) is lower than the required C++ standard (17).\"\\\n               in c.out\n        c.run(f\"install {settings} --requires=pkg/0.1 -s compiler.cppstd=20\")\n        assert \"valid standard!!\" in c.out\n        assert \"pkg/0.1: CPPSTD: 17\" in c.out\n\n    def test_check_min_cstd(self):\n        \"\"\" test that the check_min_cstd works fine with compatibility\n        \"\"\"\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.build import check_min_cstd\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n                languages = \"C\"\n                def validate(self):\n                    check_min_cstd(self, \"17\", False)\n                    self.output.info(\"valid standard!!\")\n                def package_info(self):\n                    self.output.info(\"CSTD: {}\".format(self.settings.compiler.cstd))\n            \"\"\")\n\n        c = TestClient()\n        c.save({\"conanfile.py\": conanfile})\n        settings = \"-s compiler=gcc -s compiler.version=14 -s compiler.libcxx=libstdc++11\"\n        c.run(f\"create .  {settings} -s compiler.cstd=17\")\n        assert \"pkg/0.1: valid standard!!\" in c.out\n        assert \"pkg/0.1: CSTD: 17\" in c.out\n        c.run(f\"install {settings} --requires=pkg/0.1 -s compiler.cstd=11\", assert_error=True)\n        assert \"pkg/0.1: Invalid: Current cstd (11) is lower than the required C standard (17).\"\\\n               in c.out\n        c.run(f\"install {settings} --requires=pkg/0.1 -s compiler.cstd=23\")\n        assert \"valid standard!!\" in c.out\n        assert \"pkg/0.1: CSTD: 17\" in c.out\n\n    def test_check_min_cppstd_interface(self):\n        \"\"\" test that says that compatible binaries are ok, as long as the user defined\n        cppstd>=14. The syntax is a bit forced, maybe we want to improve ``check_min_cppstd``\n        capabilities to be able to raise ConanInvalidConfiguration too\n        \"\"\"\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.errors import ConanInvalidConfiguration\n            from conan.tools.build import check_min_cppstd, valid_min_cppstd\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n                def validate(self):\n                    if int(str(self.info.settings.compiler.cppstd).replace(\"gnu\", \"\")) <= 14:\n                        raise ConanInvalidConfiguration(\"incompatible cppstd!\")\n                    check_min_cppstd(self, \"17\", False)  # based on self.info\n                    self.output.info(\"valid standard!!\")\n                def package_info(self):\n                    self.output.info(\"CPPSTD: {}\".format(self.settings.compiler.cppstd))\n            \"\"\")\n\n        c = TestClient()\n        c.save({\"conanfile.py\": conanfile})\n        settings = \"-s compiler=gcc -s compiler.version=9 -s compiler.libcxx=libstdc++11\"\n        c.run(f\"create .  {settings} -s compiler.cppstd=17\")\n        assert \"pkg/0.1: valid standard!!\" in c.out\n        assert \"pkg/0.1: CPPSTD: 17\" in c.out\n        c.run(f\"install {settings} --requires=pkg/0.1 -s compiler.cppstd=14\", assert_error=True)\n        assert \"valid standard!!\" not in c.out\n        assert \"pkg/0.1: Invalid: incompatible cppstd!\" in c.out\n        c.run(f\"install {settings} --requires=pkg/0.1 -s compiler.cppstd=20\")\n        assert \"valid standard!!\" in c.out\n        assert \"pkg/0.1: CPPSTD: 17\" in c.out\n\n    def test_can_create_multiple(self):\n        c = TestClient()\n        c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_settings(\"os\", \"arch\", \"compiler\",\n                                                                         \"build_type\")})\n        settings = \"-s os=Linux -s arch=x86_64 -s compiler=gcc -s compiler.version=9 \"\\\n                   \"-s compiler.libcxx=libstdc++11\"\n        c.run(f\"create . {settings} -s compiler.cppstd=11\")\n        c.assert_listed_binary({\"pkg/0.1\": (\"0d5f0b9d89187b4e62abb10ae409997e152db9de\", \"Build\")})\n        c.run(f\"create . {settings} -s compiler.cppstd=14\")\n        c.assert_listed_binary({\"pkg/0.1\": (\"145f423d315bee340546093be5b333ef5238668e\", \"Build\")})\n        c.run(f\"create . {settings} -s compiler.cppstd=17\")\n        c.assert_listed_binary({\"pkg/0.1\": (\"00fcbc3b6ab76a68f15e7e750e8081d57a6f5812\", \"Build\")})\n\n    def test_unnecessary_builds(self):\n        # https://github.com/conan-io/conan/issues/15657\n        c = TestClient()\n        c.save({\"tool/conanfile.py\": GenConanfile(\"tool\", \"0.1\"),\n                \"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\").with_tool_requires(\"tool/0.1\"),\n                \"app/conanfile.py\": GenConanfile(\"app\", \"0.1\").with_requires(\"dep/0.1\")\n                                                              .with_tool_requires(\"tool/0.1\")})\n        c.run(\"create tool\")\n        c.run(\"create dep \")\n        c.run(\"create app \")\n        c.run(\"remove tool:* -c\")\n        c.run(\"install --requires=dep/0.1  --build=missing\")\n        assert re.search(r\"Skipped binaries(\\s*)tool/0.1\", c.out)\n        c.run(\"graph info --requires=app/0.1 --build=missing\")\n        assert re.search(r\"Skipped binaries(\\s*)tool/0.1\", c.out)\n        c.run(\"install --requires=app/0.1  --build=missing\")\n        assert re.search(r\"Skipped binaries(\\s*)tool/0.1\", c.out)\n\n    def test_msvc_194_fallback(self):\n        c = TestClient()\n        c.save_home({\"profiles/default\": \"\"})\n        c.save({\"conanfile.py\": GenConanfile(\"mylib\", \"1.0\").with_settings(\"os\", \"arch\",\n                                                                           \"compiler\", \"build_type\"),\n                \"profile_build\": \"[settings]\\nos=Windows\\narch=x86_64\"})\n\n        c.run(\"create . -s os=Windows -s arch=x86_64 -s build_type=Release \"\n              \"-s compiler=msvc \"\n              \"-s compiler.version=193 -s compiler.cppstd=17 \"\n              \"-s compiler.runtime=dynamic -pr:b=profile_build\")\n        package_id1 = c.created_package_id(\"mylib/1.0\")\n\n        # Try to install with cppstd 14, it will find cppstd 17 as compatible\n        c.run(\"install --requires=mylib/1.0@ -s os=Windows -s arch=x86_64 -s build_type=Release \"\n              \"-s compiler=msvc \"\n              \"-s compiler.version=194 -s compiler.cppstd=14 \"\n              \"-s compiler.runtime=dynamic -pr:b=profile_build\")\n        assert \"mylib/1.0: Main binary package 'e340edd75790e7156c595edebd3d98b10a2e091e' missing.\"\\\n               f\"Using compatible package '{package_id1}'\"\n\n        c.run(\"install --requires=mylib/1.0@ -s os=Windows -s arch=x86_64 -s build_type=Release \"\n              \"-s compiler=msvc \"\n              \"-s compiler.version=194 -s compiler.cppstd=17 \"\n              \"-s compiler.runtime=dynamic -pr:b=profile_build\")\n        assert \"mylib/1.0: Main binary package 'e340edd75790e7156c595edebd3d98b10a2e091e' missing.\" \\\n               f\"Using compatible package '{package_id1}'\"\n\n\nclass TestErrorsCompatibility:\n    \"\"\" when the plugin fails, we want a clear message and a helpful trace\n    \"\"\"\n    def test_error_compatibility(self):\n        c = TestClient()\n        debug_compat = textwrap.dedent(\"\"\"\\\n            def debug_compat(conanfile):\n                other(conanfile)\n\n            def other(conanfile):\n                conanfile.settings.os\n            \"\"\")\n        compatibles = textwrap.dedent(\"\"\"\\\n            from debug_compat import debug_compat\n            def compatibility(conanfile):\n                return debug_compat(conanfile)\n            \"\"\")\n        c.save_home({\"extensions/plugins/compatibility/compatibility.py\": compatibles,\n                     \"extensions/plugins/compatibility/debug_compat.py\": debug_compat})\n\n        conanfile = GenConanfile(\"dep\", \"0.1\")\n        c.save({\"dep/conanfile.py\": conanfile,\n                \"consumer/conanfile.py\": GenConanfile().with_requires(\"dep/0.1\")})\n\n        c.run(f\"export dep\")\n        c.run(f\"install consumer\", assert_error=True)\n        assert \"Error while processing 'compatibility.py' plugin for 'dep/0.1', line 3\" in c.out\n        assert \"while calling 'debug_compat', line 2\" in c.out\n        assert \"while calling 'other', line 5\" in c.out\n\n    def test_remove_plugin_file(self):\n        c = TestClient()\n        c.run(\"version\")  # to trigger the creation\n        os.remove(os.path.join(HomePaths(c.cache_folder).compatibility_plugin_path,\n                               \"compatibility.py\"))\n        c.save({\"conanfile.txt\": \"\"})\n        c.run(\"install .\", assert_error=True)\n        assert \"ERROR: The 'compatibility.py' plugin file doesn't exist\" in c.out\n\n\ndef test_compatible_prev_from_cache():\n    tc = TestClient()\n    tc.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_settings(\"compiler\")})\n    settings = (\"-s os=Linux -s arch=x86_64 -s compiler=gcc -s compiler.version=8 \"\n                \"-s compiler.libcxx=libstdc++11\")\n    tc.run(f\"create . {settings} -s=compiler.cppstd=17\")\n    tc.run(f\"install --requires=pkg/0.1 {settings} -s=compiler.cppstd=14 -u\")\n    tc.assert_listed_binary({\"pkg/0.1\": (\"6179018ccb6b15e6443829bf3640e25f2718b931\",\n                                         \"Cache\")})\n"
  },
  {
    "path": "test/integration/package_id/test_config_package_id.py",
    "content": "import json\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import save\n\n\n@pytest.mark.parametrize(\"config_version, mode, result\", [\n    (\"myconfig/1.2.3#rev1\", \"minor_mode\", \"myconfig/1.2.Z\"),\n    (\"myconfig/1.2.3#rev1\", \"patch_mode\", \"myconfig/1.2.3\"),\n    (\"myconfig/1.2.3#rev1\", \"full_mode\", \"myconfig/1.2.3#rev1\"),\n    (\"myconfig/1.2.3#rev1\", \"revision_mode\", \"myconfig/1.2.3#rev1\"),\n    (\"myconfig/1.2.3\", \"minor_mode\", \"myconfig/1.2.Z\")])\ndef test_config_package_id(config_version, mode, result):\n    c = TestClient()\n    config_version = json.dumps({\"config_version\": [config_version]})\n    save(c.paths.config_version_path, config_version)\n    save(c.paths.global_conf_path, f\"core.package_id:config_mode={mode}\")\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n    c.run(\"create .\")\n    assert f\"config_version: {result}\" in c.out\n    c.run(\"list pkg/0.1:* --format=json\")\n    info = json.loads(c.stdout)\n    rrev = info[\"Local Cache\"][\"pkg/0.1\"][\"revisions\"][\"485dad6cb11e2fa99d9afbe44a57a164\"]\n    package_id = {\"myconfig/1.2.Z\": \"c78b4d8224154390356fe04fe598d67aec930199\",\n                  \"myconfig/1.2.3\": \"60005f5b11bef3ddd686b13f5c6bf576a9b882b8\",\n                  \"myconfig/1.2.3#rev1:pid1\": \"3e4270809028e4566b55d3958e94ae3d6f0c92a7\",\n                  \"myconfig/1.2.3#rev1\": \"aae875ae226416f177bf386a3e4ad6aaffce09e7\"}\n    package_id = package_id.get(result)\n    pkg = rrev[\"packages\"][package_id]\n    assert pkg[\"info\"] == {\"config_version\": [result]}\n\n\ndef test_error_config_package_id():\n    c = TestClient()\n    c.save_home({\"global.conf\": \"core.package_id:config_mode=minor_mode\"})\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n    c.run(\"create .\", assert_error=True)\n    assert \"ERROR: core.package_id:config_mode defined, \" \\\n           \"but error while loading 'config_version.json'\" in c.out\n\n\n@pytest.mark.parametrize(\"config_version, mode, result\", [\n    (\"myconfig/1.2.3#rev1\", \"minor_mode\", \"myconfig/1.2.Z\"),\n    (\"myconfig/1.2.3#rev1\", \"patch_mode\", \"myconfig/1.2.3\"),\n])\ndef test_config_package_id_clear(config_version, mode, result):\n    c = TestClient(light=True)\n    config_version = json.dumps({\"config_version\": [config_version]})\n    save(c.paths.config_version_path, config_version)\n    save(c.paths.global_conf_path, f\"core.package_id:config_mode={mode}\")\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_package_id(\"self.info.clear()\")})\n    c.run(\"create .\")\n    assert f\"config_version: {result}\" not in c.out\n\n\ndef test_recipe_revision_mode():\n    clienta = TestClient()\n    clienta.save_home({\"global.conf\": \"core.package_id:default_unknown_mode=recipe_revision_mode\"})\n\n    clienta.save({\"conanfile.py\": GenConanfile()})\n    clienta.run(\"create . --name=liba --version=0.1 --user=user --channel=testing\")\n\n    clientb = TestClient(cache_folder=clienta.cache_folder)\n    clientb.save({\"conanfile.py\": GenConanfile(\"libb\", \"0.1\").with_require(\"liba/0.1@user/testing\")})\n    clientb.run(\"create . --user=user --channel=testing\")\n\n    clientc = TestClient(cache_folder=clienta.cache_folder)\n    clientc.save({\"conanfile.py\": GenConanfile(\"libc\", \"0.1\").with_require(\"libb/0.1@user/testing\")})\n    clientc.run(\"install . --user=user --channel=testing\")\n\n    # Do a minor change to the recipe, it will change the recipe revision\n    clienta.save({\"conanfile.py\": str(GenConanfile()) + \"# comment\"})\n    clienta.run(\"create . --name=liba --version=0.1 --user=user --channel=testing\")\n\n    clientc.run(\"install . --user=user --channel=testing\", assert_error=True)\n    assert \"ERROR: Missing prebuilt package for 'libb/0.1@user/testing'\" in clientc.out\n    # Building b with the new recipe revision of liba works\n    clientc.run(\"install . --user=user --channel=testing --build=libb*\")\n\n    # Now change only the package revision of liba\n    clienta.run(\"create . --name=liba --version=0.1 --user=user --channel=testing\")\n    clientc.run(\"install . --user=user --channel=testing\")\n\n\ndef test_config_package_id_mode():\n    # chicken and egg problem when the configuration package itself is affected by the mode\n    c = TestClient(light=True)\n    config_version = json.dumps({\"config_version\": [\"myconfig/0.1\"]})\n    save(c.paths.config_version_path, config_version)\n    c.save_home({\"global.conf\": \"core.package_id:config_mode=minor_mode\"})\n\n    c.save({\"conanfile.py\": GenConanfile(\"myconfig\", \"0.1\").with_package_type(\"configuration\")})\n    c.run(\"create . \")\n    c.run(\"list *:*\")\n    # The binary is independent of the configuration version\n    assert \"config_version\" not in c.out\n"
  },
  {
    "path": "test/integration/package_id/test_default_package_id.py",
    "content": "import pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.parametrize(\"typedep, typeconsumer, different_id\",\n                         [(\"header-library\", \"application\", False),\n                          (\"header-library\", \"shared-library\", False),\n                          (\"header-library\", \"static-library\", False),\n                          (\"static-library\", \"application\", True),\n                          (\"static-library\", \"shared-library\", True),\n                          (\"static-library\", \"header-library\", False),\n                          (\"static-library\", \"static-library\", False),\n                          (\"shared-library\", \"header-library\", False),\n                          (\"shared-library\", \"static-library\", False),\n                          (\"shared-library\", \"shared-library\", False),\n                          (\"shared-library\", \"application\", False)\n                          ])\ndef test_default_package_id_options(typedep, typeconsumer, different_id):\n    \"\"\" test that some consumer package ids are changed when the dependency change one of its\n    options\n    \"\"\"\n    c = TestClient(light=True)\n    dep = GenConanfile(\"dep\", \"0.1\").with_option(\"myopt\", [True, False]) \\\n        .with_package_type(typedep).with_class_attribute('implements = [\"auto_shared_fpic\", \"auto_header_only\"]')\n    consumer = GenConanfile(\"consumer\", \"0.1\").with_requires(\"dep/0.1\")\\\n        .with_package_type(typeconsumer).with_class_attribute('implements = [\"auto_shared_fpic\", \"auto_header_only\"]')\n\n    c.save({\"dep/conanfile.py\": dep,\n            \"consumer/conanfile.py\": consumer})\n    c.run(\"create dep -o dep/*:myopt=True\")\n    pid1 = c.created_package_id(\"dep/0.1\")\n    c.run(\"create dep -o dep/*:myopt=False\")\n    pid2 = c.created_package_id(\"dep/0.1\")\n    if typedep != \"header-library\":\n        assert pid1 != pid2\n\n    c.run(\"create consumer -o dep/*:myopt=True\")\n    pid1 = c.created_package_id(\"consumer/0.1\")\n    c.run(\"create consumer -o dep/*:myopt=False\")\n    pid2 = c.created_package_id(\"consumer/0.1\")\n    if different_id:\n        assert pid1 != pid2\n    else:\n        assert pid1 == pid2\n\n\n@pytest.mark.parametrize(\"typedep, versiondep, typeconsumer, different_id\",\n                         [(\"static-library\", \"1.1\", \"header-library\", False),\n                          (\"static-library\", \"1.0.1\", \"static-library\", False),\n                          (\"static-library\", \"1.1\", \"static-library\", True),\n                          (\"shared-library\", \"1.1\", \"header-library\", False),\n                          (\"shared-library\", \"1.0.1\", \"static-library\", False),\n                          (\"shared-library\", \"1.1\", \"static-library\", True),\n                          (\"shared-library\", \"1.0.1\", \"shared-library\", False),\n                          (\"shared-library\", \"1.1\", \"shared-library\", True),\n                          (\"shared-library\", \"1.0.1\", \"application\", False),\n                          (\"shared-library\", \"1.1\", \"application\", True),\n                          (\"application\", \"2.1\", \"application\", False),\n                          ])\ndef test_default_package_id_versions(typedep, versiondep, typeconsumer, different_id):\n    \"\"\" test that some consumer package ids are changed when the dependency changes its version\n    \"\"\"\n    c = TestClient(light=True)\n    dep = GenConanfile(\"dep\").with_package_type(typedep)\n    consumer = GenConanfile(\"consumer\", \"0.1\").with_requires(\"dep/[>0.0]\") \\\n        .with_package_type(typeconsumer)\n    c.save({\"dep/conanfile.py\": dep,\n            \"consumer/conanfile.py\": consumer})\n    c.run(\"create dep --version=1.0\")\n    c.run(\"create consumer\")\n    pid1 = c.created_package_id(\"consumer/0.1\")\n\n    c.run(f\"create dep --version={versiondep}\")\n    c.run(\"create consumer\")\n    pid2 = c.created_package_id(\"consumer/0.1\")\n    if different_id:\n        assert pid1 != pid2\n    else:\n        assert pid1 == pid2\n"
  },
  {
    "path": "test/integration/package_id/test_package_id_test_requires.py",
    "content": "import pytest\n\nfrom conan.test.utils.tools import GenConanfile, TestClient\n\n\n@pytest.mark.parametrize(\"build_mode\", [None, \"patch_mode\"])\ndef test_package_id_not_affected_test_requires(build_mode):\n    \"\"\"\n    By default, test_requires do not affect the package_id\n    \"\"\"\n    c = TestClient()\n    if build_mode is not None:\n        c.save_home({\"global.conf\": f\"core.package_id:default_build_mode={build_mode}\"})\n    c.save({\"gtest/conanfile.py\": GenConanfile(\"gtest\", \"1.0\"),\n            \"engine/conanfile.py\": GenConanfile(\"engine\", \"1.0\").with_test_requires(\"gtest/1.0\")})\n    c.run(\"create gtest\")\n    c.run(\"create engine\")\n    c.run(\"list engine:*\")\n    assert \"engine/1.0\" in c.out\n    assert \"gtest\" not in c.out\n\n\ndef test_package_id_not_affected_test_requires_transitive():\n    \"\"\"\n    By default, transitive deps of test_requires do not affect the package_id\n    \"\"\"\n    c = TestClient()\n\n    c.save({\"zlib/conanfile.py\": GenConanfile(\"zlib\", \"1.0\"),\n            \"gtest/conanfile.py\": GenConanfile(\"gtest\", \"1.0\").with_requires(\"zlib/1.0\"),\n            \"engine/conanfile.py\": GenConanfile(\"engine\", \"1.0\").with_test_requires(\"gtest/1.0\")})\n    c.run(\"create zlib\")\n    c.run(\"create gtest\")\n    c.run(\"create engine\")\n    c.run(\"list engine:*\")\n    assert \"engine/1.0\" in c.out\n    assert \"gtest\" not in c.out\n    assert \"zlib\" not in c.out\n"
  },
  {
    "path": "test/integration/package_id/test_valid_package_id_values.py",
    "content": "import textwrap\n\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestValidPackageIdValue:\n\n    def test_valid(self):\n        c = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                options = {\"shared\": [False, True]}\n            \"\"\")\n\n        c.save({\"conanfile.py\": conanfile})\n\n        c.run(\"create . --name=pkg --version=0.1\", assert_error=True)\n        assert \"pkg/0.1: Invalid: 'options.shared' value not defined\" in c.out\n"
  },
  {
    "path": "test/integration/package_id/test_validate.py",
    "content": "import json\nimport os\nimport platform\nimport re\nimport textwrap\n\nimport pytest\n\nfrom conan.cli.exit_codes import ERROR_INVALID_CONFIGURATION, ERROR_GENERAL\nfrom conan.internal.graph.graph import BINARY_INVALID\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.internal.util.files import save, load\nfrom conan.test.utils.tools import TestClient, NO_SETTINGS_PACKAGE_ID\n\n\nclass TestValidate:\n\n    def test_validate_create(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.errors import ConanInvalidConfiguration\n            class Pkg(ConanFile):\n                settings = \"os\"\n\n                def validate(self):\n                    if self.info.settings.os == \"Windows\":\n                        raise ConanInvalidConfiguration(\"Windows not supported\")\n            \"\"\")\n\n        client.save({\"conanfile.py\": conanfile})\n\n        client.run(\"create . --name=pkg --version=0.1 -s os=Linux\")\n        assert \"pkg/0.1: Package '9a4eb3c8701508aa9458b1a73d0633783ecc2270' created\" in client.out\n\n        error = client.run(\"create . --name=pkg --version=0.1 -s os=Windows\", assert_error=True)\n        assert error == ERROR_INVALID_CONFIGURATION\n        assert \"pkg/0.1: Invalid: Windows not supported\" in client.out\n\n        client.run(\"graph info --require pkg/0.1 -s os=Windows\")\n        assert \"binary: Invalid\" in client.out\n        assert \"info_invalid: Windows not supported\" in client.out\n\n        client.run(\"graph info --require pkg/0.1 -s os=Windows --format json\")\n        myjson = json.loads(client.stdout)\n        assert myjson[\"graph\"][\"nodes\"][\"1\"][\"binary\"] == BINARY_INVALID\n        assert myjson[\"graph\"][\"nodes\"][\"1\"][\"info_invalid\"] == \"Windows not supported\" in client.out\n\n    def test_validate_header_only(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.errors import ConanInvalidConfiguration\n            from conan.tools.build import check_min_cppstd\n            class Pkg(ConanFile):\n                settings = \"os\", \"compiler\"\n                options = {\"shared\": [True, False], \"header_only\": [True, False],}\n                default_options = {\"shared\": False, \"header_only\": True}\n\n                def package_id(self):\n                   if self.info.options.header_only:\n                       self.info.clear()\n\n                def validate(self):\n                    if self.info.options.get_safe(\"header_only\") == \"False\":\n                        if self.info.settings.get_safe(\"compiler.version\") == \"12\":\n                          raise ConanInvalidConfiguration(\"This package cannot exist in gcc 12\")\n                        check_min_cppstd(self, 11)\n                        # These configurations are impossible\n                        if self.info.settings.os != \"Windows\" and self.info.options.shared:\n                            raise ConanInvalidConfiguration(\"shared is only supported under windows\")\n\n                    # HOW CAN WE VALIDATE CPPSTD > 11 WHEN HEADER ONLY?\n\n            \"\"\")\n\n        client.save({\"conanfile.py\": conanfile})\n\n        client.run(\"create . --name pkg --version=0.1 -s os=Linux -s compiler=gcc \"\n                   \"-s compiler.version=11 -s compiler.libcxx=libstdc++11\")\n        assert re.search(r\"Package '(.*)' created\", str(client.out))\n\n        client.run(\"create . --name pkg --version=0.1 -o header_only=False -s os=Linux \"\n                   \"-s compiler=gcc -s compiler.version=12 -s compiler.libcxx=libstdc++11\",\n                   assert_error=True)\n\n        assert \"Invalid: This package cannot exist in gcc 12\" in client.out\n\n        client.run(\"create . --name pkg --version=0.1  -o header_only=False -s os=Macos \"\n                   \"-s compiler=gcc -s compiler.version=11 -s compiler.libcxx=libstdc++11 \"\n                   \"-s compiler.cppstd=98\",\n                   assert_error=True)\n\n        assert \"Invalid: Current cppstd (98) is lower than the required C++ \" \\\n               \"standard (11)\" in client.out\n\n        client.run(\"create . --name pkg --version=0.1  -o header_only=False -o shared=True \"\n                   \"-s os=Macos -s compiler=gcc \"\n                   \"-s compiler.version=11 -s compiler.libcxx=libstdc++11 -s compiler.cppstd=11\",\n                   assert_error=True)\n\n        assert \"Invalid: shared is only supported under windows\" in client.out\n\n    def test_validate_compatible(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.errors import ConanInvalidConfiguration\n            class Pkg(ConanFile):\n                settings = \"os\"\n\n                def validate_build(self):\n                    if self.settings.os == \"Windows\":\n                        raise ConanInvalidConfiguration(\"Windows not supported\")\n\n                def compatibility(self):\n                    if self.settings.os == \"Windows\":\n                        return [{\"settings\": [(\"os\", \"Linux\")]}]\n            \"\"\")\n\n        client.save({\"conanfile.py\": conanfile})\n\n        client.run(\"create . --name=pkg --version=0.1 -s os=Linux\")\n        package_id = \"9a4eb3c8701508aa9458b1a73d0633783ecc2270\"\n        missing_id = \"ebec3dc6d7f6b907b3ada0c3d3cdc83613a2b715\"\n        assert f\"pkg/0.1: Package '{package_id}' created\" in client.out\n\n        # This is the main difference, building from source for the specified conf, fails\n        client.run(\"create . --name=pkg --version=0.1 -s os=Windows\", assert_error=True)\n        assert \"pkg/0.1: Cannot build for this configuration: Windows not supported\" in client.out\n        client.assert_listed_binary({\"pkg/0.1\": (missing_id, \"Invalid\")})\n\n        client.run(\"install --requires=pkg/0.1@ -s os=Windows --build=pkg*\", assert_error=True)\n        assert \"pkg/0.1: Cannot build for this configuration: Windows not supported\" in client.out\n        assert \"Windows not supported\" in client.out\n\n        client.run(\"install --requires=pkg/0.1@ -s os=Windows\")\n        assert f\"pkg/0.1: Main binary package '{missing_id}' missing\" in client.out\n        assert f\"Found compatible package '{package_id}'\" in client.out\n        client.assert_listed_binary({\"pkg/0.1\": (package_id, \"Cache\")})\n\n        # --build=missing means \"use existing binary if possible\", and compatibles are valid binaries\n        client.run(\"install --requires=pkg/0.1@ -s os=Windows --build=missing\")\n        assert f\"pkg/0.1: Main binary package '{missing_id}' missing\" in client.out\n        assert f\"Found compatible package '{package_id}'\" in client.out\n        client.assert_listed_binary({\"pkg/0.1\": (package_id, \"Cache\")})\n\n        client.run(\"graph info --requires=pkg/0.1@ -s os=Windows\")\n        assert f\"pkg/0.1: Main binary package '{missing_id}' missing\" in client.out\n        assert f\"Found compatible package '{package_id}'\" in client.out\n        assert f\"package_id: {package_id}\" in client.out\n\n        client.run(\"graph info --requires=pkg/0.1@ -s os=Windows --build=pkg*\")\n        assert \"binary: Invalid\" in client.out\n\n    def test_validate_remove_package_id_create(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n               from conan import ConanFile\n               from conan.errors import ConanInvalidConfiguration\n               class Pkg(ConanFile):\n                   settings = \"os\"\n\n                   def validate(self):\n                       if self.info.settings.os == \"Windows\":\n                           raise ConanInvalidConfiguration(\"Windows not supported\")\n\n                   def package_id(self):\n                       del self.info.settings.os\n               \"\"\")\n\n        client.save({\"conanfile.py\": conanfile})\n\n        client.run(\"create . --name=pkg --version=0.1 -s os=Linux\")\n        assert \"pkg/0.1: Package '{}' created\".format(NO_SETTINGS_PACKAGE_ID) in client.out\n\n        client.run(\"create . --name=pkg --version=0.1 -s os=Windows\", assert_error=True)\n        assert \"pkg/0.1: Invalid: Windows not supported\" in client.out\n        client.assert_listed_binary({\"pkg/0.1\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\",\n                                                 \"Invalid\")})\n\n        client.run(\"graph info --requires=pkg/0.1@ -s os=Windows\")\n        assert \"package_id: {}\".format(NO_SETTINGS_PACKAGE_ID) in client.out\n\n    def test_validate_compatible_also_invalid(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n           from conan import ConanFile\n           from conan.errors import ConanInvalidConfiguration\n           class Pkg(ConanFile):\n               settings = \"os\", \"build_type\"\n\n               def validate(self):\n                   if self.info.settings.os == \"Windows\":\n                       raise ConanInvalidConfiguration(\"Windows not supported\")\n\n               def compatibility(self):\n                   if self.settings.build_type == \"Debug\" and self.settings.os != \"Windows\":\n                       return [{\"settings\": [(\"build_type\", \"Release\")]}]\n               \"\"\")\n\n        client.save({\"conanfile.py\": conanfile})\n\n        client.run(\"create . --name=pkg --version=0.1 -s os=Linux -s build_type=Release\")\n        package_id = \"c26ded3c7aa4408e7271e458d65421000e000711\"\n        client.assert_listed_binary({\"pkg/0.1\": (package_id, \"Build\")})\n        # compatible_packges fallback works\n        client.run(\"install --requires=pkg/0.1@ -s os=Linux -s build_type=Debug\")\n        client.assert_listed_binary({\"pkg/0.1\": (package_id, \"Cache\")})\n\n        error = client.run(\"create . --name=pkg --version=0.1 -s os=Windows -s build_type=Release\",\n                           assert_error=True)\n\n        assert error == ERROR_INVALID_CONFIGURATION\n        assert \"pkg/0.1: Invalid: Windows not supported\" in client.out\n\n        client.run(\"graph info --requires=pkg/0.1@ -s os=Windows\")\n        assert \"binary: Invalid\" in client.out\n\n    def test_validate_compatible_also_invalid_fail(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n           from conan import ConanFile\n           from conan.errors import ConanInvalidConfiguration\n           class Pkg(ConanFile):\n               settings = \"os\", \"build_type\"\n\n               def validate(self):\n                   if self.info.settings.os == \"Windows\":\n                       raise ConanInvalidConfiguration(\"Windows not supported\")\n\n               def compatibility(self):\n                   if self.settings.build_type == \"Debug\":\n                       return [{\"settings\": [(\"build_type\", \"Release\")]}]\n               \"\"\")\n\n        client.save({\"conanfile.py\": conanfile})\n\n        package_id = \"c26ded3c7aa4408e7271e458d65421000e000711\"\n        client.run(\"create . --name=pkg --version=0.1 -s os=Linux -s build_type=Release\")\n        assert f\"pkg/0.1: Package '{package_id}' created\" in client.out\n        # compatible_packges fallback works\n        client.run(\"install --requires=pkg/0.1@ -s os=Linux -s build_type=Debug\")\n        client.assert_listed_binary({\"pkg/0.1\": (package_id, \"Cache\")})\n        # Windows invalid configuration\n        error = client.run(\"create . --name=pkg --version=0.1 -s os=Windows -s build_type=Release\",\n                           assert_error=True)\n        assert error == ERROR_INVALID_CONFIGURATION\n        assert \"pkg/0.1: Invalid: Windows not supported\" in client.out\n\n        error = client.run(\"install --requires=pkg/0.1@ -s os=Windows -s build_type=Release\",\n                           assert_error=True)\n        assert error == ERROR_INVALID_CONFIGURATION\n        assert \"pkg/0.1: Invalid: Windows not supported\" in client.out\n\n        # Windows missing binary: INVALID\n        error = client.run(\"install --requires=pkg/0.1@ -s os=Windows -s build_type=Debug\",\n                           assert_error=True)\n        assert error == ERROR_INVALID_CONFIGURATION\n        assert \"pkg/0.1: Invalid: Windows not supported\" in client.out\n\n        error = client.run(\"create . --name=pkg --version=0.1 -s os=Windows -s build_type=Debug\",\n                           assert_error=True)\n        assert error == ERROR_INVALID_CONFIGURATION\n        assert \"pkg/0.1: Invalid: Windows not supported\" in client.out\n\n        # info\n        client.run(\"graph info --requires=pkg/0.1@ -s os=Windows\")\n        assert \"binary: Invalid\" in client.out\n        client.run(\"graph info --requires=pkg/0.1@ -s os=Windows -s build_type=Debug\")\n        assert \"binary: Invalid\" in client.out\n\n    def test_validate_options(self):\n        # The dependency option doesn't affect pkg package_id, so it could find a valid binary\n        # in the cache. So ConanInvalidConfiguration will solve this issue.\n        client = TestClient()\n        client.save({\"conanfile.py\": GenConanfile().with_option(\"myoption\", [1, 2, 3])\n                                                   .with_default_option(\"myoption\", 1)})\n        client.run(\"create . --name=dep --version=0.1\")\n        client.run(\"create . --name=dep --version=0.1 -o dep/*:myoption=2\")\n        conanfile = textwrap.dedent(\"\"\"\n           from conan import ConanFile\n           from conan.errors import ConanInvalidConfiguration\n           class Pkg(ConanFile):\n               requires = \"dep/0.1\"\n\n               def validate(self):\n                   if self.dependencies[\"dep\"].options.myoption == 2:\n                       raise ConanInvalidConfiguration(\"Option 2 of 'dep' not supported\")\n           \"\"\")\n\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --name=pkg1 --version=0.1 -o dep/*:myoption=1\")\n\n        client.save({\"conanfile.py\": GenConanfile().with_requires(\"dep/0.1\")\n                                                   .with_default_option(\"dep/*:myoption\", 2)})\n        client.run(\"create . --name=pkg2 --version=0.1\")\n\n        client.save({\"conanfile.py\": GenConanfile().with_requires(\"pkg2/0.1\", \"pkg1/0.1\")})\n        error = client.run(\"install .\", assert_error=True)\n        assert error == ERROR_INVALID_CONFIGURATION\n        assert \"pkg1/0.1: Invalid: Option 2 of 'dep' not supported\" in client.out\n\n    def test_validate_requires(self):\n        client = TestClient()\n        client.save({\"conanfile.py\": GenConanfile()})\n        client.run(\"create . --name=dep --version=0.1\")\n        client.run(\"create . --name=dep --version=0.2\")\n        conanfile = textwrap.dedent(\"\"\"\n           from conan import ConanFile\n           from conan.errors import ConanInvalidConfiguration\n           class Pkg(ConanFile):\n               requires = \"dep/0.1\"\n\n               def validate(self):\n                   if self.dependencies[\"dep\"].ref.version > \"0.1\":\n                       raise ConanInvalidConfiguration(\"dep> 0.1 is not supported\")\n           \"\"\")\n\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --name=pkg1 --version=0.1\")\n\n        client.save({\"conanfile.py\": GenConanfile()\n                    .with_requirement(\"pkg1/0.1\")\n                    .with_requirement(\"dep/0.2\", override=True)})\n        error = client.run(\"install .\", assert_error=True)\n        assert error == ERROR_INVALID_CONFIGURATION\n        assert \"pkg1/0.1: Invalid: dep> 0.1 is not supported\" in client.out\n\n        client.save({\"conanfile.py\": GenConanfile()\n                    .with_requirement(\"pkg1/0.1\")\n                    .with_requirement(\"dep/0.2\", force=True)})\n        error = client.run(\"install .\", assert_error=True)\n        assert error == ERROR_INVALID_CONFIGURATION\n        assert \"pkg1/0.1: Invalid: dep> 0.1 is not supported\" in client.out\n\n    def test_validate_package_id_mode(self):\n        client = TestClient()\n        client.save_home({\"global.conf\": \"core.package_id:default_unknown_mode=full_package_mode\"})\n        conanfile = textwrap.dedent(\"\"\"\n          from conan import ConanFile\n          from conan.errors import ConanInvalidConfiguration\n          class Pkg(ConanFile):\n              settings = \"os\"\n\n              def validate(self):\n                  if self.info.settings.os == \"Windows\":\n                      raise ConanInvalidConfiguration(\"Windows not supported\")\n              \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"export . --name=dep --version=0.1\")\n\n        client.save({\"conanfile.py\": GenConanfile().with_requires(\"dep/0.1\")})\n        error = client.run(\"create . --name=pkg --version=0.1 -s os=Windows\", assert_error=True)\n        assert error == ERROR_INVALID_CONFIGURATION\n        client.assert_listed_binary({\"dep/0.1\": (\"ebec3dc6d7f6b907b3ada0c3d3cdc83613a2b715\",\n                                                 \"Invalid\")})\n        client.assert_listed_binary({\"pkg/0.1\": (\"19ad5731bb09f24646c81060bd7730d6cb5b6108\",\n                                                 \"Build\")})\n        assert \"ERROR: There are invalid packages:\" in client.out\n        assert \"dep/0.1: Invalid: Windows not supported\" in client.out\n\n    def test_validate_export_pkg(self):\n        # https://github.com/conan-io/conan/issues/9797\n        c = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.errors import ConanInvalidConfiguration\n\n            class TestConan(ConanFile):\n                def validate(self):\n                    raise ConanInvalidConfiguration(\"never ever\")\n            \"\"\")\n        c.save({\"conanfile.py\": conanfile})\n        c.run(\"export-pkg . --name=test --version=1.0\", assert_error=True)\n        assert \"ERROR: conanfile.py (test/1.0): Invalid ID: Invalid: never ever\" in c.out\n\n    def test_validate_build_export_pkg(self):\n        # https://github.com/conan-io/conan/issues/9797\n        c = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n               from conan import ConanFile\n               from conan.errors import ConanInvalidConfiguration\n\n               class TestConan(ConanFile):\n                   def validate_build(self):\n                       raise ConanInvalidConfiguration(\"never ever\")\n               \"\"\")\n        c.save({\"conanfile.py\": conanfile})\n        c.run(\"export-pkg . --name=test --version=1.0\", assert_error=True)\n        assert \"conanfile.py (test/1.0): Cannot build for this configuration: never ever\" in c.out\n\n    def test_validate_install(self):\n        # https://github.com/conan-io/conan/issues/10602\n        c = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.errors import ConanInvalidConfiguration\n\n            class TestConan(ConanFile):\n                def validate(self):\n                    raise ConanInvalidConfiguration(\"never ever\")\n            \"\"\")\n        c.save({\"conanfile.py\": conanfile})\n        c.run(\"install .\", assert_error=True)\n        assert \"ERROR: conanfile.py: Invalid ID: Invalid: never ever\" in c.out\n\n\nclass TestValidateCppstd:\n    \"\"\" aims to be a very close to real use case of cppstd management and validation in recipes\n    \"\"\"\n    def test_build_17_consume_14(self):\n        client = TestClient()\n        # simplify it a bit\n        compat = textwrap.dedent(\"\"\"\\\n            def compatibility(conanfile):\n                return [{\"settings\": [(\"compiler.cppstd\", v)]} for v in (\"11\", \"14\", \"17\", \"20\")]\n            \"\"\")\n        client.save_home({\"extensions/plugins/compatibility/compatibility.py\": compat})\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.errors import ConanInvalidConfiguration\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                settings = \"compiler\"\n\n                def validate_build(self):\n                    # Explicit logic instead of using check_min_cppstd that hides details\n                    if int(str(self.settings.compiler.cppstd)) < 17:\n                        raise ConanInvalidConfiguration(\"I need at least cppstd=17 to build\")\n\n                def validate(self):\n                    if int(str(self.settings.compiler.cppstd)) < 14:\n                        raise ConanInvalidConfiguration(\"I need at least cppstd=14 to be used\")\n            \"\"\")\n\n        client.save({\"conanfile.py\": conanfile})\n\n        settings = \"-s compiler=gcc -s compiler.version=9 -s compiler.libcxx=libstdc++\"\n        client.run(f\"create . {settings} -s compiler.cppstd=17\")\n        client.assert_listed_binary({\"pkg/0.1\": (\"91faf062eb94767a31ff62a46767d3d5b41d1eff\",\n                                                 \"Build\")})\n        # create with cppstd=14 fails, not enough\n        client.run(f\"create . {settings} -s compiler.cppstd=14\", assert_error=True)\n        client.assert_listed_binary({\"pkg/0.1\": (\"36d978cbb4dc35906d0fd438732d5e17cd1e388d\",\n                                                 \"Invalid\")})\n        assert \"pkg/0.1: Cannot build for this configuration: I need at least cppstd=17 to build\" \\\n               in client.out\n\n        # Install with cppstd=14 can fallback to the previous one\n        client.run(f\"install --requires=pkg/0.1 {settings} -s compiler.cppstd=14\")\n        # 2 valid binaries, 17 and 20\n        assert \"pkg/0.1: Checking 2 compatible configurations\" in client.out\n        client.assert_listed_binary({\"pkg/0.1\": (\"91faf062eb94767a31ff62a46767d3d5b41d1eff\",\n                                                 \"Cache\")})\n\n        # install with not enough cppstd should fail\n        client.run(f\"install --requires=pkg/0.1@ {settings} -s compiler.cppstd=11\",\n                   assert_error=True)\n        # not even trying to fallback to compatibles\n        assert \"pkg/0.1: Checking\" not in client.out\n        client.assert_listed_binary({\"pkg/0.1\": (\"8415595b7485d90fc413c2f47298aa5fb05a5468\",\n                                                 \"Invalid\")})\n        assert \"I need at least cppstd=14 to be used\" in client.out\n\n    def test_header_only_14(self):\n        client = TestClient()\n\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.build import check_min_cppstd\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                settings = \"compiler\"\n\n                def package_id(self):\n                    self.info.clear()\n\n                def validate(self):\n                    check_min_cppstd(self, 14)\n            \"\"\")\n\n        client.save({\"conanfile.py\": conanfile})\n\n        settings = \"-s compiler=gcc -s compiler.version=9 -s compiler.libcxx=libstdc++\"\n        client.run(f\"create . {settings} -s compiler.cppstd=17\")\n        client.assert_listed_binary({\"pkg/0.1\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\",\n                                                 \"Build\")})\n        client.run(f\"create . {settings} -s compiler.cppstd=14\")\n        client.assert_listed_binary({\"pkg/0.1\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\",\n                                                 \"Build\")})\n\n        client.run(f\"create . {settings} -s compiler.cppstd=11\", assert_error=True)\n        client.assert_listed_binary({\"pkg/0.1\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\",\n                                                 \"Invalid\")})\n        assert \"Current cppstd (11) is lower than the required C++ standard (14)\" in client.out\n\n        # Install with cppstd=14 can fallback to the previous one\n        client.run(f\"install --requires=pkg/0.1 {settings} -s compiler.cppstd=14\")\n        client.assert_listed_binary({\"pkg/0.1\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\",\n                                                 \"Cache\")})\n\n        # install with not enough cppstd should fail\n        client.run(f\"install --requires=pkg/0.1@ {settings} -s compiler.cppstd=11\",\n                   assert_error=True)\n        # not even trying to fallback to compatibles\n        assert \"pkg/0.1: Checking\" not in client.out\n        client.assert_listed_binary({\"pkg/0.1\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\",\n                                                 \"Invalid\")})\n        assert \"Current cppstd (11) is lower than the required C++ standard (14)\" in client.out\n\n    def test_build_17_consume_14_transitive(self):\n        \"\"\" what happens if we have:\n        app->engine(shared-lib)->pkg(static-lib)\n        if pkg is only buildable with cppstd>=17 and needs cppstd>=14 to be consumed, but\n        as it is static it becomes an implementation detail of engine, that doesn't have any\n        constraint or validate() at all\n        \"\"\"\n        client = TestClient()\n        # simplify it a bit\n        compat = textwrap.dedent(\"\"\"\\\n            def compatibility(conanfile):\n                return [{\"settings\": [(\"compiler.cppstd\", v)]} for v in (\"11\", \"14\", \"17\", \"20\")]\n            \"\"\")\n        client.save_home({\"extensions/plugins/compatibility/compatibility.py\": compat})\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.errors import ConanInvalidConfiguration\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                settings = \"compiler\"\n                package_type = \"static-library\"\n\n                def validate_build(self):\n                    # Explicit logic instead of using check_min_cppstd that hides details\n                    if int(str(self.settings.compiler.cppstd)) < 17:\n                        raise ConanInvalidConfiguration(\"I need at least cppstd=17 to build\")\n\n                def validate(self):\n                    if int(str(self.settings.compiler.cppstd)) < 14:\n                        raise ConanInvalidConfiguration(\"I need at least cppstd=14 to be used\")\n            \"\"\")\n        engine = GenConanfile(\"engine\", \"0.1\").with_package_type(\"shared-library\") \\\n                                              .with_requires(\"pkg/0.1\")\n        app = GenConanfile(\"app\", \"0.1\").with_package_type(\"application\") \\\n                                        .with_requires(\"engine/0.1\")\n        client.save({\"pkg/conanfile.py\": conanfile,\n                     \"engine/conanfile.py\": engine,\n                     \"app/conanfile.py\": app})\n\n        settings = \"-s compiler=gcc -s compiler.version=9 -s compiler.libcxx=libstdc++\"\n        client.run(f\"create pkg {settings} -s compiler.cppstd=17\")\n        client.assert_listed_binary({\"pkg/0.1\": (\"91faf062eb94767a31ff62a46767d3d5b41d1eff\",\n                                                 \"Build\")})\n        client.run(f\"create engine {settings} -s compiler.cppstd=17\")\n        client.assert_listed_binary({\"pkg/0.1\": (\"91faf062eb94767a31ff62a46767d3d5b41d1eff\",\n                                                 \"Cache\")})\n        client.run(f\"install app {settings} -s compiler.cppstd=17 -v\")\n        client.assert_listed_binary({\"pkg/0.1\": (\"91faf062eb94767a31ff62a46767d3d5b41d1eff\",\n                                                 \"Skip\")})\n        client.run(f\"install app {settings} -s compiler.cppstd=14 -v\")\n        client.assert_listed_binary({\"pkg/0.1\": (\"91faf062eb94767a31ff62a46767d3d5b41d1eff\",\n                                                 \"Skip\")})\n        # No binary for engine exist for cppstd=11\n        client.run(f\"install app {settings} -s compiler.cppstd=11\", assert_error=True)\n        client.assert_listed_binary({\"engine/0.1\": (\"dc24e2caf6e1fa3e8bb047ca0f5fa053c71df6db\",\n                                                    \"Missing\")})\n        client.run(f\"install app {settings} -s compiler.cppstd=11 --build=missing\",\n                   assert_error=True)\n        assert 'pkg/0.1: Invalid: I need at least cppstd=14 to be used' in client.out\n\n    def test_build_17_consume_14_transitive_erasure(self):\n        \"\"\" The same as the above test:\n        app->engine(shared-lib)->pkg(static-lib)\n        but in this test, the engine shared-lib does \"package_id()\" erasure of \"pkg\" dependency,\n        being able to reuse it then even when cppstd==11\n        \"\"\"\n        client = TestClient()\n        # simplify it a bit\n        compat = textwrap.dedent(\"\"\"\\\n            def compatibility(conanfile):\n                return [{\"settings\": [(\"compiler.cppstd\", v)]} for v in (\"11\", \"14\", \"17\", \"20\")]\n            \"\"\")\n        client.save_home({\"extensions/plugins/compatibility/compatibility.py\": compat})\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.errors import ConanInvalidConfiguration\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                settings = \"compiler\"\n                package_type = \"static-library\"\n\n                def validate_build(self):\n                    # Explicit logic instead of using check_min_cppstd that hides details\n                    if int(str(self.settings.compiler.cppstd)) < 17:\n                        raise ConanInvalidConfiguration(\"I need at least cppstd=17 to build\")\n\n                def validate(self):\n                    if int(str(self.settings.compiler.cppstd)) < 14:\n                        raise ConanInvalidConfiguration(\"I need at least cppstd=14 to be used\")\n            \"\"\")\n        engine = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.errors import ConanInvalidConfiguration\n            class Pkg(ConanFile):\n                name = \"engine\"\n                version = \"0.1\"\n                settings = \"compiler\"\n                package_type = \"shared-library\"\n                requires = \"pkg/0.1\"\n\n                def package_id(self):\n                    del self.info.settings.compiler.cppstd\n                    self.info.requires[\"pkg\"].full_version_mode()\n\n            \"\"\")\n        app = GenConanfile(\"app\", \"0.1\").with_package_type(\"application\") \\\n                                        .with_requires(\"engine/0.1\")\n        client.save({\"pkg/conanfile.py\": conanfile,\n                     \"engine/conanfile.py\": engine,\n                     \"app/conanfile.py\": app})\n\n        settings = \"-s compiler=gcc -s compiler.version=9 -s compiler.libcxx=libstdc++\"\n        client.run(f\"create pkg {settings} -s compiler.cppstd=17\")\n        client.assert_listed_binary({\"pkg/0.1\": (\"91faf062eb94767a31ff62a46767d3d5b41d1eff\",\n                                                 \"Build\")})\n        client.run(f\"create engine {settings} -s compiler.cppstd=17\")\n        client.assert_listed_binary({\"engine/0.1\": (\"493976208e9989b554704f94f9e7b8e5ba39e5ab\",\n                                                    \"Build\")})\n        client.assert_listed_binary({\"pkg/0.1\": (\"91faf062eb94767a31ff62a46767d3d5b41d1eff\",\n                                                 \"Cache\")})\n        client.run(f\"install app {settings} -s compiler.cppstd=17 -v\")\n        client.assert_listed_binary({\"engine/0.1\": (\"493976208e9989b554704f94f9e7b8e5ba39e5ab\",\n                                                    \"Cache\")})\n        client.assert_listed_binary({\"pkg/0.1\": (\"91faf062eb94767a31ff62a46767d3d5b41d1eff\",\n                                                 \"Skip\")})\n        client.run(f\"install app {settings} -s compiler.cppstd=14 -v\")\n        client.assert_listed_binary({\"engine/0.1\": (\"493976208e9989b554704f94f9e7b8e5ba39e5ab\",\n                                                    \"Cache\")})\n        client.assert_listed_binary({\"pkg/0.1\": (\"91faf062eb94767a31ff62a46767d3d5b41d1eff\",\n                                                 \"Skip\")})\n        # No binary for engine exist for cppstd=11\n        client.run(f\"install app {settings} -s compiler.cppstd=11 -v\")\n        client.assert_listed_binary({\"pkg/0.1\": (\"8415595b7485d90fc413c2f47298aa5fb05a5468\",\n                                                 \"Skip\")})\n        client.assert_listed_binary({\"engine/0.1\": (\"493976208e9989b554704f94f9e7b8e5ba39e5ab\",\n                                                    \"Cache\")})\n        client.run(f\"install app {settings} -s compiler.cppstd=11 --build=engine*\",\n                   assert_error=True)\n        assert 'pkg/0.1: Invalid: I need at least cppstd=14 to be used' in client.out\n\n    @pytest.mark.parametrize(\"use_attribute\", [True, False])\n    def test_exact_cppstd(self, use_attribute):\n        \"\"\" Using the default cppstd_compat sometimes is not desired, and a recipe can\n        explicitly opt-out this default cppstd_compat behavior, if it knows its binaries\n        won't be binary compatible among them for different cppstd values\n        \"\"\"\n        client = TestClient()\n        if use_attribute:\n            conanfile = textwrap.dedent(\"\"\"\n                from conan import ConanFile\n                class Pkg(ConanFile):\n                    settings = \"compiler\"\n                    extension_properties = {\"compatibility_cppstd\": False}\n            \"\"\")\n        else:\n            conanfile = textwrap.dedent(\"\"\"\n                from conan import ConanFile\n                class Pkg(ConanFile):\n                    settings = \"compiler\"\n                    def compatibility(self):\n                        self.extension_properties = {\"compatibility_cppstd\": False}\n            \"\"\")\n\n        client.save({\"conanfile.py\": conanfile})\n\n        settings = \"-s compiler=gcc -s compiler.version=9 -s compiler.libcxx=libstdc++\"\n        client.run(f\"create . --name=pkg --version=0.1 {settings} -s compiler.cppstd=17\")\n        client.assert_listed_binary({\"pkg/0.1\": (\"91faf062eb94767a31ff62a46767d3d5b41d1eff\",\n                                                 \"Build\")})\n\n        # Install with cppstd=14 can NOT fallback to the previous one\n        client.run(f\"install --requires=pkg/0.1 {settings} -s compiler.cppstd=14\", assert_error=True)\n        assert \"ERROR: Missing prebuilt package for 'pkg/0.1'\" in client.out\n        assert \"compiler.cppstd=14\" in client.out\n        assert \"compiler.cppstd=17\" not in client.out\n        client.run(f\"install --requires=pkg/0.1 {settings} -s compiler.cppstd=14 --build=missing\")\n        client.assert_listed_binary({\"pkg/0.1\": (\"36d978cbb4dc35906d0fd438732d5e17cd1e388d\",\n                                                 \"Build\")})\n        assert \"compiler.cppstd=14\" in client.out\n        assert \"compiler.cppstd=17\" not in client.out\n\n    @pytest.mark.skipif(platform.system() == \"Windows\",\n                        reason=\"Needs at least 3 cppstd values available, msvc 191 does not\")\n    def test_extension_properties_cppstd_compat_non_transitiveness(self):\n        \"\"\"\n        The cppstd_compat is not transitive, so if a recipe has cppstd_compat=False,\n        its dependencies will still be checked for compatibility\n        \"\"\"\n        tc = TestClient()\n        tc.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"1.0\").with_setting(\"compiler\"),\n                 \"lib/conanfile.py\": GenConanfile(\"lib\", \"1.0\").with_setting(\"compiler\")\n                 .with_class_attribute('extension_properties = {\"compatibility_cppstd\": False}')\n                 .with_requirement(\"dep/1.0\"),\n                 \"app/conanfile.py\": GenConanfile(\"app\", \"1.0\").with_setting(\"compiler\")\n                 .with_requirement(\"lib/1.0\")})\n        tc.run(\"create dep -s=compiler.cppstd=20\")\n        tc.run(\"create lib -s=compiler.cppstd=17\")\n        tc.run(\"create app -s=compiler.cppstd=14\", assert_error=True)\n\n        tc.run(\"install --requires=app/1.0 -s=compiler.cppstd=11\", assert_error=True)\n        assert \"dep/1.0: Found compatible package\" in tc.out\n        assert \"ERROR: Missing binary: app/1.0\" in tc.out\n\n    def test_extension_properties_make_transitive(self):\n        \"\"\"\n        The cppstd_compat is not transitive, so if a recipe has cppstd_compat=False,\n        its dependencies will still be checked for compatibility\n        \"\"\"\n        tc = TestClient()\n        tc.save({\"lib/conanfile.py\": GenConanfile(\"lib\", \"1.0\").with_setting(\"compiler\"),\n                 \"dep/conanfile.py\": GenConanfile(\"dep\", \"1.0\").with_setting(\"compiler\")\n                .with_class_attribute('extension_properties = {\"compatibility_cppstd\": False}')\n                .with_requirement(\"lib/1.0\"),\n                 \"conanfile.py\": GenConanfile(\"app\", \"1.0\").with_setting(\"compiler\")\n                .with_requirement(\"dep/1.0\")})\n        tc.run(\"create lib -s=compiler.cppstd=17\")\n        tc.run(\"create dep -s=compiler.cppstd=14\")\n        tc.run(\"create . -s=compiler.cppstd=14\")\n\n        compat_path = os.path.join(tc.cache_folder,\n                                   \"extensions/plugins/compatibility/compatibility.py\")\n        compat_contents = load(compat_path)\n\n        transitive_expansions = textwrap.indent(textwrap.dedent(\"\"\"\n            extension_properties = getattr(conanfile, \"extension_properties\", {}).copy()\n            for dep in conanfile.dependencies.values():\n                if not dep.extension_properties.get(\"compatibility_cppstd\", True):\n                    extension_properties[\"compatibility_cppstd\"] = False\n            \"\"\"), \"    \")\n        existing = 'extension_properties = getattr(conanfile, \"extension_properties\", {})'\n        compat_contents = compat_contents.replace(existing, transitive_expansions)\n        save(compat_path, compat_contents)\n\n        tc.run(\"install --requires=app/1.0 -s=compiler.cppstd=17\", assert_error=True)\n\n        assert \"Missing prebuilt package for 'app/1.0', 'dep/1.0'\" in tc.out\n\n\nclass TestCompatibleSettingsTarget:\n    \"\"\" aims to be a very close to real use case of tool being used across different settings_target\n    \"\"\"\n    def test_settings_target_in_compatibility_method_within_recipe(self):\n        client = TestClient()\n        \"\"\"\n        test setting_target in recipe's compatibility method\n        \"\"\"\n        tool_conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class Pkg(ConanFile):\n                settings = \"arch\"\n                def compatibility(self):\n                    if self.settings_target.arch == \"armv7\":\n                        return [{\"settings_target\": [(\"arch\", \"armv6\")]}]\n\n                def package_id(self):\n                    self.info.settings_target = self.settings_target\n                    for field in self.info.settings_target.fields:\n                        if field != \"arch\":\n                            self.info.settings_target.rm_safe(field)\n            \"\"\")\n\n        client.save({\"conanfile.py\": tool_conanfile})\n        client.run(\"create . --name=tool --version=0.1 -s os=Linux -s:h arch=armv6 --build-require\")\n        package_id = client.created_package_id(\"tool/0.1\")\n        assert f\"tool/0.1: Package '{package_id}' created\" in client.out\n\n        app_conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class Pkg(ConanFile):\n                settings = \"arch\"\n                def requirements(self):\n                    self.tool_requires(\"tool/0.1\")\n            \"\"\")\n\n        client.save({\"conanfile.py\": app_conanfile})\n        client.run(\"create . --name=app --version=0.1 -s os=Linux -s:h arch=armv7\")\n        assert f\"Found compatible package '{package_id}'\" in client.out\n\n    def test_settings_target_in_compatibility_in_global_compatibility_py(self):\n        client = TestClient()\n        \"\"\"\n        test setting_target in global compatibility method\n        \"\"\"\n        compat = textwrap.dedent(\"\"\"\\\n            def compatibility(self):\n                if self.settings_target.arch == \"armv7\":\n                    return [{\"settings_target\": [(\"arch\", \"armv6\")]}]\n            \"\"\")\n        client.save_home({\"extensions/plugins/compatibility/compatibility.py\": compat})\n\n        tool_conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class Pkg(ConanFile):\n                settings = \"arch\"\n\n                def package_id(self):\n                    self.info.settings_target = self.settings_target\n                    for field in self.info.settings_target.fields:\n                        if field != \"arch\":\n                            self.info.settings_target.rm_safe(field)\n            \"\"\")\n\n        client.save({\"conanfile.py\": tool_conanfile})\n        client.run(\"create . --name=tool --version=0.1 -s os=Linux -s:h arch=armv6 --build-require\")\n        package_id = client.created_package_id(\"tool/0.1\")\n\n        assert f\"tool/0.1: Package '{package_id}' created\" in client.out\n\n        app_conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class Pkg(ConanFile):\n                settings = \"arch\"\n                def requirements(self):\n                    self.tool_requires(\"tool/0.1\")\n            \"\"\")\n\n        client.save({\"conanfile.py\": app_conanfile})\n        client.run(\"create . --name=app --version=0.1 -s os=Linux -s:h arch=armv7\")\n        assert f\"Found compatible package '{package_id}'\" in client.out\n\n    def test_no_settings_target_in_recipe_but_in_compatibility_method(self):\n        client = TestClient()\n        \"\"\"\n        test settings_target in compatibility method when recipe is not a build-require\n        this should not crash. When building down-stream package it should end up with\n        ERROR_GENERAL instead of crash\n        \"\"\"\n\n        tool_conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class Pkg(ConanFile):\n                settings = \"arch\"\n                def compatibility(self):\n                    if self.settings_target.arch == \"armv7\":\n                        return [{\"settings_target\": [(\"arch\", \"armv6\")]}]\n            \"\"\")\n\n        client.save({\"conanfile.py\": tool_conanfile})\n        client.run(\"create . --name=tool --version=0.1 -s os=Linux -s:h arch=armv6\")\n        package_id = client.created_package_id(\"tool/0.1\")\n        assert f\"tool/0.1: Package '{package_id}' created\" in client.out\n\n        app_conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class Pkg(ConanFile):\n                settings = \"arch\"\n                def requirements(self):\n                    self.tool_requires(\"tool/0.1\")\n            \"\"\")\n\n        client.save({\"conanfile.py\": app_conanfile})\n        error = client.run(\"create . --name=app --version=0.1 -s os=Linux -s:h arch=armv7\",\n                           assert_error=True)\n        assert error == ERROR_GENERAL\n        assert \"ERROR: Missing prebuilt package for 'tool/0.1'\" in client.out\n\n    def test_no_settings_target_in_recipe_but_in_global_compatibility(self):\n        client = TestClient()\n        \"\"\"\n        test settings_target in global compatibility method when recipe is not a build-require\n        this should not crash. When building down-stream package it should end up with\n        ERROR_GENERAL instead of crash\n        \"\"\"\n        compat = textwrap.dedent(\"\"\"\\\n            def compatibility(self):\n                if self.settings_target.arch == \"armv7\":\n                    return [{\"settings_target\": [(\"arch\", \"armv6\")]}]\n            \"\"\")\n        client.save_home({\"extensions/plugins/compatibility/compatibility.py\": compat})\n\n        tool_conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class Pkg(ConanFile):\n                settings = \"arch\"\n            \"\"\")\n\n        client.save({\"conanfile.py\": tool_conanfile})\n        client.run(\"create . --name=tool --version=0.1 -s os=Linux -s:h arch=armv6\")\n        package_id = client.created_package_id(\"tool/0.1\")\n        assert f\"tool/0.1: Package '{package_id}' created\" in client.out\n\n        app_conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class Pkg(ConanFile):\n                settings = \"arch\"\n                def requirements(self):\n                    self.tool_requires(\"tool/0.1\")\n            \"\"\")\n\n        client.save({\"conanfile.py\": app_conanfile})\n        error = client.run(\"create . --name=app --version=0.1 -s os=Linux -s:h arch=armv7\",\n                           assert_error=True)\n        assert error == ERROR_GENERAL\n        assert \"ERROR: Missing prebuilt package for 'tool/0.1'\" in client.out\n\n    def test_three_packages_with_and_without_settings_target(self):\n        client = TestClient()\n        \"\"\"\n        test 3 packages, tool_a and tool_b have a mutual downstream package (app), and when\n        build app it should find tool_a (a compatible version of it), and find tool_b,\n        and conan create should be successful.\n        \"\"\"\n        compat = textwrap.dedent(\"\"\"\\\n            def compatibility(self):\n                if self.settings_target.arch == \"armv7\":\n                    return [{\"settings_target\": [(\"arch\", \"armv6\")]}]\n            \"\"\")\n        client.save_home({\"extensions/plugins/compatibility/compatibility.py\": compat})\n\n        tool_a_conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class Pkg(ConanFile):\n                settings = \"arch\"\n\n                def package_id(self):\n                    self.info.settings_target = self.settings_target\n                    for field in self.info.settings_target.fields:\n                        if field != \"arch\":\n                            self.info.settings_target.rm_safe(field)\n            \"\"\")\n\n        client.save({\"conanfile.py\": tool_a_conanfile})\n        client.run(\"create . --name=tool_a --version=0.1 \"\n                   \"-s os=Linux -s:h arch=armv6 -s:b arch=x86_64 --build-require\")\n        package_id_tool_a = client.created_package_id(\"tool_a/0.1\")\n        assert f\"tool_a/0.1: Package '{package_id_tool_a}' created\" in client.out\n\n        tool_b_conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class Pkg(ConanFile):\n                settings = \"arch\"\n            \"\"\")\n\n        client.save({\"conanfile.py\": tool_b_conanfile})\n        client.run(\"create . --name=tool_b --version=0.1 -s os=Linux \"\n                   \"-s arch=x86_64 -s:b arch=x86_64\")\n        package_id_tool_b = client.created_package_id(\"tool_b/0.1\")\n        assert f\"tool_b/0.1: Package '{package_id_tool_b}' created\" in client.out\n\n        app_conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class Pkg(ConanFile):\n                settings = \"arch\"\n                def requirements(self):\n                    self.tool_requires(\"tool_a/0.1\")\n                    self.tool_requires(\"tool_b/0.1\")\n            \"\"\")\n\n        client.save({\"conanfile.py\": app_conanfile})\n        client.run(\"create . --name=app --version=0.1 -s os=Linux -s:h arch=armv7 -s:b arch=x86_64\")\n        assert f\"Found compatible package '{package_id_tool_a}'\" in client.out\n        assert package_id_tool_b in client.out\n\n    def test_settings_target_in_compatibility_method_within_recipe_package_info(self):\n        # https://github.com/conan-io/conan/issues/14823\n        client = TestClient()\n        tool_conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class Pkg(ConanFile):\n                settings = \"arch\"\n\n                def compatibility(self):\n                    return [{'settings': [('arch', 'armv6')]}]\n\n                def package_info(self):\n                    # This used to crash\n                    self.settings_target.get_safe('compiler.link_time_optimization')\n            \"\"\")\n\n        client.save({\"conanfile.py\": tool_conanfile})\n        client.run(\"create . --name=tool --version=0.1 -s os=Linux -s:b arch=armv6 --build-require\")\n        package_id = client.created_package_id(\"tool/0.1\")\n        assert f\"tool/0.1: Package '{package_id}' created\" in client.out\n\n        client.run(\"install --tool-requires=tool/0.1 -s os=Linux -s:b arch=armv7\")\n        # This used to crash, not anymore\n        assert f\"Found compatible package '{package_id}'\" in client.out\n"
  },
  {
    "path": "test/integration/package_id/transitive_header_only_test.py",
    "content": "from conan.test.utils.tools import TestClient, GenConanfile\n\n\nclass TestTransitiveIds:\n\n    def test_transitive_library(self):\n        # https://github.com/conan-io/conan/issues/6450\n        client = TestClient(light=True)\n        client.save_home({\"global.conf\": \"core.package_id:default_unknown_mode=full_version_mode\"})\n        client.save({\"conanfile.py\": GenConanfile()})\n        client.run(\"create . --name=liba --version=1.0\")\n        client.run(\"create . --name=liba --version=1.1\")\n        client.save({\"conanfile.py\": GenConanfile().with_require(\"liba/1.0\")})\n        client.run(\"create . --name=libb --version=1.0\")\n        client.save({\"conanfile.py\": GenConanfile().with_require(\"libb/1.0\")})\n        client.run(\"create . --name=libc --version=1.0\")\n        client.save({\"conanfile.py\": GenConanfile().with_require(\"libc/1.0\")\n                                                   .with_require(\"liba/1.0\")})\n        client.run(\"create . --name=libd --version=1.0\")\n        # The consumer forces to depend on liba/2, instead of liba/1\n        client.save({\"conanfile.py\": GenConanfile().with_require(\"libc/1.0\")\n                                                   .with_requirement(\"liba/1.1\", force=True)})\n        client.run(\"create . --name=libd --version=1.0\", assert_error=True)\n        # both B and C require a new binary\n        client.assert_listed_binary(\n            {\"liba/1.1\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\", \"Cache\"),\n             \"libb/1.0\": (\"efdeb15efa0e3e6ce0c9ef9bd82c56e4b2188c8a\", \"Missing\"),\n             \"libc/1.0\": (\"fea281081e89fcc36242a68b0dbb16276a84f624\", \"Missing\"),\n             \"libd/1.0\": (\"13a3ed814d78c8b91f303db7d4cdd7c4e614323c\", \"Build\")\n             })\n\n    def test_transitive_major_mode(self):\n        # https://github.com/conan-io/conan/issues/6450\n        # Test LibE->LibD->LibC->LibB->LibA\n        # LibC declares that it only depends on major version changes of its upstream\n        # So LibC package ID doesn't change, even if LibA changes\n        # But LibD package ID changes, even if its direct dependency LibC doesn't\n        client = TestClient(light=True)\n        client.save_home({\"global.conf\": \"core.package_id:default_unknown_mode=full_version_mode\"})\n        # LibA\n        client.save({\"conanfile.py\": GenConanfile()})\n        client.run(\"create . --name=liba --version=1.0\")\n        client.run(\"create . --name=liba --version=1.1\")\n        # libB -> LibA\n        client.save({\"conanfile.py\": GenConanfile().with_require(\"liba/1.0\")})\n        client.run(\"create . --name=libb --version=1.0\")\n        # libC -> libB\n        major_mode = \"self.info.requires.major_mode()\"\n        client.save({\"conanfile.py\": GenConanfile().with_require(\"libb/1.0\")\n                                                   .with_package_id(major_mode)})\n        client.run(\"create . --name=libc --version=1.0\")\n        # Check the LibC ref with RREV keeps the same\n        client.assert_listed_binary({\"libc/1.0\": (\"2aa3bb6726dfc6c825a91f3b465b769e770ee902\",\n                                                  \"Build\")})\n        # LibD -> LibC\n        client.save({\"conanfile.py\": GenConanfile().with_require(\"libc/1.0\")})\n        client.run(\"create . --name=libd --version=1.0\")\n        # LibE -> LibD, LibA/2.0\n        client.save({\"conanfile.py\": GenConanfile().with_require(\"libd/1.0\")\n                                                   .with_requirement(\"liba/1.1\", force=True)})\n        client.run(\"create . --name=libe --version=1.0\", assert_error=True)\n        # Check the LibC ref with RREV keeps the same, it is in cache, not missing\n        # But LibD package ID changes and is missing, because it depends transitively on LibA\n        client.assert_listed_binary(\n            {\"liba/1.1\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\", \"Cache\"),\n             \"libb/1.0\": (\"efdeb15efa0e3e6ce0c9ef9bd82c56e4b2188c8a\", \"Missing\"),\n             \"libc/1.0\": (\"2aa3bb6726dfc6c825a91f3b465b769e770ee902\", \"Cache\"),\n             \"libd/1.0\": (\"13a3ed814d78c8b91f303db7d4cdd7c4e614323c\", \"Missing\"),\n             \"libe/1.0\": (\"f93a37dd8bc53991d7485235c6b3e448942c52ff\", \"Build\")\n             })\n\n    def test_transitive_unrelated(self):\n        # https://github.com/conan-io/conan/issues/6450\n        client = TestClient(light=True)\n        # LibA\n        client.save({\"conanfile.py\": GenConanfile()})\n        client.run(\"create . --name=liba --version=1.0\")\n        client.run(\"create . --name=liba --version=2.0\")\n        # libB -> LibA\n        client.save({\"conanfile.py\": GenConanfile().with_require(\"liba/1.0\")})\n        client.run(\"create . --name=libb --version=1.0\")\n        # libC -> libB\n        unrelated = \"self.info.requires['libb'].unrelated_mode()\"\n        client.save({\"conanfile.py\": GenConanfile().with_require(\"libb/1.0\")\n                    .with_package_id(unrelated)})\n        client.run(\"create . --name=libc --version=1.0\")\n        # LibD -> LibC\n        client.save({\"conanfile.py\": GenConanfile().with_require(\"libc/1.0\")})\n        client.run(\"create . --name=libd --version=1.0\")\n        # LibE -> LibD, LibA/2.0\n        client.save({\"conanfile.py\": GenConanfile().with_require(\"libd/1.0\")\n                    .with_requirement(\"liba/2.0\", force=True)})\n        client.run(\"create . --name=libe --version=1.0\", assert_error=True)\n        client.assert_listed_binary({\"liba/2.0\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\", \"Cache\"),\n                                     \"libb/1.0\": (\"9c5273fc489264e39c2c16494d8a4178f239e6e2\", \"Missing\"),\n                                     \"libc/1.0\": (\"9c5273fc489264e39c2c16494d8a4178f239e6e2\", \"Missing\"),\n                                     \"libd/1.0\": (\"060865748907651202e4caa396a4c11a11f91e28\", \"Missing\")})\n\n    def test_transitive_second_level_header_only(self):\n        # https://github.com/conan-io/conan/issues/6450\n        client = TestClient(light=True)\n        # LibA\n        client.save({\"conanfile.py\": GenConanfile()})\n        client.run(\"create . --name=liba --version=1.0\")\n        client.run(\"create . --name=liba --version=2.0\")\n        # libB -> LibA\n        client.save({\"conanfile.py\": GenConanfile().with_require(\"liba/1.0\")})\n        client.run(\"create . --name=libb --version=1.0\")\n        # libC -> libB\n\n        unrelated = \"self.info.clear()\"\n        client.save({\"conanfile.py\": GenConanfile().with_require(\"libb/1.0\")\n                                                   .with_package_id(unrelated)})\n        client.run(\"create . --name=libc --version=1.0\")\n        # LibD -> LibC\n        client.save({\"conanfile.py\": GenConanfile().with_require(\"libc/1.0\")})\n        client.run(\"create . --name=libd --version=1.0\")\n        client.assert_listed_binary({\"libc/1.0\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\", \"Cache\")})\n\n        # LibE -> LibD, LibA/2.0\n        client.save({\"conanfile.py\": GenConanfile().with_require(\"libd/1.0\")\n                                                   .with_requirement(\"liba/2.0\", force=True)})\n        client.run(\"create . --name=libe --version=1.0\", assert_error=True)  # LibD is NOT missing!\n\n        client.assert_listed_binary(\n            {\"liba/2.0\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\", \"Cache\"),\n             \"libb/1.0\": (\"9c5273fc489264e39c2c16494d8a4178f239e6e2\", \"Missing\"),\n             \"libc/1.0\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\", \"Cache\"),\n             \"libd/1.0\": (\"060865748907651202e4caa396a4c11a11f91e28\", \"Missing\")})\n\n    def test_transitive_header_only(self):\n        # https://github.com/conan-io/conan/issues/6450\n        client = TestClient(light=True)\n        client.save_home({\"global.conf\": \"core.package_id:default_unknown_mode=full_version_mode\"})\n        client.save({\"conanfile.py\": GenConanfile()})\n        client.run(\"create . --name=liba --version=1.0\")\n        client.run(\"create . --name=liba --version=2.0\")\n        client.save({\"conanfile.py\": GenConanfile().with_require(\"liba/1.0\")\n                                                   .with_package_id(\"self.info.clear()\")})\n        client.run(\"create . --name=libb --version=1.0\")\n        client.save({\"conanfile.py\": GenConanfile().with_require(\"libb/1.0\")})\n        client.run(\"create . --name=libc --version=1.0\")\n        client.save({\"conanfile.py\": GenConanfile().with_require(\"libc/1.0\")\n                                                   .with_require(\"liba/1.0\")})\n        client.run(\"create . --name=libd --version=1.0\")\n        client.save({\"conanfile.py\": GenConanfile().with_require(\"libc/1.0\")\n                                                   .with_requirement(\"liba/2.0\", force=True)})\n        # USE THE NEW FIXED PACKAGE_ID\n        client.run(\"create . --name=libd --version=1.0\", assert_error=True)\n        client.assert_listed_binary({\"liba/2.0\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\", \"Cache\"),\n                                     \"libb/1.0\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\", \"Cache\"),\n                                     \"libc/1.0\": (\"2d7000cf800f37e01880897faf74a366a21bebdc\", \"Missing\"),\n                                     })\n"
  },
  {
    "path": "test/integration/package_id/transitive_options_affect_id_test.py",
    "content": "import textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestTransitiveOptionsAffectPackageID:\n\n    def test_basic(self):\n        client = TestClient()\n        conanfile = GenConanfile(\"pkg\", \"0.1\").with_option(\"noaffect\", [1, 2])\\\n                                              .with_option(\"affect\", [True, False])\\\n                                              .with_package_type(\"static-library\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . -o pkg*:noaffect=1 -o pkg*:affect=False\")\n        client.assert_listed_binary({\"pkg\": (\"7ff068ae587920b4f40b0dd81e891808c419f78c\", \"Build\")})\n\n        client.run(\"create . -o pkg*:noaffect=2 -o pkg*:affect=False\")\n        client.assert_listed_binary({\"pkg\": (\"66de80286b3d7ae1d5c05a9b795d6a6e622a778e\", \"Build\")})\n\n        client.run(\"create . -o pkg*:noaffect=1 -o pkg*:affect=True\")\n        client.assert_listed_binary({\"pkg\": (\"8e0cdf1d5b1c1c557b6f4b4ec01a4383b8f50dc3\", \"Build\")})\n\n        client.run(\"create . -o pkg*:noaffect=2 -o pkg*:affect=True\")\n        client.assert_listed_binary({\"pkg\": (\"4a18825b7c66155f03b27a1963e42ab3a836fd28\", \"Build\")})\n\n        app = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                name = \"app\"\n                version = \"0.1\"\n                package_type = \"application\"\n                requires = \"pkg/0.1\"\n                def package_id(self):\n                    if self.dependencies[\"pkg\"].package_type == \"static-library\":\n                        self.output.info(\"EMBED MODE!!\")\n                        self.info.requires[\"pkg\"].package_id = None\n                        self.info.options[\"pkg/*\"].affect = self.dependencies[\"pkg\"].options.affect\n            \"\"\")\n        client.save({\"conanfile.py\": app})\n        client.run(\"create . -o pkg*:noaffect=1 -o pkg*:affect=False\")\n        assert \"EMBED MODE!!\" in client.out\n        common_pkg_id = \"2060adfe3cc9040e5ee7e54c783d752f9ca1ba43\"  # Should be the same!\n        client.assert_listed_binary({\"app\": (common_pkg_id, \"Build\")})\n        client.run(\"create . -o pkg*:noaffect=2 -o pkg*:affect=False\")\n        assert \"EMBED MODE!!\" in client.out\n        client.assert_listed_binary({\"app\": (common_pkg_id, \"Build\")})\n\n        client.run(\"create . -o pkg*:noaffect=1 -o pkg*:affect=True\")\n        assert \"EMBED MODE!!\" in client.out\n        different_pkg_id = \"acfad205713f0d2fce61e7927d059635c0abbfff\"  # Should be the same!\n        client.assert_listed_binary({\"app\": (different_pkg_id, \"Build\")})\n        client.run(\"create . -o pkg*:noaffect=2 -o pkg*:affect=True\")\n        assert \"EMBED MODE!!\" in client.out\n        client.assert_listed_binary({\"app\": (different_pkg_id, \"Build\")})\n\n    def test_transitive_shared(self):\n        # https://github.com/conan-io/conan/issues/18900\n        c = TestClient()\n\n        lib1 = GenConanfile(\"lib1\", \"0.1\").with_shared_option(True)\n        lib2 = (GenConanfile(\"lib2\", \"0.1\").with_shared_option(True)\n                .with_requirement(\"lib1/0.1\", transitive_libs=True))\n        lib3 = (GenConanfile(\"lib3\", \"0.1\").with_shared_option(True)\n                .with_requirement(\"lib2/0.1\"))\n        lib4 = (GenConanfile(\"lib4\", \"0.1\").with_shared_option(True)\n                .with_requirement(\"lib3/0.1\"))\n        c.save({\"lib1/conanfile.py\": lib1,\n                \"lib2/conanfile.py\": lib2,\n                \"lib3/conanfile.py\": lib3,\n                \"lib4/conanfile.py\": lib4})\n        c.run(\"create lib1\")\n        c.run(\"create lib2\")\n        c.run(\"create lib3\")\n        c.run(\"create lib4\")\n\n        c.run(\"install --requires=lib4/0.1 -o lib1/*:shared=False --build=missing\")\n        c.assert_listed_binary({\"lib1/0.1\": (\"55c609fe8808aa5308134cb5989d23d3caffccf2\", \"Build\"),\n                                \"lib2/0.1\": (\"76844632e497abea8503d65ffd8324460dc70745\", \"Build\"),\n                                \"lib3/0.1\": (\"7b10301e532fc0269d6ac70470aee5780f0836cd\", \"Build\"),\n                                \"lib4/0.1\": (\"635372f179ad582c713637e361a7cd7ac7cd1d09\", \"Cache\"),\n                                })\n\n        lib3 = (GenConanfile(\"lib3\", \"0.1\").with_shared_option(True)\n                .with_requirement(\"lib2/0.1\", transitive_libs=True))\n        c.save({\"lib3/conanfile.py\": lib3})\n        c.run(\"remove * -c\")\n        c.run(\"create lib1\")\n        c.run(\"create lib2\")\n        c.run(\"create lib3\")\n        c.run(\"create lib4\")\n        c.run(\"install --requires=lib4/0.1 -o lib1/*:shared=False --build=missing\")\n        c.assert_listed_binary({\"lib1/0.1\": (\"55c609fe8808aa5308134cb5989d23d3caffccf2\", \"Build\"),\n                                \"lib2/0.1\": (\"76844632e497abea8503d65ffd8324460dc70745\", \"Build\"),\n                                \"lib3/0.1\": (\"7b10301e532fc0269d6ac70470aee5780f0836cd\", \"Build\"),\n                                \"lib4/0.1\": (\"dd8f5355b399fd7d96c883ddd39b992ae968cb14\", \"Build\"),\n                                })\n\n\nclass TestPackageIDABIOptions:\n    \"\"\"\n    These tests use the ``shared=True/False`` options for a proxy of the real issue\n    reported in https://github.com/conan-io/conan/issues/19108\n\n    The issue appears in MSVC when headers define\n\n    define FOO_EXPORT __declspec(dllimport)\n\n    Then, a static library will be a different artifact if it links against a static library\n    or a shared library. This isn't a very common issue because of 2 reasons:\n    - The most general linkage method are either all static or all shared, it is not that frequent\n      to have static libraries linking shared libraries\n    - Many third parties and open source libraries declare and use the __declspec(dllexport),\n      which is necessary for correctly exporting the symbols in MSVC. But the dllimport is not\n      that necessary and mostly a linking optimization, so not that frequent\n    \"\"\"\n    def test_package_id_abi_options(self):\n        c = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                options = {\"shared\": [True, False]}\n                default_options = {\"shared\": False}\n                package_id_abi_options = [\"shared\"]\n            \"\"\")\n        app = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                name = \"app\"\n                version = \"0.1\"\n                package_type = \"static-library\"\n                requires = \"pkg/0.1\"\n            \"\"\")\n        c.save({\"pkg/conanfile.py\": conanfile,\n                \"app/conanfile.py\": app})\n        c.run(\"create pkg\")\n        c.run(\"create pkg -o *:shared=True\")\n\n        c.run(\"create app\")\n        c.assert_listed_binary({\"app\": (\"e822341e143eb3bba372e24b7cd908c8f91dc24e\", \"Build\")})\n        c.run(\"list app/0.1:e822341e143eb3bba372e24b7cd908c8f91dc24e\")\n        assert \"pkg/*:shared: False\" in c.out\n\n        c.run(\"create app -o *:shared=True\")\n        c.assert_listed_binary({\"app\": (\"8c15f2b19bd994dcd5b44780eda3f03bde74c217\", \"Build\")})\n        c.run(\"list app/0.1:8c15f2b19bd994dcd5b44780eda3f03bde74c217\")\n        assert \"pkg/*:shared: True\" in c.out\n\n    def test_package_id_abi_options_conditional(self):\n        c = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                options = {\"shared\": [True, False]}\n                default_options = {\"shared\": False}\n                settings = \"os\"\n\n                def configure(self):\n                    if self.settings.os == \"Windows\":\n                        self.package_id_abi_options = [\"shared\"]\n            \"\"\")\n        app = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                name = \"app\"\n                version = \"0.1\"\n                package_type = \"static-library\"\n                requires = \"pkg/0.1\"\n            \"\"\")\n        c.save({\"pkg/conanfile.py\": conanfile,\n                \"app/conanfile.py\": app})\n        c.run(\"create pkg -s os=Linux\")\n        c.run(\"create pkg -s os=Linux -o *:shared=True\")\n        c.run(\"create pkg -s os=Windows\")\n        c.run(\"create pkg -s os=Windows -o *:shared=True\")\n\n        c.run(\"create app -s os=Linux\")\n        c.assert_listed_binary({\"app\": (\"e250b55435052b5e55b151d0b03900c73d262473\", \"Build\")})\n        c.run(\"list app/0.1:e250b55435052b5e55b151d0b03900c73d262473\")\n        assert \"pkg/*:shared: False\" not in c.out\n\n        c.run(\"create app -o *:shared=True -s os=Linux --build=missing:&\")\n        c.assert_listed_binary({\"app\": (\"e250b55435052b5e55b151d0b03900c73d262473\", \"Cache\")})\n\n        c.run(\"create app -s os=Windows\")\n        c.assert_listed_binary({\"app\": (\"e822341e143eb3bba372e24b7cd908c8f91dc24e\", \"Build\")})\n        c.run(\"list app/0.1:e822341e143eb3bba372e24b7cd908c8f91dc24e\")\n        assert \"pkg/*:shared: False\" in c.out\n\n        c.run(\"create app -o *:shared=True -s os=Windows --build=missing:&\")\n        c.assert_listed_binary({\"app\": (\"8c15f2b19bd994dcd5b44780eda3f03bde74c217\", \"Build\")})\n        c.run(\"list app/0.1:8c15f2b19bd994dcd5b44780eda3f03bde74c217\")\n        assert \"pkg/*:shared: True\" in c.out\n\n    def test_package_id_abi_options_transitive(self):\n        c = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                options = {\"shared\": [True, False]}\n                default_options = {\"shared\": False}\n                package_id_abi_options = [\"shared\"]\n            \"\"\")\n        middle = (GenConanfile(\"middle\", \"0.1\").with_requires(\"pkg/0.1\")\n                                               .with_package_type(\"shared-library\"))\n        app = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                name = \"app\"\n                version = \"0.1\"\n                package_type = \"application\"\n                requires = \"middle/0.1\"\n            \"\"\")\n        c.save({\"pkg/conanfile.py\": conanfile,\n                \"middle/conanfile.py\": middle,\n                \"app/conanfile.py\": app})\n        c.run(\"create pkg\")\n        c.run(\"create pkg -o *:shared=True\")\n        c.run(\"create middle\")\n        c.run(\"create middle -o *:shared=True\")\n\n        c.run(\"create app\")\n        c.assert_listed_binary({\"app\": (\"6da48adc0fa03ddc8b74de14b3fd5513a3688a52\", \"Build\")})\n        # binary not affected, because headers not propagated!\n        c.run(\"list app/0.1:6da48adc0fa03ddc8b74de14b3fd5513a3688a52\")\n        assert \"pkg/*:shared: False\" not in c.out\n\n        c.run(\"create app -o *:shared=True\")\n        # Still affected by \"middle\" full package-id, that is static\n        c.assert_listed_binary({\"app\": (\"6da48adc0fa03ddc8b74de14b3fd5513a3688a52\", \"Build\")})\n        c.run(\"list app/0.1:6da48adc0fa03ddc8b74de14b3fd5513a3688a52\")\n        assert \"pkg/*:shared: False\" not in c.out\n\n        # But if the header is propagated\n        middle = (GenConanfile(\"middle\", \"0.1\").with_requirement(\"pkg/0.1\", transitive_headers=True)\n                  .with_package_type(\"shared-library\"))\n        c.save({\"middle/conanfile.py\": middle})\n        c.run(\"create middle\")\n        c.run(\"create middle -o *:shared=True\")\n\n        c.run(\"create app\")\n        c.assert_listed_binary({\"app\": (\"ae20c28d303d1c561f95683add6638d6155c2bd9\", \"Build\")})\n        c.run(\"list app/0.1:ae20c28d303d1c561f95683add6638d6155c2bd9\")\n        assert \"pkg/*:shared: False\" in c.out\n\n        c.run(\"create app -o *:shared=True\")\n        # Still affected by \"middle\" full package-id, that is static\n        c.assert_listed_binary({\"app\": (\"321ad086fc1bbb3c2cf7f3e4d8d69c6d2096196d\", \"Build\")})\n        c.run(\"list app/0.1:321ad086fc1bbb3c2cf7f3e4d8d69c6d2096196d\")\n        assert \"pkg/*:shared: True\" in c.out\n"
  },
  {
    "path": "test/integration/py_requires/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/py_requires/python_requires_test.py",
    "content": "import os\nimport textwrap\nimport time\n\nfrom conan.api.model import RecipeReference\nfrom conan.test.utils.tools import TestClient, GenConanfile\n\n\nclass TestPyRequiresExtend:\n\n    @staticmethod\n    def _define_base(client):\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class MyConanfileBase(ConanFile):\n                def source(self):\n                    self.output.info(\"My cool source!\")\n                def build(self):\n                    self.output.info(\"My cool build!\")\n                def package(self):\n                    self.output.info(\"My cool package!\")\n                def package_info(self):\n                    self.output.info(\"My cool package_info!\")\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"export . --name=base --version=1.1 --user=user --channel=testing\")\n\n    def test_reuse(self):\n        client = TestClient(light=True, default_server_user=True)\n        self._define_base(client)\n        reuse = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class PkgTest(ConanFile):\n                python_requires = \"base/1.1@user/testing\"\n                python_requires_extend = \"base.MyConanfileBase\"\n            \"\"\")\n        client.save({\"conanfile.py\": reuse}, clean_first=True)\n        client.run(\"create . --name=pkg --version=0.1 --user=user --channel=testing\")\n        package_id = client.created_package_id(\"pkg/0.1@user/testing\")\n        assert \"pkg/0.1@user/testing: My cool source!\" in client.out\n        assert \"pkg/0.1@user/testing: My cool build!\" in client.out\n        assert \"pkg/0.1@user/testing: My cool package!\" in client.out\n        assert \"pkg/0.1@user/testing: My cool package_info!\" in client.out\n\n        client.run(\"upload * --confirm -r default\")\n        client.run(\"remove * -c\")\n        client.run(\"install --requires=pkg/0.1@user/testing\")\n        assert \"pkg/0.1@user/testing: My cool package_info!\" in client.out\n        client.run(\"remove * -c\")\n        client.run(\"download pkg/0.1@user/testing#latest:* -r default\")\n        assert f\"pkg/0.1@user/testing: Package installed {package_id}\" in client.out\n        # But it's broken with a single download\n        client.run(\"install --requires=pkg/0.1@user/testing -nr\", assert_error=True)\n        assert \"Cannot resolve python_requires 'base/1.1@user/testing'\" in client.out\n        # If pyrequires are expected, then first graph info -f=json and then get recipes from pkglist\n        client.run(\"remove * -c\")\n        client.run(\"graph info --requires=pkg/0.1@user/testing -f=json\",\n                   redirect_stdout=\"graph_info.json\")\n        # We can even remove from the cache now (The pyrequires is already downloaded in above step)\n        client.run(\"remove * -c\")\n        client.run(\"list --graph=graph_info.json --graph-recipes=* -f=json\",\n                   redirect_stdout=\"pkglist.json\")\n        client.run(\"download --list=pkglist.json -r default\")\n        assert \"Downloading recipe 'base/1.1@user/testing\" in client.out\n        client.run(\"install --requires=pkg/0.1@user/testing -nr\")\n        assert \"pkg/0.1@user/testing: My cool package_info!\" in client.out\n\n    def test_reuse_super(self):\n        client = TestClient(light=True, default_server_user=True)\n        self._define_base(client)\n        reuse = textwrap.dedent(\"\"\"\n               from conan import ConanFile\n               class PkgTest(ConanFile):\n                   python_requires = \"base/1.1@user/testing\"\n                   python_requires_extend = \"base.MyConanfileBase\"\n\n                   def source(self):\n                       super().source()\n                       self.output.info(\"MY OWN SOURCE\")\n               \"\"\")\n        client.save({\"conanfile.py\": reuse}, clean_first=True)\n        client.run(\"source . --name=pkg --version=0.1\")\n        assert \"conanfile.py (pkg/0.1): My cool source!\" in client.out\n        assert \"conanfile.py (pkg/0.1): MY OWN SOURCE\" in client.out\n\n    def test_reuse_dot(self):\n        client = TestClient(light=True, default_server_user=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class MyConanfileBase(ConanFile):\n                def build(self):\n                    self.output.info(\"My cool build!\")\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"export . --name=my.base --version=1.1 --user=user --channel=testing\")\n        reuse = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class PkgTest(ConanFile):\n                python_requires = \"my.base/1.1@user/testing\"\n                python_requires_extend = \"my.base.MyConanfileBase\"\n            \"\"\")\n        client.save({\"conanfile.py\": reuse}, clean_first=True)\n        client.run(\"create . --name=pkg --version=0.1 --user=user --channel=testing\")\n        assert \"pkg/0.1@user/testing: My cool build!\" in client.out\n\n    def test_with_alias(self):\n        client = TestClient(light=True)\n        self._define_base(client)\n        client.alias(\"base/latest@user/testing\", \"base/1.1@user/testing\")\n\n        reuse = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class PkgTest(ConanFile):\n                name = \"pkg\"\n                version = \"1.0\"\n                python_requires = \"base/latest@user/testing\"\n            \"\"\")\n        client.save({\"conanfile.py\": reuse}, clean_first=True)\n        client.run(\"install .\", assert_error=True)\n        assert \"python-requires 'alias' are not supported in Conan 2.0\" in client.out\n        client.run(\"create .\", assert_error=True)\n        assert \"python-requires 'alias' are not supported in Conan 2.0\" in client.out\n\n    def test_reuse_version_ranges(self):\n        client = TestClient(light=True)\n        self._define_base(client)\n\n        reuse = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class PkgTest(ConanFile):\n                python_requires = \"base/[>1.0 <1.2]@user/testing\"\n                python_requires_extend = \"base.MyConanfileBase\"\n            \"\"\")\n\n        client.save({\"conanfile.py\": reuse}, clean_first=True)\n        client.run(\"create . --name=pkg --version=0.1 --user=user --channel=testing\")\n        client.assert_listed_require({\"base/1.1@user/testing\": \"Cache\"}, python=True)\n        assert \"pkg/0.1@user/testing: My cool source!\" in client.out\n        assert \"pkg/0.1@user/testing: My cool build!\" in client.out\n        assert \"pkg/0.1@user/testing: My cool package!\" in client.out\n        assert \"pkg/0.1@user/testing: My cool package_info!\" in client.out\n\n    def test_multiple_reuse(self):\n        client = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class SourceBuild(ConanFile):\n                def source(self):\n                    self.output.info(\"My cool source!\")\n                def build(self):\n                    self.output.info(\"My cool build!\")\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"export . --name=sourcebuild --version=1.0 --user=user --channel=channel\")\n\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class PackageInfo(ConanFile):\n                def package(self):\n                    self.output.info(\"My cool package!\")\n                def package_info(self):\n                    self.output.info(\"My cool package_info!\")\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"export . --name=packageinfo --version=1.0 --user=user --channel=channel\")\n\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class MyConanfileBase(ConanFile):\n                python_requires = \"sourcebuild/1.0@user/channel\", \"packageinfo/1.0@user/channel\"\n                python_requires_extend = \"sourcebuild.SourceBuild\", \"packageinfo.PackageInfo\"\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --name=pkg --version=0.1 --user=user --channel=testing\")\n        assert \"pkg/0.1@user/testing: My cool source!\" in client.out\n        assert \"pkg/0.1@user/testing: My cool build!\" in client.out\n        assert \"pkg/0.1@user/testing: My cool package!\" in client.out\n        assert \"pkg/0.1@user/testing: My cool package_info!\" in client.out\n\n    @staticmethod\n    def test_transitive_access():\n        client = TestClient(light=True)\n        client.save({\"conanfile.py\": GenConanfile()})\n        client.run(\"export . --name=base --version=1.0 --user=user --channel=channel\")\n\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Helper(ConanFile):\n                python_requires = \"base/1.0@user/channel\"\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"export . --name=helper --version=1.0 --user=user --channel=channel\")\n\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                python_requires = \"helper/1.0@user/channel\"\n                def build(self):\n                    self.python_requires[\"base\"]\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --name=pkg --version=0.1 --user=user --channel=channel\")\n        assert \"pkg/0.1@user/channel: Created package\" in client.out\n\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                python_requires = \"helper/1.0@user/channel\"\n                python_requires_extend = \"base.HelloConan\"\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --name=pkg --version=0.1 --user=user --channel=channel\")\n        assert \"pkg/0.1@user/channel: Created package\" in client.out\n\n    def test_multiple_requires_error(self):\n        client = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            myvar = 123\n            def myfunct():\n                return 123\n            class Pkg(ConanFile):\n                pass\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"export . --name=pkg1 --version=1.0 --user=user --channel=channel\")\n\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            myvar = 234\n            def myfunct():\n                return 234\n            class Pkg(ConanFile):\n                pass\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"export . --name=pkg2 --version=1.0 --user=user --channel=channel\")\n\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class MyConanfileBase(ConanFile):\n                python_requires = \"pkg1/1.0@user/channel\", \"pkg2/1.0@user/channel\"\n                def build(self):\n                    self.output.info(\"PKG1 N: %s\" % self.python_requires[\"pkg1\"].conanfile.name)\\\n                               .info(\"PKG1 V: %s\" % self.python_requires[\"pkg1\"].conanfile.version)\\\n                               .info(\"PKG1 U: %s\" % self.python_requires[\"pkg1\"].conanfile.user)\\\n                               .info(\"PKG1 C: %s\" % self.python_requires[\"pkg1\"].conanfile.channel)\\\n                               .info(\"PKG1 : %s\" % self.python_requires[\"pkg1\"].module.myvar)\\\n                               .info(\"PKG2 : %s\" % self.python_requires[\"pkg2\"].module.myvar)\\\n                               .info(\"PKG1F : %s\" % self.python_requires[\"pkg1\"].module.myfunct())\\\n                               .info(\"PKG2F : %s\" % self.python_requires[\"pkg2\"].module.myfunct())\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --name=consumer --version=0.1 --user=user --channel=testing\")\n        assert \"consumer/0.1@user/testing: PKG1 N: pkg1\" in client.out\n        assert \"consumer/0.1@user/testing: PKG1 V: 1.0\" in client.out\n        assert \"consumer/0.1@user/testing: PKG1 U: user\" in client.out\n        assert \"consumer/0.1@user/testing: PKG1 C: channel\" in client.out\n        assert \"consumer/0.1@user/testing: PKG1 : 123\" in client.out\n        assert \"consumer/0.1@user/testing: PKG2 : 234\" in client.out\n        assert \"consumer/0.1@user/testing: PKG1F : 123\" in client.out\n        assert \"consumer/0.1@user/testing: PKG2F : 234\" in client.out\n\n    def test_local_import(self):\n        client = TestClient(light=True, default_server_user=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            import mydata\n            class MyConanfileBase(ConanFile):\n                exports = \"*.py\"\n                def source(self):\n                    self.output.info(mydata.src)\n                def build(self):\n                    self.output.info(mydata.build)\n                def package(self):\n                    self.output.info(mydata.pkg)\n                def package_info(self):\n                    self.output.info(mydata.info)\n            \"\"\")\n        mydata = textwrap.dedent(\"\"\"\n            src = \"My cool source!\"\n            build = \"My cool build!\"\n            pkg = \"My cool package!\"\n            info = \"My cool package_info!\"\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile,\n                     \"mydata.py\": mydata})\n        client.run(\"export . --name=base --version=1.1 --user=user --channel=testing\")\n        reuse = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class PkgTest(ConanFile):\n                python_requires = \"base/1.1@user/testing\"\n                python_requires_extend = \"base.MyConanfileBase\"\n            \"\"\")\n\n        client.save({\"conanfile.py\": reuse}, clean_first=True)\n        client.run(\"create . --name=pkg --version=0.1 --user=user --channel=testing\")\n        package_id = client.created_package_id(\"pkg/0.1@user/testing\")\n        assert \"pkg/0.1@user/testing: My cool source!\" in client.out\n        assert \"pkg/0.1@user/testing: My cool build!\" in client.out\n        assert \"pkg/0.1@user/testing: My cool package!\" in client.out\n        assert \"pkg/0.1@user/testing: My cool package_info!\" in client.out\n\n        client.run(\"upload * --confirm -r default\")\n        client.run(\"remove * -c\")\n        client.run(\"install --requires=pkg/0.1@user/testing\")\n        assert \"pkg/0.1@user/testing: My cool package_info!\" in client.out\n        client.run(\"remove * -c\")\n        client.run(\"download pkg/0.1@user/testing#*:* -r default\")\n        assert f\"pkg/0.1@user/testing: Package installed {package_id}\" in client.out\n\n    def test_reuse_class_members(self):\n        client = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class MyConanfileBase(ConanFile):\n                license = \"MyLicense\"\n                author = \"author@company.com\"\n                exports = \"*.txt\"\n                exports_sources = \"*.h\"\n                generators = \"CMakeToolchain\"\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile,\n                     \"header.h\": \"some content\"})\n        client.run(\"export . --name=base --version=1.1 --user=user --channel=testing\")\n\n        reuse = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import load\n            import os\n            class PkgTest(ConanFile):\n                python_requires = \"base/1.1@user/testing\"\n                python_requires_extend = \"base.MyConanfileBase\"\n                def build(self):\n                    self.output.info(\"Exports sources! %s\" % self.exports_sources)\n                    self.output.info(\"HEADER CONTENT!: %s\" % load(self, \"header.h\"))\n                    self.output.info(\"License! %s\" % self.license)\n                    self.output.info(\"Author! %s\" % self.author)\n                    assert os.path.exists(\"conan_toolchain.cmake\")\n            \"\"\")\n        client.save({\"conanfile.py\": reuse,\n                     \"header.h\": \"pkg new header contents\",\n                     \"other.txt\": \"text\"})\n        client.run(\"create . --name=pkg --version=0.1 --user=user --channel=testing\")\n        assert \"pkg/0.1@user/testing: Exports sources! *.h\" in client.out\n        assert \"pkg/0.1@user/testing: Copied 1 '.txt' file: other.txt\" in client.out\n        assert \"pkg/0.1@user/testing: Copied 1 '.h' file: header.h\" in client.out\n        assert \"pkg/0.1@user/testing: License! MyLicense\" in client.out\n        assert \"pkg/0.1@user/testing: Author! author@company.com\" in client.out\n        assert \"pkg/0.1@user/testing: HEADER CONTENT!: pkg new header contents\" in client.out\n        ref = RecipeReference.loads(\"pkg/0.1@user/testing\")\n        assert os.path.exists(os.path.join(client.get_latest_ref_layout(ref).export(), \"other.txt\"))\n\n    def test_reuse_system_requirements(self):\n        # https://github.com/conan-io/conan/issues/7718\n        client = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n           from conan import ConanFile\n           class MyConanfileBase(ConanFile):\n               def system_requirements(self):\n                   self.output.info(\"My system_requirements %s being called!\" % self.name)\n           \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"export . --name=base --version=1.1 --user=user --channel=testing\")\n        reuse = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class PkgTest(ConanFile):\n                python_requires = \"base/1.1@user/testing\"\n                python_requires_extend = \"base.MyConanfileBase\"\n            \"\"\")\n        client.save({\"conanfile.py\": reuse}, clean_first=True)\n        client.run(\"create . --name=pkg --version=0.1 --user=user --channel=testing\")\n        assert \"pkg/0.1@user/testing: My system_requirements pkg being called!\" in client.out\n\n    def test_reuse_requirements(self):\n        client = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n                   from conan import ConanFile\n                   class MyConanfileBase(ConanFile):\n                       def requirements(self):\n                           self.output.info(\"My requirements %s being called!\" % self.name)\n                           self.requires(\"foo/1.0\")\n                   \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"export . --name=base --version=1.1 --user=user --channel=testing\")\n        client.save({\"conanfile.py\": GenConanfile(\"foo\", \"1.0\")})\n        client.run(\"create .\")\n        reuse = textwrap.dedent(\"\"\"\n                    from conan import ConanFile\n                    class PkgTest(ConanFile):\n                        python_requires = \"base/1.1@user/testing\"\n                        python_requires_extend = \"base.MyConanfileBase\"\n                    \"\"\")\n        client.save({\"conanfile.py\": reuse}, clean_first=True)\n        client.run(\"create . --name=pkg --version=0.1 --user=user --channel=testing\")\n        assert \"pkg/0.1@user/testing: My requirements pkg being called!\" in client.out\n        client.assert_listed_require({\"foo/1.0#f5288356d9cc303f25cb05bccbad8fbb\": \"Cache\"})\n\n    def test_overwrite_class_members(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class MyConanfileBase(ConanFile):\n                license = \"MyLicense\"\n                author = \"author@company.com\"\n                settings = \"os\", # tuple!\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"export . --name=base --version=1.1 --user=user --channel=testing\")\n\n        reuse = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class PkgTest(ConanFile):\n                license = \"MIT\"\n                author = \"frodo\"\n                settings = \"arch\", # tuple!\n                python_requires = \"base/1.1@user/testing\"\n                python_requires_extend = \"base.MyConanfileBase\"\n\n                def init(self):\n                    base = self.python_requires[\"base\"].module.MyConanfileBase\n                    self.settings = base.settings + self.settings\n                    self.license = base.license\n\n                def build(self):\n                    self.output.info(\"License! %s\" % self.license)\n                    self.output.info(\"Author! %s\" % self.author)\n                    self.output.info(\"os: %s arch: %s\" % (self.settings.get_safe(\"os\"),\n                                                          self.settings.arch))\n            \"\"\")\n        client.save({\"conanfile.py\": reuse})\n        client.run(\"create . --name=pkg --version=0.1 -s os=Windows -s arch=armv7\")\n        assert \"pkg/0.1: License! MyLicense\" in client.out\n        assert \"pkg/0.1: Author! frodo\" in client.out\n        assert \"pkg/0.1: os: Windows arch: armv7\" in client.out\n\n    def test_basic_option_inherit(self):\n        client = TestClient()\n        base = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class MyBase:\n                settings = \"os\", \"build_type\", \"arch\"\n                options = {\"base_option\": [1, 2, 3]}\n                default_options = {\"base_option\": 2}\n\n            class BaseConanFile(ConanFile):\n                pass\n            \"\"\")\n        client.save({\"conanfile.py\": base})\n        client.run(\"export . --name=base --version=1.0\")\n        derived = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class DerivedConan(ConanFile):\n                settings = \"os\", \"build_type\", \"arch\"\n\n                python_requires = \"base/1.0\"\n                python_requires_extend = 'base.MyBase'\n\n                def generate(self):\n                    self.output.info(f\"MYOPTION: {self.options.base_option}!!!!\")\n                \"\"\")\n        client.save({\"conanfile.py\": derived})\n        client.run(\"install .\")\n        assert \"conanfile.py: MYOPTION: 2!!!!\" in client.out\n\n    def test_failure_init_method(self):\n        client = TestClient()\n        base = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class MyBase(object):\n                settings = \"os\", \"build_type\", \"arch\"\n                options = {\"base_option\": [True, False]}\n                default_options = {\"base_option\": False}\n\n            class BaseConanFile(ConanFile):\n                pass\n            \"\"\")\n        client.save({\"conanfile.py\": base})\n        client.run(\"export . --name=base --version=1.0\")\n        derived = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class DerivedConan(ConanFile):\n                settings = \"os\", \"build_type\", \"arch\"\n\n                python_requires = \"base/1.0\"\n                python_requires_extend = 'base.MyBase'\n\n                options = {\"derived_option\": [True, False]}\n                default_options = {\"derived_option\": False}\n\n                def init(self):\n                    base = self.python_requires['base'].module.MyBase\n                    self.options.update(base.options, base.default_options)\n                \"\"\")\n        client.save({\"conanfile.py\": derived})\n        client.run(\"create . --name=pkg --version=0.1 -o base_option=True -o derived_option=True\")\n        assert \"pkg/0.1: Created package\" in client.out\n        client.run(\"create . --name=pkg --version=0.1 -o whatever=True\", assert_error=True)\n        assert \"Possible options are ['derived_option', 'base_option']\" in client.out\n\n    def test_transitive_imports_conflicts(self):\n        # https://github.com/conan-io/conan/issues/3874\n        client = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            import myhelper\n            class SourceBuild(ConanFile):\n                exports = \"*.py\"\n            \"\"\")\n        helper = textwrap.dedent(\"\"\"\n            def myhelp(output):\n                output.info(\"MyHelperOutput!\")\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile,\n                     \"myhelper.py\": helper})\n        client.run(\"export . --name=base1 --version=1.0 --user=user --channel=channel\")\n        client.save({\"myhelper.py\": helper.replace(\"MyHelperOutput!\", \"MyOtherHelperOutput!\")})\n        client.run(\"export . --name=base2 --version=1.0 --user=user --channel=channel\")\n\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class MyConanfileBase(ConanFile):\n                python_requires = \"base2/1.0@user/channel\", \"base1/1.0@user/channel\"\n                def build(self):\n                    self.python_requires[\"base1\"].module.myhelper.myhelp(self.output)\n                    self.python_requires[\"base2\"].module.myhelper.myhelp(self.output)\n            \"\"\")\n        # This should work, even if there is a local \"myhelper.py\" file, which could be\n        # accidentaly imported (and it was, it was a bug)\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --name=pkg --version=0.1 --user=user --channel=testing\")\n        assert \"pkg/0.1@user/testing: MyHelperOutput!\" in client.out\n        assert \"pkg/0.1@user/testing: MyOtherHelperOutput!\" in client.out\n\n        # Now, the same, but with \"clean_first=True\", should keep working\n        client.save({\"conanfile.py\": conanfile}, clean_first=True)\n        client.run(\"create . --name=pkg --version=0.1 --user=user --channel=testing\")\n        assert \"pkg/0.1@user/testing: MyHelperOutput!\" in client.out\n        assert \"pkg/0.1@user/testing: MyOtherHelperOutput!\" in client.out\n\n    def test_update(self):\n        client = TestClient(light=True, default_server_user=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            somevar = 42\n            class MyConanfileBase(ConanFile):\n                pass\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"export . --name=base --version=1.1 --user=user --channel=testing\")\n        client.run(\"upload * --confirm -r default\")\n\n        client2 = TestClient(light=True, servers=client.servers, inputs=[\"user\", \"password\"])\n        reuse = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class PkgTest(ConanFile):\n                python_requires = \"base/1.1@user/testing\"\n                python_requires_extend = \"base.MyConanfileBase\"\n                def configure(self):\n                    self.output.info(\"PYTHON REQUIRE VAR %s\"\n                                     % self.python_requires[\"base\"].module.somevar)\n        \"\"\")\n\n        client2.save({\"conanfile.py\": reuse})\n        client2.run(\"install .\")\n        assert \"conanfile.py: PYTHON REQUIRE VAR 42\" in client2.out\n\n        client.save({\"conanfile.py\": conanfile.replace(\"42\", \"143\")})\n        time.sleep(1)  # guarantee time offset\n        client.run(\"export . --name=base --version=1.1 --user=user --channel=testing\")\n        client.run(\"upload * --confirm -r default\")\n\n        client2.run(\"install . --update\")\n        assert \"conanfile.py: PYTHON REQUIRE VAR 143\" in client2.out\n\n    def test_update_ranges(self):\n        # Same as the above, but using a version range, and no --update\n        # https://github.com/conan-io/conan/issues/4650#issuecomment-497464305\n        client = TestClient(light=True, default_server_user=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            somevar = 42\n            class MyConanfileBase(ConanFile):\n                pass\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"export . --name=base --version=1.1 --user=user --channel=testing\")\n        client.run(\"upload * --confirm -r default\")\n\n        client2 = TestClient(light=True, servers=client.servers, inputs=[\"user\", \"password\"])\n        reuse = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class PkgTest(ConanFile):\n                python_requires = \"base/[>1.0]@user/testing\"\n                python_requires_extend = \"base.MyConanfileBase\"\n                def configure(self):\n                    self.output.info(\"PYTHON REQUIRE VAR %s\"\n                                     % self.python_requires[\"base\"].module.somevar)\n        \"\"\")\n\n        client2.save({\"conanfile.py\": reuse})\n        client2.run(\"install .\")\n        assert \"conanfile.py: PYTHON REQUIRE VAR 42\" in client2.out\n\n        client.save({\"conanfile.py\": conanfile.replace(\"42\", \"143\")})\n        # Make sure to bump the version!\n        client.run(\"export . --name=base --version=1.2 --user=user --channel=testing\")\n        client.run(\"upload * --confirm -r default\")\n\n        client2.run(\"install . --update\")\n        assert \"conanfile.py: PYTHON REQUIRE VAR 143\" in client2.out\n\n    def test_duplicate_pyreq(self):\n        t = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class PyReq(ConanFile):\n                pass\n        \"\"\")\n        t.save({\"conanfile.py\": conanfile})\n        t.run(\"export . --name=pyreq --version=1.0 --user=user --channel=channel\")\n        t.run(\"export . --name=pyreq --version=2.0 --user=user --channel=channel\")\n\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Lib(ConanFile):\n                python_requires = \"pyreq/1.0@user/channel\", \"pyreq/2.0@user/channel\"\n        \"\"\")\n        t.save({\"conanfile.py\": conanfile})\n        t.run(\"create . --name=name --version=version --user=user --channel=channel\",\n              assert_error=True)\n        assert \"ERROR: Error loading conanfile\" in t.out\n        assert \"The python_require 'pyreq' already exists\" in t.out\n\n    def test_local_build(self):\n        client = TestClient(light=True)\n        client.save({\"conanfile.py\": \"var=42\\n\" + str(GenConanfile())})\n        client.run(\"export . --name=tool --version=0.1 --user=user --channel=channel\")\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class MyConanfileBase(ConanFile):\n                python_requires = \"tool/0.1@user/channel\"\n                def source(self):\n                    self.output.info(\"Pkg1 source: %s\" % self.python_requires[\"tool\"].module.var)\n                def build(self):\n                    self.output.info(\"Pkg1 build: %s\" % self.python_requires[\"tool\"].module.var)\n                def package(self):\n                    self.output.info(\"Pkg1 package: %s\" % self.python_requires[\"tool\"].module.var)\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"source .\")\n        assert \"conanfile.py: Pkg1 source: 42\" in client.out\n        client.run(\"install .\")\n        client.run(\"build .\")\n        assert \"conanfile.py: Pkg1 build: 42\" in client.out\n        client.run(\"export-pkg . --name=pkg1 --version=0.1 --user=user --channel=testing\")\n\n    def test_reuse_name_version(self):\n        client = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import load\n            import os\n\n            class Source(object):\n                def set_name(self):\n                    self.name = load(self, \"name.txt\")\n\n                def set_version(self):\n                    self.version = load(self, \"version.txt\")\n\n            class MyConanfileBase(ConanFile):\n                pass\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"export . --name=tool --version=0.1 --user=user --channel=channel\")\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class MyConanfileBase(ConanFile):\n                python_requires = \"tool/0.1@user/channel\"\n                python_requires_extend = \"tool.Source\"\n                def source(self):\n                    self.output.info(\"Pkg1 source: %s:%s\" % (self.name, self.version))\n                def build(self):\n                    self.output.info(\"Pkg1 build: %s:%s\" % (self.name, self.version))\n                def package(self):\n                    self.output.info(\"Pkg1 package: %s:%s\" % (self.name, self.version))\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile,\n                     \"name.txt\": \"mypkg\",\n                     \"version.txt\": \"myversion\"})\n        client.run(\"export .\")\n        assert \"mypkg/myversion: Exported\" in client.out\n        client.run(\"create .\")\n        assert \"mypkg/myversion: Pkg1 source: mypkg:myversion\" in client.out\n        assert \"mypkg/myversion: Pkg1 build: mypkg:myversion\" in client.out\n        assert \"mypkg/myversion: Pkg1 package: mypkg:myversion\" in client.out\n\n    def test_reuse_name_version_override(self):\n        client = TestClient(light=True)\n\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import load\n            import os\n\n            class Source(object):\n                def set_name(self):\n                    self.name = load(self, \"name.txt\")\n\n                def set_version(self):\n                    self.version = load(self, \"version.txt\")\n\n            class MyConanfileBase(ConanFile):\n                pass\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"export . --name=tool --version=0.1 --user=user --channel=channel\")\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class MyConanfileBase(ConanFile):\n                python_requires = \"tool/0.1@user/channel\"\n                python_requires_extend = \"tool.Source\"\n\n                def set_version(self):\n                    super().set_version()\n                    self.version = self.version + \"2\"\n\n                def source(self):\n                    self.output.info(\"Pkg1 source: %s:%s\" % (self.name, self.version))\n                def build(self):\n                    self.output.info(\"Pkg1 build: %s:%s\" % (self.name, self.version))\n                def package(self):\n                    self.output.info(\"Pkg1 package: %s:%s\" % (self.name, self.version))\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile,\n                     \"name.txt\": \"mypkg\",\n                     \"version.txt\": \"myversion\"})\n        client.run(\"export .\")\n        assert \"mypkg/myversion2: Exported\" in client.out\n        client.run(\"create .\")\n        assert \"mypkg/myversion2: Pkg1 source: mypkg:myversion2\" in client.out\n        assert \"mypkg/myversion2: Pkg1 build: mypkg:myversion2\" in client.out\n        assert \"mypkg/myversion2: Pkg1 package: mypkg:myversion2\" in client.out\n\n    def test_reuse_export_sources(self):\n        client = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class MyConanfileBase(ConanFile):\n                exports = \"*\"\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile,\n                     \"file.h\": \"myheader\",\n                     \"folder/other.h\": \"otherheader\"})\n        client.run(\"export . --name=tool --version=0.1 --user=user --channel=channel\")\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import load\n            import os\n            class MyConanfileBase(ConanFile):\n                python_requires = \"tool/0.1@user/channel\"\n                def source(self):\n                    sources = self.python_requires[\"tool\"].path\n                    file_h = os.path.join(sources, \"file.h\")\n                    other_h = os.path.join(sources, \"folder/other.h\")\n                    self.output.info(\"Source: tool header: %s\" % load(self, file_h))\n                    self.output.info(\"Source: tool other: %s\" % load(self, other_h))\n                def build(self):\n                    sources = self.python_requires[\"tool\"].path\n                    file_h = os.path.join(sources, \"file.h\")\n                    other_h = os.path.join(sources, \"folder/other.h\")\n                    self.output.info(\"Build: tool header: %s\" % load(self, file_h))\n                    self.output.info(\"Build: tool other: %s\" % load(self, other_h))\n                def package(self):\n                    sources = self.python_requires[\"tool\"].path\n                    file_h = os.path.join(sources, \"file.h\")\n                    other_h = os.path.join(sources, \"folder/other.h\")\n                    self.output.info(\"Package: tool header: %s\" % load(self, file_h))\n                    self.output.info(\"Package: tool other: %s\" % load(self, other_h))\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile,\n                     \"name.txt\": \"MyPkg\",\n                     \"version.txt\": \"MyVersion\"})\n        client.run(\"export . --name=pkg --version=1.0 --user=user --channel=channel\")\n        assert \"pkg/1.0@user/channel: Exported\" in client.out\n        client.run(\"create . --name=pkg --version=1.0 --user=user --channel=channel\")\n        assert \"pkg/1.0@user/channel: Source: tool header: myheader\" in client.out\n        assert \"pkg/1.0@user/channel: Source: tool other: otherheader\" in client.out\n        assert \"pkg/1.0@user/channel: Build: tool header: myheader\" in client.out\n        assert \"pkg/1.0@user/channel: Build: tool other: otherheader\" in client.out\n        assert \"pkg/1.0@user/channel: Package: tool header: myheader\" in client.out\n        assert \"pkg/1.0@user/channel: Package: tool other: otherheader\" in client.out\n\n        # The local flow\n        client.run(\"install .\")\n        client.run(\"source .\")\n        assert \"conanfile.py: Source: tool header: myheader\" in client.out\n        assert \"conanfile.py: Source: tool other: otherheader\" in client.out\n        client.run(\"build .\")\n        assert \"conanfile.py: Build: tool header: myheader\" in client.out\n        assert \"conanfile.py: Build: tool other: otherheader\" in client.out\n\n    def test_reuse_editable_exports(self):\n        client = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class MyConanfileBase(ConanFile):\n                exports = \"*\"\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile,\n                     \"file.h\": \"myheader\",\n                     \"folder/other.h\": \"otherheader\"})\n        client.run(\"editable add . --name=tool --version=0.1\")\n\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import load\n            import os\n            class MyConanfileBase(ConanFile):\n                python_requires = \"tool/0.1\"\n                def source(self):\n                    sources = self.python_requires[\"tool\"].path\n                    file_h = os.path.join(sources, \"file.h\")\n                    other_h = os.path.join(sources, \"folder/other.h\")\n                    self.output.info(\"Source: tool header: %s\" % load(self, file_h))\n                    self.output.info(\"Source: tool other: %s\" % load(self, other_h))\n                def build(self):\n                    sources = self.python_requires[\"tool\"].path\n                    file_h = os.path.join(sources, \"file.h\")\n                    other_h = os.path.join(sources, \"folder/other.h\")\n                    self.output.info(\"Build: tool header: %s\" % load(self, file_h))\n                    self.output.info(\"Build: tool other: %s\" % load(self, other_h))\n            \"\"\")\n\n        client2 = TestClient(light=True, cache_folder=client.cache_folder)\n        client2.save({\"conanfile.py\": conanfile,\n                      \"name.txt\": \"MyPkg\",\n                      \"version.txt\": \"MyVersion\"})\n\n        # The local flow\n        client2.run(\"install .\")\n        client2.run(\"source .\")\n        assert \"conanfile.py: Source: tool header: myheader\" in client2.out\n        assert \"conanfile.py: Source: tool other: otherheader\" in client2.out\n        client2.run(\"build .\")\n        assert \"conanfile.py: Build: tool header: myheader\" in client2.out\n        assert \"conanfile.py: Build: tool other: otherheader\" in client2.out\n\n    def test_build_id(self):\n        client = TestClient(light=True, default_server_user=True)\n        self._define_base(client)\n        reuse = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class PkgTest(ConanFile):\n                python_requires = \"base/1.1@user/testing\"\n                python_requires_extend = \"base.MyConanfileBase\"\n                def build_id(self):\n                    pass\n            \"\"\")\n        client.save({\"conanfile.py\": reuse}, clean_first=True)\n        client.run(\"create . --name=pkg --version=0.1 --user=user --channel=testing\")\n        assert \"pkg/0.1@user/testing: My cool source!\" in client.out\n        assert \"pkg/0.1@user/testing: My cool build!\" in client.out\n        assert \"pkg/0.1@user/testing: My cool package!\" in client.out\n        assert \"pkg/0.1@user/testing: My cool package_info!\" in client.out\n\n    def test_options_errors(self):\n        c = TestClient(light=True)\n        base = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class BaseConan:\n                options = {\"base\": [True, False]}\n                default_options = {\"base\": True}\n\n            class PyReq(ConanFile):\n                name = \"base\"\n                version = \"1.0.0\"\n                package_type = \"python-require\"\n                \"\"\")\n        derived = textwrap.dedent(\"\"\"\n            import conan\n\n            class DerivedConan(conan.ConanFile):\n                name = \"derived\"\n                python_requires = \"base/1.0.0\"\n                python_requires_extend = \"base.BaseConan\"\n                options = {\"derived\": [True, False]}\n                default_options = {\"derived\": False}\n\n                def init(self):\n                    base = self.python_requires[\"base\"].module.BaseConan\n                    self.options.update(base.options, base.default_options)\n\n                def generate(self):\n                    self.output.info(f\"OptionBASE: {self.options.base}\")\n                    self.output.info(f\"OptionDERIVED: {self.options.derived}\")\n            \"\"\")\n        c.save({\"base/conanfile.py\": base,\n                \"derived/conanfile.py\": derived})\n        c.run(\"create base\")\n        c.run(\"install derived\")\n        assert \"OptionBASE: True\" in c.out\n        assert \"OptionDERIVED: False\" in c.out\n\n    def test_options_default_update(self):\n        c = TestClient(light=True)\n        base = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class BaseConan:\n                options = {\"base\": [True, False]}\n                default_options = {\"base\": True}\n\n            class PyReq(ConanFile):\n                name = \"base\"\n                version = \"1.0.0\"\n                package_type = \"python-require\"\n                \"\"\")\n        derived = textwrap.dedent(\"\"\"\n            import conan\n\n            class DerivedConan(conan.ConanFile):\n                name = \"derived\"\n                python_requires = \"base/1.0.0\"\n                python_requires_extend = \"base.BaseConan\"\n                options = {\"derived\": [True, False]}\n                default_options = {\"derived\": False}\n\n                def init(self):\n                    base = self.python_requires[\"base\"].module.BaseConan\n                    self.options.update(base.options, base.default_options)\n                    self.options.base = False\n\n                def generate(self):\n                    self.output.info(f\"OptionBASE: {self.options.base}\")\n                    self.output.info(f\"OptionDERIVED: {self.options.derived}\")\n            \"\"\")\n        c.save({\"base/conanfile.py\": base,\n                \"derived/conanfile.py\": derived})\n        c.run(\"create base\")\n        c.run(\"install derived\")\n        assert \"OptionBASE: False\" in c.out\n        assert \"OptionDERIVED: False\" in c.out\n\n        c.run(\"install derived -o=&:base=True\")\n        assert \"OptionBASE: True\" in c.out\n        assert \"OptionDERIVED: False\" in c.out\n\n\ndef test_transitive_python_requires():\n    # https://github.com/conan-io/conan/issues/8546\n    client = TestClient(light=True)\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        myvar = 123\n        def myfunct():\n            return 234\n        class SharedFunction(ConanFile):\n            name = \"shared-function\"\n            version = \"1.0\"\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"export . --user=user --channel=channel\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class BaseClass(ConanFile):\n            name = \"base-class\"\n            version = \"1.0\"\n            python_requires = \"shared-function/1.0@user/channel\"\n            def build(self):\n                pyreqs = self.python_requires\n                v = pyreqs[\"shared-function\"].module.myvar  # v will be 123\n                f = pyreqs[\"shared-function\"].module.myfunct()  # f will be 234\n                self.output.info(\"%s, %s\" % (v, f))\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"export . --user=user --channel=channel\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Consumer(ConanFile):\n            name = \"consumer\"\n            version = \"1.0\"\n            python_requires = \"base-class/1.0@user/channel\"\n            python_requires_extend = \"base-class.BaseClass\"\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --user=user --channel=channel\")\n    assert \"consumer/1.0@user/channel: Calling build()\\nconsumer/1.0@user/channel: 123, 234\" in \\\n           client.out\n\n\ndef test_transitive_diamond_python_requires():\n    client = TestClient(light=True)\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        myvar = 123\n        def myfunct():\n            return 234\n        class SharedFunction(ConanFile):\n            name = \"shared-function\"\n            version = \"1.0\"\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"export . --user=user --channel=channel\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        myvar = 222\n        def myfunct():\n            return 2222\n        class SharedFunction2(ConanFile):\n            name = \"shared-function2\"\n            version = \"1.0\"\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"export . --user=user --channel=channel\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class BaseClass(ConanFile):\n            name = \"base-class\"\n            version = \"1.0\"\n            python_requires = \"shared-function/1.0@user/channel\", \"shared-function2/1.0@user/channel\"\n            def build(self):\n                pyreqs = self.python_requires\n                v = pyreqs[\"shared-function\"].module.myvar  # v will be 123\n                f = pyreqs[\"shared-function2\"].module.myfunct()  # f will be 2222\n                self.output.info(\"%s, %s\" % (v, f))\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"export . --user=user --channel=channel\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class BaseClass2(ConanFile):\n            name = \"base-class2\"\n            version = \"1.0\"\n            python_requires = \"shared-function/1.0@user/channel\", \"shared-function2/1.0@user/channel\"\n            def package(self):\n                pyreqs = self.python_requires\n                v = pyreqs[\"shared-function2\"].module.myvar  # v will be 222\n                f = pyreqs[\"shared-function\"].module.myfunct()  # f will be 234\n                self.output.info(\"%s, %s\" % (v, f))\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"export . --user=user --channel=channel\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Consumer(ConanFile):\n            name = \"consumer\"\n            version = \"1.0\"\n            python_requires = \"base-class/1.0@user/channel\", \"base-class2/1.0@user/channel\"\n            python_requires_extend = \"base-class.BaseClass\", \"base-class2.BaseClass2\"\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --user=user --channel=channel\")\n    assert \"consumer/1.0@user/channel: Calling build()\\nconsumer/1.0@user/channel: 123, 2222\" in \\\n           client.out\n    assert \"consumer/1.0@user/channel: Calling package()\\nconsumer/1.0@user/channel: 222, 234\" in \\\n           client.out\n\n\nclass TestConflictPyRequires:\n    # https://github.com/conan-io/conan/issues/15016\n    def test_diamond_conflict_fixed(self):\n        c = TestClient(light=True)\n\n        c.save({\"tool/conanfile.py\": GenConanfile(\"tool\"),\n                \"sub1/conanfile.py\": GenConanfile(\"sub1\", \"1.0\").with_python_requires(\"tool/1.0\"),\n                \"sub2/conanfile.py\": GenConanfile(\"sub2\", \"1.0\").with_python_requires(\"tool/1.1\"),\n                \"app/conanfile.py\": GenConanfile().with_python_requires(\"sub1/1.0\", \"sub2/1.0\")})\n        c.run(\"export tool --version=1.0\")\n        c.run(\"export tool --version=1.1\")\n        c.run(\"export sub1\")\n        c.run(\"export sub2\")\n        c.run(\"install app\", assert_error=True)\n        assert \"Conflict in py_requires tool/1.0 - tool/1.1\" in c.out\n\n    def test_diamond_conflict_ranges(self):\n        c = TestClient(light=True)\n\n        c.save({\"tool/conanfile.py\": GenConanfile(\"tool\"),\n                \"sub1/conanfile.py\": GenConanfile(\"sub1\", \"1.0\").with_python_requires(\"tool/[*]\"),\n                \"sub2/conanfile.py\": GenConanfile(\"sub2\", \"1.0\").with_python_requires(\"tool/1.0\"),\n                \"app/conanfile.py\": GenConanfile().with_python_requires(\"sub1/1.0\", \"sub2/1.0\")})\n        c.run(\"export tool --version=1.0\")\n        c.run(\"export tool --version=1.1\")\n        c.run(\"export sub1\")\n        c.run(\"export sub2\")\n        c.run(\"install app\", assert_error=True)\n        assert \"Conflict in py_requires tool/1.1 - tool/1.0\" in c.out\n\n\ndef test_multiple_reuse():\n    \"\"\" test how to enable the multiple code reuse for custom user generators\n        # https://github.com/conan-io/conan/issues/11589\n    \"\"\"\n\n    c = TestClient(light=True)\n    common = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        def mycommon():\n            return 42\n        class Common(ConanFile):\n            name = \"common\"\n            version = \"0.1\"\n        \"\"\")\n    tool = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class MyGenerator:\n            common = None\n            def __init__(self, conanfile):\n                self.conanfile = conanfile\n            def generate(self):\n                self.conanfile.output.info(\"VALUE TOOL: {}!!!\".format(MyGenerator.common.mycommon()))\n\n        class Tool(ConanFile):\n            name = \"tool\"\n            version = \"0.1\"\n            python_requires = \"common/0.1\"\n            def init(self):\n                MyGenerator.common = self.python_requires[\"common\"].module\n        \"\"\")\n    consumer = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Consumer(ConanFile):\n            python_requires = \"tool/0.1\", \"common/0.1\"\n            def generate(self):\n                mycommon = self.python_requires[\"common\"].module.mycommon\n                self.output.info(\"VALUE COMMON: {}!!!\".format(mycommon()))\n                mygenerator = self.python_requires[\"tool\"].module.MyGenerator(self)\n                mygenerator.generate()\n        \"\"\")\n    c.save({\"common/conanfile.py\": common,\n            \"tool/conanfile.py\": tool,\n            \"consumer/conanfile.py\": consumer})\n    c.run(\"export common\")\n    c.run(\"export tool\")\n    c.run(\"install consumer\")\n    assert \"VALUE COMMON: 42!!!\" in c.out\n    assert \"VALUE TOOL: 42!!!\" in c.out\n\n\nclass TestTestPackagePythonRequire:\n    def test_test_package_python_requires(self):\n        \"\"\" test how to test_package a python_require\n        \"\"\"\n\n        c = TestClient(light=True)\n        c.save({\"conanfile.py\": GenConanfile(\"mytool\", \"0.1\")})\n        c.run(\"create .\")\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            def mycommon():\n                return 42\n            class Common(ConanFile):\n                name = \"common\"\n                version = \"0.1\"\n                package_type = \"python-require\"\n            \"\"\")\n        test = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class Tool(ConanFile):\n                python_requires = \"tested_reference_str\"\n                def test(self):\n                    self.output.info(\"{}!!!\".format(self.python_requires[\"common\"].module.mycommon()))\n            \"\"\")\n        c.save({\"conanfile.py\": conanfile,\n                \"test_package/conanfile.py\": test})\n        c.run(\"create .\")\n        assert \"WARN: deprecated: test_package/conanfile.py\" not in c.out\n        assert \"common/0.1 (test package): 42!!!\" in c.out\n\n        c.run(\"test test_package common/0.1\")\n        assert \"WARN: deprecated: test_package/conanfile.py\" not in c.out\n        assert \"common/0.1 (test package): 42!!!\" in c.out\n\n        # https://github.com/conan-io/conan/issues/18224\n        c.save({\"myprofile\": \"[tool_requires]\\nmytool/0.1\"})\n        c.run(\"create . -pr=myprofile\")\n        assert \"common/0.1 (test package): 42!!!\" in c.out\n\n    def test_test_package_python_requires_configs(self):\n        \"\"\" test how to test_package a python_require with various configurations\n        \"\"\"\n\n        c = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            def mycommon(build_type):\n                return str(build_type).upper() + \"OK\"\n            class Common(ConanFile):\n                name = \"common\"\n                version = \"0.1\"\n                package_type = \"python-require\"\n            \"\"\")\n        test = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class Tool(ConanFile):\n                settings = \"build_type\"\n                def test(self):\n                    result = self.python_requires[\"common\"].module.mycommon(self.settings.build_type)\n                    self.output.info(\"{}!!!\".format(result))\n            \"\"\")\n        c.save({\"conanfile.py\": conanfile,\n                \"test_package/conanfile.py\": test})\n        c.run(\"create . \")\n        assert \"common/0.1 (test package): RELEASEOK!!!\" in c.out\n        assert \"WARN: deprecated: test_package/conanfile.py should declare 'python_requires\" in c.out\n        c.run(\"create . -s build_type=Debug\")\n        assert \"common/0.1 (test package): DEBUGOK!!!\" in c.out\n\n\nclass TestResolveRemote:\n    def test_resolve_remote_export(self):\n        \"\"\" a \"conan export\" command should work even when a python_requires\n        is in the server\n        \"\"\"\n        c = TestClient(light=True, default_server_user=True)\n        c.save({\"common/conanfile.py\": GenConanfile(\"tool\", \"0.1\"),\n                \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_python_requires(\"tool/0.1\")})\n        c.run(\"export common\")\n        c.run(\"upload * -r=default -c\")\n        c.run(\"remove * -c\")\n        c.run(\"create pkg\")\n        assert \"tool/0.1: Downloaded recipe\" in c.out\n\n        c.run(\"remove * -c\")\n        c.run(\"export pkg\")\n        assert \"tool/0.1: Downloaded recipe\" in c.out\n\n        c.run(\"remove * -c\")\n        c.run(\"export pkg -r=default\")\n        assert \"tool/0.1: Downloaded recipe\" in c.out\n\n        c.run(\"remove * -c\")\n        c.run(\"create pkg -r=default\")\n        assert \"tool/0.1: Downloaded recipe\" in c.out\n\n    def test_missing_python_require_error(self):\n        \"\"\" make sure the error is clear enough for users UX\n        \"\"\"\n        c = TestClient(light=True)\n        c.save({\"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_python_requires(\"tool/0.1\")})\n        c.run(\"create pkg\", assert_error=True)\n        assert \"Cannot resolve python_requires 'tool/0.1'\" in c.out\n\n\nclass TestTransitiveExtend:\n    # https://github.com/conan-io/conan/issues/10511\n    # https://github.com/conan-io/conan/issues/10565\n    def test_transitive_extend(self):\n        client = TestClient(light=True)\n        company = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class CompanyConanFile(ConanFile):\n                name = \"company\"\n                version = \"1.0\"\n\n                def msg1(self):\n                    return \"company\"\n                def msg2(self):\n                    return \"company\"\n            \"\"\")\n        project = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class ProjectBaseConanFile(ConanFile):\n                name = \"project\"\n                version = \"1.0\"\n\n                python_requires = \"company/1.0\"\n                python_requires_extend = \"company.CompanyConanFile\"\n\n                def msg1(self):\n                    return \"project\"\n            \"\"\")\n        consumer = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Base(ConanFile):\n                name = \"consumer\"\n                version = \"1.0\"\n                python_requires = \"project/1.0\"\n                python_requires_extend = \"project.ProjectBaseConanFile\"\n                def generate(self):\n                    self.output.info(\"Msg1:{}!!!\".format(self.msg1()))\n                    self.output.info(\"Msg2:{}!!!\".format(self.msg2()))\n                \"\"\")\n        client.save({\"company/conanfile.py\": company,\n                     \"project/conanfile.py\": project,\n                     \"consumer/conanfile.py\": consumer})\n        client.run(\"export company\")\n        client.run(\"export project\")\n        client.run(\"install consumer\")\n        assert \"conanfile.py (consumer/1.0): Msg1:project!!!\" in client.out\n        assert \"conanfile.py (consumer/1.0): Msg2:company!!!\" in client.out\n\n    def test_transitive_extend2(self):\n        client = TestClient(light=True)\n        company = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class CompanyConanFile(ConanFile):\n                name = \"company\"\n                version = \"1.0\"\n\n            class CompanyBase:\n                def msg1(self):\n                    return \"company\"\n                def msg2(self):\n                    return \"company\"\n            \"\"\")\n        project = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class ProjectBase:\n                def msg1(self):\n                    return \"project\"\n\n            class ProjectBaseConanFile(ConanFile):\n                name = \"project\"\n                version = \"1.0\"\n                python_requires = \"company/1.0\"\n\n                def init(self):\n                    pkg_name, base_class_name = \"company\", \"CompanyBase\"\n                    base_class = getattr(self.python_requires[pkg_name].module, base_class_name)\n                    global ProjectBase\n                    ProjectBase = type('ProjectBase', (ProjectBase, base_class, object), {})\n            \"\"\")\n        consumer = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Base(ConanFile):\n                name = \"consumer\"\n                version = \"1.0\"\n                python_requires = \"project/1.0\"\n                python_requires_extend = \"project.ProjectBase\"\n                def generate(self):\n                    self.output.info(\"Msg1:{}!!!\".format(self.msg1()))\n                    self.output.info(\"Msg2:{}!!!\".format(self.msg2()))\n                \"\"\")\n        client.save({\"company/conanfile.py\": company,\n                     \"project/conanfile.py\": project,\n                     \"consumer/conanfile.py\": consumer})\n        client.run(\"export company\")\n        client.run(\"export project\")\n        client.run(\"install consumer\")\n        assert \"conanfile.py (consumer/1.0): Msg1:project!!!\" in client.out\n        assert \"conanfile.py (consumer/1.0): Msg2:company!!!\" in client.out\n\n\ndef test_multi_top_missing_from_remote():\n    \"\"\"\n    https://github.com/conan-io/conan/issues/13656\n    \"\"\"\n    tc = TestClient(light=True, default_server_user=True)\n    tc.save({\"conanfile.py\": GenConanfile(\"base\", \"1.1\")})\n    tc.run(\"create . --user=user --channel=testing\")\n\n    tc.save({\"conanfile.py\": GenConanfile(\"dep\", \"1.0\")\n            .with_python_requires(\"base/1.1@user/testing\")})\n    tc.run(\"create . --user=user --channel=testing -r default\")\n\n    tc.run(\"upload * -c -r default\")\n    tc.run(\"remove * -c\")\n\n    tc.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\")\n            .with_python_requires(\"dep/1.0@user/testing\")})\n\n    # This used to crash, with errors about not defining remotes\n    tc.run(\"create . --name=pkg --version=1.0 -r default\")\n\n    # Ensure we found them in the remote\n    assert \"dep/1.0@user/testing: Not found in local cache, looking in remotes...\" in tc.out\n    assert \"dep/1.0@user/testing: Downloaded recipe revision\" in tc.out\n    assert \"base/1.1@user/testing: Not found in local cache, looking in remotes...\" in tc.out\n    assert \"base/1.1@user/testing: Downloaded recipe revision\" in tc.out\n\n\ndef test_transitive_range_not_found_in_cache():\n    \"\"\"\n    https://github.com/conan-io/conan/issues/13761\n    \"\"\"\n    c = TestClient(light=True)\n    c.save({\"conanfile.py\": GenConanfile(\"pr\", \"1.0\")})\n    c.run(\"create .\")\n\n    c.save({\"conanfile.py\": GenConanfile(\"dep\", \"1.0\").with_python_requires(\"pr/[>0]\")})\n    c.run(\"create .\")\n\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_requires(\"dep/1.0\")})\n    c.run(\"create . \")\n    c.assert_listed_require({\"pr/1.0\": \"Cache\"}, python=True)\n    assert \"pr/[>0]: pr/1.0\" in c.out\n\n\ndef test_export_pkg():\n    c = TestClient(light=True)\n    c.save({\"conanfile.py\": GenConanfile(\"pytool\", \"0.1\").with_package_type(\"python-require\")})\n    c.run(\"export-pkg .\", assert_error=True)\n    assert \"export-pkg can only be used for binaries, not for 'python-require'\" in c.out\n    # Make sure nothing is exported\n    c.run(\"list *\")\n    assert \"WARN: There are no matching recipe references\" in c.out\n    assert \"pytool/0.1\" not in c.out\n\n\ndef test_py_requires_override_method():\n    tc = TestClient(light=True)\n    pyreq = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class MyConanfileBase:\n            def get_toolchain(self):\n                return \"mybasetoolchain\"\n\n            def generate(self):\n                self.output.info(\"MyConanfileBase generate with value %s\" % self.get_toolchain())\n\n        class MyConanfile(ConanFile):\n            name = \"myconanfile\"\n            version = \"1.0\"\n            package_type = \"python-require\"\n    \"\"\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class MyConanfile(ConanFile):\n            name = \"app\"\n            version = \"1.0\"\n            python_requires = \"myconanfile/1.0\"\n            python_requires_extend = \"myconanfile.MyConanfileBase\"\n            def get_toolchain(self):\n                return \"mycustomtoolchain\"\n    \"\"\")\n    tc.save({\"myconanfile/conanfile.py\": pyreq,\n             \"conanfile.py\": conanfile})\n    tc.run(\"create myconanfile\")\n    tc.run(\"create .\")\n    assert \"MyConanfileBase generate with value mycustomtoolchain\" in tc.out\n"
  },
  {
    "path": "test/integration/remote/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/remote/auth_bearer_test.py",
    "content": "from bottle import request\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient, TestServer\n\n\nclass AuthorizationHeaderSpy:\n    \"\"\" Generic plugin to handle Authorization header. Must be extended and implement\n    some abstract methods in subclasses\"\"\"\n\n    name = 'authorizationheaderspy'\n    api = 2\n\n    def __init__(self):\n        self.auths = []\n\n    def apply(self, callback, context):  # noqa\n        auth = request.headers.get(\"Authorization\")\n        name = callback.__name__\n        self.auths.append((name, auth))\n        return callback\n\n\nclass TestAuthorizeBearer:\n\n    def test_basic(self):\n        auth = AuthorizationHeaderSpy()\n        server = TestServer(plugins=[auth])\n        client = TestClient(servers={\"default\": server}, inputs=[\"admin\", \"password\"])\n        client.save({\"conanfile.py\": GenConanfile(\"hello\", \"0.1\")})\n        client.run(\"export . --user=lasote --channel=stable\")\n        errors = client.run(\"upload hello/0.1@lasote/stable -r default --only-recipe\")\n        assert not errors\n\n        expected_calls = [('get_recipe_revisions_references', None),\n                          ('check_credentials', None),\n                          ('authenticate', 'Basic'),\n                          ('upload_recipe_file', 'Bearer')]\n\n        assert len(expected_calls) == len(auth.auths)\n        for i, (method, auth_type) in enumerate(expected_calls):\n            real_call = auth.auths[i]\n            assert method == real_call[0]\n            if auth_type:\n                assert auth_type in real_call[1]\n"
  },
  {
    "path": "test/integration/remote/auth_test.py",
    "content": "import copy\nimport os\nimport textwrap\n\nimport pytest\nfrom requests.models import Response\n\nfrom conan.api.model import RecipeReference\nfrom conan.internal.api.remotes.localdb import LocalDB\nfrom conan.internal.util.files import save\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.env import environment_update\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient\nfrom conan.test.utils.tools import TestRequester\nfrom conan.test.utils.tools import TestServer\n\n\nclass TestAuthorize:\n\n    @pytest.fixture(autouse=True)\n    def setup(self):\n        self.servers = {}\n        self.ref = RecipeReference.loads(\"openssl/2.0.1@lasote/testing\")\n        # Create a default remote. R/W is not authorized for ref,\n        # just for pepe, nacho and owner\n        self.test_server = TestServer([(str(self.ref), \"pepe,nacho@gmail.com\")],  # read permissions\n                                      [(str(self.ref), \"pepe,nacho@gmail.com\")],  # write permissions\n                                      users={\"lasote\": \"mypass\",\n                                             \"pepe\": \"pepepass\",\n                                             \"nacho@gmail.com\": \"nachopass\"})  # exported creds\n        self.servers[\"default\"] = self.test_server\n\n    def test_retries(self):\n        \"\"\"Bad login 2 times\"\"\"\n        self.conan = TestClient(servers=self.servers, inputs=[\"bad\", \"1\",\n                                                              \"bad2\", \"2\",\n                                                              \"nacho@gmail.com\", \"nachopass\"])\n        self.conan.save({\"conanfile.py\": GenConanfile(\"openssl\", \"2.0.1\")})\n        self.conan.run(\"export . --user=lasote --channel=testing\")\n        errors = self.conan.run(\"upload %s -r default --only-recipe -v=quiet\" % str(self.ref))\n        # Check that return was  ok\n        assert not errors\n        # Check that upload was granted\n        rev = self.test_server.server_store.get_last_revision(self.ref).revision\n        ref = copy.copy(self.ref)\n        ref.revision = rev\n        assert os.path.exists(self.test_server.server_store.export(ref))\n        assert \"Please enter a password for user 'bad'\" in self.conan.out\n        assert \"Please enter a password for user 'bad2'\" in self.conan.out\n        assert \"Please enter a password for user 'nacho@gmail.com'\" in self.conan.out\n\n    def test_auth_with_env(self):\n\n        def _upload_with_credentials(credentials, assert_error=False):\n            cli = TestClient(servers=self.servers)\n            cli.save({\"conanfile.py\": GenConanfile(\"openssl\", \"2.0.1\")})\n            cli.run(\"export . --user=lasote --channel=testing\")\n            with environment_update(credentials):\n                cli.run(\"upload %s -r default --only-recipe\" % str(self.ref),\n                        assert_error=assert_error)\n            return cli\n\n        # Try with remote name in credentials\n        client = _upload_with_credentials({\"CONAN_PASSWORD_DEFAULT\": \"pepepass\",\n                                           \"CONAN_LOGIN_USERNAME_DEFAULT\": \"pepe\"})\n        assert \"Got username 'pepe' from environment\" in client.out\n        assert \"Got password '******' from environment\" in client.out\n\n        # Try with generic password and login\n        client = _upload_with_credentials({\"CONAN_PASSWORD\": \"pepepass\",\n                                           \"CONAN_LOGIN_USERNAME_DEFAULT\": \"pepe\"})\n        assert \"Got username 'pepe' from environment\" in client.out\n        assert \"Got password '******' from environment\" in client.out\n\n        # Try with generic password and generic login\n        client = _upload_with_credentials({\"CONAN_PASSWORD\": \"pepepass\",\n                                           \"CONAN_LOGIN_USERNAME\": \"pepe\"})\n        assert \"Got username 'pepe' from environment\" in client.out\n        assert \"Got password '******' from environment\" in client.out\n\n        # Bad pass raise\n        client = _upload_with_credentials({\"CONAN_PASSWORD\": \"bad\",\n                                           \"CONAN_LOGIN_USERNAME\": \"pepe\"}, assert_error=True)\n        assert \"Authentication error in remote 'default'\" in client.out\n\n    def test_max_retries(self):\n        \"\"\"Bad login 3 times\"\"\"\n        client = TestClient(servers=self.servers, inputs=[\"baduser\", \"badpass\",\n                                                          \"baduser\", \"badpass2\",\n                                                          \"baduser3\", \"badpass3\"])\n        client.save({\"conanfile.py\": GenConanfile(\"openssl\", \"2.0.1\")})\n        client.run(\"export . --user=lasote --channel=testing\")\n        errors = client.run(\"upload %s -r default --only-recipe\" % str(self.ref), assert_error=True)\n        # Check that return was not ok\n        assert errors\n        # Check that upload was not granted\n        rev = self.servers[\"default\"].server_store.get_last_revision(self.ref)\n        assert rev is None\n\n        # Check that login failed all times\n        assert \"Too many failed login attempts, bye!\" in client.out\n\n    def test_no_client_username_checks(self):\n        \"\"\"Checks whether client username checks are disabled.\"\"\"\n\n        # Try with a load of names that contain special characters\n        client = TestClient(servers=self.servers, inputs=[\"some_random.special!characters\",\n                                                          \"badpass\",\n                                                          \"nacho@gmail.com\", \"nachopass\"])\n\n        client.save({\"conanfile.py\": GenConanfile(\"openssl\", \"2.0.1\")})\n        client.run(\"export . --user=lasote --channel=testing\")\n        client.run(\"upload %s -r default --only-recipe\" % str(self.ref))\n\n        # Check that upload was granted\n        rev = self.test_server.server_store.get_last_revision(self.ref).revision\n        ref = copy.copy(self.ref)\n        ref.revision = rev\n        assert os.path.exists(self.test_server.server_store.export(ref))\n        assert (\"Please enter a password for user 'some_random.special!characters' \"\n                \"on remote 'default'\") in client.out\n\n    def test_authorize_disabled_remote(self):\n        tc = TestClient(servers=self.servers)\n        # Sanity check, this should not fail\n        tc.run(\"remote login default pepe -p pepepass\")\n        tc.run(\"remote logout default\")\n        # This used to fail when the authentication was not possible for disabled remotes\n        tc.run(\"remote disable default\")\n        tc.run(\"remote login default pepe -p pepepass\")\n        assert (\"Changed user of remote 'default' \"\n                \"from 'None' (anonymous) to 'pepe' (authenticated)\") in tc.out\n\n\nclass TestAuthenticationTest:\n\n    def test_unauthorized_during_capabilities(self):\n\n        class RequesterMock(TestRequester):\n            @staticmethod\n            def get(url, **kwargs):\n                resp_basic_auth = Response()\n                resp_basic_auth.status_code = 200\n                if \"authenticate\" in url:\n                    assert kwargs[\"auth\"].password == \"PASSWORD!\"\n                    resp_basic_auth._content = b\"TOKEN\"\n                    resp_basic_auth.headers = {\"Content-Type\": \"text/plain\"}\n                elif \"ping\" in url:\n                    resp_basic_auth.headers = {\"Content-Type\": \"application/json\",\n                                               \"X-Conan-Server-Capabilities\": \"revisions\"}\n                    bearer = getattr(kwargs[\"auth\"], \"bearer\", None)\n                    password = getattr(kwargs[\"auth\"], \"password\", None)\n                    assert bearer == \"Bearer TOKEN\" or password\n                else:\n                    assert \"search\" in url\n                    assert kwargs[\"auth\"].bearer == \"Bearer TOKEN\"\n                    resp_basic_auth._content = b'{\"results\": []}'\n                    resp_basic_auth.headers = {\"Content-Type\": \"application/json\"}\n                return resp_basic_auth\n\n        client = TestClient(requester_class=RequesterMock, default_server_user=True)\n        client.run(\"remote login default user -p PASSWORD!\")\n        assert \"Changed user of remote 'default' from 'None' (anonymous) to 'user'\" in client.out\n        client.run(\"search pkg -r=default\")\n        assert \"ERROR: Recipe 'pkg' not found\" in client.out\n\n\n@pytest.mark.xfail(reason=\"This test is randomly failing\")\ndef test_token_expired():\n    server_folder = temp_folder()\n    server_conf = textwrap.dedent(\"\"\"\n       [server]\n       jwt_expire_minutes: 0.02\n       authorize_timeout: 0\n       disk_authorize_timeout: 0\n       disk_storage_path: ./data\n       updown_secret: 12345\n       jwt_secret: mysecretmysecretmysecretmysecret\n       port: 12345\n       [read_permissions]\n       */*@*/*: *\n       [write_permissions]\n       */*@*/*: admin\n       \"\"\")\n    save(os.path.join(server_folder, \".conan_server\", \"server.conf\"), server_conf)\n    server = TestServer(base_path=server_folder, users={\"admin\": \"password\", \"other\": \"pass\"})\n\n    c = TestClient(servers={\"default\": server}, inputs=[\"admin\", \"password\", \"other\", \"pass\"])\n    c.save({\"conanfile.py\": GenConanfile()})\n    c.run(\"create . --name=pkg --version=0.1 --user=user --channel=stable\")\n    c.run(\"upload * -r=default -c\")\n    localdb = LocalDB(c.cache_folder)\n    user, token, _ = localdb.get_login(server.fake_url)\n    assert user == \"admin\"\n    assert token is not None\n\n    import time\n    time.sleep(3)\n    c.users = {}\n    c.run(\"remove * -c\")\n    c.run(\"install --requires=pkg/0.1@user/stable\")\n    assert \"Remote 'default' needs authentication, obtaining credentials\" in c.out\n    user, token, _ = localdb.get_login(server.fake_url)\n    assert user == \"other\"\n    assert token is not None\n\n\ndef test_auth_username_space():\n    server = TestServer(users={\"super admin\": \"password\"})\n    c = TestClient(servers={\"default\": server}, inputs=[\"super admin\", \"password\"])\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n    c.run(\"export .\")\n    c.run(\"upload * -r=default -c\")\n    # it doesn't crash, it accepts user with space\n"
  },
  {
    "path": "test/integration/remote/broken_download_test.py",
    "content": "import json\nimport os\n\nimport pytest\nfrom requests import Response\n\nfrom requests.exceptions import ConnectionError\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient, TestRequester, TestServer\nfrom conan.internal.util.files import save\n\n\nclass TestBrokenDownload:\n\n    @pytest.fixture()\n    def setup(self):\n        server = TestServer()\n        client = TestClient(servers={\"default\": server}, inputs=[\"admin\", \"password\"])\n        client.save({\"conanfile.py\": GenConanfile(\"hello\", \"0.1\")})\n        client.run(\"create .\")\n        pref = client.created_package_reference(\"hello/0.1\")\n        client.run(\"upload * -r default -c\")\n        client.run(\"remove * -c\")\n        return client, pref\n\n    def test_corrupt_export_tgz(self, setup):\n        client, pref = setup\n        server = client.servers[\"default\"]\n        path = server.test_server.server_store.export(pref.ref)\n        tgz = os.path.join(path, \"conan_export.tgz\")\n        save(tgz, \"contents\")  # dummy content to break it, so the download decompress will fail\n        client.run(\"install --requires=hello/0.1\", assert_error=True)\n        assert \"Error while extracting downloaded file\" in client.out\n        assert not os.path.exists(client.get_latest_ref_layout(pref.ref).export())\n\n    def test_remove_conaninfo(self, setup):\n        \"\"\"\n        if the conaninfo is removed, it is considered at least a broken package by the client\n        \"\"\"\n        client, pref = setup\n        server = client.servers[\"default\"]\n        path = server.test_server.server_store.package(pref)\n        conaninfo = os.path.join(path, \"conaninfo.txt\")\n        os.unlink(conaninfo)\n        client.run(\"install --requires=hello/0.1\", assert_error=True)\n        assert \"ERROR: Corrupted hello/0.1:da39a3ee5e6b4b0d3255bfef95601890afd80709\" \\\n               \" in 'default' remote: no conaninfo.txt\" in client.out\n\n    def test_remove_conanfile(self, setup):\n        \"\"\"\n        if the conanfile is removed, it is considered at least a broken package by the client\n        \"\"\"\n        client, pref = setup\n        server = client.servers[\"default\"]\n        path = server.test_server.server_store.export(pref.ref)\n        conanfile = os.path.join(path, \"conanfile.py\")\n        os.unlink(conanfile)\n        client.run(\"install --requires=hello/0.1\", assert_error=True)\n        assert \"Corrupted hello/0.1 in 'default' remote: no conanfile.py\" in client.out\n\n    def test_remove_pkg_conanmanifest(self, setup):\n        \"\"\"\n        if the manifest is missing the server side can say there is no package\n        \"\"\"\n        client, pref = setup\n        server = client.servers[\"default\"]\n\n        path = server.test_server.server_store.package(pref)\n        manifest = os.path.join(path, \"conanmanifest.txt\")\n        os.unlink(manifest)\n        client.run(\"install --requires=hello/0.1\", assert_error=True)\n        assert \"ERROR: Binary package not found: 'hello/0.1\" in client.out\n\n    def test_remove_recipe_conanmanifest(self, setup):\n        \"\"\"\n        if the manifest is missing the server side can say there is no recipe\n        \"\"\"\n        client, pref = setup\n        server = client.servers[\"default\"]\n\n        path = server.test_server.server_store.export(pref.ref)\n        manifest = os.path.join(path, \"conanmanifest.txt\")\n        os.unlink(manifest)\n        client.run(\"install --requires=hello/0.1\", assert_error=True)\n        assert \"Recipe not found: 'hello/0.1\" in client.out\n\n\ndef test_client_retries():\n    server = TestServer()\n    servers = {\"default\": server}\n    client = TestClient(servers=servers, inputs=[\"admin\", \"password\"])\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"create . --name=lib --version=1.0 --user=lasote --channel=stable\")\n    client.run(\"upload lib/1.0@lasote/stable -c -r default\")\n\n    class DownloadFilesBrokenRequester(TestRequester):\n        def __init__(self, times_to_fail=1, *args, **kwargs):\n            self.times_to_fail = times_to_fail\n            super(DownloadFilesBrokenRequester, self).__init__(*args, **kwargs)\n\n        def get(self, url, **kwargs):\n            # conaninfo is skipped sometimes from the output, use manifest\n            if \"conanmanifest.txt\" in url and self.times_to_fail > 0:\n                self.times_to_fail = self.times_to_fail - 1\n                raise ConnectionError(\"Fake connection error exception\")\n            else:\n                return super(DownloadFilesBrokenRequester, self).get(url, **kwargs)\n\n    def DownloadFilesBrokenRequesterTimesOne(*args, **kwargs):  # noqa\n        return DownloadFilesBrokenRequester(1, *args, **kwargs)\n    client = TestClient(servers=servers, inputs=[\"admin\", \"password\"],\n                        requester_class=DownloadFilesBrokenRequesterTimesOne)\n    client.run(\"install --requires=lib/1.0@lasote/stable\")\n    assert \"WARN: network: Error downloading file\" in client.out\n    assert 'Fake connection error exception' in client.out\n    assert 1 == str(client.out).count(\"Waiting 0 seconds to retry...\")\n\n    client = TestClient(servers=servers, inputs=[\"admin\", \"password\"],\n                        requester_class=DownloadFilesBrokenRequesterTimesOne)\n    client.save_home({\"global.conf\": \"core.download:retry_wait=1\"})\n    client.run(\"install --requires=lib/1.0@lasote/stable\")\n    assert 1 == str(client.out).count(\"Waiting 1 seconds to retry...\")\n\n    def DownloadFilesBrokenRequesterTimesTen(*args, **kwargs):  # noqa\n        return DownloadFilesBrokenRequester(10, *args, **kwargs)\n    client = TestClient(servers=servers, inputs=[\"admin\", \"password\"],\n                        requester_class=DownloadFilesBrokenRequesterTimesTen)\n    client.save_home({\"global.conf\": \"core.download:retry_wait=0\\n\"\n                                     \"core.download:retry=11\"})\n    client.run(\"install --requires=lib/1.0@lasote/stable\")\n    assert 10 == str(client.out).count(\"Waiting 0 seconds to retry...\")\n\n\ndef test_forbidden_blocked_conanmanifest():\n    \"\"\" this is what happens when a server blocks downloading a specific file\n    \"\"\"\n    server = TestServer()\n    servers = {\"default\": server}\n    client = TestClient(servers=servers, inputs=[\"admin\", \"password\"])\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"create . --name=lib --version=1.0\")\n    client.run(\"upload lib/1.0* -c -r default\")\n\n    class DownloadForbidden(TestRequester):\n        def get(self, url, **kwargs):\n            if \"conanmanifest.txt\" in url:\n                r = Response()\n                r._content = \"Forbidden because of security!!!\"\n                r.status_code = 403\n                return r\n            else:\n                return super(DownloadForbidden, self).get(url, **kwargs)\n\n    client = TestClient(servers=servers, inputs=[\"admin\", \"password\"],\n                        requester_class=DownloadForbidden)\n    client.run(\"download lib/1.0 -r=default\", assert_error=True)\n    assert \"Forbidden because of security!!!\" in client.out\n\n    client.run(\"list *\")\n    assert \"lib/1.0\" not in client.out\n\n    client.run(\"install --requires=lib/1.0\", assert_error=True)\n    assert \"Forbidden because of security!!!\" in client.out\n\n    client.run(\"list *\")\n    assert \"lib/1.0\" not in client.out\n\n\ndef test_forbidden_blocked_package_conanmanifest():\n    \"\"\" this is what happens when a server blocks downloading a specific file\n    \"\"\"\n    server = TestServer()\n    servers = {\"default\": server}\n    client = TestClient(servers=servers, inputs=[\"admin\", \"password\"])\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"create . --name=lib --version=1.0\")\n    client.run(\"upload lib/1.0* -c -r default\")\n\n    class DownloadForbidden(TestRequester):\n        def get(self, url, **kwargs):\n            if \"packages/\" in url and \"conanmanifest.txt\" in url:\n                r = Response()\n                r._content = \"Forbidden because of security!!!\"\n                r.status_code = 403\n                return r\n            else:\n                return super(DownloadForbidden, self).get(url, **kwargs)\n\n    client = TestClient(servers=servers, inputs=[\"admin\", \"password\"],\n                        requester_class=DownloadForbidden)\n    client.run(\"download lib/1.0 -r=default\", assert_error=True)\n\n    def check_cache():\n        assert \"Forbidden because of security!!!\" in client.out\n        client.run(\"list *:* --format=json\")\n        listjson = json.loads(client.stdout)\n        revisions = listjson[\"Local Cache\"][\"lib/1.0\"][\"revisions\"]\n        packages = revisions[\"4d670581ccb765839f2239cc8dff8fbd\"][\"packages\"]\n        assert packages == {}  # No binaries\"\n\n    check_cache()\n\n    client.run(\"install --requires=lib/1.0\", assert_error=True)\n    assert \"Forbidden because of security!!!\" in client.out\n    check_cache()\n"
  },
  {
    "path": "test/integration/remote/download_retries_test.py",
    "content": "from conan.internal.paths import CONANFILE\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient, TestServer, TestRequester\n\n\nclass TestDownloadRetries:\n\n    def test_recipe_download_retry(self):\n        test_server = TestServer()\n        client = TestClient(servers={\"default\": test_server}, inputs=[\"admin\", \"password\"])\n\n        client.save({CONANFILE: GenConanfile()})\n        client.run(\"create . --name=pkg --version=0.1 --user=lasote --channel=stable\")\n        client.run(\"upload '*' -c -r default\")\n\n        class Response:\n            def __init__(self, ok, status_code):\n                self.ok = ok\n                self.status_code = status_code\n\n        class BuggyRequester(TestRequester):\n            def get(self, *args, **kwargs):\n                if \"files/conanfile.py\" not in args[0]:\n                    return super(BuggyRequester, self).get(*args, **kwargs)\n                else:\n                    return Response(False, 200)\n\n        # The buggy requester will cause a failure only downloading files, not in regular requests\n        client = TestClient(servers={\"default\": test_server}, inputs=[\"admin\", \"password\"],\n                            requester_class=BuggyRequester)\n        client.run(\"install --requires=pkg/0.1@lasote/stable\", assert_error=True)\n        assert str(client.out).count(\"Waiting 0 seconds to retry...\") == 2\n        assert str(client.out).count(\"Error 200 downloading\") == 3\n"
  },
  {
    "path": "test/integration/remote/download_test.py",
    "content": "from requests import Response\n\nfrom conan.test.utils.tools import TestClient, TestServer, TestRequester\n\nmyconan1 = \"\"\"\nfrom conan import ConanFile\nimport platform\n\nclass HelloConan(ConanFile):\n    name = \"hello\"\n    version = \"1.2.1\"\n\"\"\"\n\n\nclass TestDownload:\n\n    def test_returns_on_failures(self):\n        test_server = TestServer([(\"*/*@*/*\", \"*\")], [(\"*/*@*/*\", \"*\")])\n        servers = {\"default\": test_server}\n\n        class BuggyRequester(TestRequester):\n            def get(self, *args, **kwargs):\n                resp = Response()\n                resp.status_code = 404\n                resp._content = b''\n                return resp\n\n        client2 = TestClient(servers=servers, requester_class=BuggyRequester)\n        client2.run(\"remote add remotename url\")\n        client2.run(\"install --requires=foo/bar@ -r remotename\", assert_error=True)\n        assert \"Package 'foo/bar' not resolved: Unable to find 'foo/bar' in remotes\" in client2.out\n\n        class BuggyRequester2(BuggyRequester):\n            def get(self, *args, **kwargs):\n                resp = Response()\n                resp.status_code = 500\n                resp._content = b'This server is under maintenance'\n                return resp\n\n        client2 = TestClient(servers=servers, requester_class=BuggyRequester2)\n        client2.run(\"remote add remotename url\")\n        client2.run(\"install --requires=foo/bar@ -r remotename\", assert_error=True)\n        assert \"ERROR: Package 'foo/bar' not resolved\" in client2.out\n        assert \"This server is under maintenance\" in client2.out\n        assert \"not found\" not in client2.out\n"
  },
  {
    "path": "test/integration/remote/multi_remote_checks_test.py",
    "content": "from collections import OrderedDict\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import NO_SETTINGS_PACKAGE_ID, TestClient, TestServer\n\n\nclass TestRemoteChecks:\n\n    def test_binary_defines_remote(self):\n        servers = OrderedDict([(\"server1\", TestServer()),\n                               (\"server2\", TestServer()),\n                               (\"server3\", TestServer())])\n        client = TestClient(servers=servers, inputs=3*[\"admin\", \"password\"])\n        conanfile = \"\"\"from conan import ConanFile\nclass Pkg(ConanFile):\n    pass\"\"\"\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --name=pkg --version=0.1 --user=lasote --channel=testing\")\n        client.run(\"upload pkg* -r=server1 --confirm\")\n        client.run(\"upload pkg* -r=server2 --confirm\")\n\n        # It takes the default remote\n        client.run(\"remove * -c\")\n\n        # Exported recipe gets binary from default remote\n        client.run(\"export . --name=pkg --version=0.1 --user=lasote --channel=testing\")\n        client.run(\"install --requires=pkg/0.1@lasote/testing\")\n        client.assert_listed_binary(\n            {\"pkg/0.1@lasote/testing\": (NO_SETTINGS_PACKAGE_ID, \"Download (server1)\")})\n        assert \"pkg/0.1@lasote/testing: Retrieving package \" \\\n                      \"%s from remote 'server1'\" % NO_SETTINGS_PACKAGE_ID in client.out\n\n        # Explicit remote also defines the remote\n        client.run(\"remove * -c\")\n        client.run(\"export . --name=pkg --version=0.1 --user=lasote --channel=testing\")\n        client.run(\"install --requires=pkg/0.1@lasote/testing -r=server2\")\n        client.assert_listed_binary(\n            {\"pkg/0.1@lasote/testing\": (NO_SETTINGS_PACKAGE_ID, \"Download (server2)\")})\n        assert \"pkg/0.1@lasote/testing: Retrieving package \" \\\n                      \"%s from remote 'server2'\" % NO_SETTINGS_PACKAGE_ID in client.out\n\n        # Ordered search of binary works\n        client.run(\"remove * -c\")\n        client.run(\"remove * -c -r=server1\")\n        client.run(\"export . --name=pkg --version=0.1 --user=lasote --channel=testing\")\n        client.run(\"install --requires=pkg/0.1@lasote/testing\")\n        client.assert_listed_binary(\n            {\"pkg/0.1@lasote/testing\": (NO_SETTINGS_PACKAGE_ID, \"Download (server2)\")})\n        assert \"pkg/0.1@lasote/testing: Retrieving package \" \\\n                      \"%s from remote 'server2'\" % NO_SETTINGS_PACKAGE_ID in client.out\n\n        # Download recipe and binary from the remote2 by iterating\n        client.run(\"remove * -c\")\n        client.run(\"remove * -c -r=server1\")\n        client.run(\"install --requires=pkg/0.1@lasote/testing\")\n        client.assert_listed_binary(\n            {\"pkg/0.1@lasote/testing\": (NO_SETTINGS_PACKAGE_ID, \"Download (server2)\")})\n        assert \"pkg/0.1@lasote/testing: Retrieving package \" \\\n                      \"%s from remote 'server2'\" % NO_SETTINGS_PACKAGE_ID in client.out\n\n    def test_binaries_from_different_remotes(self):\n        servers = OrderedDict()\n        servers[\"server1\"] = TestServer()\n        servers[\"server2\"] = TestServer()\n        client = TestClient(servers=servers, inputs=2*[\"admin\", \"password\"])\n        conanfile = \"\"\"from conan import ConanFile\nclass Pkg(ConanFile):\n    options = {\"opt\": [1, 2, 3]}\n\"\"\"\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --name=pkg --version=0.1 --user=lasote --channel=testing -o pkg/*:opt=1\")\n        client.run(\"upload pkg* -r=server1 --confirm\")\n        client.run(\"remove *:* -c\")\n        client.run(\"create . --name=pkg --version=0.1 --user=lasote --channel=testing -o pkg/*:opt=2\")\n        package_id2 = client.created_package_id(\"pkg/0.1@lasote/testing\")\n        client.run(\"upload pkg* -r=server2 --confirm\")\n        client.run(\"remove *:* -c\")\n\n        # recipe is cached, takes binary from server2\n        client.run(\"install --requires=pkg/0.1@lasote/testing -o pkg/*:opt=2 -r=server2\")\n        client.assert_listed_binary({\"pkg/0.1@lasote/testing\": (package_id2, \"Download (server2)\")})\n        assert f\"pkg/0.1@lasote/testing: Retrieving package {package_id2} \" \\\n                      \"from remote 'server2'\" in client.out\n\n        # Nothing to update\n        client.run(\"install --requires=pkg/0.1@lasote/testing -o pkg/*:opt=2 -r=server2 -u\")\n        client.assert_listed_binary({\"pkg/0.1@lasote/testing\": (package_id2, \"Cache\")})\n\n        # Build missing\n        client.run(\"install --requires=pkg/0.1@lasote/testing -o pkg/*:opt=3 -r=server2\", assert_error=True)\n        assert \"ERROR: Missing prebuilt package for 'pkg/0.1@lasote/testing'\" in client.out\n\n        client.run(\"install --requires=pkg/0.1@lasote/testing -o pkg/*:opt=3\", assert_error=True)\n        assert \"ERROR: Missing prebuilt package for 'pkg/0.1@lasote/testing'\" in client.out\n\n\ndef test_version_range_multi_remote():\n    \"\"\" captures the behavior of version-range resolution with multiple remotes:\n    - normally the first occurrence stops: if a valid is found in the cache, it returns, if a\n      valid is found in the first server, it is return\n    - Using --update forces to really update to the latest version available, anywhere\n    \"\"\"\n    servers = OrderedDict([(\"server1\", TestServer()),\n                           (\"server2\", TestServer()),\n                           (\"server3\", TestServer())])\n    client = TestClient(servers=servers, inputs=3*[\"admin\", \"password\"])\n    client.save({\"conanfile.py\": GenConanfile()})\n    for i in (1, 2, 3):\n        client.run(f\"create . --name=pkg1 --version=1.{i}\")\n        client.run(f\"upload pkg1/1.{i} -r=server{i}\")\n        client.run(f\"create . --name=pkg2 --version=1.{i}\")\n        client.run(f\"upload pkg2/1.{i} -r=server{4-i}\")\n\n    client.run(\"remove * -c\")\n    client.run(\"install  --requires=pkg1/[*] --requires=pkg2/[*]\")\n    # First found\n    assert \"pkg1/1.1#4d670581ccb765839f2239cc8dff8fbd - Downloaded (server1)\" in client.out\n    assert \"pkg2/1.3#4d670581ccb765839f2239cc8dff8fbd - Downloaded (server1)\" in client.out\n    assert \"pkg1/[*]: pkg1/1.1\" in client.out\n    assert \"pkg2/[*]: pkg2/1.3\" in client.out\n\n    client.run(\"remove * -c\")\n    client.run(\"install  --requires=pkg1/[*] --requires=pkg2/[*] --update\")\n    # with --update, it guarantees the greatest version is found among remotes\n    assert \"pkg1/1.3#4d670581ccb765839f2239cc8dff8fbd - Downloaded (server3)\" in client.out\n    assert \"pkg2/1.3#4d670581ccb765839f2239cc8dff8fbd - Downloaded (server1)\" in client.out\n    assert \"pkg1/[*]: pkg1/1.3\" in client.out\n    assert \"pkg2/[*]: pkg2/1.3\" in client.out\n"
  },
  {
    "path": "test/integration/remote/multi_remote_test.py",
    "content": "import pytest\nfrom collections import OrderedDict\nfrom time import sleep\n\nfrom conan.api.model import RecipeReference\nfrom conan.internal.paths import CONANFILE\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient, TestServer\n\n\nclass TestExportsSourcesMissing:\n\n    def test_exports_sources_missing(self):\n        client = TestClient(default_server_user=True)\n        client.save({\"conanfile.py\": GenConanfile().with_exports_sources(\"*\"),\n                     \"source.txt\": \"somesource\"})\n        client.run(\"create . --name=pkg --version=0.1 --user=user --channel=testing\")\n        client.run(\"upload pkg/0.1@user/testing -r default\")\n\n        # Failure because remote is removed\n        servers = OrderedDict(client.servers)\n        servers[\"new_server\"] = TestServer(users={\"user\": \"password\"})\n        client2 = TestClient(servers=servers, inputs=[\"user\", \"password\"])\n        client2.run(\"install --requires=pkg/0.1@user/testing\")\n        client2.run(\"remote remove default\")\n        client2.run(\"upload pkg/0.1@user/testing -r=new_server\", assert_error=True)\n        assert \"The 'pkg/0.1@user/testing' package has 'exports_sources' but sources \" \\\n                      \"not found in local cache.\" in client2.out\n        assert \"Probably it was installed from a remote that is no longer available.\" \\\n                      in client2.out\n\n        # Failure because remote removed the package\n        client2 = TestClient(servers=servers, inputs=2*[\"admin\", \"password\"])\n        client2.run(\"install --requires=pkg/0.1@user/testing\")\n        client2.run(\"remove * -r=default -c\")\n        client2.run(\"upload pkg/0.1@user/testing -r=new_server\", assert_error=True)\n        assert \"pkg/0.1@user/testing Error while compressing: The 'pkg/0.1@user/testing' \" \\\n                      in client2.out\n        assert \"The 'pkg/0.1@user/testing' package has 'exports_sources' but sources \" \\\n                      in client2.out\n        assert \"Probably it was installed from a remote that is no longer available.\" \\\n                      in client2.out\n\n\nclass TestMultiRemotes:\n\n    @pytest.fixture(autouse=True)\n    def setup(self):\n        self.servers = OrderedDict()\n        self.servers[\"default\"] = TestServer()\n        self.servers[\"local\"] = TestServer()\n\n    @staticmethod\n    def _create(client, number, version, modifier=\"\"):\n        files = {CONANFILE: str(GenConanfile(number, version)) + modifier}\n        client.save(files, clean_first=True)\n        client.run(\"export . --user=lasote --channel=stable\")\n\n    def test_conan_install_build_flag(self):\n        \"\"\"\n        Checks conan install --update works with different remotes\n        \"\"\"\n        client_a = TestClient(servers=self.servers, inputs=2*[\"admin\", \"password\"])\n        client_b = TestClient(servers=self.servers, inputs=2*[\"admin\", \"password\"])\n\n        # Upload hello0 to local and default from client_a\n        self._create(client_a, \"hello0\", \"0.0\")\n        client_a.run(\"upload hello0/0.0@lasote/stable -r local --only-recipe\")\n        client_a.run(\"upload hello0/0.0@lasote/stable -r default --only-recipe\")\n        sleep(1)  # For timestamp and updates checks\n\n        # Download hello0 from local with client_b\n        client_b.run(\"install --requires=hello0/0.0@lasote/stable -r local --build missing\")\n\n        # Update hello0 with client_a and reupload\n        self._create(client_a, \"hello0\", \"0.0\", modifier=\"\\n\")\n        client_a.run(\"upload hello0/0.0@lasote/stable -r local --only-recipe\")\n        assert \"Uploading recipe 'hello0/0.0@lasote/stable\" in client_a.out\n\n        # Execute info method in client_b, should advise that there is an update\n        client_b.run(\"graph info --requires=hello0/0.0@lasote/stable --check-updates\")\n        assert \"recipe: Update available\" in client_b.out\n        assert \"binary: Cache\" in client_b.out\n\n        # Now try to update the package with install -u\n        client_b.run(\"install --requires=hello0/0.0@lasote/stable -u --build='*'\")\n        assert \"hello0/0.0@lasote/stable#64fd8ae21db9eff69c6c681b0e2fc178 - Updated\" \\\n                      in client_b.out\n\n        # Upload a new version from client A, but only to the default server (not the ref-listed)\n        # Upload hello0 to local and default from client_a\n        sleep(1)  # For timestamp and updates checks\n        self._create(client_a, \"hello0\", \"0.0\", modifier=\"\\n\\n\")\n        client_a.run(\"upload hello0/0.0@lasote/stable#latest -r default --only-recipe\")\n\n        # Now client_b checks for updates without -r parameter\n        # TODO: cache2.0 conan info not yet implemented with new cache\n        client_b.run(\"graph info --requires=hello0/0.0@lasote/stable --check-updates\")\n        assert \"recipe: Update available\" in client_b.out\n        # assert \"Recipe: Cache\" in client_b.out\n\n        # But if we connect to default, should tell us that there is an update IN DEFAULT!\n        # TODO: cache2.0 conan info not yet implemented with new cache\n        client_b.run(\"graph info --requires=hello0/0.0@lasote/stable -r default --check-updates\")\n        # assert \"Remote: local\" in client_b.out\n        assert \"recipe: Update available\" in client_b.out\n\n        # Well, now try to update the package with -r default -u\n        client_b.run(\"install --requires=hello0/0.0@lasote/stable -r default -u --build='*'\")\n        assert \"hello0/0.0@lasote/stable: Forced build from source\" \\\n                      in str(client_b.out)\n        # TODO: cache2.0 conan info not yet implemented with new cache\n        client_b.run(\"graph info --requires=hello0/0.0@lasote/stable -u\")\n        assert \"recipe: Cache\" in client_b.out\n        assert \"binary: Cache\" in client_b.out\n\n    def test_conan_install_update(self):\n        \"\"\"\n        Checks conan install --update works only with the remote associated\n        \"\"\"\n        client = TestClient(servers=self.servers, inputs=2*[\"admin\", \"password\"])\n\n        self._create(client, \"hello0\", \"0.0\")\n        default_remote_rev = client.exported_recipe_revision()\n        client.run(\"install --requires=hello0/0.0@lasote/stable --build missing\")\n\n        client.run(\"upload hello0/0.0@lasote/stable -r default\")\n        sleep(1)  # For timestamp and updates checks\n        self._create(client, \"hello0\", \"0.0\", modifier=\" \")\n        local_remote_rev = client.exported_recipe_revision()\n        client.run(\"install --requires=hello0/0.0@lasote/stable --build missing\")\n\n        client.run(\"upload hello0/0.0@lasote/stable#latest -r local\")\n        client.run(\"remove '*' -c\")\n\n        client.run(\"install --requires=hello0/0.0@lasote/stable\")\n        # If we don't set a remote we find between all remotes and get the first match\n        assert f\"hello0/0.0@lasote/stable#{default_remote_rev} - Downloaded\" in client.out\n        client.run(\"install --requires=hello0/0.0@lasote/stable --update\")\n        assert f\"hello0/0.0@lasote/stable#{local_remote_rev} - Updated\" in client.out\n\n        client.run(\"install --requires=hello0/0.0@lasote/stable --update -r default\")\n        assert f\"hello0/0.0@lasote/stable#{local_remote_rev} - Newer\" \\\n                      in client.out\n\n        sleep(1)  # For timestamp and updates checks\n        # Check that it really updates in case of newer package uploaded to the associated remote\n        client_b = TestClient(servers=self.servers, inputs=3*[\"admin\", \"password\"])\n        self._create(client_b, \"hello0\", \"0.0\", modifier=\"  \")\n        new_local_remote_rev = client_b.exported_recipe_revision()\n        client_b.run(\"install --requires=hello0/0.0@lasote/stable --build missing\")\n        client_b.run(\"upload hello0/0.0@lasote/stable -r local\")\n        client.run(\"install --requires=hello0/0.0@lasote/stable --update\")\n        assert f\"hello0/0.0@lasote/stable#{new_local_remote_rev} - Updated\" in client.out\n\n\nclass TestMultiRemote:\n\n    @pytest.fixture(autouse=True)\n    def setup(self):\n        self.servers = OrderedDict()\n        self.users = {}\n        for i in range(3):\n            test_server = TestServer()\n            self.servers[\"remote%d\" % i] = test_server\n            self.users[\"remote%d\" % i] = [(\"admin\", \"password\")]\n\n        self.client = TestClient(servers=self.servers, inputs=3*[\"admin\", \"password\"])\n\n    def test_fail_when_not_notfound(self):\n        \"\"\"\n        If a remote fails with a 404 it has to keep looking in the next remote, but if it fails by\n        any other reason it has to stop\n        \"\"\"\n        servers = OrderedDict()\n        servers[\"s0\"] = TestServer()\n        servers[\"s1\"] = TestServer()\n        servers[\"s2\"] = TestServer()\n\n        client = TestClient(servers=servers)\n        client.save({\"conanfile.py\": GenConanfile(\"mylib\", \"0.1\")})\n        client.run(\"create . --user=lasote --channel=testing\")\n        client.run(\"remote login s1 admin -p password\")\n        client.run(\"upload mylib* -r s1 -c\")\n\n        servers[\"s1\"].fake_url = \"http://asdlhaljksdhlajkshdljakhsd.com\"  # Do not exist\n        client2 = TestClient(servers=servers)\n        client2.run(\"install --requires=mylib/0.1@conan/testing --build=missing\", assert_error=True)\n        assert \"mylib/0.1@conan/testing: Checking remote: s0\" in client2.out\n        assert \"mylib/0.1@conan/testing: Checking remote: s1\" in client2.out\n        assert \"Unable to connect to remote s1=http://asdlhaljksdhlajkshdljakhsd.com\" \\\n                      in client2.out\n        # s2 is not even tried\n        assert \"mylib/0.1@conan/testing: Trying with 's2'...\" not in client2.out\n\n    def test_install_from_remotes(self):\n        for i in range(3):\n            ref = RecipeReference.loads(\"hello%d/0.1@lasote/stable\" % i)\n            self.client.save({\"conanfile.py\": GenConanfile(\"hello%d\" % i, \"0.1\")})\n            self.client.run(\"export . --user=lasote --channel=stable\")\n            self.client.run(\"upload %s -r=remote%d\" % (str(ref), i))\n\n        # Now install it in other machine from remote 0\n        client2 = TestClient(servers=self.servers)\n\n        refs = [\"hello0/0.1@lasote/stable\", \"hello1/0.1@lasote/stable\", \"hello2/0.1@lasote/stable\"]\n        client2.save({\"conanfile.py\": GenConanfile(\"helloX\", \"0.1\").with_requires(*refs)})\n        client2.run(\"install . --build=missing\")\n        client2.assert_listed_require({\"hello0/0.1@lasote/stable\": \"Downloaded (remote0)\",\n                                       \"hello1/0.1@lasote/stable\": \"Downloaded (remote1)\",\n                                       \"hello2/0.1@lasote/stable\": \"Downloaded (remote2)\",\n                                       })\n"
  },
  {
    "path": "test/integration/remote/requester_test.py",
    "content": "from requests import Response\n\nfrom conan.test.utils.tools import TestClient, TestRequester\n\n\nconanfile = \"\"\"\nfrom conan import ConanFile\nfrom conan.tools.files import download\n\nclass HelloConan(ConanFile):\n    def source(self):\n        download(self, \"http://foo\", \"bar.txt\")\n\"\"\"\n\n\nclass MyRequester(TestRequester):\n\n    def get(self, _, **kwargs):\n        print(\"TIMEOUT: {}\".format(kwargs.get(\"timeout\", \"NOT SPECIFIED\")))\n        resp = Response()\n        resp.status_code = 200\n        resp._content = b''\n        return resp\n\n\nclass TestRequester:\n\n    def test_requester_timeout(self):\n        client = TestClient(requester_class=MyRequester)\n        client.save_home({\"global.conf\": \"core.net.http:timeout=4.3\"})\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --name=foo --version=1.0\")\n        assert \"TIMEOUT: 4.3\" in client.out\n\n    def test_requester_timeout_tuple(self):\n        client = TestClient(requester_class=MyRequester)\n        client.save_home({\"global.conf\": \"core.net.http:timeout=(2, 3.4)\"})\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --name=foo --version=1.0\")\n        assert \"TIMEOUT: (2, 3.4)\" in client.out\n\n    def test_request_infinite_timeout(self):\n        # Test that not having timeout works\n        client = TestClient(requester_class=MyRequester)\n        client.save_home({\"global.conf\": \"core.net.http:timeout=-1\"})\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --name=foo --version=1.0\")\n        assert \"TIMEOUT: NOT SPECIFIED\" in client.out\n\n    def test_unset_request_timeout_use_default_one(self):\n        client = TestClient(requester_class=MyRequester)\n        client.save_home({\"global.conf\": \"core.net.http:timeout=!\"})\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --name=foo --version=1.0\")\n        assert \"TIMEOUT: (30, 60)\" in client.out\n"
  },
  {
    "path": "test/integration/remote/rest_api_test.py",
    "content": "import os\nimport pytest\n\nfrom conan.api.model import Remote\nfrom conan.internal.model.conf import ConfDefinition\nfrom conan.internal.model.manifest import FileTreeManifest\nfrom conan.api.model import PkgReference\nfrom conan.api.model import RecipeReference\nfrom conan.internal.paths import CONANFILE, CONANINFO, CONAN_MANIFEST\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.env import environment_update\nfrom conan.test.utils.server_launcher import TestServerLauncher\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import get_free_port\nfrom conan.internal.rest.conan_requester import ConanRequester\nfrom conan.internal.rest.rest_client import RestApiClient\nfrom conan.internal.util.files import md5, save\n\n\nclass TestRestApi:\n    \"\"\"Open a real server (sockets) to test rest_api function.\"\"\"\n\n    @pytest.fixture(scope=\"class\", autouse=True)\n    def setup_class(self):\n        with environment_update({\"CONAN_SERVER_PORT\": str(get_free_port())}):\n            read_perms = [(\"*/*@*/*\", \"private_user\")]\n            write_perms = [(\"*/*@*/*\", \"private_user\")]\n            self.server = TestServerLauncher(server_capabilities=['ImCool', 'TooCool'],\n                                             read_permissions=read_perms,\n                                             write_permissions=write_perms)\n            self.server.start()\n\n            config = ConfDefinition()\n            requester = ConanRequester(config)\n\n            remote = Remote(\"myremote\", f\"http://127.0.0.1:{self.server.port}\", True, True)\n            self.api = RestApiClient(remote, None, requester, config)\n            self.api._token = self.api.authenticate(user=\"private_user\", password=\"private_pass\")\n            # Necessary for setup_class approach\n            TestRestApi.api = self.api\n            TestRestApi.server = self.server\n        yield\n\n        self.server.stop()\n        self.server.clean()\n\n    def test_get_conan(self):\n        # Upload a conans\n        ref = RecipeReference.loads(\"conan1/1.0.0@private_user/testing#myreciperev\")\n        self._upload_recipe(ref)\n\n        # Get the conans\n        tmp_dir = temp_folder()\n        self.api.get_recipe(ref, tmp_dir, metadata=None, only_metadata=False)\n        assert CONANFILE in os.listdir(tmp_dir)\n        assert CONAN_MANIFEST in os.listdir(tmp_dir)\n\n    def test_get_package(self):\n        # Upload a conans\n        ref = RecipeReference.loads(\"conan3/1.0.0@private_user/testing#myreciperev\")\n        self._upload_recipe(ref)\n\n        # Upload an package\n        pref = PkgReference(ref, \"1F23223EFDA2\", \"mypackagerev\")\n        self._upload_package(pref)\n\n        # Get the package\n        tmp_dir = temp_folder()\n        self.api.get_package(pref, tmp_dir, metadata=None, only_metadata=False)\n        # The hello.cpp file is not downloaded!\n        assert \"hello.cpp\" not in os.listdir(tmp_dir)\n\n    def test_upload_huge_conan(self):\n        ref = RecipeReference.loads(\"conanhuge/1.0.0@private_user/testing#myreciperev\")\n        self._upload_recipe(ref, {\"file9.cpp\": \"\"})\n\n        tmp = temp_folder()\n        files = self.api.get_recipe(ref, tmp, metadata=None, only_metadata=False)\n        assert files is not None\n        assert not os.path.exists(os.path.join(tmp, \"file9.cpp\"))\n\n    def test_search(self):\n        # Upload a conan1\n        conan_name1 = \"HelloOnly/0.10@private_user/testing#myreciperev\"\n        ref1 = RecipeReference.loads(conan_name1)\n        self._upload_recipe(ref1)\n\n        # Upload a package\n        conan_info = \"\"\"[settings]\n    arch=x86_64\n    compiler=gcc\n    os=Linux\n[options]\n    386=False\n[requires]\n    Hello\n    Bye/2.9\n    Say/2.1@user/testing\n    Chat/2.1@user/testing:SHA_ABC\n\"\"\"\n        pref = PkgReference(ref1, \"1F23223EFDA\", \"mypackagerev\")\n        self._upload_package(pref, {CONANINFO: conan_info})\n\n        # Upload a conan2\n        conan_name2 = \"helloonlyToo/2.1@private_user/stable#myreciperev\"\n        ref2 = RecipeReference.loads(conan_name2)\n        self._upload_recipe(ref2)\n\n        # Get the info about this ConanFileReference\n        info = self.api.search_packages(ref1)\n        assert conan_info == info[\"1F23223EFDA\"][\"content\"]\n\n        # Search packages\n        results = self.api.search(\"HelloOnly*\", ignorecase=False)\n        results = [RecipeReference(r.name, r.version, r.user, r.channel, revision=None)\n                   for r in results]\n        ref1.revision = None\n        assert results == [ref1]\n\n    def test_remove(self):\n        # Upload a conans\n        ref = RecipeReference.loads(\"MyFirstConan/1.0.0@private_user/testing#myreciperev\")\n        self._upload_recipe(ref)\n        ref.revision = \"myreciperev\"\n        path1 = self.server.server_store.base_folder(ref)\n        assert os.path.exists(path1)\n        # Remove conans and packages\n        self.api.remove_recipe(ref)\n        assert not os.path.exists(path1)\n\n    def test_remove_packages(self):\n        ref = RecipeReference.loads(\"MySecondConan/2.0.0@private_user/testing#myreciperev\")\n        self._upload_recipe(ref)\n\n        folders = {}\n        for sha in [\"1\", \"2\", \"3\", \"4\", \"5\"]:\n            # Upload an package\n            pref = PkgReference(ref, sha, \"mypackagerev\")\n            self._upload_package(pref, {CONANINFO: \"\"})\n            folder = self.server.server_store.package(pref)\n            assert os.path.exists(folder)\n            folders[sha] = folder\n\n        data = self.api.search_packages(ref)\n        assert len(data) == 5\n\n        self.api.remove_packages([PkgReference(ref, \"1\")])\n        assert os.path.exists(self.server.server_store.base_folder(ref))\n        assert not os.path.exists(folders[\"1\"])\n        assert os.path.exists(folders[\"2\"])\n        assert os.path.exists(folders[\"3\"])\n        assert os.path.exists(folders[\"4\"])\n        assert os.path.exists(folders[\"5\"])\n\n        self.api.remove_packages([PkgReference(ref, \"2\"), PkgReference(ref, \"3\")])\n        assert os.path.exists(self.server.server_store.base_folder(ref))\n        assert not os.path.exists(folders[\"1\"])\n        assert not os.path.exists(folders[\"2\"])\n        assert not os.path.exists(folders[\"3\"])\n        assert os.path.exists(folders[\"4\"])\n        assert os.path.exists(folders[\"5\"])\n\n        self.api.remove_all_packages(ref)\n        assert os.path.exists(self.server.server_store.base_folder(ref))\n        for sha in [\"1\", \"2\", \"3\", \"4\", \"5\"]:\n            assert not os.path.exists(folders[sha])\n\n    def _upload_package(self, package_reference, base_files=None):\n\n        files = {\"conanfile.py\": GenConanfile(\"3\").with_requires(\"1\", \"12\").with_exports(\"*\"),\n                 \"hello.cpp\": \"hello\",\n                 \"conanmanifest.txt\": \"\",\n                 \"conan_package.tgz\": \"\"}\n        if base_files:\n            files.update(base_files)\n\n        tmp_dir = temp_folder()\n        abs_paths = {}\n        for filename, content in files.items():\n            abs_path = os.path.join(tmp_dir, filename)\n            save(abs_path, str(content))\n            abs_paths[filename] = abs_path\n\n        self.api.upload_package(package_reference, abs_paths)\n\n    def _upload_recipe(self, ref, base_files=None):\n\n        files = {\"conanfile.py\": GenConanfile(\"3\").with_requires(\"1\", \"12\")}\n        if base_files:\n            files.update(base_files)\n        content = \"\"\"\nfrom conan import ConanFile\n\nclass MyConan(ConanFile):\n    name = \"%s\"\n    version = \"%s\"\n    settings = arch, compiler, os\n\"\"\" % (ref.name, ref.version)\n        files[CONANFILE] = content\n        files_md5s = {filename: md5(content) for filename, content in files.items()}\n        conan_digest = FileTreeManifest(123123123, files_md5s)\n\n        tmp_dir = temp_folder()\n        abs_paths = {}\n        for filename, content in files.items():\n            abs_path = os.path.join(tmp_dir, filename)\n            save(abs_path, content)\n            abs_paths[filename] = abs_path\n        abs_paths[CONAN_MANIFEST] = os.path.join(tmp_dir, CONAN_MANIFEST)\n        conan_digest.save(tmp_dir)\n\n        self.api.upload_recipe(ref, abs_paths)\n"
  },
  {
    "path": "test/integration/remote/retry_test.py",
    "content": "import os\nimport pytest\nfrom collections import namedtuple, Counter\n\nfrom requests.exceptions import HTTPError\n\nfrom conan.internal.rest.file_uploader import FileUploader\nfrom conan.internal.errors import AuthenticationException, ForbiddenException\nfrom conan.test.utils.mocks import RedirectedTestOutput\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import redirect_output\nfrom conan.internal.util.files import save\n\n\nclass _ResponseMock:\n    def __init__(self, status_code, content):\n        self.status_code = status_code\n        self.content = content\n\n    def raise_for_status(self):\n        \"\"\"Raises stored :class:`HTTPError`, if one occurred.\"\"\"\n        http_error_msg = ''\n        if 500 <= self.status_code < 600:\n            http_error_msg = u'%s Server Error: %s' % (self.status_code, self.content)\n\n        if http_error_msg:\n            raise HTTPError(http_error_msg, response=self)\n\n\nclass _RequesterMock:\n    def __init__(self, status_code, content):\n        self.response = _ResponseMock(status_code, content)\n        self.retry = 0\n        self.retry_wait = 0\n\n    def put(self, *args, **kwargs):\n        return self.response\n\n\nclass _ConfigMock:\n\n    def get(self, conf_name, default=None, check_type=None):  # noqa\n        return 0\n\n\nclass TestRetryDownload:\n\n    @pytest.fixture(autouse=True)\n    def setup(self):\n        self.filename = os.path.join(temp_folder(), \"anyfile\")\n        save(self.filename, \"anything\")\n\n    def test_error_401(self):\n        output = RedirectedTestOutput()\n        with redirect_output(output):\n            uploader = FileUploader(requester=_RequesterMock(401, \"content\"),\n                                    verify=False, config=_ConfigMock())\n            with pytest.raises(AuthenticationException, match=\"content\"):\n                uploader.upload(url=\"fake\", abs_path=self.filename, retry=2)\n            output_lines = output.getvalue().splitlines()\n            counter = Counter(output_lines)\n            assert counter[\"ERROR: content\"] == 0\n            assert counter[\"Waiting 0 seconds to retry...\"] == 0\n\n    def test_error_403_forbidden(self):\n        output = RedirectedTestOutput()\n        with redirect_output(output):\n            uploader = FileUploader(requester=_RequesterMock(403, \"content\"),\n                                    verify=False, config=_ConfigMock())\n            with pytest.raises(ForbiddenException, match=\"content\"):\n                auth = namedtuple(\"auth\", \"bearer\")\n                uploader.upload(url=\"fake\", abs_path=self.filename, retry=2, auth=auth(\"token\"))\n            output_lines = output.getvalue().splitlines()\n            counter = Counter(output_lines)\n            assert counter[\"ERROR: content\"] == 0\n            assert counter[\"Waiting 0 seconds to retry...\"] == 0\n\n    def test_error_403_authentication(self):\n        output = RedirectedTestOutput()\n        with redirect_output(output):\n            uploader = FileUploader(requester=_RequesterMock(403, \"content\"),\n                                    verify=False, config=_ConfigMock())\n            with pytest.raises(AuthenticationException, match=\"content\"):\n                auth = namedtuple(\"auth\", \"bearer\")\n                uploader.upload(url=\"fake\", abs_path=self.filename, retry=2, auth=auth(None))\n            output_lines = output.getvalue().splitlines()\n            counter = Counter(output_lines)\n            assert counter[\"ERROR: content\"] == 0\n            assert counter[\"Waiting 0 seconds to retry...\"] == 0\n\n    def test_error_requests(self):\n        class _RequesterExcp:\n\n            def put(self, *args, **kwargs):\n                raise Exception(\"any exception\")\n\n        output = RedirectedTestOutput()\n        with redirect_output(output):\n            uploader = FileUploader(requester=_RequesterExcp(), verify=False, config=_ConfigMock())\n            with pytest.raises(Exception, match=\"any exception\"):\n                uploader.upload(url=\"fake\", abs_path=self.filename, retry=2)\n            output_lines = output.getvalue().splitlines()\n            counter = Counter(output_lines)\n            assert counter[\"WARN: network: any exception\"] == 2\n            assert counter[\"Waiting 0 seconds to retry...\"] == 2\n\n    def test_error_500(self):\n        output = RedirectedTestOutput()\n        with redirect_output(output):\n            uploader = FileUploader(requester=_RequesterMock(500, \"content\"), verify=False,\n                                    config=_ConfigMock())\n            with pytest.raises(Exception, match=\"500 Server Error: content\"):\n                uploader.upload(url=\"fake\", abs_path=self.filename, retry=2)\n            output_lines = output.getvalue().splitlines()\n            counter = Counter(output_lines)\n            assert counter[\"WARN: network: 500 Server Error: content\"] == 2\n            assert counter[\"Waiting 0 seconds to retry...\"] == 2\n"
  },
  {
    "path": "test/integration/remote/selected_remotes_test.py",
    "content": "from collections import OrderedDict\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient, TestServer\n\n\nclass TestSelectedRemotesInstall:\n    @pytest.fixture(autouse=True)\n    def _setup(self):\n        servers = OrderedDict()\n        for index in range(3):\n            servers[f\"server{index}\"] = TestServer([(\"*/*@*/*\", \"*\")], [(\"*/*@*/*\", \"*\")],\n                                                   users={\"user\": \"password\"})\n        self.client = TestClient(servers=servers, inputs=3 * [\"user\", \"password\"])\n\n    def test_selected_remotes(self):\n        self.client.save({\"conanfile.py\": GenConanfile(\"liba\", \"1.0\").with_build_msg(\"OLDREV\")})\n        self.client.run(\"create .\")\n        self.client.run(\"upload liba/1.0 -r server0 -c\")\n        self.client.run(\"remove * -c\")\n        self.client.save({\"conanfile.py\": GenConanfile(\"liba\", \"1.0\").with_build_msg(\"NEWER_REV\")})\n        self.client.run(\"create .\")\n        self.client.run(\"upload liba/1.0 -r server1 -c\")\n        self.client.run(\"remove * -c\")\n\n        self.client.run(\"install --requires=liba/1.0 -r server0 -r server1 --build='*'\")\n        # we install the revision from the server with more preference\n        assert \"OLDREV\" in self.client.out\n        self.client.run(\"remove * -c\")\n        self.client.run(\"install --requires=liba/1.0 -r server1 -r server0 --build='*'\")\n        # changing the order of the remotes in the arguments does change the result\n        # we install the revision from the server with more preference\n        assert \"NEWER_REV\" in self.client.out\n        # select two remotes, just one has liba, will install the rev from that one\n        self.client.run(\"remove * -c\")\n        self.client.run(\"install --requires=liba/1.0 -r server2 -r server1 --build='*'\")\n        assert \"NEWER_REV\" in self.client.out\n\n        self.client.save({\"consumer.py\": GenConanfile().with_require(\"liba/1.0\")})\n        self.client.run(\"remove * -c\")\n        self.client.run(\"create . --build='*' -r server0 -r server1 -r server2\")\n        assert \"NEWER_REV\" in self.client.out\n\n    def test_upload_raise_multiple_remotes(self):\n        self.client.run(\"upload liba -r server0 -r server1 -c\", assert_error=True)\n        assert \"conan upload: error: -r can only be specified once\" in self.client.out\n\n    def test_remove_raise_multiple_remotes(self):\n        self.client.run(\"remove liba -r server0 -r server1 -c\", assert_error=True)\n        assert \"conan remove: error: -r can only be specified once\" in self.client.out\n"
  },
  {
    "path": "test/integration/remote/server_error_test.py",
    "content": "from requests import Response\n\nfrom conan.internal import REVISIONS\nfrom conan.test.utils.tools import TestClient, TestServer, TestRequester\nfrom collections import namedtuple\n\n\nclass TestError200NoJson:\n\n    def test_error_no_json(self):\n        class RequesterMock(TestRequester):\n            def get(self, *args, **kwargs):  # @UnusedVariable\n                # Response must be binary, it is decoded in RestClientCommon\n                headers = {\"X-Conan-Server-Capabilities\": REVISIONS}\n                return namedtuple(\"Response\", \"status_code headers content ok\")(200, headers, b'<>',\n                                                                                True)\n        # https://github.com/conan-io/conan/issues/3432\n        client = TestClient(servers={\"default\": TestServer()},\n                            requester_class=RequesterMock,\n                            inputs=[\"admin\", \"password\"])\n\n        client.run(\"install --requires=pkg/ref@user/testing\", assert_error=True)\n        assert \"Response from remote is not json, but 'None'\" in client.out\n\n    def test_error_broken_json(self):\n        class RequesterMock(TestRequester):\n            def get(self, *args, **kwargs):  # @UnusedVariable\n                # Response must be binary, it is decoded in RestClientCommon\n                headers = {\"Content-Type\": \"application/json\",\n                           \"X-Conan-Server-Capabilities\": REVISIONS}\n                return namedtuple(\"Response\", \"status_code headers content ok\")(200, headers,\n                                                                                b'<>', True)\n\n        # https://github.com/conan-io/conan/issues/3432\n        client = TestClient(servers={\"default\": TestServer()},\n                            requester_class=RequesterMock,\n                            inputs=[\"admin\", \"password\"])\n\n        client.run(\"install --requires=pkg/ref@user/testing\", assert_error=True)\n        assert \"Remote responded with broken json: <>\" in client.out\n\n    def test_error_json(self):\n        class RequesterMock(TestRequester):\n\n            def get(self, *args, **kwargs):  # @UnusedVariable\n                # Response must be binary, it is decoded in RestClientCommon\n                headers = {\"Content-Type\": \"application/json\",\n                           \"X-Conan-Server-Capabilities\": REVISIONS}\n                return namedtuple(\"Response\", \"status_code headers content ok\")(200, headers,\n                                                                                b'[1, 2, 3]', True)\n\n        # https://github.com/conan-io/conan/issues/3432\n        client = TestClient(servers={\"default\": TestServer()},\n                            requester_class=RequesterMock,\n                            inputs=[\"admin\", \"password\"])\n\n        client.run(\"install --requires=pkg/ref@user/testing\", assert_error=True)\n        assert \"Unexpected server response [1, 2, 3]\" in client.out\n\n\ndef test_unrecongized_exception():\n    class BuggyRequester(TestRequester):\n        def get(self, *args, **kwargs):\n            resp = Response()\n            resp.status_code = 444\n            resp._content = 'some 444 error message'\n            return resp\n\n    c = TestClient(default_server_user=True, requester_class=BuggyRequester)\n    c.run(\"install --requires=zlib/1.2 -r=default\", assert_error=True)\n    assert (\"ERROR: Package 'zlib/1.2' not resolved: Server exception 444:\"\n            \" some 444 error message\") in c.out\n"
  },
  {
    "path": "test/integration/remote/test_conaninfo_parsing.py",
    "content": "# coding=utf-8\n\nimport textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.artifactory_ready\ndef test_conaninfo_special_chars():\n\n    t = TestClient(default_server_user=True)\n    conanfile = textwrap.dedent(\"\"\"\n    # coding=utf-8\n    from conan import ConanFile\n\n    class Recipe(ConanFile):\n        name = \"weird_info\"\n        version = \"1.0\"\n        options = {\"ññ¨¨&是\": ['是\"是', '][{}\"是是是']}\n        default_options = {\"ññ¨¨&是\": '][{}\"是是是'}\n    \"\"\")\n\n    t.save({\"conanfile.py\": conanfile})\n    t.run(\"create . \")\n    t.run('list weird_info/1.0:*')\n    assert 'ññ¨¨&是: ][{}\"是是是' in t.out\n\n    t.run(\"upload * -c -r default\")\n    # TODO: I have struggled with this, it was not accepting \"latest\", revision needs explicit one\n    t.run('list weird_info/1.0#8c9e59246220eef8ca3bd4ac4f39ceb3:* -r default')\n    assert 'ññ¨¨&是: ][{}\"是是是' in t.out\n"
  },
  {
    "path": "test/integration/remote/test_local_recipes_index.py",
    "content": "import json\nimport os\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import mkdir, save, save_files\n\n\n@pytest.fixture(scope=\"module\")\ndef c3i_folder():\n    folder = temp_folder()\n    recipes_folder = os.path.join(folder, \"recipes\")\n    zlib_config = textwrap.dedent(\"\"\"\n        versions:\n          \"1.2.8\":\n            folder: all\n          \"1.2.11\":\n            folder: all\n        \"\"\")\n    zlib = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import load\n        class Zlib(ConanFile):\n            name = \"zlib\"\n            exports_sources = \"*\"\n            def build(self):\n                self.output.info(f\"CONANDATA: {self.conan_data}\")\n                self.output.info(f\"BUILDING: {load(self, 'file.h')}\")\n            \"\"\")\n    save_files(recipes_folder,\n               {\"zlib/config.yml\": zlib_config,\n                \"zlib/all/conanfile.py\": zlib,\n                \"zlib/all/conandata.yml\": \"\",\n                \"zlib/all/file.h\": \"//myheader\"})\n    mkdir(os.path.join(recipes_folder, \"openssl\", \"1.X\"))\n    mkdir(os.path.join(recipes_folder, \"openssl\", \"2.X\"))\n    save(os.path.join(recipes_folder, \"openssl\", \"config.yml\"), textwrap.dedent(\"\"\"\n        versions:\n          \"1.0\":\n            folder: \"1.X\"\n          \"1.1\":\n            folder: \"1.X\"\n          \"2.0\":\n            folder: \"2.X\"\n        \"\"\"))\n    save(os.path.join(recipes_folder, \"openssl\", \"1.X\", \"conanfile.py\"),\n         str(GenConanfile().with_require(\"zlib/1.2.8\")))\n    save(os.path.join(recipes_folder, \"openssl\", \"2.X\", \"conanfile.py\"),\n         str(GenConanfile().with_require(\"zlib/1.2.11\")))\n    mkdir(os.path.join(recipes_folder, \"libcurl\", \"all\"))\n    save(os.path.join(recipes_folder, \"libcurl\", \"config.yml\"), textwrap.dedent(\"\"\"\n            versions:\n              \"1.0\":\n                folder: \"all\"\n            \"\"\"))\n    save(os.path.join(recipes_folder, \"libcurl\", \"all\", \"conanfile.py\"),\n         str(GenConanfile().with_require(\"openssl/2.0\")))\n\n    save(os.path.join(recipes_folder, \".DS_Store\", \"foo\"), \"\")\n\n    return folder\n\n\nclass TestSearchList:\n    def test_basic_search(self, c3i_folder):\n        client = TestClient(light=True)\n        client.run(f\"remote add local '{c3i_folder}' --type=local-recipes-index\")  # Keep --type test\n        assert \"WARN\" not in client.out  # Make sure it does not complain about url\n        client.run(\"search *\")\n        assert textwrap.dedent(\"\"\"\\\n            local\n              libcurl\n                libcurl/1.0\n              openssl\n                openssl/1.0\n                openssl/1.1\n                openssl/2.0\n              zlib\n                zlib/1.2.8\n                zlib/1.2.11\n            \"\"\") in client.out\n\n    def test_list_refs(self, c3i_folder):\n        client = TestClient(light=True)\n        client.run(f\"remote add local '{c3i_folder}'\")\n        client.run(\"list *#* -r=local --format=json\")\n        listjson = json.loads(client.stdout)\n        revs = listjson[\"local\"][\"libcurl/1.0\"][\"revisions\"]\n        assert len(revs) == 1 and \"e468388f0e4e098d5b62ad68979aebd5\" in revs\n        revs = listjson[\"local\"][\"openssl/1.0\"][\"revisions\"]\n        assert len(revs) == 1 and \"b35ffb31b6d5a9d8af39f5de3cf4fd63\" in revs\n        revs = listjson[\"local\"][\"openssl/1.1\"][\"revisions\"]\n        assert len(revs) == 1 and \"b35ffb31b6d5a9d8af39f5de3cf4fd63\" in revs\n        revs = listjson[\"local\"][\"openssl/2.0\"][\"revisions\"]\n        assert len(revs) == 1 and \"e50e871efca149f160fa6354c8534449\" in revs\n        revs = listjson[\"local\"][\"zlib/1.2.8\"][\"revisions\"]\n        assert len(revs) == 1 and \"6f5c31bb1219e9393743d1fbf2ee1b52\" in revs\n        revs = listjson[\"local\"][\"zlib/1.2.11\"][\"revisions\"]\n        assert len(revs) == 1 and \"6f5c31bb1219e9393743d1fbf2ee1b52\" in revs\n\n    def test_list_revisions_notfound(self, c3i_folder):\n        client = TestClient(light=True)\n        client.run(f\"remote add local '{c3i_folder}'\")\n        client.run(\"list potato/1.0#* -r=local\")\n        # More like remotes than cache\n        assert \"ERROR: Recipe not found: 'potato/1.0'\"\n\n    def test_list_rrevs(self, c3i_folder):\n        client = TestClient(light=True)\n        client.run(f\"remote add local '{c3i_folder}'\")\n        client.run(\"list libcurl/1.0#* -r=local --format=json\")\n        listjson = json.loads(client.stdout)\n        revs = listjson[\"local\"][\"libcurl/1.0\"][\"revisions\"]\n        assert len(revs) == 1 and \"e468388f0e4e098d5b62ad68979aebd5\" in revs\n\n    def test_list_binaries(self, c3i_folder):\n        client = TestClient(light=True)\n        client.run(f\"remote add local '{c3i_folder}'\")\n        client.run(\"list libcurl/1.0:* -r=local --format=json\")\n        listjson = json.loads(client.stdout)\n        rev = listjson[\"local\"][\"libcurl/1.0\"][\"revisions\"][\"e468388f0e4e098d5b62ad68979aebd5\"]\n        assert rev[\"packages\"] == {}\n\n\nclass TestInstall:\n    def test_install(self, c3i_folder):\n        c = TestClient(light=True)\n        c.run(f\"remote add local '{c3i_folder}'\")\n        c.run(\"install --requires=libcurl/1.0 --build missing\")\n        assert \"zlib/1.2.11: CONANDATA: {}\" in c.out\n        assert \"zlib/1.2.11: BUILDING: //myheader\" in c.out\n        bins = {\"libcurl/1.0\": (\"aa69c1e1e39a18fe70001688213dbb7ada95f890\", \"Build\"),\n                \"openssl/2.0\": (\"594ed0eb2e9dfcc60607438924c35871514e6c2a\", \"Build\"),\n                \"zlib/1.2.11\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\", \"Build\")}\n        c.assert_listed_binary(bins)\n\n        # Already installed in the cache\n        c.run(\"install --requires=libcurl/1.0\")\n        assert \"zlib/1.2.11: Already installed!\" in c.out\n        assert \"openssl/2.0: Already installed!\" in c.out\n        assert \"libcurl/1.0: Already installed!\" in c.out\n\n        # Update doesn't fail, but doesn't update revision time\n        c.run(\"install --requires libcurl/1.0 --update\")\n        bins = {\"libcurl/1.0\": \"Cache (Updated date) (local)\",\n                \"openssl/2.0\": \"Cache (Updated date) (local)\",\n                \"zlib/1.2.11\": \"Cache (Updated date) (local)\"}\n\n        c.assert_listed_require(bins)\n        assert \"zlib/1.2.11: Already installed!\" in c.out\n        assert \"openssl/2.0: Already installed!\" in c.out\n        assert \"libcurl/1.0: Already installed!\" in c.out\n\n        # Doing local changes creates a new revision\n        # New recipe revision for the zlib library\n        save(os.path.join(c3i_folder, \"recipes\", \"zlib\", \"all\", \"conanfile.py\"),\n             str(GenConanfile()) + \"\\n\")\n        c.run(\"install --requires=libcurl/1.0 --build missing --update\")\n        # it is updated\n        assert \"zlib/1.2.11#dd82451a95902c89bb66a2b980c72de5 - Updated (local)\" in c.out\n\n    def test_install_with_exported_files(self):\n        folder = temp_folder()\n        recipes_folder = os.path.join(folder, \"recipes\")\n        boost_config = textwrap.dedent(\"\"\"\n            versions:\n              \"1.0\":\n                folder: all\n            \"\"\")\n        boost = textwrap.dedent(\"\"\"\n            import os\n            from conan.tools.files import load\n            from conan import ConanFile\n            class Boost(ConanFile):\n                name = \"boost\"\n                version = \"1.0\"\n                exports = \"*\"\n                def source(self):\n                    myfile = os.path.join(self.recipe_folder, \"dependencies\", \"myfile.json\")\n                    self.output.info(load(self, myfile))\n                \"\"\")\n        deps_json = '{\"potato\": 42}'\n        save_files(recipes_folder,\n                   {\"boost/config.yml\": boost_config,\n                    \"boost/all/conanfile.py\": boost,\n                    \"boost/all/dependencies/myfile.json\": deps_json})\n        c = TestClient(light=True)\n        c.run(f\"remote add local '{folder}'\")\n        c.run(\"install --requires=boost/[*] --build missing\")\n        assert 'boost/1.0: {\"potato\": 42}' in c.out\n\n    def test_trim_conandata_yaml(self):\n        folder = temp_folder()\n        recipes_folder = os.path.join(folder, \"recipes\")\n        config = textwrap.dedent(\"\"\"\n            versions:\n              \"1.0\":\n                folder: all\n            \"\"\")\n        conandata = textwrap.dedent(\"\"\"\\\n            sources:\n              \"1.0\":\n                url:\n                sha256: \"ff0ba4c292013dbc27530b3a81e1f9a813cd39de01ca5e0f8bf355702efa593e\"\n            patches:\n              \"1.0\":\n                - patch_file: \"patches/1.3/0001-fix-cmake.patch\"\n            \"\"\")\n        save_files(recipes_folder,\n                   {\"pkg/config.yml\": config,\n                    \"pkg/all/conanfile.py\": str(GenConanfile(\"pkg\")),\n                    \"pkg/all/conandata.yml\": conandata})\n        c = TestClient(light=True)\n        c.run(f\"remote add local '{folder}'\")\n        c.run(\"install --requires=pkg/1.0 --build missing -vvv\")\n        assert \"pkg/1.0#86b609916bbdfe63c579f034ad0edfe7\" in c.out\n\n        # User modifies conandata.yml to add new version\n        new_conandata = textwrap.dedent(\"\"\"\\\n            sources:\n              \"1.0\":\n                url:\n                sha256: \"ff0ba4c292013dbc27530b3a81e1f9a813cd39de01ca5e0f8bf355702efa593e\"\n              \"1.1\":\n                url:\n            patches:\n              \"1.0\":\n                - patch_file: \"patches/1.3/0001-fix-cmake.patch\"\n            \"\"\")\n        save_files(recipes_folder, {\"pkg/all/conandata.yml\": new_conandata})\n        c.run(\"install --requires=pkg/1.0 --build missing --update -vvv\")\n        assert \"pkg/1.0#86b609916bbdfe63c579f034ad0edfe7\" in c.out\n\n    def test_export_patches(self):\n        folder = temp_folder()\n        recipes_folder = os.path.join(folder, \"recipes\")\n        zlib_config = textwrap.dedent(\"\"\"\n            versions:\n              \"0.1\":\n                folder: all\n            \"\"\")\n        zlib = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import export_conandata_patches, apply_conandata_patches\n            class Zlib(ConanFile):\n                name = \"zlib\"\n                exports_sources = \"*.cpp\"\n                def export_sources(self):\n                    export_conandata_patches(self)\n\n                def source(self):\n                    apply_conandata_patches(self)\n                    \"\"\")\n        conandata_yml = textwrap.dedent(\"\"\"\\\n            versions:\n              \"0.1\":\n            patches:\n              \"0.1\":\n                - patch_file: \"patches/patch1\"\n                    \"\"\")\n        patch = textwrap.dedent(\"\"\"\\\n            --- a/main.cpp\n            +++ b/main.cpp\n            @@ -0,0 +1 @@\n            +hello\n            \"\"\")\n        save_files(recipes_folder,\n                   {\"zlib/config.yml\": zlib_config,\n                    \"zlib/all/conanfile.py\": zlib,\n                    \"zlib/all/conandata.yml\": conandata_yml,\n                    \"zlib/all/patches/patch1\": patch,\n                    \"zlib/all/main.cpp\": \"\\n\"})\n        client = TestClient(light=True)\n        client.run(f\"remote add local '{folder}'\")\n        client.run(\"install --requires=zlib/0.1 --build=missing -vv\")\n        assert \"zlib/0.1: Copied 1 file: patch1\" in client.out\n        assert \"zlib/0.1: Apply patch (file): patches/patch1\" in client.out\n\n    def test_export_user_channel(self):\n        folder = temp_folder()\n        recipes_folder = os.path.join(folder, \"recipes\")\n        zlib_config = textwrap.dedent(\"\"\"\n            versions:\n              \"0.1\":\n                folder: all\n            \"\"\")\n        zlib = GenConanfile(\"zlib\").with_class_attribute(\"user='myuser'\")\\\n                                   .with_class_attribute(\"channel='mychannel'\")\n        conandata_yml = textwrap.dedent(\"\"\"\\\n            versions:\n              \"0.1\":\n            \"\"\")\n        save_files(recipes_folder, {\"zlib/config.yml\": zlib_config,\n                                    \"zlib/all/conanfile.py\": str(zlib),\n                                    \"zlib/all/conandata.yml\": conandata_yml})\n        client = TestClient()\n        client.run(f\"remote add local '{folder}'\")\n        client.run(\"install --requires=zlib/0.1@myuser/mychannel --build=missing\")\n        assert \"zlib/0.1@myuser/mychannel:\" in client.out\n        client.run(\"list * -r=local\")\n        assert \"zlib/0.1@myuser/mychannel\" in client.out\n\n\nclass TestRestrictedOperations:\n    def test_upload(self):\n        folder = temp_folder()\n        c3i_folder = os.path.join(folder, \"recipes\")\n        mkdir(c3i_folder)\n        c = TestClient(light=True)\n        c.run(f\"remote add local '{c3i_folder}'\")\n        c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n        c.run(\"create .\")\n        c.run(\"upload pkg/0.1 -r=local\", assert_error=True)\n        assert \"ERROR: Remote local-recipes-index 'local' doesn't support upload\" in c.out\n\n\nclass TestErrorsUx:\n    def test_errors(self):\n        folder = temp_folder()\n        recipes_folder = os.path.join(folder, \"recipes\")\n        zlib_config = textwrap.dedent(\"\"\"\n            versions:\n              \"1.2.11\":\n                folder: all\n            \"\"\")\n        zlib = textwrap.dedent(\"\"\"\n            class Zlib(ConanFile):\n                name = \"zlib\"\n                \"\"\")\n        save_files(recipes_folder,\n                   {\"zlib/config.yml\": zlib_config,\n                    \"zlib/all/conanfile.py\": zlib})\n        c = TestClient(light=True)\n        c.run(f\"remote add local '{folder}'\")\n        c.run(\"install --requires=zlib/[*] --build missing\", assert_error=True)\n        assert \"NameError: name 'ConanFile' is not defined\" in c.out\n\n    def test_require_revision(self):\n        # https://github.com/conan-io/conan/issues/17814\n        folder = temp_folder()\n        recipes_folder = os.path.join(folder, \"recipes\")\n        zlib_config = textwrap.dedent(\"\"\"\n           versions:\n             \"1.2.11\":\n               folder: all\n           \"\"\")\n        save_files(recipes_folder,\n                   {\"zlib/config.yml\": zlib_config,\n                    \"zlib/all/conanfile.py\": str(GenConanfile(\"zlib\"))})\n        c = TestClient(light=True)\n        c.run(f\"remote add local '{folder}'\")\n        c.run(\"install --requires=zlib/1.2.11#rev1\", assert_error=True)\n        assert \"A specific revision 'zlib/1.2.11#rev1' was requested\" in c.out\n\n    def test_no_user_channel(self):\n        # https://github.com/conan-io/conan/issues/18142\n        folder = temp_folder()\n        recipes_folder = os.path.join(folder, \"recipes\")\n        zlib_config = textwrap.dedent(\"\"\"\n          versions:\n            \"0.1\":\n              folder: all\n          \"\"\")\n        zlib = GenConanfile(\"zlib\")\n        conandata_yml = textwrap.dedent(\"\"\"\\\n          versions:\n            \"0.1\":\n          \"\"\")\n        save_files(recipes_folder, {\"zlib/config.yml\": zlib_config,\n                                    \"zlib/all/conanfile.py\": str(zlib),\n                                    \"zlib/all/conandata.yml\": conandata_yml})\n        c = TestClient()\n        c.run(f\"remote add local '{folder}'\")\n        c.run(\"install --requires=zlib/0.1@myuser/mychannel\", assert_error=True)\n        assert \"ERROR: Package 'zlib/0.1@myuser/mychannel' not resolved\" in c.out\n\n        c = TestClient(default_server_user=True)\n        c.save({\"conanfile.py\": GenConanfile(\"zlib\", \"0.1\")})\n        c.run(\"create . --user=myuser --channel=mychannel\")\n        c.run(\"upload * -r=default -c\")\n        c.run(f\"remote add local '{folder}' --index=0\")\n        c.run(\"install --requires=zlib/0.1@myuser/mychannel\")\n        c.assert_listed_require({\"zlib/0.1@myuser/mychannel\": \"Cache\"})\n\n        # Force resolving in remotes\n        c.run(\"remove * -c\")\n        c.run(\"install --requires=zlib/0.1@myuser/mychannel\")\n        c.assert_listed_require({\"zlib/0.1@myuser/mychannel\": \"Downloaded (default)\"})\n\n    def test_errors_missing_folder(self):\n        folder = temp_folder()\n        repo = os.path.join(folder, \"repo\")\n        mkdir(repo)\n        c = TestClient(light=True)\n        c.run(f\"remote add local '{repo}'\")\n        # shutil.rmtree(repo)\n        c.run(\"install --requires=zlib/[*] --build missing\", assert_error=True)\n        assert \"Cannot connect to 'local-recipes-index' repository, missing 'recipes'\" in c.out\n\n\nclass TestPythonRequires:\n    @pytest.fixture(scope=\"class\")\n    def c3i_pyrequires_folder(self):\n        folder = temp_folder()\n        recipes_folder = os.path.join(folder, \"recipes\")\n        config = textwrap.dedent(\"\"\"\n            versions:\n              \"1.0\":\n                folder: all\n            \"\"\")\n        pkg = str(GenConanfile(\"pkg\").with_python_requires(\"pyreq/1.0\"))\n        save_files(recipes_folder,\n                   {\"pkg/config.yml\": config,\n                    \"pkg/all/conanfile.py\": pkg,\n                    \"pyreq/config.yml\": config,\n                    \"pyreq/all/conanfile.py\": str(GenConanfile(\"pyreq\", \"1.0\"))})\n        return folder\n\n    def test_install(self, c3i_pyrequires_folder):\n        c = TestClient(light=True)\n        c.run(f\"remote add local '{c3i_pyrequires_folder}'\")\n        c.run(\"list * -r=local\")\n        assert \"pyreq/1.0\" in c.out\n        assert \"pkg/1.0\" in c.out\n        c.run(\"install --requires=pkg/1.0 --build missing -vvv\")\n        assert \"pyreq/1.0#a0d63ca853edefa33582a24a1bb3c75f - Downloaded (local)\" in c.out\n        assert \"pkg/1.0: Created package\" in c.out\n\n\nclass TestUserChannel:\n    @pytest.fixture(scope=\"class\")\n    def c3i_user_channel_folder(self):\n        folder = temp_folder()\n        recipes_folder = os.path.join(folder, \"recipes\")\n        config = textwrap.dedent(\"\"\"\n                versions:\n                  \"1.0\":\n                    folder: all\n                  \"2.0\":\n                    folder: other\n                \"\"\")\n        pkg = str(GenConanfile(\"pkg\").with_class_attribute(\"user='myuser'\")\n                                     .with_class_attribute(\"channel='mychannel'\"))\n        save_files(recipes_folder,\n                   {\"pkg/config.yml\": config,\n                    \"pkg/all/conanfile.py\": pkg,\n                    \"pkg/other/conanfile.py\": str(GenConanfile(\"pkg\"))})\n        return folder\n\n    def test_user_channel_requirement(self, c3i_user_channel_folder):\n        tc = TestClient(light=True)\n        tc.run(f\"remote add local '{c3i_user_channel_folder}'\")\n        tc.run(\"graph info --requires=pkg/[*]@myuser/mychannel\")\n        assert \"Version range '*' from requirement 'pkg/[*]@myuser/mychannel'\" not in tc.out\n        assert \"pkg/[*]@myuser/mychannel: pkg/1.0@myuser/mychannel\" in tc.out\n        assert \"pkg/1.0@myuser/mychannel#0b23a5938afb0457079e41aac8991595 - Downloaded (local)\" in tc.out\n\n    @pytest.mark.parametrize(\"user_channel\", [\"@foo/bar\", \"@foo\"])\n    def test_user_channel_requirement_no_match(self, c3i_user_channel_folder, user_channel):\n        tc = TestClient(light=True)\n        tc.run(f\"remote add local '{c3i_user_channel_folder}'\")\n        tc.run(f\"graph info --requires=pkg/[*]{user_channel}\", assert_error=True)\n        assert f\"Version range '*' from requirement 'pkg/[*]{user_channel}' required by 'None' could not be resolved.\" in tc.out\n\n    def test_user_channel_requirement_only_at(self, c3i_user_channel_folder):\n        tc = TestClient(light=True)\n        tc.run(f\"remote add local '{c3i_user_channel_folder}'\")\n        tc.run(f\"graph info --requires=pkg/[*]@\")\n        assert f\"pkg/[*]: pkg/2.0\" in tc.out\n\n        tc.run(f\"graph info --requires=pkg/[<2]@\", assert_error=True)\n        assert f\" Package 'pkg/[<2]' not resolved\" in tc.out\n\n        tc.run(f\"graph info --requires=pkg/[<2]\", assert_error=True)\n        assert f\" Package 'pkg/[<2]' not resolved\" in tc.out\n\n\nclass TestResetRemote:\n    def test_resetting_remote_error(self):\n        # https://github.com/conan-io/conan/issues/18371\n        folder = temp_folder()\n        recipes_folder = os.path.join(folder, \"recipes\")\n        zlib_config = textwrap.dedent(\"\"\"\n            versions:\n              \"1.2.11\":\n                folder: all\n            \"\"\")\n        zlib = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import load\n            class Zlib(ConanFile):\n                name = \"zlib\"\n                exports_sources = \"*\"\n                \"\"\")\n        save_files(recipes_folder,\n                   {\"zlib/config.yml\": zlib_config,\n                    \"zlib/all/conanfile.py\": zlib,\n                    \"zlib/all/conandata.yml\": \"\",\n                    \"zlib/all/file.h\": \"//myheader\"})\n\n        client = TestClient(light=True)\n        client.run(f\"remote add local '{folder}'\")\n        client.run(\"graph info --requires=zlib/[*]\")\n\n        # This second --force destroys the previous remote database\n        client.run(f\"remote add local '{folder}' --force\")\n        client.run(\"install --requires=zlib/[*] --build=missing\")\n        # It doesn't fail or crash anymore\n\n    def test_changing_revisions(self):\n        # https://github.com/conan-io/conan/issues/18371\n        folder = temp_folder()\n        recipes_folder = os.path.join(folder, \"recipes\")\n        zlib_config = textwrap.dedent(\"\"\"\n            versions:\n              \"1.2.11\":\n                folder: all\n            \"\"\")\n        zlib = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import load\n            class Zlib(ConanFile):\n                name = \"zlib\"\n                exports_sources = \"*\"\n                def build(self):\n                    self.output.info(f\"BUILDING: {load(self, 'file.h')}\")\n            \"\"\")\n        save_files(recipes_folder,\n                   {\"zlib/config.yml\": zlib_config,\n                    \"zlib/all/conanfile.py\": zlib,\n                    \"zlib/all/conandata.yml\": \"\",\n                    \"zlib/all/file.h\": \"//myheader\"})\n\n        c = TestClient(light=True)\n        c.run(f\"remote add local '{folder}'\")\n        c.run(\"graph info --requires=zlib/[*]\")\n        rev1 = \"bd69839cb4c933336fceb32302aaf91f\"\n\n        # Modify zlib code\n        save_files(recipes_folder, {\"zlib/all/file.h\": \"//myheader 222\"})\n        c.run(\"graph info --requires=zlib/[*] --update\")\n        rev2 = \"c912566276abca17d2fb5fb6fc957852\"\n\n        c.run(f\"remote add local '{folder}' --force\")\n        c.run(f\"install --requires=zlib/1.2.11#{rev2} --build=missing\")  # works\n        c.run(f\"install --requires=zlib/1.2.11#{rev1} --build=missing\", assert_error=True)\n        assert (\"WARN: A specific revision 'zlib/1.2.11#bd69839cb4c933336fceb32302aaf91f' was \"\n                \"requested, but it doesn't match the current available revision in source\") in c.out\n        assert (\"ERROR: The 'zlib/1.2.11' package has 'exports_sources' but sources \"\n                \"not found in local cache\") in c.out\n\n    def test_reverting_to_older_revision(self):\n        # https://github.com/conan-io/conan/issues/19313\n        folder = temp_folder()\n        recipes_folder = os.path.join(folder, \"recipes\")\n        zlib_config = textwrap.dedent(\"\"\"\n           versions:\n             \"1.2.11\":\n               folder: all\n               \"\"\")\n        zlib = textwrap.dedent(\"\"\"\n           from conan import ConanFile\n           class Zlib(ConanFile):\n               name = \"zlib\"\n               exports_sources = \"*\"\n               \"\"\")\n        save_files(recipes_folder,\n                   {\"zlib/config.yml\": zlib_config,\n                    \"zlib/all/conanfile.py\": zlib,\n                    \"zlib/all/conandata.yml\": \"\",\n                    \"zlib/all/file.h\": \"//myheader\"})\n\n        c = TestClient(light=True)\n        c.run(f\"remote add local '{folder}'\")\n        c.run(\"install --requires=zlib/[*] --build=missing\")\n        rev1 = \"169da4321a56b77e8538821613a81f1d\"\n        c.assert_listed_require({f\"zlib/1.2.11#{rev1}\": \"Downloaded (local)\"})\n\n        # Modify zlib code\n        save_files(recipes_folder, {\"zlib/all/file.h\": \"//myheader 222\"})\n        c.run(\"install --requires=zlib/[*] --build=missing --update\")\n        rev2 = \"8e9fa314a3fd51ab4c930f7e4972f3e7\"\n        c.assert_listed_require({f\"zlib/1.2.11#{rev2}\": \"Updated (local)\"})\n\n        # Modify zlib code again to a new one\n        save_files(recipes_folder, {\"zlib/all/file.h\": \"//myheader 333\"})\n        c.run(\"install --requires=zlib/[*] --update --build=missing\")\n        rev3 = \"dd54aebe11b96b3661d8360c68619a72\"\n        c.assert_listed_require({f\"zlib/1.2.11#{rev3}\": \"Updated (local)\"})\n\n        # Revert to previous one\n        save_files(recipes_folder, {\"zlib/all/file.h\": \"//myheader\"})\n        c.run(\"install --requires=zlib/[*] --update --build=missing\")\n        # This crashed https://github.com/conan-io/conan/issues/19313\n        c.assert_listed_require({f\"zlib/1.2.11#{rev1}\": \"Updated (local)\"})\n"
  },
  {
    "path": "test/integration/remote/test_offline.py",
    "content": "import re\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient, TestRequester\n\n\ndef test_offline():\n    c = TestClient(servers={\"default\": None}, requester_class=None)\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n    c.run(\"create .\")\n    c.run(\"install --requires=pkg/0.1\")\n    # doesn't fail, install without issues\n    assert \"Install finished successfully\" in c.out\n\n\ndef test_offline_uploaded():\n    c = TestClient(default_server_user=True)\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\")})\n    c.run(\"create . --version=0.1\")\n    c.run(\"create . --version=0.2\")\n    c.run(\"upload * -r=default -c\")\n    c.run(\"remove * -c\")\n    c.run(\"install --requires=pkg/0.1\")\n    assert \"Install finished successfully\" in c.out\n    c.servers = {\"default\": None}\n    c.run(\"install --requires=pkg/0.1\")\n    assert \"Install finished successfully\" in c.out\n    # Lets make sure the server is broken\n    c.run(\"install --requires=pkg/0.2\", assert_error=True)\n    assert \"ERROR: Package 'pkg/0.2' not resolved\" in c.out\n\n\ndef test_offline_build_requires():\n    \"\"\"\n    When there are tool-requires that are not installed locally, Conan will try to check\n    its existence in the remote, because that package might be needed later. Even if some\n    packages can be marked later as \"skip\" and not fail, that cannot be known a priori, so if the\n    package is not in the cache, it will be checked in servers\n    https://github.com/conan-io/conan/issues/15339\n\n    Approaches to avoid the WARNING:\n    - conan remote disable <remotes>\n    - conan install ... -nr (--no-remotes)\n    - prepopulate the cache with all tool-requires with `-c:a tools.graph:skip_binaries=False`\n    \"\"\"\n    c = TestClient(default_server_user=True)\n    c.save({\"tool/conanfile.py\": GenConanfile(\"tool\", \"0.1\"),\n            \"lib/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_tool_requires(\"tool/0.1\")})\n    c.run(\"create tool\")\n    c.run(\"create lib\")\n    c.run(\"upload * -r=default -c\")\n    c.run(\"remove * -c\")\n    c.run(\"install --requires=pkg/0.1\")\n    assert \"Install finished successfully\" in c.out\n\n    class MyHttpRequester(TestRequester):\n\n        def get(self, _, **kwargs):\n            from requests.exceptions import ConnectionError\n            raise ConnectionError(\"ALL BAD\")\n\n    c.requester_class = MyHttpRequester\n    # this will fail\n    c.run(\"install --requires=pkg/0.1\", assert_error=True)\n    assert \"ERROR: Failed checking for binary 'tool/0.1:da39a3ee5e6b4b0d3255bfef95601890afd80709'\" \\\n           in c.out\n    # Explicitly telling that no-remotes, works\n    c.run(\"install --requires=pkg/0.1 -nr\")\n    assert \"tool/0.1: WARN\" not in c.out\n    assert \"Install finished successfully\" in c.out\n\n    # graph info also breaks\n    c.run(\"graph info --requires=pkg/0.1\", assert_error=True)\n    assert \"ERROR: Failed checking for binary 'tool/0.1:da39a3ee5e6b4b0d3255bfef95601890afd80709'\" \\\n           in c.out\n\n    c.run(\"graph info --requires=pkg/0.1 -nr\")\n    assert \"tool/0.1: WARN\" not in c.out\n    assert re.search(r\"Skipped binaries(\\s*)tool/0.1\", c.out)\n"
  },
  {
    "path": "test/integration/remote/test_remote_file_credentials.py",
    "content": "import json\nimport os\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient, TestServer\nfrom conan.internal.util.files import save\n\n\n@pytest.fixture()\ndef client():\n    test_server = TestServer()\n    c = TestClient(servers={\"default\": test_server})\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n    c.run(\"create .\")\n    c.run(\"upload * -r=default -c\", assert_error=True)\n    return c\n\n\ndef test_remote_file_credentials(client):\n    c = client\n    content = {\"credentials\": [{\"remote\": \"default\", \"user\": \"admin\", \"password\": \"password\"}]}\n    save(os.path.join(c.cache_folder, \"credentials.json\"), json.dumps(content))\n    c.run(\"upload * -r=default -c\")\n    # it works without problems!\n    assert \"Uploading recipe\" in c.out\n\n\ndef test_remote_file_credentials_remote_login(client):\n    c = client\n    content = {\"credentials\": [{\"remote\": \"default\", \"user\": \"admin\", \"password\": \"password\"}]}\n    save(os.path.join(c.cache_folder, \"credentials.json\"), json.dumps(content))\n    c.run(\"remote login default\")\n    assert \"Changed user of remote 'default' from 'None' (anonymous) \" \\\n           \"to 'admin' (authenticated)\" in c.out\n\n\ndef test_remote_file_credentials_error(client):\n    c = client\n    content = {\"credentials\": [{\"remote\": \"default\", \"user\": \"admin\", \"password\": \"wrong\"}]}\n    save(os.path.join(c.cache_folder, \"credentials.json\"), json.dumps(content))\n    c.run(\"upload * -r=default -c\", assert_error=True)\n    assert \"ERROR: Wrong user or password\" in c.out\n\n\ndef test_remote_file_credentials_bad_file(client):\n    c = client\n    save(os.path.join(c.cache_folder, \"credentials.json\"), \"\")\n    c.run(\"upload * -r=default -c\", assert_error=True)\n    assert \"ERROR: Error loading 'credentials.json'\" in c.out\n    content = {\"credentials\": [{\"remote\": \"default\"}]}\n    save(os.path.join(c.cache_folder, \"credentials.json\"), json.dumps(content))\n    c.run(\"upload * -r=default -c\", assert_error=True)\n    assert \"ERROR: Error loading 'credentials.json'\" in c.out\n"
  },
  {
    "path": "test/integration/remote/test_remote_recipes_only.py",
    "content": "import json\nimport os\n\nimport pytest\n\nfrom conan.api.model import PkgReference\nfrom conan.internal.util.files import save\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\nPKG_ID = \"da39a3ee5e6b4b0d3255bfef95601890afd80709\"\nRREV = \"a9ec2e5fbb166568d4670a9cd1ef4b26\"\n\n\n@pytest.fixture(scope=\"module\")\ndef client():\n    tc = TestClient(light=True, default_server_user=True)\n    tc.save({\"conanfile.py\": GenConanfile(\"pkg\")})\n    tc.run(\"create . --version=1.0\")\n    assert RREV == tc.exported_recipe_revision()\n    assert PKG_ID == tc.created_package_id(\"pkg/1.0\")\n    tc.run(\"upload * -r=default -c\")\n    tc.run(\"remove * -c\")\n    tc.run(\"remote update default --recipes-only\")\n    return tc\n\n\ndef test_graph_binary_analyze(client):\n    client.run(\"install --requires=pkg/1.0 -f=json\", assert_error=True)\n    client.assert_listed_binary({\"pkg/1.0\": (PKG_ID, \"Missing\")})\n\n    client.run(\"graph explain --requires=pkg/1.0\")\n    assert \"ERROR: No package binaries exist\" in client.out\n\n\ndef test_list_packages(client):\n    client.run(\"list pkg/1.0:* -r=default -f=json\", redirect_stdout=\"list.json\")\n    result = json.loads(client.load(\"list.json\"))\n    assert len(result[\"default\"][\"pkg/1.0\"][\"revisions\"][RREV][\"packages\"]) == 0\n\n    client.run(f\"list pkg/1.0:{PKG_ID} -r=default -f=json\", redirect_stdout=\"list.json\")\n    result = json.loads(client.load(\"list.json\"))\n    assert \"error\" in result[\"default\"]  # not found error\n\n\ndef test_download_package(client):\n    client.run(\"download pkg/1.0:* -r=default -f=json\", redirect_stdout=\"download.json\")\n    result = json.loads(client.load(\"download.json\"))\n    assert len(result[\"Local Cache\"][\"pkg/1.0\"][\"revisions\"][RREV][\"packages\"]) == 0\n\n\ndef test_remove_package(client):\n    client.run(f\"remove pkg/1.0:{PKG_ID} -r=default -c -f=json\", redirect_stdout=\"remove.json\")\n    result = json.loads(client.load(\"remove.json\"))\n    assert result[\"default\"] == {}\n\n    client.run(f\"remove pkg/1.0:* -r=default -c -f=json\", redirect_stdout=\"remove.json\")\n    result = json.loads(client.load(\"remove.json\"))\n    assert result[\"default\"] == {}\n\n    client.run(f\"remove pkg/1.0 -r=default -c -f=json\", redirect_stdout=\"remove.json\")\n    result = json.loads(client.load(\"remove.json\"))\n    assert \"packages\" not in result[\"default\"][\"pkg/1.0\"][\"revisions\"][RREV]\n\n\n@pytest.mark.parametrize(\"pattern\", [\"*\", \"pkg/2.0\", \"pkg/2.0:*\", f\"pkg/2.0:{PKG_ID}\"])\ndef test_upload_still_works(client, pattern):\n    client.run(\"create . --version=2.0\")\n    layout = client.created_layout()\n    save(os.path.join(layout.metadata(), \"metadata.log\"), \"New hello\")\n\n    client.run(f\"upload {pattern} -r=default -c\")\n\n    # Now check that the binary was in fact uploaded\n    client.run(\"remote update default --recipes-only=False\")\n    client.run(\"remove * -c\")\n    client.run(\"list pkg/2.0:* -r=default -f=json\", redirect_stdout=\"list.json\")\n    result = json.loads(client.load(\"list.json\"))\n    assert len(result[\"default\"][\"pkg/2.0\"][\"revisions\"][RREV][\"packages\"]) == 1\n    assert PKG_ID in result[\"default\"][\"pkg/2.0\"][\"revisions\"][RREV][\"packages\"]\n\n    client.run(f\"download {pattern} -r=default -f=json --metadata=*\", redirect_stdout=\"download.json\")\n    pkg2_layout = client.get_latest_pkg_layout(PkgReference().loads(f\"pkg/2.0#{RREV}:{PKG_ID}\"))\n    assert os.path.exists(os.path.join(pkg2_layout.metadata(), \"metadata.log\"))\n"
  },
  {
    "path": "test/integration/remote/test_request_headers.py",
    "content": "from conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient, TestRequester\n\n\nclass RequesterClass(TestRequester):\n\n    def get(self, url, headers=None, **kwargs):\n        print(f\"URL: {url}-HEADERS: {headers}\")\n        return super(RequesterClass, self).get(url, headers=headers, **kwargs)\n\n\ndef test_request_info_headers():\n    c = TestClient(requester_class=RequesterClass, default_server_user=True)\n    conanfile = GenConanfile(\"pkg\", \"0.1\").with_settings('os', 'arch', 'compiler') \\\n                                          .with_shared_option(False)\n    c.save({'conanfile.py': conanfile})\n    c.run(\"export .\")\n    c.run(\"install --requires=pkg/0.1 -s arch=x86_64\", assert_error=True)\n    assert \"'Conan-PkgID-Options': 'shared=False'\" in c.out\n    assert \"'Conan-PkgID-Settings': 'arch=x86_64;\" in c.out\n\n"
  },
  {
    "path": "test/integration/sbom/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/sbom/test_cyclonedx.py",
    "content": "import textwrap\nimport json\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import save\nimport os\n\n# Using the sbom tool with \"conan create\"\nsbom_hook_post_package = \"\"\"\nimport json\nimport os\nfrom conan.errors import ConanException\nfrom conan.api.output import ConanOutput\nfrom conan.tools.sbom import {cyclone_version}\n\ndef post_package(conanfile):\n    sbom_{cyclone_version} = {cyclone_version}(conanfile, add_build={add_build}, add_tests={add_tests})\n    metadata_folder = conanfile.package_metadata_folder\n    file_name = \"sbom.cdx.json\"\n    with open(os.path.join(metadata_folder, file_name), 'w') as f:\n        json.dump(sbom_{cyclone_version}, f, indent=4)\n    ConanOutput().success(f\"CYCLONEDX CREATED - {{conanfile.package_metadata_folder}}\")\n\"\"\"\n\n# Using the sbom tool with \"conan install\"\nsbom_hook_post_generate = \"\"\"\nimport json\nimport os\nfrom conan.errors import ConanException\nfrom conan.api.output import ConanOutput\nfrom conan.tools.sbom import {cyclone_version}\n\ndef post_generate(conanfile):\n    sbom_{cyclone_version} = {cyclone_version}(conanfile, name={name})\n    generators_folder = conanfile.generators_folder\n    file_name = \"sbom.cdx.json\"\n    os.mkdir(os.path.join(generators_folder, \"sbom\"))\n    with open(os.path.join(generators_folder, \"sbom\", file_name), 'w') as f:\n        json.dump(sbom_{cyclone_version}, f, indent=4)\n    ConanOutput().success(f\"CYCLONEDX CREATED - {{conanfile.generators_folder}}\")\n\"\"\"\n\n\n@pytest.mark.parametrize(\"cyclone_version\", [\"cyclonedx_1_4\", \"cyclonedx_1_6\"])\nclass TestCyclonedx:\n\n    @pytest.fixture()\n    def hook_setup_post_package(self, cyclone_version):\n        tc = TestClient(light=True)\n        hook_path = os.path.join(tc.paths.hooks_path, \"hook_sbom.py\")\n        save(hook_path, sbom_hook_post_package.format(cyclone_version=cyclone_version,\n                                                      add_build=True, add_tests=True))\n        return tc\n\n    @pytest.fixture()\n    def hook_setup_post_package_no_tool_requires(self, cyclone_version):\n        tc = TestClient(light=True)\n        hook_path = os.path.join(tc.paths.hooks_path, \"hook_sbom.py\")\n        save(hook_path, sbom_hook_post_package.format(cyclone_version=cyclone_version,\n                                                      add_build=False, add_tests=True))\n        return tc\n\n    @pytest.fixture()\n    def hook_setup_post_package_no_test(self, cyclone_version):\n        tc = TestClient(light=True)\n        hook_path = os.path.join(tc.paths.hooks_path, \"hook_sbom.py\")\n        save(hook_path, sbom_hook_post_package.format(cyclone_version=cyclone_version,\n                                                      add_build=True, add_tests=False))\n        return tc\n\n    def test_sbom_generation_skipped_dependencies(self, hook_setup_post_package):\n        tc = hook_setup_post_package\n        tc.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"1.0\"),\n                 \"app/conanfile.py\": GenConanfile(\"app\", \"1.0\")\n                .with_package_type(\"application\")\n                .with_requires(\"dep/1.0\"),\n                 \"conanfile.py\": GenConanfile(\"foo\", \"1.0\").with_tool_requires(\"app/1.0\")})\n        tc.run(\"create dep\")\n        tc.run(\"create app\")\n        tc.run(\"create .\")\n        create_layout = tc.created_layout()\n\n        cyclone_path = os.path.join(create_layout.metadata(), \"sbom.cdx.json\")\n        content = tc.load(cyclone_path)\n        # A skipped dependency also shows up in the sbom\n        assert \"pkg:conan/dep@1.0?rref=6a99f55e933fb6feeb96df134c33af44\" in content\n\n    @pytest.mark.parametrize(\"lic, n\", [('\"simple\"', 1), ('\"multi1\", \"multi2\"', 2),\n                                        ('(\"tuple1\", \"tuple2\")', 2)])\n    def test_multi_license(self, hook_setup_post_package, lic, n):\n        tc = hook_setup_post_package\n        conanfile = textwrap.dedent(f\"\"\"\n            from conan import ConanFile\n            class HelloConan(ConanFile):\n                name = 'foo'\n                version = '1.0'\n                license = {lic}\n        \"\"\")\n        tc.save({\"conanfile.py\": conanfile})\n        tc.run(\"create .\")\n        create_layout = tc.created_layout()\n        cyclone_path = os.path.join(create_layout.metadata(), \"sbom.cdx.json\")\n        content = json.loads(tc.load(cyclone_path))\n        assert len(content[\"components\"][0][\"licenses\"]) == n\n\n    @pytest.mark.parametrize(\"lic, keys\", [('\"Mit\"', [\"id\"]), ('\"custom_license name\"', [\"name\"]),\n                                           ('(\"mIT\", \"custom\")', [\"id\", \"name\"])])\n    def test_license_spdx_valid(self, hook_setup_post_package, lic, keys):\n        tc = hook_setup_post_package\n        conanfile = textwrap.dedent(f\"\"\"\n                from conan import ConanFile\n                class HelloConan(ConanFile):\n                    name = 'foo'\n                    version = '1.0'\n                    license = {lic}\n            \"\"\")\n        tc.save({\"conanfile.py\": conanfile})\n        tc.run(\"create .\")\n        create_layout = tc.created_layout()\n        cyclone_path = os.path.join(create_layout.metadata(), \"sbom.cdx.json\")\n        content = json.loads(tc.load(cyclone_path))\n        for i, l in enumerate(content[\"components\"][0][\"licenses\"]):\n            assert next(iter(l[\"license\"])) == keys[i]\n\n    def test_sbom_generation_no_tool_requires(self, hook_setup_post_package_no_tool_requires):\n        tc = hook_setup_post_package_no_tool_requires\n        tc.save({\"app/conanfile.py\": GenConanfile(\"app\", \"1.0\")\n                .with_package_type(\"application\"),\n                 \"conanfile.py\": GenConanfile(\"foo\", \"1.0\").with_tool_requires(\"app/1.0\")})\n        tc.run(\"create app\")\n        tc.run(\"create .\")\n        create_layout = tc.created_layout()\n\n        cyclone_path = os.path.join(create_layout.metadata(), \"sbom.cdx.json\")\n        content = tc.load(cyclone_path)\n\n        assert \"pkg:conan/app\" not in content\n\n    def test_sbom_generation_transitive_test_requires(self, hook_setup_post_package_no_test):\n        tc = hook_setup_post_package_no_test\n        tc.save({\"test_re/conanfile.py\": GenConanfile(\"test_re\", \"1.0\"),\n                 \"app/conanfile.py\": GenConanfile(\"app\", \"1.0\")\n                .with_package_type(\"application\")\n                .with_test_requires(\"test_re/1.0\"),\n                 \"conanfile.py\": GenConanfile(\"foo\", \"1.0\").with_tool_requires(\"app/1.0\")})\n        tc.run(\"create test_re\")\n\n        tc.run(\"create app\")\n        create_layout = tc.created_layout()\n        cyclone_path = os.path.join(create_layout.metadata(), \"sbom.cdx.json\")\n        content = tc.load(cyclone_path)\n        assert \"pkg:conan/test_re@1.0\" not in content\n\n        tc.run(\"create .\")\n        create_layout = tc.created_layout()\n        cyclone_path = os.path.join(create_layout.metadata(), \"sbom.cdx.json\")\n        content = tc.load(cyclone_path)\n        assert \"pkg:conan/test_re@1.0\" not in content\n\n    def test_sbom_generation_dependency_test_require(self, hook_setup_post_package_no_test):\n        tc = hook_setup_post_package_no_test\n        tc.save({\"special/conanfile.py\": GenConanfile(\"special\", \"1.0\"),\n                 \"foo/conanfile.py\": GenConanfile(\"foo\", \"1.0\")\n                .with_test_requires(\"special/1.0\"),\n                 \"conanfile.py\": GenConanfile(\"bar\", \"1.0\").with_tool_requires(\n                     \"foo/1.0\").with_require(\"special/1.0\")})\n        tc.run(\"create special\")\n        tc.run(\"create foo\")\n\n        tc.run(\"create .\")\n        create_layout = tc.created_layout()\n        cyclone_path = os.path.join(create_layout.metadata(), \"sbom.cdx.json\")\n        content = tc.load(cyclone_path)\n        assert \"pkg:conan/special@1.0\" in content\n\n    @pytest.fixture()\n    def hook_setup_post_generate(self, cyclone_version):\n        tc = TestClient(light=True)\n        hook_path = os.path.join(tc.paths.hooks_path, \"hook_sbom.py\")\n        save(hook_path, sbom_hook_post_generate.format(cyclone_version=cyclone_version, name=None))\n        return tc\n\n    def test_sbom_generation_install_requires(self, hook_setup_post_generate):\n        tc = hook_setup_post_generate\n        tc.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"1.0\"),\n                 \"conanfile.py\": GenConanfile(\"foo\", \"1.0\").with_requires(\"dep/1.0\")})\n        tc.run(\"export dep\")\n        tc.run(\"create . --build=missing\")\n\n        # cli -> foo -> dep\n        tc.run(\"install --requires=foo/1.0\")\n        assert os.path.exists(os.path.join(tc.current_folder, \"sbom\", \"sbom.cdx.json\"))\n\n    def test_sbom_generation_install_path(self, hook_setup_post_generate):\n        tc = hook_setup_post_generate\n        tc.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"1.0\"),\n                 \"conanfile.py\": GenConanfile(\"foo\", \"1.0\").with_requires(\"dep/1.0\")})\n        tc.run(\"create dep\")\n\n        # foo -> dep\n        tc.run(\"install .\")\n        assert os.path.exists(os.path.join(tc.current_folder, \"sbom\", \"sbom.cdx.json\"))\n\n    def test_sbom_generation_install_path_consumer(self, hook_setup_post_generate):\n        tc = hook_setup_post_generate\n        tc.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"1.0\"),\n                 \"conanfile.py\": GenConanfile().with_requires(\"dep/1.0\")})\n        tc.run(\"create dep\")\n\n        # conanfile.py -> dep\n        tc.run(\"install .\")\n        assert os.path.exists(os.path.join(tc.current_folder, \"sbom\", \"sbom.cdx.json\"))\n\n    def test_sbom_generation_install_path_txt(self, hook_setup_post_generate):\n        tc = hook_setup_post_generate\n        tc.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"1.0\"),\n                 \"conanfile.txt\": textwrap.dedent(\n                     \"\"\"\n                     [requires]\n                     dep/1.0\n                     \"\"\"\n                 )})\n        tc.run(\"create dep\")\n\n        # foo -> dep\n        tc.run(\"install .\")\n        assert os.path.exists(os.path.join(tc.current_folder, \"sbom\", \"sbom.cdx.json\"))\n\n    def test_sbom_with_special_root_node(self, hook_setup_post_generate):\n        # In this test, we have only one node in the subgraph, which has build context, so the number\n        # of components after processing it is zero.\n        tc = hook_setup_post_generate\n        package_name = \"foo\"\n\n        conanfile = textwrap.dedent(\"\"\"\n                from conan import ConanFile\n                class FooPackage(ConanFile):\n                    name = \"foo\"\n                    version = \"1.0\"\n                    package_type = \"build-scripts\"\n        \"\"\")\n        tc.save({\"conanfile.py\": conanfile})\n        tc.run(\"create .\")\n        create_layout = tc.created_layout()\n        assert os.path.exists(os.path.join(create_layout.build(), \"sbom\", \"sbom.cdx.json\"))\n        with open(os.path.join(create_layout.build(), \"sbom\", \"sbom.cdx.json\"), 'r') as file:\n            sbom_json = json.load(file)\n            assert package_name in sbom_json[\"metadata\"][\"component\"][\"name\"]\n\n    @pytest.mark.parametrize(\"name, result\", [\n        (\"None\", \"conan-sbom\"),\n        ('\"custom-name\"', \"custom-name\")\n    ])\n    def test_sbom_generation_custom_name(self, cyclone_version, name, result):\n        tc = TestClient(light=True)\n        hook_path = os.path.join(tc.paths.hooks_path, \"hook_sbom.py\")\n        save(hook_path, sbom_hook_post_generate.format(cyclone_version=cyclone_version, name=name))\n\n        tc.save({\"conanfile.py\": GenConanfile()})\n        tc.run(\"install .\")\n        assert os.path.exists(os.path.join(tc.current_folder, \"sbom\", \"sbom.cdx.json\"))\n        assert f'\"name\": \"{result}\"' in tc.load(\n            os.path.join(tc.current_folder, \"sbom\", \"sbom.cdx.json\"))\n\n    def test_cyclonedx_check_content(self, cyclone_version):\n        _sbom_hook_post_package = textwrap.dedent(\"\"\"\n        import json\n        import os\n        from conan.errors import ConanException\n        from conan.api.output import ConanOutput\n        from conan.tools.sbom import {cyclone_version}\n\n        def post_package(conanfile):\n            sbom_cyclonedx= {cyclone_version}(conanfile)\n            metadata_folder = conanfile.package_metadata_folder\n            file_name = \"sbom.cdx.json\"\n            with open(os.path.join(metadata_folder, file_name), 'w') as f:\n                json.dump(sbom_cyclonedx, f, indent=4)\n            ConanOutput().success(f\"CYCLONEDX CREATED - {{conanfile.package_metadata_folder}}\")\n        \"\"\")\n        tc = TestClient(light=True)\n        hook_path = os.path.join(tc.paths.hooks_path, \"hook_sbom.py\")\n        save(hook_path, _sbom_hook_post_package.format(cyclone_version=cyclone_version))\n        conanfile_bar = textwrap.dedent(\"\"\"\n                from conan import ConanFile\n                class HelloConan(ConanFile):\n                    name = 'bar'\n                    version = '1.0'\n                    author = 'conan-dev'\n                    package_type = 'application'\n            \"\"\")\n\n        conanfile_foo = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class HelloConan(ConanFile):\n                name = 'foo'\n                version = '1.0'\n                author = 'conan-dev'\n                package_type = 'application'\n\n                def requirements(self):\n                    self.requires(\"bar/1.0\")\n        \"\"\")\n        tc.save({\"conanfile.py\": conanfile_bar})\n        tc.run(\"create .\")\n        tc.save({\"conanfile.py\": conanfile_foo})\n        tc.run(\"create .\")\n\n        create_layout = tc.created_layout()\n        cyclone_path = os.path.join(create_layout.metadata(), \"sbom.cdx.json\")\n        content = tc.load(cyclone_path)\n        content_json = json.loads(content)\n        if cyclone_version == 'cyclonedx_1_4':\n            assert content_json[\"metadata\"][\"component\"][\"author\"] == 'conan-dev'\n            assert content_json[\"metadata\"][\"component\"][\"type\"] == 'application'\n            assert content_json[\"metadata\"][\"tools\"][0]\n            assert content_json[\"components\"][0][\"author\"] == 'conan-dev'\n            assert content_json[\"components\"][0][\"type\"] == 'application'\n        elif cyclone_version == 'cyclonedx_1_6':\n            assert not content_json[\"metadata\"][\"component\"].get(\"author\")\n            assert content_json[\"metadata\"][\"component\"][\"authors\"][0][\"name\"] == 'conan-dev'\n            assert content_json[\"metadata\"][\"component\"][\"type\"] == 'application'\n            assert content_json[\"metadata\"][\"tools\"][\"components\"][0]\n            assert not content_json[\"components\"][0].get(\"author\")\n            assert content_json[\"components\"][0][\"authors\"][0][\"name\"] == 'conan-dev'\n            assert content_json[\"components\"][0][\"type\"] == 'application'\n\n    def test_sbom_test_requires_skipped(self, cyclone_version):\n        tc = TestClient(light=True)\n        hook_path = os.path.join(tc.paths.hooks_path, \"hook_sbom.py\")\n        save(hook_path, sbom_hook_post_generate.format(cyclone_version=cyclone_version, name=None,\n                                                       add_build=False, add_tests=False))\n        tc.save({\"dep/conanfile.py\": GenConanfile(\"mydep\", \"1.0\"),\n                 \"conanfile.py\": GenConanfile(\"foo\", \"1.0\").with_test_requires(\"mydep/1.0\")})\n        tc.run(\"create dep\")\n        tc.run(\"install .\")\n        content = tc.load(\"sbom/sbom.cdx.json\")\n        assert \"mydep\" not in content\n\n    @pytest.mark.parametrize(\"install\", [\"--requires=foo/1.0\", \"\"])\n    def test_sbom_deployer(self, cyclone_version, install):\n        tc = TestClient(light=True)\n        tc.save({\"dep/conanfile.py\": GenConanfile(\"mydep\", \"1.0\"),\n                 \"conanfile.py\": GenConanfile(\"foo\", \"1.0\").with_requires(\"mydep/1.0\")})\n        tc.run(\"create dep\")\n        tc.run(\"create\")\n        method = {\n            \"cyclonedx_1_4\": \"1.4\",\n            \"cyclonedx_1_6\": \"1.6\",\n        }.get(cyclone_version)\n        tc.run(f\"install {install} --deployer=cyclone_{method}\")\n        assert os.path.exists(os.path.join(tc.current_folder, f\"sbom-cyclonedx-{method}.json\"))\n"
  },
  {
    "path": "test/integration/settings/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/settings/built_type_setting_test.py",
    "content": "from conan.test.utils.tools import TestClient\n\n\nclass TestBuildTypeSetting:\n\n    def test_build_type(self):\n        # https://github.com/conan-io/conan/issues/2500\n        client = TestClient()\n        conanfile = \"\"\"from conan import ConanFile\nclass Pkg(ConanFile):\n    settings = \"build_type\"\n    def build(self):\n        self.output.info(\"BUILD TYPE: %s\" % (self.settings.build_type or \"Not defined\"))\n\"\"\"\n        test_conanfile = \"\"\"from conan import ConanFile\nclass Pkg(ConanFile):\n    settings = \"build_type\"\n    def requirements(self):\n        self.requires(self.tested_reference_str)\n    def build(self):\n        self.output.info(\"BUILD TYPE: %s\" % (self.settings.build_type or \"Not defined\"))\n    def test(self):\n        pass\n\"\"\"\n        client.save({\"conanfile.py\": conanfile,\n                     \"test_package/conanfile.py\": test_conanfile,\n                     \"myprofile\": \"\"})\n\n        # This won't fail, as it has a build_type=None, which is allowed\n        client.run(\"export . --name=pkg --version=0.1 --user=lasote --channel=testing\")\n        client.run(\"install --requires=pkg/0.1@lasote/testing -pr=myprofile --build='*'\")\n        assert 1 == str(client.out).count(\"BUILD TYPE: Not defined\")\n\n        # test_package is totally consinstent with the regular package\n        client.run(\"create . --name=pkg --version=0.1 --user=lasote --channel=testing -pr=myprofile\")\n        assert 2 == str(client.out).count(\"BUILD TYPE: Not defined\")\n\n        client.save({\"conanfile.py\": conanfile,\n                     \"test_package/conanfile.py\": test_conanfile,\n                     \"myprofile\": \"[settings]\\nbuild_type=Release\"})\n\n        client.run(\"export . --name=pkg --version=0.1 --user=user --channel=testing\")\n        client.run(\"install --requires=pkg/0.1@lasote/testing -pr=myprofile --build='*'\")\n        assert 1 == str(client.out).count(\"BUILD TYPE: Release\")\n\n        client.run(\"create . --name=pkg --version=0.1 --user=lasote --channel=testing -pr=myprofile\")\n        assert 2 == str(client.out).count(\"BUILD TYPE: Release\")\n\n        # Explicit build_tyep=None is NOT allowed, it is not a valid value\n        client.save({\"conanfile.py\": conanfile,\n                     \"test_package/conanfile.py\": test_conanfile,\n                     \"myprofile\": \"[settings]\\nbuild_type=None\"})\n\n        client.run(\"export . --name=pkg --version=0.1 --user=lasote --channel=testing\")\n        client.run(\"install --requires=pkg/0.1@lasote/testing -pr=myprofile --build='*'\",\n                   assert_error=True)\n        assert \"ERROR: Invalid setting 'None' is not a valid 'settings.build_type'\" in client.out\n        assert \"Possible values are ['Debug', 'Release', 'RelWithDebInfo', 'MinSizeRel']\" in \\\n            client.out\n"
  },
  {
    "path": "test/integration/settings/per_package_settings_test.py",
    "content": "import json\nimport textwrap\n\nfrom conan.test.utils.tools import TestClient, GenConanfile\n\n\nclass TestPerPackageSetting:\n\n    def test_per_package_setting(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                settings = \"os\"\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --name=pkg --version=0.1 --user=user --channel=testing -s os=Windows\")\n        client.save({\"conanfile.py\": GenConanfile().with_require(\"pkg/0.1@user/testing\")})\n        client.run(\"create . --name=consumer --version=0.1 --user=user --channel=testing -s os=Linux -s pkg*:os=Windows\")\n        assert \"consumer/0.1@user/testing: Created package\" in client.out\n\n    def test_per_package_setting_build_type(self):\n        \"\"\" comes from https://github.com/conan-io/conan/pull/9842\n        In Conan 1.X there was a weird behavior if you used different patterns,\n        only first matching one win. This was broken:\n          -s pkg*:os=Windows -s *model:build_type=Debug\n        keeps the build_type=Release, because pkg* matches, assign os=Windows and stops\n        \"\"\"\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                name = \"pkg-model\"\n                version = \"0.1\"\n                settings = \"os\", \"build_type\"\n                def build(self):\n                    self.output.info(\"BUILDTYPE {}:{}!!!!\".format(self.settings.os,\n                                                                  self.settings.build_type))\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        # Different pattern, no issue, works now\n        client.run(\"create . -s *:os=Windows -s *-model*:build_type=Debug -s build_type=Release\")\n        assert \"pkg-model/0.1: BUILDTYPE Windows:Debug!!!!\" in client.out\n\n        client.save({\"conanfile.py\": GenConanfile(\"consumer\", \"0.1\").with_require(\"pkg-model/0.1\")})\n        client.run('create . -s *:os=Linux -s *-model*:os=Windows '\n                   '-s \"*-model*:build_type=Debug\" -s build_type=Release --build=*')\n        assert \"pkg-model/0.1: BUILDTYPE Windows:Debug!!!!\" in client.out\n        assert \"consumer/0.1: Created package\" in client.out\n\n    def test_per_package_setting_no_userchannel(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                settings = \"os\"\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --name=pkg --version=0.1 -s os=Windows\")\n        client.save({\"conanfile.py\": GenConanfile().with_require(\"pkg/0.1\")})\n        client.run(\"create . --name=consumer --version=0.1 -s os=Linux -s pkg*:os=Windows\")\n        assert \"consumer/0.1: Created package\" in client.out\n\n    def test_per_package_subsetting(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                settings = \"os\", \"compiler\"\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        settings = \"-s os=Linux -s compiler=gcc -s compiler.version=5\"\n        client.run(\"create . --name=pkg --version=0.1 --user=user --channel=testing %s  -s compiler.libcxx=libstdc++11\" % settings)\n        client.save({\"conanfile.py\": GenConanfile().with_require(\"pkg/0.1@user/testing\")})\n        client.run(\"create . --name=consumer --version=0.1 --user=user --channel=testing %s -s compiler.libcxx=libstdc++ \"\n                   \"-s pkg*:compiler.libcxx=libstdc++11\" % settings)\n        assert \"consumer/0.1@user/testing: Created package\" in client.out\n\n    def test_per_package_setting_all_packages_without_user_channel(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                settings = \"os\"\n                def configure(self):\n                    self.output.info(f\"I am a {self.settings.os} pkg!!!\")\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --name=pkg1 --version=0.1 -s os=Windows\")\n        client.run(\"create . --name=pkg2 --version=0.1 --user=user -s os=Linux\")\n        client.run(\"create . --name=pkg3 --version=0.1 --user=user --channel=channel -s os=Linux\")\n        client.save({\"conanfile.py\": GenConanfile().with_requires(\"pkg1/0.1\", \"pkg2/0.1@user\",\n                                                                  \"pkg3/0.1@user/channel\")})\n        client.run(\"install . -s os=Linux -s *@:os=Windows\")\n        assert \"pkg1/0.1: I am a Windows pkg!!!\" in client.out\n        assert \"pkg2/0.1@user: I am a Linux pkg!!!\" in client.out\n        assert \"pkg3/0.1@user/channel: I am a Linux pkg!!!\" in client.out\n\n\ndef test_per_package_settings_target():\n    c = TestClient()\n    gcc = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Pkg(ConanFile):\n            name = \"gcc\"\n            version = \"0.1\"\n            settings = \"arch\"\n\n            def configure(self):\n                self.settings_target.rm_safe(\"os\")\n                self.settings_target.rm_safe(\"compiler\")\n                self.settings_target.rm_safe(\"build_type\")\n\n            def package_id(self):\n                self.info.settings_target = self.settings_target\n        \"\"\")\n    c.save({\"conanfile.py\": gcc})\n    c.run(\"create . -s:b arch=x86_64 -s:h arch=armv7 --build-require\")\n    pkg_id = c.created_package_id(\"gcc/0.1\")\n\n    c.run(\"install --tool-requires=gcc/0.1 -s:b arch=x86_64 -s arch=armv8 -s:h gcc*:arch=armv7\"\n          \" --format=json\")\n    # it will not fail due to armv8, but use the binary for armv7\n    c.assert_listed_binary({\"gcc/0.1\": (pkg_id, \"Cache\")}, build=True)\n\n    graph = json.loads(c.stdout)\n    assert graph[\"graph\"][\"nodes\"][\"1\"][\"info\"][\"settings_target\"] == {\"arch\": \"armv7\"}\n\n\ndef test_per_package_settings_build():\n    c = TestClient()\n    cmake = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Pkg(ConanFile):\n            name = \"cmake\"\n            version = \"0.1\"\n            settings = \"build_type\"\n\n            def build(self):\n                self.output.info(f\"Building myself with {self.settings.build_type}!!\")\n        \"\"\")\n    c.save({\"conanfile.py\": cmake})\n    c.run(\"export .\")\n\n    c.run(\"install --tool-requires=cmake/0.1 -s:b build_type=Release -s:b cmake*:build_type=Debug \"\n          \"--build=missing\")\n    assert \"cmake/0.1: Building myself with Debug!!\" in c.out\n\n\ndef test_package_settings_mixed_patterns():\n    # https://github.com/conan-io/conan/issues/16606\n    c = TestClient()\n    profile = textwrap.dedent(\"\"\"\n        [settings]\n        arch=x86_64\n        *@test/*:build_type=Release\n\n        os=Linux\n        compiler=gcc\n        &:compiler.version=12\n        compiler.libcxx = libstdc++\n        \"\"\")\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"mypkg\"\n            version = \"0.1\"\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            def build(self):\n                self.output.info(f\"BUILD_TYPE={self.settings.build_type}!\")\n                self.output.info(f\"COMPILER_VERSION={self.settings.compiler.version}!\")\n                self.output.info(f\"COMPILER_LIBCXX={self.settings.compiler.libcxx}!\")\n            \"\"\")\n    c.save({\"profile\": profile,\n            \"conanfile.py\": conanfile})\n    c.run(\"create . -pr=profile --user=test --channel=test\")\n    assert \"mypkg/0.1@test/test: BUILD_TYPE=Release!\" in c.out\n    assert \"mypkg/0.1@test/test: COMPILER_VERSION=12!\" in c.out\n    assert \"mypkg/0.1@test/test: COMPILER_LIBCXX=libstdc++!\" in c.out\n\n\ndef test_package_settings_negate_patterns():\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Dep(ConanFile):\n            version = \"0.1\"\n            settings = \"os\"\n            def build(self):\n                self.output.info(f\"BUILD OS={self.settings.os}!!!\")\n            \"\"\")\n    c.save({\"dep/conanfile.py\": conanfile,\n            \"pkg/conanfile.py\": GenConanfile().with_requires(\"dep1/0.1\", \"dep2/0.1\", \"dep3/0.1\")})\n    c.run(\"export dep --name=dep1\")\n    c.run(\"export dep --name=dep2\")\n    c.run(\"export dep --name=dep3\")\n\n    c.run(\"install pkg --build=* -s os=Linux -s ~dep1/*:os=Macos\")\n    assert \"dep1/0.1: BUILD OS=Linux!!!\" in c.out\n    assert \"dep2/0.1: BUILD OS=Macos!!!\" in c.out\n    assert \"dep3/0.1: BUILD OS=Macos!!!\" in c.out\n\n    # Order doesn't matter if using the base \"os=Linux\"\n    c.run(\"install pkg --build=* -s ~dep1/*:os=Macos -s os=Linux\")\n    assert \"dep1/0.1: BUILD OS=Linux!!!\" in c.out\n    assert \"dep2/0.1: BUILD OS=Macos!!!\" in c.out\n    assert \"dep3/0.1: BUILD OS=Macos!!!\" in c.out\n\n    # Order DOES matter if using the pattern \"*:os=Linux\"\n    c.run(\"install pkg --build=* -s ~dep1/*:os=Macos -s *:os=Linux\")\n    assert \"dep1/0.1: BUILD OS=Linux!!!\" in c.out\n    assert \"dep2/0.1: BUILD OS=Linux!!!\" in c.out\n    assert \"dep3/0.1: BUILD OS=Linux!!!\" in c.out\n\n    # dep3 comes later, works\n    c.run(\"install pkg --build=* -s os=Linux -s ~dep1/*:os=Macos -s dep3/*:os=Windows\")\n    assert \"dep1/0.1: BUILD OS=Linux!!!\" in c.out\n    assert \"dep2/0.1: BUILD OS=Macos!!!\" in c.out\n    assert \"dep3/0.1: BUILD OS=Windows!!!\" in c.out\n\n    # dep3 comes first, then last !dep1 pattern prevails\n    c.run(\"install pkg --build=* -s os=Linux -s dep3/*:os=Windows -s ~dep1/*:os=Macos\")\n    assert \"dep1/0.1: BUILD OS=Linux!!!\" in c.out\n    assert \"dep2/0.1: BUILD OS=Macos!!!\" in c.out\n    assert \"dep3/0.1: BUILD OS=Macos!!!\" in c.out\n"
  },
  {
    "path": "test/integration/settings/remove_subsetting_test.py",
    "content": "import os\nimport textwrap\n\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import mkdir\n\n\nclass TestRemoveSubsetting:\n\n    def test_remove_options(self):\n        # https://github.com/conan-io/conan/issues/2327\n        # https://github.com/conan-io/conan/issues/2781\n        client = TestClient()\n        conanfile = \"\"\"from conan import ConanFile\nclass Pkg(ConanFile):\n    options = {\"opt1\": [True, False], \"opt2\": [True, False]}\n    default_options = {\"opt1\": True, \"opt2\": False}\n    def config_options(self):\n        del self.options.opt2\n    def build(self):\n        assert \"opt2\" not in self.options\n        self.options.opt2\n\"\"\"\n        client.save({\"conanfile.py\": conanfile})\n        build_folder = os.path.join(client.current_folder, \"build\")\n        mkdir(build_folder)\n        client.current_folder = build_folder\n        client.run(\"install ..\")\n        client.run(\"build ..\", assert_error=True)\n        assert \"ConanException: option 'opt2' doesn't exist\" in client.out\n        assert \"Possible options are ['opt1']\" in client.out\n\n    def test_remove_setting(self):\n        # https://github.com/conan-io/conan/issues/2327\n        client = TestClient()\n        conanfile = \"\"\"from conan import ConanFile\nclass Pkg(ConanFile):\n    settings = \"os\", \"build_type\"\n    def configure(self):\n        del self.settings.build_type\n\n    def build(self):\n        self.settings.build_type\n\"\"\"\n        client.save({\"conanfile.py\": conanfile})\n        build_folder = os.path.join(client.current_folder, \"build\")\n        mkdir(build_folder)\n        client.current_folder = build_folder\n\n        client.run(\"build ..\", assert_error=True)\n        assert \"'settings.build_type' doesn't exist\" in client.out\n\n\ndef test_settings_and_options_rm_safe():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    class Pkg(ConanFile):\n        settings = \"os\", \"build_type\", \"compiler\"\n        options = {\"opt1\": [True, False], \"opt2\": [True, False]}\n        default_options = {\"opt1\": \"True\", \"opt2\": \"False\"}\n\n        def configure(self):\n            # setting\n            self.settings.rm_safe(\"build_type\")\n            # sub-setting\n            self.settings.rm_safe(\"compiler.version\")\n            # wrong settings\n            self.settings.rm_safe(\"fake_field\")\n            self.settings.rm_safe(\"fake_field.version\")\n\n        def config_options(self):\n            # option\n            self.options.rm_safe(\"opt2\")\n            # wrong option\n            self.options.rm_safe(\"opt15\")\n\n        def build(self):\n            try:\n                self.settings.build_type\n            except Exception as exc:\n                self.output.warning(str(exc))\n            try:\n                self.settings.compiler.version\n            except Exception as exc:\n                self.output.warning(str(exc))\n            try:\n                self.options.opt2\n            except Exception as exc:\n                self.output.warning(str(exc))\n            assert \"opt2\" not in self.options\n    \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"install .\")\n    client.run(\"build .\")\n    assert \"'settings.build_type' doesn't exist\" in client.out\n    assert \"'settings' possible configurations are ['compiler', 'os']\" in client.out\n    assert \"'settings.compiler.version' doesn't exist\" in client.out\n    assert \"'settings.compiler' possible configurations are [\" in client.out\n    assert \"option 'opt2' doesn't exist\" in client.out\n    assert \"Possible options are ['opt1']\" in client.out\n"
  },
  {
    "path": "test/integration/settings/settings_override_test.py",
    "content": "import os\n\nimport pytest\n\nfrom conan.api.model import RecipeReference\nfrom conan.internal.paths import CONANINFO\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import load\n\n\n@pytest.fixture()\ndef client():\n    client = TestClient()\n    conanfile = GenConanfile(\"mingw\", \"0.1\").with_settings(\"compiler\")\n    build_msg = \"\"\"\n    def build(self):\n        self.output.warning(\"COMPILER=> %s %s\" % (self.name, str(self.settings.compiler)))\n    \"\"\"\n    client.save({\"conanfile.py\": str(conanfile) + build_msg})\n    client.run(\"export . --user=lasote --channel=testing\")\n    conanfile = GenConanfile(\"visual\", \"0.1\").with_requires(\"mingw/0.1@lasote/testing\")\n    conanfile.with_settings(\"compiler\")\n    client.save({\"conanfile.py\": str(conanfile) + build_msg})\n    client.run(\"export . --user=lasote --channel=testing\")\n    return client\n\n\ndef test_override(client):\n    client.run(\"install --requires=visual/0.1@lasote/testing --build missing -s compiler=msvc \"\n               \"-s compiler.version=191 -s compiler.runtime=dynamic \"\n               \"-s mingw*:compiler='gcc' -s mingw*:compiler.libcxx='libstdc++' \"\n               \"-s mingw*:compiler.version=4.8\")\n\n    assert \"COMPILER=> mingw gcc\" in client.out\n    assert \"COMPILER=> visual msvc\" in client.out\n\n    # CHECK CONANINFO FILE\n    latest_rrev = client.cache.get_latest_recipe_revision(\n        RecipeReference.loads(\"mingw/0.1@lasote/testing\"))\n    pkg_ids = client.cache.get_package_references(latest_rrev)\n    latest_prev = client.cache.get_latest_package_revision(pkg_ids[0])\n    package_path = client.cache.pkg_layout(latest_prev).package()\n    conaninfo = load(os.path.join(package_path, CONANINFO))\n    assert \"compiler=gcc\" in conaninfo\n\n    # CHECK CONANINFO FILE\n    package_path = client.created_layout().package()\n    conaninfo = load(os.path.join(package_path, CONANINFO))\n    assert \"compiler=msvc\" in conaninfo\n    assert \"compiler.version=191\" in conaninfo\n\n\ndef test_non_existing_setting(client):\n    client.run(\"install --requires=visual/0.1@lasote/testing --build missing -s compiler=msvc \"\n               \"-s compiler.version=191 -s compiler.runtime=dynamic \"\n               \"-s mingw/*:missingsetting='gcc' \", assert_error=True)\n    assert \"settings.missingsetting' doesn't exist\" in client.out\n\n\ndef test_override_in_non_existing_recipe(client):\n    client.run(\"install --requires=visual/0.1@lasote/testing --build missing -s compiler=msvc \"\n               \"-s compiler.version=191 -s compiler.runtime=dynamic \"\n               \"-s MISSINGID:compiler='gcc' \")\n\n    assert \"COMPILER=> mingw msvc\" in client.out\n    assert \"COMPILER=> visual msvc\" in client.out\n\n\ndef test_exclude_patterns_settings():\n\n    client = TestClient()\n    gen = GenConanfile().with_settings(\"build_type\")\n    client.save({\"zlib/conanfile.py\": gen})\n    client.save({\"openssl/conanfile.py\": gen.with_require(\"zlib/1.0\")})\n    client.save({\"consumer/conanfile.py\": gen.with_require(\"openssl/1.0\")})\n    client.run(\"create zlib --name zlib --version 1.0\")\n    client.run(\"create openssl --name openssl --version 1.0\")\n\n    # We miss openssl and zlib debug packages\n    client.run(\"install consumer -s build_type=Debug\", assert_error=True)\n    assert \"ERROR: Missing prebuilt package for 'openssl/1.0', 'zlib/1.0'\" in client.out\n\n    # All except zlib are Release, the only missing is zlib debug\n    client.run(\"install consumer -s build_type=Debug \"\n               \"                 -s !zlib*:build_type=Release\", assert_error=True)\n    assert \"ERROR: Missing prebuilt package for 'zlib/1.0'\"\n\n    # All the packages matches !potato* so all are Release\n    client.run(\"install consumer -s build_type=Debug -s !potato*:build_type=Release\")\n\n    # All the packages except the consumer are Release, but we are creating consumer in Debug\n    client.run(\"create consumer --name=consumer --version=1.0 \"\n               \"-s=build_type=Debug -s=!&:build_type=Release\")\n\n    client.run(\"install --requires consumer/1.0 -s consumer/*:build_type=Debug\")\n\n    # Priority between package scoped settings\n    client.run('remove consumer/*#* -c')\n    client.run(\"install --reference consumer/1.0 -s build_type=Debug\", assert_error=True)\n    # Pre-check, there is no Debug package for any of them\n    assert \"ERROR: Missing prebuilt package for 'consumer/1.0', 'openssl/1.0', 'zlib/1.0'\"\n    # Pre-check there are Release packages\n    client.run(\"create consumer --name=consumer --version=1.0 -s build_type=Release\")\n\n    # Try to install with this two scoped conditions, This is OK the right side has priority\n    client.run(\"install --requires consumer/1.0 -s zlib/*:build_type=Debug -s *:build_type=Release\")\n\n    # Try to install with this two scoped conditions, This is ERROR the right side has priority\n    client.run(\"install --requires consumer/1.0 -s *:build_type=Release -s zlib/*:build_type=Debug\",\n               assert_error=True)\n    assert \"ERROR: Missing prebuilt package for 'zlib/1.0'\" in client.out\n\n    # Try to install with this two scoped conditions, This is OK again, the right side has priority\n    # The z* points to Release later, so zlib in Release\n    client.run(\"install --requires consumer/1.0 -s *:build_type=Release \"\n               \"-s zlib/*:build_type=Debug -s z*:build_type=Release\")\n\n    # Try to install with this two scoped conditions, This is OK again, the right side has priority\n    # No package is potato, so all packages in Release\n    client.run(\"install --requires consumer/1.0 -s !zlib:build_type=Debug \"\n               \"-s !potato:build_type=Release\")\n\n"
  },
  {
    "path": "test/integration/settings/test_disable_settings_assignment.py",
    "content": "import textwrap\n\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_disable_settings_assignment():\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            settings = \"os\"\n            def generate(self):\n                self.settings.os = \"FreeBSD\"\n            \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"install .\", assert_error=True)\n    assert \"Tried to define 'os' setting inside recipe\" in c.out\n"
  },
  {
    "path": "test/integration/settings/test_non_defining_settings.py",
    "content": "import textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_settings_not_defined_consuming():\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"1.0\"\n            settings = \"os\", \"arch\"\n\n            def build(self):\n                self.output.info(f\"Building with os={self.settings.os}\")\n                self.output.info(f\"Building with arch={self.settings.arch}\")\n\n            def package_id(self):\n                del self.info.settings.os\n                del self.info.settings.arch\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile,\n            \"profile\": \"\"})\n    c.run(\"create . -pr=profile -s os=Windows -s arch=armv8\")\n    assert \"Building with os=Windows\" in c.out\n    assert \"Building with arch=armv8\" in c.out\n    c.run(\"install --requires=pkg/1.0 -pr=profile\")\n    # It doesn't fail, even if settings not defined\n    c.run(\"install --requires=pkg/1.0 -pr=profile -s os=Linux -s arch=x86\")\n    # It doesn't fail, even if settings different value\n\n\ndef test_settings_undefined():\n    client = TestClient()\n    client.save({\n        \"conanfile.py\": GenConanfile(name=\"hello\", version=\"1.0\")\n    })\n    # Undefined settings field\n    client.run(\"install . -s foo=None\", assert_error=True)\n    assert \"'settings.foo' doesn't exist for 'settings'\" in client.out\n    client.run(\"install . -s foo.bar=None\", assert_error=True)\n    assert \"'settings.foo' doesn't exist for 'settings'\" in client.out\n"
  },
  {
    "path": "test/integration/settings/test_settings_possible_values.py",
    "content": "import textwrap\n\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_settings_definitions():\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            settings = \"os\"\n            def generate(self):\n                definition = self.settings.possible_values()\n                assert \"os\" in definition\n                assert \"compiler\" not in definition\n                assert \"arch\" not in definition\n                self.output.info(\", \".join(definition[\"os\"]))\n                ios = definition[\"os\"][\"iOS\"][\"version\"]\n                self.output.info(f\"iOS: {ios}\")\n\n                os_definition = self.settings.os.possible_values()\n                ios = os_definition[\"iOS\"][\"version\"]\n                self.output.info(f\"iOS2: {ios}\")\n            \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    # New settings are there\n    c.run(\"install . -s os=Linux\")\n    assert \"conanfile.py: Windows, WindowsStore, WindowsCE, Linux,\" in c.out\n    assert \"conanfile.py: iOS: ['7.0', '7.1', '8.0',\" in c.out\n    assert \"conanfile.py: iOS2: ['7.0', '7.1', '8.0',\" in c.out\n\n\ndef test_settings_definitions_compiler():\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            settings = \"compiler\"\n            def generate(self):\n                definition = self.settings.compiler.version.possible_values()\n                self.output.info(\"HOST: \" + \", \".join(definition))\n                definition = self.settings_build.compiler.version.possible_values()\n                self.output.info(\"BUILD: \" + \", \".join(definition))\n                cppstds = self.settings.compiler.cppstd.possible_values()\n                self.output.info(\"CPPSTDS: \" + str(cppstds))\n            \"\"\")\n    profile = textwrap.dedent(\"\"\"\\\n        [settings]\n        compiler=msvc\n        compiler.version=192\n        compiler.runtime=dynamic\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile,\n            \"profile\": profile})\n    # New settings are there\n    c.run(\"install . -pr=profile -s:b compiler=gcc\")\n    assert \"conanfile.py: HOST: 170, 180, 190, 191, 192\" in c.out\n    assert \"conanfile.py: BUILD: 4.1, 4.4, 4.5, 4.6, 4.7,\" in c.out\n    assert \"conanfile.py: CPPSTDS: [None, '14', '17', '20', '23']\" in c.out\n"
  },
  {
    "path": "test/integration/settings/test_settings_user.py",
    "content": "import os\nimport textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import save\n\n\ndef test_settings_user():\n    c = TestClient()\n    settings_user = textwrap.dedent(\"\"\"\\\n        os:\n            Windows:\n                subsystem: [new_sub]\n            Linux:\n                new_versions: [\"a\", \"b\", \"c\"]\n            new_os:\n        new_global: [\"42\", \"21\"]\n        \"\"\")\n    save(os.path.join(c.cache_folder, \"settings_user.yml\"), settings_user)\n    c.save({\"conanfile.py\": GenConanfile().with_settings(\"os\").with_settings(\"new_global\")})\n    # New settings are there\n    c.run(\"install . -s os=Windows -s os.subsystem=new_sub -s new_global=42\")\n    assert \"new_global=42\" in c.out\n    assert \"os.subsystem=new_sub\" in c.out\n    # Existing values of subsystem are still there\n    c.run(\"install . -s os=Windows -s os.subsystem=msys2 -s new_global=42\")\n    assert \"new_global=42\" in c.out\n    assert \"os.subsystem=msys2\" in c.out\n    # Completely new values, not appended, but new, are there\n    c.run(\"install . -s os=Linux -s os.new_versions=a -s new_global=42\")\n    assert \"new_global=42\" in c.out\n    assert \"os.new_versions=a\" in c.out\n    # Existing values of OSs are also there\n    c.run(\"install . -s os=Macos -s new_global=42\")\n    assert \"os=Macos\" in c.out\n    assert \"new_global=42\" in c.out\n\n\ndef test_settings_user_subdict():\n    c = TestClient()\n    settings_user = textwrap.dedent(\"\"\"\\\n        other_new:\n            other1:\n            other2:\n                version: [1, 2, 3]\n        \"\"\")\n    save(os.path.join(c.cache_folder, \"settings_user.yml\"), settings_user)\n    c.save({\"conanfile.py\": GenConanfile().with_settings(\"other_new\")})\n    c.run(\"install . -s other_new=other1\")\n    assert \"other_new=other1\" in c.out\n    c.run(\"install . -s other_new=other2 -s other_new.version=2\")\n    assert \"other_new=other2\" in c.out\n    assert \"other_new.version=2\" in c.out\n\n\ndef test_settings_user_convert_list_dict():\n    c = TestClient()\n    settings_user = textwrap.dedent(\"\"\"\\\n        arch:\n            x86:\n                subarch32:\n                    a:\n                        version: [\"a1\", \"a2\"]\n                    b:\n                        variant: [\"b1\", \"b2\"]\n            x86_64:\n                subarch: [1, 2, 3]\n          \"\"\")\n    save(os.path.join(c.cache_folder, \"settings_user.yml\"), settings_user)\n    c.save({\"conanfile.py\": GenConanfile().with_settings(\"arch\")})\n    # check others are maintained\n    c.run(\"install . -s arch=armv8\")\n    assert \"arch=armv8\" in c.out\n\n    c.run(\"install . -s arch=x86 -s arch.subarch32=a -s arch.subarch32.version=a1\")\n    assert \"arch=x86\" in c.out\n    assert \"arch.subarch32=a\" in c.out\n    assert \"arch.subarch32.version=a1\" in c.out\n\n    c.run(\"install . -s arch=x86_64 -s arch.subarch=2 \")\n    assert \"arch=x86_64\" in c.out\n    assert \"arch.subarch=2\" in c.out\n\n\ndef test_settings_user_error():\n    c = TestClient()\n    settings_user = textwrap.dedent(\"\"\"\\\n        os:\n            Windows:\n                libc: null\n        \"\"\")\n    save(os.path.join(c.cache_folder, \"settings_user.yml\"), settings_user)\n    c.run(\"profile show\", assert_error=True)\n    assert \"ERROR: Definition of settings.yml 'settings.os.libc' cannot be null\" in c.out\n\n\ndef test_settings_user_breaking_universal_binaries():\n    # If you had a settings_user.yml with a custom architecture wit will error\n    # in the Apple block of CMakeToolchain\n    # https://github.com/conan-io/conan/issues/16086#issuecomment-2059118224\n    c = TestClient()\n    settings_user = textwrap.dedent(\"\"\"\\\n        arch: [universal]\n        \"\"\")\n    save(os.path.join(c.cache_folder, \"settings_user.yml\"), settings_user)\n    c.save({\"conanfile.py\": GenConanfile().with_settings(\"os\").with_settings(\"arch\").with_generator(\"CMakeToolchain\")})\n    c.run('install . -s=\"arch=universal\"')\n    assert \"CMakeToolchain generated: conan_toolchain.cmake\" in c.out\n"
  },
  {
    "path": "test/integration/symlinks/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/symlinks/symlinks_test.py",
    "content": "import os\nimport platform\nimport textwrap\n\nimport pytest\n\nfrom conan.api.model import PkgReference\nfrom conan.api.model import RecipeReference\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient, TestServer\nfrom conan.internal.util.files import load, rmdir, chdir, save\n\nlinks_conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    from conan.tools.files import copy\n\n    class HelloConan(ConanFile):\n        name = \"hello\"\n        version = \"0.1\"\n        exports_sources = \"*\"\n\n        def package(self):\n            copy(self, \"*\", self.build_folder, self.package_folder)\n    \"\"\")\n\n\n@pytest.mark.skipif(platform.system() == \"Windows\", reason=\"Requires Symlinks\")\ndef test_complete_round_trip():\n    \"\"\" a full round trip with a in package symlink, that is maintained all the way to\n    the server and re-deployed in the client\n    the symlink is relative just \"link.txt\" -> \"midlink.txt\" -> \"target.txt\" (local)\n    \"\"\"\n    c = TestClient(default_server_user=True)\n    c.save({\"conanfile.py\": links_conanfile,\n            \"target.txt\": \"hello world!\"})\n    os.symlink(\"target.txt\", os.path.join(c.current_folder, \"midlink.txt\"))\n    os.symlink(\"midlink.txt\", os.path.join(c.current_folder, \"link.txt\"))\n    assert c.load(\"link.txt\") == \"hello world!\"\n\n    c.run(\"create .\")\n\n    def checker(folder):\n        with chdir(folder):\n            assert os.path.exists(\"target.txt\")\n            assert os.readlink(\"link.txt\") == \"midlink.txt\"\n            assert os.readlink(\"midlink.txt\") == \"target.txt\"\n            assert load(\"link.txt\") == \"hello world!\"\n\n    ref = RecipeReference.loads(\"hello/0.1\")\n    checker(c.get_latest_ref_layout(ref).source())\n    pref = c.get_latest_package_reference(ref)\n    pkg_layout = c.get_latest_pkg_layout(pref)\n    checker(pkg_layout.build())\n    checker(pkg_layout.package())\n\n    c.run(\"upload * -r=default -c\")\n    c.run(\"remove * -c\")\n    c.save({}, clean_first=True)\n    c.run(\"install --requires=hello/0.1 --deployer=full_deploy\")\n    checker(os.path.join(c.current_folder, \"full_deploy\", \"host\", \"hello\", \"0.1\"))\n\n\n@pytest.mark.skipif(platform.system() == \"Windows\", reason=\"Requires Symlinks\")\ndef test_complete_round_trip_broken_link():\n    \"\"\" same as above but with a broken one\n    link.txt->midlink.txt->(broken)\n    \"\"\"\n    c = TestClient(default_server_user=True)\n    c.save({\"conanfile.py\": links_conanfile})\n    os.symlink(\"target.txt\", os.path.join(c.current_folder, \"midlink.txt\"))\n    os.symlink(\"midlink.txt\", os.path.join(c.current_folder, \"link.txt\"))\n\n    c.run(\"create .\")\n\n    def checker(folder):\n        with chdir(folder):\n            assert not os.path.exists(\"target.txt\")\n            assert os.readlink(\"link.txt\") == \"midlink.txt\"\n            assert os.readlink(\"midlink.txt\") == \"target.txt\"\n\n    ref = RecipeReference.loads(\"hello/0.1\")\n    checker(c.get_latest_ref_layout(ref).source())\n    pref = c.get_latest_package_reference(ref)\n    pkg_layout = c.get_latest_pkg_layout(pref)\n    checker(pkg_layout.build())\n    checker(pkg_layout.package())\n\n    c.run(\"upload * -r=default -c\")\n    c.run(\"remove * -c\")\n    c.save({}, clean_first=True)\n    c.run(\"install --requires=hello/0.1 --deployer=full_deploy\")\n    checker(os.path.join(c.current_folder, \"full_deploy\", \"host\", \"hello\", \"0.1\"))\n\n\n@pytest.mark.skipif(platform.system() == \"Windows\", reason=\"Requires Symlinks\")\ndef test_complete_round_trip_external_link():\n    \"\"\" same as above but with a broken one\n    link.txt->midlink.txt->/abs/path/to/target.txt\n    \"\"\"\n    c = TestClient(default_server_user=True)\n    target = os.path.join(temp_folder(), \"target.txt\")\n    save(target, \"foo\")\n\n    c.save({\"conanfile.py\": links_conanfile})\n    os.symlink(target, os.path.join(c.current_folder, \"midlink.txt\"))\n    os.symlink(\"midlink.txt\", os.path.join(c.current_folder, \"link.txt\"))\n\n    c.run(\"create .\")\n\n    def checker(folder):\n        with chdir(folder):\n            assert \"target.txt\" not in os.listdir(\".\")\n            assert not os.path.exists(\"target.txt\")\n            assert os.readlink(\"link.txt\") == \"midlink.txt\"\n            assert os.readlink(\"midlink.txt\") == target\n            assert load(\"link.txt\") == \"foo\"\n\n    ref = RecipeReference.loads(\"hello/0.1\")\n    checker(c.get_latest_ref_layout(ref).source())\n    pref = c.get_latest_package_reference(ref)\n    pkg_layout = c.get_latest_pkg_layout(pref)\n    checker(pkg_layout.build())\n    checker(pkg_layout.package())\n\n    c.run(\"upload * -r=default -c\")\n    c.run(\"remove * -c\")\n    c.save({}, clean_first=True)\n    c.run(\"install --requires=hello/0.1 --deployer=full_deploy\")\n    checker(os.path.join(c.current_folder, \"full_deploy\", \"host\", \"hello\", \"0.1\"))\n\n\n@pytest.mark.skipif(platform.system() == \"Windows\", reason=\"Requires Symlinks\")\ndef test_complete_round_trip_folders():\n    \"\"\" similar to above, but with 2 folder symlinks and one file symlink\n    # Reproduces issue: https://github.com/conan-io/conan/issues/5329\n    \"\"\"\n    c = TestClient(default_server_user=True)\n\n    c.save({\"conanfile.py\": links_conanfile,\n            \"src/framework/Versions/v1/headers/content\": \"myheader!\",\n            \"src/framework/Versions/v1/file\": \"myfile!\"})\n\n    # Add two levels of symlinks\n    os.symlink('v1', os.path.join(c.current_folder, 'src', 'framework', 'Versions', 'Current'))\n    os.symlink('Versions/Current/headers',\n               os.path.join(c.current_folder, 'src', 'framework', 'headers'))\n    os.symlink('Versions/Current/file',\n               os.path.join(c.current_folder, 'src', 'framework', 'file'))\n\n    c.run(\"create .\")\n\n    def checker(folder):\n        with chdir(folder):\n            assert os.readlink(\"src/framework/Versions/Current\") == \"v1\"\n            assert os.readlink(\"src/framework/headers\") == \"Versions/Current/headers\"\n            assert os.readlink(\"src/framework/file\") == \"Versions/Current/file\"\n            assert os.path.exists(\"src/framework/Versions/v1/headers/content\")\n            assert os.path.exists(\"src/framework/Versions/v1/file\")\n\n            assert load(\"src/framework/file\") == \"myfile!\"\n            assert load(\"src/framework/headers/content\") == \"myheader!\"\n\n    ref = RecipeReference.loads(\"hello/0.1\")\n    checker(c.get_latest_ref_layout(ref).source())\n    pref = c.get_latest_package_reference(ref)\n    pkg_layout = c.get_latest_pkg_layout(pref)\n    checker(pkg_layout.build())\n    checker(pkg_layout.package())\n\n    c.run(\"upload * -r=default -c\")\n    c.run(\"remove * -c\")\n    c.save({}, clean_first=True)\n    c.run(\"install --requires=hello/0.1 --deployer=full_deploy\")\n    checker(os.path.join(c.current_folder, \"full_deploy\", \"host\", \"hello\", \"0.1\"))\n\n\n@pytest.mark.skipif(platform.system() != \"Linux\", reason=\"Only linux\")\n@pytest.mark.parametrize(\"package_files\",\n                         [{\"files\": [\"foo/bar/folder/file.txt\",\n                                     \"foo/bar/folder/other/other_file.txt\"],\n                           \"symlinks\": [(\"../file.txt\", \"foo/bar/folder/other/file2.txt\")]},\n                          # relative ../ symlink\n                          {\"files\": [\"foo/bar/file/file.txt\"],\n                           \"symlinks\": [(temp_folder(), \"foo/symlink_folder\")]},  # absolute symlink\n                          {\"files\": [\"folder/file.txt\"],\n                           \"symlinks\": [(\"folder\", \"folder2\"),\n                                        (\"file.txt\", \"folder/file2.txt\")]},  # single level symlink\n                          {\"files\": [\"foo/bar/file/file.txt\"],\n                           \"symlinks\": [(\"bar/file\", \"foo/symlink_folder\"),\n                                        (\"foo/symlink_folder/file.txt\", \"file2.txt\")]},\n                          # double level symlink\n                          ])\ndef test_package_with_symlinks(package_files):\n\n    client = TestClient(default_server_user=True)\n    client2 = TestClient(servers=client.servers)\n    client.save({\"conanfile.py\": links_conanfile})\n\n    for path in package_files[\"files\"]:\n        client.save({path: \"foo contents\"})\n\n    for link_dest, link_file in package_files[\"symlinks\"]:\n        os.symlink(link_dest, os.path.join(client.current_folder, link_file))\n\n    client.run(\"create .\")\n\n    def assert_folder_symlinks(base_folder):\n        with chdir(base_folder):\n            for f in package_files[\"files\"]:\n                assert os.path.exists(f)\n            for link_dst, link in package_files[\"symlinks\"]:\n                assert os.readlink(link) == link_dst\n                if os.path.isfile(link):\n                    assert load(link) == \"foo contents\"\n\n    # Check exported sources are there\n    ref_layout = client.exported_layout()\n    assert_folder_symlinks(ref_layout.export_sources())\n    assert_folder_symlinks(ref_layout.source())\n\n    # Check files have been copied to the build\n    pkg_layout = client.created_layout()\n    assert_folder_symlinks(pkg_layout.build())\n    assert_folder_symlinks(pkg_layout.package())\n\n    client.run(\"upload '*' -c -r default\")\n    client.run(\"remove * -c\")\n\n    # Client 2 install\n    client2.run(\"install --requires=hello/0.1 --deployer=full_deploy\")\n    ref = client2.get_latest_ref_layout(RecipeReference.loads(\"hello/0.1\"))\n    pref = PkgReference(ref.reference, \"da39a3ee5e6b4b0d3255bfef95601890afd80709\")\n\n    # Check package files are there\n    package_folder = client2.get_latest_pkg_layout(pref).package()\n    assert_folder_symlinks(package_folder)\n    assert_folder_symlinks(os.path.join(client2.current_folder, \"full_deploy\", \"host\", \"hello\", \"0.1\"))\n\n\n@pytest.mark.skipif(platform.system() == \"Windows\", reason=\"Symlinks not in Windows\")\ndef test_exports_does_not_follow_symlink():\n    tmp = temp_folder()\n    linked_abs_folder = tmp\n    save(os.path.join(tmp, \"source.cpp\"), \"foo\")\n    client = TestClient(default_server_user=True)\n    conanfile = GenConanfile(\"lib\", \"1.0\")\\\n        .with_package('copy(self, \"*\", self.source_folder, self.package_folder)')\\\n        .with_exports_sources(\"*\")\\\n        .with_import(\"from conan.tools.files import copy\")\n    client.save({\"conanfile.py\": conanfile, \"foo.txt\": \"bar\"})\n    os.symlink(linked_abs_folder, os.path.join(client.current_folder, \"linked_folder\"))\n    client.run(\"create . \")\n    exports_sources_folder = client.exported_layout().export_sources()\n    assert os.path.islink(os.path.join(exports_sources_folder, \"linked_folder\"))\n    assert os.path.exists(os.path.join(exports_sources_folder, \"linked_folder\", \"source.cpp\"))\n\n    # Check files have been copied to the build\n    build_folder = client.created_layout().build()\n    assert os.path.islink(os.path.join(build_folder, \"linked_folder\"))\n    assert os.path.exists(os.path.join(build_folder, \"linked_folder\", \"source.cpp\"))\n\n    # Check package files are there\n    package_folder = client.created_layout().package()\n    assert os.path.islink(os.path.join(package_folder, \"linked_folder\"))\n    assert os.path.exists(os.path.join(package_folder, \"linked_folder\", \"source.cpp\"))\n\n    # Check that the manifest doesn't contain the symlink nor the source.cpp\n    contents = load(os.path.join(package_folder, \"conanmanifest.txt\"))\n    assert \"foo.txt\" in contents\n    assert \"linked_folder\" not in contents\n    assert \"source.cpp\" not in contents\n\n    # Now is a broken link, but the files are not in the cache, just a broken link\n    rmdir(linked_abs_folder)\n    assert not os.path.exists(os.path.join(exports_sources_folder, \"linked_folder\", \"source.cpp\"))\n    assert not os.path.exists(os.path.join(build_folder, \"linked_folder\", \"source.cpp\"))\n    assert not os.path.exists(os.path.join(package_folder, \"linked_folder\", \"source.cpp\"))\n\n\n@pytest.mark.skipif(platform.system() == \"Windows\", reason=\"Symlinks not in Windows\")\n@pytest.mark.parametrize(\"uppercase\", [False, True])\ndef test_exports_with_uppercase_symlink_folder(uppercase):\n    # BaseFolder\n    #     |- Folder\n    #           |- source.cpp\n    #     |- Symlink (Points to \"./Folder\")\n    base_dir_name = \"BaseFolder\" if uppercase else \"basefolder\"\n\n    client = TestClient(default_server_user=True)\n    conanfile = GenConanfile(\"lib\", \"1.0\")\\\n        .with_package('copy(self, \"*\", self.source_folder, self.package_folder, ignore_case=False)')\\\n        .with_exports_sources(base_dir_name + \"/*\")\\\n        .with_import(\"from conan.tools.files import copy\")\n\n    folder_dir_name = \"Folder\" if uppercase else \"folder\"\n    folder_dir_path = os.path.join(base_dir_name, folder_dir_name)\n\n    symlink_name = \"SymLink\" if uppercase else \"symlink\"\n    symlink_path = os.path.join(base_dir_name, symlink_name)\n\n    dummy_file_name = \"source.cpp\"\n    dummy_file_path = os.path.join(folder_dir_path, dummy_file_name)\n\n    client.save({\"conanfile.py\": conanfile,\n                 dummy_file_path: \"foo\"})\n\n    os.symlink(folder_dir_name,  os.path.join(client.current_folder, symlink_path))\n\n    client.run(\"create . \")\n\n    exports_sources_folder = client.exported_layout().export_sources()\n    assert os.path.islink(os.path.join(exports_sources_folder, symlink_path))\n    assert os.path.exists(os.path.join(exports_sources_folder, symlink_path, dummy_file_name))\n\n    # Check files have been copied to the build\n    build_folder = client.created_layout().build()\n    assert os.path.islink(os.path.join(build_folder, symlink_path))\n    assert os.path.exists(os.path.join(build_folder, symlink_path, dummy_file_name))\n\n    # Check package files are there\n    package_folder = client.created_layout().package()\n    assert os.path.islink(os.path.join(package_folder, symlink_path))\n    assert os.path.exists(os.path.join(package_folder, symlink_path, dummy_file_name))\n\n    # Check that the manifest doesn't contain the symlink to the source.cpp\n    contents = load(os.path.join(package_folder, \"conanmanifest.txt\"))\n    assert symlink_path not in contents\n    assert dummy_file_path in contents\n    assert os.path.join(symlink_path, dummy_file_name) not in contents\n\n\n@pytest.mark.skipif(platform.system() != \"Linux\", reason=\"Only linux\")\ndef test_package_symlinks_zero_size():\n    server = TestServer()\n    client = TestClient(servers={\"default\": server}, inputs=[\"admin\", \"password\"])\n\n    conanfile = \"\"\"\nimport os\nfrom conan import ConanFile\nfrom conan.tools.files import save\n\nclass HelloConan(ConanFile):\n    name = \"hello\"\n    version = \"0.1\"\n\n    def package(self):\n        # Link to file.txt and then remove it\n        save(self, os.path.join(self.package_folder, \"file.txt\"), \"contents\")\n        os.symlink(\"file.txt\", os.path.join(self.package_folder, \"link.txt\"))\n\"\"\"\n    client.save({\"conanfile.py\": conanfile})\n    # By default it is not allowed\n    client.run(\"create .\")\n    p_folder = client.created_layout().download_package()\n    # Upload, it will create the tgz\n    client.run(\"upload * -r=default -c\")\n\n    # We can uncompress it without warns\n    tgz = os.path.join(p_folder, \"conan_package.tgz\")\n    client.run_command('gzip -d \"{}\"'.format(tgz))\n    client.run_command('tar tvf \"{}\"'.format(os.path.join(p_folder, \"conan_package.tar\")))\n    lines = str(client.out).splitlines()\n    \"\"\"\n-rw-r--r-- 0/0               8 1970-01-01 01:00 file.txt\nlrw-r--r-- 0/0               0 1970-01-01 01:00 link.txt -> file.txt\n    \"\"\"\n\n    assert \"link.txt\" in \" \".join(lines)\n    for line in lines:\n        assert \".txt\" in line\n        size = int([i for i in line.split(\" \") if i][2])\n        if \"link.txt\" in line:\n            assert int(size) == 0\n        elif \"file.txt\":\n            assert int(size) > 0\n"
  },
  {
    "path": "test/integration/sysroot_test.py",
    "content": "from conan.test.utils.tools import TestClient\n\n\nclass TestSysroot:\n\n    def test(self):\n        client = TestClient()\n        sysroot = \"\"\"from conan import ConanFile\nclass Pkg(ConanFile):\n    def package_info(self):\n        self.cpp_info.sysroot = \"HelloSysRoot\"\n\"\"\"\n        client.save({\"conanfile.py\": sysroot})\n        client.run(\"create . --name=sysroot --version=0.1 --user=user --channel=testing\")\n\n        conanfile = \"\"\"from conan import ConanFile\nclass Pkg(ConanFile):\n    requires = \"sysroot/0.1@user/testing\"\n    def build(self):\n        self.output.info(\"PKG SYSROOT: %s\" % self.dependencies[\"sysroot\"].cpp_info.sysroot)\n    def package_info(self):\n        self.cpp_info.sysroot = \"HelloSysRoot\"\n\"\"\"\n        test_conanfile = \"\"\"from conan import ConanFile\nclass Pkg(ConanFile):\n    def requirements(self):\n        self.requires(self.tested_reference_str)\n    def build(self):\n        self.output.info(\"Test SYSROOT: %s\"\n                          % self.dependencies[\"sysroot\"].cpp_info.sysroot)\n    def test(self):\n        pass\n\"\"\"\n        client.save({\"conanfile.py\": conanfile,\n                     \"test_package/conanfile.py\": test_conanfile})\n        client.run(\"create . --name=pkg --version=0.1 --user=user --channel=testing\")\n        assert \"pkg/0.1@user/testing: PKG SYSROOT: HelloSysRoot\" in client.out\n        assert \"pkg/0.1@user/testing (test package): Test SYSROOT: HelloSysRoot\" in client.out\n\n        client.run(\"install .\")\n"
  },
  {
    "path": "test/integration/system_reqs_test.py",
    "content": "from conan.test.utils.tools import TestClient\n\nbase_conanfile = '''\nfrom conan import ConanFile\n\nclass TestSystemReqs(ConanFile):\n    name = \"test\"\n    version = \"0.1\"\n\n    def system_requirements(self):\n        self.output.info(\"*+Running system requirements+*\")\n'''\n\n\nclass TestSystemReqs:\n\n    def test_force_system_reqs_rerun(self):\n        client = TestClient()\n        client.save({'conanfile.py': base_conanfile})\n        client.run(\"create . \")\n        assert \"*+Running system requirements+*\" in client.out\n        client.run(\"install --requires=test/0.1\")\n        assert \"*+Running system requirements+*\" in client.out\n\n    def test_local_system_requirements(self):\n        client = TestClient()\n        client.save({'conanfile.py': base_conanfile})\n        client.run(\"install .\")\n        assert \"*+Running system requirements+*\" in client.out\n"
  },
  {
    "path": "test/integration/test_components.py",
    "content": "import textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_components_cycles():\n    \"\"\"c -> b -> a -> c\"\"\"\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class TestcycleConan(ConanFile):\n            name = \"testcycle\"\n            version = \"1.0\"\n\n            def package_info(self):\n                self.cpp_info.components[\"c\"].requires = [\"b\"]\n                self.cpp_info.components[\"b\"].requires = [\"a\"]\n                self.cpp_info.components[\"a\"].requires = [\"c\"] # cycle!\n        \"\"\")\n    test_conanfile = GenConanfile().with_test(\"pass\").with_generator(\"CMakeDeps\")\\\n        .with_settings(\"build_type\")\n    c.save({\"conanfile.py\": conanfile,\n            \"test_package/conanfile.py\": test_conanfile})\n    c.run(\"create .\", assert_error=True)\n    out = c.out\n    assert \"ERROR: Error in generator 'CMakeDeps': error generating context for 'testcycle/1.0': \" \\\n           \"There is a dependency loop in 'self.cpp_info.components' requires:\" in out\n    assert \"a requires c\" in out\n    assert \"b requires a\" in out\n    assert \"c requires b\" in out\n\n\ndef test_components_cycle_complex():\n    \"\"\"\n    Cycle: a -> b -> c -> d -> b\n    Isolated j declaring its libs\n    \"\"\"\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class TestcycleConan(ConanFile):\n            name = \"testcycle\"\n            version = \"1.0\"\n\n            def package_info(self):\n                self.cpp_info.components[\"a\"].requires = [\"b\"]\n                self.cpp_info.components[\"b\"].requires = [\"c\"]\n                self.cpp_info.components[\"c\"].requires = [\"d\"]\n                self.cpp_info.components[\"d\"].requires = [\"b\"]  # cycle!\n                self.cpp_info.components[\"j\"].libs = [\"libj\"]\n        \"\"\")\n    test_conanfile = GenConanfile().with_test(\"pass\").with_generator(\"CMakeDeps\") \\\n        .with_settings(\"build_type\")\n    c.save({\"conanfile.py\": conanfile,\n            \"test_package/conanfile.py\": test_conanfile})\n    c.run(\"create .\", assert_error=True)\n    out = c.out\n    assert \"ERROR: Error in generator 'CMakeDeps': error generating context for 'testcycle/1.0': \" \\\n           \"There is a dependency loop in 'self.cpp_info.components' requires:\" in out\n    assert \"a requires b\" in out\n    assert \"b requires c\" in out\n    assert \"c requires d\" in out\n    assert \"d requires b\" in out\n\n\ndef test_components_cycles_error():\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class TestcycleConan(ConanFile):\n            name = \"testcycle\"\n            version = \"1.0\"\n\n            def package_info(self):\n                self.cpp_info.components[\"c\"].requires = [\"b\", \"d\"]\n                self.cpp_info.components[\"b\"].requires = [\"a\"]\n                self.cpp_info.components[\"a\"].requires = [\"c\"] # cycle!\n                self.cpp_info.components[\"d\"].includedirs = []\n        \"\"\")\n    test_conanfile = GenConanfile().with_test(\"pass\").with_generator(\"CMakeDeps\")\\\n        .with_settings(\"build_type\")\n    c.save({\"conanfile.py\": conanfile,\n            \"test_package/conanfile.py\": test_conanfile})\n    c.run(\"create .\", assert_error=True)\n    assert \"ERROR: Error in generator 'CMakeDeps': error generating context for 'testcycle/1.0': \" \\\n           \"There is a dependency loop in 'self.cpp_info.components' requires:\" in c.out\n    assert \"a requires c\" in c.out\n    assert \"b requires a\" in c.out\n    assert \"c requires b\" in c.out\n\n\ndef test_components_not_required():\n    \"\"\"\n    Allow requiring and building against one component, but not propagating it\n    https://github.com/conan-io/conan/issues/12965\n\n    \"\"\"\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n           from conan import ConanFile\n\n           class TestcycleConan(ConanFile):\n            name = \"wayland\"\n            version = \"1.0\"\n            requires = \"expat/1.0\"\n\n            def package_info(self):\n                self.cpp_info.components[\"wayland-scanner\"].libdirs = []\n        \"\"\")\n    c.save({\"expat/conanfile.py\": GenConanfile(\"expat\", \"1.0\"),\n            \"wayland/conanfile.py\": conanfile})\n    c.run(\"create expat\")\n    c.run(\"create wayland\")\n    assert \"wayland/1.0: Created package\" in c.out\n\n\ndef test_components_overrides():\n    \"\"\"\n    overrides are not direct dependencies, and as such, they don't need to be mandatory\n    to specify in the components requires\n\n    https://github.com/conan-io/conan/issues/13922\n    \"\"\"\n    c = TestClient()\n    consumer = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class ConanRecipe(ConanFile):\n            name = \"app\"\n            version = \"0.1\"\n\n            def requirements(self):\n                self.requires(\"libffi/3.4.4\", override=True)\n                self.requires(\"glib/2.76.2\")\n\n            def package_info(self):\n                self.cpp_info.requires = [\"glib::glib\"]\n        \"\"\")\n    c.save({\"libffi/conanfile.py\": GenConanfile(\"libffi\"),\n           \"glib/conanfile.py\": GenConanfile(\"glib\", \"2.76.2\").with_requires(\"libffi/3.0\"),\n            \"app/conanfile.py\": consumer})\n    c.run(\"create libffi --version=3.0\")\n    c.run(\"create libffi --version=3.4.4\")\n    c.run(\"create glib\")\n    # This used to crash, because override was not correctly excluded\n    c.run(\"create app\")\n    assert \"app/0.1: Created package\" in c.out\n\n\ndef test_duplication_component_properties():\n    \"\"\" Regression for PR 17503 - component lists would be incorrectly aggregated \"\"\"\n    tc = TestClient(light=True)\n\n    dep = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n\n    class Dep(ConanFile):\n        name = \"dep\"\n        version = \"0.1\"\n\n        def package_info(self):\n            self.cpp_info.components[\"acomp\"].set_property(\"prop_list\", [\"value1\"])\n            self.cpp_info.components[\"bcomp\"].set_property(\"prop_list\", [\"value2\"])\n            self.cpp_info.components[\"ccomp\"].set_property(\"prop_list\", [\"value3\"])\n    \"\"\")\n\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n\n    class Pkg(ConanFile):\n        name = \"pkg\"\n        version = \"0.1\"\n        requires = \"dep/0.1\"\n\n        def generate(self):\n            # Calling this would break property lists of the last lex sorted component\n            aggregated_components = self.dependencies[\"dep\"].cpp_info.aggregated_components()\n            ccomp = self.dependencies[\"dep\"].cpp_info.components[\"ccomp\"]\n            self.output.info(\"ccomp list: \" + str(ccomp.get_property(\"prop_list\")))\n    \"\"\")\n\n    tc.save({\"dep/conanfile.py\": dep,\n             \"conanfile.py\": conanfile})\n    tc.run(\"create dep\")\n    tc.run(\"create .\")\n    # The bug would give ccomp the prop_list values of the other two components\n    assert \"pkg/0.1: ccomp list: ['value3', 'value2', 'value1']\" not in tc.out\n    assert \"pkg/0.1: ccomp list: ['value3']\" in tc.out\n"
  },
  {
    "path": "test/integration/test_components_error.py",
    "content": "import os\nimport re\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_component_error():\n    # https://github.com/conan-io/conan/issues/12027\n    c = TestClient()\n    t1 = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class t1Conan(ConanFile):\n            name = \"t1\"\n            version = \"0.1.0\"\n            package_type = \"static-library\"\n\n            def package_info(self):\n                self.cpp_info.components[\"comp1\"].set_property(\"cmake_target_name\", \"t1::comp1\")\n                self.cpp_info.components[\"comp2\"].set_property(\"cmake_target_name\", \"t1::comp2\")\n        \"\"\")\n    t2 = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class t2Conan(ConanFile):\n            name = \"t2\"\n            version = \"0.1.0\"\n            requires = \"t1/0.1.0\"\n            package_type = \"shared-library\"\n\n            def package_info(self):\n                self.cpp_info.requires.append(\"t1::comp1\")\n        \"\"\")\n    t3 = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class t3Conan(ConanFile):\n            name = \"t3\"\n            version = \"0.1.0\"\n            requires = \"t2/0.1.0\"\n            package_type = \"application\"\n            generators = \"CMakeDeps\"\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n        \"\"\")\n\n    c.save({\"t1/conanfile.py\": t1,\n            \"t2/conanfile.py\": t2,\n            \"t3/conanfile.py\": t3})\n    c.run(\"create t1\")\n    c.run(\"create t2\")\n    c.run(\"install t3\")\n\n    arch = c.get_default_host_profile().settings['arch']\n    assert 'list(APPEND t2_FIND_DEPENDENCY_NAMES )' in c.load(f\"t3/t2-release-{arch}-data.cmake\")\n    assert not os.path.exists(os.path.join(c.current_folder, \"t3/t1-config.cmake\"))\n\n\ndef test_verify_get_property_check_type():\n    c = TestClient(light=True)\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class HelloConan(ConanFile):\n            name = \"hello\"\n            version = \"0.1\"\n            def package_info(self):\n                self.cpp_info.set_property(\"test_property\", \"foo\")\n                self.cpp_info.get_property(\"test_property\", check_type=list)\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"create .\", assert_error=True)\n    assert 'The expected type for test_property is \"list\", but \"str\" was found' in c.out\n\n\n@pytest.mark.parametrize(\"component\", [True, False])\ndef test_unused_requirement(component):\n    \"\"\" Requires should include all listed requirements\n        This error is known when creating the package if the requirement is consumed.\n    \"\"\"\n\n    t = TestClient(light=True)\n    conanfile = textwrap.dedent(f\"\"\"\n        from conan import ConanFile\n        class Consumer(ConanFile):\n            name = \"wrong\"\n            version = \"version\"\n            requires = \"top/version\", \"top2/version\"\n            def package_info(self):\n                self.cpp_info{'.components[\"foo\"]' if component else ''}.requires = [\"top::other\"]\n    \"\"\")\n    t.save({\"top/conanfile.py\": GenConanfile().with_package_info({\"components\": {\"cmp1\": {\"libs\": [\"top_cmp1\"]}}}),\n            \"conanfile.py\": conanfile})\n    t.run('create top --name=top --version=version')\n    t.run('create top --name=top2 --version=version')\n    t.run('create .', assert_error=True)\n    assert \"ERROR: wrong/version: package_info(): The direct dependency 'top2' is not used \" \\\n           \"by any '(cpp_info/components).requires'.\" in t.out\n\n\ndef test_unused_requirement_not_propagated():\n    # https://github.com/conan-io/conan/issues/19026\n    t = TestClient()\n    conanfile = textwrap.dedent(f\"\"\"\n        from conan import ConanFile\n        class Consumer(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            requires = \"header/0.1\", \"lib/0.1\"\n\n            def package_info(self):\n                self.cpp_info.requires = [\"lib::lib\", \"header::header\"]\n    \"\"\")\n    t.save({\"header/conanfile.py\": GenConanfile(\"header\", \"0.1\").with_package_type(\"header-library\"),\n            \"lib/conanfile.py\": GenConanfile(\"lib\", \"0.1\").with_package_type(\"static-library\"),\n            \"pkg/conanfile.py\": conanfile,\n            \"app/conanfile.py\": GenConanfile().with_requires(\"pkg/0.1\")})\n    t.run('create header')\n    t.run('create lib')\n    t.run('create pkg')\n    t.run(\"install app\")\n    assert re.search(r\"Skipped binaries(\\s*)header/0.1\", t.out)\n\n\n@pytest.mark.parametrize(\"component\", [True, False])\ndef test_wrong_requirement(component):\n    \"\"\" If we require a wrong requirement, we get a meaninful error.\n        This error is known when creating the package if the requirement is not there.\n    \"\"\"\n    t = TestClient(light=True)\n    conanfile = textwrap.dedent(f\"\"\"\n        from conan import ConanFile\n        class Consumer(ConanFile):\n            name = \"wrong\"\n            version = \"version\"\n            requires = \"top/version\"\n            def package_info(self):\n                self.cpp_info{'.components[\"foo\"]' if component else ''}.requires =  [\"top::cmp1\", \"other::other\"]\n    \"\"\")\n    t.save({\"top/conanfile.py\": GenConanfile().with_package_info({\"components\": {\"cmp1\": {\"libs\": [\"top_cmp1\"]}}}),\n            \"conanfile.py\": conanfile})\n    t.run('create top --name=top --version=version')\n    t.run('create .', assert_error=True)\n    assert \"ERROR: wrong/version: package_info(): There are '(cpp_info/components).requires' \" \\\n           \"that includes package 'other::', but such package is not a a direct requirement \" \\\n           \"of the recipe\" in t.out\n\n\n@pytest.mark.parametrize(\"component\", [True, False])\ndef test_missing_internal(component):\n    consumer = textwrap.dedent(f\"\"\"\n        from conan import ConanFile\n        class Recipe(ConanFile):\n            def package_info(self):\n                self.cpp_info{'.components[\"foo\"]' if component else ''}.requires = [\"other\", \"another\"]\n                self.cpp_info{'.components[\"bar\"]' if component else ''}.requires = [\"other\", \"another\"]\n    \"\"\")\n    t = TestClient(light=True)\n    t.save({'conanfile.py': consumer})\n    t.run('create . --name=wrong --version=version', assert_error=True)\n    assert \"ERROR: wrong/version: package_info(): There are '(cpp_info/components).requires' \" \\\n           \"to other internal components that are not defined: ['other', 'another']\" in t.out\n\n\ndef test_unused_tool_requirement():\n    \"\"\" Requires should include all listed requirements\n        This error is known when creating the package if the requirement is consumed.\n    \"\"\"\n    top_conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Recipe(ConanFile):\n\n            def package_info(self):\n                self.cpp_info.components[\"cmp1\"].libs = [\"top_cmp1\"]\n                self.cpp_info.components[\"cmp2\"].libs = [\"top_cmp2\"]\n        \"\"\")\n    consumer = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Recipe(ConanFile):\n            requires = \"top/version\"\n            tool_requires = \"top2/version\"\n            def package_info(self):\n                self.cpp_info.requires = [\"top::other\"]\n    \"\"\")\n    t = TestClient()\n    t.save({'top.py': top_conanfile, 'consumer.py': consumer})\n    t.run('create top.py --name=top --version=version')\n    t.run('create top.py --name=top2 --version=version')\n    t.run('create consumer.py --name=wrong --version=version')\n    # This runs without crashing, because it is not chcking that top::other doesn't exist\n\n\ndef test_component_double_colon_error_message():\n    c = TestClient()\n    t2 = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class t2Conan(ConanFile):\n            name = \"t2\"\n            version = \"0.1.0\"\n            requires = \"t1/0.1.0\"\n            def package_info(self):\n                self.cpp_info.requires.append(\"t1::comp1::other\")\n        \"\"\")\n\n    c.save({\"t1/conanfile.py\": GenConanfile(\"t1\", \"0.1.0\"),\n            \"t2/conanfile.py\": t2,\n            \"t2/test_package/conanfile.py\": GenConanfile().with_settings(\"build_type\")\n                                                          .with_generator(\"CMakeDeps\")\n                                                          .with_test(\"pass\")})\n    c.run(\"create t1\")\n    c.run(\"create t2\", assert_error=True)\n    assert \"Component 't1::comp1::other' not found in 't1' package requirement\" in c.out\n"
  },
  {
    "path": "test/integration/test_compressions.py",
    "content": "import json\nimport os\nimport sys\nimport textwrap\n\nimport pytest\n\nfrom conan.api.model import RecipeReference, PkgReference\nfrom conan.internal.util import load\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.parametrize(\"compress\", [\"gz\", \"xz\", \"zst\"])\ndef test_xz(compress):\n    if compress == \"zst\" and sys.version_info.minor < 14:\n        pytest.skip(\"Skipping zst compression tests\")\n\n    c = TestClient(default_server_user=True)\n    c.save_home({\"global.conf\": f\"core.upload:compression_format={compress}\"})\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import copy\n\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            exports_sources = \"*.h\"\n            exports = \"*.yml\"\n            def package(self):\n                copy(self, \"*.h\", self.source_folder, self.package_folder)\n        \"\"\")\n\n    c.save({\"conanfile.py\": conanfile,\n            \"header.h\": \"myheader\",\n            \"myfile.yml\": \"myyml\"})\n    c.run(\"create -tf=\")\n    c.run(\"upload * -r=default -c --format=json\")\n\n    # Verify the uploaded files are all txz\n    upload_json = json.loads(c.stdout)\n    rrev = upload_json[\"default\"][\"pkg/0.1\"][\"revisions\"][\"4e81a0b14da7ae918cf3dba3a07578d6\"]\n    rfiles = rrev[\"files\"]\n    assert f\"conan_export.t{compress}\" in rfiles\n    assert f\"conan_sources.t{compress}\" in rfiles\n    prevs = rrev[\"packages\"][\"da39a3ee5e6b4b0d3255bfef95601890afd80709\"][\"revisions\"]\n    prev = prevs[\"13eb72928af98144fa7bf104b69663bc\"]\n    pfiles = prev[\"files\"]\n    assert f\"conan_package.t{compress}\" in pfiles\n\n    # decompress should work anyway\n    c.save_home({\"global.conf\": \"\"})\n    c.run(\"remove * -c\")\n    c.run(\"install --requires=pkg/0.1\")\n\n    # checking the recipe\n    ref = RecipeReference.loads(\"pkg/0.1\")\n    rlayout = c.get_latest_ref_layout(ref)\n    downloaded_files = os.listdir(rlayout.download_export())\n    assert f\"conan_export.t{compress}\" in downloaded_files\n    assert f\"conan_sources.t{compress}\" not in downloaded_files\n    assert \"myyml\" == load(os.path.join(rlayout.export(), \"myfile.yml\"))\n\n    # checking the package\n    pref = PkgReference(rlayout.reference, \"da39a3ee5e6b4b0d3255bfef95601890afd80709\")\n    playout = c.get_latest_pkg_layout(pref)\n    downloaded_files = os.listdir(playout.download_package())\n    assert f\"conan_package.t{compress}\" in downloaded_files\n    assert \"myheader\" == load(os.path.join(playout.package(), \"header.h\"))\n\n    # Force the build from source\n    c.run(\"install --requires=pkg/0.1 --build=*\")\n    downloaded_files = os.listdir(rlayout.download_export())\n    assert f\"conan_export.t{compress}\" in downloaded_files\n    assert f\"conan_sources.t{compress}\" in downloaded_files\n\n\n@pytest.mark.skipif(sys.version_info.minor >= 14, reason=\"validate zstd error in python<314\")\ndef test_unsupported_zstd():\n    c = TestClient(default_server_user=True)\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_package_file(\"myfile.h\", \"contents\")})\n    c.run(\"create\")\n    playout = c.created_layout()\n    c.run(\"upload * -r=default -c -cc core.upload:compression_format=zst\", assert_error=True)\n    assert \"ERROR: The 'core.upload:compression_format=zst' is only for Python>=3.14\" in c.out\n\n    # Lets cheat, creating a fake zstd to test download\n    c.run(\"upload * -r=default -c --dry-run\")\n    os.rename(os.path.join(playout.download_package(), \"conan_package.tgz\"),\n              os.path.join(playout.download_package(), \"conan_package.tzst\"))\n    c.run(\"upload * -r=default -c\")\n    c.run(\"remove * -c\")\n    c.run(\"install --requires=pkg/0.1\", assert_error=True)\n    assert (\"ERROR: File conan_package.tzst compressed with 'zst', unsupported \"\n            \"for Python<3.14\") in c.out\n\n\nclass TestDuplicatedInServerErrors:\n\n    def test_duplicated_export(self):\n        c = TestClient(default_server_user=True)\n        c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\"),\n                \"conandata.yml\": \"\"})\n        c.run(\"export\")\n        c.run(\"upload * -r=default -c\")\n        c.run(\"remove * -c\")\n        c.run(\"export\")\n        c.run(\"upload * -r=default -c -cc core.upload:compression_format=xz --force\")\n        assert \"WARN: experimental: The 'xz' compression is experimental\" in c.out\n\n        c.run(\"remove * -c\")\n        c.run(\"install --requires=pkg/0.1\", assert_error=True)\n        assert (\"it contains more than one compressed file: \"\n                \"['conan_export.tgz', 'conan_export.txz']\") in c.out\n\n    def test_duplicated_source(self):\n        c = TestClient(default_server_user=True)\n        c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_exports_sources(\"*.h\"),\n                \"myheader.h\": \"content\"})\n        c.run(\"export\")\n        c.run(\"upload * -r=default -c\")\n        c.run(\"remove * -c\")\n        c.run(\"export\")\n        c.run(\"upload * -r=default -c -cc core.upload:compression_format=xz --force\")\n\n        c.run(\"remove * -c\")\n        c.run(\"install --requires=pkg/0.1 --build=missing\", assert_error=True)\n        assert (\"it contains more than one compressed file: \"\n                \"['conan_sources.tgz', 'conan_sources.txz']\") in c.out\n\n    def test_duplicated_package(self):\n        c = TestClient(default_server_user=True)\n        c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n        c.run(\"create\")\n        c.run(\"upload * -r=default -c\")\n        c.run(\"remove * -c\")\n        c.run(\"create\")\n        c.run(\"upload * -r=default -c -cc core.upload:compression_format=xz --force\")\n\n        c.run(\"remove * -c\")\n        c.run(\"install --requires=pkg/0.1\", assert_error=True)\n        assert (\"it contains more than one compressed file: \"\n                \"['conan_package.tgz', 'conan_package.txz']\") in c.out\n"
  },
  {
    "path": "test/integration/test_db_error.py",
    "content": "import os\nimport shutil\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_db_error():\n    # https://github.com/conan-io/conan/issues/14517\n    c = TestClient(default_server_user=True)\n    c.save({\"liba/conanfile.py\": GenConanfile(\"liba\", \"0.1\")})\n    c.run(\"create liba\")\n    c.run(\"install --requires=liba/0.1 --format=json\", redirect_stdout=\"graph.json\")\n    c.run(\"list --graph=graph.json --format=json\", redirect_stdout=\"installed.json\")\n    c.run(\"upload --list=installed.json -r=default --format=json -c\", redirect_stdout=\"upload.json\")\n\n    c2 = TestClient(servers=c.servers, inputs=[\"admin\", \"password\"])\n    shutil.copy(os.path.join(c.current_folder, \"upload.json\"), c2.current_folder)\n    c2.run(\"download --list=upload.json -r=default --format=json\")\n    # This used to crash\n    assert \"liba/0.1: Downloaded package revision\" in c2.out\n"
  },
  {
    "path": "test/integration/test_migrations.py",
    "content": "import os\nimport textwrap\nfrom unittest.mock import patch\n\nimport pytest\n\nfrom conan import conan_version\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.api.migrations import ClientMigrator\nfrom conan.internal.model.version import Version\nfrom conan.internal.util.files import save, load\n\n\n@pytest.mark.parametrize([\"plugin_path\", \"string_replace\", \"new_string\"],\n                         [(\"profile.py\", \"msvc\", \"EME_ESE_VC\"),\n                          (\"compatibility/compatibility.py\", \"conanfile\", \"conian_file\")])\ndef test_migration_profile_checker_plugin(plugin_path, string_replace, new_string):\n    t = TestClient(light=True)\n    # Any command that checks the package cache generates the DB\n    t.run(\"list\")\n    assert os.path.exists(os.path.join(t.cache_folder, \"p\", \"cache.sqlite3\"))\n\n    profile_plugin_path = os.path.join(t.cache_folder, \"extensions\", \"plugins\", plugin_path)\n    contents = load(profile_plugin_path)\n\n    # Let's change the version\n    version_txt_file_path = os.path.join(t.cache_folder, \"version.txt\")\n    save(version_txt_file_path, \"1.0.0\")\n    assert os.path.exists(os.path.join(t.cache_folder, \"p\", \"cache.sqlite3\"))\n\n    # Do a modification to the profile plugin without changing the comment\n    contents = contents.replace(string_replace, new_string)\n    save(profile_plugin_path, contents)\n\n    # Trigger the migrations\n    t.run(\"-v\")\n    assert f\"Migration: Successfully updated {os.path.basename(plugin_path)}\" in t.out\n    contents = load(profile_plugin_path)\n    # Our changes are removed!!!\n    assert string_replace in contents\n    assert new_string not in contents\n\n    # New client, everything new\n    t2 = TestClient(light=True)\n    # This generates the new plugin file\n    t2.run(\"list\")\n\n    # Do a modification to the profile plugin but changing the comment\n    profile_plugin_path2 = os.path.join(t2.cache_folder, \"extensions\", \"plugins\", plugin_path)\n    contents = load(profile_plugin_path2)\n    contents = contents.replace(string_replace, new_string)\n    contents = contents.replace(\"This file was generated by Conan\", \"This file is from ACME corp, \"\n                                                                    \"please don't touch it.\")\n    save(profile_plugin_path2, contents)\n\n    # Let's change the version\n    version_txt_file_path2 = os.path.join(t2.cache_folder, \"version.txt\")\n    save(version_txt_file_path2, \"1.0.0\")\n\n    # Trigger the migrations\n    t2.run(\"list\")\n    assert \"Migration: Successfully updated\" not in t2.out\n    contents = load(profile_plugin_path2)\n    # Our Changes are kept!\n    assert \"This file is from ACME corp, \" in contents\n    assert string_replace not in contents\n    assert new_string in contents\n\n\ndef test_back_migrations():\n    t = TestClient(light=True)\n\n    # add 3 migrations\n    for number in (1, 2, 3):\n        migration_file = os.path.join(t.cache_folder, \"migrations\", f\"2.100.0_{number}-migrate.py\")\n        migrate = textwrap.dedent(f\"\"\"\n            import os\n            def migrate(cache_folder):\n                os.remove(os.path.join(cache_folder, \"file{number}.txt\"))\n            \"\"\")\n        save(migration_file, migrate)\n        save(os.path.join(t.cache_folder, f\"file{number}.txt\"), \"some content\")\n        # Some older versions migrations that shouldn't be applied if we downgrade to current\n        wrong_migration_file = os.path.join(t.cache_folder, \"migrations\", f\"2.0_{number}-migrate.py\")\n        save(wrong_migration_file, \"this is not python, it would crash\")\n\n    # Let's change the old version\n    version_txt_file_path = os.path.join(t.cache_folder, \"version.txt\")\n    save(version_txt_file_path, \"200.0\")\n    t.run(\"-v\")  # Fire the backward migration\n    assert f\"WARN: Downgrading cache from Conan 200.0 to {conan_version}\" in t.out\n    for number in (1, 2, 3):\n        assert f\"WARN: Applying downgrade migration 2.100.0_{number}-migrate.py\" in t.out\n        assert not os.path.exists(os.path.join(t.cache_folder, f\"file{number}.txt\"))\n        migration_file = os.path.join(t.cache_folder, \"migrations\", f\"2.100.0_{number}-migrate.py\")\n        assert not os.path.exists(migration_file)\n\n\ndef test_back_default_compatibility_migration():\n    t = TestClient(light=True)\n    t.run(\"-v\")  # Fire the backward migration\n    migration_file = os.path.join(t.cache_folder, \"migrations\", \"2.4_1-migrate.py\")\n    assert os.path.exists(migration_file)\n\n    # downgrade from a clean latest conan_version to 2.3.2\n    # simulate that we are in 2.3.2 and the old one is latest conan_version\n    migrator = ClientMigrator(t.cache_folder, Version(\"2.3.2\"))\n\n    with patch('conan.api.conan_api.ClientMigrator', new=lambda *args, **kwargs: migrator):\n        t.run(\"-v\")  # Fire the backward migration\n        assert f\"WARN: Downgrading cache from Conan {conan_version} to 2.3.2\" in t.out\n\n\nclass TestMigrationCppstdCompat:\n    def test_migration(self):\n        t = TestClient(light=True)\n        t.run(\"-v\")\n        cppstd_compat_path = \"extensions/plugins/compatibility/cppstd_compat.py\"\n        compatibility_path = \"extensions/plugins/compatibility/compatibility.py\"\n\n        # both files exist and not modified\n        t.save_home({\"version.txt\": \"2.11\"})\n        t.run(\"-v\")\n        assert \"def cppstd_compat(conanfile)\" in t.load_home(compatibility_path)\n        assert not os.path.exists(os.path.join(t.cache_folder, cppstd_compat_path))\n\n    def test_cppstd_modified(self):\n        t = TestClient(light=True)\n        t.run(\"-v\")\n        cppstd_compat_path = \"extensions/plugins/compatibility/cppstd_compat.py\"\n        compatibility_path = \"extensions/plugins/compatibility/compatibility.py\"\n        # cppstd_compat modified\n        t.save_home({\"version.txt\": \"2.11\",\n                     compatibility_path: \"# This file was generated by Conan\",\n                     cppstd_compat_path: \"custom file content\"})\n        t.run(\"-v\")\n        assert t.load_home(cppstd_compat_path) == \"custom file content\"\n        # compatibility not migrated, keeps the old content\n        assert \"def cppstd_compat(conanfile)\" not in t.load_home(compatibility_path)\n\n    def test_compatibility_modified(self):\n        t = TestClient(light=True)\n        t.run(\"-v\")\n        cppstd_compat_path = \"extensions/plugins/compatibility/cppstd_compat.py\"\n        compatibility_path = \"extensions/plugins/compatibility/compatibility.py\"\n        t.save_home({\"version.txt\": \"2.11\",\n                     cppstd_compat_path: \"# This file was generated by Conan POTATO\",\n                     compatibility_path: \"Modified file\"})\n        t.run(\"-v\")\n        assert t.load_home(compatibility_path) == \"Modified file\"\n        # not Removed because compatibility was modified\n        assert \"POTATO\" in t.load_home(cppstd_compat_path)\n\n    def test_compatibility_modified_by_conan(self):\n        t = TestClient(light=True)\n        t.run(\"-v\")\n        compatibility_path = \"extensions/plugins/compatibility/compatibility.py\"\n        old = t.load_home(compatibility_path)\n        # In old versions of Conan, assume POTATO was present in the file\n        new = old + \"\\n# POTATO\"\n        t.save_home({\"version.txt\": \"2.11\",\n                     compatibility_path: new})\n        # But now with the newer version, Conan removed it\n        # so the triggered migration should remove it\n        t.run(\"-v\")\n        assert \"Successfully updated compatibility.py\" in t.out\n        assert \"# POTATO\" not in t.load_home(compatibility_path)\n\n    def test_compatibility_no_rewrite(self):\n        t = TestClient(light=True)\n        t.run(\"-v\")\n        # compatibility.py exists and is not modified\n        t.save_home({\"version.txt\": \"2.11\"})\n        t.run(\"-v\")\n        assert \"Successfully updated compatibility.py\" not in t.out\n"
  },
  {
    "path": "test/integration/test_package_python_files.py",
    "content": "import os\nimport textwrap\n\nfrom conan.api.model import RecipeReference\nfrom conan.internal.util.files import load\nfrom conan.test.utils.tools import TestClient, NO_SETTINGS_PACKAGE_ID\n\n\ndef test_package_python_files():\n    client = TestClient(default_server_user=True)\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import copy\n        class Pkg(ConanFile):\n            exports_sources = \"*\"\n            def package(self):\n                copy(self, \"*\", self.source_folder, self.package_folder)\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile,\n                 \"myfile.pyc\": \"\",\n                 \"myfile.pyo\": \"\",\n                 \".DS_Store\": \"\"})\n    client.run(\"create . --name=pkg --version=0.1\")\n    ref_layout = client.exported_layout()\n    pkg_layout = client.created_layout()\n    export = ref_layout.export()\n    export_sources = ref_layout.export_sources()\n    assert os.path.isfile(os.path.join(export_sources, \"myfile.pyc\"))\n    assert os.path.isfile(os.path.join(export_sources, \"myfile.pyo\"))\n    assert os.path.isfile(os.path.join(export_sources, \".DS_Store\"))\n    manifest = load(os.path.join(export, \"conanmanifest.txt\"))\n    assert \"myfile.pyc\" in manifest\n    assert \"myfile.pyo\" in manifest\n    assert \".DS_Store\" not in manifest\n    pkg_folder = pkg_layout.package()\n    assert os.path.isfile(os.path.join(pkg_folder, \"myfile.pyc\"))\n    assert os.path.isfile(os.path.join(pkg_folder, \"myfile.pyo\"))\n    assert os.path.isfile(os.path.join(pkg_folder, \".DS_Store\"))\n    manifest = load(os.path.join(pkg_folder, \"conanmanifest.txt\"))\n    assert \"myfile.pyc\" in manifest\n    assert \"myfile.pyo\" in manifest\n    assert \".DS_Store\" not in manifest\n\n    client.run(\"upload * -r=default --confirm\")\n    client.run(\"remove * -c\")\n    client.run(\"download pkg/0.1#*:* -r default\")\n\n    # The download will be in a different pkg folder now.\n    ref = RecipeReference.loads(\"pkg/0.1\")\n    pref = client.get_latest_package_reference(ref, NO_SETTINGS_PACKAGE_ID)\n    pkg_folder = client.get_latest_pkg_layout(pref).package()\n\n    assert os.path.isfile(os.path.join(export_sources, \"myfile.pyc\"))\n    assert os.path.isfile(os.path.join(export_sources, \"myfile.pyo\"))\n    assert not os.path.isfile(os.path.join(export_sources, \".DS_Store\"))\n    manifest = load(os.path.join(export, \"conanmanifest.txt\"))\n    assert \"myfile.pyc\" in manifest\n    assert \"myfile.pyo\" in manifest\n    assert \".DS_Store\" not in manifest\n    assert os.path.isfile(os.path.join(pkg_folder, \"myfile.pyc\"))\n    assert os.path.isfile(os.path.join(pkg_folder, \"myfile.pyo\"))\n    assert not os.path.isfile(os.path.join(pkg_folder, \".DS_Store\"))\n    manifest = load(os.path.join(pkg_folder, \"conanmanifest.txt\"))\n    assert \"myfile.pyc\" in manifest\n    assert \"myfile.pyo\" in manifest\n    assert \".DS_Store\" not in manifest\n\n\ndef test_package_empty_folders():\n    c = TestClient(default_server_user=True)\n\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            def package(self):\n                os.mkdir(os.path.join(self.package_folder, \"empty_folder\"))\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"create . --name=pkg --version=0.1\")\n    pkg_folder = c.created_layout().package()\n    assert os.path.isdir(os.path.join(pkg_folder, \"empty_folder\"))\n    manifest = load(os.path.join(pkg_folder, \"conanmanifest.txt\"))\n    assert \"empty_folder\" not in manifest\n\n    c.run(\"upload * -r=default --confirm\")\n    c.run(\"remove * -c\")\n    c.run(\"download pkg/0.1#*:* -r default\")\n\n    # The download will be in a different pkg folder now.\n    ref = RecipeReference.loads(\"pkg/0.1\")\n    pref = c.get_latest_package_reference(ref, NO_SETTINGS_PACKAGE_ID)\n    pkg_folder = c.get_latest_pkg_layout(pref).package()\n    assert os.path.isdir(os.path.join(pkg_folder, \"empty_folder\"))\n    manifest = load(os.path.join(pkg_folder, \"conanmanifest.txt\"))\n    assert \"empty_folder\" not in manifest\n"
  },
  {
    "path": "test/integration/test_package_vendor.py",
    "content": "import os\nimport textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_package_vendor():\n    c = TestClient()\n    app = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import copy, save\n\n        class App(ConanFile):\n            name = \"app\"\n            version = \"0.1\"\n            package_type = \"application\"\n            vendor = True\n            requires = \"pkga/0.1\"\n            def package(self):\n                copy(self, \"*\", src=self.dependencies[\"pkga\"].package_folder,\n                     dst=self.package_folder)\n                save(self, os.path.join(self.package_folder, \"app.exe\"), \"app\")\n            \"\"\")\n\n    c.save({\"pkga/conanfile.py\": GenConanfile(\"pkga\", \"0.1\").with_package_type(\"shared-library\")\n                                                            .with_package_file(\"pkga.dll\", \"dll\"),\n            \"app/conanfile.py\": app\n            })\n    c.run(\"create pkga\")\n    c.run(\"create app\")  # -c tools.graph:vendor=build will be automatic\n    assert \"app/0.1: package(): Packaged 1 '.dll' file: pkga.dll\" in c.out\n\n    # we can safely remove pkga\n    c.run(\"remove pkg* -c\")\n    c.run(\"list app:*\")\n    assert \"pkga\" not in c.out  # The binary doesn't depend on pkga\n    c.run(\"install --requires=app/0.1 --deployer=full_deploy\")\n    assert \"pkga\" not in c.out\n    assert c.load(\"full_deploy/host/app/0.1/app.exe\") == \"app\"\n    assert c.load(\"full_deploy/host/app/0.1/pkga.dll\") == \"dll\"\n\n    # we can create a modified pkga\n    c.save({\"pkga/conanfile.py\": GenConanfile(\"pkga\", \"0.1\").with_package_type(\"shared-library\")\n           .with_package_file(\"pkga.dll\", \"newdll\")})\n    c.run(\"create pkga\")\n    # still using the re-packaged one\n    c.run(\"install --requires=app/0.1 --deployer=full_deploy\")\n    assert \"pkga\" not in c.out\n    assert c.load(\"full_deploy/host/app/0.1/app.exe\") == \"app\"\n    assert c.load(\"full_deploy/host/app/0.1/pkga.dll\") == \"dll\"\n\n    # but we can force the expansion, still not the rebuild\n    c.run(\"install --requires=app/0.1 --deployer=full_deploy -c tools.graph:vendor=build\")\n    assert \"pkga\" in c.out\n    assert c.load(\"full_deploy/host/app/0.1/app.exe\") == \"app\"\n    assert c.load(\"full_deploy/host/app/0.1/pkga.dll\") == \"dll\"\n\n    # and finally we can force the expansion and the rebuild\n    c.run(\"install --requires=app/0.1 --build=app* --deployer=full_deploy \"\n          \"-c tools.graph:vendor=build\")\n    assert \"pkga\" in c.out\n    assert c.load(\"full_deploy/host/app/0.1/app.exe\") == \"app\"\n    assert c.load(\"full_deploy/host/app/0.1/pkga.dll\") == \"newdll\"\n    # This shoulnd't happen, no visibility over transitive dependencies of app\n    assert not os.path.exists(os.path.join(c.current_folder, \"full_deploy\", \"host\", \"pkga\"))\n\n    # lets remove the binary\n    c.run(\"remove app:* -c\")\n    c.run(\"install --requires=app/0.1\", assert_error=True)\n    assert \"Missing binary\" in c.out\n    c.run(\"install --requires=app/0.1 --build=missing\", assert_error=True)\n    assert \"app/0.1: Invalid: The package 'app/0.1' is a vendoring one, needs to be built \" \\\n           \"from source, but it didn't enable 'tools.graph:vendor=build'\" in c.out\n\n    c.run(\"install --requires=app/0.1 --build=missing  -c tools.graph:vendor=build\")\n    assert \"pkga\" in c.out  # it works\n\n\ndef test_package_vendor_editable():\n    c = TestClient()\n    pkgb = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import copy, save\n\n        class App(ConanFile):\n            name = \"pkgb\"\n            version = \"0.1\"\n            package_type = \"shared-library\"\n            vendor = True\n            requires = \"pkga/0.1\"\n            def layout(self):\n                self.folders.build = \"build\"\n                self.cpp.build.bindirs = [\"build\"]\n            def generate(self):\n                copy(self, \"*\", src=self.dependencies[\"pkga\"].package_folder,\n                     dst=self.build_folder)\n            def build(self):\n                save(self, os.path.join(self.build_folder, \"pkgb.dll\"), \"dll\")\n            \"\"\")\n\n    c.save({\"pkga/conanfile.py\": GenConanfile(\"pkga\", \"0.1\").with_package_type(\"shared-library\")\n                                                            .with_package_file(\"bin/pkga.dll\", \"d\"),\n            \"pkgb/conanfile.py\": pkgb,\n            \"app/conanfile.py\": GenConanfile(\"app\", \"0.1\").with_settings(\"os\")\n                                                          .with_requires(\"pkgb/0.1\")\n            })\n    c.run(\"create pkga\")\n    c.run(\"editable add pkgb\")\n    c.run(\"install app -s os=Linux --build=editable\")\n    assert \"pkga\" in c.out\n    # The environment file of \"app\" doesn't have any visibility of the \"pkga\" paths\n    envfile_app = c.load(\"app/conanrunenv.sh\")\n    assert \"pkga\" not in envfile_app\n    # But the environment file needed to build \"pkgb\" has visibility over the \"pkga\" paths\n    envfile_pkgb = c.load(\"pkgb/conanrunenv.sh\")\n    assert \"pkga\" in envfile_pkgb\n\n\ndef test_vendor_dont_propagate_options():\n    c = TestClient()\n    app = GenConanfile(\"app\", \"0.1\").with_requires(\"pkga/0.1\").with_class_attribute(\"vendor=True\")\n    c.save({\"pkga/conanfile.py\": GenConanfile(\"pkga\", \"0.1\").with_shared_option(False),\n            \"app/conanfile.py\": app,\n            \"consumer/conanfile.txt\": \"[requires]\\napp/0.1\",\n            \"consumer_shared/conanfile.txt\": \"[requires]\\napp/0.1\\n[options]\\n*:shared=True\"\n            })\n    c.run(\"create pkga\")\n    c.assert_listed_binary({\"pkga/0.1\": (\"55c609fe8808aa5308134cb5989d23d3caffccf2\", \"Build\")})\n    c.run(\"create app\")\n    c.assert_listed_binary({\"pkga/0.1\": (\"55c609fe8808aa5308134cb5989d23d3caffccf2\", \"Cache\"),\n                            \"app/0.1\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\", \"Build\")})\n    c.run(\"install consumer --build=app/* -c tools.graph:vendor=build\")\n    c.assert_listed_binary({\"pkga/0.1\": (\"55c609fe8808aa5308134cb5989d23d3caffccf2\", \"Cache\"),\n                            \"app/0.1\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\", \"Build\")})\n    c.run(\"install consumer_shared --build=app/* -c tools.graph:vendor=build\")\n    c.assert_listed_binary({\"pkga/0.1\": (\"55c609fe8808aa5308134cb5989d23d3caffccf2\", \"Cache\"),\n                            \"app/0.1\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\", \"Build\")})\n\n\ndef test_package_vendor_export_pkg():\n    c = TestClient()\n    app = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import copy, save\n\n        class App(ConanFile):\n            name = \"app\"\n            version = \"0.1\"\n            package_type = \"application\"\n            vendor = True\n            requires = \"pkga/0.1\"\n            def package(self):\n                copy(self, \"*\", src=self.dependencies[\"pkga\"].package_folder,\n                     dst=self.package_folder)\n                save(self, os.path.join(self.package_folder, \"app.exe\"), \"app\")\n            \"\"\")\n\n    c.save({\"pkga/conanfile.py\": GenConanfile(\"pkga\", \"0.1\").with_package_type(\"shared-library\")\n                                                            .with_package_file(\"pkga.dll\", \"dll\"),\n            \"app/conanfile.py\": app\n            })\n    c.run(\"create pkga\")\n    c.run(\"build app\")  # -c tools.graph:vendor=build will be automatic\n    c.run(\"export-pkg app\")\n    assert \"pkga/0.1\" in c.out  # In the export-pkg process, dependencies are still needed\n    assert \"conanfile.py (app/0.1): package(): Packaged 1 '.dll' file: pkga.dll\" in c.out\n\n    # we can safely remove pkga, once the package is created, it can work without deps\n    c.run(\"remove pkg* -c\")\n    c.run(\"list app:*\")\n    assert \"pkga\" not in c.out  # The binary doesn't depend on pkga\n    c.run(\"install --requires=app/0.1 --deployer=full_deploy\")\n    assert \"pkga\" not in c.out\n    assert c.load(\"full_deploy/host/app/0.1/app.exe\") == \"app\"\n    assert c.load(\"full_deploy/host/app/0.1/pkga.dll\") == \"dll\"\n"
  },
  {
    "path": "test/integration/test_pkg_signing.py",
    "content": "import os\nimport textwrap\n\nfrom conan.api.model import RecipeReference\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_pkg_sign():\n    c = TestClient(default_server_user=True)\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_exports(\"export/*\")\n            .with_exports_sources(\"export_sources/*\").with_package_file(\"myfile\", \"mycontents!\"),\n            \"export/file1.txt\": \"file1!\",\n            \"export_sources/file2.txt\": \"file2!\"})\n    signer = textwrap.dedent(r\"\"\"\n        import os\n\n        def sign(ref, artifacts_folder, signature_folder, **kwargs):\n            print(\"Signing ref: \", ref)\n            print(\"Signing folder: \", artifacts_folder)\n            files = []\n            for f in sorted(os.listdir(artifacts_folder)):\n                if os.path.isfile(os.path.join(artifacts_folder, f)):\n                    files.append(f)\n            print(\"Signing files: \", sorted(files))\n            signature = os.path.join(signature_folder, \"signature.asc\")\n            open(signature, \"w\").write(\"\\n\".join(files))\n\n        def verify(ref, artifacts_folder, signature_folder, files, **kwargs):\n            print(\"Verifying ref: \", ref)\n            print(\"Verifying folder: \", artifacts_folder)\n            signature = os.path.join(signature_folder, \"signature.asc\")\n            contents = open(signature).read()\n            print(\"verifying contents\", contents)\n            for f in files:\n                print(\"VERIFYING \", f)\n                if os.path.isfile(os.path.join(artifacts_folder, f)):\n                    assert f in contents\n        \"\"\")\n    c.save_home({\"extensions/plugins/sign/sign.py\": signer})\n    c.run(\"create .\")\n    c.run(\"cache sign pkg/0.1\")\n    assert \"Signing ref:  pkg/0.1\" in c.out\n    assert \"Signing ref:  pkg/0.1:da39a3ee5e6b4b0d3255bfef95601890afd80709\" in c.out\n    # Make sure it is signing the sources too\n    assert \"Signing files:  ['conan_export.tgz', 'conan_sources.tgz', \" \\\n           \"'conanfile.py', 'conanmanifest.txt']\" in c.out\n    assert (\"WARN: deprecated: [Package sign] The signature plugin sign() function must return a \"\n            \"list of signature dicts\") in c.out\n    c.run(\"upload * -r=default -c\")\n    assert (\"WARN: deprecated: [Package sign] Implicitly signing packages in the upload command \"\n            \"has been removed. Use 'conan cache sign' command before uploading instead\") in c.out\n    c.run(\"remove * -c\")\n    c.run(\"install --requires=pkg/0.1\")\n    assert \"Verifying ref:  pkg/0.1\" in c.out\n    assert \"Verifying ref:  pkg/0.1:da39a3ee5e6b4b0d3255bfef95601890afd80709\" in c.out\n    assert \"VERIFYING  conanfile.py\" in c.out\n    assert \"VERIFYING  conan_sources.tgz\" not in c.out  # Sources not retrieved now\n    # Lets force the retrieval of the sources\n    c.run(\"install --requires=pkg/0.1 --build=*\")\n    assert \"Verifying ref:  pkg/0.1\" in c.out\n    assert \"VERIFYING  conanfile.py\" not in c.out  # It doesn't re-verify previous contents\n    assert \"VERIFYING  conan_sources.tgz\" in c.out\n\n\ndef test_pkg_sign_manifest_signatures():\n    \"\"\"Test that the sign function generates the manifest and signatures files\n    and the verify function can access them\"\"\"\n    c = TestClient()\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_exports(\"export/*\")\n            .with_exports_sources(\"export_sources/*\").with_package_file(\"myfile\", \"mycontents!\"),\n            \"export/file1.txt\": \"file1!\",\n            \"export_sources/file2.txt\": \"file2!\"})\n    signer = textwrap.dedent(r\"\"\"\n        import json\n        import os\n        from conan.internal.util.files import load, save  # This is only for test purposes\n\n        def sign(ref, artifacts_folder, signature_folder, **kwargs):\n            save(os.path.join(signature_folder, \"pkgsign-manifest.json.sig\"), \"\")\n            print(f\"Creating signature pkgsign-manifest.json.sig for {ref}\")\n            # Return the pkgsign-signatures.json's content\n            return [{\"method\": \"openssl-dgst\",\n                    \"provider\": \"conan-client\",\n                    \"sign_artifacts\": {\"manifest\": \"pkgsign-manifest.json\",\n                                       \"signature\": \"pkgsign-manifest.json.sig\"}}]\n\n        def verify(ref, artifacts_folder, signature_folder, files, **kwargs):\n            manifest = load(os.path.join(signature_folder, \"pkgsign-manifest.json\"))\n            manifest_content = json.loads(manifest)\n            print(f\"Manifest content:\\n {manifest_content}\")\n            signatures = load(os.path.join(signature_folder, \"pkgsign-signatures.json\"))\n            signatures_content = json.loads(signatures)\n            signatures = signatures_content[\"signatures\"]\n            for signature in signatures_content[\"signatures\"]:\n                provider = signature.get(\"provider\")\n                method = signature.get(\"method\")\n                signature = signature.get(\"sign_artifacts\", {}).get(\"signature\")\n                print(f\"Provider: {provider}, Method: {method}, Signature: {signature}\")\n                # Verify signature here\n        \"\"\")\n    c.save_home({\"extensions/plugins/sign/sign.py\": signer})\n    c.run(\"create .\")\n    c.run(\"cache sign *\")\n    assert \"Creating signature pkgsign-manifest.json.sig for pkg/0.1\" in c.out\n    c.run(\"cache verify *\")\n    assert \"Manifest content:\\n {'files': [{'file': 'conan_export.tgz'\" in c.out\n    assert \"Checksum verified for file conanfile.py\" in c.out\n    assert \"Provider: conan-client, Method: openssl-dgst, Signature: pkgsign-manifest.json.sig\"\n    assert \"Manifest content:\\n {'files': [{'file': 'conan_package.tgz'\" in c.out\n    assert \"Checksum verified for file conan_package.tgz\" in c.out\n\n\ndef test_pkg_sign_canonical():\n    c = TestClient(default_server_user=True)\n    c.save({\"conanfile1.py\": GenConanfile(\"lib1ok\", \"0.1\")\n                .with_exports_sources(\"*.txt\").with_package_file(\"package.txt\", \"kk\"),\n            \"conanfile2.py\": GenConanfile(\"lib2fail\", \"0.1\"),  # will fail when installed\n            \"conanfile3.py\": GenConanfile(\"lib3fail\", \"0.1\"),  # should always fail\n            \"sources.txt\": \"kk\"})\n    c.run(\"create conanfile1.py\")\n    c.run(\"create conanfile2.py\")\n    c.run(\"create conanfile3.py\")\n    signer = textwrap.dedent(r\"\"\"\n        import json\n        import os\n        from conan.errors import ConanException\n        from conan.api.output import ConanOutput\n        from conan.internal.util.files import load, save  # This is only for test purposes\n\n        def sign(ref, artifacts_folder, signature_folder, **kwargs):\n            ConanOutput().info(f\"Signing reference {ref}\")\n            ConanOutput().info(f\"Signing folder: {artifacts_folder}\")\n\n            if \"lib3fail\" in str(ref):\n                raise ConanException(\"sign failed\")\n            elif \"lib2fail\" in str(ref):\n                provider = \"this will fail to verify\"\n            else:\n                provider = \"conan-client\"\n            # Simulate signing the package\n            save(os.path.join(signature_folder, \"pkgsign-manifest.json.sig\"), \"\")\n            ConanOutput().info(f\"Signature ok for {ref}\")\n            return [{\"method\": \"dummy-method\",\n                     \"provider\": provider,\n                     \"sign_artifacts\": {\"manifest\": \"pkgsign-manifest.json\",\n                                        \"signature\": \"pkgsign-manifest.json.sig\"}\n            }]\n\n        def verify(ref, artifacts_folder, signature_folder, files, **kwargs):\n            ConanOutput().info(f\"Verifying reference {ref}\")\n            signatures_file_path = os.path.join(signature_folder, \"pkgsign-signatures.json\")\n            if not os.path.isfile(signatures_file_path):\n                raise ConanException(\"Package is not signed\")\n\n            if \"lib3fail\" in str(ref):\n                raise ConanException(f\"verify failed for {ref}\")\n            # Simulate verification\n            signatures = json.loads(load(os.path.join(signature_folder, \"pkgsign-signatures.json\")))\n            provider = signatures[\"signatures\"][0][\"provider\"]\n            if provider != \"conan-client\":\n                raise ConanException(f\"Failed to verify the package {ref}\")\n            signature = signatures[\"signatures\"][0][\"sign_artifacts\"][\"signature\"]\n            ConanOutput().info(f\"Verification ok for {ref} with signature {signature}\")\n        \"\"\")\n    c.save_home({\"extensions/plugins/sign/sign.py\": signer})\n\n    # Cache verify command fails and reports if package is not signed\n    c.run(\"cache verify *\", assert_error=True)\n    assert (\"WARN: deprecated: [Package sign] Manifest file 'pkgsign-manifest.json' does not exist \"\n            \"in signature folder\") in c.out\n    assert \"ERROR: Package is not signed\" in c.out\n\n    # Cache sign command fails if a package fails to sign and reports it\n    c.run(\"cache sign *\", assert_error=True)\n    assert textwrap.dedent(\"\"\"\n        [Package sign] Results:\n\n        lib1ok/0.1\n          revisions\n            a6a4e799bb673d6e5ca4f904118d672e\n              packages\n                da39a3ee5e6b4b0d3255bfef95601890afd80709\n                  revisions\n                    76285bcb59a81071122cba04b2269b52\n        lib2fail/0.1\n          revisions\n            70a185be5a95af3dde25b74ae800b2f2\n              packages\n                da39a3ee5e6b4b0d3255bfef95601890afd80709\n                  revisions\n                    0ba8627bd47edc3a501e8f0eb9a79e5e\n        lib3fail/0.1\n          revisions\n            09ccc766ddd11c96aa78307b3f166fd6\n              packages\n                da39a3ee5e6b4b0d3255bfef95601890afd80709\n                  revisions\n                    0ba8627bd47edc3a501e8f0eb9a79e5e\n                      ERROR: sign failed\n              ERROR: sign failed\n\n        [Package sign] Summary: OK=4, FAILED=2\n        \"\"\") in c.out\n\n    # cache sign fails if package signing fails\n    c.run(\"cache sign *\", assert_error=True)\n    assert \"ERROR: sign failed\" in c.out\n\n    # Upload packages individually\n    c.run(\"upload lib1ok* -c -r default\")\n    c.run(\"upload lib2fail* -c -r default\")\n    c.run(\"remove * -c\")\n\n    # Install verify command should fail if package sign verification fails\n    c.run(\"install --requires lib1ok/0.1 --requires lib2fail/0.1 -r default\",\n          assert_error=True)\n    assert \"ERROR: Package 'lib2fail/0.1' not resolved: Failed to verify \" \\\n           \"the package lib2fail/0.1\" in c.out\n\n    # If packages fail to verify signature, they should not be installed\n    c.run(\"list *\")\n    assert \"lib1ok\" in c.out\n    assert \"lib2fail\" not in c.out\n    c.run(\"cache verify *\")\n    assert textwrap.dedent(\"\"\"\\\n        [Package sign] Results:\n\n        lib1ok/0.1\n          revisions\n            a6a4e799bb673d6e5ca4f904118d672e\n\n        [Package sign] Summary: OK=1, FAILED=0\n    \"\"\") in c.out\n\n\ndef test_pkg_sign_exports_sources():\n    \"\"\"Test that the sign function generates the manifest and signatures files\n    and the verify function can access them\"\"\"\n    c = TestClient(default_server_user=True)\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_exports(\"export/*\")\n            .with_exports_sources(\"export_sources/*\").with_package_file(\"myfile\", \"mycontents!\"),\n            \"export/file1.txt\": \"file1!\",\n            \"export_sources/file2.txt\": \"file2!\"})\n    signer = textwrap.dedent(r\"\"\"\n        import os\n        from conan.internal.util.files import save  # This is only for test purposes\n        from conan.tools.files import load\n\n        def sign(ref, artifacts_folder, signature_folder, **kwargs):\n            save(os.path.join(signature_folder, \"pkgsign-manifest.json.sig\"), \"\")\n            print(f\"Creating signature pkgsign-manifest.json.sig for {ref}\")\n            # Return the pkgsign-signatures.json's content\n            return [{\"method\": \"openssl-dgst\",\n                    \"provider\": \"conan-client\",\n                    \"sign_artifacts\": {\"manifest\": \"pkgsign-manifest.json\",\n                                       \"signature\": \"pkgsign-manifest.json.sig\"}}]\n\n        def verify(ref, artifacts_folder, signature_folder, files, **kwargs):\n            pass\n        \"\"\")\n    c.save_home({\"extensions/plugins/sign/sign.py\": signer})\n    c.run(\"create .\")\n    c.run(\"cache sign pkg/0.1\")\n    assert \"Creating signature pkgsign-manifest.json.sig\" in c.out\n    c.run(\"upload pkg/0.1 -r=default -c\")\n    c.run(\"remove * -c\")\n    c.run(\"install --requires=pkg/0.1 -r=default\")\n    assert \"Checksum verified for file conan_export.tgz\" in c.out\n    assert \"Checksum verified for file conan_package.tgz\" in c.out\n    c.run(\"install --requires=pkg/0.1 -r=default --build=pkg/0.1\")\n    assert \"Checksum verified for file conan_sources.tgz\" in c.out\n\n\ndef test_pkg_sign_no_op():\n    c = TestClient()\n    c.save({\"conanfile1.py\": GenConanfile(\"pkg\", \"0.1\"),\n            \"conanfile2.py\": GenConanfile(\"no-op\", \"0.1\")})\n    signer = textwrap.dedent(r\"\"\"\n        def sign(ref, artifacts_folder, signature_folder, **kwargs):\n            if \"pkg/0.1\" in str(ref):\n                print(\"Signing package\", str(ref))\n                # Return the pkgsign-signatures.json's content\n                return [{\"method\": \"openssl-dgst\",\n                        \"provider\": \"conan-client\",\n                        \"sign_artifacts\": {\"manifest\": \"pkgsign-manifest.json\",\n                                           \"signature\": \"pkgsign-manifest.json.sig\"}}]\n            else:\n                # no-op: The package should not be signed or if it is signed, it shouldn't be resigned\n                print(\"Skipping package\", str(ref))\n                return []\n\n        \"\"\")\n    c.save_home({\"extensions/plugins/sign/sign.py\": signer})\n    c.run(\"create conanfile1.py\")\n    c.run(\"cache sign pkg/0.1\")\n    assert \"Signing package pkg/0.1\" in c.out\n    metadata_folder = c.cache.recipe_layout(\n        RecipeReference(\"pkg\", \"0.1\", revision=\"485dad6cb11e2fa99d9afbe44a57a164\")).metadata()\n    signatures_path = os.path.join(metadata_folder, \"sign\", \"pkgsign-signatures.json\")\n    assert os.path.exists(signatures_path)\n    c.run(\"create conanfile2.py\")\n    c.run(\"cache sign no-op/0.1\")\n    assert \"Skipping package no-op/0.1\" in c.out\n    metadata_folder = c.cache.recipe_layout(\n        RecipeReference(\"no-op\", \"0.1\", revision=\"9f8243dd2f341b13df241e599326b3cb\")).metadata()\n    signatures_path = os.path.join(metadata_folder, \"sign\", \"pkgsign-signatures.json\")\n    assert not os.path.exists(signatures_path)\n"
  },
  {
    "path": "test/integration/test_recipe_policies.py",
    "content": "from conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_build_policies_in_conanfile():\n    client = TestClient(default_server_user=True, light=True)\n    base = GenConanfile(\"hello0\", \"1.0\").with_exports(\"*\")\n    conanfile = str(base) + \"\\n    build_policy = 'missing'\"\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"export . --user=lasote --channel=stable\")\n\n    # Install, it will build automatically if missing (without the --build missing option)\n    client.run(\"install --requires=hello0/1.0@lasote/stable\")\n    assert \"Building\" in client.out\n\n    # Try to do it again, now we have the package, so no build is done\n    client.run(\"install --requires=hello0/1.0@lasote/stable\")\n    assert \"Building\" not in client.out\n\n    # Try now to upload all packages, should not crash because of the \"missing\" build policy\n    client.run(\"upload hello0/1.0@lasote/stable -r default\")\n\n    #  --- Build policy to always ---\n    conanfile = str(base) + \"\\n    build_policy = 'always'\"\n    client.save({\"conanfile.py\": conanfile}, clean_first=True)\n    client.run(\"export . --user=lasote --channel=stable\")\n\n    # Install, it will build automatically if missing (without the --build missing option)\n    client.run(\"install --requires=hello0/1.0@lasote/stable\", assert_error=True)\n    assert \"ERROR: hello0/1.0@lasote/stable: build_policy='always' has been removed\" in client.out\n\n\ndef test_build_policy_missing():\n    c = TestClient(default_server_user=True, light=True)\n    conanfile = GenConanfile(\"pkg\", \"1.0\").with_class_attribute('build_policy = \"missing\"')\\\n                                          .with_class_attribute('upload_policy = \"skip\"')\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"export .\")\n\n    # the --build=never has higher priority\n    c.run(\"install --requires=pkg/1.0@ --build=never\", assert_error=True)\n    assert \"ERROR: Missing prebuilt package for 'pkg/1.0'\" in c.out\n\n    c.run(\"install --requires=pkg/1.0@\")\n    assert \"pkg/1.0: Building package from source as defined by build_policy='missing'\" in c.out\n\n    # If binary already there it should do nothing\n    c.run(\"install --requires=pkg/1.0@\")\n    assert \"pkg/1.0: Building package from source\" not in c.out\n\n    c.run(\"upload * -r=default -c\")\n    assert \"Uploading package\" not in c.out\n    assert \"pkg/1.0: Skipping upload of binaries, because upload_policy='skip'\" in c.out\n"
  },
  {
    "path": "test/integration/test_source_download_password.py",
    "content": "import json\nimport os\nimport platform\nimport sys\nimport textwrap\nfrom shutil import copy\nfrom unittest import mock\n\nimport pytest\n\nfrom conan.internal.api.uploader import compress_files\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.file_server import TestFileServer\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import save\n\n\ndef test_source_download_password():\n    c = TestClient()\n    file_server = TestFileServer()\n    c.servers[\"file_server\"] = file_server\n    save(os.path.join(file_server.store, \"myfile.txt\"), \"hello world!\")\n\n    server_url = file_server.fake_url\n\n    conanfile = textwrap.dedent(f\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import download, load\n        class Pkg(ConanFile):\n            def source(self):\n                download(self, \"{server_url}/basic-auth/myfile.txt\", \"myfile.txt\")\n                self.output.info(f\"Content: {{load(self, 'myfile.txt')}}\")\n            \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    content = {\"credentials\": [{\"url\": server_url, \"token\": \"password\"}]}\n    save(os.path.join(c.cache_folder, \"source_credentials.json\"), json.dumps(content))\n    c.run(\"source .\")\n    assert \"Content: hello world!\" in c.out\n    content = {\"credentials\": [{\"url\": server_url,\n                                \"user\": \"user\", \"password\": \"password\"}]}\n    save(os.path.join(c.cache_folder, \"source_credentials.json\"), json.dumps(content))\n    c.run(\"source .\")\n    assert \"Content: hello world!\" in c.out\n\n    content = {\"credentials\": [{\"url\": server_url, \"token\": \"{{mytk}}\"}]}\n    content = \"{% set mytk = 'password' %}\\n\" + json.dumps(content)\n    save(os.path.join(c.cache_folder, \"source_credentials.json\"), content)\n    c.run(\"source .\")\n    assert \"Content: hello world!\" in c.out\n\n    # Errors loading file\n    for invalid in [\"\",\n                    \"potato\",\n                    {\"token\": \"mytoken\"},\n                    {},\n                    {\"url\": server_url},\n                    {\"auth\": {}},\n                    {\"user\": \"other\", \"password\": \"pass\"}]:\n        content = {\"credentials\": [invalid]}\n        save(os.path.join(c.cache_folder, \"source_credentials.json\"), json.dumps(content))\n        c.run(\"source .\", assert_error=True)\n        assert \"Error loading 'source_credentials.json'\" in c.out\n\n    content = {\"credentials\": [{\"url\": server_url, \"token\": \"mytoken2\"}]}\n    save(os.path.join(c.cache_folder, \"source_credentials.json\"), json.dumps(content))\n    c.run(\"source .\", assert_error=True)\n    assert \"ERROR: conanfile.py: Error in source() method, line 6\" in c.out\n    assert \"Authentication\" in c.out\n\n\ndef test_source_credentials_only_download():\n    # https://github.com/conan-io/conan/issues/16396\n    c = TestClient(default_server_user=True)\n    url = c.servers[\"default\"].fake_url\n\n    content = {\"credentials\": [{\"url\": url, \"token\": \"password stpaces\"}]}\n    save(os.path.join(c.cache_folder, \"source_credentials.json\"), json.dumps(content))\n\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n    c.run(\"create .\")\n    # add_auth should never be called for regular upload/download\n    with mock.patch(\"conan.internal.rest.conan_requester._SourceURLCredentials.add_auth\", None):\n        c.run(\"upload * -c -r=default\")\n        c.run(\"remove * -c\")\n        c.run(\"download pkg/0.1 -r=default\")\n\n\n@pytest.mark.skipif(sys.version_info.minor < 12 or platform.system() == \"Windows\",\n                    reason=\"Extraction filters only Python 3.12, using symlinks (not Windows)\")\ndef test_blocked_malicius_tgz():\n    folder = temp_folder()\n    f = os.path.join(folder, \"myfile.txt\")\n    save(f, \"The contents\")\n    s = os.path.join(folder, \"mylink.txt\")\n    os.symlink(f, s)\n    tgz_path = compress_files({f: f, s: s}, \"myfiles.tgz\", dest_dir=folder)\n    os.remove(f)\n\n    conan_file = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import get\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            def source(self):\n                get(self, \"http://fake_url/myfiles.tgz\")\n            \"\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conan_file})\n\n    with mock.patch(\"conan.tools.files.files.download\") as mock_download:\n        def download_zip(*args, **kwargs):  # noqa\n            copy(tgz_path, os.getcwd())\n        mock_download.side_effect = download_zip\n        client.run(\"create . -c tools.files.unzip:filter=data\", assert_error=True)\n        assert \"AbsoluteLinkError\" in client.out\n        client.save({\"conanfile.py\": conan_file.format(\"extract_filter='fully_trusted'\")})\n        client.run(\"create . \")  # Doesn't fail now\n        # user conf has precedence\n        client.save({\"conanfile.py\": conan_file.format(\"extract_filter='data'\")})\n        client.run(\"create . -c tools.files.unzip:filter=fully_trusted\")  # Doesn't fail now\n"
  },
  {
    "path": "test/integration/test_timestamp_error.py",
    "content": "import textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_timestamp_error():\n    \"\"\" this test is a reproduction for\n    # https://github.com/conan-io/conan/issues/11606\n\n    It was crashing because of multiple test_requires, some of them being BINARY_SKIP,\n    and the prev_timestamp was not being assigned by GraphBinariesAnalizer when caching\n    \"\"\"\n\n    c = TestClient(default_server_user=True)\n    engine = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Engine(ConanFile):\n            name = \"engine\"\n            version = \"0.1\"\n            def build_requirements(self):\n                self.test_requires(\"gtest/0.1\")\n        \"\"\")\n    app = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class App(ConanFile):\n            def requirements(self):\n                self.requires(\"engine/0.1\")\n            def build_requirements(self):\n                self.test_requires(\"gtest/0.1\")\n        \"\"\")\n    c.save({\"gtest/conanfile.py\": GenConanfile(\"gtest\", \"0.1\"),\n            \"engine/conanfile.py\": engine,\n            \"app/conanfile.py\": app})\n    c.run(\"create gtest\")\n    c.run(\"create engine\")\n    c.run(\"upload * -r=default -c\")\n    c.run(\"remove * -c\")\n    c.run(\"install app\")\n    # This used to fail, now it is not crashing anymore\n    assert \"Finalizing install\" in c.out\n"
  },
  {
    "path": "test/integration/tgz_macos_dot_files_test.py",
    "content": "import os\nimport platform\nimport shutil\nimport subprocess\nimport tempfile\nimport textwrap\n\nimport pytest\n\nfrom conan.internal.rest.remote_manager import uncompress_file\nfrom conan.api.model import RecipeReference\nfrom conan.test.utils.tools import TestClient, NO_SETTINGS_PACKAGE_ID\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Requires OSX\")\nclass TestTgzMacosDotFiles:\n\n    @staticmethod\n    def _test_for_metadata_in_zip_file(tgz, annotated_file, dot_file_expected):\n        tmp_folder = tempfile.mkdtemp()\n        try:\n            uncompress_file(src_path=tgz, dest_folder=tmp_folder)\n            assert os.path.exists(os.path.join(tmp_folder, annotated_file))\n            assert dot_file_expected == \\\n                             os.path.exists(os.path.join(tmp_folder, \"._\" + annotated_file))\n        finally:\n            shutil.rmtree(tmp_folder)\n\n    def _test_for_metadata(self, folder, annotated_file, dot_file_expected):\n        \"\"\" We want to check if the file has metadata associated: Mac creates the\n            ._ files at the moment of creating a tar file in order to send the\n            metadata associated to every file. \"\"\"\n        assert os.path.exists(os.path.join(folder, annotated_file))\n\n        tmp_folder = tempfile.mkdtemp()\n        try:\n            tgz = os.path.join(tmp_folder, 'compressed.tgz')\n            subprocess.call([\"tar\", \"-zcvf\", tgz, \"-C\", folder, \".\"])\n            self._test_for_metadata_in_zip_file(tgz, annotated_file, dot_file_expected)\n        finally:\n            shutil.rmtree(tmp_folder)\n\n    def test_dot_files(self):\n        \"\"\" Check behavior related to ._ files in Macos OS\n\n            Macos has the ability to store metadata associated to files. This metadata can be\n            stored in the HFS+ (Apple native) or Unix/UFS volumes, but if the store does\n            not have this capability it will be placed in a ._ file. So these files will\n            automatically be created by the OS when it is creating a package in order to\n            send this information.\n\n            Nevertheless, Conan is using the Python libraries to copy, tar and untar files\n            and this metadata is lost when using them. It can avoid some problems like\n            #3529 but there is missing information that can be valuable at some point in time.\n\n            This test is here just to be sure that the behavior is not changed without\n            noticing.\n            \"\"\"\n\n        conanfile = textwrap.dedent(\"\"\"\\\n            from conan import ConanFile\n            from conan.tools.files import copy\n\n            class Lib(ConanFile):\n                name = \"lib\"\n                version = \"version\"\n                exports_sources = \"file.txt\"\n\n                def package(self):\n                    copy(self, \"file.txt\", self.source_folder, self.package_folder)\n            \"\"\")\n\n        t = TestClient(path_with_spaces=False, default_server_user=True)\n        t.save({'conanfile.py': conanfile, 'file.txt': \"content\"})\n\n        def _add_macos_metadata_to_file(filepath):\n            subprocess.call([\"xattr\", \"-w\", \"name\", \"value\", filepath])\n\n        _add_macos_metadata_to_file(os.path.join(t.current_folder, 'file.txt'))\n        t.run(\"create . --user=user --channel=channel\")\n\n        # Check if the metadata travels through the Conan commands\n        pref = t.get_latest_package_reference(RecipeReference.loads(\"lib/version@user/channel\"),\n                                              NO_SETTINGS_PACKAGE_ID)\n        pkg_folder = t.get_latest_pkg_layout(pref).package()\n\n        # 1) When copied to the package folder, the metadata is lost\n        self._test_for_metadata(pkg_folder, 'file.txt', dot_file_expected=False)\n\n        # 2) If we add metadata to a file, it will be there\n        _add_macos_metadata_to_file(os.path.join(pkg_folder, 'file.txt'))\n        self._test_for_metadata(pkg_folder, 'file.txt', dot_file_expected=True)\n\n        # 3) In the upload process, the metadata is lost again\n        export_download_folder = t.get_latest_ref_layout(pref.ref).download_export()\n        tgz = os.path.join(export_download_folder, \"conan_sources.tgz\")\n        assert not os.path.exists(tgz)\n        t.run(\"upload lib/version@user/channel -r default --only-recipe\")\n        self._test_for_metadata_in_zip_file(tgz, 'file.txt', dot_file_expected=False)\n"
  },
  {
    "path": "test/integration/toolchains/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/toolchains/apple/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/toolchains/apple/test_xcodedeps.py",
    "content": "import os\nimport platform\nimport re\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom test.integration.toolchains.apple.test_xcodetoolchain import _get_filename\nfrom conan.test.utils.tools import TestClient\n\n_expected_dep_xconfig = [\n    \"SYSTEM_HEADER_SEARCH_PATHS = $(inherited) $(SYSTEM_HEADER_SEARCH_PATHS_{name}_{name})\",\n    \"GCC_PREPROCESSOR_DEFINITIONS = $(inherited) $(GCC_PREPROCESSOR_DEFINITIONS_{name}_{name})\",\n    \"OTHER_CFLAGS = $(inherited) $(OTHER_CFLAGS_{name}_{name})\",\n    \"OTHER_CPLUSPLUSFLAGS = $(inherited) $(OTHER_CPLUSPLUSFLAGS_{name}_{name})\",\n    \"FRAMEWORK_SEARCH_PATHS = $(inherited) $(FRAMEWORK_SEARCH_PATHS_{name}_{name})\",\n    \"LIBRARY_SEARCH_PATHS = $(inherited) $(LIBRARY_SEARCH_PATHS_{name}_{name})\",\n    \"OTHER_LDFLAGS = $(inherited) $(OTHER_LDFLAGS_{name}_{name})\",\n]\n\n_expected_conf_xconfig = [\n    \"SYSTEM_HEADER_SEARCH_PATHS_{name}_{name}[config={configuration}][arch={architecture}][sdk={sdk}{sdk_version}] = \",\n    \"GCC_PREPROCESSOR_DEFINITIONS_{name}_{name}[config={configuration}][arch={architecture}][sdk={sdk}{sdk_version}] = \",\n    \"OTHER_CFLAGS_{name}_{name}[config={configuration}][arch={architecture}][sdk={sdk}{sdk_version}] = \",\n    \"OTHER_CPLUSPLUSFLAGS_{name}_{name}[config={configuration}][arch={architecture}][sdk={sdk}{sdk_version}] = \",\n    \"FRAMEWORK_SEARCH_PATHS_{name}_{name}[config={configuration}][arch={architecture}][sdk={sdk}{sdk_version}] = \",\n    \"LIBRARY_SEARCH_PATHS_{name}_{name}[config={configuration}][arch={architecture}][sdk={sdk}{sdk_version}] = \",\n    \"OTHER_LDFLAGS_{name}_{name}[config={configuration}][arch={architecture}][sdk={sdk}{sdk_version}] = \"\n]\n\n\ndef expected_files(current_folder, configuration, architecture, sdk_version):\n    files = []\n    name = _get_filename(configuration, architecture, sdk_version)\n    deps = [\"hello\", \"goodbye\"]\n    files.extend(\n        [os.path.join(current_folder, \"conan_{dep}_{dep}{name}.xcconfig\".format(dep=dep, name=name)) for dep in deps])\n    files.append(os.path.join(current_folder, \"conandeps.xcconfig\"))\n    return files\n\n\ndef check_contents(client, deps, configuration, architecture, sdk_version):\n    for dep_name in deps:\n        dep_xconfig = client.load(\"conan_{dep}_{dep}.xcconfig\".format(dep=dep_name))\n        fname = _get_filename(configuration, architecture, sdk_version)\n        conf_name = \"conan_{}_{}{}.xcconfig\".format(dep_name, dep_name, fname)\n\n        assert '#include \"{}\"'.format(conf_name) in dep_xconfig\n        for var in _expected_dep_xconfig:\n            line = var.format(name=dep_name)\n            assert line in dep_xconfig\n\n        conan_conf = client.load(conf_name)\n        for var in _expected_conf_xconfig:\n            assert var.format(name=dep_name, configuration=configuration, architecture=architecture,\n                              sdk=\"macosx\", sdk_version=sdk_version) in conan_conf\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only for MacOS\")\ndef test_generator_files():\n    client = TestClient()\n    client.save({\"hello.py\": GenConanfile().with_settings(\"os\", \"arch\", \"compiler\", \"build_type\")\n                                           .with_package_info(cpp_info={\"libs\": [\"hello\"],\n                                                                        \"frameworks\": ['framework_hello']})})\n    client.run(\"export hello.py --name=hello --version=0.1\")\n    client.save({\"goodbye.py\": GenConanfile().with_settings(\"os\", \"arch\", \"compiler\", \"build_type\")\n                                             .with_package_info(cpp_info={\"libs\": [\"goodbye\"],\n                                                                          \"frameworks\": ['framework_goodbye']})})\n    client.run(\"export goodbye.py --name=goodbye --version=0.1\")\n    client.save({\"conanfile.txt\": \"[requires]\\nhello/0.1\\ngoodbye/0.1\\n\"}, clean_first=True)\n\n    for build_type in [\"Release\", \"Debug\"]:\n\n        client.run(\"install . -g XcodeDeps -s build_type={} -s arch=x86_64 -s os.sdk_version=12.1 --build missing\".format(build_type))\n\n        for config_file in expected_files(client.current_folder, build_type, \"x86_64\", \"12.1\"):\n            assert os.path.isfile(config_file)\n\n        conandeps = client.load(\"conandeps.xcconfig\")\n        assert '#include \"conan_hello.xcconfig\"' in conandeps\n        assert '#include \"conan_goodbye.xcconfig\"' in conandeps\n\n        conan_config = client.load(\"conan_config.xcconfig\")\n        assert '#include \"conandeps.xcconfig\"' in conan_config\n\n        check_contents(client, [\"hello\", \"goodbye\"], build_type, \"x86_64\", \"12.1\")\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only for MacOS\")\ndef test_generator_files_with_custom_config():\n    client = TestClient()\n\n    client.save({\"hello.py\": GenConanfile().with_settings(\"os\", \"arch\", \"compiler\", \"build_type\")\n                                           .with_package_info(cpp_info={\"libs\": [\"hello\"]})})\n    client.run(\"export hello.py --name=hello --version=0.1\")\n\n    client.save({\"goodbye.py\": GenConanfile().with_settings(\"os\", \"arch\", \"compiler\", \"build_type\")\n                                             .with_package_info(cpp_info={\"libs\": [\"goodbye\"]})})\n    client.run(\"export goodbye.py --name=goodbye --version=0.1\")\n\n    conanfile_py = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.apple import XcodeDeps\n        class LibConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            options = {\"XcodeConfigName\": [None, \"ANY\"]}\n            default_options = {\"XcodeConfigName\": None}\n            requires = \"hello/0.1\", \"goodbye/0.1\"\n\n            def generate(self):\n                xcode = XcodeDeps(self)\n                if self.options.get_safe(\"XcodeConfigName\"):\n                    xcode.configuration = str(self.options.get_safe(\"XcodeConfigName\"))\n                xcode.generate()\n        \"\"\")\n\n    client.save({\"conanfile.py\": conanfile_py})\n    custom_config_name = \"CustomConfig\"\n\n    for use_custom_config in [True, False]:\n        for build_type in [\"Release\", \"Debug\"]:\n            cli_command = \"install . -s build_type={} -s arch=x86_64 -s os.sdk_version=12.1  --build missing\".format(build_type)\n            if use_custom_config:\n                cli_command += \" -o XcodeConfigName={}\".format(custom_config_name)\n                configuration_name = custom_config_name\n            else:\n                configuration_name = build_type\n\n            client.run(cli_command)\n\n            for config_file in expected_files(client.current_folder, configuration_name, \"x86_64\", \"12.1\"):\n                assert os.path.isfile(config_file)\n\n            conandeps = client.load(\"conandeps.xcconfig\")\n            assert '#include \"conan_hello.xcconfig\"' in conandeps\n            assert '#include \"conan_goodbye.xcconfig\"' in conandeps\n\n            conan_config = client.load(\"conan_config.xcconfig\")\n            assert '#include \"conandeps.xcconfig\"' in conan_config\n\n            check_contents(client, [\"hello\", \"goodbye\"],  configuration_name, \"x86_64\", \"12.1\",)\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only for MacOS\")\ndef test_xcodedeps_aggregate_components():\n    client = TestClient()\n\n    conanfile_py = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class LibConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            def package_info(self):\n                self.cpp_info.includedirs = [\"liba_include\"]\n        \"\"\")\n\n    client.save({\"conanfile.py\": conanfile_py})\n\n    client.run(\"create . --name=liba --version=1.0\")\n\n    r\"\"\"\"\n        1   a\n       / \\ /\n      2   3\n       \\ /\n        4   5  6\n        |   |  /\n         \\ / /\n           7\n    \"\"\"\n\n    conanfile_py = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class LibConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            requires = \"liba/1.0\"\n            def package_info(self):\n                self.cpp_info.components[\"libb_comp1\"].includedirs = [\"libb_comp1\"]\n                self.cpp_info.components[\"libb_comp1\"].libdirs = [\"mylibdir\"]\n                self.cpp_info.components[\"libb_comp2\"].includedirs = [\"libb_comp2\"]\n                self.cpp_info.components[\"libb_comp2\"].libdirs = [\"mylibdir\"]\n                self.cpp_info.components[\"libb_comp2\"].requires = [\"libb_comp1\"]\n                self.cpp_info.components[\"libb_comp3\"].includedirs = [\"libb_comp3\"]\n                self.cpp_info.components[\"libb_comp3\"].libdirs = [\"mylibdir\"]\n                self.cpp_info.components[\"libb_comp3\"].requires = [\"libb_comp1\", \"liba::liba\"]\n                self.cpp_info.components[\"libb_comp4\"].includedirs = [\"libb_comp4\"]\n                self.cpp_info.components[\"libb_comp4\"].libdirs = [\"mylibdir\"]\n                self.cpp_info.components[\"libb_comp4\"].requires = [\"libb_comp2\", \"libb_comp3\"]\n                self.cpp_info.components[\"libb_comp5\"].includedirs = [\"libb_comp5\"]\n                self.cpp_info.components[\"libb_comp5\"].libdirs = [\"mylibdir\"]\n                self.cpp_info.components[\"libb_comp6\"].includedirs = [\"libb_comp6\"]\n                self.cpp_info.components[\"libb_comp6\"].libdirs = [\"mylibdir\"]\n                self.cpp_info.components[\"libb_comp7\"].includedirs = [\"libb_comp7\"]\n                self.cpp_info.components[\"libb_comp7\"].libdirs = [\"mylibdir\"]\n                self.cpp_info.components[\"libb_comp7\"].requires = [\"libb_comp4\", \"libb_comp5\", \"libb_comp6\"]\n        \"\"\")\n\n    client.save({\"conanfile.py\": conanfile_py})\n\n    client.run(\"create . --name=libb --version=1.0\")\n\n    client.run(\"install --requires=libb/1.0 -g XcodeDeps\")\n\n    lib_entry = client.load(\"conan_libb.xcconfig\")\n\n    for index in range(1, 8):\n        assert f\"conan_libb_libb_comp{index}.xcconfig\" in lib_entry\n\n    component7_entry = client.load(\"conan_libb_libb_comp7.xcconfig\")\n    assert '#include \"conan_liba.xcconfig\"' in component7_entry\n\n    arch_setting = client.get_default_host_profile().settings['arch']\n    arch = \"arm64\" if arch_setting == \"armv8\" else arch_setting\n\n    component7_vars = client.load(f\"conan_libb_libb_comp7_release_{arch}.xcconfig\")\n\n    # all of the transitive required components and the component itself are added\n    for index in range(1, 8):\n        assert f\"libb_comp{index}\" in component7_vars\n\n    assert \"mylibdir\" in component7_vars\n\n    component4_vars = client.load(f\"conan_libb_libb_comp4_release_{arch}.xcconfig\")\n\n    # all of the transitive required components and the component itself are added\n    for index in range(1, 5):\n        assert f\"libb_comp{index}\" in component4_vars\n\n    for index in range(5, 8):\n        assert f\"libb_comp{index}\" not in component4_vars\n\n    # folders are aggregated\n    assert \"mylibdir\" in component4_vars\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only for MacOS\")\ndef test_xcodedeps_traits():\n    client = TestClient()\n    conanfile_py = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class LibConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            {package_info}\n            {requirements}\n        \"\"\")\n\n    package_info = \"\"\"\n    def package_info(self):\n        self.cpp_info.components[\"cmp1\"].includedirs = [\"cmp1_includedir\"]\n        self.cpp_info.components[\"cmp2\"].includedirs = [\"cmp2_includedir\"]\n\n        self.cpp_info.components[\"cmp1\"].libdirs = [\"cmp1_libdir\"]\n        self.cpp_info.components[\"cmp2\"].libdirs = [\"cmp2_libdir\"]\n        self.cpp_info.components[\"cmp1\"].libs = [\"cmp1_lib\"]\n        self.cpp_info.components[\"cmp2\"].libs = [\"cmp2_lib\"]\n        self.cpp_info.components[\"cmp1\"].system_libs = [\"cmp1_system_lib\"]\n        self.cpp_info.components[\"cmp2\"].system_libs = [\"cmp2_system_lib\"]\n        self.cpp_info.components[\"cmp1\"].frameworkdirs = [\"cmp1_frameworkdir\"]\n        self.cpp_info.components[\"cmp2\"].frameworkdirs = [\"cmp2_frameworkdir\"]\n        self.cpp_info.components[\"cmp1\"].frameworks = [\"cmp1_framework\"]\n        self.cpp_info.components[\"cmp2\"].frameworks = [\"cmp2_framework\"]\n\n        self.cpp_info.components[\"cmp1\"].defines = [\"cmp1_define\"]\n        self.cpp_info.components[\"cmp2\"].defines = [\"cmp2_define\"]\n        self.cpp_info.components[\"cmp1\"].cflags = [\"cmp1_cflag\"]\n        self.cpp_info.components[\"cmp2\"].cflags = [\"cmp2_cflag\"]\n        self.cpp_info.components[\"cmp1\"].cxxflags = [\"cmp1_cxxflag\"]\n        self.cpp_info.components[\"cmp2\"].cxxflags = [\"cmp2_cxxflag\"]\n        self.cpp_info.components[\"cmp1\"].sharedlinkflags = [\"cmp1_sharedlinkflag\"]\n        self.cpp_info.components[\"cmp2\"].sharedlinkflags = [\"cmp2_sharedlinkflag\"]\n        self.cpp_info.components[\"cmp1\"].exelinkflags = [\"cmp1_exelinkflag\"]\n        self.cpp_info.components[\"cmp2\"].exelinkflags = [\"cmp2_exelinkflag\"]\n        \"\"\"\n\n    client.save({\"lib_a.py\": conanfile_py.format(requirements=\"\", package_info=package_info)})\n\n    client.run(\"create lib_a.py --name=lib_a --version=1.0\")\n\n    requirements = \"\"\"\n    def requirements(self):\n        self.requires(\"lib_a/1.0\", headers=False)\n    \"\"\"\n\n    client.save({\"lib_b.py\": conanfile_py.format(requirements=requirements, package_info=\"\")},\n                clean_first=True)\n\n    client.run(\"install lib_b.py -g XcodeDeps\")\n\n    arch_setting = client.get_default_host_profile().settings['arch']\n    arch = \"arm64\" if arch_setting == \"armv8\" else arch_setting\n\n    comp1_info = client.load(f\"conan_lib_a_cmp1_release_{arch}.xcconfig\")\n    comp2_info = client.load(f\"conan_lib_a_cmp2_release_{arch}.xcconfig\")\n\n    assert \"cmp1_include\" not in comp1_info\n    assert \"cmp2_include\" not in comp2_info\n\n    requirements = \"\"\"\n    def requirements(self):\n        self.requires(\"lib_a/1.0\", libs=False)\n    \"\"\"\n\n    client.save({\"lib_b.py\": conanfile_py.format(requirements=requirements, package_info=\"\")},\n                clean_first=True)\n    client.run(\"install lib_b.py -g XcodeDeps\")\n\n    comp1_info = client.load(f\"conan_lib_a_cmp1_release_{arch}.xcconfig\")\n    comp2_info = client.load(f\"conan_lib_a_cmp2_release_{arch}.xcconfig\")\n\n    assert \"cmp1_frameworkdir\" not in comp1_info\n    assert \"cmp2_frameworkdir\" not in comp2_info\n\n    assert \"-lcmp1_lib -lcmp1_system_lib -framework cmp1_framework\" not in comp1_info\n    assert \"-lcmp2_lib -lcmp2_system_lib -framework cmp2_framework\" not in comp2_info\n\n    requirements = \"\"\"\n    def requirements(self):\n        self.requires(\"lib_a/1.0\", headers=False, libs=False)\n    \"\"\"\n\n    client.save({\"lib_b.py\": conanfile_py.format(requirements=requirements, package_info=\"\")},\n                clean_first=True)\n    client.run(\"install lib_b.py -g XcodeDeps\")\n\n    # this changed from non-existing to existing after https://github.com/conan-io/conan/pull/15128\n    existing = [f\"conan_lib_a_cmp1_release_{arch}.xcconfig\", \"conan_lib_a_cmp1.xcconfig\",\n                f\"conan_lib_a_cmp2_release_{arch}.xcconfig\", \"conan_lib_a_cmp2.xcconfig\",\n                \"conan_lib_a.xcconfig\"]\n\n    for file in existing:\n        assert os.path.exists(os.path.join(client.current_folder, file))\n\n    assert '#include \"conan_lib_a.xcconfig\"' in client.load(\"conandeps.xcconfig\")\n\n    requirements = \"\"\"\n    def requirements(self):\n        self.requires(\"lib_a/1.0\", headers=False, libs=False, run=True)\n    \"\"\"\n\n    client.save({\"lib_b.py\": conanfile_py.format(requirements=requirements, package_info=\"\")},\n                clean_first=True)\n\n    client.run(\"install lib_b.py -g XcodeDeps\")\n\n    comp1_info = client.load(f\"conan_lib_a_cmp1_release_{arch}.xcconfig\")\n    comp2_info = client.load(f\"conan_lib_a_cmp2_release_{arch}.xcconfig\")\n\n    assert \"cmp1_define\" not in comp1_info\n    assert \"cmp2_define\" not in comp2_info\n    assert \"cmp1_cflag\" not in comp1_info\n    assert \"cmp2_cflag\" not in comp2_info\n    assert \"cmp1_cxxflag\" not in comp1_info\n    assert \"cmp2_cxxflag\" not in comp2_info\n    assert \"cmp1_sharedlinkflag\" not in comp1_info\n    assert \"cmp2_sharedlinkflag\" not in comp2_info\n    assert \"cmp1_exelinkflag\" not in comp1_info\n    assert \"cmp2_exelinkflag\" not in comp2_info\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only for MacOS\")\ndef test_xcodedeps_frameworkdirs():\n    client = TestClient()\n\n    conanfile_py = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class LibConan(ConanFile):\n            name = \"lib_a\"\n            version = \"1.0\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            def package_info(self):\n                self.cpp_info.frameworkdirs = [\"lib_a_frameworkdir\"]\n        \"\"\")\n\n    client.save({\"conanfile.py\": conanfile_py})\n    client.run(\"create .\")\n\n    arch_setting = client.get_default_host_profile().settings['arch']\n    arch = \"arm64\" if arch_setting == \"armv8\" else arch_setting\n\n    client.run(\"install --requires=lib_a/1.0 -g XcodeDeps\")\n\n    lib_a_xcconfig = client.load(f\"conan_lib_a_lib_a_release_{arch}.xcconfig\")\n\n    assert \"lib_a_frameworkdir\" in lib_a_xcconfig\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only for MacOS\")\ndef test_xcodedeps_cppinfo_requires():\n\n    \"\"\"\n    lib_a: has four components cmp1, cmp2, cmp3, cmp4\n    lib_b --> uses libA cmp1 so cpp_info.requires = [\"lib_a::cmp1\"]\n    lib_c --> uses libA cmp2 so cpp_info.requires = [\"lib_a::cmp2\"]\n    consumer --> libB, libC\n    \"\"\"\n    client = TestClient()\n    lib_a = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class lib_aConan(ConanFile):\n            name = \"lib_a\"\n            version = \"1.0\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            def package_info(self):\n                self.cpp_info.components[\"cmp1\"].includedirs = [\"include\"]\n                self.cpp_info.components[\"cmp2\"].includedirs = [\"include\"]\n                self.cpp_info.components[\"cmp3\"].includedirs = [\"include\"]\n                self.cpp_info.components[\"cmp4\"].includedirs = [\"include\"]\n        \"\"\")\n\n    lib = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class lib_{name}Conan(ConanFile):\n            name = \"lib_{name}\"\n            version = \"1.0\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            def requirements(self):\n                self.requires(\"lib_a/1.0\")\n            def package_info(self):\n                self.cpp_info.requires = {cppinfo_comps}\n        \"\"\")\n\n    consumer = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    class ConsumerConan(ConanFile):\n        name = \"consumer\"\n        version = \"1.0\"\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n        generators = \"XcodeDeps\"\n        def requirements(self):\n            self.requires(\"lib_b/1.0\")\n            self.requires(\"lib_c/1.0\")\n    \"\"\")\n\n    client.save({\n        'lib_a/conanfile.py': lib_a,\n        'lib_b/conanfile.py': lib.format(name=\"b\", cppinfo_comps='[\"lib_a::cmp1\"]'),\n        'lib_c/conanfile.py': lib.format(name=\"c\", cppinfo_comps='[\"lib_a::cmp2\"]'),\n        'consumer/conanfile.py': consumer,\n    })\n\n    client.run(\"create lib_a\")\n\n    client.run(\"create lib_b\")\n\n    client.run(\"create lib_c\")\n\n    client.run(\"install consumer\")\n\n    \"\"\"\n    Check that the generated lib_b and lib_c xcconfig only use the cmp1 and cmp2 components\n    So we will only link against the components specified in the cpp_info.requires of lib_b and lib_c\n    \"\"\"\n\n    lib_b = client.load(os.path.join(\"consumer\", \"conan_lib_b_lib_b.xcconfig\"))\n\n    # check that nothing from other components than the specified in the cpp_info.requires\n    # from lib_b and lib_c exist in the xcconfig that adds the includes from components\n    assert \"cmp1\" in lib_b\n    assert \"cmp2\" not in lib_b\n    assert \"cmp3\" not in lib_b\n    assert \"cmp4\" not in lib_b\n\n    lib_c = client.load(os.path.join(\"consumer\", \"conan_lib_c_lib_c.xcconfig\"))\n\n    assert \"cmp1\" not in lib_c\n    assert \"cmp2\" in lib_c\n    assert \"cmp3\" not in lib_c\n    assert \"cmp4\" not in lib_c\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only for MacOS\")\ndef test_dependency_of_dependency_components():\n    # testing: https://github.com/conan-io/conan/pull/11772\n\n    \"\"\"\n    When a dependency of a dependency would have components, only the default\n    name conan_dep_dep.xconfig would be included. However, this file was never\n    generated, as they are in the form conan_dep_component.xconfig.\n\n    lib_a -> lib_b -> lib_c (with components)\n    \"\"\"\n    client = TestClient()\n    lib_a = GenConanfile(\"lib_a\", \"1.0\").with_require(\"lib_b/1.0\").with_settings(\"os\", \"arch\", \"build_type\", \"compiler\")\n    lib_b = GenConanfile(\"lib_b\", \"1.0\").with_require(\"lib_c/1.0\").with_settings(\"os\", \"arch\", \"build_type\", \"compiler\")\n\n    lib_c = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class lib_aConan(ConanFile):\n            name = \"lib_c\"\n            version = \"1.0\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            def package_info(self):\n                self.cpp_info.components[\"cmp1\"].includedirs = [\"include_cmp1\"]\n                self.cpp_info.components[\"cmp2\"].includedirs = [\"include_cmp2\"]\n        \"\"\")\n\n    client.save({\n        'conanfile.py': lib_a,\n        'lib_b/conanfile.py': lib_b,\n        'lib_c/conanfile.py': lib_c,\n    })\n\n    client.run(\"create lib_c\")\n\n    client.run(\"create lib_b\")\n\n    client.run(\"install . -g XcodeDeps\")\n\n    lib_b_xconfig = client.load(\"conan_lib_b_lib_b.xcconfig\")\n\n    assert '#include \"conan_lib_c_cmp1.xcconfig\"' in lib_b_xconfig\n    assert '#include \"conan_lib_c_cmp1.xcconfig\"' in lib_b_xconfig\n    assert '#include \"conan_lib_c_lib_c.xcconfig\"' not in lib_b_xconfig\n\n\ndef test_skipped_not_included():\n    # https://github.com/conan-io/conan/issues/13818\n    client = TestClient()\n    pkg_info = {\"components\": {\"component\": {\"defines\": [\"SOMEDEFINE\"]}}}\n\n    client.save({\"dep/conanfile.py\": GenConanfile().with_package_type(\"header-library\")\n                                                   .with_package_info(cpp_info=pkg_info),\n                 \"pkg/conanfile.py\": GenConanfile().with_requirement(\"dep/0.1\")\n                                                   .with_package_type(\"library\")\n                                                   .with_shared_option(),\n                 \"consumer/conanfile.py\": GenConanfile().with_requires(\"pkg/0.1\")\n                                                        .with_settings(\"os\", \"build_type\", \"arch\")})\n    client.run(\"create dep --name=dep --version=0.1\")\n    client.run(\"create pkg --name=pkg --version=0.1\")\n    client.run(\"install consumer -g XcodeDeps -s arch=x86_64 -s build_type=Release\")\n    assert re.search(r\"Skipped binaries\\n\\s+(.*?)\", client.out, re.DOTALL)\n    dep_xconfig = client.load(\"consumer/conan_pkg_pkg.xcconfig\")\n    assert \"conan_dep.xcconfig\" not in dep_xconfig\n\n\ndef test_correctly_handle_transitive_components():\n    # https://github.com/conan-io/conan/issues/14887\n    client = TestClient()\n    has_components = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class PkgWithComponents(ConanFile):\n            name = 'has_components'\n            version = '1.0'\n            settings = 'os', 'compiler', 'arch', 'build_type'\n            def package_info(self):\n                self.cpp_info.components['first'].libs = ['first']\n                self.cpp_info.components['second'].libs = ['donottouch']\n                self.cpp_info.components['second'].requires = ['first']\n        \"\"\")\n\n    uses_components = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class PkgUsesComponent(ConanFile):\n            name = 'uses_components'\n            version = '1.0'\n            settings = 'os', 'compiler', 'arch', 'build_type'\n            def requirements(self):\n                self.requires('has_components/1.0')\n            def package_info(self):\n                self.cpp_info.libs = ['uses_only_first']\n                self.cpp_info.requires = ['has_components::first']\n        \"\"\")\n\n    consumer = textwrap.dedent(\"\"\"\n        [requires]\n        uses_components/1.0\n        \"\"\")\n\n    client.save({\"has_components.py\": has_components,\n                 \"uses_components.py\": uses_components,\n                 \"consumer.txt\": consumer})\n    client.run(\"create has_components.py\")\n    client.run(\"create uses_components.py\")\n    client.run(\"install consumer.txt -g XcodeDeps\")\n    conandeps = client.load(\"conandeps.xcconfig\")\n    assert '#include \"conan_has_components.xcconfig\"' not in conandeps\n    assert '#include \"conan_uses_components.xcconfig\"' in conandeps\n    conan_uses_xcconfig = client.load(\"conan_uses_components_uses_components.xcconfig\")\n    assert '#include \"conan_has_components_first.xcconfig\"' in conan_uses_xcconfig\n    assert '#include \"conan_has_components_second.xcconfig\"' not in conan_uses_xcconfig\n\n\ndef test_dont_add_skipped_xcconfigs_when_required_by_components():\n    client = TestClient()\n    regular_lib = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class PkgWithComponents(ConanFile):\n            name = 'regular_lib'\n            version = '1.0'\n            settings = 'os', 'compiler', 'arch', 'build_type'\n            def requirements(self):\n                self.requires('header_skip/1.0')\n                self.requires('header_transitive/1.0', transitive_headers=True)\n            def package_info(self):\n                self.cpp_info.components['component'].requires = ['header_skip::header_skip',\n                                                                  'header_transitive::header_transitive']\n        \"\"\")\n\n    header_transitive = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class PkgUsesComponent(ConanFile):\n            name = 'header_transitive'\n            version = '1.0'\n            settings = 'os', 'compiler', 'arch', 'build_type'\n            package_type = 'header-library'\n            def package_info(self):\n                self.cpp_info.includedirs = [\"include\"]\n        \"\"\")\n\n    header_skip = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class PkgUsesComponent(ConanFile):\n            name = 'header_skip'\n            version = '1.0'\n            settings = 'os', 'compiler', 'arch', 'build_type'\n            package_type = 'header-library'\n            def package_info(self):\n                self.cpp_info.includedirs = [\"include\"]\n        \"\"\")\n\n    client.save({\"header_transitive.py\": header_transitive,\n                 \"header_skip.py\": header_skip,\n                 \"regular_lib.py\": regular_lib})\n    client.run(\"create header_transitive.py\")\n    client.run(\"create header_skip.py\")\n    client.run(\"create regular_lib.py\")\n    client.run(\"install --requires=regular_lib/1.0 -g XcodeDeps\")\n\n    conandeps = client.load(\"conan_regular_lib_component.xcconfig\")\n    assert '#include \"conan_header_skip.xcconfig\"' not in conandeps\n    assert '#include \"conan_header_transitive.xcconfig\"' in conandeps\n\n    # Verify that header_skip xcconfig files are NOT generated (skipped dependency)\n    skip_files = [f for f in os.listdir(client.current_folder) if 'header_skip' in f and f.endswith('.xcconfig')]\n    assert len(skip_files) == 0, f\"Header skip files should not be generated: {skip_files}\"\n\n    # Verify that header_transitive xcconfig files ARE generated (transitive dependency)\n    transitive_files = [f for f in os.listdir(client.current_folder) if 'header_transitive' in f and f.endswith('.xcconfig')]\n    assert len(transitive_files) > 0, f\"Header transitive files should be generated: {transitive_files}\"\n"
  },
  {
    "path": "test/integration/toolchains/apple/test_xcodetoolchain.py",
    "content": "import platform\nimport re\nimport textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\n\ndef _get_filename(configuration, architecture, sdk_version):\n    props = [(\"configuration\", configuration),\n             (\"architecture\", architecture),\n             (\"sdk version\", sdk_version)]\n    name = \"\".join(\"_{}\".format(v) for _, v in props if v is not None and v)\n    name = name.replace(\".\", \"_\").replace(\"-\", \"_\")\n    return name.lower()\n\n\ndef _condition(configuration, architecture, sdk_version):\n    sdk = \"macosx{}\".format(sdk_version or \"*\")\n    return \"[config={}][arch={}][sdk={}]\".format(configuration, architecture, sdk)\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only for MacOS\")\n@pytest.mark.parametrize(\"configuration, os_version, libcxx, cppstd, arch, sdk_version, clang_cppstd\", [\n    (\"Release\", \"\", \"\", \"\", \"x86_64\", \"\", \"\"),\n    (\"Debug\", \"\", \"\", \"\", \"armv8\", \"\", \"\"),\n    (\"Release\", \"12.0\", \"libc++\", \"20\", \"x86_64\", \"\", \"c++20\"),\n    (\"Debug\", \"12.0\", \"libc++\", \"20\", \"x86_64\", \"\", \"c++20\"),\n    (\"Release\", \"12.0\", \"libc++\", \"20\", \"x86_64\", \"11.3\", \"c++20\"),\n    (\"Release\", \"12.0\", \"libc++\", \"20\", \"x86_64\", \"\", \"c++20\"),\n])\ndef test_toolchain_files(configuration, os_version, cppstd, libcxx, arch, sdk_version, clang_cppstd):\n    client = TestClient()\n    client.save({\"conanfile.txt\": \"[generators]\\nXcodeToolchain\\n\"})\n    cmd = \"install . -s build_type={}\".format(configuration)\n    cmd = cmd + \" -s os.version={}\".format(os_version) if os_version else cmd\n    cmd = cmd + \" -s compiler.cppstd={}\".format(cppstd) if cppstd else cmd\n    cmd = cmd + \" -s os.sdk_version={}\".format(sdk_version) if sdk_version else cmd\n    cmd = cmd + \" -s arch={}\".format(arch) if arch else cmd\n    client.run(cmd)\n    arch_name = \"arm64\" if arch == \"armv8\" else arch\n    filename = _get_filename(configuration, arch_name, sdk_version)\n    condition = _condition(configuration, arch, sdk_version)\n\n    toolchain_all = client.load(\"conantoolchain.xcconfig\")\n    toolchain_vars = client.load(\"conantoolchain{}.xcconfig\".format(filename))\n    conan_config = client.load(\"conan_config.xcconfig\")\n\n    assert '#include \"conantoolchain.xcconfig\"' in conan_config\n    assert '#include \"conantoolchain{}.xcconfig\"'.format(filename) in toolchain_all\n\n    if libcxx:\n        assert 'CLANG_CXX_LIBRARY{}={}'.format(condition, libcxx) in toolchain_vars\n    if os_version:\n        assert 'MACOSX_DEPLOYMENT_TARGET{}={}'.format(condition, os_version) in toolchain_vars\n    if cppstd:\n        assert 'CLANG_CXX_LANGUAGE_STANDARD{}={}'.format(condition, clang_cppstd) in toolchain_vars\n\n\ndef test_toolchain_flags():\n    client = TestClient()\n    client.save({\"conanfile.txt\": \"[generators]\\nXcodeToolchain\\n\"})\n    cmd = \"install . -c 'tools.build:cxxflags=[\\\"flag1\\\"]' \" \\\n          \"-c 'tools.build:defines=[\\\"MYDEFINITION\\\"]' \" \\\n          \"-c 'tools.build:cflags=[\\\"flag2\\\"]' \" \\\n          \"-c 'tools.build:sharedlinkflags=[\\\"flag3\\\"]' \" \\\n          \"-c 'tools.build:exelinkflags=[\\\"flag4\\\"]'\"\n    client.run(cmd)\n    conan_global_flags = client.load(\"conan_global_flags.xcconfig\")\n    assert \"GCC_PREPROCESSOR_DEFINITIONS = $(inherited) MYDEFINITION\" in conan_global_flags\n    assert \"OTHER_CFLAGS = $(inherited) flag2\" in conan_global_flags\n    assert \"OTHER_CPLUSPLUSFLAGS = $(inherited) flag1\" in conan_global_flags\n    assert \"OTHER_LDFLAGS = $(inherited) flag3 flag4\" in conan_global_flags\n    conan_global_file = client.load(\"conan_config.xcconfig\")\n    assert '#include \"conan_global_flags.xcconfig\"' in conan_global_file\n\n\ndef test_flags_generated_if_only_defines():\n    # https://github.com/conan-io/conan/issues/16422\n    client = TestClient()\n    client.save({\"conanfile.txt\": \"[generators]\\nXcodeToolchain\\n\"})\n    client.run(\"install . -c 'tools.build:defines=[\\\"MYDEFINITION\\\"]'\")\n    conan_global_flags = client.load(\"conan_global_flags.xcconfig\")\n    assert \"GCC_PREPROCESSOR_DEFINITIONS = $(inherited) MYDEFINITION\" in conan_global_flags\n    conan_global_file = client.load(\"conan_config.xcconfig\")\n    assert '#include \"conan_global_flags.xcconfig\"' in conan_global_file\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only for MacOS\")\n@pytest.mark.parametrize(\"os_name, sdk, min_version, deployment_target_flag\", [\n    (\"Macos\", None, \"11.0\", \"MACOSX_DEPLOYMENT_TARGET\"),\n    (\"iOS\", \"iphoneos\", \"18.0\", \"IPHONEOS_DEPLOYMENT_TARGET\"),\n    (\"tvOS\", \"appletvos\", \"18.4\", \"TVOS_DEPLOYMENT_TARGET\"),\n    (\"watchOS\", \"watchos\", \"9.0\", \"WATCHOS_DEPLOYMENT_TARGET\"),\n    (\"visionOS\", \"xros\", \"2.0\", \"XROS_DEPLOYMENT_TARGET\"),\n])\ndef test_xcodetoolchain_xcconfig_deplyment_target(os_name, sdk, min_version, deployment_target_flag):\n    client = TestClient()\n\n    conanfile = textwrap.dedent(f\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.apple import XcodeToolchain\n        from conan.tools.files import save\n        class MyApplicationConan(ConanFile):\n            name = \"myapplication\"\n            version = \"1.0\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            def generate(self):\n                tc = XcodeToolchain(self)\n                tc.generate()\n                # Private access to get the generated xcconfig filename\n                # It changes based on the settings, so this is the less fragile way to get it\n                save(self, os.path.join(self.generators_folder, \"name.txt\"), tc._vars_xconfig_filename)\n        \"\"\")\n\n    client.save({\"conanfile.py\": conanfile})\n\n    settings = f\"-s os={os_name} -s os.version={min_version}\"\n    if sdk:\n        settings += f\" -s os.sdk={sdk}\"\n\n    client.run(f\"install . -s build_type=Release {settings} --build=missing\")\n\n    xcconfig_name = client.load(\"name.txt\").strip()\n    xcconfig = client.load(xcconfig_name)\n    match = re.search(f\"^{deployment_target_flag}.+={min_version}$\", xcconfig, re.MULTILINE)\n    assert match is not None\n"
  },
  {
    "path": "test/integration/toolchains/cmake/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/toolchains/cmake/cmakeconfigdeps/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/toolchains/cmake/cmakeconfigdeps/test_cmakeconfigdeps.py",
    "content": "import re\nimport textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\nnew_value = \"will_break_next\"\n\n\ndef test_cmakedeps_direct_deps_paths():\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan.tools.files import copy\n        from conan import ConanFile\n        class TestConan(ConanFile):\n            name = \"lib\"\n            version = \"1.0\"\n            def package_info(self):\n                self.cpp_info.includedirs = [\"myincludes\"]\n                self.cpp_info.libdirs = [\"mylib\"]\n                self.cpp_info.frameworkdirs = [\"myframework\"]\n    \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"create .\")\n    conanfile = textwrap.dedent(f\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n        class PkgConan(ConanFile):\n            requires = \"lib/1.0\"\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            generators = \"CMakeDeps\"\n    \"\"\")\n    c.save({\"conanfile.py\": conanfile}, clean_first=True)\n    c.run(f\"install . -c tools.cmake.cmakedeps:new={new_value}\")\n    cmake_paths = c.load(\"conan_cmakedeps_paths.cmake\")\n    assert \"set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON)\" in cmake_paths\n    assert re.search(r\"list\\(PREPEND CMAKE_PROGRAM_PATH \\\".*/bin\\\"\", cmake_paths)  # default\n    assert re.search(r\"list\\(PREPEND CMAKE_LIBRARY_PATH \\\".*/mylib\\\"\", cmake_paths)\n    assert re.search(r\"list\\(PREPEND CMAKE_INCLUDE_PATH \\\".*/myincludes\\\"\", cmake_paths)\n    assert re.search(r\"list\\(PREPEND CMAKE_FRAMEWORK_PATH \\\".*/myframework\\\"\", cmake_paths)\n\n\ndef test_cmakedeps_transitive_paths():\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan.tools.files import copy\n        from conan import ConanFile\n        class TestConan(ConanFile):\n            name = \"liba\"\n            version = \"1.0\"\n            def package_info(self):\n                self.cpp_info.includedirs = [\"includea\"]\n                self.cpp_info.libdirs = [\"liba\"]\n                self.cpp_info.bindirs = [\"bina\"]\n    \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"create .\")\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan.tools.files import copy\n        from conan import ConanFile\n        class TestConan(ConanFile):\n            name = \"libb\"\n            version = \"1.0\"\n            requires = \"liba/1.0\"\n            def package_info(self):\n                self.cpp_info.includedirs = [\"includeb\"]\n                self.cpp_info.libdirs = [\"libb\"]\n                self.cpp_info.bindirs = [\"binb\"]\n    \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"create .\")\n    conanfile = textwrap.dedent(f\"\"\"\n        from conan import ConanFile\n        class PkgConan(ConanFile):\n            requires = \"libb/1.0\"\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            generators = \"CMakeDeps\"\n    \"\"\")\n    c.save({\"conanfile.py\": conanfile}, clean_first=True)\n    c.run(f\"install . -c tools.cmake.cmakedeps:new={new_value}\")\n    cmake_paths = c.load(\"conan_cmakedeps_paths.cmake\")\n    assert re.search(r\"list\\(PREPEND CMAKE_PROGRAM_PATH \\\".*/libb.*/p/binb\\\"\\)\", cmake_paths)\n    assert not re.search(r\"list\\(PREPEND CMAKE_PROGRAM_PATH /bina\\\"\", cmake_paths)\n    assert re.search(r\"list\\(PREPEND CMAKE_LIBRARY_PATH \\\".*/libb.*/p/libb\\\" \\\".*/liba.*/p/liba\\\"\\)\",\n                     cmake_paths)\n    assert re.search(r\"list\\(PREPEND CMAKE_INCLUDE_PATH \\\".*/libb.*/p/includeb\\\" \"\n                     r\"\\\".*/liba.*/p/includea\\\"\\)\", cmake_paths)\n\n\ndef test_cmakedeps_deployer_relative_paths():\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan.tools.files import copy\n        from conan import ConanFile\n        class TestConan(ConanFile):\n            name = \"liba\"\n            version = \"1.0\"\n\n            def package_info(self):\n                self.cpp_info.includedirs = [\"includea\"]\n                self.cpp_info.libdirs = [\"bina\"]\n                self.cpp_info.bindirs = [\"bina\"]\n                crypto_module = os.path.join(\"share\", \"cmake\", \"crypto.cmake\")\n                self.cpp_info.set_property(\"cmake_build_modules\", [crypto_module])\n    \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"create .\")\n\n    conanfile_cmake = textwrap.dedent(\"\"\"\n        import os\n        from conan.tools.files import save\n        from conan import ConanFile\n        class TestConan(ConanFile):\n            name = \"libb\"\n            version = \"1.0\"\n\n            def package(self):\n                save(self, os.path.join(self.package_folder, \"libb-config.cmake\"), \"\")\n            def package_info(self):\n                self.cpp_info.set_property(\"cmake_find_mode\", \"none\")\n        \"\"\")\n\n    c.save({\"conanfile.py\": conanfile_cmake})\n    c.run(\"create .\")\n    conanfile = textwrap.dedent(f\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n        class PkgConan(ConanFile):\n            requires = \"liba/1.0\", \"libb/1.0\"\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            generators = \"CMakeDeps\"\n    \"\"\")\n    c.save({\"conanfile.py\": conanfile}, clean_first=True)\n\n    # Now with a deployment\n    c.run(f\"install . -c tools.cmake.cmakedeps:new={new_value} --deployer=full_deploy\")\n    cmake_paths = c.load(\"conan_cmakedeps_paths.cmake\")\n    assert 'set(libb_DIR \"${CMAKE_CURRENT_LIST_DIR}/full_deploy/host/libb/1.0\")' in cmake_paths\n    assert ('set(CONAN_RUNTIME_LIB_DIRS \"$<$<CONFIG:Release>:${CMAKE_CURRENT_LIST_DIR}'\n            '/full_deploy/host/liba/1.0/bina>\"') in cmake_paths\n    liba_config = c.load(\"liba-config.cmake\")\n    assert ('include(\"${CMAKE_CURRENT_LIST_DIR}/full_deploy/'\n            'host/liba/1.0/share/cmake/crypto.cmake\")') in liba_config\n    assert ('set(liba_INCLUDE_DIRS \"${CMAKE_CURRENT_LIST_DIR}/full_deploy/'\n            'host/liba/1.0/includea\" )') in liba_config\n    liba_targets = c.load(\"liba-Targets-release.cmake\")\n    assert ('set(liba_PACKAGE_FOLDER_RELEASE \"${CMAKE_CURRENT_LIST_DIR}/full_deploy/'\n            'host/liba/1.0\")') in liba_targets\n\n\ndef test_cmakeconfigdeps_recipe():\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan.tools.cmake import CMakeConfigDeps\n        from conan import ConanFile\n        class TestConan(ConanFile):\n            settings = \"build_type\"\n            requires = \"dep/0.1\"\n            def generate(self):\n                deps = CMakeConfigDeps(self)\n                deps.generate()\n    \"\"\")\n    c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\"),\n            \"app/conanfile.py\": conanfile})\n    c.run(\"create dep\")\n    c.run(\"install app\")\n    assert \"WARN: experimental: CMakeConfigDeps is experimental\" in c.out\n\n    # attribute generator\n    conanfile = textwrap.dedent(\"\"\"\n        from conan.tools.cmake import CMakeConfigDeps\n        from conan import ConanFile\n        class TestConan(ConanFile):\n            settings = \"build_type\"\n            requires = \"dep/0.1\"\n            generators = \"CMakeConfigDeps\"\n        \"\"\")\n    c.save({\"app/conanfile.py\": conanfile}, clean_first=True)\n    c.run(\"install app\")\n    assert \"WARN: experimental: CMakeConfigDeps is experimental\" in c.out\n\n    # conanfile.txt\n    conanfile = textwrap.dedent(\"\"\"\n        [requires]\n        dep/0.1\n        [generators]\n        CMakeConfigDeps\n        \"\"\")\n    c.save({\"app/conanfile.txt\": conanfile}, clean_first=True)\n    c.run(\"install app\")\n    assert \"WARN: experimental: CMakeConfigDeps is experimental\" in c.out\n\n\ndef test_system_wrappers():\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan.tools.files import copy\n        from conan import ConanFile\n        class TestConan(ConanFile):\n            name = \"lib\"\n            version = \"system\"\n            package_type = \"shared-library\"\n\n            def package_info(self):\n                self.cpp_info.includedirs = []\n                self.cpp_info.libdirs = []\n                self.cpp_info.system_libs = [\"my_system_cool_lib\"]\n    \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"create .\")\n\n    c.run(f\"install --requires=lib/system -g CMakeConfigDeps \"\n          f\"-c tools.cmake.cmakedeps:new={new_value}\")\n    cmake = c.load(\"lib-Targets-release.cmake\")\n    assert \"add_library(lib::lib INTERFACE IMPORTED)\" in cmake\n    assert \"set_property(TARGET lib::lib APPEND PROPERTY INTERFACE_LINK_LIBRARIES\\n\" \\\n           '             $<$<CONFIG:RELEASE>:my_system_cool_lib>)' in cmake\n\n\ndef test_autolink_pragma():\n    \"\"\"https://github.com/conan-io/conan/issues/10837\"\"\"\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            def package_info(self):\n                self.cpp_info.set_property(\"cmake_set_interface_link_directories\", True)\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile,\n            \"test_package/conanfile.py\": GenConanfile().with_test(\"pass\")\n                                                       .with_settings(\"build_type\")\n                                                       .with_generator(\"CMakeDeps\")})\n    c.run(\"create . --name=pkg --version=0.1\")\n    assert \"CMakeDeps: cmake_set_interface_link_directories is legacy, not necessary\" in c.out\n    c.run(f\"create . --name=pkg --version=0.1 -c tools.cmake.cmakedeps:new={new_value}\")\n    assert \"CMakeConfigDeps: cmake_set_interface_link_directories deprecated and invalid. \" \\\n           \"The package 'package_info()' must correctly define the (CPS) information\" in c.out\n\n\ndef test_consuming_cpp_info_with_components_dependency_from_same_package():\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            def package_info(self):\n                self.cpp_info.components[\"lib\"].type = 'shared-library'\n                self.cpp_info.components[\"lib_extended\"].type = 'shared-library'\n                self.cpp_info.components[\"lib_extended\"].requires = ['lib']\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile,\n            \"test_package/conanfile.py\": GenConanfile().with_settings(\"build_type\")\n                                                       .with_test(\"pass\")\n                                                       .with_generator(\"CMakeDeps\")})\n    c.run(f\"create . --name=pkg --version=0.1 -c tools.cmake.cmakedeps:new={new_value}\")\n    # it doesn't break\n    assert \"find_package(pkg)\" in c.out\n\n\ndef test_consuming_cpp_info_with_components_dependency_from_other_package():\n    c = TestClient()\n    dep = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"dep\"\n            version = \"0.1\"\n            def package_info(self):\n                self.cpp_info.components[\"lib\"].type = 'shared-library'\n    \"\"\")\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            requires = \"dep/0.1\"\n            def package_info(self):\n                self.cpp_info.components[\"lib\"].type = 'shared-library'\n                self.cpp_info.components[\"lib\"].requires = ['dep::lib']\n        \"\"\")\n    c.save({\"dep/conanfile.py\": dep,\n            \"pkg/conanfile.py\": conanfile,\n            \"pkg/test_package/conanfile.py\": GenConanfile().with_settings(\"build_type\")\n                                                           .with_test(\"pass\")\n                                                           .with_generator(\"CMakeDeps\")})\n    c.run(\"create dep\")\n    c.run(f\"create pkg --name=pkg --version=0.1 -c tools.cmake.cmakedeps:new={new_value}\")\n    # it doesn't break\n    assert \"find_package(pkg)\" in c.out\n\n\ndef test_error_incorrect_component():\n    # https://github.com/conan-io/conan/issues/18554\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            requires = \"dep/0.1\"\n            def package_info(self):\n                self.cpp_info.requires = ['dep::lib']\n        \"\"\")\n    c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\"),\n            \"pkg/conanfile.py\": conanfile,\n            \"pkg/test_package/conanfile.py\": GenConanfile().with_settings(\"build_type\")\n                                                           .with_generator(\"CMakeDeps\")\n                                                           .with_test(\"pass\")})\n    c.run(\"create dep\")\n    c.run(f\"create pkg --name=pkg --version=0.1 -c tools.cmake.cmakedeps:new={new_value}\",\n          assert_error=True)\n    assert (\"ERROR: Error in generator 'CMakeDeps': pkg/0.1 recipe cpp_info did .requires to \"\n            \"'dep::lib' but component 'lib' not found in dep\") in c.out\n\n\ndef test_consuming_cpp_info_transitively_by_requiring_root_component():\n    c = TestClient()\n    dependent_conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Dependent(ConanFile):\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            name = 'dependent'\n        \"\"\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            def requirements(self):\n                self.requires('dependent/0.1')\n            def package_info(self):\n                self.cpp_info.type = 'shared-library'\n                self.cpp_info.requires = ['dependent::dependent']\n        \"\"\")\n    test_package = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class TestPkg(ConanFile):\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            generators = \"VirtualRunEnv\", \"CMakeDeps\"\n\n            def requirements(self):\n                self.requires(self.tested_reference_str)\n\n            def test(self):\n                pass\n        \"\"\")\n    c.save({\"dependent/conanfile.py\": dependent_conanfile,\n            \"main/conanfile.py\": conanfile,\n            \"main/test_package/conanfile.py\": test_package})\n    c.run(\"create ./dependent/ --name=dependent --version=0.1 \"\n          f\"-c tools.cmake.cmakedeps:new={new_value}\")\n    c.run(f\"create ./main/ --name=pkg --version=0.1 -c tools.cmake.cmakedeps:new={new_value}\")\n\n\ndef test_cmake_find_mode_deprecated():\n    tc = TestClient()\n    dep = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"dep\"\n            version = \"0.1\"\n            def package_info(self):\n                # Having both is ok as the user expects that config would\n                # be generated nonetheless\n                self.cpp_info.set_property(\"cmake_find_mode\", \"module\")\n        \"\"\")\n    tc.save({\"conanfile.py\": dep})\n    tc.run(\"create .\")\n    args = f\"-g CMakeDeps -c tools.cmake.cmakedeps:new={new_value}\"\n    tc.run(f\"install --requires=dep/0.1 {args}\")\n    assert \"CMakeConfigDeps does not support module find mode\"\n\n\ndef test_build_context_deprecated():\n    tc = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n           from conan.tools.cmake import CMakeConfigDeps\n           from conan import ConanFile\n           class TestConan(ConanFile):\n               settings = \"build_type\"\n               def generate(self):\n                   deps = CMakeConfigDeps(self)\n                   deps.build_context_activated = [\"bar\"]\n                   deps.build_context_suffix = {\"bar\": \"_BUILD\"}\n                   deps.build_context_build_modules = [\"myfunctions\"]\n                   deps.check_components_exist = True\n                   deps.generate()\n       \"\"\")\n    tc.save({\"conanfile.py\": conanfile})\n    tc.run(\"install .\")\n    assert \"WARN: deprecated: CMakeConfigDeps.build_context_activated is deprecated\" in tc.out\n    assert \"WARN: deprecated: CMakeConfigDeps.build_context_suffix is deprecated\" in tc.out\n    assert \"WARN: deprecated: CMakeConfigDeps.build_context_build_modules is deprecated\" in tc.out\n    assert \"WARN: deprecated: CMakeConfigDeps.check_components_exist is deprecated\" in tc.out\n\n\ndef test_cmake_extra_dependencies():\n    tc = TestClient()\n    dep = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"dep\"\n            version = \"0.1\"\n            def package_info(self):\n                self.cpp_info.set_property(\"cmake_extra_dependencies\", [\"MyOpenMPI\"])\n                self.cpp_info.set_property(\"cmake_extra_interface_libs\", [\"MyOpenMPILib\"])\n        \"\"\")\n    tc.save({\"conanfile.py\": dep})\n    tc.run(\"create .\")\n    args = f\"-g CMakeDeps -c tools.cmake.cmakedeps:new={new_value}\"\n    tc.run(f\"install --requires=dep/0.1 {args}\")\n    dep = tc.load(\"dep-Targets-release.cmake\")\n    assert \"find_dependency(MyOpenMPI REQUIRED )\" in dep\n    assert \"set_property(TARGET dep::dep APPEND PROPERTY INTERFACE_LINK_LIBRARIES\\n\" \\\n           \"             $<$<CONFIG:RELEASE>:MyOpenMPILib>)\" in dep\n\n\ndef test_cmake_component_type_none_check():\n    tc = TestClient()\n    dep = (GenConanfile(\"dep\", \"0.1\")\n           .with_package_file(\"lib/libmain.so\", \"dynamic library\")\n           .with_package_info({\"components\": {\"main\": {\"libs\": [\"libmain.so\"], \"type\": \"'shared-library'\"}}}))\n    tc.save({\"conanfile.py\": dep})\n    tc.run(\"create\")\n    tc.run(\"install --requires=dep/0.1 -g CMakeConfigDeps\")\n    assert \"None is not a valid PackageType\" not in tc.out\n\n\ndef test_cmake_extra_dependencies_components():\n    tc = TestClient()\n    dep = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"dep\"\n            version = \"0.1\"\n            def package_info(self):\n                self.cpp_info.set_property(\"cmake_extra_dependencies\", [\"MyOpenMPI\"])\n                self.cpp_info.components[\"mycomp\"].set_property(\"cmake_extra_interface_libs\",\n                                                                [\"MyOpenMPILib\"])\n                self.cpp_info.components[\"mycomp\"].libs = [\"mycomplib\"]\n                self.cpp_info.components[\"mycomp\"].type = \"static-library\"\n                self.cpp_info.components[\"mycomp\"].location = \"lib/mycomp.a\"\n        \"\"\")\n    tc.save({\"conanfile.py\": dep})\n    tc.run(\"create .\")\n    args = f\"-g CMakeDeps -c tools.cmake.cmakedeps:new={new_value}\"\n    tc.run(f\"install --requires=dep/0.1 {args}\")\n    dep = tc.load(\"dep-Targets-release.cmake\")\n    assert \"find_dependency(MyOpenMPI REQUIRED )\" in dep\n    assert \"set_property(TARGET dep::mycomp APPEND PROPERTY INTERFACE_LINK_LIBRARIES\\n\" \\\n           \"             $<$<CONFIG:RELEASE>:MyOpenMPILib>)\" in dep\n\n\nclass TestRequiresToApp:\n    def test_requires_to_application(self):\n        c = TestClient()\n        automake = GenConanfile(\"automake\", \"0.1\").with_package_type(\"application\")\n        conanfile = (GenConanfile(\"libtool\", \"0.1\").with_package_type(\"static-library\")\n                                                   .with_requirement(\"automake/0.1\"))\n        test_package = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.cmake import CMake\n\n            class TestPkg(ConanFile):\n                settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n                generators = \"CMakeDeps\", \"CMakeToolchain\"\n\n                def requirements(self):\n                    self.requires(self.tested_reference_str)\n\n                def test(self):\n                    pass\n            \"\"\")\n\n        c.save({\"automake/conanfile.py\": automake,\n                \"libtool/conanfile.py\": conanfile,\n                \"libtool/test_package/conanfile.py\": test_package})\n        c.run(\"create automake\")\n        c.run(f\"create libtool -c tools.cmake.cmakedeps:new={new_value}\")\n        targets = c.load(\"libtool/test_package/libtool-Targets-release.cmake\")\n        # The libtool shouldn't depend on the automake::automake target\n        assert \"automake::automake\" not in targets\n\n    def test_requires_to_application_component(self):\n        c = TestClient()\n        automake = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Dependent(ConanFile):\n                name = \"automake\"\n                version = \"0.1\"\n                package_type = \"application\"\n\n                def package_info(self):\n                    self.cpp_info.components[\"myapp\"].exe = \"myapp\"\n                    self.cpp_info.components[\"myapp\"].location = \"path/to/myapp\"\n                    self.cpp_info.components[\"mylibapp\"].type = \"header-library\"\n            \"\"\")\n\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                name = \"libtool\"\n                version = \"0.1\"\n                package_type = \"static-library\"\n\n                def requirements(self):\n                    self.requires('automake/0.1')\n                def package_info(self):\n                    self.cpp_info.requires = [\"automake::mylibapp\"]\n            \"\"\")\n\n        c.save({\"automake/conanfile.py\": automake,\n                \"libtool/conanfile.py\": conanfile})\n        c.run(\"create automake\")\n\n        c.run(\"create libtool\")\n        c.run(\"install --requires=libtool/0.1 -g CMakeDeps \"\n              f\"-c tools.cmake.cmakedeps:new={new_value}\")\n        targets = c.load(\"libtool-Targets-release.cmake\")\n        # The libtool shouldn't depend on the automake::automake target\n        assert \"automake::automake\" not in targets\n        assert \"# Requirement libtool::libtool -> automake::mylibapp (Full link: True)\" in targets\n        assert \"$<$<CONFIG:RELEASE>:automake::mylibapp>\" in targets\n\n    def test_requires_from_library_component(self):\n        c = TestClient()\n        automake = GenConanfile(\"automake\", \"0.1\").with_package_type(\"application\")\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                name = \"libtool\"\n                version = \"0.1\"\n                package_type = \"static-library\"\n\n                def requirements(self):\n                    self.requires('automake/0.1')\n                def package_info(self):\n                    self.cpp_info.components[\"mycomp\"].requires = [\"automake::automake\"]\n            \"\"\")\n\n        c.save({\"automake/conanfile.py\": automake,\n                \"libtool/conanfile.py\": conanfile})\n        c.run(\"create automake\")\n        c.run(\"create libtool\")\n        c.run(\"install --requires=libtool/0.1 -g CMakeDeps \"\n              f\"-c tools.cmake.cmakedeps:new={new_value}\")\n        targets = c.load(\"libtool-Targets-release.cmake\")\n        # The libtool shouldn't depend on the automake::automake target\n        assert \"automake::automake\" not in targets\n\n    def test_requires_from_library_component_to_app_component(self):\n        c = TestClient()\n        automake = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Dependent(ConanFile):\n                name = \"automake\"\n                version = \"0.1\"\n\n                def package_info(self):\n                    self.cpp_info.components[\"myapp\"].exe = \"myapp\"\n                    self.cpp_info.components[\"myapp\"].location = \"path/to/myapp\"\n                    self.cpp_info.components[\"mylibapp\"].type = \"header-library\"\n            \"\"\")\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                name = \"libtool\"\n                version = \"0.1\"\n                package_type = \"static-library\"\n\n                def requirements(self):\n                    self.requires('automake/0.1')\n                def package_info(self):\n                    self.cpp_info.components[\"mycomp\"].requires = [\"automake::myapp\"]\n            \"\"\")\n\n        c.save({\"automake/conanfile.py\": automake,\n                \"libtool/conanfile.py\": conanfile})\n        c.run(\"create automake\")\n        c.run(\"create libtool\")\n        c.run(\"install --requires=libtool/0.1 -g CMakeDeps \"\n              f\"-c tools.cmake.cmakedeps:new={new_value}\")\n        targets = c.load(\"libtool-Targets-release.cmake\")\n        # The libtool shouldn't depend on the automake::automake target\n        assert \"automake::myapp\" not in targets\n        assert \"automake::automake\" not in targets\n\n\ndef test_alias_cmakedeps_set_property():\n    tc = TestClient()\n    tc.save({\"dep/conanfile.py\": textwrap.dedent(\"\"\"\n\n        from conan import ConanFile\n        class Dep(ConanFile):\n            name = \"dep\"\n            version = \"1.0\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            def package_info(self):\n                self.cpp_info.components[\"mycomp\"].set_property(\"cmake_target_name\",\n                                                                \"dep::mycomponent\")\n        \"\"\"),\n             \"conanfile.py\": textwrap.dedent(\"\"\"\n             from conan import ConanFile\n             from conan.tools.cmake import CMakeDeps, CMake\n             class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"1.0\"\n                settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n                requires = \"dep/1.0\"\n\n                def generate(self):\n                    deps = CMakeDeps(self)\n                    deps.set_property(\"dep\", \"cmake_target_aliases\", [\"alias\", \"dep::other_name\"])\n                    deps.set_property(\"dep::mycomp\", \"cmake_target_aliases\",\n                                      [\"component_alias\", \"dep::my_aliased_component\"])\n                    deps.generate()\n             \"\"\")})\n    tc.run(\"create dep\")\n    tc.run(f\"install . -c tools.cmake.cmakedeps:new={new_value}\")\n    targets_data = tc.load('dep-Targets-release.cmake')\n    assert \"add_library(dep::dep\" in targets_data\n    assert \"add_library(alias\" in targets_data\n    assert \"add_library(dep::other_name\" in targets_data\n\n    assert \"add_library(component_alias\" in targets_data\n    assert \"add_library(dep::my_aliased_component\" in targets_data\n\n\ndef test_package_info_extra_variables():\n    \"\"\" Test extra_variables property - This just shows that it works,\n    there are tests for cmaketoolchain that check the actual behavior\n    of parsing the variables\"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n\n            def package_info(self):\n                self.cpp_info.set_property(\"cmake_extra_variables\", {\"FOO\": 42,\n                                           \"BAR\": 42,\n                                           \"CMAKE_GENERATOR_INSTANCE\":\n                                                 \"${GENERATOR_INSTANCE}/buildTools/\",\n                                           \"CACHE_VAR_DEFAULT_DOC\": {\"value\": \"hello world\",\n                                                                     \"cache\": True, \"type\": \"PATH\"}})\n    \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create .\")\n\n    client.run(f\"install --requires=pkg/0.1 -g CMakeDeps -c tools.cmake.cmakedeps:new={new_value} \"\n               \"\"\"-c tools.cmake.cmaketoolchain:extra_variables=\"{'BAR': 9}\" \"\"\")\n    target = client.load(\"pkg-config.cmake\")\n    assert 'set(BAR' not in target\n    assert 'set(CMAKE_GENERATOR_INSTANCE \"${GENERATOR_INSTANCE}/buildTools/\")' in target\n    assert 'set(FOO 42)' in target\n    assert 'set(CACHE_VAR_DEFAULT_DOC \"hello world\" CACHE PATH \"CACHE_VAR_DEFAULT_DOC\")' in target\n\n\ndef test_target_defines_only():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n\n            def package_info(self):\n                self.cpp_info.components[\"base\"].includedirs = []\n                self.cpp_info.components[\"base\"].defines = [\"FOO=1\"]\n                self.cpp_info.components[\"comp\"].includedirs = [\"include\"]\n                self.cpp_info.components[\"comp\"].requires = [\"base\"]\n    \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create .\")\n\n    client.run(f\"install --requires=pkg/0.1 -g CMakeDeps -c tools.cmake.cmakedeps:new={new_value}\")\n    target = client.load(\"pkg-Targets-release.cmake\")\n    assert 'add_library(pkg::base INTERFACE IMPORTED)' in target\n    assert \"# Requirement pkg::comp -> pkg::base (Full link: True)\" in target\n\n\nclass TestLinkFeatures:\n    def test_link_info_global_cpp_info(self):\n        tc = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"1.0\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n            def package_info(self):\n                self.cpp_info.set_property(\"cmake_link_feature\", \"MYFET\")\n        \"\"\")\n        tc.save({\"conanfile.py\": conanfile})\n        tc.run(\"create\")\n\n        dep = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Dep(ConanFile):\n            name = \"dep\"\n            version = \"1.0\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            requires = \"pkg/1.0\"\n        \"\"\")\n        tc.save({\"conanfile.py\": dep})\n        tc.run(\"create\")\n        tc.run(\"install --requires=dep/1.0 -g CMakeConfigDeps\")\n        # The requirement should propagate the link feature info\n        target = tc.load(\"dep-Targets-release.cmake\")\n        assert \"# Requirement dep::dep -> pkg::pkg (Full link: True)\\n# Link feature: MYFET\" in target\n\n    def test_link_info_local_component_from_interface(self):\n        tc = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"1.0\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n            def package_info(self):\n                self.cpp_info.components[\"compA\"].set_property(\"cmake_link_feature\", \"MYFET\")\n        \"\"\")\n        tc.save({\"conanfile.py\": conanfile})\n        tc.run(\"create\")\n        tc.run(\"install --requires=pkg/1.0 -g CMakeConfigDeps\")\n        targets = tc.load(\"pkg-Targets-release.cmake\")\n        # The interface library created as a global target should have the requirement\n        assert \"# Requirement pkg::pkg -> pkg::compA (Full link: True)\\n# Link feature: MYFET\" in targets\n\n    def test_link_info_local_component_to_component_require(self):\n        tc = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"1.0\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n            def package_info(self):\n                self.cpp_info.components[\"compA\"].set_property(\"cmake_link_feature\", \"MYFET\")\n                self.cpp_info.components[\"compB\"].requires = [\"compA\"]\n        \"\"\")\n        tc.save({\"conanfile.py\": conanfile})\n        tc.run(\"create\")\n        tc.run(\"install --requires=pkg/1.0 -g CMakeConfigDeps\")\n        targets = tc.load(\"pkg-Targets-release.cmake\")\n        # The component requirement should have the link feature info\n        assert \"# Requirement pkg::compB -> pkg::compA (Full link: True)\\n# Link feature: MYFET\" in targets\n\n    def test_link_info_lib_to_component_require(self):\n        tc = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"1.0\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n            def package_info(self):\n                self.cpp_info.components[\"compA\"].set_property(\"cmake_link_feature\", \"MYFET\")\n        \"\"\")\n        tc.save({\"conanfile.py\": conanfile})\n        tc.run(\"create\")\n\n        dep = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Dep(ConanFile):\n            name = \"dep\"\n            version = \"1.0\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            requires = \"pkg/1.0\"\n\n            def package_info(self):\n                self.cpp_info.requires = [\"pkg::compA\"]\n        \"\"\")\n        tc.save({\"conanfile.py\": dep})\n        tc.run(\"create\")\n        tc.run(\"install --requires=dep/1.0 -g CMakeConfigDeps\")\n        targets = tc.load(\"dep-Targets-release.cmake\")\n        # The requirement should have the link feature info\n        assert \"# Requirement dep::dep -> pkg::compA (Full link: True)\\n# Link feature: MYFET\" in targets\n\n\ndef test_legacy_defines():\n    # We used not to populate this.\n    # We do for backward compatibility with old check_symbol_exists and similar CMake code\n    tc = TestClient()\n    tc.save({\"conanfile.py\": GenConanfile(\"mypkg\", \"1.0\")\n             .with_package_info({\"defines\": [\"MY_DEFINE\", \"MYVAR=1\"]})})\n    tc.run(\"create\")\n    tc.run(\"install --requires=mypkg/1.0 -g CMakeConfigDeps\")\n    mypkg_config = tc.load(\"mypkg-config.cmake\")\n    assert 'set(mypkg_DEFINITIONS \"-DMY_DEFINE;-DMYVAR=1\" )' in mypkg_config\n\n\nclass TestPropertiesBuildContext:\n    def test_property_build_context(self):\n        c = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.cmake import CMakeConfigDeps\n\n            class PackageConan(ConanFile):\n                name = \"package\"\n                settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n\n                def requirements(self):\n                    self.requires(\"zlib/1.3.1\")\n\n                def generate(self):\n                    deps = CMakeConfigDeps(self)\n                    deps.set_property(\"zlib\", \"cmake_file_name\", \"MyZlibName\")\n                    deps.generate()\n            \"\"\")\n        c.save({\"zlib/conanfile.py\": GenConanfile(\"zlib\", \"1.3.1\"),\n                \"pkg/conanfile.py\": conanfile})\n        c.run(\"create zlib\")\n        c.run(\"install pkg --build-require\")\n        assert \"find_package(MyZlibName)\" in c.out\n        config = c.load(\"pkg/MyZlibNameConfig.cmake\")\n        assert 'set(MyZlibName_VERSION_STRING \"1.3.1\")' in config\n\n\nclass TestExtraFindExtraVariants:\n    def test_generated_dir_entries(self):\n        tc = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n                from conan import ConanFile\n\n                class HelloConan(ConanFile):\n                    name = \"hello\"\n                    version = \"1.0\"\n\n                    def package_info(self):\n                        self.cpp_info.set_property(\"cmake_file_name_variants\", [\"HellO\", \"HELLO\"])\n                \"\"\")\n        tc.save({\"conanfile.py\": conanfile})\n        tc.run(\"create\")\n        tc.run(\"install --requires=hello/1.0 -g CMakeConfigDeps\")\n        paths_content = tc.load(\"conan_cmakedeps_paths.cmake\")\n        assert \"set(hello_DIR\" in paths_content\n        assert \"set(HellO_DIR\" in paths_content\n        assert \"set(HELLO_DIR\" in paths_content\n\n    def test_differing_names_instead_of_case(self):\n        tc = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class HelloConan(ConanFile):\n            name = \"hello\"\n            version = \"1.0\"\n\n            def package_info(self):\n                self.cpp_info.set_property(\"cmake_file_name_variants\", [\"Bye!\"])\n        \"\"\")\n        tc.save({\"conanfile.py\": conanfile})\n        tc.run(\"create\")\n        tc.run(\"install --requires=hello/1.0 -g CMakeConfigDeps\", assert_error=True)\n        assert (\"'cmake_file_name_variants' property contains \"\n                \"entries that differ from the default 'cmake_file_name'='hello'\") in tc.out\n\n    def test_consumer_dependency_name_change(self):\n        \"\"\" If the consumer changes the dependency name via\n        cmake_file_name, the extra casings do not get generated\"\"\"\n        tc = TestClient()\n        hello = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class HelloConan(ConanFile):\n            name = \"hello\"\n            version = \"1.0\"\n\n            def package_info(self):\n                self.cpp_info.set_property(\"cmake_file_name_variants\", [\"HellO\"])\n        \"\"\")\n        tc.save({\"hello/conanfile.py\": hello})\n        tc.run(\"create hello\")\n\n        conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMakeConfigDeps\n\n        class Consumer(ConanFile):\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            requires = \"hello/1.0\"\n            def generate(self):\n                deps = CMakeConfigDeps(self)\n                deps.set_property(\"hello\", \"cmake_file_name\", \"greetings\")\n                deps.generate()\n        \"\"\")\n\n        tc.save({\"conanfile.py\": conanfile})\n        tc.run(\"install\")\n        assert (\"'cmake_file_name_variants' property contains names \"\n                \"with different casings than the defined name 'greetings'\") in tc.out\n        paths_content = tc.load(\"conan_cmakedeps_paths.cmake\")\n        assert \"set(greetings_DIR\" in paths_content\n        # But the old casing names are not generated, even if they were defined in the package\n        # they would not work\n        assert \"set(HellO_DIR\" not in paths_content\n        # The original name is not created in any case either way, as expected when cmake_file_name is used\n        assert \"set(hello_DIR\" not in paths_content\n\n    def test_generated_dir_none_find_mode_multi_entries(self):\n        tc = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n                from conan import ConanFile\n\n                class HelloConan(ConanFile):\n                    name = \"hello\"\n                    version = \"1.0\"\n                    settings = \"build_type\"\n\n                    def package_info(self):\n                        self.cpp_info.set_property(\"cmake_find_mode\", \"none\")\n                        self.cpp_info.set_property(\"cmake_file_name_variants\", [\"HellO\", \"HELLO\"])\n                \"\"\")\n        tc.save({\"conanfile.py\": conanfile})\n        tc.run(\"create\")\n        tc.run(\"create -s=build_type=Debug\")\n        tc.run(\"install --requires=hello/1.0 -g CMakeConfigDeps\")\n        paths_content = tc.load(\"conan_cmakedeps_paths.cmake\")\n        assert \"set(hello_DIR\" not in paths_content\n        assert \"set(HellO_DIR\" not in paths_content\n        assert \"set(HELLO_DIR\" not in paths_content\n\n        assert \"list(APPEND CONAN_hello_DIR_MULTI\" in paths_content\n        assert \"list(APPEND CONAN_HellO_DIR_MULTI\" in paths_content\n        assert \"list(APPEND CONAN_HELLO_DIR_MULTI\" in paths_content\n\n        tc.run(\"install --requires=hello/1.0 -g CMakeConfigDeps -s=build_type=Debug\")\n        paths_content = tc.load(\"conan_cmakedeps_paths.cmake\")\n        # Reading already existing MULTI variables works\n        assert paths_content.count(\"list(APPEND CONAN_hello_DIR_MULTI\") == 2\n        assert paths_content.count(\"list(APPEND CONAN_HellO_DIR_MULTI\") == 2\n        assert paths_content.count(\"list(APPEND CONAN_HELLO_DIR_MULTI\") == 2\n\n    def test_find_file_in_package(self):\n        tc = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.files import save\n\n            class HelloConan(ConanFile):\n                name = \"hello\"\n                version = \"1.0\"\n                settings = \"build_type\"\n\n                def package(self):\n                    save(self, os.path.join(self.package_folder, \"HellOConfig.cmake\"), \"\")\n\n                def package_info(self):\n                    self.cpp_info.builddirs = [\".\"]\n                    self.cpp_info.set_property(\"cmake_find_mode\", \"none\")\n                    self.cpp_info.set_property(\"cmake_file_name_variants\", [\"HellO\", \"HELLO\"])\n            \"\"\")\n        tc.save({\"conanfile.py\": conanfile})\n        tc.run(\"create\")\n        tc.run(\"create -s=build_type=Debug\")\n        tc.run(\"install --requires=hello/1.0 -g CMakeConfigDeps\")\n        paths_content = tc.load(\"conan_cmakedeps_paths.cmake\")\n        assert \"set(hello_DIR\" in paths_content\n        assert \"set(HellO_DIR\" in paths_content\n        assert \"set(HELLO_DIR\" in paths_content\n\n\ndef test_requires_only_component_target_generation():\n    tc = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"1.0\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n            def package_info(self):\n                self.cpp_info.components[\"compA\"].includedirs = [\"include\"]\n                self.cpp_info.components[\"compB\"].includedirs = []\n                self.cpp_info.components[\"compB\"].requires = [\"compA\"]\n    \"\"\")\n    tc.save({\"conanfile.py\": conanfile})\n    tc.run(\"create .\")\n    tc.run(\"install --requires=pkg/1.0 -g CMakeConfigDeps\")\n    target = tc.load(\"pkg-Targets-release.cmake\")\n    # An otherwise empty component is generated as a target if it requires another component\n    # to work as an interface target for the requirement\n    # (For example, useful when a component aggregates optional components under it)\n    assert \"add_library(pkg::compB INTERFACE\" in target\n    assert \"# Requirement pkg::compB -> pkg::compA (Full link: True)\" in target\n    # And even if it's INTERFACE, the globally generated target requires it as usual\n    assert \"# Requirement pkg::pkg -> pkg::compB (Full link: True)\" in target\n"
  },
  {
    "path": "test/integration/toolchains/cmake/cmakeconfigdeps/test_cmakeconfigdeps_frameworks.py",
    "content": "import platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\nnew_value = \"will_break_next\"\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only OSX\")\ndef test_package_framework_needs_location():\n    conanfile = textwrap.dedent(f\"\"\"\n    import os\n    from conan import ConanFile\n\n    class MyFramework(ConanFile):\n        name = \"frame\"\n        version = \"1.0\"\n        settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n        package_type = 'static-library'\n\n        def package_info(self):\n            self.cpp_info.type = 'static-library'\n            self.cpp_info.package_framework = \"MyFramework\"\n    \"\"\")\n    test_conanfile = textwrap.dedent(\"\"\"\n    import os\n    from conan import ConanFile\n\n    class LibTestConan(ConanFile):\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n        generators = \"CMakeConfigDeps\", \"CMakeToolchain\"\n\n        def requirements(self):\n            self.requires(self.tested_reference_str)\n    \"\"\")\n    client = TestClient()\n    client.save({\n        'test_package/conanfile.py': test_conanfile,\n        'conanfile.py': conanfile\n    })\n    client.run(f\"create . -c tools.cmake.cmakedeps:new={new_value}\", assert_error=True)\n    assert \"Error in generator 'CMakeConfigDeps': cpp_info.location missing for framework MyFramework\" in client.out\n\n\ndef test_framework_only_component_generates_target():\n    conanfile = textwrap.dedent(f\"\"\"\n    import os\n    from conan import ConanFile\n\n    class MyFramework(ConanFile):\n        name = \"frame\"\n        version = \"1.0\"\n        settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n\n        def package_info(self):\n            self.cpp_info.frameworks = [\"MyFramework\"]\n            self.cpp_info.libdirs = []\n            self.cpp_info.includedirs = []\n    \"\"\")\n\n    tc = TestClient()\n    tc.save({\"conanfile.py\": conanfile})\n    tc.run(\"create .\")\n    tc.run(f\"install --requires=frame/1.0 -g CMakeConfigDeps -c=tools.cmake.cmakedeps:new={new_value}\")\n    targets = tc.load(\"frame-Targets-release.cmake\")\n    assert \"add_library(frame::frame INTERFACE IMPORTED)\" in targets\n"
  },
  {
    "path": "test/integration/toolchains/cmake/cmakedeps/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/toolchains/cmake/cmakedeps/test_cmakedeps.py",
    "content": "import os\nimport platform\nimport textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_package_from_system():\n    \"\"\"\n    If a node declares \"system_package\" property, the CMakeDeps generator will skip generating\n    the -config.cmake and the other files for that node but will keep the \"find_dependency\" for\n    the nodes depending on it. That will cause that cmake looks for the config files elsewhere\n    https://github.com/conan-io/conan/issues/8919\"\"\"\n    client = TestClient()\n    dep2 = str(GenConanfile().with_name(\"dep2\").with_version(\"1.0\")\n               .with_settings(\"os\", \"arch\", \"build_type\"))\n    dep2 += \"\"\"\n    def package_info(self):\n        self.cpp_info.set_property(\"cmake_find_mode\", \"None\")\n        self.cpp_info.set_property(\"cmake_file_name\", \"custom_dep2\")\n\n    \"\"\"\n    client.save({\"conanfile.py\": dep2})\n    client.run(\"create .\")\n\n    dep1 = GenConanfile().with_name(\"dep1\").with_version(\"1.0\").with_require(\"dep2/1.0\")\\\n                         .with_settings(\"os\", \"arch\", \"build_type\")\n    client.save({\"conanfile.py\": dep1})\n    client.run(\"create .\")\n\n    consumer = GenConanfile().with_name(\"consumer\").with_version(\"1.0\").\\\n        with_require(\"dep1/1.0\").with_generator(\"CMakeDeps\").\\\n        with_settings(\"os\", \"arch\", \"build_type\")\n    client.save({\"conanfile.py\": consumer})\n    client.run(\"install .\")\n\n    assert os.path.exists(os.path.join(client.current_folder, \"dep1-config.cmake\"))\n    assert not os.path.exists(os.path.join(client.current_folder, \"dep2-config.cmake\"))\n    assert not os.path.exists(os.path.join(client.current_folder, \"custom_dep2-config.cmake\"))\n    host_arch = client.get_default_host_profile().settings['arch']\n    dep1_contents = client.load(f\"dep1-release-{host_arch}-data.cmake\")\n    assert 'list(APPEND dep1_FIND_DEPENDENCY_NAMES custom_dep2)' in dep1_contents\n    assert 'set(custom_dep2_FIND_MODE \"\")' in dep1_contents\n\n\ndef test_test_package():\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"create . --name=gtest --version=1.0\")\n    client.run(\"create . --name=cmake --version=1.0\")\n\n    client.save({\"conanfile.py\": GenConanfile().with_tool_requires(\"cmake/1.0\").\n                with_test_requires(\"gtest/1.0\")})\n\n    client.run(\"export . --name=pkg --version=1.0\")\n\n    consumer = textwrap.dedent(r\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"CMakeDeps\"\n            requires = \"pkg/1.0\"\n        \"\"\")\n    client.save({\"conanfile.py\": consumer})\n    client.run(\"install . -s:b os=Windows -s:h os=Linux -s:h compiler=gcc -s:h compiler.version=7 \"\n               \"-s:h compiler.libcxx=libstdc++11 -s:h arch=x86_64 --build=missing\")\n    cmake_data = client.load(\"pkg-release-x86_64-data.cmake\")\n    assert \"gtest\" not in cmake_data\n\n\ndef test_components_error():\n    # https://github.com/conan-io/conan/issues/9331\n    client = TestClient()\n\n    conan_hello = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n\n        from conan.tools.files import save\n        class Pkg(ConanFile):\n            settings = \"os\"\n\n            def layout(self):\n                pass\n\n            def package_info(self):\n                self.cpp_info.components[\"say\"].includedirs = [\"include\"]\n            \"\"\")\n\n    client.save({\"conanfile.py\": conan_hello})\n    client.run(\"create . --name=hello --version=1.0\")\n\n\ndef test_cpp_info_component_objects():\n    client = TestClient()\n    conan_hello = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            settings = \"os\", \"arch\", \"build_type\"\n            def package_info(self):\n                self.cpp_info.components[\"say\"].objects = [\"mycomponent.o\"]\n            \"\"\")\n\n    client.save({\"conanfile.py\": conan_hello})\n    client.run(\"create . --name=hello --version=1.0 -s arch=x86_64 -s build_type=Release\")\n    client.run(\"install --requires=hello/1.0@ -g CMakeDeps -s arch=x86_64 -s build_type=Release\")\n    with open(os.path.join(client.current_folder, \"hello-Target-release.cmake\")) as f:\n        content = f.read()\n        assert \"\"\"set_property(TARGET hello::say\n                     APPEND PROPERTY INTERFACE_LINK_LIBRARIES\n                     $<$<CONFIG:Release>:${hello_hello_say_OBJECTS_RELEASE}>\n                     $<$<CONFIG:Release>:${hello_hello_say_LIBRARIES_TARGETS}>\n                     )\"\"\" in content\n        # If there are componets, there is not a global cpp so this is not generated\n        assert \"hello_OBJECTS_RELEASE\" not in content\n        # But the global target is linked with the targets from the components\n        assert \"set_property(TARGET hello::hello APPEND PROPERTY INTERFACE_LINK_LIBRARIES \" \\\n               \"hello::say)\" in content\n\n    with open(os.path.join(client.current_folder, \"hello-release-x86_64-data.cmake\")) as f:\n        content = f.read()\n        # https://github.com/conan-io/conan/issues/11862\n        # Global variables\n        assert 'set(hello_OBJECTS_RELEASE \"${hello_PACKAGE_FOLDER_RELEASE}/mycomponent.o\")' \\\n               in content\n        # But component variables\n        assert 'set(hello_hello_say_OBJECTS_RELEASE \"${hello_PACKAGE_FOLDER_RELEASE}/' \\\n               'mycomponent.o\")' in content\n\n\ndef test_cpp_info_component_error_aggregate():\n    # https://github.com/conan-io/conan/issues/10176\n    # This test was consistently failing because \"VirtualRunEnv\" was not doing a \"copy()\"\n    # of cpp_info before calling \"aggregate_components()\", and it was destructive, removing\n    # components data\n    client = TestClient()\n    conan_hello = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            def package_info(self):\n                self.cpp_info.components[\"say\"].includedirs = [\"include\"]\n            \"\"\")\n    consumer = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            requires = \"hello/1.0\"\n            generators = \"VirtualRunEnv\", \"CMakeDeps\"\n            def package_info(self):\n                self.cpp_info.components[\"chat\"].requires = [\"hello::say\"]\n        \"\"\")\n    test_package = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            generators = \"VirtualRunEnv\", \"CMakeDeps\"\n\n            def requirements(self):\n                self.requires(self.tested_reference_str)\n\n            def test(self):\n                pass\n        \"\"\")\n\n    client.save({\"hello/conanfile.py\": conan_hello,\n                 \"consumer/conanfile.py\": consumer,\n                 \"consumer/test_package/conanfile.py\": test_package})\n    client.run(\"create hello --name=hello --version=1.0\")\n    client.run(\"create consumer --name=consumer --version=1.0\")\n    assert \"consumer/1.0 (test package): Running test()\" in client.out\n\n\ndef test_cmakedeps_cppinfo_complex_strings():\n    client = TestClient(path_with_spaces=False)\n    conanfile = textwrap.dedent(r'''\n        from conan import ConanFile\n        class HelloLib(ConanFile):\n            def package_info(self):\n                self.cpp_info.defines.append(\"escape=partially \\\"escaped\\\"\")\n                self.cpp_info.defines.append(\"spaces=me you\")\n                self.cpp_info.defines.append(\"foobar=bazbuz\")\n                self.cpp_info.defines.append(\"answer=42\")\n        ''')\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"export . --name=hello --version=1.0\")\n    client.save({\"conanfile.txt\": \"[requires]\\nhello/1.0\\n\"}, clean_first=True)\n    client.run(\"install . --build=missing -g CMakeDeps\")\n    arch = client.get_default_host_profile().settings['arch']\n    deps = client.load(f\"hello-release-{arch}-data.cmake\")\n    assert r\"escape=partially \\\"escaped\\\"\" in deps\n    assert r\"spaces=me you\" in deps\n    assert r\"foobar=bazbuz\" in deps\n    assert r\"answer=42\" in deps\n\n\ndef test_dependency_props_from_consumer():\n    client = TestClient(path_with_spaces=False)\n    bar = textwrap.dedent(r'''\n        from conan import ConanFile\n        class FooConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            def package_info(self):\n                self.cpp_info.set_property(\"cmake_find_mode\", \"both\")\n                self.cpp_info.components[\"component1\"].requires = []\n        ''')\n\n    foo = textwrap.dedent(r'''\n        from conan import ConanFile\n        from conan.tools.cmake import CMakeDeps, cmake_layout\n        class FooConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            requires = \"bar/1.0\"\n            def layout(self):\n                cmake_layout(self)\n            def generate(self):\n                deps = CMakeDeps(self)\n                {set_find_mode}\n                deps.set_property(\"bar\", \"cmake_file_name\", \"custom_bar_file_name\")\n                deps.set_property(\"bar\", \"cmake_module_file_name\", \"custom_bar_module_file_name\")\n                deps.set_property(\"bar\", \"cmake_target_name\", \"custom_bar_target_name\")\n                deps.set_property(\"bar\", \"cmake_module_target_name\", \"custom_bar_module_target_name\")\n                deps.set_property(\"bar::component1\", \"cmake_target_name\", \"custom_bar_component_target_name\")\n                deps.generate()\n        ''')\n\n    set_find_mode = \"\"\"\n        deps.set_property(\"bar\", \"cmake_find_mode\", {find_mode})\n    \"\"\"\n\n    client.save({\"foo.py\": foo.format(set_find_mode=\"\"), \"bar.py\": bar}, clean_first=True)\n\n    if platform.system() != \"Windows\":\n        gen_folder = os.path.join(client.current_folder, \"build\", \"Release\", \"generators\")\n    else:\n        gen_folder = os.path.join(client.current_folder, \"build\", \"generators\")\n\n    module_file = os.path.join(gen_folder, \"module-custom_bar_module_file_nameTargets.cmake\")\n    components_module = os.path.join(gen_folder, \"custom_bar_file_name-Target-release.cmake\")\n    config_file = os.path.join(gen_folder, \"custom_bar_file_nameTargets.cmake\")\n\n    # uses cmake_find_mode set in bar: both\n    client.run(\"create bar.py --name=bar --version=1.0\")\n    client.run(\"install foo.py\")\n    assert os.path.exists(module_file)\n    assert os.path.exists(config_file)\n    module_content = client.load(module_file)\n    assert \"add_library(custom_bar_module_target_name INTERFACE IMPORTED)\" in module_content\n    config_content = client.load(config_file)\n    assert \"add_library(custom_bar_target_name INTERFACE IMPORTED)\" in config_content\n    components_module_content = client.load(components_module)\n    assert \"add_library(bar_custom_bar_component_target_name_DEPS_TARGET INTERFACE IMPORTED)\" in components_module_content\n\n    client.save({\"foo.py\": foo.format(set_find_mode=set_find_mode.format(find_mode=\"'none'\")),\n                 \"bar.py\": bar}, clean_first=True)\n    client.run(\"create bar.py --name=bar --version=1.0\")\n    client.run(\"install foo.py\")\n    assert not os.path.exists(module_file)\n    assert not os.path.exists(config_file)\n\n    client.save({\"foo.py\": foo.format(set_find_mode=set_find_mode.format(find_mode=\"'module'\")),\n                 \"bar.py\": bar}, clean_first=True)\n    client.run(\"create bar.py --name=bar --version=1.0\")\n    client.run(\"install foo.py\")\n    assert os.path.exists(module_file)\n    assert not os.path.exists(config_file)\n\n    client.save({\"foo.py\": foo.format(set_find_mode=set_find_mode.format(find_mode=\"'config'\")),\n                 \"bar.py\": bar}, clean_first=True)\n    client.run(\"create bar.py --name=bar --version=1.0\")\n    client.run(\"install foo.py\")\n    assert not os.path.exists(module_file)\n    assert os.path.exists(config_file)\n\n\ndef test_props_from_consumer_build_context_activated():\n    client = TestClient(path_with_spaces=False)\n    bar = textwrap.dedent(r'''\n        from conan import ConanFile\n        class FooConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            def package_info(self):\n                self.cpp_info.set_property(\"cmake_find_mode\", \"both\")\n                self.cpp_info.components[\"component1\"].requires = []\n        ''')\n\n    foo = textwrap.dedent(r'''\n        from conan import ConanFile\n        from conan.tools.cmake import CMakeDeps, cmake_layout\n        class FooConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            requires = \"bar/1.0\"\n            tool_requires = \"bar/1.0\"\n            def layout(self):\n                cmake_layout(self)\n            def generate(self):\n                deps = CMakeDeps(self)\n                deps.build_context_activated = [\"bar\"]\n                deps.build_context_suffix = {{\"bar\": \"_BUILD\"}}\n                {set_find_mode}\n\n                deps.set_property(\"bar\", \"cmake_file_name\", \"custom_bar_file_name\")\n                deps.set_property(\"bar\", \"cmake_module_file_name\", \"custom_bar_module_file_name\")\n                deps.set_property(\"bar\", \"cmake_target_name\", \"custom_bar_target_name\")\n                deps.set_property(\"bar\", \"cmake_module_target_name\", \"custom_bar_module_target_name\")\n                deps.set_property(\"bar::component1\", \"cmake_target_name\", \"custom_bar_component_target_name\")\n\n                deps.set_property(\"bar\", \"cmake_file_name\", \"custom_bar_build_file_name\", build_context=True)\n                deps.set_property(\"bar\", \"cmake_module_file_name\", \"custom_bar_build_module_file_name\", build_context=True)\n                deps.set_property(\"bar\", \"cmake_target_name\", \"custom_bar_build_target_name\", build_context=True)\n                deps.set_property(\"bar\", \"cmake_module_target_name\", \"custom_bar_build_module_target_name\", build_context=True)\n                deps.set_property(\"bar::component1\", \"cmake_target_name\", \"custom_bar_build_component_target_name\", build_context=True)\n\n                deps.generate()\n        ''')\n\n    set_find_mode = \"\"\"\n        deps.set_property(\"bar\", \"cmake_find_mode\", {find_mode})\n        deps.set_property(\"bar\", \"cmake_find_mode\", {find_mode}, build_context=True)\n    \"\"\"\n\n    client.save({\"foo.py\": foo.format(set_find_mode=\"\"), \"bar.py\": bar}, clean_first=True)\n\n    if platform.system() != \"Windows\":\n        gen_folder = os.path.join(client.current_folder, \"build\", \"Release\", \"generators\")\n    else:\n        gen_folder = os.path.join(client.current_folder, \"build\", \"generators\")\n\n    module_file = os.path.join(gen_folder, \"module-custom_bar_module_file_nameTargets.cmake\")\n    components_module = os.path.join(gen_folder, \"custom_bar_file_name-Target-release.cmake\")\n    config_file = os.path.join(gen_folder, \"custom_bar_file_nameTargets.cmake\")\n\n    module_file_build = os.path.join(gen_folder,\n                                     \"module-custom_bar_build_module_file_name_BUILDTargets.cmake\")\n    components_module_build = os.path.join(gen_folder,\n                                           \"custom_bar_build_file_name_BUILD-Target-release.cmake\")\n    config_file_build = os.path.join(gen_folder, \"custom_bar_build_file_name_BUILDTargets.cmake\")\n\n    # uses cmake_find_mode set in bar: both\n    client.run(\"create bar.py --name=bar --version=1.0 -pr:h=default -pr:b=default\")\n    client.run(\"install foo.py --name=foo --version=1.0 -pr:h=default -pr:b=default\")\n    assert os.path.exists(module_file)\n    assert os.path.exists(config_file)\n    assert os.path.exists(module_file_build)\n    assert os.path.exists(config_file_build)\n\n    module_content = client.load(module_file)\n    assert \"add_library(custom_bar_module_target_name INTERFACE IMPORTED)\" in module_content\n    config_content = client.load(config_file)\n    assert \"add_library(custom_bar_target_name INTERFACE IMPORTED)\" in config_content\n\n    module_content_build = client.load(module_file_build)\n    assert \"add_library(custom_bar_build_module_target_name INTERFACE IMPORTED)\" in module_content_build\n    config_content_build = client.load(config_file_build)\n    assert \"add_library(custom_bar_build_target_name INTERFACE IMPORTED)\" in config_content_build\n\n    components_module_content = client.load(components_module)\n    assert \"add_library(bar_custom_bar_component_target_name_DEPS_TARGET INTERFACE IMPORTED)\" in components_module_content\n\n    components_module_content_build = client.load(components_module_build)\n    assert \"add_library(bar_BUILD_custom_bar_build_component_target_name_DEPS_TARGET INTERFACE IMPORTED)\" in components_module_content_build\n\n    client.save(\n        {\"foo.py\": foo.format(set_find_mode=set_find_mode.format(find_mode=\"'none'\")), \"bar.py\": bar},\n        clean_first=True)\n    client.run(\"create bar.py --name=bar --version=1.0 -pr:h=default -pr:b=default\")\n    client.run(\"install foo.py --name=foo --version=1.0 -pr:h=default -pr:b=default\")\n    assert not os.path.exists(module_file)\n    assert not os.path.exists(config_file)\n    assert not os.path.exists(module_file_build)\n    assert not os.path.exists(config_file_build)\n\n    client.save({\"foo.py\": foo.format(set_find_mode=set_find_mode.format(find_mode=\"'module'\")),\n                 \"bar.py\": bar}, clean_first=True)\n    client.run(\"create bar.py --name=bar --version=1.0 -pr:h=default -pr:b=default\")\n    client.run(\"install foo.py --name=foo --version=1.0 -pr:h=default -pr:b=default\")\n    assert os.path.exists(module_file)\n    assert not os.path.exists(config_file)\n    assert os.path.exists(module_file_build)\n    assert not os.path.exists(config_file_build)\n\n    client.save({\"foo.py\": foo.format(set_find_mode=set_find_mode.format(find_mode=\"'config'\")),\n                 \"bar.py\": bar}, clean_first=True)\n    client.run(\"create bar.py --name=bar --version=1.0 -pr:h=default -pr:b=default\")\n    client.run(\"install foo.py --name=foo --version=1.0 -pr:h=default -pr:b=default\")\n    assert not os.path.exists(module_file)\n    assert os.path.exists(config_file)\n    assert not os.path.exists(module_file_build)\n    assert os.path.exists(config_file_build)\n\n    # invalidate upstream property setting a None, will use config that's the default\n    client.save({\"foo.py\": foo.format(set_find_mode=set_find_mode.format(find_mode=\"None\")),\n                 \"bar.py\": bar}, clean_first=True)\n    client.run(\"create bar.py --name=bar --version=1.0 -pr:h=default -pr:b=default\")\n    client.run(\"install foo.py --name=foo --version=1.0 -pr:h=default -pr:b=default\")\n    assert not os.path.exists(module_file)\n    assert os.path.exists(config_file)\n    assert not os.path.exists(module_file_build)\n    assert os.path.exists(config_file_build)\n\n\ndef test_skip_transitive_components():\n    \"\"\" when a transitive depenency is skipped, because its binary is not necessary\n    (shared->static), the ``components[].requires`` clause pointing to that skipped dependency\n    was failing with KeyError, as the dependency info was not there\n    \"\"\"\n    c = TestClient()\n    pkg = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            package_type = \"shared-library\"\n            requires = \"dep/0.1\"\n            def package_info(self):\n                self.cpp_info.components[\"mycomp\"].requires = [\"dep::dep\"]\n        \"\"\")\n\n    c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\").with_package_type(\"static-library\"),\n            \"pkg/conanfile.py\": pkg,\n            \"consumer/conanfile.py\": GenConanfile().with_settings(\"build_type\")\n                                                   .with_requires(\"pkg/0.1\")})\n    c.run(\"create dep\")\n    c.run(\"create pkg\")\n    c.run(\"install consumer -g CMakeDeps -v\")\n    c.assert_listed_binary({\"dep\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\", \"Skip\")})\n    # This used to error, as CMakeDeps was raising a KeyError\n    assert \"'CMakeDeps' calling 'generate()'\" in c.out\n\n\ndef test_error_missing_config_build_context():\n    \"\"\"\n    CMakeDeps was failing, not generating the zlib-config.cmake in the\n    build context, for a test_package that both requires(example/1.0) and\n    tool_requires(example/1.0), which depends on zlib\n    # https://github.com/conan-io/conan/issues/12664\n    \"\"\"\n    c = TestClient()\n    example = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        class Example(ConanFile):\n            name = \"example\"\n            version = \"1.0\"\n            requires = \"game/1.0\"\n            generators = \"CMakeDeps\"\n            settings = \"build_type\"\n            def build(self):\n                assert os.path.exists(\"math-config.cmake\")\n                assert os.path.exists(\"engine-config.cmake\")\n                assert os.path.exists(\"game-config.cmake\")\n            \"\"\")\n    c.save({\"math/conanfile.py\": GenConanfile(\"math\", \"1.0\").with_settings(\"build_type\"),\n            \"engine/conanfile.py\": GenConanfile(\"engine\", \"1.0\").with_settings(\"build_type\")\n                                                                .with_require(\"math/1.0\"),\n            \"game/conanfile.py\": GenConanfile(\"game\", \"1.0\").with_settings(\"build_type\")\n                                                            .with_requires(\"engine/1.0\"),\n            \"example/conanfile.py\": example,\n            # The example test_package contains already requires(self.tested_reference_str)\n            \"example/test_package/conanfile.py\": GenConanfile().with_build_requires(\"example/1.0\")\n                                                               .with_test(\"pass\")})\n    c.run(\"create math\")\n    c.run(\"create engine\")\n    c.run(\"create game\")\n    # This used to crash because of the assert inside the build() method\n    c.run(\"create example -pr:b=default -pr:h=default\")\n    # Now make sure we can actually build with build!=host context\n    # The debug binaries are missing, so adding --build=missing\n    c.run(\"create example -pr:b=default -pr:h=default -s:h build_type=Debug --build=missing \"\n          \"--build=example\")\n\n    # listed as both requires and build_requires\n    c.assert_listed_require({\"example/1.0\": \"Cache\"})\n    c.assert_listed_require({\"example/1.0\": \"Cache\"}, build=True)\n\n\ndef test_using_package_module():\n    \"\"\"\n    This crashed, because the profile \"build\" didn't have \"build_type\"\n    https://github.com/conan-io/conan/issues/13209\n    \"\"\"\n    c = TestClient()\n    c.save({\"conanfile.py\": GenConanfile(\"tool\", \"0.1\")})\n    c.run(\"create .\")\n\n    consumer = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMakeDeps\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            tool_requires = \"tool/0.1\"\n\n            def generate(self):\n                deps = CMakeDeps(self)\n                deps.build_context_activated = [\"tool\"]\n                deps.build_context_build_modules = [\"tool\"]\n                deps.generate()\n        \"\"\")\n    c.save({\"conanfile.py\": consumer,\n            \"profile_build\": \"[settings]\\nos=Windows\"}, clean_first=True)\n    c.run(\"create . -pr:b=profile_build\")\n    # it doesn't crash anymore, it used to crash\n    assert \"pkg/0.1: Created package\" in c.out\n\n\ndef test_system_libs_transitivity():\n    \"\"\"\n    https://github.com/conan-io/conan/issues/13358\n    \"\"\"\n    c = TestClient()\n    system = textwrap.dedent(\"\"\"\\\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"dep\"\n            version = \"system\"\n            def package_info(self):\n                self.cpp_info.system_libs = [\"m\"]\n                self.cpp_info.frameworks = [\"CoreFoundation\"]\n            \"\"\")\n    header = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Header(ConanFile):\n            name = \"header\"\n            version = \"0.1\"\n            package_type = \"header-library\"\n            requires = \"dep/system\"\n            def package_info(self):\n                self.cpp_info.system_libs = [\"dl\"]\n                self.cpp_info.frameworks = [\"CoreDriver\"]\n            \"\"\")\n    app = textwrap.dedent(\"\"\"\\\n        from conan import ConanFile\n        class App(ConanFile):\n            requires = \"header/0.1\"\n            settings = \"build_type\"\n            generators = \"CMakeDeps\"\n        \"\"\")\n    c.save({\"dep/conanfile.py\": system,\n            \"header/conanfile.py\": header,\n            \"app/conanfile.py\": app})\n    c.run(\"create dep\")\n    c.run(\"create header\")\n    c.run(\"install app\")\n    dep = c.load(\"app/dep-release-data.cmake\")\n    assert \"set(dep_SYSTEM_LIBS_RELEASE m)\" in dep\n    assert \"set(dep_FRAMEWORKS_RELEASE CoreFoundation)\" in dep\n    app = c.load(\"app/header-release-data.cmake\")\n    assert \"set(header_SYSTEM_LIBS_RELEASE dl)\" in app\n    assert \"set(header_FRAMEWORKS_RELEASE CoreDriver)\" in app\n\n\nclass TestCMakeVersionConfigCompat:\n    \"\"\"\n    https://github.com/conan-io/conan/issues/13809\n    \"\"\"\n    def test_cmake_version_config_compatibility(self):\n        c = TestClient()\n        dep = textwrap.dedent(\"\"\"\\\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                name = \"dep\"\n                version = \"0.1\"\n                def package_info(self):\n                    self.cpp_info.set_property(\"cmake_config_version_compat\", \"AnyNewerVersion\")\n                \"\"\")\n\n        c.save({\"conanfile.py\": dep})\n        c.run(\"create .\")\n        c.run(\"install --requires=dep/0.1 -g CMakeDeps\")\n        dep = c.load(\"dep-config-version.cmake\")\n        expected = textwrap.dedent(\"\"\"\\\n            if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION)\n                set(PACKAGE_VERSION_COMPATIBLE FALSE)\n            else()\n                set(PACKAGE_VERSION_COMPATIBLE TRUE)\n\n                if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION)\n                    set(PACKAGE_VERSION_EXACT TRUE)\n                endif()\n            endif()\"\"\")\n        assert expected in dep\n\n    def test_cmake_version_config_compatibility_error(self):\n        c = TestClient()\n        dep = textwrap.dedent(\"\"\"\\\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                name = \"dep\"\n                version = \"0.1\"\n                def package_info(self):\n                    self.cpp_info.set_property(\"cmake_config_version_compat\", \"Unknown\")\n                \"\"\")\n\n        c.save({\"conanfile.py\": dep})\n        c.run(\"create .\")\n        c.run(\"install --requires=dep/0.1 -g CMakeDeps\", assert_error=True)\n        assert \"Unknown cmake_config_version_compat=Unknown in dep/0.1\" in c.out\n\n    def test_cmake_version_config_compatibility_consumer(self):\n        c = TestClient()\n        app = textwrap.dedent(\"\"\"\\\n            from conan import ConanFile\n            from conan.tools.cmake import CMakeDeps\n            class Pkg(ConanFile):\n                settings = \"build_type\"\n                requires = \"dep/0.1\"\n                def generate(self):\n                    deps = CMakeDeps(self)\n                    deps.set_property(\"dep\", \"cmake_config_version_compat\", \"AnyNewerVersion\")\n                    deps.generate()\n                \"\"\")\n\n        c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\"),\n                \"app/conanfile.py\": app})\n        c.run(\"create dep\")\n        c.run(\"install app\")\n        dep = c.load(\"app/dep-config-version.cmake\")\n        expected = textwrap.dedent(\"\"\"\\\n            if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION)\n                set(PACKAGE_VERSION_COMPATIBLE FALSE)\n            else()\n                set(PACKAGE_VERSION_COMPATIBLE TRUE)\n\n                if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION)\n                    set(PACKAGE_VERSION_EXACT TRUE)\n                endif()\n            endif()\"\"\")\n        assert expected in dep\n\n\nclass TestSystemPackageVersion:\n    def test_component_version(self):\n        c = TestClient()\n        dep = textwrap.dedent(\"\"\"\\\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                name = \"dep\"\n                version = \"system\"\n                def package_info(self):\n                    self.cpp_info.set_property(\"system_package_version\", \"1.0\")\n                    self.cpp_info.components[\"mycomp\"].set_property(\"component_version\", \"2.3\")\n                \"\"\")\n\n        c.save({\"conanfile.py\": dep})\n        c.run(\"create .\")\n        c.run(\"install --requires=dep/system -g CMakeDeps -g PkgConfigDeps\")\n        dep = c.load(\"dep-config-version.cmake\")\n        assert 'set(PACKAGE_VERSION \"1.0\")' in dep\n        dep = c.load(\"dep.pc\")\n        assert 'Version: 1.0' in dep\n        dep = c.load(\"dep-mycomp.pc\")\n        assert 'Version: 2.3' in dep\n\n    def test_component_version_consumer(self):\n        c = TestClient()\n        app = textwrap.dedent(\"\"\"\\\n            from conan import ConanFile\n            from conan.tools.cmake import CMakeDeps\n            class Pkg(ConanFile):\n                settings = \"build_type\"\n                requires = \"dep/system\"\n                def generate(self):\n                    deps = CMakeDeps(self)\n                    deps.set_property(\"dep\", \"system_package_version\", \"1.0\")\n                    deps.generate()\n                \"\"\")\n\n        c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"system\"),\n                \"app/conanfile.py\": app})\n        c.run(\"create dep\")\n        c.run(\"install app\")\n        dep = c.load(\"app/dep-config-version.cmake\")\n        assert 'set(PACKAGE_VERSION \"1.0\")' in dep\n\n\ndef test_cmakedeps_set_property_overrides():\n    c = TestClient()\n    app = textwrap.dedent(\"\"\"\\\n        import os\n        from conan import ConanFile\n        from conan.tools.cmake import CMakeDeps\n        class Pkg(ConanFile):\n            settings = \"build_type\"\n            requires = \"dep/0.1\", \"other/0.1\"\n            def generate(self):\n                deps = CMakeDeps(self)\n                # Need the absolute path inside package\n                dep = self.dependencies[\"dep\"].package_folder\n                deps.set_property(\"dep\", \"cmake_build_modules\", [os.path.join(dep, \"my_module1\")])\n                deps.set_property(\"dep\", \"nosoname\", True)\n                deps.set_property(\"other::mycomp1\", \"nosoname\", True)\n                deps.generate()\n            \"\"\")\n\n    pkg_info = {\"components\": {\"mycomp1\": {\"libs\": [\"mylib\"]}}}\n    c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\").with_package_type(\"shared-library\"),\n            \"other/conanfile.py\": GenConanfile(\"other\", \"0.1\").with_package_type(\"shared-library\")\n                                                              .with_package_info(pkg_info),\n            \"app/conanfile.py\": app})\n    c.run(\"create dep\")\n    c.run(\"create other\")\n    c.run(\"install app\")\n    dep = c.load(\"app/dep-release-data.cmake\")\n    assert 'set(dep_BUILD_MODULES_PATHS_RELEASE \"${dep_PACKAGE_FOLDER_RELEASE}/my_module1\")' in dep\n    assert 'set(dep_NO_SONAME_MODE_RELEASE TRUE)' in dep\n    other = c.load(\"app/other-release-data.cmake\")\n    assert 'set(other_other_mycomp1_NO_SONAME_MODE_RELEASE TRUE)' in other\n\n\ndef test_cmakedeps_set_legacy_variable_name():\n    client = TestClient()\n    base_conanfile = str(GenConanfile(\"dep\", \"1.0\"))\n    conanfile = base_conanfile + \"\"\"\n    def package_info(self):\n        self.cpp_info.set_property(\"cmake_file_name\", \"CMakeFileName\")\n        self.cpp_info.set_property(\"cmake_find_mode\", \"both\")\n    \"\"\"\n    client.save({\"dep/conanfile.py\": conanfile})\n    client.run(\"create dep\")\n    client.run(\"install --requires=dep/1.0 -g CMakeDeps\")\n\n    # Check that all the CMake variables are generated with the file_name\n    dep_config = client.load(\"CMakeFileNameConfig.cmake\")\n    cmake_variables = [\"VERSION_STRING\", \"INCLUDE_DIRS\", \"INCLUDE_DIR\", \"LIBRARIES\", \"DEFINITIONS\"]\n    for variable in cmake_variables:\n        assert f\"CMakeFileName_{variable}\" in dep_config\n    dep_find = client.load(\"FindCMakeFileName.cmake\")\n    for variable in cmake_variables:\n        assert f\"CMakeFileName_{variable}\" in dep_find\n\n    consumer_conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMakeDeps\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            settings = \"os\", \"build_type\", \"arch\", \"compiler\"\n\n            def requirements(self):\n                self.requires(\"dep/1.0\")\n\n            def generate(self):\n                deps = CMakeDeps(self)\n                deps.set_property(\"dep\", \"cmake_additional_variables_prefixes\", [\"PREFIX\", \"prefix\", \"PREFIX\"])\n                deps.generate()\n        \"\"\")\n\n    client.save({\"consumer/conanfile.py\": consumer_conanfile})\n    client.run(\"install consumer\")\n\n    dep_config = client.load(os.path.join(\"consumer\", \"CMakeFileNameConfig.cmake\"))\n    for variable in cmake_variables:\n        assert f\"CMakeFileName_{variable}\" in dep_config\n        assert f\"PREFIX_{variable}\" in dep_config\n        assert f\"prefix_{variable}\" in dep_config\n\n    dep_find = client.load(os.path.join(\"consumer\", \"FindCMakeFileName.cmake\"))\n    for variable in cmake_variables:\n        assert f\"CMakeFileName_{variable}\" in dep_find\n        assert f\"PREFIX_{variable}\" in dep_find\n        assert f\"prefix_{variable}\" in dep_find\n    assert \"set(prefix_FOUND 1)\" in dep_find\n    assert \"set(PREFIX_FOUND 1)\" in dep_find\n    assert 'set(prefix_VERSION \"1.0\")' in dep_find\n    assert 'set(PREFIX_VERSION \"1.0\")' in dep_find\n\n    conanfile = base_conanfile + \"\"\"\n    def package_info(self):\n        self.cpp_info.set_property(\"cmake_file_name\", \"NewCMakeFileName\")\n        self.cpp_info.set_property(\"cmake_additional_variables_prefixes\", [\"PREFIX\", \"prefix\", \"PREFIX\"])\n    \"\"\"\n    client.save({\"dep/conanfile.py\": conanfile})\n    client.run(\"create dep\")\n    client.run(\"install --requires=dep/1.0 -g CMakeDeps\")\n\n    # Check that all the CMake variables are generated with the file_name and both prefixes\n    dep_config = client.load(\"NewCMakeFileNameConfig.cmake\")\n    for variable in cmake_variables:\n        assert f\"NewCMakeFileName_{variable}\" in dep_config\n        assert f\"PREFIX_{variable}\" in dep_config\n        assert f\"prefix_{variable}\" in dep_config\n    # Check that variables are not duplicated\n    assert dep_config.count(\"PREFIX_VERSION\") == 1\n\n\ndef test_different_versions():\n    # https://github.com/conan-io/conan/issues/16274\n    c = TestClient()\n    c.save({\"dep/conanfile.py\": GenConanfile(\"dep\")})\n    c.run(\"create dep --version 1.2\")\n    c.run(\"create dep --version 2.3\")\n    c.run(\"install --requires=dep/1.2 -g CMakeDeps\")\n    config = c.load(\"dep-config.cmake\")\n    assert 'set(dep_VERSION_STRING \"1.2\")' in config\n    c.run(\"install --requires=dep/2.3 -g CMakeDeps\")\n    config = c.load(\"dep-config.cmake\")\n    assert 'set(dep_VERSION_STRING \"2.3\")' in config\n\n\ndef test_using_deployer_folder():\n    \"\"\"\n    Related to: https://github.com/conan-io/conan/issues/16543\n\n    CMakeDeps was failing if --deployer-folder was used. The error looked like:\n\n    conans.errors.ConanException: Error in generator 'CMakeDeps': error generating context for 'dep/1.0': mydeploy/direct_deploy/dep/include is not absolute\n    \"\"\"\n    c = TestClient()\n    profile = textwrap.dedent(\"\"\"\n    [settings]\n    arch=x86_64\n    build_type=Release\n    compiler=apple-clang\n    compiler.cppstd=gnu17\n    compiler.libcxx=libc++\n    compiler.version=15\n    os=Macos\n    \"\"\")\n    c.save({\n        \"profile\": profile,\n        \"dep/conanfile.py\": GenConanfile(\"dep\")})\n    c.run(\"create dep --version 1.0\")\n    c.run(\"install --requires=dep/1.0 -pr profile --deployer=direct_deploy \"\n          \"--deployer-folder=mydeploy -g CMakeDeps\")\n    content = c.load(\"dep-release-x86_64-data.cmake\")\n    assert ('set(dep_PACKAGE_FOLDER_RELEASE \"${CMAKE_CURRENT_LIST_DIR}/mydeploy/direct_deploy/dep\")'\n            in content)\n\n\ndef test_component_name_same_package():\n    \"\"\"\n    When the package and the component are the same the variables declared in data and linked\n    to the target have to be the same.\n    https://github.com/conan-io/conan/issues/9071\n\n    This doesn't seem to have any special treatment, in fact, last FIXME looks it could be\n    problematic\n    \"\"\"\n    c = TestClient()\n    dep = textwrap.dedent(\"\"\"\\\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"dep\"\n            version = \"0.1\"\n            def package_info(self):\n                self.cpp_info.components[\"dep\"].includedirs = [\"myincludes\"]\n            \"\"\")\n    c.save({\"conanfile.py\": dep})\n    c.run(\"create .\")\n    c.run(\"install --requires=dep/0.1 -g CMakeDeps -s arch=x86_64\")\n    cmake_data = c.load(\"dep-release-x86_64-data.cmake\")\n    assert 'set(dep_dep_dep_INCLUDE_DIRS_RELEASE ' \\\n           '\"${dep_PACKAGE_FOLDER_RELEASE}/myincludes\")' in cmake_data\n    cmake_target = c.load(\"dep-Target-release.cmake\")\n    assert 'add_library(dep_dep_dep_DEPS_TARGET INTERFACE IMPORTED)' in cmake_target\n    assert 'set_property(TARGET dep::dep APPEND' in cmake_target\n    # FIXME: Depending on itself, this doesn't look good\n    assert 'set_property(TARGET dep::dep APPEND PROPERTY ' \\\n           'INTERFACE_LINK_LIBRARIES dep::dep)' in cmake_target\n\n\ndef test_cmakedeps_set_get_property_checktype():\n    c = TestClient()\n    app = textwrap.dedent(\"\"\"\\\n        from conan import ConanFile\n        from conan.tools.cmake import CMakeDeps\n        class Pkg(ConanFile):\n            name = \"app\"\n            version = \"0.1\"\n            settings = \"build_type\"\n            requires = \"dep/0.1\"\n            def generate(self):\n                deps = CMakeDeps(self)\n                deps.set_property(\"dep\", \"foo\", 1)\n                deps.get_property(\"foo\", self.dependencies[\"dep\"], check_type=list)\n                deps.generate()\n            \"\"\")\n\n    c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\"),\n            \"app/conanfile.py\": app})\n    c.run(\"create dep\")\n    c.run(\"create app\", assert_error=True)\n    assert 'The expected type for foo is \"list\", but \"int\" was found' in c.out\n\n\ndef test_alias_cmakedeps_set_property():\n    tc = TestClient()\n    tc.save({\"dep/conanfile.py\": textwrap.dedent(\"\"\"\n\n        from conan import ConanFile\n        class Dep(ConanFile):\n            name = \"dep\"\n            version = \"1.0\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            def package_info(self):\n                self.cpp_info.components[\"mycomp\"].set_property(\"cmake_target_name\", \"dep::mycomponent\")\n        \"\"\"),\n             \"conanfile.py\": textwrap.dedent(\"\"\"\n             from conan import ConanFile\n             from conan.tools.cmake import CMakeDeps, CMake\n             class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"1.0\"\n                settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n                requires = \"dep/1.0\"\n\n                def generate(self):\n                    deps = CMakeDeps(self)\n                    deps.set_property(\"dep\", \"cmake_target_aliases\", [\"alias\", \"dep::other_name\"])\n                    deps.set_property(\"dep::mycomp\", \"cmake_target_aliases\", [\"component_alias\", \"dep::my_aliased_component\"])\n                    deps.generate()\n             \"\"\")})\n    tc.run(\"create dep\")\n    tc.run(\"install .\")\n    targets_data = tc.load(\"depTargets.cmake\")\n    assert \"add_library(dep::dep\" in targets_data\n    assert \"add_library(alias\" in targets_data\n    assert \"add_library(dep::other_name\" in targets_data\n\n    assert \"add_library(component_alias\" in targets_data\n    assert \"add_library(dep::my_aliased_component\" in targets_data\n\n\ndef test_package_info_extra_variables():\n    \"\"\" Test extra_variables property - This just shows that it works,\n    there are tests for cmaketoolchain that check the actual behavior\n    of parsing the variables\"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n\n            def package_info(self):\n                self.cpp_info.set_property(\"cmake_extra_variables\", {\"FOO\": 42,\n                                           \"BAR\": 42,\n                                           \"CMAKE_GENERATOR_INSTANCE\": \"${GENERATOR_INSTANCE}/buildTools/\",\n                                           \"CACHE_VAR_DEFAULT_DOC\": {\"value\": \"hello world\",\n                                                                     \"cache\": True, \"type\": \"PATH\"}})\n    \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create .\")\n\n    client.run(\"install --requires=pkg/0.1 -g CMakeDeps \"\n               \"\"\"-c tools.cmake.cmaketoolchain:extra_variables=\"{'BAR': 9}\" \"\"\")\n    target = client.load(\"pkg-config.cmake\")\n    assert 'set(BAR' not in target\n    assert 'set(CMAKE_GENERATOR_INSTANCE \"${GENERATOR_INSTANCE}/buildTools/\")' in target\n    assert 'set(FOO 42)' in target\n    assert 'set(CACHE_VAR_DEFAULT_DOC \"hello world\" CACHE PATH \"CACHE_VAR_DEFAULT_DOC\")' in target\n"
  },
  {
    "path": "test/integration/toolchains/cmake/cmakedeps/test_cmakedeps_find_module_and_config.py",
    "content": "import os\nimport textwrap\n\nimport pytest\n\nfrom conan.tools.cmake.cmakedeps.cmakedeps import FIND_MODE_CONFIG, FIND_MODE_MODULE, \\\n    FIND_MODE_BOTH, FIND_MODE_NONE\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.parametrize(\"cmake_find_mode\", [FIND_MODE_CONFIG, FIND_MODE_MODULE,\n                                             FIND_MODE_BOTH, FIND_MODE_NONE, None])\ndef test_reuse_with_modules_and_config(cmake_find_mode):\n    t = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Conan(ConanFile):\n            def package_info(self):\n                {}\n        \"\"\")\n\n    if cmake_find_mode is not None:\n        s = 'self.cpp_info.set_property(\"cmake_find_mode\", \"{}\")'.format(cmake_find_mode)\n        conanfile = conanfile.format(s)\n    t.save({\"conanfile.py\": conanfile})\n    t.run(\"create . --name=mydep --version=1.0\")\n\n    conanfile = GenConanfile().with_name(\"myapp\").with_require(\"mydep/1.0\")\\\n                                                 .with_generator(\"CMakeDeps\")\\\n                                                 .with_settings(\"build_type\", \"os\", \"arch\")\n    t.save({\"conanfile.py\": conanfile})\n\n    t.run(\"install . --output-folder=install -s os=Linux -s compiler=gcc -s compiler.version=6 \"\n          \"-s compiler.libcxx=libstdc++11\")\n\n    def exists_config():\n        return os.path.exists(os.path.join(t.current_folder, \"install\", \"mydep-config.cmake\"))\n\n    def exists_module():\n        return os.path.exists(os.path.join(t.current_folder, \"install\", \"Findmydep.cmake\"))\n\n    if cmake_find_mode == FIND_MODE_CONFIG or cmake_find_mode is None:\n        # None is default \"config\"\n        assert exists_config()\n        assert not exists_module()\n    elif cmake_find_mode == FIND_MODE_MODULE:\n        assert not exists_config()\n        assert exists_module()\n    elif cmake_find_mode == FIND_MODE_BOTH:\n        assert exists_config()\n        assert exists_module()\n    elif cmake_find_mode == FIND_MODE_NONE:\n        assert not exists_config()\n        assert not exists_module()\n"
  },
  {
    "path": "test/integration/toolchains/cmake/test_cmake.py",
    "content": "import textwrap\nfrom string import Template\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_configure_args():\n    client = TestClient()\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"CMakeToolchain\"\n            def build(self):\n                cmake = CMake(self)\n                cmake.configure(variables={\"MYVAR\": \"MYVALUE\"})\n                cmake.build(cli_args=[\"--verbosebuild\"], build_tool_args=[\"-something\"])\n                cmake.test(cli_args=[\"--testverbose\"], build_tool_args=[\"-testok\"])\n\n            def run(self, *args, **kwargs):\n                self.output.info(\"MYRUN: {}\".format(*args))\n            \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . \")\n    # TODO: This check is ugly, because the command line is so different in each platform,\n    #  and args_to_string() is doing crazy stuff\n    assert '-DMYVAR=\"MYVALUE\"' in client.out\n    assert \"--verbosebuild\" in client.out\n    assert \"-something\" in client.out\n    assert \"--testverbose\" in client.out\n    assert \"-testok\" in client.out\n\n\n@pytest.mark.parametrize(\"argument, output_args\", [\n    (\"'target'\", \"--target target\"),\n    (\"['target']\", \"--target target\"),\n    (\"['target1', 'target2']\", \"--target target1 target2\"),\n])\ndef test_multiple_targets(argument, output_args):\n    client = TestClient()\n\n    conanfile_template = Template(textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n        class Pkg(ConanFile):\n            generators = \"CMakeToolchain\"\n            name = \"pkg\"\n            version = \"0.1\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            def build(self):\n                cmake = CMake(self)\n                cmake.build(target=${argument})\n\n            def run(self, *args, **kwargs):\n                self.output.info(\"MYRUN: {}\".format(*args))\n            \"\"\"))\n    conanfile = conanfile_template.substitute(argument=argument)\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . \")\n    assert output_args in client.out\n"
  },
  {
    "path": "test/integration/toolchains/cmake/test_cmaketoolchain.py",
    "content": "import json\nimport os\nimport platform\nimport re\nimport textwrap\n\nimport pytest\nfrom unittest import mock\n\nfrom conan.tools.cmake.presets import load_cmake_presets\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import rmdir, load\n\n\ndef test_cross_build():\n    windows_profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=Windows\n        arch=x86_64\n        \"\"\")\n    rpi_profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=Linux\n        compiler=gcc\n        compiler.version=6\n        compiler.libcxx=libstdc++11\n        arch=armv8\n        build_type=Release\n        \"\"\")\n    embedwin = textwrap.dedent(\"\"\"\n        [settings]\n        os=Windows\n        compiler=gcc\n        compiler.version=6\n        compiler.libcxx=libstdc++11\n        arch=armv8\n        build_type=Release\n        \"\"\")\n\n    client = TestClient(path_with_spaces=False)\n\n    conanfile = GenConanfile().with_settings(\"os\", \"arch\", \"compiler\", \"build_type\")\\\n        .with_generator(\"CMakeToolchain\")\n    client.save({\"conanfile.py\": conanfile,\n                 \"rpi\": rpi_profile,\n                 \"embedwin\": embedwin,\n                 \"windows\": windows_profile})\n    client.run(\"install . --profile:build=windows --profile:host=rpi\")\n    toolchain = client.load(\"conan_toolchain.cmake\")\n\n    assert \"set(CMAKE_SYSTEM_NAME Linux)\" in toolchain\n    assert \"set(CMAKE_SYSTEM_PROCESSOR aarch64)\" in toolchain\n    # Revert of https://github.com/conan-io/conan/pull/18559, even if it was correct\n    # assert \"set(CMAKE_TRY_COMPILE_CONFIGURATION Release)\" in toolchain\n\n    client.run(\"install . --profile:build=windows --profile:host=embedwin\")\n    toolchain = client.load(\"conan_toolchain.cmake\")\n\n    assert \"set(CMAKE_SYSTEM_NAME Windows)\" in toolchain\n    assert \"set(CMAKE_SYSTEM_PROCESSOR ARM64)\" in toolchain\n\n\ndef test_cross_build_linux_to_macos():\n    linux_profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=Linux\n        arch=x86_64\n        \"\"\")\n    macos_profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=Macos\n        os.version=13.1\n        arch=x86_64\n        compiler=apple-clang\n        compiler.version=13\n        compiler.libcxx=libc++\n        build_type=Release\n        \"\"\")\n\n    client = TestClient(path_with_spaces=False)\n\n    client.save({\"conanfile.txt\": \"[generators]\\nCMakeToolchain\",\n                 \"linux\": linux_profile,\n                 \"macos\": macos_profile})\n    client.run(\"install . --profile:build=linux --profile:host=macos\")\n    toolchain = client.load(\"conan_toolchain.cmake\")\n\n    assert \"set(CMAKE_SYSTEM_NAME Darwin)\" in toolchain\n    assert \"set(CMAKE_SYSTEM_VERSION 22)\" in toolchain\n    assert \"set(CMAKE_SYSTEM_PROCESSOR x86_64)\" in toolchain\n    # Revert of https://github.com/conan-io/conan/pull/18559, even if it was correct\n    # assert \"set(CMAKE_TRY_COMPILE_CONFIGURATION Release)\" in toolchain\n\n\ndef test_cross_build_user_toolchain():\n    # When a user_toolchain is defined in [conf], CMakeToolchain will not generate anything\n    # for cross-build\n    windows_profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=Windows\n        arch=x86_64\n        \"\"\")\n    rpi_profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=Linux\n        compiler=gcc\n        compiler.version=6\n        compiler.libcxx=libstdc++11\n        arch=armv8\n        build_type=Release\n        [conf]\n        tools.cmake.cmaketoolchain:user_toolchain+=rpi_toolchain.cmake\n        \"\"\")\n\n    client = TestClient(path_with_spaces=False)\n\n    conanfile = GenConanfile().with_settings(\"os\", \"arch\", \"compiler\", \"build_type\")\\\n        .with_generator(\"CMakeToolchain\")\n    client.save({\"conanfile.py\": conanfile,\n                \"rpi\": rpi_profile,\n                 \"windows\": windows_profile})\n    client.run(\"install . --profile:build=windows --profile:host=rpi\")\n    toolchain = client.load(\"conan_toolchain.cmake\")\n\n    # Fixed in https://github.com/conan-io/conan/issues/16807\n    expected = textwrap.dedent(\"\"\"\\\n        # Cross building\n        if(NOT DEFINED CMAKE_SYSTEM_NAME) # It might have been defined by a user toolchain\n        set(CMAKE_SYSTEM_NAME Linux)\n        endif()\n        if(NOT DEFINED CMAKE_SYSTEM_PROCESSOR) # It might have been defined by a user toolchain\n        set(CMAKE_SYSTEM_PROCESSOR aarch64)\n        endif()\"\"\")\n    assert expected in toolchain\n\n\ndef test_cross_build_user_toolchain_confs():\n    # When a user_toolchain is defined in [conf], but other confs are defined, they will be used\n    windows_profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=Windows\n        arch=x86_64\n        \"\"\")\n    rpi_profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=Linux\n        compiler=gcc\n        compiler.version=6\n        compiler.libcxx=libstdc++11\n        arch=armv8\n        build_type=Release\n        [conf]\n        tools.cmake.cmaketoolchain:user_toolchain+=rpi_toolchain.cmake\n        tools.cmake.cmaketoolchain:system_name=Linux\n        tools.cmake.cmaketoolchain:system_processor=aarch64\n        \"\"\")\n\n    client = TestClient(path_with_spaces=False)\n\n    conanfile = GenConanfile().with_settings(\"os\", \"arch\", \"compiler\", \"build_type\")\\\n        .with_generator(\"CMakeToolchain\")\n    client.save({\"conanfile.py\": conanfile,\n                \"rpi\": rpi_profile,\n                 \"windows\": windows_profile})\n    client.run(\"install . --profile:build=windows --profile:host=rpi\")\n    toolchain = client.load(\"conan_toolchain.cmake\")\n\n    assert \"set(CMAKE_SYSTEM_NAME Linux)\" in toolchain\n    assert \"set(CMAKE_SYSTEM_PROCESSOR aarch64)\" in toolchain\n\n\ndef test_no_cross_build():\n    windows_profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=Windows\n        arch=x86_64\n        compiler=gcc\n        compiler.version=6\n        compiler.libcxx=libstdc++11\n        build_type=Release\n        \"\"\")\n\n    client = TestClient(path_with_spaces=False)\n\n    conanfile = GenConanfile().with_settings(\"os\", \"arch\", \"compiler\", \"build_type\")\\\n        .with_generator(\"CMakeToolchain\")\n    client.save({\"conanfile.py\": conanfile,\n                 \"windows\": windows_profile})\n    client.run(\"install . --profile:build=windows --profile:host=windows\")\n    toolchain = client.load(\"conan_toolchain.cmake\")\n\n    assert \"CMAKE_SYSTEM_NAME \" not in toolchain\n    assert \"CMAKE_SYSTEM_PROCESSOR\" not in toolchain\n\n\ndef test_cross_arch():\n    # Compiling to 32bits in an architecture that runs is not full cross-compiling\n    build_profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=Linux\n        arch=x86_64\n        \"\"\")\n    profile_arm = textwrap.dedent(\"\"\"\n        [settings]\n        os=Linux\n        arch=armv8\n        compiler=gcc\n        compiler.version=6\n        compiler.libcxx=libstdc++11\n        build_type=Release\n        \"\"\")\n    profile_macos = textwrap.dedent(\"\"\"\n        [settings]\n        os=Macos\n        arch=armv8\n        compiler=gcc\n        compiler.version=6\n        compiler.libcxx=libstdc++11\n        build_type=Release\n        \"\"\")\n\n    client = TestClient(path_with_spaces=False)\n\n    conanfile = GenConanfile().with_settings(\"os\", \"arch\", \"compiler\", \"build_type\")\\\n        .with_generator(\"CMakeToolchain\")\n    client.save({\"conanfile.py\": conanfile,\n                 \"linux64\": build_profile,\n                 \"macos\": profile_macos,\n                 \"linuxarm\": profile_arm})\n    client.run(\"install . --profile:build=linux64 --profile:host=linuxarm\")\n    toolchain = client.load(\"conan_toolchain.cmake\")\n\n    assert \"set(CMAKE_SYSTEM_NAME Linux)\" in toolchain\n    assert \"set(CMAKE_SYSTEM_PROCESSOR aarch64)\" in toolchain\n\n    client.run(\"install . --profile:build=linux64 --profile:host=macos\")\n    toolchain = client.load(\"conan_toolchain.cmake\")\n\n    assert \"set(CMAKE_SYSTEM_NAME Darwin)\" in toolchain\n    assert \"set(CMAKE_SYSTEM_PROCESSOR arm64)\" in toolchain\n\n\ndef test_no_cross_build_arch():\n    # Compiling to 32bits in an architecture that runs is not full cross-compiling\n    build_profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=Linux\n        arch=x86_64\n        \"\"\")\n    profile_32 = textwrap.dedent(\"\"\"\n        [settings]\n        os=Linux\n        arch=x86\n        compiler=gcc\n        compiler.version=6\n        compiler.libcxx=libstdc++11\n        build_type=Release\n        \"\"\")\n\n    client = TestClient(path_with_spaces=False)\n\n    conanfile = GenConanfile().with_settings(\"os\", \"arch\", \"compiler\", \"build_type\")\\\n        .with_generator(\"CMakeToolchain\")\n    client.save({\"conanfile.py\": conanfile,\n                \"linux64\": build_profile,\n                 \"linux32\": profile_32})\n    client.run(\"install . --profile:build=linux64 --profile:host=linux32\")\n    toolchain = client.load(\"conan_toolchain.cmake\")\n\n    assert \"CMAKE_SYSTEM_NAME\" not in toolchain\n    assert \"CMAKE_SYSTEM_PROCESSOR \" not in toolchain\n\n\ndef test_cross_build_conf():\n    windows_profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=Windows\n        arch=x86_64\n        \"\"\")\n    rpi_profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=Linux\n        compiler=gcc\n        compiler.version=6\n        compiler.libcxx=libstdc++11\n        arch=armv8\n        build_type=Release\n\n        [conf]\n        tools.cmake.cmaketoolchain:system_name = Custom\n        tools.cmake.cmaketoolchain:system_version= 42\n        tools.cmake.cmaketoolchain:system_processor = myarm\n        \"\"\")\n\n    client = TestClient(path_with_spaces=False)\n\n    conanfile = GenConanfile().with_settings(\"os\", \"arch\", \"compiler\", \"build_type\")\\\n        .with_generator(\"CMakeToolchain\")\n    client.save({\"conanfile.py\": conanfile,\n                \"rpi\": rpi_profile,\n                 \"windows\": windows_profile})\n    client.run(\"install . --profile:build=windows --profile:host=rpi\")\n    toolchain = client.load(\"conan_toolchain.cmake\")\n\n    assert \"set(CMAKE_SYSTEM_NAME Custom)\" in toolchain\n    assert \"set(CMAKE_SYSTEM_VERSION 42)\" in toolchain\n    assert \"set(CMAKE_SYSTEM_PROCESSOR myarm)\" in toolchain\n\n\ndef test_find_builddirs():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Conan(ConanFile):\n\n            def package_info(self):\n                self.cpp_info.builddirs = [\"/path/to/builddir\"]\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=dep --version=1.0\")\n\n    conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.cmake import CMakeToolchain\n\n            class Conan(ConanFile):\n                settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n                requires = \"dep/1.0@\"\n\n                def generate(self):\n                    cmake = CMakeToolchain(self)\n                    cmake.generate()\n            \"\"\")\n\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"install . \")\n    with open(os.path.join(client.current_folder, \"conan_toolchain.cmake\")) as f:\n        contents = f.read()\n        assert \"/path/to/builddir\" in contents\n\n    conanfile = textwrap.dedent(\"\"\"\n       import os\n       from conan import ConanFile\n       from conan.tools.cmake import CMakeToolchain\n\n       class Conan(ConanFile):\n           name = \"mydep\"\n           version = \"1.0\"\n           settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n\n           def build_requirements(self):\n               self.test_requires(\"dep/1.0\")\n\n           def generate(self):\n               cmake = CMakeToolchain(self)\n               cmake.generate()\n       \"\"\")\n\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"install . \")\n    with open(os.path.join(client.current_folder, \"conan_toolchain.cmake\")) as f:\n        contents = f.read()\n        assert \"/path/to/builddir\" in contents\n\n\n@pytest.fixture\ndef lib_dir_setup():\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile().with_generator(\"CMakeToolchain\")})\n    client.run(\"create . --name=onelib --version=1.0\")\n    client.run(\"create . --name=twolib --version=1.0\")\n    conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class Conan(ConanFile):\n                requires = \"onelib/1.0\", \"twolib/1.0\"\n\n            \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=dep --version=1.0\")\n\n    conanfile = (GenConanfile().with_requires(\"dep/1.0\").with_generator(\"CMakeToolchain\")\n                 .with_settings(\"os\", \"arch\", \"compiler\", \"build_type\"))\n\n    client.save({\"conanfile.py\": conanfile})\n    return client\n\n\ndef test_runtime_lib_dirs_single_conf(lib_dir_setup):\n    client = lib_dir_setup\n    generator = \"\"\n    is_windows = platform.system() == \"Windows\"\n    if is_windows:\n        generator = '-c tools.cmake.cmaketoolchain:generator=Ninja'\n\n    client.run(f'install . -s build_type=Release {generator}')\n    contents = client.load(\"conan_toolchain.cmake\")\n    pattern_lib_path = r'list\\(PREPEND CMAKE_LIBRARY_PATH (.*)\\)'\n    pattern_lib_dirs = r'set\\(CONAN_RUNTIME_LIB_DIRS (.*) \\)'\n\n    # On *nix platforms: the list in `CMAKE_LIBRARY_PATH`\n    # is the same as `CONAN_RUNTIME_LIB_DIRS`\n    # On windows, it's the same but with `bin` instead of `lib`\n    cmake_library_path = re.search(pattern_lib_path, contents).group(1)\n    conan_runtime_lib_dirs = re.search(pattern_lib_dirs, contents).group(1)\n    lib_path = cmake_library_path.replace(\"/p/lib\", \"/p/bin\") if is_windows else cmake_library_path\n\n    assert lib_path == conan_runtime_lib_dirs\n\n\ndef test_runtime_lib_dirs_multiconf(lib_dir_setup):\n    client = lib_dir_setup\n    generator = \"\"\n    if platform.system() != \"Windows\":\n        generator = '-c tools.cmake.cmaketoolchain:generator=\"Ninja Multi-Config\"'\n\n    client.run(f'install . -s build_type=Release {generator}')\n    client.run(f'install . -s build_type=Debug {generator}')\n\n    contents = client.load(\"conan_toolchain.cmake\")\n    pattern_lib_dirs = r\"set\\(CONAN_RUNTIME_LIB_DIRS ([^)]*)\\)\"\n    runtime_lib_dirs = re.search(pattern_lib_dirs, contents).group(1)\n\n    assert \"<CONFIG:Release>\" in runtime_lib_dirs\n    assert \"<CONFIG:Debug>\" in runtime_lib_dirs\n\n\ndef test_disable_package_registry():\n    # https://github.com/conan-io/conan/issues/19749\n    client = TestClient(light=True)\n    client.save({\"conanfile.txt\": \"[generators]\\nCMakeToolchain\"})\n    client.run(\"install .\")\n    toolchain = client.load(\"conan_toolchain.cmake\")\n    before_output_dirs, output_dirs_block = toolchain.split(\"########## 'output_dirs' block #############\\n\", 1)\n    assert \"CMAKE_EXPORT_PACKAGE_REGISTRY\" not in before_output_dirs\n    assert \"cmake_policy(SET CMP0090 NEW)\" in output_dirs_block\n    assert \"set(CMAKE_EXPORT_PACKAGE_REGISTRY OFF)\" in toolchain\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only OSX\")\ndef test_cmaketoolchain_cmake_system_processor_cross_apple():\n    \"\"\"\n    https://github.com/conan-io/conan/pull/10434\n    CMAKE_SYSTEM_PROCESSOR was not set when cross-building in Mac\n    \"\"\"\n    client = TestClient()\n    client.save({\"hello.py\": GenConanfile().with_name(\"hello\")\n                                           .with_version(\"1.0\")\n                                           .with_settings(\"os\", \"arch\", \"compiler\", \"build_type\")})\n    profile_ios = textwrap.dedent(\"\"\"\n        include(default)\n        [settings]\n        os=iOS\n        os.version=15.4\n        os.sdk=iphoneos\n        os.sdk_version=15.0\n        arch=armv8\n    \"\"\")\n    client.save({\"profile_ios\": profile_ios})\n    client.run(\"install hello.py -pr:h=./profile_ios -pr:b=default -g CMakeToolchain\")\n    toolchain = client.load(\"conan_toolchain.cmake\")\n    assert \"set(CMAKE_SYSTEM_NAME iOS)\" in toolchain\n    assert \"set(CMAKE_SYSTEM_VERSION 21)\" in toolchain\n    assert \"set(CMAKE_SYSTEM_PROCESSOR arm64)\" in toolchain\n\n\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only OSX\")\ndef test_apple_vars_overwrite_user_conf():\n    \"\"\"\n        tools.cmake.cmaketoolchain:system_name and tools.cmake.cmaketoolchain:system_version\n        will be overwritten by the apple block\n    \"\"\"\n    client = TestClient()\n    client.save({\"hello.py\": GenConanfile().with_name(\"hello\")\n                                           .with_version(\"1.0\")\n                                           .with_settings(\"os\", \"arch\", \"compiler\", \"build_type\")})\n    profile_ios = textwrap.dedent(\"\"\"\n        include(default)\n        [settings]\n        os=iOS\n        os.version=15.4\n        os.sdk=iphoneos\n        os.sdk_version=15.0\n        arch=armv8\n    \"\"\")\n    client.save({\"profile_ios\": profile_ios})\n    client.run(\"install hello.py -pr:h=./profile_ios -pr:b=default -g CMakeToolchain \"\n               \"-c tools.cmake.cmaketoolchain:system_name=tvOS \"\n               \"-c tools.cmake.cmaketoolchain:system_version=15.1 \"\n               \"-c tools.cmake.cmaketoolchain:system_processor=x86_64 \")\n\n    toolchain = client.load(\"conan_toolchain.cmake\")\n\n    # should set the conf values but system/version are overwritten by the apple block\n    assert \"CMAKE_SYSTEM_NAME tvOS\" in toolchain\n    assert \"CMAKE_SYSTEM_NAME iOS\" not in toolchain\n    assert \"CMAKE_SYSTEM_VERSION 15.1\" in toolchain\n    assert \"CMAKE_SYSTEM_VERSION 15.0\" not in toolchain\n    assert \"CMAKE_SYSTEM_PROCESSOR x86_64\" in toolchain\n    assert \"CMAKE_SYSTEM_PROCESSOR armv8\" not in toolchain\n\n\ndef test_extra_flags_via_conf():\n    profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=Linux\n        compiler=gcc\n        compiler.version=6\n        compiler.libcxx=libstdc++11\n        arch=armv8\n        build_type=Release\n\n        [conf]\n        tools.build:cxxflags=[\"--flag1\", \"--flag2\"]\n        tools.build:cflags+=[\"--flag3\", \"--flag4\"]\n        tools.build:sharedlinkflags=+[\"--flag5\", \"--flag6\"]\n        tools.build:exelinkflags=[\"--flag7\", \"--flag8\"]\n        tools.build:defines=[\"D1\", \"D2\"]\n        \"\"\")\n\n    client = TestClient(path_with_spaces=False)\n\n    conanfile = GenConanfile().with_settings(\"os\", \"arch\", \"compiler\", \"build_type\")\\\n        .with_generator(\"CMakeToolchain\")\n    client.save({\"conanfile.py\": conanfile,\n                \"profile\": profile})\n    client.run(\"install . --profile:build=profile --profile:host=profile\")\n    toolchain = client.load(\"conan_toolchain.cmake\")\n    assert 'string(APPEND CONAN_CXX_FLAGS \" --flag1 --flag2\")' in toolchain\n    assert 'string(APPEND CONAN_C_FLAGS \" --flag3 --flag4\")' in toolchain\n    assert 'string(APPEND CONAN_SHARED_LINKER_FLAGS \" --flag5 --flag6\")' in toolchain\n    assert 'string(APPEND CONAN_EXE_LINKER_FLAGS \" --flag7 --flag8\")' in toolchain\n    assert 'add_compile_definitions( \"D1\" \"D2\")' in toolchain\n\n\ndef test_cmaketoolchain_rcflags():\n    \"\"\"Test that tools.build:rcflags is applied to CONAN_RC_FLAGS and CMAKE_RC_FLAGS_INIT\"\"\"\n    profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=Linux\n        arch=x86_64\n        compiler=gcc\n        compiler.version=6\n        compiler.libcxx=libstdc++11\n        build_type=Release\n\n        [conf]\n        tools.build:rcflags=[\"/nologo\", \"/flag-rc\"]\n        \"\"\")\n\n    client = TestClient()\n    conanfile = GenConanfile().with_settings(\"os\", \"arch\", \"compiler\", \"build_type\")\\\n        .with_generator(\"CMakeToolchain\")\n    client.save({\"conanfile.py\": conanfile, \"profile\": profile})\n    client.run(\"install . --profile:host=profile\")\n    toolchain = client.load(\"conan_toolchain.cmake\")\n    assert 'string(APPEND CONAN_RC_FLAGS \" /nologo /flag-rc\")' in toolchain\n    assert 'string(APPEND CMAKE_RC_FLAGS_INIT \" ${CONAN_RC_FLAGS}\")' in toolchain\n\n\ndef test_bitcode_enable_flag():\n    profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=Macos\n        arch=armv8\n        compiler=apple-clang\n        compiler.version=17\n        compiler.libcxx=libc++\n        build_type=Release\n\n        [conf]\n        tools.apple:enable_bitcode=True\n        \"\"\")\n\n    client = TestClient(path_with_spaces=False)\n\n    conanfile = GenConanfile().with_settings(\"os\", \"arch\", \"compiler\", \"build_type\") \\\n                              .with_generator(\"CMakeToolchain\")\n    client.save({\"conanfile.py\": conanfile,\n                 \"profile\": profile})\n    client.run(\"install . --profile:build=profile --profile:host=profile\")\n    toolchain = client.load(\"conan_toolchain.cmake\")\n    assert 'set(BITCODE \"-fembed-bitcode\")' in toolchain\n\n\ndef test_cmake_presets_binary_dir_available():\n    client = TestClient(path_with_spaces=False)\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    from conan.tools.cmake import cmake_layout\n    class HelloConan(ConanFile):\n        generators = \"CMakeToolchain\"\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n        def layout(self):\n            cmake_layout(self)\n\n    \"\"\")\n\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"install .\")\n    if platform.system() != \"Windows\":\n        build_dir = os.path.join(client.current_folder, \"build\", \"Release\")\n    else:\n        build_dir = os.path.join(client.current_folder, \"build\")\n\n    presets = load_cmake_presets(os.path.join(build_dir, \"generators\"))\n    assert presets[\"configurePresets\"][0][\"binaryDir\"] == build_dir\n\n\n@pytest.mark.parametrize(\"presets\", [\"CMakePresets.json\", \"CMakeUserPresets.json\"])\ndef test_cmake_presets_shared_preset(presets):\n    \"\"\"valid user preset file is created when multiple project presets inherit\n    from the same conan presets.\n    \"\"\"\n    client = TestClient()\n    project_presets = textwrap.dedent(\"\"\"\n    {\n        \"version\": 4,\n        \"cmakeMinimumRequired\": {\n            \"major\": 3,\n            \"minor\": 23,\n            \"patch\": 0\n        },\n        \"include\":[\"ConanPresets.json\"],\n        \"configurePresets\": [\n            {\n                \"name\": \"debug1\",\n                \"inherits\": [\"conan-debug\"]\n            },\n            {\n                \"name\": \"debug2\",\n                \"inherits\": [\"conan-debug\"]\n            },\n            {\n                \"name\": \"release1\",\n                \"inherits\": [\"conan-release\"]\n            },\n            {\n                \"name\": \"release2\",\n                \"inherits\": [\"conan-release\"]\n            }\n        ]\n    }\"\"\")\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    from conan.tools.cmake import cmake_layout, CMakeToolchain\n\n    class TestPresets(ConanFile):\n        generators = [\"CMakeDeps\"]\n        settings = \"build_type\"\n\n        def layout(self):\n            cmake_layout(self)\n\n        def generate(self):\n            tc = CMakeToolchain(self)\n            tc.user_presets_path = 'ConanPresets.json'\n            tc.generate()\n    \"\"\")\n\n    client.save({presets: project_presets,\n                 \"conanfile.py\": conanfile,\n                 \"CMakeLists.txt\": \"\"})  # File must exist for Conan to do Preset things.\n\n    client.run(\"install . -s build_type=Debug\")\n\n    conan_presets = json.loads(client.load(\"ConanPresets.json\"))\n    assert len(conan_presets[\"configurePresets\"]) == 1\n    assert conan_presets[\"configurePresets\"][0][\"name\"] == \"conan-release\"\n\n\ndef test_cmake_presets_multiconfig():\n    client = TestClient()\n    profile = textwrap.dedent(\"\"\"\n        [settings]\n        os = Windows\n        arch = x86_64\n        compiler=msvc\n        compiler.version=193\n        compiler.runtime=static\n        compiler.runtime_type=Release\n    \"\"\")\n    client.save({\"conanfile.py\": GenConanfile(\"mylib\", \"1.0\"), \"profile\": profile})\n    client.run(\"create . -s build_type=Release --profile:h=profile\")\n    client.run(\"create . -s build_type=Debug --profile:h=profile\")\n\n    client.run(\"install --requires=mylib/1.0@ -g CMakeToolchain \"\n               \"-s build_type=Release --profile:h=profile\")\n    presets = json.loads(client.load(\"CMakePresets.json\"))\n    assert len(presets[\"configurePresets\"]) == 1\n    assert len(presets[\"buildPresets\"]) == 1\n    assert presets[\"buildPresets\"][0][\"configuration\"] == \"Release\"\n    assert len(presets[\"testPresets\"]) == 1\n    assert presets[\"testPresets\"][0][\"configuration\"] == \"Release\"\n\n    client.run(\"install --requires=mylib/1.0@ -g CMakeToolchain \"\n               \"-s build_type=Debug --profile:h=profile\")\n    presets = json.loads(client.load(\"CMakePresets.json\"))\n    assert len(presets[\"configurePresets\"]) == 1\n    assert len(presets[\"buildPresets\"]) == 2\n    assert presets[\"buildPresets\"][0][\"configuration\"] == \"Release\"\n    assert presets[\"buildPresets\"][1][\"configuration\"] == \"Debug\"\n    assert len(presets[\"testPresets\"]) == 2\n    assert presets[\"testPresets\"][0][\"configuration\"] == \"Release\"\n    assert presets[\"testPresets\"][1][\"configuration\"] == \"Debug\"\n\n    client.run(\"install --requires=mylib/1.0@ -g CMakeToolchain \"\n               \"-s build_type=RelWithDebInfo --profile:h=profile\")\n    client.run(\"install --requires=mylib/1.0@ -g CMakeToolchain \"\n               \"-s build_type=MinSizeRel --profile:h=profile\")\n\n    presets = json.loads(client.load(\"CMakePresets.json\"))\n    assert len(presets[\"configurePresets\"]) == 1\n    assert len(presets[\"buildPresets\"]) == 4\n    assert presets[\"buildPresets\"][0][\"configuration\"] == \"Release\"\n    assert presets[\"buildPresets\"][1][\"configuration\"] == \"Debug\"\n    assert presets[\"buildPresets\"][2][\"configuration\"] == \"RelWithDebInfo\"\n    assert presets[\"buildPresets\"][3][\"configuration\"] == \"MinSizeRel\"\n    assert len(presets[\"testPresets\"]) == 4\n    assert presets[\"testPresets\"][0][\"configuration\"] == \"Release\"\n    assert presets[\"testPresets\"][1][\"configuration\"] == \"Debug\"\n    assert presets[\"testPresets\"][2][\"configuration\"] == \"RelWithDebInfo\"\n    assert presets[\"testPresets\"][3][\"configuration\"] == \"MinSizeRel\"\n\n    # Repeat one\n    client.run(\"install --requires=mylib/1.0@ -g CMakeToolchain \"\n               \"-s build_type=Debug --profile:h=profile\")\n    client.run(\"install --requires=mylib/1.0@ -g CMakeToolchain \"\n               \"-s build_type=Debug --profile:h=profile\")\n    presets = json.loads(client.load(\"CMakePresets.json\"))\n    assert len(presets[\"configurePresets\"]) == 1\n    assert len(presets[\"buildPresets\"]) == 4\n    assert presets[\"buildPresets\"][0][\"configuration\"] == \"Release\"\n    assert presets[\"buildPresets\"][1][\"configuration\"] == \"Debug\"\n    assert presets[\"buildPresets\"][2][\"configuration\"] == \"RelWithDebInfo\"\n    assert presets[\"buildPresets\"][3][\"configuration\"] == \"MinSizeRel\"\n\n    assert len(presets[\"testPresets\"]) == 4\n    assert presets[\"testPresets\"][0][\"configuration\"] == \"Release\"\n    assert presets[\"testPresets\"][1][\"configuration\"] == \"Debug\"\n    assert presets[\"testPresets\"][2][\"configuration\"] == \"RelWithDebInfo\"\n    assert presets[\"testPresets\"][3][\"configuration\"] == \"MinSizeRel\"\n\n    assert len(presets[\"configurePresets\"]) == 1\n    assert presets[\"configurePresets\"][0][\"name\"] == \"conan-default\"\n\n\ndef test_cmake_presets_singleconfig():\n    \"\"\" without defining a layout, single config always overwrites\n    the existing CMakePresets.json\n    \"\"\"\n    client = TestClient()\n    profile = textwrap.dedent(\"\"\"\n        [settings]\n        os = Linux\n        arch = x86_64\n        compiler=gcc\n        compiler.version=8\n    \"\"\")\n    client.save({\"conanfile.py\": GenConanfile(\"mylib\", \"1.0\"), \"profile\": profile})\n    client.run(\"create . -s build_type=Release --profile:h=profile\")\n    client.run(\"create . -s build_type=Debug --profile:h=profile\")\n\n    client.run(\"install --requires=mylib/1.0@ \"\n               \"-g CMakeToolchain -s build_type=Release --profile:h=profile\")\n    presets = json.loads(client.load(\"CMakePresets.json\"))\n    assert len(presets[\"configurePresets\"]) == 1\n    assert presets[\"configurePresets\"][0][\"name\"] == \"conan-release\"\n\n    assert len(presets[\"buildPresets\"]) == 1\n    assert presets[\"buildPresets\"][0][\"configurePreset\"] == \"conan-release\"\n\n    assert len(presets[\"testPresets\"]) == 1\n    assert presets[\"testPresets\"][0][\"configurePreset\"] == \"conan-release\"\n\n    # This overwrites the existing profile, as there is no layout\n    client.run(\"install --requires=mylib/1.0@ \"\n               \"-g CMakeToolchain -s build_type=Debug --profile:h=profile\")\n\n    presets = json.loads(client.load(\"CMakePresets.json\"))\n    assert len(presets[\"configurePresets\"]) == 1\n    assert presets[\"configurePresets\"][0][\"name\"] == \"conan-debug\"\n\n    assert len(presets[\"buildPresets\"]) == 1\n    assert presets[\"buildPresets\"][0][\"configurePreset\"] == \"conan-debug\"\n\n    assert len(presets[\"testPresets\"]) == 1\n    assert presets[\"testPresets\"][0][\"configurePreset\"] == \"conan-debug\"\n\n    # Repeat configuration, it shouldn't add a new one\n    client.run(\"install --requires=mylib/1.0@ \"\n               \"-g CMakeToolchain -s build_type=Debug --profile:h=profile\")\n    presets = json.loads(client.load(\"CMakePresets.json\"))\n    assert len(presets[\"configurePresets\"]) == 1\n\n\ndef test_toolchain_cache_variables():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMakeToolchain\n\n        class Conan(ConanFile):\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            options = {\"enable_foobar\": [True, False], \"qux\": [\"ANY\"], \"number\": [1,2]}\n            default_options = {\"enable_foobar\": True, \"qux\": \"baz\", \"number\": 1}\n\n            def generate(self):\n                toolchain = CMakeToolchain(self)\n                toolchain.cache_variables[\"foo\"] = True\n                toolchain.cache_variables[\"foo2\"] = False\n                toolchain.cache_variables[\"var\"] = \"23\"\n                toolchain.cache_variables[\"ENABLE_FOOBAR\"] = self.options.enable_foobar\n                toolchain.cache_variables[\"QUX\"] = self.options.qux\n                toolchain.cache_variables[\"NUMBER\"] = self.options.number\n                toolchain.cache_variables[\"CMAKE_SH\"] = \"THIS VALUE HAS PRIORITY\"\n                toolchain.cache_variables[\"CMAKE_POLICY_DEFAULT_CMP0091\"] = \"THIS VALUE HAS PRIORITY\"\n                toolchain.cache_variables[\"CMAKE_MAKE_PROGRAM\"] = \"THIS VALUE HAS NO PRIORITY\"\n                toolchain.generate()\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    with mock.patch(\"platform.system\", mock.MagicMock(return_value=\"Windows\")):\n        client.run(\"install . --name=mylib --version=1.0 \"\n                   \"-c tools.cmake.cmaketoolchain:generator='MinGW Makefiles' \"\n                   \"-c tools.gnu:make_program='MyMake' -c tools.build:skip_test=True\")\n\n    presets = json.loads(client.load(\"CMakePresets.json\"))\n    cache_variables = presets[\"configurePresets\"][0][\"cacheVariables\"]\n    assert cache_variables[\"foo\"] == 'ON'\n    assert cache_variables[\"foo2\"] == 'OFF'\n    assert cache_variables[\"var\"] == '23'\n    assert cache_variables[\"CMAKE_SH\"] == \"THIS VALUE HAS PRIORITY\"\n    assert cache_variables[\"CMAKE_POLICY_DEFAULT_CMP0091\"] == \"THIS VALUE HAS PRIORITY\"\n    assert cache_variables[\"CMAKE_MAKE_PROGRAM\"] == \"MyMake\"\n    assert cache_variables[\"BUILD_TESTING\"] == 'OFF'\n    assert cache_variables[\"ENABLE_FOOBAR\"] == 'ON'\n    assert cache_variables[\"QUX\"] == 'baz'\n    assert cache_variables[\"NUMBER\"] == 1\n\n    def _format_val(val):\n        return f'\"{val}\"' if isinstance(val, str) and \" \" in val else f\"{val}\"\n\n    for var, value in cache_variables.items():\n        assert f\"-D{var}={_format_val(value)}\" in client.out\n    assert \"-DCMAKE_TOOLCHAIN_FILE=\" in client.out\n    assert f\"-G {_format_val('MinGW Makefiles')}\" in client.out\n\n    client.run(\"install . --name=mylib --version=1.0 -c tools.gnu:make_program='MyMake'\")\n    presets = json.loads(client.load(\"CMakePresets.json\"))\n    cache_variables = presets[\"configurePresets\"][0][\"cacheVariables\"]\n    assert cache_variables[\"CMAKE_MAKE_PROGRAM\"] == \"MyMake\"\n\n\ndef test_variables_types():\n    # https://github.com/conan-io/conan/pull/10941\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMakeToolchain\n\n        class Conan(ConanFile):\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            def generate(self):\n                toolchain = CMakeToolchain(self)\n                toolchain.variables[\"FOO\"] = True\n                toolchain.generate()\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"install . --name=mylib --version=1.0\")\n\n    toolchain = client.load(\"conan_toolchain.cmake\")\n    assert 'set(FOO ON CACHE BOOL \"Variable FOO conan-toolchain defined\")' in toolchain\n\n\ndef test_variables_escaping():\n    # https://github.com/conan-io/conan/issues/19638\n    client = TestClient()\n    # NOTE: Users need to do explicit escaping\n    conanfile = textwrap.dedent(r\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMakeToolchain\n\n        class Conan(ConanFile):\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            def generate(self):\n                toolchain = CMakeToolchain(self)\n                toolchain.variables[\"FOO\"] = r\"D:\\new\\thing\\path\".replace(\"\\\\\", \"\\\\\\\\\")\n                toolchain.variables[\"CMAKE_Fortran_FLAGS_INIT\"] = \"${CMAKE_C_FLAGS_INIT}\"\n                toolchain.variables.release[\"BAR\"] = r\"C:\\new\\thing\\path\".replace(\"\\\\\", \"\\\\\\\\\")\n                toolchain.generate()\n        \"\"\")\n\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"install .\")\n\n    toolchain = client.load(\"conan_toolchain.cmake\")\n    assert 'set(CMAKE_Fortran_FLAGS_INIT \"${CMAKE_C_FLAGS_INIT}\"' in toolchain\n    assert r'set(FOO \"D:\\\\new\\\\thing\\\\path\" CACHE STRING' in toolchain\n    assert r'set(CONAN_DEF_releaseBAR \"C:\\\\new\\\\thing\\\\path\")' in toolchain\n\n\ndef test_android_c_library():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Conan(ConanFile):\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            generators = \"CMakeToolchain\"\n\n            def configure(self):\n                if self.settings.compiler != \"msvc\":\n                    del self.settings.compiler.libcxx\n\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    # Settings\n    settings = \"-s arch=x86_64 -s os=Android -s os.api_level=23 -c tools.android:ndk_path=/foo\"\n    # Checking the Android variables created\n    # Issue: https://github.com/conan-io/conan/issues/11798\n    client.run(\"install . \" + settings)\n    conan_toolchain = client.load(os.path.join(client.current_folder, \"conan_toolchain.cmake\"))\n    assert \"set(ANDROID_PLATFORM android-23)\" in conan_toolchain\n    assert \"set(ANDROID_ABI x86_64)\" in conan_toolchain\n    assert 'include(\"/foo/build/cmake/android.toolchain.cmake\")' in conan_toolchain\n    client.run(\"create . --name=foo --version=1.0 \" + settings)\n\n\n@pytest.mark.parametrize(\"cmake_legacy_toolchain\", [True, False, None])\ndef test_android_legacy_toolchain_flag(cmake_legacy_toolchain):\n    client = TestClient()\n    conanfile = GenConanfile().with_settings(\"os\", \"arch\")\\\n        .with_generator(\"CMakeToolchain\")\n    client.save({\"conanfile.py\": conanfile})\n    settings = \"-s arch=x86_64 -s os=Android -s os.api_level=23 -c tools.android:ndk_path=/foo\"\n    expected = None\n    if cmake_legacy_toolchain is not None:\n        settings += f\" -c tools.android:cmake_legacy_toolchain={cmake_legacy_toolchain}\"\n        expected = \"ON\" if cmake_legacy_toolchain else \"OFF\"\n    client.run(\"install . \" + settings)\n    conan_toolchain = client.load(os.path.join(client.current_folder, \"conan_toolchain.cmake\"))\n    if cmake_legacy_toolchain is not None:\n        assert f\"set(ANDROID_USE_LEGACY_TOOLCHAIN_FILE {expected})\" in conan_toolchain\n    else:\n        assert \"ANDROID_USE_LEGACY_TOOLCHAIN_FILE\" not in conan_toolchain\n\n\n@pytest.mark.parametrize(\"cmake_legacy_toolchain\", [True, False, None])\ndef test_android_legacy_toolchain_with_compileflags(cmake_legacy_toolchain):\n    # https://github.com/conan-io/conan/issues/13374\n    client = TestClient()\n    conanfile = GenConanfile().with_settings(\"os\", \"arch\")\\\n        .with_generator(\"CMakeToolchain\")\n    profile = textwrap.dedent(\"\"\"\n    [settings]\n    os=Android\n    os.api_level=23\n    arch=armv8\n\n    [conf]\n    tools.android:ndk_path=/foo\n    tools.build:cflags=[\"-foobar\"]\n    tools.build:cxxflags=[\"-barfoo\"]\n    \"\"\")\n    if cmake_legacy_toolchain is not None:\n        profile += f\"\\ntools.android:cmake_legacy_toolchain={cmake_legacy_toolchain}\"\n\n    client.save({\"conanfile.py\": conanfile, \"profile_host\": profile})\n    client.run(\"install . -pr profile_host\")\n    warning_text = \"Consider setting tools.android:cmake_legacy_toolchain to False\"\n    if cmake_legacy_toolchain is not False:\n        assert warning_text in client.out\n    else:\n        assert warning_text not in client.out\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Only Windows\")\ndef test_presets_paths_normalization():\n    # https://github.com/conan-io/conan/issues/11795\n    # But then also https://github.com/conan-io/conan/issues/18434\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import cmake_layout\n\n        class Conan(ConanFile):\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            generators = \"CMakeToolchain\"\n\n            def layout(self):\n                cmake_layout(self)\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile, \"CMakeLists.txt\": \"foo\"})\n    client.run(\"install .\")\n\n    presets = json.loads(client.load(\"CMakeUserPresets.json\"))\n    assert \"/\" in presets[\"include\"][0]\n    assert \"\\\\\" not in presets[\"include\"][0]\n\n\n@pytest.mark.parametrize(\"arch, arch_toolset\", [(\"x86\", \"x86_64\"), (\"x86_64\", \"x86_64\"),\n                                                (\"x86\", \"x86\"), (\"x86_64\", \"x86\")])\ndef test_presets_ninja_msvc(arch, arch_toolset):\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.cmake import cmake_layout\n\n            class Conan(ConanFile):\n                settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n                generators = \"CMakeToolchain\"\n\n                def layout(self):\n                    cmake_layout(self)\n            \"\"\")\n    client.save({\"conanfile.py\": conanfile, \"CMakeLists.txt\": \"foo\"})\n    configs = [\"-c tools.cmake.cmaketoolchain:toolset_arch={}\".format(arch_toolset),\n               \"-c tools.cmake.cmake_layout:build_folder_vars='[\\\"settings.compiler.cppstd\\\"]'\",\n               \"-c tools.cmake.cmaketoolchain:generator=Ninja\"]\n    msvc = \" -s compiler=msvc -s compiler.version=191 -s compiler.runtime=static \" \\\n           \"-s compiler.runtime_type=Release\"\n    client.run(\"install . {} -s compiler.cppstd=14 {} -s arch={}\".format(\" \".join(configs), msvc, arch))\n\n    presets = json.loads(client.load(\"build/14/Release/generators/CMakePresets.json\"))\n\n    toolset_value = {\"x86_64\": \"v141,host=x86_64\", \"x86\": \"v141,host=x86\"}.get(arch_toolset)\n    arch_value = {\"x86_64\": \"x64\", \"x86\": \"x86\"}.get(arch)\n    assert presets[\"configurePresets\"][0][\"architecture\"][\"value\"] == arch_value\n    assert presets[\"configurePresets\"][0][\"architecture\"][\"strategy\"] == \"external\"\n    assert presets[\"configurePresets\"][0][\"toolset\"][\"value\"] == toolset_value\n    assert presets[\"configurePresets\"][0][\"toolset\"][\"strategy\"] == \"external\"\n\n    # Only for Ninja, no ninja, no values\n    rmdir(os.path.join(client.current_folder, \"build\"))\n    configs = [\"-c tools.cmake.cmaketoolchain:toolset_arch={}\".format(arch_toolset),\n               \"-c tools.cmake.cmake_layout:build_folder_vars='[\\\"settings.compiler.cppstd\\\"]'\"]\n    client.run(\n        \"install . {} -s compiler.cppstd=14 {} -s arch={}\".format(\" \".join(configs), msvc, arch))\n\n    toolset_value = {\"x86_64\": \"v141,host=x86_64\", \"x86\": \"v141,host=x86\"}.get(arch_toolset)\n    arch_value = {\"x86_64\": \"x64\", \"x86\": \"Win32\"}.get(arch)  # NOTE: Win32 is different!!\n    presets = json.loads(client.load(\"build/14/generators/CMakePresets.json\"))\n    assert presets[\"configurePresets\"][0][\"architecture\"][\"value\"] == arch_value\n    assert presets[\"configurePresets\"][0][\"architecture\"][\"strategy\"] == \"external\"\n    assert presets[\"configurePresets\"][0][\"toolset\"][\"value\"] == toolset_value\n    assert presets[\"configurePresets\"][0][\"toolset\"][\"strategy\"] == \"external\"\n\n    rmdir(os.path.join(client.current_folder, \"build\"))\n    configs = [\"-c tools.cmake.cmake_layout:build_folder_vars='[\\\"settings.compiler.cppstd\\\"]'\",\n               \"-c tools.cmake.cmaketoolchain:generator=Ninja\"]\n\n    client.run(\n        \"install . {} -s compiler.cppstd=14 {} -s arch={}\".format(\" \".join(configs), msvc, arch))\n    presets = json.loads(client.load(\"build/14/Release/generators/CMakePresets.json\"))\n    toolset_value = {\"x86_64\": \"v141\", \"x86\": \"v141\"}.get(arch_toolset)\n    arch_value = {\"x86_64\": \"x64\", \"x86\": \"x86\"}.get(arch)\n    assert presets[\"configurePresets\"][0][\"architecture\"][\"value\"] == arch_value\n    assert presets[\"configurePresets\"][0][\"architecture\"][\"strategy\"] == \"external\"\n    assert presets[\"configurePresets\"][0][\"toolset\"][\"value\"] == toolset_value\n    assert presets[\"configurePresets\"][0][\"toolset\"][\"strategy\"] == \"external\"\n\n\ndef test_pkg_config_block():\n    os_ = platform.system()\n    os_ = \"Macos\" if os_ == \"Darwin\" else os_\n    profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=%s\n        arch=x86_64\n\n        [conf]\n        tools.gnu:pkg_config=/usr/local/bin/pkg-config\n        \"\"\" % os_)\n\n    client = TestClient(path_with_spaces=False)\n    conanfile = GenConanfile().with_settings(\"os\", \"arch\")\\\n        .with_generator(\"CMakeToolchain\")\n    client.save({\"conanfile.py\": conanfile,\n                \"profile\": profile})\n    client.run(\"install . -pr:b profile -pr:h profile\")\n    toolchain = client.load(\"conan_toolchain.cmake\")\n    assert 'set(PKG_CONFIG_EXECUTABLE /usr/local/bin/pkg-config CACHE FILEPATH ' in toolchain\n    pathsep = \":\" if os_ != \"Windows\" else \";\"\n    pkg_config_path_set = 'set(ENV{PKG_CONFIG_PATH} \"%s$ENV{PKG_CONFIG_PATH}\")' % \\\n                          (\"${CMAKE_CURRENT_LIST_DIR}\" + pathsep)\n    assert pkg_config_path_set in toolchain\n\n\n@pytest.mark.parametrize(\"path\", [\"subproject\", False])\ndef test_user_presets_custom_location(path):\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n                import os\n                from conan import ConanFile\n                from conan.tools.cmake import cmake_layout, CMakeToolchain\n\n                class Conan(ConanFile):\n                    settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n\n                    def generate(self):\n                        t = CMakeToolchain(self)\n                        t.user_presets_path = {}\n                        t.generate()\n\n                    def layout(self):\n                        cmake_layout(self)\n                \"\"\".format('\"{}\"'.format(path) if isinstance(path, str) else path))\n    client.save({\"CMakeLists.txt\": \"\",\n                 \"subproject/CMakeLists.txt\": \"\",\n                 \"subproject2/foo.txt\": \"\",\n                 \"conanfile.py\": conanfile})\n\n    # We want to generate it to build the subproject\n    client.run(\"install . \")\n\n    if path is not False:\n        assert not os.path.exists(os.path.join(client.current_folder, \"CMakeUserPresets.json\"))\n        assert os.path.exists(os.path.join(client.current_folder, \"subproject\", \"CMakeUserPresets.json\"))\n    else:\n        assert not os.path.exists(os.path.join(client.current_folder, \"CMakeUserPresets.json\"))\n        assert not os.path.exists(os.path.join(client.current_folder, \"False\", \"CMakeUserPresets.json\"))\n\n\ndef test_set_cmake_lang_compilers_and_launchers():\n    profile = textwrap.dedent(r\"\"\"\n    [settings]\n    os=Windows\n    arch=x86_64\n    compiler=clang\n    compiler.version=15\n    compiler.libcxx=libstdc++11\n    [conf]\n    tools.build:compiler_executables={\"c\": \"/my/local/gcc\", \"cpp\": \"g++\", \"rc\": \"C:\\\\local\\\\rc.exe\"}\n    \"\"\")\n    client = TestClient(path_with_spaces=False)\n    conanfile = GenConanfile().with_settings(\"os\", \"arch\", \"compiler\")\\\n        .with_generator(\"CMakeToolchain\")\n    client.save({\"conanfile.py\": conanfile,\n                \"profile\": profile})\n    client.run(\"install . -pr:b profile -pr:h profile\")\n    toolchain = client.load(\"conan_toolchain.cmake\")\n    assert 'set(CMAKE_C_COMPILER clang)' not in toolchain\n    assert 'set(CMAKE_CXX_COMPILER clang++)' not in toolchain\n    assert 'set(CMAKE_C_COMPILER \"/my/local/gcc\")' in toolchain\n    assert 'set(CMAKE_CXX_COMPILER \"g++\")' in toolchain\n    assert 'set(CMAKE_RC_COMPILER \"C:/local/rc.exe\")' in toolchain\n\n\ndef test_cmake_layout_toolchain_folder():\n    \"\"\" in single-config generators, the toolchain is a different file per configuration\n    https://github.com/conan-io/conan/issues/12827\n    \"\"\"\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import cmake_layout\n\n        class Conan(ConanFile):\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            generators = \"CMakeToolchain\"\n\n            def layout(self):\n                cmake_layout(self)\n            \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"install . -s os=Linux -s compiler=gcc -s compiler.version=7 -s build_type=Release \"\n          \"-s compiler.libcxx=libstdc++11\")\n    assert os.path.exists(os.path.join(c.current_folder,\n                                       \"build/Release/generators/conan_toolchain.cmake\"))\n    c.run(\"install . -s os=Linux -s compiler=gcc -s compiler.version=7 -s build_type=Debug \"\n          \"-s compiler.libcxx=libstdc++11\")\n    assert os.path.exists(os.path.join(c.current_folder,\n                                       \"build/Debug/generators/conan_toolchain.cmake\"))\n    c.run(\"install . -s os=Linux -s compiler=gcc -s compiler.version=7 -s build_type=Debug \"\n          \"-s compiler.libcxx=libstdc++11 -s arch=x86 \"\n          \"-c tools.cmake.cmake_layout:build_folder_vars='[\\\"settings.arch\\\", \\\"settings.build_type\\\"]'\")\n    assert os.path.exists(os.path.join(c.current_folder,\n                                       \"build/x86-debug/generators/conan_toolchain.cmake\"))\n    c.run(\"install . -s os=Linux -s compiler=gcc -s compiler.version=7 -s build_type=Debug \"\n          \"-s compiler.libcxx=libstdc++11 -s arch=x86 \"\n          \"-c tools.cmake.cmake_layout:build_folder_vars='[\\\"settings.os\\\"]'\")\n    assert os.path.exists(os.path.join(c.current_folder,\n                                       \"build/linux/Debug/generators/conan_toolchain.cmake\"))\n\n\ndef test_build_folder_vars_editables():\n    \"\"\" when packages are in editable, they must also follow the build_folder_vars\n    https://github.com/conan-io/conan/issues/13485\n    \"\"\"\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import cmake_layout\n\n        class Conan(ConanFile):\n            name = \"dep\"\n            version = \"0.1\"\n            settings = \"os\", \"build_type\"\n            generators = \"CMakeToolchain\"\n\n            def layout(self):\n                cmake_layout(self)\n        \"\"\")\n    c.save({\"dep/conanfile.py\": conanfile,\n            \"app/conanfile.py\": GenConanfile().with_requires(\"dep/0.1\")})\n    c.run(\"editable add dep\")\n    conf = \"tools.cmake.cmake_layout:build_folder_vars='[\\\"settings.os\\\", \\\"settings.build_type\\\"]'\"\n    settings = \" -s os=FreeBSD -s arch=armv8 -s build_type=Debug\"\n    c.run(\"install app -c={} {} --build=editable\".format(conf, settings))\n    assert os.path.exists(os.path.join(c.current_folder, \"dep\", \"build\", \"freebsd-debug\"))\n\n\ndef test_set_linker_scripts():\n    profile = textwrap.dedent(r\"\"\"\n    [settings]\n    os=Windows\n    arch=x86_64\n    compiler=clang\n    compiler.version=15\n    compiler.libcxx=libstdc++11\n    [conf]\n    tools.build:linker_scripts=[\"/usr/local/src/flash.ld\", \"C:\\\\local\\\\extra_data.ld\"]\n    \"\"\")\n    client = TestClient(path_with_spaces=False)\n    conanfile = GenConanfile().with_settings(\"os\", \"arch\", \"compiler\")\\\n        .with_generator(\"CMakeToolchain\")\n    client.save({\"conanfile.py\": conanfile,\n                \"profile\": profile})\n    client.run(\"install . -pr:b profile -pr:h profile\")\n    toolchain = client.load(\"conan_toolchain.cmake\")\n    assert 'string(APPEND CONAN_EXE_LINKER_FLAGS ' \\\n           r'\" -T\\\"/usr/local/src/flash.ld\\\" -T\\\"C:/local/extra_data.ld\\\"\")' in toolchain\n\n\ndef test_test_package_layout():\n    \"\"\"\n    test that the ``test_package`` folder also follows the cmake_layout and the\n    build_folder_vars\n    \"\"\"\n    client = TestClient()\n    test_conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import cmake_layout\n\n        class Conan(ConanFile):\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            generators = \"CMakeToolchain\"\n\n            def requirements(self):\n                self.requires(self.tested_reference_str)\n\n            def layout(self):\n                cmake_layout(self)\n\n            def test(self):\n                pass\n    \"\"\")\n    client.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\"),\n                 \"test_package/conanfile.py\": test_conanfile})\n    config = \"-c tools.cmake.cmake_layout:build_folder_vars='[\\\"settings.compiler.cppstd\\\"]'\"\n    client.run(f\"create . {config} -s compiler.cppstd=14\")\n    build_folder = client.created_test_build_folder(\"pkg/0.1\")\n    assert os.path.exists(os.path.join(client.current_folder, \"test_package\", build_folder))\n    client.run(f\"create . {config} -s compiler.cppstd=17\")\n    build_folder2 = client.created_test_build_folder(\"pkg/0.1\")\n    assert os.path.exists(os.path.join(client.current_folder, \"test_package\", build_folder2))\n    assert build_folder != build_folder2\n\n\ndef test_presets_not_found_error_msg():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMake\n\n        class Conan(ConanFile):\n            settings = \"build_type\"\n\n            def build(self):\n                CMake(self).configure()\n    \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"build .\", assert_error=True)\n    assert \"CMakePresets.json was not found\" in client.out\n    assert \"Check that you are using CMakeToolchain as generator \" \\\n           \"to ensure its correct initialization.\" in client.out\n\n\ndef test_recipe_build_folders_vars():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import cmake_layout\n\n        class Conan(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            settings = \"os\", \"arch\", \"build_type\"\n            options = {\"shared\": [True, False]}\n            generators = \"CMakeToolchain\"\n\n            def layout(self):\n                self.folders.build_folder_vars = [\"settings.os\", \"options.shared\"]\n                cmake_layout(self)\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"install . -s os=Windows -s arch=armv8 -s build_type=Debug -o shared=True\")\n    presets = client.load(\"build/windows-shared/Debug/generators/CMakePresets.json\")\n    assert \"conan-windows-shared-debug\" in presets\n    client.run(\"install . -s os=Linux -s arch=x86 -s build_type=Release -o shared=False\")\n    presets = client.load(\"build/linux-static/Release/generators/CMakePresets.json\")\n    assert \"linux-static-release\" in presets\n\n    # CLI override has priority\n    client.run(\"install . -s os=Linux -s arch=x86 -s build_type=Release -o shared=False \"\n               \"-c tools.cmake.cmake_layout:build_folder_vars='[\\\"settings.os\\\"]'\")\n    presets = client.load(\"build/linux/Release/generators/CMakePresets.json\")\n    assert \"conan-linux-release\" in presets\n\n    # Now we do the build in the cache, the recipe folders are still used\n    client.run(\"create . -s os=Windows -s arch=armv8 -s build_type=Debug -o shared=True\")\n    build_folder = client.created_layout().build()\n    presets = load(os.path.join(build_folder,\n                                \"build/windows-shared/Debug/generators/CMakePresets.json\"))\n    assert \"conan-windows-shared-debug\" in presets\n\n    # If we change the conf ``build_folder_vars``, it doesn't affect the cache build\n    client.run(\"create . -s os=Windows -s arch=armv8 -s build_type=Debug -o shared=True \"\n               \"-c tools.cmake.cmake_layout:build_folder_vars='[\\\"settings.os\\\"]'\")\n    build_folder = client.created_layout().build()\n    presets = load(os.path.join(build_folder,\n                                \"build/windows-shared/Debug/generators/CMakePresets.json\"))\n    assert \"conan-windows-shared-debug\" in presets\n\n\ndef test_build_folder_vars_self_name_version():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import cmake_layout\n\n        class Conan(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            settings = \"os\", \"build_type\"\n            generators = \"CMakeToolchain\"\n\n            def layout(self):\n                self.folders.build_folder_vars = [\"settings.os\", \"self.name\", \"self.version\"]\n                cmake_layout(self)\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"install . -s os=Windows -s build_type=Debug\")\n    presets = client.load(\"build/windows-pkg-0.1/Debug/generators/CMakePresets.json\")\n    assert \"conan-windows-pkg-0.1-debug\" in presets\n    client.run(\"install . -s os=Linux -s build_type=Release\")\n    presets = client.load(\"build/linux-pkg-0.1/Release/generators/CMakePresets.json\")\n    assert \"linux-pkg-0.1-release\" in presets\n\n    # CLI override has priority\n    client.run(\"install . -s os=Linux  -s build_type=Release \"\n               \"-c tools.cmake.cmake_layout:build_folder_vars='[\\\"self.name\\\"]'\")\n    presets = client.load(\"build/pkg/Release/generators/CMakePresets.json\")\n    assert \"conan-pkg-release\" in presets\n\n    # Now we do the build in the cache, the recipe folders are still used\n    client.run(\"create . -s os=Windows -s build_type=Debug\")\n    build_folder = client.created_layout().build()\n    presets = load(os.path.join(build_folder,\n                                \"build/windows-pkg-0.1/Debug/generators/CMakePresets.json\"))\n    assert \"conan-windows-pkg-0.1-debug\" in presets\n\n    # If we change the conf ``build_folder_vars``, it doesn't affect the cache build\n    client.run(\"create . -s os=Windows -s build_type=Debug \"\n               \"-c tools.cmake.cmake_layout:build_folder_vars='[\\\"settings.os\\\"]'\")\n    build_folder = client.created_layout().build()\n    presets = load(os.path.join(build_folder,\n                                \"build/windows-pkg-0.1/Debug/generators/CMakePresets.json\"))\n    assert \"conan-windows-pkg-0.1-debug\" in presets\n\n\ndef test_build_folder_vars_constants_user():\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import cmake_layout\n\n        class Conan(ConanFile):\n            name = \"dep\"\n            version = \"0.1\"\n            settings = \"os\", \"build_type\"\n            generators = \"CMakeToolchain\"\n\n            def layout(self):\n                cmake_layout(self)\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    conf = \"tools.cmake.cmake_layout:build_folder_vars='[\\\"const.myvalue\\\"]'\"\n    settings = \" -s os=FreeBSD -s arch=armv8 -s build_type=Debug\"\n    c.run(\"install . -c={} {}\".format(conf, settings))\n    assert \"cmake --preset conan-myvalue-debug\" in c.out\n    assert os.path.exists(os.path.join(c.current_folder, \"build\", \"myvalue\", \"Debug\"))\n    presets = load(os.path.join(c.current_folder,\n                                \"build/myvalue/Debug/generators/CMakePresets.json\"))\n    assert \"conan-myvalue-debug\" in presets\n\n\ndef test_extra_flags():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMakeToolchain\n\n        class Conan(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            settings = \"os\", \"arch\", \"build_type\"\n            def generate(self):\n                tc = CMakeToolchain(self)\n                tc.extra_cxxflags = [\"extra_cxxflags\"]\n                tc.extra_cflags = [\"extra_cflags\"]\n                tc.extra_sharedlinkflags = [\"extra_sharedlinkflags\"]\n                tc.extra_exelinkflags = [\"extra_exelinkflags\"]\n                tc.generate()\n        \"\"\")\n    profile = textwrap.dedent(\"\"\"\n        include(default)\n        [conf]\n        tools.build:cxxflags+=['cxxflags']\n        tools.build:cflags+=['cflags']\n        tools.build:sharedlinkflags+=['sharedlinkflags']\n        tools.build:exelinkflags+=['exelinkflags']\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile, \"profile\": profile})\n    client.run('install . -pr=./profile')\n    toolchain = client.load(\"conan_toolchain.cmake\")\n\n    assert 'string(APPEND CONAN_CXX_FLAGS \" extra_cxxflags cxxflags\")' in toolchain\n    assert 'string(APPEND CONAN_C_FLAGS \" extra_cflags cflags\")' in toolchain\n    assert 'string(APPEND CONAN_SHARED_LINKER_FLAGS \" extra_sharedlinkflags sharedlinkflags\")' in toolchain\n    assert 'string(APPEND CONAN_EXE_LINKER_FLAGS \" extra_exelinkflags exelinkflags\")' in toolchain\n\n\ndef test_avoid_ovewrite_user_cmakepresets():\n    # https://github.com/conan-io/conan/issues/15052\n    c = TestClient()\n    c.save({\"conanfile.txt\": \"\",\n            \"CMakePresets.json\": \"{}\"})\n    c.run('install . -g CMakeToolchain', assert_error=True)\n    assert \"Error in generator 'CMakeToolchain': Existing CMakePresets.json not generated\" in c.out\n    assert \"Use --output-folder or define a 'layout' to avoid collision\" in c.out\n\n\ndef test_presets_njobs():\n    c = TestClient()\n    c.save({\"conanfile.txt\": \"\"})\n    c.run('install . -g CMakeToolchain -c tools.build:jobs=42')\n    presets = json.loads(c.load(\"CMakePresets.json\"))\n    assert presets[\"buildPresets\"][0][\"jobs\"] == 42\n    assert presets[\"testPresets\"][0][\"execution\"][\"jobs\"] == 42\n    c.run('install . -g CMakeToolchain -c tools.build:jobs=0')\n    presets = json.loads(c.load(\"CMakePresets.json\"))\n    assert \"jobs\" not in presets[\"buildPresets\"][0]\n    assert \"execution\" not in presets[\"testPresets\"][0]\n\n\ndef test_add_cmakeexe_to_presets():\n    c = TestClient()\n\n    tool = textwrap.dedent(r\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import chdir, save\n        class Tool(ConanFile):\n            name = \"cmake\"\n            version = \"3.27\"\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            def package(self):\n                with chdir(self, self.package_folder):\n                    save(self, \"bin/{}\", \"\")\n        \"\"\")\n\n    profile = textwrap.dedent(\"\"\"\n        include(default)\n        [platform_tool_requires]\n        cmake/3.27\n    \"\"\")\n\n    consumer = textwrap.dedent(\"\"\"\n        [tool_requires]\n        cmake/3.27\n        [layout]\n        cmake_layout\n    \"\"\")\n\n    cmake_exe = \"cmake.exe\" if platform.system() == \"Windows\" else \"cmake\"\n\n    c.save({\"tool.py\": tool.format(cmake_exe),\n            \"conanfile.txt\": consumer,\n            \"myprofile\": profile})\n    c.run(\"create tool.py\")\n    c.run(\"install . -g CMakeToolchain -g CMakeDeps\")\n\n    presets_path = os.path.join(\"build\", \"Release\", \"generators\", \"CMakePresets.json\") \\\n        if platform.system() != \"Windows\" else os.path.join(\"build\", \"generators\", \"CMakePresets.json\")\n    presets = json.loads(c.load(presets_path))\n\n    assert cmake_exe == os.path.basename(presets[\"configurePresets\"][0].get(\"cmakeExecutable\"))\n\n    # if we set \"tools.cmake:cmake_program\" that will have preference\n    c.run(\"install . -g CMakeToolchain -g CMakeDeps -c tools.cmake:cmake_program='/other/path/cmake'\")\n    presets = json.loads(c.load(presets_path))\n\n    assert '/other/path/cmake' == presets[\"configurePresets\"][0].get(\"cmakeExecutable\")\n\n    # if we have a platform_tool_requires it will not be set because  it is filtered before\n    # so it will not be in direct_build dependencies\n    c.run(\"install . -g CMakeToolchain -g CMakeDeps -pr:h=./myprofile\")\n\n    presets = json.loads(c.load(presets_path))\n    assert presets[\"configurePresets\"][0].get(\"cmakeExecutable\") is None\n\n\ndef test_toolchain_ends_newline():\n    # https://github.com/conan-io/conan/issues/15785\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile()})\n    client.run(\"install . -g CMakeToolchain\")\n    toolchain = client.load(\"conan_toolchain.cmake\")\n    assert toolchain[-1] == \"\\n\"\n\n\ndef test_toolchain_and_compilers_build_context():\n    \"\"\"\n    Tests how CMakeToolchain manages the build context profile if the build profile is\n    specifying another compiler path (using conf)\n\n    Issue related: https://github.com/conan-io/conan/issues/15878\n    \"\"\"\n    host = textwrap.dedent(\"\"\"\n    [settings]\n    arch=armv8\n    build_type=Release\n    compiler=gcc\n    compiler.cppstd=gnu17\n    compiler.libcxx=libstdc++11\n    compiler.version=11\n    os=Linux\n\n    [conf]\n    tools.build:compiler_executables={\"c\": \"gcc\", \"cpp\": \"g++\"}\n    \"\"\")\n    build = textwrap.dedent(\"\"\"\n    [settings]\n    os=Linux\n    arch=x86_64\n    compiler=clang\n    compiler.version=12\n    compiler.libcxx=libc++\n    compiler.cppstd=11\n\n    [conf]\n    tools.build:compiler_executables={\"c\": \"clang\", \"cpp\": \"clang++\"}\n    \"\"\")\n    tool = textwrap.dedent(\"\"\"\n    import os\n    from conan import ConanFile\n    from conan.tools.files import load\n\n    class toolRecipe(ConanFile):\n        name = \"tool\"\n        version = \"1.0\"\n        # Binary configuration\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n        generators = \"CMakeToolchain\"\n\n        def build(self):\n            toolchain = os.path.join(self.generators_folder, \"conan_toolchain.cmake\")\n            content = load(self, toolchain)\n            assert 'set(CMAKE_C_COMPILER \"clang\")' in content\n            assert 'set(CMAKE_CXX_COMPILER \"clang++\")' in content\n    \"\"\")\n    consumer = textwrap.dedent(\"\"\"\n    import os\n    from conan import ConanFile\n    from conan.tools.files import load\n\n    class consumerRecipe(ConanFile):\n        name = \"consumer\"\n        version = \"1.0\"\n        # Binary configuration\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n        generators = \"CMakeToolchain\"\n        tool_requires = \"tool/1.0\"\n\n        def build(self):\n            toolchain = os.path.join(self.generators_folder, \"conan_toolchain.cmake\")\n            content = load(self, toolchain)\n            assert 'set(CMAKE_C_COMPILER \"gcc\")' in content\n            assert 'set(CMAKE_CXX_COMPILER \"g++\")' in content\n    \"\"\")\n    client = TestClient()\n    client.save({\n        \"host\": host,\n        \"build\": build,\n        \"tool/conanfile.py\": tool,\n        \"consumer/conanfile.py\": consumer\n    })\n    client.run(\"export tool\")\n    client.run(\"create consumer -pr:h host -pr:b build --build=missing\")\n\n\ndef test_toolchain_keep_absolute_paths():\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMakeToolchain, cmake_layout\n        class Pkg(ConanFile):\n            settings = \"build_type\"\n            def generate(self):\n                tc = CMakeToolchain(self)\n                tc.absolute_paths = True\n                tc.generate()\n            def layout(self):\n                cmake_layout(self)\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile,\n            \"CMakeLists.txt\": \"\"})\n    c.run('install . ')\n\n    user_presets = json.loads(c.load(\"CMakeUserPresets.json\"))\n    assert os.path.isabs(user_presets[\"include\"][0])\n    presets = json.loads(c.load(user_presets[\"include\"][0]))\n    assert os.path.isabs(presets[\"configurePresets\"][0][\"toolchainFile\"])\n\n\ndef test_customize_cmakeuserpresets():\n    # https://github.com/conan-io/conan/issues/15639\n    c = TestClient()\n    c.save({\"conanfile.py\": GenConanfile(),\n            \"CMakeLists.txt\": \"\"})\n    c.run(\"install . -g CMakeToolchain -of=build\")\n    old = c.load(\"CMakeUserPresets.json\")\n    os.remove(os.path.join(c.current_folder, \"CMakeUserPresets.json\"))\n\n    c.run(\"install . -g CMakeToolchain -of=build -c tools.cmake.cmaketoolchain:user_presets=my.json\")\n    new = c.load(\"my.json\")\n    assert old == new\n    # also in subfolder\n    c.run(\"install . -g CMakeToolchain -of=build \"\n          \"-c tools.cmake.cmaketoolchain:user_presets=mysub/my.json\")\n    assert os.path.exists(os.path.join(c.current_folder, \"mysub\", \"my.json\"))\n\n    assert not os.path.exists(os.path.join(c.current_folder, \"CMakeUserPresets.json\"))\n    c.run(\"install . -g CMakeToolchain -of=build -c tools.cmake.cmaketoolchain:user_presets=\")\n    assert not os.path.exists(os.path.join(c.current_folder, \"CMakeUserPresets.json\"))\n\n\ndef test_output_dirs_gnudirs_local_default():\n    # https://github.com/conan-io/conan/issues/14733\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import cmake_layout\n        from conan.tools.files import load\n\n        class Conan(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            generators = \"CMakeToolchain\"\n            def build(self):\n                tc = load(self, \"conan_toolchain.cmake\")\n                self.output.info(tc)\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"create .\")\n\n    def _assert_install(out):\n        assert 'set(CMAKE_INSTALL_BINDIR \"bin\")' in out\n        assert 'set(CMAKE_INSTALL_SBINDIR \"bin\")' in out\n        assert 'set(CMAKE_INSTALL_LIBEXECDIR \"bin\")' in out\n        assert 'set(CMAKE_INSTALL_LIBDIR \"lib\")' in out\n        assert 'set(CMAKE_INSTALL_INCLUDEDIR \"include\")' in out\n\n    _assert_install(c.out)\n    assert \"CMAKE_INSTALL_PREFIX\" in c.out\n\n    c.run(\"build .\")\n    _assert_install(c.out)\n    assert \"CMAKE_INSTALL_PREFIX\" not in c.out\n\n\ndef test_output_dirs_gnudirs_local_custom():\n    # https://github.com/conan-io/conan/issues/14733\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import cmake_layout\n        from conan.tools.files import load\n\n        class Conan(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            generators = \"CMakeToolchain\"\n            def layout(self):\n                self.cpp.package.bindirs = [\"mybindir\"]\n                self.cpp.package.includedirs = [\"myincludedir\"]\n                self.cpp.package.libdirs = [\"mylibdir\"]\n\n            def build(self):\n                tc = load(self, \"conan_toolchain.cmake\")\n                self.output.info(tc)\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"create .\")\n\n    def _assert_install(out):\n        assert 'set(CMAKE_INSTALL_BINDIR \"mybindir\")' in out\n        assert 'set(CMAKE_INSTALL_SBINDIR \"mybindir\")' in out\n        assert 'set(CMAKE_INSTALL_LIBEXECDIR \"mybindir\")' in out\n        assert 'set(CMAKE_INSTALL_LIBDIR \"mylibdir\")' in out\n        assert 'set(CMAKE_INSTALL_INCLUDEDIR \"myincludedir\")' in out\n\n    _assert_install(c.out)\n    assert \"CMAKE_INSTALL_PREFIX\" in c.out\n\n    c.run(\"build .\")\n    _assert_install(c.out)\n    assert \"CMAKE_INSTALL_PREFIX\" not in c.out\n\n\ndef test_toolchain_extra_variables():\n    windows_profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=Windows\n        arch=x86_64\n        [conf]\n        tools.cmake.cmaketoolchain:extra_variables={'CMAKE_GENERATOR_INSTANCE': '${GENERATOR_INSTANCE}/buildTools/', 'FOO': '42' }\n        \"\"\")\n\n    client = TestClient()\n    client.save({\"conanfile.txt\": \"[generators]\\nCMakeToolchain\",\n                 \"windows\": windows_profile})\n\n    # Test passing extra_variables from pro ile\n    client.run(\"install . --profile:host=windows\")\n    toolchain = client.load(\"conan_toolchain.cmake\")\n    assert 'set(CMAKE_GENERATOR_INSTANCE \"${GENERATOR_INSTANCE}/buildTools/\")' in toolchain\n    assert 'set(FOO \"42\")' in toolchain\n\n    # Test input from command line passing dict between doble quotes\n    client.run(textwrap.dedent(r\"\"\"\n        install . -c tools.cmake.cmaketoolchain:extra_variables=\"{'CMAKE_GENERATOR_INSTANCE': '${GENERATOR_INSTANCE}/buildTools/', 'FOO': 42.2, 'DICT': {'value': 1}, 'CACHE_VAR': {'value': 'hello world', 'cache': True, 'type': 'BOOL', 'docstring': 'test variable'}}\"\n        \"\"\")\n    )\n\n    toolchain = client.load(\"conan_toolchain.cmake\")\n    assert 'set(CMAKE_GENERATOR_INSTANCE \"${GENERATOR_INSTANCE}/buildTools/\")' in toolchain\n    assert 'set(FOO 42.2)' in toolchain\n    assert 'set(DICT 1)' in toolchain\n    assert 'set(CACHE_VAR \"hello world\" CACHE BOOL \"test variable\")' in toolchain\n\n    client.run(textwrap.dedent(\"\"\"\n        install . -c tools.cmake.cmaketoolchain:extra_variables=\"{'myVar': {'value': 'hello world', 'cache': 'true'}}\"\n    \"\"\"), assert_error=True)\n    assert 'tools.cmake.cmaketoolchain:extra_variables \"myVar\" \"cache\" must be a boolean' in client.out\n\n    # Test invalid force\n    client.run(textwrap.dedent(\"\"\"\n        install . -c tools.cmake.cmaketoolchain:extra_variables=\"{'myVar': {'value': 'hello world', 'force': True}}\"\n    \"\"\"), assert_error=True)\n    assert 'tools.cmake.cmaketoolchain:extra_variables \"myVar\" \"force\" is only allowed for cache variables' in client.out\n\n    client.run(textwrap.dedent(\"\"\"\n        install . -c tools.cmake.cmaketoolchain:extra_variables=\"{'myVar': {'value': 'hello world', 'cache': True, 'force': 'true'}}\"\n    \"\"\"), assert_error=True)\n    assert 'tools.cmake.cmaketoolchain:extra_variables \"myVar\" \"force\" must be a boolean' in client.out\n\n    # Test invalid cache variable\n    client.run(textwrap.dedent(\"\"\"\n        install . -c tools.cmake.cmaketoolchain:extra_variables=\"{'myVar': {'value': 'hello world', 'cache': True}}\"\n    \"\"\"), assert_error=True)\n    assert 'tools.cmake.cmaketoolchain:extra_variables \"myVar\" needs \"type\" defined for cache variable' in client.out\n\n    client.run(textwrap.dedent(\"\"\"\n        install . -c tools.cmake.cmaketoolchain:extra_variables=\"{'myVar': {'value': 'hello world', 'cache': True, 'type': 'INVALID_TYPE'}}\"\n    \"\"\"), assert_error=True)\n    assert 'tools.cmake.cmaketoolchain:extra_variables \"myVar\" invalid type \"INVALID_TYPE\" for cache variable. Possible types: BOOL, FILEPATH, PATH, STRING, INTERNAL' in client.out\n\n    client.run(textwrap.dedent(\"\"\"\n        install . -c tools.cmake.cmaketoolchain:extra_variables=\"{'CACHE_VAR_DEFAULT_DOC': {'value': 'hello world', 'cache': True, 'type': 'PATH'}}\"\n    \"\"\"))\n    toolchain = client.load(\"conan_toolchain.cmake\")\n    assert 'set(CACHE_VAR_DEFAULT_DOC \"hello world\" CACHE PATH \"CACHE_VAR_DEFAULT_DOC\")' in toolchain\n\n    client.run(textwrap.dedent(\"\"\"\n        install . -c tools.cmake.cmaketoolchain:extra_variables=\"{'myVar': {'value': 'hello world', 'cache': True, 'type': 'PATH', 'docstring': 'My cache variable', 'force': True}}\"\n    \"\"\"))\n    toolchain = client.load(\"conan_toolchain.cmake\")\n    assert 'set(myVar \"hello world\" CACHE PATH \"My cache variable\" FORCE)' in toolchain\n\n\ndef test_variables_wrong_scaping():\n    # https://github.com/conan-io/conan/issues/16432\n    c = TestClient()\n    c.save({\"tool/conanfile.py\": GenConanfile(\"tool\", \"0.1\"),\n            \"pkg/conanfile.txt\": \"[tool_requires]\\ntool/0.1\\n[generators]\\nCMakeToolchain\"})\n    c.run(\"create tool\")\n    c.run(\"install pkg\")\n    toolchain = c.load(\"pkg/conan_toolchain.cmake\")\n    cache_folder = c.cache_folder.replace(\"\\\\\", \"/\")\n    assert f'list(PREPEND CMAKE_PROGRAM_PATH \"{cache_folder}' in toolchain\n\n    c.run(\"install pkg --deployer=full_deploy\")\n    toolchain = c.load(\"pkg/conan_toolchain.cmake\")\n    assert 'list(PREPEND CMAKE_PROGRAM_PATH \"${CMAKE_CURRENT_LIST_DIR}/full_deploy' in toolchain\n\n\ndef test_tricore():\n    # making sure the arch ``tc131`` is there\n    c = TestClient()\n    c.save({\"conanfile.txt\": \"[generators]\\nCMakeToolchain\"})\n    c.run(\"install . -s os=baremetal -s compiler=gcc -s arch=tc131\")\n    content = c.load(\"conan_toolchain.cmake\")\n    assert 'set(CMAKE_SYSTEM_NAME Generic-ELF)' in content\n    assert 'set(CMAKE_SYSTEM_PROCESSOR tricore)' in content\n    assert 'string(APPEND CONAN_CXX_FLAGS \" -mtc131\")' in content\n    assert 'string(APPEND CONAN_C_FLAGS \" -mtc131\")' in content\n    assert 'string(APPEND CONAN_SHARED_LINKER_FLAGS \" -mtc131\")' in content\n    assert 'string(APPEND CONAN_EXE_LINKER_FLAGS \" -mtc131\")' in content\n\n\ndef test_declared_stdlib_and_passed():\n    client = TestClient()\n    client.save({\"conanfile.txt\": \"[generators]\\nCMakeToolchain\"})\n\n    client.run('install . -s compiler=sun-cc -s compiler.libcxx=libCstd')\n    tc = client.load(\"conan_toolchain.cmake\")\n    assert 'string(APPEND CONAN_CXX_FLAGS \" -library=Cstd\")' in tc\n\n    client.run('install . -s compiler=sun-cc -s compiler.libcxx=libstdcxx')\n    tc = client.load(\"conan_toolchain.cmake\")\n    assert 'string(APPEND CONAN_CXX_FLAGS \" -library=stdcxx4\")' in tc\n\n\ndef test_cmake_presets_compiler():\n    profile = textwrap.dedent(r\"\"\"\n        [settings]\n        os=Windows\n        arch=x86_64\n        compiler=msvc\n        compiler.version=193\n        compiler.runtime=dynamic\n        [conf]\n        tools.build:compiler_executables={\"c\": \"cl\", \"cpp\": \"cl.exe\"}\n        \"\"\")\n    client = TestClient()\n    conanfile = GenConanfile().with_settings(\"os\", \"arch\", \"compiler\")\\\n        .with_generator(\"CMakeToolchain\")\n    client.save({\"conanfile.py\": conanfile,\n                 \"profile\": profile})\n    client.run(\"install . -pr:b profile -pr:h profile\")\n    presets = json.loads(client.load(\"CMakePresets.json\"))\n    cache_variables = presets[\"configurePresets\"][0][\"cacheVariables\"]\n    # https://github.com/microsoft/vscode-cmake-tools/blob/a1ceda25ea93fc0060324de15970a8baa69addf6/src/presets/preset.ts#L1095C23-L1095C35\n    assert cache_variables[\"CMAKE_C_COMPILER\"] == \"cl\"\n    assert cache_variables[\"CMAKE_CXX_COMPILER\"] == \"cl.exe\"\n\n\n@pytest.mark.parametrize(\n    \"threads, flags\",\n    [(\"posix\", \"-pthread\"), (\"wasm_workers\", \"-sWASM_WORKERS=1\")],\n)\ndef test_thread_flags(threads, flags):\n    client = TestClient()\n    profile = textwrap.dedent(f\"\"\"\n        [settings]\n        arch=wasm\n        build_type=Release\n        compiler=emcc\n        compiler.cppstd=17\n        compiler.threads={threads}\n        compiler.libcxx=libc++\n        compiler.version=4.0.10\n        os=Emscripten\n        \"\"\")\n    client.save(\n        {\n            \"conanfile.py\": GenConanfile(\"pkg\", \"1.0\")\n            .with_settings(\"os\", \"arch\", \"compiler\", \"build_type\")\n            .with_generator(\"CMakeToolchain\"),\n            \"profile\": profile,\n        }\n    )\n    client.run(\"install . -pr=./profile\")\n    toolchain = client.load(\"conan_toolchain.cmake\")\n    assert f'string(APPEND CONAN_CXX_FLAGS \" {flags}\")' in toolchain\n    assert f'string(APPEND CONAN_C_FLAGS \" {flags}\")' in toolchain\n    assert f'string(APPEND CONAN_SHARED_LINKER_FLAGS \" {flags}\")' in toolchain\n    assert f'string(APPEND CONAN_EXE_LINKER_FLAGS \" {flags}\")' in toolchain\n"
  },
  {
    "path": "test/integration/toolchains/cmake/test_cmaketoolchain_blocks.py",
    "content": "import textwrap\n\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_custom_block():\n    # https://github.com/conan-io/conan/issues/9998\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import CMakeToolchain\n        class Pkg(ConanFile):\n            def generate(self):\n                toolchain = CMakeToolchain(self)\n\n                class MyBlock:\n                    template = \"Hello {{myvar}}!!!\"\n\n                    def context(self):\n                        return {\"myvar\": \"World\"}\n\n                toolchain.blocks[\"mynewblock\"] = MyBlock\n                toolchain.generate()\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"install .\")\n    assert \"Hello World!!!\" in c.load(\"conan_toolchain.cmake\")\n"
  },
  {
    "path": "test/integration/toolchains/env/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/toolchains/env/test_buildenv.py",
    "content": "import platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Fails on windows\")\ndef test_crossbuild_windows_incomplete():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            def build(self):\n                # using python --version as it does not depend on shell\n                self.run(\"python --version\")\n            \"\"\")\n    build_profile = textwrap.dedent(\"\"\"\n        [settings]\n        arch=x86_64\n    \"\"\")\n    client.save({\"conanfile.py\": conanfile, \"build_profile\": build_profile})\n    client.run(\"create . -pr:b=build_profile\", assert_error=True)\n    assert \"The 'build' profile must have a 'os' declared\" in client.out\n\n    build_profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=Windows\n        arch=x86_64\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile, \"build_profile\": build_profile})\n    client.run(\"create . -pr:b=build_profile\")\n    assert \"Python\" in client.out\n\n\ndef test_quoted_vars():\n    # https://github.com/conan-io/conan/issues/18761\n    c = TestClient()\n\n    dep = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            name = \"dep\"\n            version = \"0.1\"\n            settings = \"os\"\n            def package_info(self):\n                v = 'MyVar:\"content!! | other!!\"'\n                v = v.replace(\"|\", \"^|\") if self.settings.os == \"Windows\" else v  # escape\n                self.buildenv_info.define(\"MyCustomEscapedVar\", v)\n        \"\"\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        import os, platform\n        from conan import ConanFile\n\n        class ConanFileToolsTest(ConanFile):\n            settings = \"os\"\n            requires = \"dep/0.1\"\n            def build(self):\n                if platform.system() == \"Windows\":\n                    self.run(\"set MyCustomEscapedVar\")\n                else:\n                    self.run(\"printenv MyCustomEscapedVar\")\n                self.run(\"echo Hello!!!!\")\n        \"\"\")\n\n    c.save({\"dep/conanfile.py\": dep,\n            \"consumer/conanfile.py\": conanfile})\n\n    c.run(\"create dep\")\n    c.run(\"build consumer\")\n    assert 'MyVar:\"content!! | other!!\"' in c.out\n    assert \"Hello!!!!\" in c.out\n"
  },
  {
    "path": "test/integration/toolchains/env/test_environment.py",
    "content": "import platform\nimport textwrap\n\nfrom conan.test.utils.tools import TestClient\n\n\n# TODO: Change this test when we refactor EnvVars. The UX leaves much to be desired\ndef test_env_and_scope_none():\n    \"\"\"\n    Check scope=None does not append foo=var to conan{build|run}.{bat|sh|ps1}\n\n    Issue: https://github.com/conan-io/conan/issues/17249\n    \"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.env import Environment\n        class Pkg(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            def generate(self):\n                env1 = Environment()\n                env1.define(\"foo\", \"var\")\n                # Will not append \"my_env_file\" to \"conanbuild.bat|sh|ps1\"\n                envvars = env1.vars(self, scope=None)\n                envvars.save_script(\"my_env_file\")\n                # Let's check the apply() function\n                with env1.vars(self, scope=None).apply():\n                    import os\n                    assert os.environ[\"foo\"] == \"var\"\n            \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"install .\")\n    ext = \".bat\" if platform.system() == \"Windows\" else \".sh\"\n    assert \"my_env_file\" not in client.load(f\"conanbuild{ext}\")\n    assert \"my_env_file\" not in client.load(f\"conanrun{ext}\")\n\n"
  },
  {
    "path": "test/integration/toolchains/env/test_virtualenv_default_apply.py",
    "content": "import os\nimport platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.fixture\ndef client():\n    client = TestClient()\n    conanfile = str(GenConanfile())\n    conanfile += \"\"\"\n    def package_info(self):\n        self.buildenv_info.define(\"Foo\", \"MyVar!\")\n        self.runenv_info.define(\"Foo\", \"MyRunVar!\")\n    \"\"\"\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=foo --version=1.0\")\n    return client\n\n\n@pytest.mark.parametrize(\"scope\", [\"build\", \"run\"])\n@pytest.mark.parametrize(\"default_virtualenv\", [True, False, None])\n@pytest.mark.parametrize(\"cli_value\", [None, \"false\"])\ndef test_virtualenv_deactivated(client, scope, default_virtualenv, cli_value):\n    format_str = {True: f\"virtual{scope}env = True\",\n                  False: f\"virtual{scope}env = False\",\n                  None: \"\"}[default_virtualenv]\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n\n    class ConanFileToolsTest(ConanFile):\n        settings = \"os\"\n        {}\n        requires = \"foo/1.0\"\n    \"\"\").format(format_str)\n\n    client.save({\"conanfile.py\": conanfile})\n    cli_extra = f\"--envs-generation={cli_value}\" if cli_value is not None else \"\"\n    client.run(f\"install . {cli_extra}\")\n    extension = \"bat\" if platform.system() == \"Windows\" else \"sh\"\n\n    filename = f\"conan{scope}env.{extension}\"\n    filepath = os.path.join(client.current_folder, filename)\n\n    exists_file = os.path.exists(filepath)\n\n    should_exist = cli_value != \"false\" and (default_virtualenv is None or default_virtualenv)\n\n    if should_exist:\n        assert exists_file, f\"File {filename} should exist in {os.listdir(client.current_folder)}\"\n        assert \"Foo\" in client.load(filepath)\n    else:\n        assert not exists_file, f\"File {filename} should not exist in {os.listdir(client.current_folder)}\"\n\n\ndef test_deactivate_virtualxxxenv_attr():\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class ConanFileToolsTest(ConanFile):\n            virtualbuildenv = False\n            virtualrunenv = False\n        \"\"\")\n    c = TestClient(light=True)\n    c.save({\"conanfile.py\": conanfile})\n    c.run(f\"install \")\n    assert os.listdir(c.current_folder) == [\"conanfile.py\"]\n\n\ndef test_virtualrunenv_not_applied(client):\n    \"\"\"By default the VirtualRunEnv is not added to the list, otherwise when declaring\n       generators = \"VirtualBuildEnv\", \"VirtualRunEnv\" will be always added\"\"\"\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    import platform\n\n    class ConanFileToolsTest(ConanFile):\n        settings = \"os\"\n        generators = \"VirtualBuildEnv\", \"VirtualRunEnv\"\n        requires = \"foo/1.0\"\n    \"\"\")\n\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"install . \")\n    extension = \"bat\" if platform.system() == \"Windows\" else \"sh\"\n    exists_file = os.path.exists(os.path.join(client.current_folder,\n                                              \"conanrun.{}\".format(extension)))\n    assert exists_file\n\n    global_env = client.load(\"conanbuild.{}\".format(extension))\n    assert \"conanrunenv\" not in global_env\n\n\n@pytest.mark.parametrize(\"explicit_declare\", [True, False, None])\ndef test_virtualrunenv_explicit_declare(client, explicit_declare):\n    \"\"\"By default the VirtualRunEnv is not added to the list, otherwise when declaring\n       generators = \"VirtualBuildEnv\", \"VirtualRunEnv\" will be always added\"\"\"\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    from conan.tools.env import VirtualRunEnv\n    import platform\n\n    class ConanFileToolsTest(ConanFile):\n        requires = \"foo/1.0\"\n\n        def generate(self):\n            VirtualRunEnv(self).generate({})\n\n    \"\"\").format({True: \"scope='build'\",\n                 False: \"scope='run'\",\n                 None: \"\"}.get(explicit_declare))\n\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"install . \")\n    extension = \"bat\" if platform.system() == \"Windows\" else \"sh\"\n    exists_file = os.path.exists(os.path.join(client.current_folder,\n                                              \"conanbuild.{}\".format(extension)))\n    assert exists_file\n\n    global_env = client.load(\"conanbuild.{}\".format(extension))\n    if explicit_declare:\n        assert \"conanrun\" in global_env\n    else:\n        assert \"conanrun\" not in global_env\n"
  },
  {
    "path": "test/integration/toolchains/env/test_virtualenv_object_access.py",
    "content": "import textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.fixture\ndef client():\n    client = TestClient()\n    conanfile = str(GenConanfile())\n    conanfile += \"\"\"\n    def package_info(self):\n        self.buildenv_info.define(\"Foo\", \"MyVar!\")\n        self.runenv_info.define(\"runFoo\", \"Value!\")\n        self.buildenv_info.append(\"Hello\", \"MyHelloValue!\")\n    \"\"\"\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=foo --version=1.0\")\n    return client\n\n\ndef test_virtualenv_object_access(client):\n    conanfile = textwrap.dedent(\"\"\"\n    import os\n    from conan import ConanFile\n    from conan.tools.env import VirtualBuildEnv, VirtualRunEnv\n\n    class ConanFileToolsTest(ConanFile):\n        requires = \"foo/1.0\"\n\n        def build(self):\n          build_env = VirtualBuildEnv(self).vars()\n          run_env = VirtualRunEnv(self).vars()\n          self.output.warning(\"Foo: *{}*\".format(build_env[\"Foo\"]))\n          self.output.warning(\"runFoo: *{}*\".format(run_env[\"runFoo\"]))\n          self.output.warning(\"Hello: *{}*\".format(build_env[\"Hello\"]))\n\n          with build_env.apply():\n            with run_env.apply():\n              self.output.warning(\"Applied Foo: *{}*\".format(os.getenv(\"Foo\", \"\")))\n              self.output.warning(\"Applied Hello: *{}*\".format(os.getenv(\"Hello\", \"\")))\n              self.output.warning(\"Applied runFoo: *{}*\".format(os.getenv(\"runFoo\", \"\")))\n    \"\"\")\n\n    profile = textwrap.dedent(\"\"\"\n            [buildenv]\n            Foo+=MyFooValue\n        \"\"\")\n\n    client.save({\"conanfile.py\": conanfile, \"profile\": profile})\n\n    client.run(\"create . --name=app --version=1.0 --profile=profile\")\n    assert \"Foo: *MyVar! MyFooValue*\"\n    assert \"runFoo:* Value!*\"\n    assert \"Hello:* MyHelloValue!*\"\n\n    assert \"Applied Foo: *MyVar! MyFooValue*\"\n    assert \"Applied runFoo: **\"\n    assert \"Applied Hello: * MyHelloValue!*\"\n"
  },
  {
    "path": "test/integration/toolchains/env/test_virtualenv_winbash.py",
    "content": "import os\nimport platform\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\"\"\"\nWhen we use the VirtualRunEnv and VirtualBuildEnd generators, we take information from the\nself.dependencies env_buildinfo and env_runinfo, but to format correctly the environment\nvariables that are paths to run in a windows bash, we need to look at the consumer conanfile\nnot the dependency conanfile. This is testing that in the process of aggregating the paths,\nthese are correct.\n\"\"\"\n\n\n@pytest.fixture\ndef client():\n    client = TestClient()\n    conanfile = str(GenConanfile())\n    conanfile += \"\"\"\n\n    def package_info(self):\n        self.buildenv_info.define_path(\"AR\", \"c:/path/to/ar\")\n        self.buildenv_info.append_path(\"PATH\", \"c:/path/to/something\")\n        self.runenv_info.define_path(\"RUNTIME_VAR\", \"c:/path/to/exe\")\n    \"\"\"\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=foo --version=1.0\")\n    client.save_home({\"global.conf\": \"tools.microsoft.bash:subsystem=cygwin\"})\n    return client\n\n\n@pytest.mark.parametrize(\"win_bash\", [True, False, None])\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows\")\ndef test_virtualenv_deactivated(client, win_bash):\n    conanfile = GenConanfile().with_settings(\"os\").with_require(\"foo/1.0\")\n    if win_bash:\n        conanfile.with_class_attribute(\"win_bash = True\")\n\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"install . -s:b os=Windows -s:h os=Windows\")\n\n    if win_bash:\n        # Assert there is no \"bat\" files generated because the environment can and will be run inside\n        # the bash\n        assert not os.path.exists(os.path.join(client.current_folder, \"conanbuildenv.bat\"))\n        build_contents = client.load(\"conanbuildenv.sh\")\n        assert \"/cygdrive/c/path/to/ar\" in build_contents\n        assert \"${PATH:-}${PATH:+:}/cygdrive/c/path/to/something\" in build_contents\n    else:\n        assert not os.path.exists(os.path.join(client.current_folder, \"conanbuildenv.sh\"))\n        build_contents = client.load(\"conanbuildenv.bat\")\n        assert \"c:/path/to/ar\" in build_contents\n        assert \"c:/path/to/something\" in build_contents\n\n    assert not os.path.exists(os.path.join(client.current_folder, \"conanrunenv.sh\"))\n    run_contents = client.load(\"conanrunenv.bat\")\n    assert \"c:/path/to/exe\" in run_contents\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows\")\ndef test_nowinbash(client):\n    \"\"\" whe the recipe doesn't define win_bash=True 2 things can happen:\n    - No need to run in bash, things will run in normal command, with .bat\n    - You run directly in a subsytem terminal a recipe that was not aware of that, still the\n       files need to follow the subsystem\n    \"\"\"\n    conanfile = str(GenConanfile().with_settings(\"os\")\n                    .with_generator(\"VirtualBuildEnv\").with_generator(\"VirtualRunEnv\")\n                    .with_require(\"foo/1.0\"))\n\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"install . -s:b os=Windows -s:h os=Windows\")\n    assert not os.path.exists(os.path.join(client.current_folder, \"conanbuildenv.sh\"))\n    build_contents = client.load(\"conanbuildenv.bat\")\n    assert 'set \"AR=c:/path/to/ar\"' in build_contents\n    assert 'set \"PATH=%PATH%;c:/path/to/something\"' in build_contents\n    assert not os.path.exists(os.path.join(client.current_folder, \"conanrunenv.sh\"))\n    run_contents = client.load(\"conanrunenv.bat\")\n    assert 'set \"RUNTIME_VAR=c:/path/to/exe\"' in run_contents\n\n    # Running it inside a cygwin subsystem\n    client.save({\"conanfile.py\": conanfile}, clean_first=True)\n    client.run(\"install . -s:b os=Windows -s:h os=Windows \"\n               \"-c:h tools.microsoft.bash:active=True\")\n    assert not os.path.exists(os.path.join(client.current_folder, \"conanbuildenv.bat\"))\n    build_contents = client.load(\"conanbuildenv.sh\")\n    assert 'export AR=\"/cygdrive/c/path/to/ar\"' in build_contents\n    assert 'export PATH=\"${PATH:-}${PATH:+:}/cygdrive/c/path/to/something\"' in build_contents\n    assert not os.path.exists(os.path.join(client.current_folder, \"conanrunenv.bat\"))\n    run_contents = client.load(\"conanrunenv.sh\")\n    assert 'export RUNTIME_VAR=\"/cygdrive/c/path/to/exe\"' in run_contents\n\n    # Running it inside a msys2 subsystem, test tat it overrides\n    client.save({\"conanfile.py\": conanfile}, clean_first=True)\n    client.run(\"install . -s:b os=Windows -s:h os=Windows \"\n               \"-c tools.microsoft.bash:subsystem=msys2 -c:h tools.microsoft.bash:active=True\")\n    assert not os.path.exists(os.path.join(client.current_folder, \"conanbuildenv.bat\"))\n    build_contents = client.load(\"conanbuildenv.sh\")\n    assert 'export AR=\"/c/path/to/ar\"' in build_contents\n    assert 'export PATH=\"${PATH:-}${PATH:+:}/c/path/to/something\"' in build_contents\n    assert not os.path.exists(os.path.join(client.current_folder, \"conanrunenv.bat\"))\n    run_contents = client.load(\"conanrunenv.sh\")\n    assert 'export RUNTIME_VAR=\"/c/path/to/exe\"' in run_contents\n"
  },
  {
    "path": "test/integration/toolchains/gnu/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/toolchains/gnu/test_autotools.py",
    "content": "import textwrap\n\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_autotools_make_parameters():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.gnu import AutotoolsToolchain, Autotools\n\n        class Conan(ConanFile):\n            settings = \"os\"\n            generators = \"AutotoolsDeps\", \"AutotoolsToolchain\", \"VirtualRunEnv\"\n\n            def run(self, cmd, *args, **kwargs):\n                self.output.info(f\"Running {cmd}\")\n\n            def build(self):\n                autotools = Autotools(self)\n                autotools.make(makefile=\"MyMake\", target=\"test\", args=[\"-j4\", \"VERBOSE=1\"])\n                autotools.install(makefile=\"OtherMake\")\n        \"\"\")\n\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"build .\")\n    assert \"make --file=MyMake test -j4 VERBOSE=1\" in client.out\n    assert \"make --file=OtherMake install\" in client.out\n"
  },
  {
    "path": "test/integration/toolchains/gnu/test_autotoolsdeps.py",
    "content": "import platform\nimport re\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.skipif(platform.system() not in [\"Linux\", \"Darwin\"], reason=\"Autotools\")\ndef test_link_lib_correct_order():\n    client = TestClient()\n    liba = GenConanfile().with_name(\"liba\").with_version(\"0.1\")\n    libb = GenConanfile().with_name(\"libb\").with_version(\"0.1\").with_require(\"liba/0.1\")\n    libc = GenConanfile().with_name(\"libc\").with_version(\"0.1\").with_require(\"libb/0.1\")\n    consumer = GenConanfile().with_require(\"libc/0.1\")\n    client.save({\"liba.py\": liba, \"libb.py\": libb, \"libc.py\": libc, \"consumer.py\": consumer})\n    client.run(\"create liba.py\")\n    folder_a = client.created_layout().package()\n    client.run(\"create libb.py\")\n    folder_b = client.created_layout().package()\n    client.run(\"create libc.py\")\n    folder_c = client.created_layout().package()\n    client.run(\"install consumer.py -g AutotoolsDeps\")\n    deps = client.load(\"conanautotoolsdeps.sh\")\n    # check the libs are added in the correct order with this regex\n    assert re.search(\"export LDFLAGS.*{}.*{}.*{}\".format(folder_c, folder_b, folder_a), deps)\n\n\n@pytest.mark.skipif(platform.system() not in [\"Linux\", \"Darwin\"], reason=\"Autotools\")\ndef test_cpp_info_aggregation():\n\n    profile = textwrap.dedent(\"\"\"\n         [settings]\n         build_type=Release\n         arch=x86\n         os=Macos\n         compiler=gcc\n         compiler.libcxx=libstdc++11\n         compiler.version=7.1\n         compiler.cppstd=17\n    \"\"\")\n\n    dep_conanfile = textwrap.dedent(r\"\"\"\n\n    from conan import ConanFile\n\n    class Dep(ConanFile):\n\n        settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n\n        def package_info(self):\n            self.cpp_info.includedirs = []\n            self.cpp_info.includedirs.append(\"path/includes/{}\".format(self.name))\n            self.cpp_info.includedirs.append(\"other\\\\include\\\\path\\\\{}\".format(self.name))\n            # To test some path in win, to be used with MinGW make or MSYS etc\n            self.cpp_info.libdirs = []\n            self.cpp_info.libdirs.append(\"one\\\\lib\\\\path\\\\{}\".format(self.name))\n            self.cpp_info.libs = []\n            self.cpp_info.libs.append(\"{}_onelib\".format(self.name))\n            self.cpp_info.libs.append(\"{}_twolib\".format(self.name))\n            self.cpp_info.defines = []\n            self.cpp_info.defines.append(\"{}_onedefinition\".format(self.name))\n            self.cpp_info.defines.append(\"{}_twodefinition\".format(self.name))\n            self.cpp_info.cflags = [\"{}_a_c_flag\".format(self.name)]\n            self.cpp_info.cxxflags = [\"{}_a_cxx_flag\".format(self.name)]\n            self.cpp_info.sharedlinkflags = [\"{}_shared_link_flag\".format(self.name)]\n            self.cpp_info.exelinkflags = [\"{}_exe_link_flag\".format(self.name)]\n            self.cpp_info.sysroot = \"/path/to/folder/{}\".format(self.name)\n            self.cpp_info.frameworks = []\n            self.cpp_info.frameworks.append(\"{}_oneframework\".format(self.name))\n            self.cpp_info.frameworks.append(\"{}_twoframework\".format(self.name))\n            self.cpp_info.system_libs = []\n            self.cpp_info.system_libs.append(\"{}_onesystemlib\".format(self.name))\n            self.cpp_info.system_libs.append(\"{}_twosystemlib\".format(self.name))\n            self.cpp_info.frameworkdirs = []\n            self.cpp_info.frameworkdirs.append(\"one/framework/path/{}\".format(self.name))\n\n    \"\"\")\n\n    t = TestClient()\n    t.save({\"conanfile.py\": dep_conanfile, \"macos\": profile})\n    t.run(\"create . --name dep1 --version 1.0 --profile:host=macos\")\n    t.run(\"create . --name dep2 --version 1.0 --profile:host=macos\")\n\n    consumer = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.gnu import AutotoolsDeps\n\n        class HelloConan(ConanFile):\n            requires = \"dep1/1.0\", \"dep2/1.0\"\n            settings = \"os\", \"arch\", \"build_type\", \"compiler\"\n\n            def generate(self):\n                deps = AutotoolsDeps(self)\n                env = deps.environment\n\n                # Customize the environment\n                env.remove(\"LDFLAGS\", \"dep2_shared_link_flag\")\n                env.append(\"LDFLAGS\", \"OtherSuperStuff\")\n\n                env = deps.vars()\n                # The contents are of course modified\n                # The topological order puts dep2 before dep1\n                assert env[\"CXXFLAGS\"] == 'dep2_a_cxx_flag dep1_a_cxx_flag'\n                assert env[\"CFLAGS\"] == 'dep2_a_c_flag dep1_a_c_flag'\n                assert env[\"LIBS\"] == \"-ldep2_onelib -ldep2_twolib -ldep1_onelib -ldep1_twolib \"\\\n                                      \"-ldep2_onesystemlib -ldep2_twosystemlib \"\\\n                                      \"-ldep1_onesystemlib -ldep1_twosystemlib\"\n\n                assert 'dep1_shared_link_flag dep2_exe_link_flag dep1_exe_link_flag -framework dep2_oneframework -framework dep2_twoframework ' \\\n                                     '-framework dep1_oneframework -framework dep1_twoframework ' in env[\"LDFLAGS\"]\n                assert 'OtherSuperStuff' in env[\"LDFLAGS\"]\n    \"\"\")\n\n    t.save({\"conanfile.py\": consumer})\n    t.run(\"create . --name consumer --version 1.0 --profile:host=macos\")\n"
  },
  {
    "path": "test/integration/toolchains/gnu/test_autotoolstoolchain.py",
    "content": "import os\nimport platform\nimport textwrap\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import save, load\n\n\ndef test_extra_flags_via_conf():\n    os_ = platform.system()\n    os_ = \"Macos\" if os_ == \"Darwin\" else os_\n\n    profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=%s\n        compiler=gcc\n        compiler.version=6\n        compiler.libcxx=libstdc++11\n        arch=armv8\n        build_type=Release\n\n        [conf]\n        tools.build:cxxflags=[\"--flag1\", \"--flag2\"]\n        tools.build:cflags+=[\"--flag3\", \"--flag4\"]\n        tools.build:sharedlinkflags+=[\"--flag5\"]\n        tools.build:exelinkflags+=[\"--flag6\"]\n        tools.build:defines+=[\"DEF1\", \"DEF2\"]\n        \"\"\" % os_)\n    client = TestClient()\n    conanfile = GenConanfile().with_settings(\"os\", \"arch\", \"compiler\", \"build_type\")\\\n        .with_generator(\"AutotoolsToolchain\")\n    client.save({\"conanfile.py\": conanfile,\n                \"profile\": profile})\n    client.run(\"install . --profile:build=profile --profile:host=profile\")\n    toolchain = client.load(\"conanautotoolstoolchain{}\".format('.bat' if os_ == \"Windows\" else '.sh'))\n    if os_ == \"Windows\":\n        assert 'set \"CPPFLAGS=%CPPFLAGS% -DNDEBUG -DDEF1 -DDEF2\"' in toolchain\n        assert 'set \"CXXFLAGS=%CXXFLAGS% -O3 --flag1 --flag2\"' in toolchain\n        assert 'set \"CFLAGS=%CFLAGS% -O3 --flag3 --flag4\"' in toolchain\n        assert 'set \"LDFLAGS=%LDFLAGS% --flag5 --flag6\"' in toolchain\n    else:\n        assert 'export CPPFLAGS=\"${CPPFLAGS:-}${CPPFLAGS:+ }-DNDEBUG -DDEF1 -DDEF2\"' in toolchain\n        assert 'export CXXFLAGS=\"${CXXFLAGS:-}${CXXFLAGS:+ }-O3 --flag1 --flag2\"' in toolchain\n        assert 'export CFLAGS=\"${CFLAGS:-}${CFLAGS:+ }-O3 --flag3 --flag4\"' in toolchain\n        assert 'export LDFLAGS=\"${LDFLAGS:-}${LDFLAGS:+ }--flag5 --flag6\"' in toolchain\n\n\ndef test_extra_flags_order():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.gnu import AutotoolsToolchain\n\n        class Conan(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            settings = \"os\", \"arch\", \"build_type\"\n            def generate(self):\n                at = AutotoolsToolchain(self)\n                at.extra_cxxflags = [\"extra_cxxflags\"]\n                at.extra_cflags = [\"extra_cflags\"]\n                at.extra_ldflags = [\"extra_ldflags\"]\n                at.extra_defines = [\"extra_defines\"]\n                at.generate()\n        \"\"\")\n    profile = textwrap.dedent(\"\"\"\n        include(default)\n        [conf]\n        tools.build:cxxflags+=['cxxflags']\n        tools.build:cflags+=['cflags']\n        tools.build:sharedlinkflags+=['sharedlinkflags']\n        tools.build:exelinkflags+=['exelinkflags']\n        tools.build:defines+=['defines']\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile, \"profile\": profile})\n    client.run('install . -pr=./profile')\n    toolchain = client.load(\"conanautotoolstoolchain{}\".format('.bat' if platform.system() == \"Windows\" else '.sh'))\n\n    assert '-Dextra_defines -Ddefines' in toolchain\n    assert 'extra_cxxflags cxxflags' in toolchain\n    assert 'extra_cflags cflags' in toolchain\n    assert 'extra_ldflags sharedlinkflags exelinkflags' in toolchain\n\n\ndef test_autotoolstoolchain_rcflags():\n    \"\"\"Test that tools.build:rcflags is applied to RCFLAGS in the generated script.\"\"\"\n    os_ = platform.system()\n    os_ = \"Macos\" if os_ == \"Darwin\" else os_\n    profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=%s\n        arch=x86_64\n        compiler=gcc\n        compiler.version=6\n        compiler.libcxx=libstdc++11\n        build_type=Release\n\n        [conf]\n        tools.build:rcflags=[\"--rcflag1\", \"--rcflag2\"]\n        \"\"\" % os_)\n    client = TestClient()\n    conanfile = GenConanfile().with_settings(\"os\", \"arch\", \"compiler\", \"build_type\").with_generator(\"AutotoolsToolchain\")\n    client.save({\"conanfile.py\": conanfile, \"profile\": profile})\n    client.run(\"install . --profile:build=profile --profile:host=profile\")\n    ext = \".bat\" if os_ == \"Windows\" else \".sh\"\n    toolchain = client.load(\"conanautotoolstoolchain{}\".format(ext))\n    assert \"RCFLAGS\" in toolchain\n    assert \"--rcflag1\" in toolchain\n    assert \"--rcflag2\" in toolchain\n\n\ndef test_autotools_custom_environment():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.gnu import AutotoolsToolchain\n\n            class Conan(ConanFile):\n                settings = \"os\"\n                def generate(self):\n                    at = AutotoolsToolchain(self)\n                    env = at.environment()\n                    env.define(\"FOO\", \"BAR\")\n                    at.generate(env)\n            \"\"\")\n\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"install . -s:b os=Linux -s:h os=Linux\")\n    content = load(os.path.join(client.current_folder,  \"conanautotoolstoolchain.sh\"))\n    assert 'export FOO=\"BAR\"' in content\n\n\ndef test_linker_scripts_via_conf():\n    os_ = platform.system()\n    os_ = \"Macos\" if os_ == \"Darwin\" else os_\n\n    profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=%s\n        compiler=gcc\n        compiler.version=6\n        compiler.libcxx=libstdc++11\n        arch=armv8\n        build_type=Release\n\n        [conf]\n        tools.build:sharedlinkflags+=[\"--flag5\"]\n        tools.build:exelinkflags+=[\"--flag6\"]\n        tools.build:linker_scripts+=[\"/linker/scripts/flash.ld\", \"/linker/scripts/extra_data.ld\"]\n        \"\"\" % os_)\n    client = TestClient()\n    conanfile = GenConanfile().with_settings(\"os\", \"arch\", \"compiler\", \"build_type\")\\\n        .with_generator(\"AutotoolsToolchain\")\n    client.save({\"conanfile.py\": conanfile,\n                \"profile\": profile})\n    client.run(\"install . --profile:build=profile --profile:host=profile\")\n    toolchain = client.load(\"conanautotoolstoolchain{}\".format('.bat' if os_ == \"Windows\" else '.sh'))\n    if os_ == \"Windows\":\n        assert 'set \"LDFLAGS=%LDFLAGS% --flag5 --flag6 -T\\'/linker/scripts/flash.ld\\' -T\\'/linker/scripts/extra_data.ld\\'\"' in toolchain\n    else:\n        assert 'export LDFLAGS=\"${LDFLAGS:-}${LDFLAGS:+ }--flag5 --flag6 -T\\'/linker/scripts/flash.ld\\' -T\\'/linker/scripts/extra_data.ld\\'\"' in toolchain\n\n\ndef test_not_none_values():\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.gnu import AutotoolsToolchain\n\n        class Foo(ConanFile):\n            name = \"foo\"\n            version = \"1.0\"\n\n            def generate(self):\n                tc = AutotoolsToolchain(self)\n                assert None not in tc.defines\n                assert None not in tc.cxxflags\n                assert None not in tc.cflags\n                assert None not in tc.ldflags\n\n    \"\"\")\n\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"install .\")\n\n\ndef test_set_prefix():\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.gnu import AutotoolsToolchain\n        from conan.tools.layout import basic_layout\n\n\n        class Foo(ConanFile):\n            name = \"foo\"\n            version = \"1.0\"\n            def layout(self):\n                basic_layout(self)\n            def generate(self):\n                at_toolchain = AutotoolsToolchain(self, prefix=\"/somefolder\")\n                at_toolchain.generate()\n    \"\"\")\n\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"install .\")\n    conanbuild = client.load(os.path.join(client.current_folder, \"build\", \"conan\", \"conanbuild.conf\"))\n    assert \"--prefix=/somefolder\" in conanbuild\n    assert conanbuild.count(\"--prefix\") == 1\n\n\ndef test_unknown_compiler():\n    client = TestClient()\n    save(client.paths.settings_path_user, \"compiler:\\n  xlc:\\n\")\n    client.save({\"conanfile.py\": GenConanfile().with_settings(\"compiler\", \"build_type\")\n                                               .with_generator(\"AutotoolsToolchain\")})\n    # this used to crash, because of build_type_flags in AutotoolsToolchain returning empty string\n    client.run(\"install . -s compiler=xlc\")\n    assert \"conanfile.py: Generator 'AutotoolsToolchain' calling 'generate()'\" in client.out\n\n\ndef test_toolchain_and_compilers_build_context():\n    \"\"\"\n    Tests how AutotoolsToolchain manages the build context profile if the build profile is\n    specifying another compiler path (using conf)\n\n    Issue related: https://github.com/conan-io/conan/issues/15878\n    \"\"\"\n    host = textwrap.dedent(\"\"\"\n    [settings]\n    arch=armv8\n    build_type=Release\n    compiler=gcc\n    compiler.cppstd=gnu17\n    compiler.libcxx=libstdc++11\n    compiler.version=11\n    os=Linux\n\n    [conf]\n    tools.build:compiler_executables={\"c\": \"gcc\", \"cpp\": \"g++\", \"rc\": \"windres\"}\n    \"\"\")\n    build = textwrap.dedent(\"\"\"\n    [settings]\n    os=Linux\n    arch=x86_64\n    compiler=clang\n    compiler.version=12\n    compiler.libcxx=libc++\n    compiler.cppstd=11\n\n    [conf]\n    tools.build:compiler_executables={\"c\": \"clang\", \"cpp\": \"clang++\"}\n    \"\"\")\n    tool = textwrap.dedent(\"\"\"\n    import os\n    from conan import ConanFile\n    from conan.tools.files import load\n\n    class toolRecipe(ConanFile):\n        name = \"tool\"\n        version = \"1.0\"\n        # Binary configuration\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n        generators = \"AutotoolsToolchain\"\n\n        def build(self):\n            toolchain = os.path.join(self.generators_folder, \"conanautotoolstoolchain.sh\")\n            content = load(self, toolchain)\n            assert 'export CC=\"clang\"' in content\n            assert 'export CXX=\"clang++\"' in content\n    \"\"\")\n    consumer = textwrap.dedent(\"\"\"\n    import os\n    from conan import ConanFile\n    from conan.tools.files import load\n\n    class consumerRecipe(ConanFile):\n        name = \"consumer\"\n        version = \"1.0\"\n        # Binary configuration\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n        generators = \"AutotoolsToolchain\"\n        tool_requires = \"tool/1.0\"\n\n        def build(self):\n            toolchain = os.path.join(self.generators_folder, \"conanautotoolstoolchain.sh\")\n            content = load(self, toolchain)\n            assert 'export CC=\"gcc\"' in content\n            assert 'export CXX=\"g++\"' in content\n            assert 'export RC=\"windres\"' in content\n            # Issue: https://github.com/conan-io/conan/issues/15486\n            assert 'export CC_FOR_BUILD=\"clang\"' in content\n            assert 'export CXX_FOR_BUILD=\"clang++\"' in content\n    \"\"\")\n    client = TestClient()\n    client.save({\n        \"host\": host,\n        \"build\": build,\n        \"tool/conanfile.py\": tool,\n        \"consumer/conanfile.py\": consumer\n    })\n    client.run(\"export tool\")\n    client.run(\"create consumer -pr:h host -pr:b build --build=missing\")\n\n\ndef test_toolchain_crossbuild_to_android():\n    \"\"\"\n    Issue related: https://github.com/conan-io/conan/issues/17441\n    \"\"\"\n    build = textwrap.dedent(\"\"\"\n    [settings]\n    arch=armv8\n    build_type=Release\n    compiler=gcc\n    compiler.cppstd=gnu17\n    compiler.libcxx=libstdc++11\n    compiler.version=11\n    os=Linux\n    \"\"\")\n    host = textwrap.dedent(\"\"\"\n    [settings]\n    os = Android\n    os.api_level = 21\n    arch=x86_64\n    compiler=clang\n    compiler.version=12\n    compiler.libcxx=libc++\n    compiler.cppstd=11\n\n    [buildenv]\n    CC=clang\n    CXX=clang++\n\n    [conf]\n    tools.android:ndk_path=/path/to/ndk\n    \"\"\")\n    consumer = textwrap.dedent(\"\"\"\n    import os\n    from conan import ConanFile\n    from conan.tools.files import load\n\n    class consumerRecipe(ConanFile):\n        name = \"consumer\"\n        version = \"1.0\"\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n        generators = \"AutotoolsToolchain\"\n\n        def build(self):\n            toolchain = os.path.join(self.generators_folder, \"conanautotoolstoolchain.sh\")\n            content = load(self, toolchain)\n            assert 'export CC=\"clang\"' not in content\n            assert 'export CXX=\"clang++\"' not in content\n            assert 'export LD=\"/path/to/ndk' in content\n\n            build_env = os.path.join(self.generators_folder, \"conanbuildenv-x86_64.sh\")\n            content = load(self, build_env)\n            assert 'export CC=\"clang\"' in content\n            assert 'export CXX=\"clang++\"' in content\n            assert 'export LD=' not in content\n    \"\"\")\n    client = TestClient()\n    client.save({\n        \"host\": host,\n        \"build\": build,\n        \"conanfile.py\": consumer\n    })\n    client.run(\"create . -pr:h host -pr:b build\")\n\n\ndef test_conf_build_does_not_exist():\n    host = textwrap.dedent(\"\"\"\n    [settings]\n    arch=x86_64\n    os=Linux\n    [conf]\n    tools.build:compiler_executables={'c': '/usr/bin/gcc', 'cpp': '/usr/bin/g++'}\n    \"\"\")\n    build = textwrap.dedent(\"\"\"\n    [settings]\n    arch=armv8\n    os=Linux\n    [conf]\n    tools.build:compiler_executables={'c': 'x86_64-linux-gnu-gcc', 'cpp': 'x86_64-linux-gnu-g++'}\n    \"\"\")\n    c = TestClient()\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\"),\n            \"host\": host,\n            \"build\": build})\n    c.run(\"export .\")\n    c.run(\"install --requires=pkg/0.1 --build=pkg/0.1 -g AutotoolsToolchain -pr:h host -pr:b build\")\n    tc = c.load(\"conanautotoolstoolchain.sh\")\n    assert 'export CC_FOR_BUILD=\"x86_64-linux-gnu-gcc\"' in tc\n    assert 'export CXX_FOR_BUILD=\"x86_64-linux-gnu-g++\"' in tc\n\n\n@pytest.mark.parametrize(\n    \"threads, flags\",\n    [(\"posix\", \"-pthread\"), (\"wasm_workers\", \"-sWASM_WORKERS=1\")],\n)\ndef test_thread_flags(threads, flags):\n    is_win = platform.system() == \"Windows\"\n    client = TestClient()\n    profile = textwrap.dedent(f\"\"\"\n        [settings]\n        arch=wasm\n        build_type=Release\n        compiler=emcc\n        compiler.cppstd=17\n        compiler.threads={threads}\n        compiler.libcxx=libc++\n        compiler.version=4.0.10\n        os=Emscripten\n        \"\"\")\n    client.save(\n        {\n            \"conanfile.py\": GenConanfile(\"pkg\", \"1.0\")\n            .with_settings(\"os\", \"arch\", \"compiler\", \"build_type\")\n            .with_generator(\"AutotoolsToolchain\"),\n            \"profile\": profile,\n        }\n    )\n    client.run(\"install . -pr=./profile\")\n    toolchain = client.load(\"conanautotoolstoolchain{}\".format('.bat' if is_win else '.sh'))\n    if is_win:\n        assert f'set \"CXXFLAGS=%CXXFLAGS% -stdlib=libc++ {flags}\"' in toolchain\n        assert f'set \"CFLAGS=%CFLAGS% {flags}\"' in toolchain\n        assert f'set \"LDFLAGS=%LDFLAGS% {flags}' in toolchain\n    else:\n        assert f'export CXXFLAGS=\"${{CXXFLAGS:-}}${{CXXFLAGS:+ }}-stdlib=libc++ {flags}\"' in toolchain\n        assert f'export CFLAGS=\"${{CFLAGS:-}}${{CFLAGS:+ }}{flags}\"' in toolchain\n        assert f'export LDFLAGS=\"${{LDFLAGS:-}}${{LDFLAGS:+ }}{flags}\"' in toolchain\n"
  },
  {
    "path": "test/integration/toolchains/gnu/test_basic_layout.py",
    "content": "import os\nimport platform\nimport textwrap\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.parametrize(\"basic_layout, expected_path\", [\n    ('basic_layout(self)', 'build-release'),\n    ('basic_layout(self, build_folder=\"custom_build_folder\")', 'custom_build_folder')])\ndef test_basic_layout_subproject(basic_layout, expected_path):\n    c = TestClient()\n    conanfile = textwrap.dedent(f\"\"\"\n        from conan import ConanFile\n        from conan.tools.layout import basic_layout\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"AutotoolsToolchain\"\n            def layout(self):\n                self.folders.root = \"..\"\n                self.folders.subproject = \"pkg\"\n                {basic_layout}\n        \"\"\")\n    c.save({\"pkg/conanfile.py\": conanfile})\n    c.run(\"install pkg\")\n    ext = \"sh\" if platform.system() != \"Windows\" else \"bat\"\n    assert os.path.isfile(os.path.join(c.current_folder, \"pkg\", expected_path, \"conan\",\n                                       \"conanautotoolstoolchain.{}\".format(ext)))\n\n\ndef test_editable_includes():\n    c = TestClient()\n    dep = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.layout import basic_layout\n\n        class Dep(ConanFile):\n            name = \"dep\"\n            version = \"0.1\"\n            def layout(self):\n                basic_layout(self, src_folder=\"src\")\n            \"\"\")\n    c.save({\"dep/conanfile.py\": dep,\n            \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_settings(\"build_type\", \"arch\")\n                                                          .with_requires(\"dep/0.1\")})\n    c.run(\"editable add dep\")\n    c.run(\"install pkg -s arch=x86_64 -g CMakeDeps -g PkgConfigDeps -g XcodeDeps\")\n    data = c.load(f\"pkg/dep-release-x86_64-data.cmake\")\n    assert 'set(dep_INCLUDE_DIRS_RELEASE \"${dep_PACKAGE_FOLDER_RELEASE}/src/include\")' in data\n    pc = c.load(\"pkg/dep.pc\")\n    assert \"includedir=${prefix}/src/include\" in pc\n    xcode = c.load(\"pkg/conan_dep_dep_release_x86_64.xcconfig\")\n    dep_path = os.path.join(c.current_folder, \"dep\", \"src\", \"include\")\n    assert f\"SYSTEM_HEADER_SEARCH_PATHS_dep_dep[config=Release][arch=x86_64][sdk=*] = \\\"{dep_path}\\\"\" in xcode\n\n\ndef test_editable_includes_previously_defined():\n    # if someone already defined self.cpp.source.includedirs make sure we don't overwrite\n    # their value\n    c = TestClient()\n    dep = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.layout import basic_layout\n\n        class Dep(ConanFile):\n            name = \"dep\"\n            version = \"0.1\"\n            def layout(self):\n                self.cpp.source.includedirs = [\"somefolder\"]\n                basic_layout(self, src_folder=\"src\")\n            \"\"\")\n    c.save({\"dep/conanfile.py\": dep,\n            \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_settings(\"build_type\", \"arch\")\n                                                          .with_requires(\"dep/0.1\")})\n    c.run(\"editable add dep\")\n    c.run(\"install pkg -s arch=x86_64 -g CMakeDeps -g PkgConfigDeps -g XcodeDeps\")\n    data = c.load(f\"pkg/dep-release-x86_64-data.cmake\")\n    assert 'set(dep_INCLUDE_DIRS_RELEASE \"${dep_PACKAGE_FOLDER_RELEASE}/src/somefolder\")' in data\n    pc = c.load(\"pkg/dep.pc\")\n    assert \"includedir=${prefix}/src/somefolder\" in pc\n    xcode = c.load(\"pkg/conan_dep_dep_release_x86_64.xcconfig\")\n    dep_path = os.path.join(c.current_folder, \"dep\", \"src\", \"somefolder\")\n    assert f\"SYSTEM_HEADER_SEARCH_PATHS_dep_dep[config=Release][arch=x86_64][sdk=*] = \\\"{dep_path}\\\"\" in xcode\n"
  },
  {
    "path": "test/integration/toolchains/gnu/test_gnutoolchain.py",
    "content": "import os\nimport platform\nimport textwrap\nimport re\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import save, load\n\n\n@pytest.mark.parametrize(\"os_\", [\"Macos\", \"Linux\", \"Windows\"])\ndef test_extra_flags_via_conf(os_):\n    os_sdk = \"tools.apple:sdk_path=/my/sdk/path\" if os_ == \"Macos\" else \"\"\n    profile = textwrap.dedent(f\"\"\"\n        [settings]\n        os={os_}\n        compiler=gcc\n        compiler.version=6\n        compiler.libcxx=libstdc++11\n        arch=armv8\n        build_type=Release\n\n        [conf]\n        tools.build:cxxflags=[\"--flag1\", \"--flag2\"]\n        tools.build:cflags+=[\"--flag3\", \"--flag4\"]\n        tools.build:sharedlinkflags+=[\"--flag5\"]\n        tools.build:exelinkflags+=[\"--flag6\"]\n        tools.build:defines+=[\"DEF1\", \"DEF2\"]\n        {os_sdk}\n        \"\"\")\n    client = TestClient()\n    conanfile = GenConanfile().with_settings(\"os\", \"arch\", \"compiler\", \"build_type\") \\\n        .with_generator(\"GnuToolchain\")\n    client.save({\"conanfile.py\": conanfile,\n                 \"profile\": profile})\n    client.run(\"install . --profile:build=profile --profile:host=profile\")\n    toolchain = client.load(\n        \"conangnutoolchain{}\".format('.bat' if os_ == \"Windows\" else '.sh'))\n    if os_ == \"Windows\":\n        assert 'set \"CPPFLAGS=%CPPFLAGS% -DNDEBUG -DDEF1 -DDEF2\"' in toolchain\n        assert 'set \"CXXFLAGS=%CXXFLAGS% -O3 --flag1 --flag2\"' in toolchain\n        assert 'set \"CFLAGS=%CFLAGS% -O3 --flag3 --flag4\"' in toolchain\n        assert 'set \"LDFLAGS=%LDFLAGS% --flag5 --flag6\"' in toolchain\n        assert f'set \"PKG_CONFIG_PATH={client.current_folder};%PKG_CONFIG_PATH%\"' in toolchain\n    else:\n        assert os_ in (\"Linux\", \"Macos\")\n        assert 'export CPPFLAGS=\"${CPPFLAGS:-}${CPPFLAGS:+ }-DNDEBUG -DDEF1 -DDEF2\"' in toolchain\n        assert 'export CXXFLAGS=\"${CXXFLAGS:-}${CXXFLAGS:+ }-O3 --flag1 --flag2\"' in toolchain\n        assert 'export CFLAGS=\"${CFLAGS:-}${CFLAGS:+ }-O3 --flag3 --flag4\"' in toolchain\n        assert 'export LDFLAGS=\"${LDFLAGS:-}${LDFLAGS:+ }--flag5 --flag6\"' in toolchain\n        assert (f'export PKG_CONFIG_PATH=\"{client.current_folder}'\n                f'${{PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}}\"') in toolchain\n\n\ndef test_extra_flags_order():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.gnu import GnuToolchain\n\n        class Conan(ConanFile):\n            name = \"pkg\"\n            version = \"0.1\"\n            settings = \"os\", \"arch\", \"build_type\"\n            def generate(self):\n                at = GnuToolchain(self)\n                at.extra_cxxflags = [\"extra_cxxflags\"]\n                at.extra_cflags = [\"extra_cflags\"]\n                at.extra_ldflags = [\"extra_ldflags\"]\n                at.extra_defines = [\"extra_defines\"]\n                at.generate()\n        \"\"\")\n    profile = textwrap.dedent(\"\"\"\n        include(default)\n        [conf]\n        tools.build:cxxflags+=['cxxflags']\n        tools.build:cflags+=['cflags']\n        tools.build:sharedlinkflags+=['sharedlinkflags']\n        tools.build:exelinkflags+=['exelinkflags']\n        tools.build:defines+=['defines']\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile, \"profile\": profile})\n    client.run('install . -pr=./profile')\n    toolchain = client.load(\n        \"conangnutoolchain{}\".format('.bat' if platform.system() == \"Windows\" else '.sh'))\n\n    assert '-Dextra_defines -Ddefines' in toolchain\n    assert 'extra_cxxflags cxxflags' in toolchain\n    assert 'extra_cflags cflags' in toolchain\n    assert 'extra_ldflags sharedlinkflags exelinkflags' in toolchain\n\n\ndef test_gnutoolchain_rcflags():\n    \"\"\"Test that tools.build:rcflags is applied to RCFLAGS in the generated script.\"\"\"\n    profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=Linux\n        arch=x86_64\n        compiler=gcc\n        compiler.version=6\n        compiler.libcxx=libstdc++11\n        build_type=Release\n\n        [conf]\n        tools.build:rcflags=[\"--rcflag1\", \"--rcflag2\"]\n        \"\"\")\n    client = TestClient()\n    conanfile = (GenConanfile().with_settings(\"os\", \"arch\", \"compiler\", \"build_type\")\n                 .with_generator(\"GnuToolchain\"))\n    client.save({\"conanfile.py\": conanfile, \"profile\": profile})\n    client.run(\"install . --profile:build=profile --profile:host=profile\")\n    toolchain = client.load(\"conangnutoolchain.sh\")\n    assert \"RCFLAGS\" in toolchain\n    assert \"--rcflag1\" in toolchain\n    assert \"--rcflag2\" in toolchain\n\n\ndef test_autotools_custom_environment():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.gnu import GnuToolchain\n\n            class Conan(ConanFile):\n                settings = \"os\"\n                def generate(self):\n                    at = GnuToolchain(self)\n                    env = at.extra_env\n                    env.define(\"FOO\", \"BAR\")\n                    at.generate()\n            \"\"\")\n\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"install . -s:b os=Linux -s:h os=Linux\")\n    content = load(os.path.join(client.current_folder, \"conangnutoolchain.sh\"))\n    assert 'export FOO=\"BAR\"' in content\n\n\n@pytest.mark.parametrize(\"os_\", [\"Linux\", \"Windows\"])\ndef test_linker_scripts_via_conf(os_):\n    profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=%s\n        compiler=gcc\n        compiler.version=6\n        compiler.libcxx=libstdc++11\n        arch=armv8\n        build_type=Release\n\n        [conf]\n\n        tools.build:sharedlinkflags+=[\"--flag5\"]\n        tools.build:exelinkflags+=[\"--flag6\"]\n        tools.build:linker_scripts+=[\"/linker/scripts/flash.ld\", \"/linker/scripts/extra_data.ld\"]\n        \"\"\" % os_)\n    client = TestClient()\n    conanfile = GenConanfile().with_settings(\"os\", \"arch\", \"compiler\", \"build_type\") \\\n        .with_generator(\"GnuToolchain\")\n    client.save({\"conanfile.py\": conanfile,\n                 \"profile\": profile})\n    client.run(\"install . --profile:build=profile --profile:host=profile\")\n    toolchain = client.load(\n        \"conangnutoolchain{}\".format('.bat' if os_ == \"Windows\" else '.sh'))\n    if os_ == \"Windows\":\n        assert 'set \"LDFLAGS=%LDFLAGS% --flag5 --flag6 -T\\'/linker/scripts/flash.ld\\' -T\\'/linker/scripts/extra_data.ld\\'\"' in toolchain\n    else:\n        assert 'export LDFLAGS=\"${LDFLAGS:-}${LDFLAGS:+ }--flag5 --flag6 -T\\'/linker/scripts/flash.ld\\' -T\\'/linker/scripts/extra_data.ld\\'\"' in toolchain\n\n\ndef test_not_none_values():\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.gnu import GnuToolchain\n\n        class Foo(ConanFile):\n            name = \"foo\"\n            version = \"1.0\"\n\n            def generate(self):\n                tc = GnuToolchain(self)\n                assert None not in tc.defines\n                assert None not in tc.cxxflags\n                assert None not in tc.cflags\n                assert None not in tc.ldflags\n\n    \"\"\")\n\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"install .\")\n\n\ndef test_set_prefix():\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.gnu import GnuToolchain\n        from conan.tools.layout import basic_layout\n\n\n        class Foo(ConanFile):\n            name = \"foo\"\n            version = \"1.0\"\n            def layout(self):\n                basic_layout(self)\n            def generate(self):\n                at_toolchain = GnuToolchain(self, prefix=\"/somefolder\")\n                at_toolchain.generate()\n    \"\"\")\n\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"install .\")\n    conanbuild = client.load(\n        os.path.join(client.current_folder, \"build\", \"conan\", \"conanbuild.conf\"))\n    assert \"--prefix=/somefolder\" in conanbuild\n    assert conanbuild.count(\"--prefix\") == 1\n\n\ndef test_unknown_compiler():\n    client = TestClient()\n    save(client.paths.settings_path_user, \"compiler:\\n  xlc:\\n\")\n    client.save({\"conanfile.py\": GenConanfile().with_settings(\"compiler\", \"build_type\")\n                .with_generator(\"GnuToolchain\")\n                 })\n    # this used to crash, because of build_type_flags in GnuToolchain returning empty string\n    client.run(\"install . -s compiler=xlc\")\n    assert \"conanfile.py: Generator 'GnuToolchain' calling 'generate()'\" in client.out\n\n\ndef test_toolchain_and_compilers_build_context():\n    \"\"\"\n    Tests how GnuToolchain manages the build context profile if the build profile is\n    specifying another compiler path (using conf)\n\n    Issue related: https://github.com/conan-io/conan/issues/15878\n    \"\"\"\n    host = textwrap.dedent(\"\"\"\n    [settings]\n    arch=armv8\n    build_type=Release\n    compiler=gcc\n    compiler.cppstd=gnu17\n    compiler.libcxx=libstdc++11\n    compiler.version=11\n    os=Linux\n\n    [conf]\n    tools.build:compiler_executables={\"c\": \"gcc\", \"cpp\": \"g++\", \"rc\": \"windres\"}\n    \"\"\")\n    build = textwrap.dedent(\"\"\"\n    [settings]\n    os=Linux\n    arch=x86_64\n    compiler=clang\n    compiler.version=12\n    compiler.libcxx=libc++\n    compiler.cppstd=11\n\n    [conf]\n    tools.build:compiler_executables={\"c\": \"clang\", \"cpp\": \"clang++\"}\n    \"\"\")\n    tool = textwrap.dedent(\"\"\"\n    import os\n    from conan import ConanFile\n    from conan.tools.files import load\n\n    class toolRecipe(ConanFile):\n        name = \"tool\"\n        version = \"1.0\"\n        # Binary configuration\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n        generators = \"GnuToolchain\"\n\n        def build(self):\n            toolchain = os.path.join(self.generators_folder, \"conangnutoolchain.sh\")\n            content = load(self, toolchain)\n            assert 'export CC=\"clang\"' in content\n            assert 'export CXX=\"clang++\"' in content\n    \"\"\")\n    consumer = textwrap.dedent(\"\"\"\n    import os\n    from conan import ConanFile\n    from conan.tools.files import load\n\n    class consumerRecipe(ConanFile):\n        name = \"consumer\"\n        version = \"1.0\"\n        # Binary configuration\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n        generators = \"GnuToolchain\"\n        tool_requires = \"tool/1.0\"\n\n        def build(self):\n            toolchain = os.path.join(self.generators_folder, \"conangnutoolchain.sh\")\n            content = load(self, toolchain)\n            assert 'export CC=\"gcc\"' in content\n            assert 'export CXX=\"g++\"' in content\n            assert 'export RC=\"windres\"' in content\n            # Issue: https://github.com/conan-io/conan/issues/15486\n            assert 'export CC_FOR_BUILD=\"clang\"' in content\n            assert 'export CXX_FOR_BUILD=\"clang++\"' in content\n    \"\"\")\n    client = TestClient()\n    client.save({\n        \"host\": host,\n        \"build\": build,\n        \"tool/conanfile.py\": tool,\n        \"consumer/conanfile.py\": consumer\n    })\n    client.run(\"export tool\")\n    client.run(\"create consumer -pr:h host -pr:b build --build=missing\")\n\n\ndef test_autotools_crossbuild_ux():\n    client = TestClient()\n    profile_build = textwrap.dedent(\"\"\"\n        [settings]\n        os = Macos\n        os.version=10.11\n        arch = armv7\n        compiler = apple-clang\n        compiler.version = 12.0\n        compiler.libcxx = libc++\n        \"\"\")\n    profile_host = textwrap.dedent(\"\"\"\n        [settings]\n        arch=x86_64\n        build_type=Release\n        compiler=apple-clang\n        compiler.cppstd=gnu17\n        compiler.libcxx=libc++\n        compiler.version=15\n        os=Macos\n        [conf]\n        tools.apple:sdk_path=/my/sdk/path\n        \"\"\")\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    from conan.tools.gnu import GnuToolchain\n    from conan.tools.build import cross_building\n    class Pkg(ConanFile):\n        settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n        def generate(self):\n            tc = GnuToolchain(self)\n            if cross_building(self):\n                host_arch = tc.triplets_info[\"host\"][\"machine\"]\n                build_arch = tc.triplets_info[\"build\"][\"machine\"]\n                if host_arch and build_arch:\n                    tc.configure_args[\"--host\"] = f\"{host_arch}-my-triplet-host\"\n                    tc.configure_args[\"--build\"] = f\"{build_arch}-my-triplet-build\"\n            tc.generate()\n            \"\"\")\n\n    client.save({\"conanfile.py\": conanfile,\n                 \"profile_build\": profile_build,\n                 \"profile_host\": profile_host})\n    client.run(\"install . --profile:build=profile_build --profile:host=profile_host\")\n    conanbuild = client.load(\"conanbuild.conf\")\n    host_flags = re.findall(r\"--host=[\\w-]*\\b\", conanbuild)\n    build_flags = re.findall(r\"--build=[\\w-]*\\b\", conanbuild)\n    assert len(host_flags) == 1\n    assert len(build_flags) == 1\n    assert host_flags[0] == '--host=x86_64-my-triplet-host'\n    assert build_flags[0] == '--build=arm-my-triplet-build'\n\n\ndef test_msvc_profile_defaults():\n    \"\"\"\n    Tests how GnuToolchain manages MSVC profile and its default env variables.\n    \"\"\"\n    profile = textwrap.dedent(\"\"\"\\\n    [settings]\n    os=Windows\n    arch=x86_64\n    compiler=msvc\n    compiler.version=191\n    compiler.runtime=dynamic\n    build_type=Release\n\n    [conf]\n    tools.build:compiler_executables={\"c\": \"clang\", \"cpp\": \"clang++\"}\n    # Fake installation path\n    tools.microsoft.msbuild:installation_path={{os.getcwd()}}\n    \"\"\")\n    # Consumer with default values\n    consumer = textwrap.dedent(\"\"\"\\\n    import os\n    from conan import ConanFile\n    from conan.tools.files import load\n\n    class consumerRecipe(ConanFile):\n        name = \"consumer\"\n        version = \"1.0\"\n        # Binary configuration\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n        generators = \"GnuToolchain\"\n\n        def build(self):\n            toolchain = os.path.join(self.generators_folder, \"conangnutoolchain.bat\")\n            content = load(self, toolchain)\n            # Default values and conf ones\n            assert r'set \"CC=clang\"' in content  # conf value has precedence\n            assert r'set \"CXX=clang++\"' in content  # conf value has precedence\n            assert 'set \"NM=dumpbin -symbols\"' in content\n            assert 'set \"OBJDUMP=:\"' in content\n            assert 'set \"RANLIB=:\"' in content\n            assert 'set \"STRIP=:\"' in content\n    \"\"\")\n    client = TestClient()\n    client.save({\n        \"profile\": profile,\n        \"consumer/conanfile.py\": consumer\n    })\n    client.run(\"create consumer -pr:a profile --build=missing\")\n    # Consumer changing default values\n    consumer = textwrap.dedent(\"\"\"\\\n    import os\n    from conan import ConanFile\n    from conan.tools.files import load\n    from conan.tools.gnu import GnuToolchain\n\n    class consumerRecipe(ConanFile):\n        name = \"consumer\"\n        version = \"1.0\"\n        # Binary configuration\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n        def generate(self):\n            tc = GnuToolchain(self)\n            # Prepending compiler wrappers\n            tc.extra_env.prepend(\"CC\", \"compile\")\n            tc.extra_env.prepend(\"CXX\", \"compile\")\n            tc.extra_env.define(\"OBJDUMP\", \"other-value\")\n            tc.extra_env.unset(\"RANLIB\")\n            tc.generate()\n\n        def build(self):\n            toolchain = os.path.join(self.generators_folder, \"conangnutoolchain.bat\")\n            content = load(self, toolchain)\n            # Default values\n            assert r'set \"CC=compile clang\"' in content\n            assert r'set \"CXX=compile clang++\"' in content\n            assert 'set \"NM=dumpbin -symbols\"' in content\n            assert 'set \"OBJDUMP=other-value\"' in content  # redefined\n            assert 'set \"RANLIB=:\"' not in content  # removed\n            assert 'set \"STRIP=:\"' in content\n    \"\"\")\n    client.save({\n        \"consumer/conanfile.py\": consumer\n    })\n    client.run(\"create consumer -pr:a profile --build=missing\")\n\n\ndef test_conf_build_does_not_exist():\n    host = textwrap.dedent(\"\"\"\n    [settings]\n    arch=x86_64\n    os=Linux\n    [conf]\n    tools.build:compiler_executables={'c': '/usr/bin/gcc', 'cpp': '/usr/bin/g++'}\n    \"\"\")\n    build = textwrap.dedent(\"\"\"\n    [settings]\n    arch=armv8\n    os=Linux\n    [conf]\n    tools.build:compiler_executables={'c': 'x86_64-linux-gnu-gcc', 'cpp': 'x86_64-linux-gnu-g++'}\n    \"\"\")\n    c = TestClient()\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\"),\n            \"host\": host,\n            \"build\": build})\n    c.run(\"export .\")\n    c.run(\"install --requires=pkg/0.1 --build=pkg/0.1 -g GnuToolchain -pr:h host -pr:b build\")\n    tc = c.load(\"conangnutoolchain.sh\")\n    assert 'export CC_FOR_BUILD=\"x86_64-linux-gnu-gcc\"' in tc\n    assert 'export CXX_FOR_BUILD=\"x86_64-linux-gnu-g++\"' in tc\n\n\n@pytest.mark.parametrize(\"toolchain\", [\"GnuToolchain\", \"AutotoolsToolchain\"])\ndef test_conf_extra_apple_flags(toolchain):\n    host = textwrap.dedent(\"\"\"\n    [settings]\n    arch=x86_64\n    os=Macos\n    [conf]\n    tools.apple:enable_bitcode = True\n    tools.apple:enable_arc = True\n    tools.apple:enable_visibility = True\n    \"\"\")\n\n    c = TestClient()\n    c.save({\"conanfile.txt\": f\"[generators]\\n{toolchain}\",\n            \"host\": host})\n    c.run(\"install . -pr:a host\")\n    f = \"conanautotoolstoolchain.sh\" if toolchain == \"AutotoolsToolchain\" else \"conangnutoolchain.sh\"\n    tc = c.load(f)\n    assert 'export CXXFLAGS=\"${CXXFLAGS:-}${CXXFLAGS:+ }-fembed-bitcode -fvisibility=default\"' in tc\n    assert 'export CFLAGS=\"${CFLAGS:-}${CFLAGS:+ }-fembed-bitcode -fvisibility=default\"' in tc\n    assert 'export LDFLAGS=\"${LDFLAGS:-}${LDFLAGS:+ }-fembed-bitcode -fvisibility=default\"' in tc\n    assert 'export OBJCFLAGS=\"${OBJCFLAGS:-}${OBJCFLAGS:+ }-fobjc-arc\"' in tc\n    assert 'export OBJCXXFLAGS=\"${OBJCXXFLAGS:-}${OBJCXXFLAGS:+ }-fobjc-arc\"' in tc\n\n    c.run(\"install . -pr:a host -s build_type=Debug\")\n    tc = c.load(f)\n    assert 'export CXXFLAGS=\"${CXXFLAGS:-}${CXXFLAGS:+ }-fembed-bitcode-marker -fvisibility=default\"' in tc\n    assert 'export CFLAGS=\"${CFLAGS:-}${CFLAGS:+ }-fembed-bitcode-marker -fvisibility=default\"' in tc\n    assert 'export LDFLAGS=\"${LDFLAGS:-}${LDFLAGS:+ }-fembed-bitcode-marker -fvisibility=default\"' in tc\n    assert 'export OBJCFLAGS=\"${OBJCFLAGS:-}${OBJCFLAGS:+ }-fobjc-arc\"' in tc\n    assert 'export OBJCXXFLAGS=\"${OBJCXXFLAGS:-}${OBJCXXFLAGS:+ }-fobjc-arc\"' in tc\n\n    host = textwrap.dedent(\"\"\"\n        [settings]\n        arch=x86_64\n        os=Macos\n        [conf]\n        tools.apple:enable_bitcode = False\n        tools.apple:enable_arc = False\n        tools.apple:enable_visibility = False\n        \"\"\")\n\n    c.save({\"host\": host})\n    c.run(\"install . -pr:a host\")\n    tc = c.load(f)\n    assert 'CXXFLAGS=\"${CXXFLAGS:-}${CXXFLAGS:+ }-fvisibility=hidden -fvisibility-inlines-hidden\"' in tc\n    assert 'CFLAGS=\"${CFLAGS:-}${CFLAGS:+ }-fvisibility=hidden -fvisibility-inlines-hidden\"' in tc\n    assert 'LDFLAGS=\"${LDFLAGS:-}${LDFLAGS:+ }-fvisibility=hidden -fvisibility-inlines-hidden\"' in tc\n    assert 'export OBJCFLAGS=\"${OBJCFLAGS:-}${OBJCFLAGS:+ }-fno-objc-arc\"' in tc\n    assert 'export OBJCXXFLAGS=\"${OBJCXXFLAGS:-}${OBJCXXFLAGS:+ }-fno-objc-arc\"' in tc\n\n\ndef test_toolchain_crossbuild_to_android():\n    \"\"\"\n    Issue related: https://github.com/conan-io/conan/issues/17441\n    \"\"\"\n    build = textwrap.dedent(\"\"\"\n    [settings]\n    arch=armv8\n    build_type=Release\n    compiler=gcc\n    compiler.cppstd=gnu17\n    compiler.libcxx=libstdc++11\n    compiler.version=11\n    os=Linux\n    \"\"\")\n    host = textwrap.dedent(\"\"\"\n    [settings]\n    os = Android\n    os.api_level = 21\n    arch=x86_64\n    compiler=clang\n    compiler.version=12\n    compiler.libcxx=libc++\n    compiler.cppstd=11\n\n    [buildenv]\n    CC=clang\n    CXX=clang++\n\n    [conf]\n    tools.android:ndk_path=/path/to/ndk\n    \"\"\")\n    consumer = textwrap.dedent(\"\"\"\n    import os\n    from conan import ConanFile\n    from conan.tools.files import load\n\n    class consumerRecipe(ConanFile):\n        name = \"consumer\"\n        version = \"1.0\"\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n        generators = \"GnuToolchain\"\n\n        def build(self):\n            toolchain = os.path.join(self.generators_folder, \"conangnutoolchain.sh\")\n            content = load(self, toolchain)\n            assert 'export CC=\"clang\"' not in content\n            assert 'export CXX=\"clang++\"' not in content\n            assert 'export LD=\"/path/to/ndk' in content\n            assert 'export STRIP=\"/path/to/ndk' in content\n            assert 'export RANLIB=\"/path/to/ndk' in content\n            assert 'export AS=\"/path/to/ndk' in content\n            assert 'export AR=\"/path/to/ndk' in content\n            assert 'export ADDR2LINE=\"/path/to/ndk' in content\n            assert 'export NM=\"/path/to/ndk' in content\n            assert 'export OBJCOPY=\"/path/to/ndk' in content\n            assert 'export OBJDUMP=\"/path/to/ndk' in content\n            assert 'export READELF=\"/path/to/ndk' in content\n            assert 'export ELFEDIT=\"/path/to/ndk' in content\n\n            build_env = os.path.join(self.generators_folder, \"conanbuildenv-x86_64.sh\")\n            content = load(self, build_env)\n            assert 'export CC=\"clang\"' in content\n            assert 'export CXX=\"clang++\"' in content\n            assert 'export LD=' not in content\n            assert 'export STRIP=\"/path/to/ndk' not in content\n            assert 'export RANLIB=\"/path/to/ndk' not in content\n            assert 'export AS=\"/path/to/ndk' not in content\n            assert 'export AR=\"/path/to/ndk' not in content\n            assert 'export ADDR2LINE=\"/path/to/ndk' not in content\n            assert 'export NM=\"/path/to/ndk' not in content\n            assert 'export OBJCOPY=\"/path/to/ndk' not in content\n            assert 'export OBJDUMP=\"/path/to/ndk' not in content\n            assert 'export READELF=\"/path/to/ndk' not in content\n            assert 'export ELFEDIT=\"/path/to/ndk' not in content\n    \"\"\")\n    client = TestClient()\n    client.save({\n        \"host\": host,\n        \"build\": build,\n        \"conanfile.py\": consumer\n    })\n    client.run(\"create . -pr:h host -pr:b build\")\n\n\n@pytest.mark.parametrize(\n    \"threads, flags\",\n    [(\"posix\", \"-pthread\"), (\"wasm_workers\", \"-sWASM_WORKERS=1\")],\n)\ndef test_thread_flags(threads, flags):\n    client = TestClient()\n    profile = textwrap.dedent(f\"\"\"\n        [settings]\n        arch=wasm\n        build_type=Release\n        compiler=emcc\n        compiler.cppstd=17\n        compiler.threads={threads}\n        compiler.libcxx=libc++\n        compiler.version=4.0.10\n        os=Emscripten\n        \"\"\")\n    client.save(\n        {\n            \"conanfile.py\": GenConanfile(\"pkg\", \"1.0\")\n            .with_settings(\"os\", \"arch\", \"compiler\", \"build_type\")\n            .with_generator(\"GnuToolchain\"),\n            \"profile\": profile,\n        }\n    )\n    client.run(\"install . -pr=./profile\")\n    is_win = platform.system() == \"Windows\"\n    toolchain = client.load(\n        \"conangnutoolchain{}\".format('.bat' if is_win else '.sh'))\n\n    if is_win:\n        assert f'set \"CXXFLAGS=%CXXFLAGS% -stdlib=libc++ {flags}\"' in toolchain\n        assert f'set \"CFLAGS=%CFLAGS% {flags}\"' in toolchain\n        assert f'set \"LDFLAGS=%LDFLAGS% {flags}' in toolchain\n    else:\n        assert f'export CXXFLAGS=\"${{CXXFLAGS:-}}${{CXXFLAGS:+ }}-stdlib=libc++ {flags}\"' in toolchain\n        assert f'export CFLAGS=\"${{CFLAGS:-}}${{CFLAGS:+ }}{flags}\"' in toolchain\n        assert f'export LDFLAGS=\"${{LDFLAGS:-}}${{LDFLAGS:+ }}{flags}\"' in toolchain\n"
  },
  {
    "path": "test/integration/toolchains/gnu/test_makedeps.py",
    "content": "import platform\nimport pytest\nimport os\nimport textwrap\nimport pathlib\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\nfrom conan.tools.gnu.makedeps import CONAN_MAKEFILE_FILENAME\n\n\ndef test_make_dirs_with_abs_path():\n    \"\"\"\n    MakeDeps should support absolute paths when cppinfp\n    \"\"\"\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n\n        class TestMakeDirsConan(ConanFile):\n            name = \"mylib\"\n            version = \"0.1\"\n\n            def package_info(self):\n                self.cpp_info.frameworkdirs = []\n                libname = \"mylib\"\n                fake_dir = os.path.join(\"/\", \"my_absoulte_path\", \"fake\")\n                include_dir = os.path.join(fake_dir, libname, \"include\")\n                lib_dir = os.path.join(fake_dir, libname, \"lib\")\n                lib_dir2 = os.path.join(self.package_folder, \"lib2\")\n                self.cpp_info.includedirs = [include_dir]\n                self.cpp_info.libdirs = [lib_dir, lib_dir2]\n                self.cpp_info.set_property(\"my_prop\", \"my prop value\")\n                self.cpp_info.set_property(\"my_prop_with_newline\", \"my\\\\nprop\")\n        \"\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create .\")\n    client.run(\"install --requires=mylib/0.1@ -g MakeDeps\")\n\n    makefile_content = client.load(CONAN_MAKEFILE_FILENAME)\n    prefix = pathlib.Path(client.current_folder).drive if platform.system() == \"Windows\" else \"\"\n    assert 'CONAN_NAME_MYLIB = mylib' in makefile_content\n    assert 'CONAN_VERSION_MYLIB = 0.1' in makefile_content\n    assert f'CONAN_LIB_DIRS_MYLIB = \\\\\\n\\t$(CONAN_LIB_DIR_FLAG){prefix}/my_absoulte_path/fake/mylib/lib \\\\\\n\\t$(CONAN_LIB_DIR_FLAG)$(CONAN_ROOT_MYLIB)/lib2' in makefile_content\n    assert f'CONAN_INCLUDE_DIRS_MYLIB = $(CONAN_INCLUDE_DIR_FLAG){prefix}/my_absoulte_path/fake/mylib/include' in makefile_content\n    assert 'CONAN_BIN_DIRS_MYLIB = $(CONAN_BIN_DIR_FLAG)$(CONAN_ROOT_MYLIB)/bin' in makefile_content\n    assert 'CONAN_PROPERTY_MYLIB_MY_PROP = my prop value' in makefile_content\n    assert 'CONAN_PROPERTY_MYLIB_MY_PROP_WITH_NEWLINE' not in makefile_content\n    assert \"WARN: Skipping propery 'my_prop_with_newline' because it contains newline\" in client.stderr\n\n    lines = makefile_content.splitlines()\n    for line_no, line in enumerate(lines):\n        includedir_pattern = \"CONAN_INCLUDE_DIRS_MYLIB = $(CONAN_INCLUDE_DIR_FLAG)\"\n        if line.startswith(includedir_pattern):\n            assert os.path.isabs(line[len(includedir_pattern):])\n            assert line.endswith(\"include\")\n        elif line.startswith(\"\\t$(CONAN_LIB_DIR_FLAG)\") and 'my_absoulte_path' in line:\n            assert os.path.isabs(line[len(\"\\t$(CONAN_LIB_DIR_FLAG)\"):-2])\n            assert line.endswith(\"lib \\\\\")\n        elif line.startswith(\"\\t$(CONAN_LIB_DIR_FLAG)\") and line.endswith('lib2'):\n            assert \"\\t$(CONAN_LIB_DIR_FLAG)$(CONAN_ROOT_MYLIB)/lib2\" in line\n\n\ndef test_make_empty_dirs():\n    \"\"\"\n    MakeDeps should support cppinfo empty dirs\n    \"\"\"\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n\n        class TestMakeDepsConan(ConanFile):\n            name = \"mylib\"\n            version = \"0.1\"\n\n            def package_info(self):\n                self.cpp_info.includedirs = []\n                self.cpp_info.libdirs = []\n                self.cpp_info.bindirs = []\n                self.cpp_info.libs = []\n                self.cpp_info.frameworkdirs = []\n        \"\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create .\")\n    client.run(\"install --requires=mylib/0.1@ -g MakeDeps\")\n\n    makefile_content = client.load(CONAN_MAKEFILE_FILENAME)\n    assert 'CONAN_ROOT_MYLIB' in makefile_content\n    assert 'SYSROOT' not in makefile_content\n    assert 'CONAN_INCLUDE_DIRS' not in makefile_content\n    assert 'CONAN_LIB_DIRS' not in makefile_content\n    assert 'CONAN_BIN_DIRS' not in makefile_content\n    assert 'CONAN_LIBS' not in makefile_content\n    assert 'CONAN_FRAMEWORK_DIRS' not in makefile_content\n    assert 'CONAN_PROPERTY' not in makefile_content\n\n\ndef test_libs_and_system_libs():\n    \"\"\"\n    MakeDeps should support cppinfo system_libs with regular libs\n    \"\"\"\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import save\n        import os\n\n        class TestMakeDepsConan(ConanFile):\n            name = \"mylib\"\n            version = \"0.1\"\n\n            def package(self):\n                save(self, os.path.join(self.package_folder, \"lib\", \"file\"), \"\")\n\n            def package_info(self):\n                self.cpp_info.libs = [\"mylib1\", \"mylib2\"]\n                self.cpp_info.system_libs = [\"system_lib1\", \"system_lib2\"]\n        \"\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create .\")\n    client.run(\"install --requires=mylib/0.1@ -g MakeDeps\")\n\n    makefile_content = client.load(CONAN_MAKEFILE_FILENAME)\n    assert \"CONAN_LIBS_MYLIB = \\\\\\n\\t$(CONAN_LIB_FLAG)mylib1 \\\\\\n\\t$(CONAN_LIB_FLAG)mylib2\" in makefile_content\n    assert \"CONAN_SYSTEM_LIBS_MYLIB = \\\\\\n\\t$(CONAN_SYSTEM_LIB_FLAG)system_lib1 \\\\\\n\\t$(CONAN_SYSTEM_LIB_FLAG)system_lib2\" in makefile_content\n    assert \"CONAN_LIBS = $(CONAN_LIBS_MYLIB)\" in makefile_content\n    assert \"CONAN_SYSTEM_LIBS = $(CONAN_SYSTEM_LIBS_MYLIB)\" in makefile_content\n\n\ndef test_multiple_include_and_lib_dirs():\n    \"\"\"\n    MakeDeps should support cppinfo multiple include directories\n    \"\"\"\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import save\n        import os\n\n        class TestMakeDepsConan(ConanFile):\n            def package(self):\n                for p in [\"inc1\", \"inc2\", \"inc3/foo\", \"lib1\", \"lib2\"]:\n                    save(self, os.path.join(self.package_folder, p, \"file\"), \"\")\n\n            def package_info(self):\n                self.cpp_info.includedirs = [\"inc1\", \"inc2\", \"inc3/foo\"]\n                self.cpp_info.libdirs = [\"lib1\", \"lib2\"]\n        \"\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=pkg --version=0.1\")\n    client.run(\"install --requires=pkg/0.1@ -g MakeDeps\")\n\n    makefile_content = client.load(CONAN_MAKEFILE_FILENAME)\n    assert \"CONAN_INCLUDE_DIRS_PKG = \\\\\\n\" \\\n           \"\\t$(CONAN_INCLUDE_DIR_FLAG)$(CONAN_ROOT_PKG)/inc1 \\\\\\n\" \\\n           \"\\t$(CONAN_INCLUDE_DIR_FLAG)$(CONAN_ROOT_PKG)/inc2 \\\\\\n\" \\\n           \"\\t$(CONAN_INCLUDE_DIR_FLAG)$(CONAN_ROOT_PKG)/inc3/foo\\n\" in makefile_content\n    assert \"CONAN_LIB_DIRS_PKG = \\\\\\n\" \\\n           \"\\t$(CONAN_LIB_DIR_FLAG)$(CONAN_ROOT_PKG)/lib1 \\\\\\n\" \\\n           \"\\t$(CONAN_LIB_DIR_FLAG)$(CONAN_ROOT_PKG)/lib2\\n\" in makefile_content\n    assert \"CONAN_INCLUDE_DIRS = $(CONAN_INCLUDE_DIRS_PKG)\\n\" in makefile_content\n    assert \"CONAN_LIB_DIRS = $(CONAN_LIB_DIRS_PKG)\\n\" in makefile_content\n\n\ndef test_make_with_public_deps_and_component_requires():\n    \"\"\"\n    Testing a complex structure like:\n\n    * lib/0.1\n        - Components: \"cmp1\"\n    * other/0.1\n    * second/0.1\n        - Requires: \"lib/0.1\"\n        - Components: \"mycomponent\", \"myfirstcomp\"\n            + \"mycomponent\" requires \"lib::cmp1\"\n            + \"myfirstcomp\" requires \"mycomponent\"\n    * third/0.1\n        - Requires: \"second/0.1\", \"other/0.1\"\n    \"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Recipe(ConanFile):\n\n            def package_info(self):\n                self.cpp_info.components[\"cmp1\"].libs = [\"libcmp1\"]\n    \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=lib --version=0.1\")\n    client.save({\"conanfile.py\": GenConanfile(\"other\", \"0.1\").with_package_file(\"file.h\", \"0.1\")})\n    client.run(\"create .\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class TestMakeDepsConan(ConanFile):\n            requires = \"lib/0.1\"\n\n            def package_info(self):\n                self.cpp_info.components[\"mycomponent\"].requires.append(\"lib::cmp1\")\n                self.cpp_info.components[\"myfirstcomp\"].requires.append(\"mycomponent\")\n                self.cpp_info.components[\"myfirstcomp\"].set_property(\"my_prop\", \"my prop value\")\n                self.cpp_info.components[\"myfirstcomp\"].set_property(\"my_prop_with_newline\", \"my\\\\nprop\")\n\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile}, clean_first=True)\n    client.run(\"create . --name=second --version=0.1\")\n    client.save({\"conanfile.py\": GenConanfile(\"third\", \"0.1\").with_package_file(\"file.h\", \"0.1\")\n                                                             .with_require(\"second/0.1\")\n                                                             .with_require(\"other/0.1\")},\n                clean_first=True)\n    client.run(\"create .\")\n\n    client2 = TestClient(cache_folder=client.cache_folder)\n    conanfile = textwrap.dedent(\"\"\"\n        [requires]\n        third/0.1\n\n        [generators]\n        MakeDeps\n        \"\"\")\n    client2.save({\"conanfile.txt\": conanfile})\n    client2.run(\"install .\")\n\n    makefile_content = client2.load(CONAN_MAKEFILE_FILENAME)\n    assert \"CONAN_DEPS = \\\\\\n\" \\\n           \"\\tthird \\\\\\n\" \\\n           \"\\tsecond \\\\\\n\" \\\n           \"\\tlib \\\\\\n\" \\\n           \"\\tother\\n\" in makefile_content\n    assert 'CONAN_REQUIRES_SECOND = \\\\\\n' \\\n           '\\t$(CONAN_REQUIRES_SECOND_MYCOMPONENT) \\\\\\n' \\\n           '\\t$(CONAN_REQUIRES_SECOND_MYFIRSTCOMP)\\n' in makefile_content\n    assert 'SYSROOT' not in makefile_content\n    assert 'CONAN_REQUIRES_SECOND_MYFIRSTCOMP = mycomponent\\n' in makefile_content\n    assert 'CONAN_LIBS_LIB = $(CONAN_LIBS_LIB_CMP1)\\n' in makefile_content\n\n    assert 'CONAN_COMPONENTS_LIB = cmp1\\n' in makefile_content\n    assert 'CONAN_LIBS_LIB_CMP1 = $(CONAN_LIB_FLAG)libcmp1\\n' in makefile_content\n    assert 'CONAN_REQUIRES = $(CONAN_REQUIRES_SECOND)\\n' in makefile_content\n    assert 'CONAN_LIBS = $(CONAN_LIBS_LIB)\\n' in makefile_content\n\n    assert 'CONAN_PROPERTY_SECOND_MYFIRSTCOMP_MY_PROP = my prop value\\n' in makefile_content\n    assert 'CONAN_PROPERTY_SECOND_MYFIRSTCOMP_MY_PROP_WITH_NEWLINE' not in makefile_content\n    assert \"WARN: Skipping propery 'my_prop_with_newline' because it contains newline\" in client2.stderr\n\n\ndef test_make_with_public_deps_and_component_requires_second():\n    \"\"\"\n    Testing another complex structure like:\n\n    * other/0.1\n        - Components: \"cmp1\", \"cmp2\", \"cmp3\"\n            + \"cmp1\" (it shouldn't be affected by \"other\")\n            + \"cmp3\" (it shouldn't be affected by \"other\")\n            + \"cmp3\" requires \"cmp1\"\n    * pkg/0.1\n        - Requires: \"other/0.1\" -> \"other::cmp1\"\n    \"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Recipe(ConanFile):\n\n            def package_info(self):\n                self.cpp_info.components[\"cmp1\"].libs = [\"other_cmp1\"]\n                self.cpp_info.components[\"cmp2\"].libs = [\"other_cmp2\"]\n                self.cpp_info.components[\"cmp3\"].requires.append(\"cmp1\")\n    \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=other --version=1.0\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class TestMakeDepsConan(ConanFile):\n            requires = \"other/1.0\"\n\n            def package_info(self):\n                self.cpp_info.requires = [\"other::cmp1\"]\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=pkg --version=0.1\")\n\n    client2 = TestClient(cache_folder=client.cache_folder)\n    conanfile = textwrap.dedent(\"\"\"\n        [requires]\n        pkg/0.1\n\n        [generators]\n        MakeDeps\n        \"\"\")\n    client2.save({\"conanfile.txt\": conanfile})\n    client2.run(\"install .\")\n    make_content = client2.load(CONAN_MAKEFILE_FILENAME)\n    assert 'CONAN_REQUIRES_PKG = other::cmp1\\n' in make_content\n    assert 'CONAN_REQUIRES_OTHER = $(CONAN_REQUIRES_OTHER_CMP3)\\n' in make_content\n    assert 'CONAN_REQUIRES_OTHER_CMP3 = cmp1\\n' in make_content\n    assert 'CONAN_COMPONENTS_OTHER = \\\\\\n\\tcmp1 \\\\\\n\\tcmp2 \\\\\\n\\tcmp3\\n' in make_content\n    assert 'CONAN_LIBS_OTHER = \\\\\\n\\t$(CONAN_LIBS_OTHER_CMP1) \\\\\\n\\t$(CONAN_LIBS_OTHER_CMP2)\\n' in make_content\n    assert 'CONAN_LIBS_OTHER_CMP1 = $(CONAN_LIB_FLAG)other_cmp1\\n' in make_content\n    assert 'CONAN_LIBS_OTHER_CMP2 = $(CONAN_LIB_FLAG)other_cmp2\\n' in make_content\n    assert 'CONAN_LIBS = $(CONAN_LIBS_OTHER)\\n' in make_content\n    assert 'CONAN_REQUIRES = \\\\\\n\\t$(CONAN_REQUIRES_PKG) \\\\\\n\\t$(CONAN_REQUIRES_OTHER)\\n' in make_content\n\n\ndef test_makedeps_with_test_requires():\n    \"\"\"\n    MakeDeps has to create any test requires to be declared on the recipe.\n    \"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class TestMakeDeps(ConanFile):\n            def package_info(self):\n                self.cpp_info.libs = [f\"lib{self.name}\"]\n        \"\"\")\n\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=app --version=1.0\")\n    client.run(\"create . --name=test --version=1.0\")\n    # Create library having build and test requires\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class HelloLib(ConanFile):\n            def build_requirements(self):\n                self.tool_requires('app/1.0')\n                self.test_requires('test/1.0')\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile}, clean_first=True)\n    client.run(\"install . -g MakeDeps\")\n    assert 'CONAN_DEPS = test\\n' in client.load(CONAN_MAKEFILE_FILENAME)\n    assert 'app' not in client.load(CONAN_MAKEFILE_FILENAME)\n\n\ndef test_makedeps_with_editable_layout():\n    \"\"\"\n    The MakeDeps should be supported with editable layour mode\n    \"\"\"\n    client = TestClient()\n    dep = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import save\n        class Dep(ConanFile):\n            name = \"dep\"\n            version = \"0.1\"\n            def layout(self):\n                self.cpp.source.includedirs = [\"include\"]\n            def package_info(self):\n                self.cpp_info.libs = [\"mylib\"]\n        \"\"\")\n    client.save({\"dep/conanfile.py\": dep,\n                 \"dep/include/header.h\": \"\",\n                 \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_requires(\"dep/0.1\")})\n    client.run(\"create dep\")\n    client.run(\"editable add dep\")\n    with client.chdir(\"pkg\"):\n        client.run(\"install . -g MakeDeps\")\n        makefile_content = client.load(CONAN_MAKEFILE_FILENAME)\n        assert 'CONAN_LIBS_DEP = $(CONAN_LIB_FLAG)mylib\\n' in makefile_content\n        assert 'CONAN_INCLUDE_DIRS_DEP = $(CONAN_INCLUDE_DIR_FLAG)$(CONAN_ROOT_DEP)/include\\n' in makefile_content\n\n\ndef test_makedeps_tool_requires():\n    \"\"\"\n    Testing if MakeDeps are created for tool requires\n    \"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class TestMakeDepsConan(ConanFile):\n\n            def package_info(self):\n                self.cpp_info.libs = [\"libtool\"]\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name tool --version 1.0\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class TestMakeDepsConan(ConanFile):\n\n            def package_info(self):\n                self.cpp_info.components[\"cmp1\"].libs = [\"other_cmp1\"]\n                self.cpp_info.components[\"cmp2\"].libs = [\"other_cmp2\"]\n                self.cpp_info.components[\"cmp3\"].requires.append(\"cmp1\")\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile}, clean_first=True)\n    client.run(\"create . --name other --version 1.0\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        [tool_requires]\n        tool/1.0\n        other/1.0\n        [generators]\n        MakeDeps\n        \"\"\")\n    client.save({\"conanfile.txt\": conanfile}, clean_first=True)\n    client.run(\"install . -pr:h default -pr:b default\")\n    make_content = client.load(CONAN_MAKEFILE_FILENAME)\n\n    # TODO: MakeDeps should support tool_requires in the future\n    assert \"CONAN_LIBS_TOOL\" not in make_content\n    assert \"CONAN_NAME_OTHER\" not in make_content\n\n\n@pytest.mark.parametrize(\"pattern, result, expected\",\n                         [(\"libs = []\", False, 'SYSROOT'),\n                          (\"sysroot = ['/foo/bar/sysroot']\", True, 'CONAN_SYSROOT_PACKAGE = /foo/bar/sysroot')\n                          if platform.system() != \"Windows\" else\n                          (\"sysroot = ['C:/my_sysroot']\", True, 'CONAN_SYSROOT_PACKAGE = C:/my_sysroot')])\ndef test_makefile_sysroot(pattern, result, expected):\n    \"\"\"\n    The MakeDeps should not enforce sysroot in case not defined\n    \"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class TestMakeDepsConan(ConanFile):\n                def package_info(self):\n                    self.cpp_info.{{ pattern }}\n            \"\"\")\n    client.save({\"conanfile.py\": conanfile.replace(\"{{ pattern }}\", pattern)})\n    client.run(\"create . --name package --version 0.1.0\")\n    client.run(\"install --requires=package/0.1.0 -pr:h default -pr:b default -g MakeDeps\")\n    makefile_content = client.load(CONAN_MAKEFILE_FILENAME)\n    assert (expected in makefile_content) == result\n\n\ndef test_makefile_reference():\n    \"\"\"\n    The MakeDeps should generate the correct package reference as variable\n    \"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Testing(ConanFile):\n                pass\n            \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n\n    # official packages <name>/<version>\n    client.run(\"create . --name package --version 0.1.0\")\n    client.run(\"install --requires=package/0.1.0 -pr:h default -pr:b default -g MakeDeps\")\n    makefile_content = client.load(CONAN_MAKEFILE_FILENAME)\n    assert 'CONAN_REFERENCE_PACKAGE = package/0.1.0\\n' in makefile_content\n\n    # custom packages <name>/<version>@<user>/<channel>\n    client.run(\"create . --name package --version 0.1.0 --user user --channel channel\")\n    client.run(\"install --requires=package/0.1.0@user/channel -pr:h default -pr:b default -g MakeDeps\")\n    makefile_content = client.load(CONAN_MAKEFILE_FILENAME)\n    assert 'CONAN_REFERENCE_PACKAGE = package/0.1.0@user/channel\\n' in makefile_content\n"
  },
  {
    "path": "test/integration/toolchains/gnu/test_pkgconfigdeps.py",
    "content": "import glob\nimport os\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import load\n\n\ndef get_requires_from_content(content):\n    for line in content.splitlines():\n        if \"Requires:\" in line:\n            return line\n    return \"\"\n\n\ndef test_pkg_config_dirs():\n    # https://github.com/conan-io/conan/issues/2756\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n\n        class PkgConfigConan(ConanFile):\n            name = \"mylib\"\n            version = \"0.1\"\n\n            def package_info(self):\n                self.cpp_info.frameworkdirs = []\n                self.cpp_info.filter_empty = False\n                libname = \"mylib\"\n                fake_dir = os.path.join(\"/\", \"my_absoulte_path\", \"fake\")\n                include_dir = os.path.join(fake_dir, libname, \"include\")\n                lib_dir = os.path.join(fake_dir, libname, \"lib\")\n                lib_dir1 = os.path.join(self.package_folder, \"lib2\")\n                self.cpp_info.includedirs = [include_dir]\n                self.cpp_info.libdirs = [lib_dir, lib_dir1]\n                self.cpp_info.bindirs = [\"mybin\"]\n        \"\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create .\")\n    client.run(\"install --requires=mylib/0.1@ -g PkgConfigDeps\")\n\n    pc_path = os.path.join(client.current_folder, \"mylib.pc\")\n    assert os.path.exists(pc_path) is True\n    pc_content = load(pc_path)\n    assert 'Name: mylib' in pc_content\n    assert 'Description: Conan package: mylib' in pc_content\n    assert 'Version: 0.1' in pc_content\n    assert 'Libs: -L\"${libdir}\" -L\"${libdir1}\"' in pc_content\n    assert 'Cflags: -I\"${includedir}\"' in pc_content\n    # https://github.com/conan-io/conan/pull/13623\n    assert 'bindir=${prefix}/mybin' in pc_content\n\n    def assert_is_abs(path):\n        assert os.path.isabs(path) is True\n\n    for line in pc_content.splitlines():\n        if line.startswith(\"includedir=\"):\n            assert_is_abs(line[len(\"includedir=\"):])\n            assert line.endswith(\"include\")\n        elif line.startswith(\"libdir=\"):\n            assert_is_abs(line[len(\"libdir=\"):])\n            assert line.endswith(\"lib\")\n        elif line.startswith(\"libdir1=\"):\n            assert \"${prefix}/lib2\" in line\n\n\ndef test_empty_dirs():\n    # Adding in package_info all the empty directories\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n\n        class PkgConfigConan(ConanFile):\n            name = \"mylib\"\n            version = \"0.1\"\n\n            def package_info(self):\n                self.cpp_info.includedirs = []\n                self.cpp_info.libdirs = []\n                self.cpp_info.bindirs = []\n                self.cpp_info.libs = []\n                self.cpp_info.frameworkdirs = []\n        \"\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create .\")\n    client.run(\"install --requires=mylib/0.1@ -g PkgConfigDeps\")\n\n    pc_path = os.path.join(client.current_folder, \"mylib.pc\")\n    assert os.path.exists(pc_path) is True\n    pc_content = load(pc_path)\n    expected = textwrap.dedent(\"\"\"\n        Name: mylib\n        Description: Conan package: mylib\n        Version: 0.1\"\"\")\n    assert \"\\n\".join(pc_content.splitlines()[1:]) == expected\n\n\ndef test_system_libs():\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import save\n        import os\n\n        class PkgConfigConan(ConanFile):\n            name = \"mylib\"\n            version = \"0.1\"\n\n            def package(self):\n                save(self, os.path.join(self.package_folder, \"lib\", \"file\"), \"\")\n\n            def package_info(self):\n                self.cpp_info.libs = [\"mylib1\", \"mylib2\"]\n                self.cpp_info.system_libs = [\"system_lib1\", \"system_lib2\"]\n        \"\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create .\")\n    client.run(\"install --requires=mylib/0.1@ -g PkgConfigDeps\")\n\n    pc_content = client.load(\"mylib.pc\")\n    assert 'Libs: -L\"${libdir}\" -lmylib1 -lmylib2 -lsystem_lib1 -lsystem_lib2' in pc_content\n\n\ndef test_multiple_include():\n    # https://github.com/conan-io/conan/issues/7056\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import save\n        import os\n\n        class PkgConfigConan(ConanFile):\n            def package(self):\n                for p in [\"inc1\", \"inc2\", \"inc3/foo\", \"lib1\", \"lib2\"]:\n                    save(self, os.path.join(self.package_folder, p, \"file\"), \"\")\n\n            def package_info(self):\n                self.cpp_info.includedirs = [\"inc1\", \"inc2\", \"inc3/foo\"]\n                self.cpp_info.libdirs = [\"lib1\", \"lib2\"]\n        \"\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=pkg --version=0.1\")\n    client.run(\"install --requires=pkg/0.1@ -g PkgConfigDeps\")\n\n    pc_content = client.load(\"pkg.pc\")\n    assert \"includedir=${prefix}/inc1\" in pc_content\n    assert \"includedir1=${prefix}/inc2\" in pc_content\n    assert \"includedir2=${prefix}/inc3/foo\" in pc_content\n    assert \"libdir=${prefix}/lib1\" in pc_content\n    assert \"libdir1=${prefix}/lib2\" in pc_content\n    assert 'Libs: -L\"${libdir}\" -L\"${libdir1}\"' in pc_content\n    assert 'Cflags: -I\"${includedir}\" -I\"${includedir1}\" -I\"${includedir2}\"' in pc_content\n\n\ndef test_custom_content():\n    # https://github.com/conan-io/conan/issues/7661\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import save\n        import os\n        import textwrap\n\n        class PkgConfigConan(ConanFile):\n\n            def package(self):\n                save(self, os.path.join(self.package_folder, \"include\" ,\"file\"), \"\")\n                save(self, os.path.join(self.package_folder, \"lib\" ,\"file\"), \"\")\n\n            def package_info(self):\n                custom_content = textwrap.dedent(\\\"\"\"\n                        bindir=${prefix}/my/bin/folder\n                        fakelibdir=${prefix}/my/lib/folder\n                        datadir=${prefix}/share\n                        schemasdir=${datadir}/mylib/schemas\n                    \\\"\"\")\n                self.cpp_info.set_property(\"pkg_config_custom_content\", custom_content)\n                self.cpp_info.includedirs = [\"include\"]\n                self.cpp_info.libdirs = [\"lib\"]\n        \"\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=pkg --version=0.1\")\n    client.run(\"install --requires=pkg/0.1@ -g PkgConfigDeps\")\n\n    pc_content = client.load(\"pkg.pc\")\n    prefix = pc_content.splitlines()[0]\n    expected = textwrap.dedent(f\"\"\"\\\n    {prefix}\n    libdir=${{prefix}}/lib\n    includedir=${{prefix}}/include\n    bindir=${{prefix}}/my/bin/folder\n    fakelibdir=${{prefix}}/my/lib/folder\n    datadir=${{prefix}}/share\n    schemasdir=${{datadir}}/mylib/schemas\n\n    Name: pkg\n    Description: Conan package: pkg\n    Version: 0.1\n    Libs: -L\"${{libdir}}\"\n    Cflags: -I\"${{includedir}}\"\n    \"\"\")\n    assert expected == pc_content\n\n\ndef test_custom_content_and_version_components():\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class PkgConfigConan(ConanFile):\n\n            def package_info(self):\n                self.cpp_info.components[\"mycomponent\"].set_property(\"pkg_config_custom_content\",\n                                                                     \"componentdir=${prefix}/mydir\")\n                self.cpp_info.components[\"mycomponent\"].set_property(\"component_version\",\n                                                                     \"19.8.199\")\n        \"\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=pkg --version=0.1\")\n    client.run(\"install --requires=pkg/0.1@ -g PkgConfigDeps\")\n    pc_content = client.load(\"pkg-mycomponent.pc\")\n    assert \"componentdir=${prefix}/mydir\" in pc_content\n    assert \"Version: 19.8.199\" in pc_content\n\n    # Now with lockfile\n    # https://github.com/conan-io/conan/issues/16197\n    lockfile = textwrap.dedent(\"\"\"\n        {\n            \"version\": \"0.5\",\n            \"requires\": [\n                \"pkg/0.1#9a5fed2bf506fd28817ddfbc92b07fc1\"\n            ]\n        }\n        \"\"\")\n    client.save({\"conan.lock\": lockfile})\n    client.run(\"install --requires=pkg/0.1 -g PkgConfigDeps --lockfile=conan.lock\")\n    pc_content = client.load(\"pkg-mycomponent.pc\")\n    assert \"componentdir=${prefix}/mydir\" in pc_content\n    assert \"Version: 19.8.199\" in pc_content\n\n\ndef test_custom_version():\n    # https://github.com/conan-io/conan/issues/16197\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class PkgConfigConan(ConanFile):\n            def package_info(self):\n                self.cpp_info.set_property(\"system_package_version\", \"19.8.199\")\n        \"\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=pkg --version=0.1\")\n    client.run(\"install --requires=pkg/0.1 -g PkgConfigDeps\")\n\n    pc_content = client.load(\"pkg.pc\")\n    assert \"Version: 19.8.199\" in pc_content\n\n    # Now with lockfile\n    # https://github.com/conan-io/conan/issues/16197\n    lockfile = textwrap.dedent(\"\"\"\n        {\n            \"version\": \"0.5\",\n            \"requires\": [\n                \"pkg/0.1#0fe93a852dd6a177bca87cb2d4491a18\"\n            ]\n        }\n        \"\"\")\n    client.save({\"conan.lock\": lockfile})\n    client.run(\"install --requires=pkg/0.1 -g PkgConfigDeps --lockfile=conan.lock\")\n    pc_content = client.load(\"pkg.pc\")\n    assert \"Version: 19.8.199\" in pc_content\n\n\ndef test_pkg_with_public_deps_and_component_requires():\n    \"\"\"\n    Testing a complex structure like:\n\n    * first/0.1\n        - Global pkg_config_name == \"myfirstlib\"\n        - Components: \"cmp1\"\n    * other/0.1\n    * second/0.1\n        - Requires: \"first/0.1\"\n        - Components: \"mycomponent\", \"myfirstcomp\"\n            + \"mycomponent\" requires \"first::cmp1\"\n            + \"myfirstcomp\" requires \"mycomponent\"\n    * third/0.1\n        - Requires: \"second/0.1\", \"other/0.1\"\n\n    Expected file structure after running PkgConfigDeps as generator:\n        - other.pc\n        - myfirstlib-cmp1.pc\n        - myfirstlib.pc\n        - second-mycomponent.pc\n        - second-myfirstcomp.pc\n        - second.pc\n        - third.pc\n    \"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Recipe(ConanFile):\n\n            def package_info(self):\n                self.cpp_info.set_property(\"pkg_config_name\", \"myfirstlib\")\n                self.cpp_info.components[\"cmp1\"].libs = [\"libcmp1\"]\n    \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=first --version=0.1\")\n    client.save({\"conanfile.py\": GenConanfile(\"other\", \"0.1\").with_package_file(\"file.h\", \"0.1\")})\n    client.run(\"create .\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class PkgConfigConan(ConanFile):\n            requires = \"first/0.1\"\n\n            def package_info(self):\n                self.cpp_info.components[\"mycomponent\"].requires.append(\"first::cmp1\")\n                self.cpp_info.components[\"myfirstcomp\"].requires.append(\"mycomponent\")\n\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile}, clean_first=True)\n    client.run(\"create . --name=second --version=0.1\")\n    client.save({\"conanfile.py\": GenConanfile(\"third\", \"0.1\").with_package_file(\"file.h\", \"0.1\")\n                                                             .with_require(\"second/0.1\")\n                                                             .with_require(\"other/0.1\")},\n                clean_first=True)\n    client.run(\"create .\")\n\n    client2 = TestClient(cache_folder=client.cache_folder)\n    conanfile = textwrap.dedent(\"\"\"\n        [requires]\n        third/0.1\n\n        [generators]\n        PkgConfigDeps\n        \"\"\")\n    client2.save({\"conanfile.txt\": conanfile})\n    client2.run(\"install .\")\n\n    pc_content = client2.load(\"third.pc\")\n    # Originally posted: https://github.com/conan-io/conan/issues/9939\n    assert \"Requires: second other\" == get_requires_from_content(pc_content)\n    pc_content = client2.load(\"second.pc\")\n    assert \"Requires: second-mycomponent second-myfirstcomp\" == get_requires_from_content(pc_content)\n    pc_content = client2.load(\"second-mycomponent.pc\")\n    assert \"Requires: myfirstlib-cmp1\" == get_requires_from_content(pc_content)\n    pc_content = client2.load(\"second-myfirstcomp.pc\")\n    assert \"Requires: second-mycomponent\" == get_requires_from_content(pc_content)\n    pc_content = client2.load(\"myfirstlib.pc\")\n    assert \"Requires: myfirstlib-cmp1\" == get_requires_from_content(pc_content)\n    pc_content = client2.load(\"other.pc\")\n    assert \"\" == get_requires_from_content(pc_content)\n\n\ndef test_pkg_with_public_deps_and_component_requires_2():\n    \"\"\"\n    Testing another complex structure like:\n\n    * other/0.1\n        - Global pkg_config_name == \"fancy_name\"\n        - Components: \"cmp1\", \"cmp2\", \"cmp3\"\n            + \"cmp1\" pkg_config_name == \"component1\" (it shouldn't be affected by \"fancy_name\")\n            + \"cmp3\" pkg_config_name == \"component3\" (it shouldn't be affected by \"fancy_name\")\n            + \"cmp3\" requires \"cmp1\"\n    * pkg/0.1\n        - Requires: \"other/0.1\" -> \"other::cmp1\"\n\n    Expected file structure after running PkgConfigDeps as generator:\n        - component1.pc\n        - component3.pc\n        - other-cmp2.pc\n        - other.pc\n        - pkg.pc\n    \"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class Recipe(ConanFile):\n\n            def package_info(self):\n                self.cpp_info.set_property(\"pkg_config_name\", \"fancy_name\")\n                self.cpp_info.components[\"cmp1\"].libs = [\"other_cmp1\"]\n                self.cpp_info.components[\"cmp1\"].set_property(\"pkg_config_name\", \"component1\")\n                self.cpp_info.components[\"cmp2\"].libs = [\"other_cmp2\"]\n                self.cpp_info.components[\"cmp3\"].requires.append(\"cmp1\")\n                self.cpp_info.components[\"cmp3\"].set_property(\"pkg_config_name\", \"component3\")\n    \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=other --version=1.0\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class PkgConfigConan(ConanFile):\n            requires = \"other/1.0\"\n\n            def package_info(self):\n                self.cpp_info.requires = [\"other::cmp1\"]\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=pkg --version=0.1\")\n\n    client2 = TestClient(cache_folder=client.cache_folder)\n    conanfile = textwrap.dedent(\"\"\"\n        [requires]\n        pkg/0.1\n\n        [generators]\n        PkgConfigDeps\n        \"\"\")\n    client2.save({\"conanfile.txt\": conanfile})\n    client2.run(\"install .\")\n    pc_content = client2.load(\"pkg.pc\")\n    assert \"Requires: component1\" == get_requires_from_content(pc_content)\n    pc_content = client2.load(\"fancy_name.pc\")\n    assert \"Requires: component1 fancy_name-cmp2 component3\" == get_requires_from_content(pc_content)\n    assert client2.load(\"component1.pc\")\n    assert client2.load(\"fancy_name-cmp2.pc\")\n    pc_content = client2.load(\"component3.pc\")\n    assert \"Requires: component1\" == get_requires_from_content(pc_content)\n\n\ndef test_pkg_config_name_full_aliases():\n    \"\"\"\n    Testing a simpler structure but paying more attention into several aliases.\n    Expected file structure after running PkgConfigDeps as generator:\n        - compo1.pc\n        - compo1_alias.pc\n        - pkg_alias1.pc\n        - pkg_alias2.pc\n        - pkg_other_name.pc\n        - second-mycomponent.pc\n        - second.pc\n    \"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        import textwrap\n        from conan import ConanFile\n\n        class Recipe(ConanFile):\n\n            def package_info(self):\n                custom_content = textwrap.dedent(\\\"\"\"\n                datadir=${prefix}/share\n                schemasdir=${datadir}/mylib/schemas\n                \\\"\"\")\n                self.cpp_info.set_property(\"pkg_config_name\", \"pkg_other_name\")\n                self.cpp_info.set_property(\"pkg_config_aliases\", [\"pkg_alias1\", \"pkg_alias2\"])\n                # Custom content only added to root pc file -> pkg_other_name.pc\n                self.cpp_info.set_property(\"pkg_config_custom_content\", custom_content)\n                self.cpp_info.components[\"cmp1\"].libs = [\"libcmp1\"]\n                self.cpp_info.components[\"cmp1\"].set_property(\"pkg_config_name\", \"compo1\")\n                self.cpp_info.components[\"cmp1\"].set_property(\"pkg_config_aliases\", [\"compo1_alias\"])\n    \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=first --version=0.3\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class PkgConfigConan(ConanFile):\n            requires = \"first/0.3\"\n\n            def package_info(self):\n                self.cpp_info.components[\"mycomponent\"].requires.append(\"first::cmp1\")\n\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile}, clean_first=True)\n    client.run(\"create . --name=second --version=0.2\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        [requires]\n        second/0.2\n\n        [generators]\n        PkgConfigDeps\n        \"\"\")\n    client.save({\"conanfile.txt\": conanfile}, clean_first=True)\n    client.run(\"install .\")\n\n    pc_content = client.load(\"compo1.pc\")\n    prefix = pc_content.splitlines()[0]\n    assert \"Description: Conan component: compo1\" in pc_content\n    assert \"Requires\" not in pc_content\n\n    pc_content = client.load(\"compo1_alias.pc\")\n    content = textwrap.dedent(f\"\"\"\\\n    Name: compo1_alias\n    Description: Alias compo1_alias for compo1\n    Version: 0.3\n    Requires: compo1\n    \"\"\")\n    assert content == pc_content\n\n    pc_content = client.load(\"pkg_other_name.pc\")\n    content = textwrap.dedent(f\"\"\"\\\n    {prefix}\n    libdir=${{prefix}}/lib\n    includedir=${{prefix}}/include\n    bindir=${{prefix}}/bin\n    datadir=${{prefix}}/share\n    schemasdir=${{datadir}}/mylib/schemas\n\n    Name: pkg_other_name\n    Description: Conan package: pkg_other_name\n    Version: 0.3\n    Libs: -L\"${{libdir}}\"\n    Cflags: -I\"${{includedir}}\"\n    Requires: compo1\n    \"\"\")\n    assert content == pc_content\n\n    pc_content = client.load(\"pkg_alias1.pc\")\n    content = textwrap.dedent(f\"\"\"\\\n    Name: pkg_alias1\n    Description: Alias pkg_alias1 for pkg_other_name\n    Version: 0.3\n    Requires: pkg_other_name\n    \"\"\")\n    assert content == pc_content\n\n    pc_content = client.load(\"pkg_alias2.pc\")\n    content = textwrap.dedent(f\"\"\"\\\n    Name: pkg_alias2\n    Description: Alias pkg_alias2 for pkg_other_name\n    Version: 0.3\n    Requires: pkg_other_name\n    \"\"\")\n    assert content == pc_content\n\n    pc_content = client.load(\"second-mycomponent.pc\")\n    assert \"Requires: compo1\" == get_requires_from_content(pc_content)\n\n\ndef test_components_and_package_pc_creation_order():\n    \"\"\"\n    Testing if the root package PC file name matches with any of the components one, the first one\n    is not going to be created. Components have more priority than root package.\n\n    Issue related: https://github.com/conan-io/conan/issues/10341\n    \"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class PkgConfigConan(ConanFile):\n\n            def package_info(self):\n                self.cpp_info.set_property(\"pkg_config_name\", \"OpenCL\")\n                self.cpp_info.components[\"_opencl-headers\"].set_property(\"pkg_config_name\", \"OpenCL\")\n                self.cpp_info.components[\"_opencl-other\"].set_property(\"pkg_config_name\", \"OtherCL\")\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=opencl --version=1.0\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class PkgConfigConan(ConanFile):\n            requires = \"opencl/1.0\"\n\n            def package_info(self):\n                self.cpp_info.components[\"comp\"].set_property(\"pkg_config_name\", \"pkgb\")\n                self.cpp_info.components[\"comp\"].requires.append(\"opencl::_opencl-headers\")\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile}, clean_first=True)\n    client.run(\"create . --name=pkgb --version=1.0\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        [requires]\n        pkgb/1.0\n\n        [generators]\n        PkgConfigDeps\n        \"\"\")\n    client.save({\"conanfile.txt\": conanfile}, clean_first=True)\n    client.run(\"install .\")\n    pc_files = [os.path.basename(i) for i in glob.glob(os.path.join(client.current_folder, '*.pc'))]\n    pc_files.sort()\n    # Let's check all the PC file names created just in case\n    assert pc_files == ['OpenCL.pc', 'OtherCL.pc', 'pkgb.pc']\n    pc_content = client.load(\"OpenCL.pc\")\n    assert \"Name: OpenCL\" in pc_content\n    assert \"Description: Conan component: OpenCL\" in pc_content\n    assert \"Requires:\" not in pc_content\n    pc_content = client.load(\"pkgb.pc\")\n    assert \"Requires: OpenCL\" in get_requires_from_content(pc_content)\n\n\ndef test_pkgconfigdeps_with_test_requires():\n    \"\"\"\n    PkgConfigDeps has to create any test requires declared on the recipe.\n\n    Related issue: https://github.com/conan-io/conan/issues/11376\n    \"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            def package_info(self):\n                self.cpp_info.libs = [\"lib%s\"]\n        \"\"\")\n    with client.chdir(\"app\"):\n        client.save({\"conanfile.py\": conanfile % \"app\"})\n        client.run(\"create . --name=app --version=1.0\")\n    with client.chdir(\"test\"):\n        client.save({\"conanfile.py\": conanfile % \"test\"})\n        client.run(\"create . --name=test --version=1.0\")\n    # Create library having build and test requires\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class HelloLib(ConanFile):\n            def build_requirements(self):\n                self.test_requires('app/1.0')\n                self.test_requires('test/1.0')\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile}, clean_first=True)\n    client.run(\"install . -g PkgConfigDeps\")\n    assert \"Description: Conan package: test\" in client.load(\"test.pc\")\n    assert \"Description: Conan package: app\" in client.load(\"app.pc\")\n\n\ndef test_with_editable_layout():\n    \"\"\"\n    https://github.com/conan-io/conan/issues/11435\n    \"\"\"\n    client = TestClient()\n    dep = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import save\n        class Dep(ConanFile):\n            name = \"dep\"\n            version = \"0.1\"\n            def layout(self):\n                self.cpp.source.includedirs = [\"include\"]\n            def package_info(self):\n                self.cpp_info.libs = [\"mylib\"]\n        \"\"\")\n    client.save({\"dep/conanfile.py\": dep,\n                 \"dep/include/header.h\": \"\",\n                 \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_requires(\"dep/0.1\")})\n    client.run(\"create dep\")\n    client.run(\"editable add dep\")\n    with client.chdir(\"pkg\"):\n        client.run(\"install . -g PkgConfigDeps\")\n        pc = client.load(\"dep.pc\")\n        assert 'Libs: -L\"${libdir}\" -lmylib' in pc\n        assert 'includedir=' in pc\n        assert 'Cflags: -I\"${includedir}\"' in pc\n\n\ndef test_tool_requires():\n    \"\"\"\n    Testing if PC files are created for tool requires if build_context_activated/_suffix is used.\n\n    Issue related: https://github.com/conan-io/conan/issues/11710\n    \"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class PkgConfigConan(ConanFile):\n\n            def package_info(self):\n                self.cpp_info.libs = [\"libtool\"]\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name tool --version 1.0\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class PkgConfigConan(ConanFile):\n\n            def package_info(self):\n                self.cpp_info.set_property(\"pkg_config_name\", \"libother\")\n                self.cpp_info.components[\"cmp1\"].libs = [\"other_cmp1\"]\n                self.cpp_info.components[\"cmp1\"].set_property(\"pkg_config_name\", \"component1\")\n                self.cpp_info.components[\"cmp2\"].libs = [\"other_cmp2\"]\n                self.cpp_info.components[\"cmp3\"].requires.append(\"cmp1\")\n                self.cpp_info.components[\"cmp3\"].set_property(\"pkg_config_name\", \"component3\")\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile}, clean_first=True)\n    client.run(\"create . --name other --version 1.0\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.gnu import PkgConfigDeps\n\n        class PkgConfigConan(ConanFile):\n            name = \"demo\"\n            version = \"1.0\"\n\n            def build_requirements(self):\n                self.build_requires(\"tool/1.0\")\n                self.build_requires(\"other/1.0\")\n\n            def generate(self):\n                tc = PkgConfigDeps(self)\n                tc.build_context_activated = [\"other\", \"tool\"]\n                tc.build_context_suffix = {\"tool\": \"_bt\", \"other\": \"_bo\"}\n                tc.generate()\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile}, clean_first=True)\n    client.run(\"install . -pr:h default -pr:b default\")\n    pc_files = [os.path.basename(i) for i in glob.glob(os.path.join(client.current_folder, '*.pc'))]\n    pc_files.sort()\n    # Let's check all the PC file names created just in case\n    assert pc_files == ['component1_bo.pc', 'component3_bo.pc',\n                        'libother_bo-cmp2.pc', 'libother_bo.pc', 'tool_bt.pc']\n    pc_content = client.load(\"tool_bt.pc\")\n    assert \"Name: tool_bt\" in pc_content\n    pc_content = client.load(\"libother_bo.pc\")\n    assert \"Name: libother_bo\" in pc_content\n    assert \"Requires: component1_bo libother_bo-cmp2 component3_bo\" == get_requires_from_content(pc_content)\n    pc_content = client.load(\"component1_bo.pc\")\n    assert \"Name: component1_bo\" in pc_content\n    pc_content = client.load(\"libother_bo-cmp2.pc\")\n    assert \"Name: libother_bo-cmp2\" in pc_content\n    pc_content = client.load(\"component3_bo.pc\")\n    assert \"Name: component3_bo\" in pc_content\n    assert \"Requires: component1_bo\" == get_requires_from_content(pc_content)\n\n\ndef test_tool_requires_not_created_if_no_activated():\n    \"\"\"\n    Testing if there are no PC files created in no context are activated\n    \"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class PkgConfigConan(ConanFile):\n\n            def package_info(self):\n                self.cpp_info.libs = [\"libtool\"]\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name tool --version 1.0\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class PkgConfigConan(ConanFile):\n            name = \"demo\"\n            version = \"1.0\"\n            generators = \"PkgConfigDeps\"\n\n            def build_requirements(self):\n                self.build_requires(\"tool/1.0\")\n\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile}, clean_first=True)\n    client.run(\"install . -pr:h default -pr:b default\")\n    pc_files = [os.path.basename(i) for i in glob.glob(os.path.join(client.current_folder, '*.pc'))]\n    pc_files.sort()\n    assert pc_files == []\n\n\ndef test_tool_requires_error_if_no_build_suffix():\n    \"\"\"\n    Testing if same dependency exists in both require and build require (without suffix)\n    \"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class PkgConfigConan(ConanFile):\n\n            def package_info(self):\n                self.cpp_info.libs = [\"libtool\"]\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name tool --version 1.0\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.gnu import PkgConfigDeps\n\n        class PkgConfigConan(ConanFile):\n            name = \"demo\"\n            version = \"1.0\"\n\n            def requirements(self):\n                self.requires(\"tool/1.0\")\n\n            def build_requirements(self):\n                self.build_requires(\"tool/1.0\")\n\n            def generate(self):\n                tc = PkgConfigDeps(self)\n                tc.build_context_activated = [\"tool\"]\n                tc.generate()\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile}, clean_first=True)\n    client.run(\"install . -pr:h default -pr:b default\", assert_error=True)\n    assert \"The packages ['tool'] exist both as 'require' and as 'build require'\" in client.out\n\n\ndef test_error_missing_pc_build_context():\n    \"\"\"\n    PkgConfigDeps was failing, not generating the zlib.pc in the\n    build context, for a test_package that both requires(example/1.0) and\n    tool_requires(example/1.0), which depends on zlib\n    # https://github.com/conan-io/conan/issues/12664\n    \"\"\"\n    c = TestClient()\n    example = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        class Example(ConanFile):\n            name = \"example\"\n            version = \"1.0\"\n            requires = \"game/1.0\"\n            generators = \"PkgConfigDeps\"\n            settings = \"build_type\"\n            def build(self):\n                assert os.path.exists(\"math.pc\")\n                assert os.path.exists(\"engine.pc\")\n                assert os.path.exists(\"game.pc\")\n            \"\"\")\n    c.save({\"math/conanfile.py\": GenConanfile(\"math\", \"1.0\").with_settings(\"build_type\"),\n            \"engine/conanfile.py\": GenConanfile(\"engine\", \"1.0\").with_settings(\"build_type\")\n                                                                .with_require(\"math/1.0\"),\n            \"game/conanfile.py\": GenConanfile(\"game\", \"1.0\").with_settings(\"build_type\")\n                                                            .with_requires(\"engine/1.0\"),\n            \"example/conanfile.py\": example,\n            # With ``with_test()`` it already generates a requires(example/1.0)\n            \"example/test_package/conanfile.py\": GenConanfile().with_build_requires(\"example/1.0\")\n                                                               .with_test(\"pass\")})\n    c.run(\"create math\")\n    c.run(\"create engine\")\n    c.run(\"create game\")\n    # This used to crash because of the assert inside the build() method\n    c.run(\"create example -pr:b=default -pr:h=default\")\n    # Now make sure we can actually build with build!=host context\n    # The debug binaries are missing, so adding --build=missing\n    c.run(\"create example -pr:b=default -pr:h=default -s:h build_type=Debug --build=missing \"\n          \"--build=example\")\n\n    c.assert_listed_require({\"example/1.0\": \"Cache\"})\n    c.assert_listed_require({\"example/1.0\": \"Cache\"}, build=True)\n\n\nclass TestPCGenerationBuildContext:\n    \"\"\"\n    https://github.com/conan-io/conan/issues/14920\n    \"\"\"\n    def test_pc_generate(self):\n        c = TestClient()\n        tool = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.gnu import PkgConfigDeps\n\n            class Example(ConanFile):\n                name = \"tool\"\n                version = \"1.0\"\n                requires = \"wayland/1.0\"\n                tool_requires = \"wayland/1.0\"\n\n                def generate(self):\n                    deps = PkgConfigDeps(self)\n                    deps.build_context_activated = [\"wayland\", \"dep\"]\n                    deps.build_context_suffix = {\"wayland\": \"_BUILD\", \"dep\": \"_BUILD\"}\n                    deps.generate()\n\n                def build(self):\n                    assert os.path.exists(\"wayland.pc\")\n                    assert os.path.exists(\"wayland_BUILD.pc\")\n                    assert os.path.exists(\"dep.pc\")\n                    assert os.path.exists(\"dep_BUILD.pc\")\n                \"\"\")\n        c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"1.0\").with_package_type(\"shared-library\"),\n                \"wayland/conanfile.py\": GenConanfile(\"wayland\", \"1.0\").with_requires(\"dep/1.0\"),\n                \"tool/conanfile.py\": tool,\n                \"app/conanfile.py\": GenConanfile().with_tool_requires(\"tool/1.0\")})\n        c.run(\"export dep\")\n        c.run(\"export wayland\")\n        c.run(\"export tool\")\n        c.run(\"install app --build=missing\")\n        assert \"Install finished successfully\" in c.out  # the asserts in build() didn't fail\n        # Deprecation warning!\n        assert \"PkgConfigDeps.build_context_suffix attribute has been deprecated\" in c.out\n        # Now make sure we can actually build with build!=host context\n        c.run(\"install app -s:h build_type=Debug --build=missing\")\n        assert \"Install finished successfully\" in c.out  # the asserts in build() didn't fail\n\n    def test_pc_generate_components(self):\n        c = TestClient()\n        tool = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.gnu import PkgConfigDeps\n\n            class Example(ConanFile):\n                name = \"tool\"\n                version = \"1.0\"\n                requires = \"wayland/1.0\"\n                tool_requires = \"wayland/1.0\"\n\n                def generate(self):\n                    deps = PkgConfigDeps(self)\n                    deps.build_context_activated = [\"wayland\", \"dep\"]\n                    deps.build_context_suffix = {\"wayland\": \"_BUILD\", \"dep\": \"_BUILD\"}\n                    deps.generate()\n\n                def build(self):\n                    assert os.path.exists(\"wayland.pc\")\n                    assert os.path.exists(\"wayland-client.pc\")\n                    assert os.path.exists(\"wayland-server.pc\")\n                    assert os.path.exists(\"wayland_BUILD.pc\")\n                    assert os.path.exists(\"wayland_BUILD-client.pc\")\n                    assert os.path.exists(\"wayland_BUILD-server.pc\")\n                    assert os.path.exists(\"dep.pc\")\n                    assert os.path.exists(\"dep_BUILD.pc\")\n\n                    # Issue: https://github.com/conan-io/conan/issues/12342\n                    # Issue: https://github.com/conan-io/conan/issues/14935\n                    assert not os.path.exists(\"build/wayland.pc\")\n                    assert not os.path.exists(\"build/wayland-client.pc\")\n                    assert not os.path.exists(\"build/wayland-server.pc\")\n                    assert not os.path.exists(\"build/dep.pc\")\n                \"\"\")\n        wayland = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class Pkg(ConanFile):\n                name = \"wayland\"\n                version = \"1.0\"\n                requires = \"dep/1.0\"\n\n                def package_info(self):\n                    self.cpp_info.components[\"client\"].libs = []\n                    self.cpp_info.components[\"server\"].libs = []\n            \"\"\")\n        c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"1.0\").with_package_type(\"shared-library\"),\n                \"wayland/conanfile.py\": wayland,\n                \"tool/conanfile.py\": tool,\n                \"app/conanfile.py\": GenConanfile().with_tool_requires(\"tool/1.0\")})\n        c.run(\"export dep\")\n        c.run(\"export wayland\")\n        c.run(\"export tool\")\n        c.run(\"install app --build=missing\")\n        assert \"Install finished successfully\" in c.out  # the asserts in build() didn't fail\n        # Now make sure we can actually build with build!=host context\n        c.run(\"install app -s:h build_type=Debug --build=missing\")\n        assert \"Install finished successfully\" in c.out  # the asserts in build() didn't fail\n\n    @pytest.mark.parametrize(\"build_folder_name\", [\"build\", \"\"])\n    def test_pc_generate_components_in_build_context_folder(self, build_folder_name):\n        c = TestClient()\n        tool = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.gnu import PkgConfigDeps\n\n            class Example(ConanFile):\n                name = \"tool\"\n                version = \"1.0\"\n                requires = \"wayland/1.0\"\n                tool_requires = \"wayland/1.0\"\n\n                def generate(self):\n                    deps = PkgConfigDeps(self)\n                    deps.build_context_activated = [\"wayland\", \"dep\"]\n                    deps.build_context_folder = \"{build_folder_name}\"\n                    deps.generate()\n\n                def build(self):\n                    assert os.path.exists(\"wayland.pc\")\n                    assert os.path.exists(\"wayland-client.pc\")\n                    assert os.path.exists(\"wayland-server.pc\")\n                    assert os.path.exists(\"dep.pc\")\n\n                    # Issue: https://github.com/conan-io/conan/issues/12342\n                    # Issue: https://github.com/conan-io/conan/issues/14935\n                    if \"{build_folder_name}\":\n                        assert os.path.exists(\"{build_folder_name}/wayland.pc\")\n                        assert os.path.exists(\"{build_folder_name}/wayland-client.pc\")\n                        assert os.path.exists(\"{build_folder_name}/wayland-server.pc\")\n                        assert os.path.exists(\"{build_folder_name}/dep.pc\")\n                \"\"\".format(build_folder_name=build_folder_name))\n        wayland = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class Pkg(ConanFile):\n                name = \"wayland\"\n                version = \"1.0\"\n                requires = \"dep/1.0\"\n\n                def package_info(self):\n                    self.cpp_info.components[\"client\"].libs = []\n                    self.cpp_info.components[\"server\"].libs = []\n            \"\"\")\n        c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"1.0\").with_package_type(\"shared-library\"),\n                \"wayland/conanfile.py\": wayland,\n                \"tool/conanfile.py\": tool,\n                \"app/conanfile.py\": GenConanfile().with_tool_requires(\"tool/1.0\")})\n        c.run(\"export dep\")\n        c.run(\"export wayland\")\n        c.run(\"export tool\")\n        c.run(\"install app --build=missing\")\n        assert \"Install finished successfully\" in c.out  # the asserts in build() didn't fail\n        # Now make sure we can actually build with build!=host context\n        c.run(\"install app -s:h build_type=Debug --build=missing\")\n        assert \"Install finished successfully\" in c.out  # the asserts in build() didn't fail\n\n    @pytest.mark.parametrize(\"build_folder_name\", [\"build\", \"\"])\n    def test_pkg_config_deps_set_in_build_context_folder(self, build_folder_name):\n        c = TestClient()\n        tool = textwrap.dedent(\"\"\"\n                    import os\n                    from conan import ConanFile\n                    from conan.tools.gnu import PkgConfigDeps\n\n                    class Example(ConanFile):\n                       name = \"tool\"\n                       version = \"1.0\"\n                       requires = \"wayland/1.0\"\n                       tool_requires = \"wayland/1.0\"\n\n                    def generate(self):\n                       deps = PkgConfigDeps(self)\n                       deps.set_property(\"wayland\", \"pkg_config_name\", \"waylandx264\")\n                       deps.build_context_activated = [\"wayland\", \"dep\"]\n                       deps.build_context_folder = \"{build_folder_name}\"\n                       deps.generate()\n\n                    def build(self):\n                        assert os.path.exists(\"waylandx264.pc\")\n                        assert not os.path.exists(\"wayland.pc\")\n                        if \"{build_folder_name}\":\n                            assert os.path.exists(\"{build_folder_name}/waylandx264.pc\")\n                            assert not os.path.exists(\"{build_folder_name}/wayland.pc\")\n                   \"\"\".format(build_folder_name=build_folder_name))\n        wayland = textwrap.dedent(\"\"\"\n               from conan import ConanFile\n\n               class Pkg(ConanFile):\n                   name = \"wayland\"\n                   version = \"1.0\"\n                   requires = \"dep/1.0\"\n\n                   def package_info(self):\n                       self.cpp_info.components[\"client\"].libs = []\n                       self.cpp_info.components[\"server\"].libs = []\n               \"\"\")\n        c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"1.0\").with_package_type(\"shared-library\"),\n                \"wayland/conanfile.py\": wayland,\n                \"tool/conanfile.py\": tool,\n                \"app/conanfile.py\": GenConanfile().with_tool_requires(\"tool/1.0\")})\n        c.run(\"create dep\")\n        c.run(\"create wayland\")\n        c.run(\"create tool\")\n        c.run(\"install app --build=missing\")\n        assert \"Install finished successfully\" in c.out  # the asserts in build() didn't fail\n        # Now make sure we can actually build with build!=host context\n        c.run(\"install app -s:h build_type=Debug --build=missing\")\n        assert \"Install finished successfully\" in c.out  # the asserts in build() didn't fail\n\n    def test_tool_requires_error_if_folder_and_suffix(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class PkgConfigConan(ConanFile):\n\n                def package_info(self):\n                    self.cpp_info.libs = [\"libtool\"]\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --name tool --version 1.0\")\n\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.gnu import PkgConfigDeps\n\n            class PkgConfigConan(ConanFile):\n                name = \"demo\"\n                version = \"1.0\"\n\n                def requirements(self):\n                    self.requires(\"tool/1.0\")\n\n                def build_requirements(self):\n                    self.build_requires(\"tool/1.0\")\n\n                def generate(self):\n                    tc = PkgConfigDeps(self)\n                    tc.build_context_activated = [\"tool\"]\n                    tc.build_context_folder = \"build\"\n                    tc.build_context_suffix = {\"tool\": \"_bt\"}\n                    tc.generate()\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile}, clean_first=True)\n        client.run(\"install . -pr:h default -pr:b default\", assert_error=True)\n        assert (\"It's not allowed to define both PkgConfigDeps.build_context_folder \"\n                \"and PkgConfigDeps.build_context_suffix (deprecated).\") in client.out\n\n\ndef test_pkg_config_deps_and_private_deps():\n    \"\"\"\n    Testing that no errors are raised when the dependency tree has a private one in the middle\n    of it.\n\n    Issue related: https://github.com/conan-io/conan/issues/15311\n    \"\"\"\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile(\"private\", \"0.1\")})\n    client.run(\"create .\")\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    class ConsumerConan(ConanFile):\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n        generators = \"PkgConfigDeps\"\n        name = \"pkg\"\n        version = \"0.1\"\n        def requirements(self):\n            self.requires(\"private/0.1\", visible=False)\n    \"\"\")\n    client.save({\"conanfile.py\": conanfile}, clean_first=True)\n    client.run(\"create .\")\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    class ConsumerConan(ConanFile):\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n        generators = \"PkgConfigDeps\"\n\n        def requirements(self):\n            self.requires(\"pkg/0.1\")\n    \"\"\")\n    client.save({\"conanfile.py\": conanfile}, clean_first=True)\n    # Now, it passes and creates the pc files correctly (the skipped one is not created)\n    client.run(\"install .\")\n    assert \"Requires:\" not in client.load(\"pkg.pc\")\n\n\ndef test_using_deployer_folder():\n    \"\"\"\n    Testing that the absolute path is kept as the prefix instead of the\n    relative path.\n\n    Issue related: https://github.com/conan-io/conan/issues/16543\n    \"\"\"\n    client = TestClient()\n    client.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\")})\n    client.run(\"create dep/conanfile.py\")\n    client.run(\"install --requires=dep/0.1 --deployer=direct_deploy \"\n               \"--deployer-folder=mydeploy -g PkgConfigDeps\")\n    content = client.load(\"dep.pc\")\n    prefix_base = client.current_folder.replace('\\\\', '/')\n    assert f\"prefix={prefix_base}/mydeploy/direct_deploy/dep\" in content\n    assert \"libdir=${prefix}/lib\" in content\n    assert \"includedir=${prefix}/include\" in content\n    assert \"bindir=${prefix}/bin\" in content\n\n\ndef test_pkg_config_deps_set_property():\n    c = TestClient()\n    app = textwrap.dedent(\"\"\"\\\n        import os\n        from conan import ConanFile\n        from conan.tools.gnu import PkgConfigDeps\n        class Pkg(ConanFile):\n            settings = \"build_type\"\n            requires = \"dep/0.1\", \"other/0.1\"\n            def generate(self):\n                pc = PkgConfigDeps(self)\n                pc.set_property(\"dep\", \"pkg_config_name\", \"depx264\")\n                pc.set_property(\"other::mycomp1\", \"nosoname\", True)\n                pc.set_property(\"other::mycomp1\", \"pkg_config_name\", \"new_other_comp\")\n                pc.generate()\n            \"\"\")\n\n    pkg_info = {\"components\": {\"mycomp1\": {\"libs\": [\"mylib\"]}}}\n    c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\").with_package_type(\"shared-library\"),\n            \"other/conanfile.py\": GenConanfile(\"other\", \"0.1\").with_package_type(\"shared-library\")\n                                                              .with_package_info(pkg_info),\n            \"app/conanfile.py\": app})\n    c.run(\"create dep\")\n    c.run(\"create other\")\n    c.run(\"install app\")\n    assert not os.path.exists(os.path.join(c.current_folder, \"app\", \"dep.pc\"))\n\n    dep = c.load(\"app/depx264.pc\")\n    assert 'Name: depx264' in dep\n    other = c.load(\"app/other.pc\")\n    assert 'Name: other' in other\n    other_mycomp1 = c.load(\"app/new_other_comp.pc\")\n    assert 'Name: new_other_comp' in other_mycomp1\n    assert other.split(\"\\n\")[0] == other_mycomp1.split(\"\\n\")[0]\n\n\ndef test_pkg_with_duplicated_component_requires():\n    \"\"\"\n    Testing that even having duplicated component requires, the PC does not include them.\n    Issue: https://github.com/conan-io/conan/issues/18283\n    \"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class PkgConfigConan(ConanFile):\n            def package_info(self):\n                self.cpp_info.components[\"mycomponent\"].libs = []\n                self.cpp_info.components[\"myfirstcomp\"].requires.append(\"mycomponent\")\n                # Duplicate one\n                self.cpp_info.components[\"myfirstcomp\"].requires.append(\"mycomponent\")\n\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile}, clean_first=True)\n    client.run(\"create . --name=mylib --version=0.1\")\n    client.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_require(\"mylib/0.1\")},\n                clean_first=True)\n    client.run(\"install . -g PkgConfigDeps\")\n    pc_content = client.load(\"mylib-myfirstcomp.pc\")\n    assert \"Requires: mylib-mycomponent\" == get_requires_from_content(pc_content)\n\n\ndef test_pkg_skip_component():\n    conanfile_a = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class PkgConfigConan(ConanFile):\n            name = \"pkg_a\"\n            version = \"0.1\"\n            def package_info(self):\n                self.cpp_info.set_property(\"pkg_config_name\", \"none\")\n        \"\"\")\n    conanfile_b = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class PkgConfigConan(ConanFile):\n            name = \"pkg_b\"\n            version = \"0.1\"\n            requires = \"pkg_a/0.1\"\n            def package_info(self):\n                self.cpp_info.components[\"cmp1\"].set_property(\"pkg_config_name\", \"b-cmp1\")\n        \"\"\")\n\n    conanfile_c = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class PkgConfigConan(ConanFile):\n                name = \"pkg_c\"\n                version = \"0.1\"\n                requires = \"pkg_b/0.1\"\n                def package_info(self):\n                    self.cpp_info.components[\"cmp2\"].set_property(\"pkg_config_name\", \"none\")\n            \"\"\")\n    tc = TestClient(light=True)\n    tc.save({\"a/conanfile.py\": conanfile_a,\n             \"b/conanfile.py\": conanfile_b,\n             \"c/conanfile.py\": conanfile_c})\n    tc.run(\"create a\")\n    tc.run(\"create b\")\n    tc.run(\"create c\")\n\n    tc.run(\"install --requires=pkg_c/0.1 --generator=PkgConfigDeps -of=out\")\n    install_contents = os.listdir(os.path.join(tc.current_folder, \"out\"))\n    assert \"pkg_a.pc\" not in install_contents\n    assert \"pkg_b.pc\" in install_contents\n    pkg_b_content = tc.load(os.path.join(\"out\", \"pkg_b.pc\"))\n    pkg_b_requires = get_requires_from_content(pkg_b_content)\n    assert \"b-cmp1\" in pkg_b_requires\n    assert \"pkg_a\" not in pkg_b_requires\n    assert \"none\" not in pkg_b_requires\n    assert \"b-cmp1.pc\" in install_contents\n    b_cmp1_content = tc.load(os.path.join(\"out\", \"b-cmp1.pc\"))\n    assert \"Requires:\" not in b_cmp1_content\n    assert \"pkg_c.pc\" in install_contents\n    # Components can not skip the PC file creation\n    assert \"none.pc\" in install_contents\n"
  },
  {
    "path": "test/integration/toolchains/google/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/toolchains/google/test_bazeldeps.py",
    "content": "import os\nimport pathlib\nimport platform\nimport re\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\nfrom conan.tools.files import load\n\n\ndef test_bazel():\n    # https://github.com/conan-io/conan/issues/10471\n    dep = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class ExampleConanIntegration(ConanFile):\n            name = \"dep\"\n            version = \"0.1\"\n            def package_info(self):\n                self.cpp_info.includedirs = []\n                self.cpp_info.libs = []\n        \"\"\")\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.google import BazelToolchain, BazelDeps\n\n        class ExampleConanIntegration(ConanFile):\n            generators = 'BazelDeps', 'BazelToolchain'\n            requires = 'dep/0.1',\n        \"\"\")\n    c = TestClient()\n    c.save({\"dep/conanfile.py\": dep,\n            \"consumer/conanfile.py\": conanfile})\n    c.run(\"create dep\")\n    c.run(\"install consumer\")\n    assert \"conanfile.py: Generator 'BazelToolchain' calling 'generate()'\" in c.out\n\n\ndef test_bazel_relative_paths():\n    # https://github.com/conan-io/conan/issues/10476\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.google import BazelToolchain, BazelDeps\n\n        class ExampleConanIntegration(ConanFile):\n            generators = 'BazelDeps', 'BazelToolchain'\n            requires = 'dep/0.1'\n\n            def layout(self):\n                self.folders.generators = \"conandeps\"\n        \"\"\")\n    c = TestClient()\n    c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\"),\n            \"consumer/conanfile.py\": conanfile})\n    c.run(\"create dep\")\n    c.run(\"install consumer\")\n    assert \"conanfile.py: Generator 'BazelToolchain' calling 'generate()'\" in c.out\n    build_file = c.load(\"consumer/conandeps/dep/BUILD.bazel\")\n    expected = textwrap.dedent(\"\"\"\\\n    # Components precompiled libs\n    # Root package precompiled libs\n\n    # Components libraries declaration\n    # Package library declaration\n    cc_library(\n        name = \"dep\",\n        hdrs = glob([\n            \"include/**\",\n        ],\n        allow_empty = True\n        ),\n        includes = [\n            \"include\",\n        ],\n        visibility = [\"//visibility:public\"],\n    )\n\n    # Filegroup library declaration\n    filegroup(\n        name = \"dep_binaries\",\n        srcs = glob([\n            \"bin/**\",\n        ],\n        allow_empty = True\n        ),\n        visibility = [\"//visibility:public\"],\n    )\n    \"\"\")\n    assert build_file == expected\n\n\ndef test_bazel_exclude_folders():\n    # https://github.com/conan-io/conan/issues/11081\n    dep = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import save\n        class ExampleConanIntegration(ConanFile):\n            name = \"dep\"\n            version = \"0.1\"\n            def package(self):\n                save(self, os.path.join(self.package_folder, \"lib\", \"mymath\", \"otherfile.a\"), \"\")\n                save(self, os.path.join(self.package_folder, \"lib\", \"libmymath.a\"), \"\")\n            def package_info(self):\n                self.cpp_info.libs = [\"mymath\"]\n        \"\"\")\n    c = TestClient()\n    c.save({\"dep/conanfile.py\": dep})\n    c.run(\"create dep\")\n    c.run(\"install --requires=dep/0.1 -g BazelDeps\")\n    build_file = c.load(\"dep/BUILD.bazel\")\n    assert 'static_library = \"lib/libmymath.a\"' in build_file\n\n\ndef test_bazeldeps_and_tool_requires():\n    \"\"\"\n    Testing that direct build requires are not included in dependencies BUILD.bazel files\n\n    Issues related:\n        * https://github.com/conan-io/conan/issues/12444\n        * https://github.com/conan-io/conan/issues/12236\n    \"\"\"\n    c = TestClient()\n    tool = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n\n        class ToolConanfile(ConanFile):\n            name = \"tool\"\n            version = \"0.1\"\n\n            def package_info(self):\n                self.cpp_info.libs = [\"mymath\"]\n        \"\"\")\n    c.save({\"tool/conanfile.py\": tool})\n    c.run(\"create tool\")\n    dep = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import save\n        class ExampleConanIntegration(ConanFile):\n            name = \"dep\"\n            version = \"0.1\"\n\n            def build_requirements(self):\n                self.tool_requires(\"tool/0.1\")\n            def package(self):\n                save(self, os.path.join(self.package_folder, \"lib\", \"mymath\", \"otherfile.a\"), \"\")\n                save(self, os.path.join(self.package_folder, \"lib\", \"libmymath.a\"), \"\")\n            def package_info(self):\n                self.cpp_info.libs = [\"mymath\"]\n                self.cpp_info.bindirs = [\"bin1\", \"bin2\"]\n        \"\"\")\n    c.save({\"dep/conanfile.py\": dep})\n    c.run(\"export dep\")\n    c.run(\"install --requires=dep/0.1 -g BazelDeps --build=missing\")\n    build_file = c.load(\"dep/BUILD.bazel\")\n    expected = textwrap.dedent(\"\"\"\\\n    # Components precompiled libs\n    # Root package precompiled libs\n    cc_import(\n        name = \"mymath_precompiled\",\n        static_library = \"lib/libmymath.a\",\n    )\n\n    # Components libraries declaration\n    # Package library declaration\n    cc_library(\n        name = \"dep\",\n        hdrs = glob([\n            \"include/**\",\n        ],\n        allow_empty = True\n        ),\n        includes = [\n            \"include\",\n        ],\n        visibility = [\"//visibility:public\"],\n        deps = [\n            # do not sort\n            \":mymath_precompiled\",\n        ],\n    )\n\n    # Filegroup library declaration\n    filegroup(\n        name = \"dep_binaries\",\n        srcs = glob([\n            \"bin1/**\",\n            \"bin2/**\",\n        ],\n        allow_empty = True\n        ),\n        visibility = [\"//visibility:public\"],\n    )\n    \"\"\")\n    assert expected == build_file\n\n\ndef test_pkg_with_public_deps_and_component_requires():\n    \"\"\"\n    Testing a complex structure like:\n\n    * first/0.1\n        - Global bazel_target_name == \"myfirstlib\"\n        - Components: \"cmp1\"\n    * other/0.1\n    * second/0.1\n        - Requires: \"first/0.1\"\n        - Components: \"mycomponent\", \"myfirstcomp\"\n            + \"mycomponent\" requires \"first::cmp1\"\n            + \"myfirstcomp\" requires \"mycomponent\"\n    * third/0.1\n        - Requires: \"second/0.1\", \"other/0.1\"\n\n    Expected file structure after running BazelDeps as generator:\n        - second/BUILD.bazel\n        - third/BUILD.bazel\n        - other/BUILD.bazel\n        - myfirstlib/BUILD.bazel\n    \"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import save\n\n        class Recipe(ConanFile):\n\n            def package(self):\n                # Saving an empty lib\n                dest_lib = os.path.join(self.package_folder, \"lib\", \"libcmp1.a\")\n                save(self, dest_lib, \"\")\n\n            def package_info(self):\n                self.cpp_info.set_property(\"bazel_target_name\", \"myfirstlib\")\n                self.cpp_info.components[\"cmp1\"].libs = [\"libcmp1\"]\n    \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=first --version=0.1\")\n    client.save({\"conanfile.py\": GenConanfile(\"other\", \"0.1\").with_package_file(\"file.h\", \"0.1\")})\n    client.run(\"create .\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class PkgBazelConan(ConanFile):\n            requires = \"first/0.1\"\n\n            def package_info(self):\n                self.cpp_info.components[\"mycomponent\"].requires.append(\"first::cmp1\")\n                self.cpp_info.components[\"myfirstcomp\"].requires.append(\"mycomponent\")\n\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile}, clean_first=True)\n    client.run(\"create . --name=second --version=0.1\")\n    client.save({\"conanfile.py\": GenConanfile(\"third\", \"0.1\").with_package_file(\"file.h\", \"0.1\")\n                                                             .with_require(\"second/0.1\")\n                                                             .with_require(\"other/0.1\")},\n                clean_first=True)\n    client.run(\"create .\")\n\n    client2 = TestClient(cache_folder=client.cache_folder)\n    conanfile = textwrap.dedent(\"\"\"\n        [requires]\n        third/0.1\n\n        [generators]\n        BazelDeps\n        \"\"\")\n    client2.save({\"conanfile.txt\": conanfile})\n    client2.run(\"install .\")\n    content = client2.load(\"third/BUILD.bazel\")\n    assert textwrap.dedent(\"\"\"\\\n    cc_library(\n        name = \"third\",\n        hdrs = glob([\n            \"include/**\",\n        ],\n        allow_empty = True\n        ),\n        includes = [\n            \"include\",\n        ],\n        visibility = [\"//visibility:public\"],\n        deps = [\n            # do not sort\n            \"@second//:second\",\n            \"@other//:other\",\n        ],\n    )\"\"\") in content\n    content = client2.load(\"second/BUILD.bazel\")\n    assert textwrap.dedent(\"\"\"\\\n    # Components libraries declaration\n    cc_library(\n        name = \"second-mycomponent\",\n        hdrs = glob([\n            \"include/**\",\n        ],\n        allow_empty = True\n        ),\n        includes = [\n            \"include\",\n        ],\n        visibility = [\"//visibility:public\"],\n        deps = [\n            # do not sort\n            \"@first//:myfirstlib-cmp1\",\n        ],\n    )\n\n    cc_library(\n        name = \"second-myfirstcomp\",\n        hdrs = glob([\n            \"include/**\",\n        ],\n        allow_empty = True\n        ),\n        includes = [\n            \"include\",\n        ],\n        visibility = [\"//visibility:public\"],\n        deps = [\n            # do not sort\n            \":second-mycomponent\",\n        ],\n    )\n\n    # Package library declaration\n    cc_library(\n        name = \"second\",\n        hdrs = glob([\n            \"include/**\",\n        ],\n        allow_empty = True\n        ),\n        includes = [\n            \"include\",\n        ],\n        visibility = [\"//visibility:public\"],\n        deps = [\n            # do not sort\n            \":second-mycomponent\",\n            \":second-myfirstcomp\",\n            \"@first//:myfirstlib\",\n        ],\n    )\"\"\") in content\n    content = client2.load(\"first/BUILD.bazel\")\n    assert textwrap.dedent(\"\"\"\\\n    # Components precompiled libs\n    cc_import(\n        name = \"libcmp1_precompiled\",\n        static_library = \"lib/libcmp1.a\",\n    )\n\n    # Root package precompiled libs\n\n    # Components libraries declaration\n    cc_library(\n        name = \"myfirstlib-cmp1\",\n        hdrs = glob([\n            \"include/**\",\n        ],\n        allow_empty = True\n        ),\n        includes = [\n            \"include\",\n        ],\n        visibility = [\"//visibility:public\"],\n        deps = [\n            # do not sort\n            \":libcmp1_precompiled\",\n        ],\n    )\n\n    # Package library declaration\n    cc_library(\n        name = \"myfirstlib\",\n        hdrs = glob([\n            \"include/**\",\n        ],\n        allow_empty = True\n        ),\n        includes = [\n            \"include\",\n        ],\n        visibility = [\"//visibility:public\"],\n        deps = [\n            # do not sort\n            \":myfirstlib-cmp1\",\n        ],\n    )\"\"\") in content\n    content = client2.load(\"other/BUILD.bazel\")\n    assert \"deps =\" not in content\n\n\ndef test_pkg_with_public_deps_and_component_requires_2():\n    \"\"\"\n    Testing another complex structure like:\n\n    * other/0.1\n        - Global bazel_target_name == \"fancy_name\"\n        - Components: \"cmp1\", \"cmp2\", \"cmp3\"\n            + \"cmp1\" bazel_target_name == \"component1\" (it shouldn't be affected by \"fancy_name\")\n            + \"cmp3\" bazel_target_name == \"component3\" (it shouldn't be affected by \"fancy_name\")\n            + \"cmp3\" requires \"cmp1\"\n    * pkg/0.1\n        - Requires: \"other/0.1\" -> \"other::cmp1\"\n\n    Expected file structure after running BazelDeps as generator:\n        - fancy_name/BUILD.bazel (components: \"component1\", \"fancy_name-cmp2\", \"component3\")\n        - pkg/BUILD.bazel\n    \"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import save\n\n        class Recipe(ConanFile):\n\n            def package(self):\n                # Saving an empty lib\n                dest_lib = os.path.join(self.package_folder, \"lib\", \"libother_cmp1.a\")\n                dest_lib2 = os.path.join(self.package_folder, \"lib\", \"libother_cmp2.a\")\n                save(self, dest_lib, \"\")\n                save(self, dest_lib2, \"\")\n\n            def package_info(self):\n                self.cpp_info.set_property(\"bazel_target_name\", \"fancy_name\")\n                self.cpp_info.components[\"cmp1\"].libs = [\"other_cmp1\"]\n                self.cpp_info.components[\"cmp1\"].set_property(\"bazel_target_name\", \"component1\")\n                self.cpp_info.components[\"cmp2\"].libs = [\"other_cmp2\"]\n                self.cpp_info.components[\"cmp3\"].requires.append(\"cmp1\")\n                self.cpp_info.components[\"cmp3\"].set_property(\"bazel_target_name\", \"component3\")\n    \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=other --version=1.0\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class PkgBazelConan(ConanFile):\n            requires = \"other/1.0\"\n\n            def package_info(self):\n                self.cpp_info.requires = [\"other::cmp1\"]\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=pkg --version=0.1\")\n\n    client2 = TestClient(cache_folder=client.cache_folder)\n    conanfile = textwrap.dedent(\"\"\"\n        [requires]\n        pkg/0.1\n\n        [generators]\n        BazelDeps\n        \"\"\")\n    client2.save({\"conanfile.txt\": conanfile})\n    client2.run(\"install .\")\n    content = client2.load(\"pkg/BUILD.bazel\")\n    assert textwrap.dedent(\"\"\"\\\n    # Package library declaration\n    cc_library(\n        name = \"pkg\",\n        hdrs = glob([\n            \"include/**\",\n        ],\n        allow_empty = True\n        ),\n        includes = [\n            \"include\",\n        ],\n        visibility = [\"//visibility:public\"],\n        deps = [\n            # do not sort\n            \"@other//:component1\",\n        ],\n    )\"\"\") in content\n    content = client2.load(\"other/BUILD.bazel\")\n    assert textwrap.dedent(\"\"\"\\\n    # Components precompiled libs\n    cc_import(\n        name = \"other_cmp1_precompiled\",\n        static_library = \"lib/libother_cmp1.a\",\n    )\n\n    cc_import(\n        name = \"other_cmp2_precompiled\",\n        static_library = \"lib/libother_cmp2.a\",\n    )\n\n\n    # Root package precompiled libs\n\n    # Components libraries declaration\n    cc_library(\n        name = \"component1\",\n        hdrs = glob([\n            \"include/**\",\n        ],\n        allow_empty = True\n        ),\n        includes = [\n            \"include\",\n        ],\n        visibility = [\"//visibility:public\"],\n        deps = [\n            # do not sort\n            \":other_cmp1_precompiled\",\n        ],\n    )\n\n    cc_library(\n        name = \"fancy_name-cmp2\",\n        hdrs = glob([\n            \"include/**\",\n        ],\n        allow_empty = True\n        ),\n        includes = [\n            \"include\",\n        ],\n        visibility = [\"//visibility:public\"],\n        deps = [\n            # do not sort\n            \":other_cmp2_precompiled\",\n        ],\n    )\n\n    cc_library(\n        name = \"component3\",\n        hdrs = glob([\n            \"include/**\",\n        ],\n        allow_empty = True\n        ),\n        includes = [\n            \"include\",\n        ],\n        visibility = [\"//visibility:public\"],\n        deps = [\n            # do not sort\n            \":component1\",\n        ],\n    )\n\n    # Package library declaration\n    cc_library(\n        name = \"fancy_name\",\n        hdrs = glob([\n            \"include/**\",\n        ],\n        allow_empty = True\n        ),\n        includes = [\n            \"include\",\n        ],\n        visibility = [\"//visibility:public\"],\n        deps = [\n            # do not sort\n            \":component1\",\n            \":fancy_name-cmp2\",\n            \":component3\",\n        ],\n    )\"\"\") in content\n\n\ndef test_pkgconfigdeps_with_test_requires():\n    \"\"\"\n    BazelDeps has to create any declared test requirements on the recipe.\n    \"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import save\n\n        class Recipe(ConanFile):\n\n            def package(self):\n                # Saving an empty lib\n                dest_lib = os.path.join(self.package_folder, \"lib\", \"liblib{0}.a\")\n                save(self, dest_lib, \"\")\n\n            def package_info(self):\n                self.cpp_info.libs = [\"lib{0}\"]\n        \"\"\")\n    with client.chdir(\"app\"):\n        client.save({\"conanfile.py\": conanfile.format(\"app\")})\n        client.run(\"create . --name=app --version=1.0\")\n    with client.chdir(\"test\"):\n        client.save({\"conanfile.py\": conanfile.format(\"test\")})\n        client.run(\"create . --name=test --version=1.0\")\n    # Create library having build and test requires\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class HelloLib(ConanFile):\n            def build_requirements(self):\n                self.test_requires('app/1.0')\n                self.test_requires('test/1.0')\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile}, clean_first=True)\n    client.run(\"install . -g BazelDeps\")\n    expected = textwrap.dedent(\"\"\"\\\n    # Root package precompiled libs\n    cc_import(\n        name = \"lib{0}_precompiled\",\n        static_library = \"lib/liblib{0}.a\",\n    )\n\n    # Components libraries declaration\n    # Package library declaration\n    cc_library(\n        name = \"{0}\",\n        hdrs = glob([\n            \"include/**\",\n        ],\n        allow_empty = True\n        ),\n        includes = [\n            \"include\",\n        ],\n        visibility = [\"//visibility:public\"],\n        deps = [\n            # do not sort\n            \":lib{0}_precompiled\",\n        ],\n    )\"\"\")\n    assert expected.format(\"test\") in client.load(\"test/BUILD.bazel\")\n    assert expected.format(\"app\") in client.load(\"app/BUILD.bazel\")\n\n\ndef test_with_editable_layout():\n    \"\"\"\n    Testing if editable mode is working for a Bazel project (using BazelDeps and bazel_layout)\n    \"\"\"\n    client = TestClient()\n    dep = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.google import bazel_layout\n        from conan.tools.files import save\n        class Dep(ConanFile):\n            name = \"dep\"\n            version = \"0.1\"\n\n            def layout(self):\n                bazel_layout(self, target_folder=\"main\")\n                self.cpp.source.includedirs = [\"include\"]\n\n            def package_info(self):\n                self.cpp_info.libs = [\"mylib\"]\n        \"\"\")\n    client.save({\"dep/conanfile.py\": dep,\n                 \"dep/include/header.h\": \"\",\n                 \"dep/bazel-bin/main/libmylib.a\": \"\",\n                 \"pkg/conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_requires(\"dep/0.1\")})\n    client.run(\"create dep\")\n    client.run(\"editable add dep --name=dep --version=0.1\")\n    recipes_folder = client.current_folder.replace(\"\\\\\", \"/\")\n    with client.chdir(\"pkg\"):\n        client.run(\"install . -g BazelDeps\")\n        # TODO: Remove when dropped Bazel 6.x compatibility\n        content = client.load(\"dependencies.bzl\")\n        assert textwrap.dedent(f\"\"\"\\\n        def load_conan_dependencies():\n            native.new_local_repository(\n                name=\"dep\",\n                path=\"{recipes_folder}/dep\",\n                build_file=\"{recipes_folder}/pkg/dep/BUILD.bazel\",\n            )\"\"\") in content\n        # Bazel 7.x\n        content = client.load(\"conan_deps_module_extension.bzl\")\n        assert textwrap.dedent(f\"\"\"\\\n        def _load_dependencies_impl(mctx):\n            conan_dependency_repo(\n                name = \"dep\",\n                package_path = \"{recipes_folder}/dep\",\n                build_file_path = \"{recipes_folder}/pkg/dep/BUILD.bazel\",\n            )\"\"\") in content\n        content = client.load(\"dep/BUILD.bazel\")\n        assert pathlib.Path(client.current_folder, \"conan_deps_repo_rules.bzl\").exists()\n        assert textwrap.dedent(\"\"\"\\\n        cc_import(\n            name = \"mylib_precompiled\",\n            static_library = \"bazel-bin/main/libmylib.a\",\n        )\n\n        # Components libraries declaration\n        # Package library declaration\n        cc_library(\n            name = \"dep\",\n            hdrs = glob([\n                \"include/**\",\n            ],\n            allow_empty = True\n            ),\n            includes = [\n                \"include\",\n            ],\n            visibility = [\"//visibility:public\"],\n            deps = [\n                # do not sort\n                \":mylib_precompiled\",\n            ],\n        )\"\"\") in content\n\n\ndef test_tool_requires():\n    \"\"\"\n    Testing if BUILD files are created for tool requires if build_context_activated=True is used.\n    \"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import save\n\n        class PkgBazelConan(ConanFile):\n\n            def package(self):\n                import os\n                libdirs = os.path.join(self.package_folder, \"lib\")\n                save(self, os.path.join(libdirs, \"libtool.lib\"), \"\")\n\n            def package_info(self):\n                self.cpp_info.libs = [\"libtool\"]\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=tool --version=1.0\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import save\n\n        class PkgBazelConan(ConanFile):\n\n            def package(self):\n                import os\n                libdirs = os.path.join(self.package_folder, \"lib\")\n                save(self, os.path.join(libdirs, \"other_cmp1.lib\"), \"\")\n                save(self, os.path.join(libdirs, \"other_cmp2.lib\"), \"\")\n\n            def package_info(self):\n                self.cpp_info.set_property(\"bazel_target_name\", \"libother\")\n                self.cpp_info.set_property(\"bazel_repository_name\", \"other-repo\")\n                self.cpp_info.components[\"cmp1\"].libs = [\"other_cmp1\"]\n                self.cpp_info.components[\"cmp1\"].set_property(\"bazel_target_name\", \"component1\")\n                self.cpp_info.components[\"cmp2\"].libs = [\"other_cmp2\"]\n                self.cpp_info.components[\"cmp3\"].requires.append(\"cmp1\")\n                self.cpp_info.components[\"cmp3\"].set_property(\"bazel_target_name\", \"component3\")\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile}, clean_first=True)\n    client.run(\"create . --name=other --version=1.0\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.google import BazelDeps\n\n        class PkgBazelConan(ConanFile):\n            name = \"demo\"\n            version = \"1.0\"\n\n            def build_requirements(self):\n                self.tool_requires(\"tool/1.0\")\n                self.tool_requires(\"other/1.0\")\n\n            def generate(self):\n                tc = BazelDeps(self)\n                tc.build_context_activated = [\"other\", \"tool\"]\n                tc.generate()\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile}, clean_first=True)\n    client.run(\"install . -pr:h default -pr:b default\")\n    assert 'name = \"tool\"' in client.load(\"build-tool/BUILD.bazel\")\n    assert textwrap.dedent(\"\"\"\\\n    # Components precompiled libs\n    cc_import(\n        name = \"other_cmp1_precompiled\",\n        static_library = \"lib/other_cmp1.lib\",\n    )\n\n    cc_import(\n        name = \"other_cmp2_precompiled\",\n        static_library = \"lib/other_cmp2.lib\",\n    )\n\n\n    # Root package precompiled libs\n\n    # Components libraries declaration\n    cc_library(\n        name = \"component1\",\n        hdrs = glob([\n            \"include/**\",\n        ],\n        allow_empty = True\n        ),\n        includes = [\n            \"include\",\n        ],\n        visibility = [\"//visibility:public\"],\n        deps = [\n            # do not sort\n            \":other_cmp1_precompiled\",\n        ],\n    )\n\n    cc_library(\n        name = \"libother-cmp2\",\n        hdrs = glob([\n            \"include/**\",\n        ],\n        allow_empty = True\n        ),\n        includes = [\n            \"include\",\n        ],\n        visibility = [\"//visibility:public\"],\n        deps = [\n            # do not sort\n            \":other_cmp2_precompiled\",\n        ],\n    )\n\n    cc_library(\n        name = \"component3\",\n        hdrs = glob([\n            \"include/**\",\n        ],\n        allow_empty = True\n        ),\n        includes = [\n            \"include\",\n        ],\n        visibility = [\"//visibility:public\"],\n        deps = [\n            # do not sort\n            \":component1\",\n        ],\n    )\n\n    # Package library declaration\n    cc_library(\n        name = \"libother\",\n        hdrs = glob([\n            \"include/**\",\n        ],\n        allow_empty = True\n        ),\n        includes = [\n            \"include\",\n        ],\n        visibility = [\"//visibility:public\"],\n        deps = [\n            # do not sort\n            \":component1\",\n            \":libother-cmp2\",\n            \":component3\",\n        ],\n    )\"\"\") in client.load(\"build-other-repo/BUILD.bazel\")\n    # TODO: Remove when dropped Bazel 6.x compatibility\n    # Let's check if the names used in the dependencies.bzl are correct\n    content = client.load(\"dependencies.bzl\")\n    assert 'name=\"build-other-repo\"' in content  # build context + bazel_repository_name prop\n    assert 'name=\"build-tool\"' in content  # build context + package reference name\n    # Bazel 7.x\n    # Let's check if the names used in the conan_deps_repo_rules.bzl are correct\n    content = client.load(\"conan_deps_module_extension.bzl\")\n    assert 'name = \"build-other-repo\"' in content  # build context + bazel_repository_name prop\n    assert 'name = \"build-tool\"' in content  # build context + package reference name\n\n\ndef test_tool_requires_not_created_if_no_activated():\n    \"\"\"\n    Testing if there are no BUILD files created in no context are activated\n    \"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import save\n\n        class PkgBazelConan(ConanFile):\n\n            def package(self):\n                import os\n                libdirs = os.path.join(self.package_folder, \"lib\")\n                save(self, os.path.join(libdirs, \"libtool.lib\"), \"\")\n            def package_info(self):\n                self.cpp_info.libs = [\"libtool\"]\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=tool --version=1.0\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class PkgBazelConan(ConanFile):\n            name = \"demo\"\n            version = \"1.0\"\n            generators = \"BazelDeps\"\n\n            def build_requirements(self):\n                self.tool_requires(\"tool/1.0\")\n\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile}, clean_first=True)\n    client.run(\"install . -pr:h default -pr:b default\")\n    assert not os.path.exists(os.path.join(client.current_folder, \"tool\"))\n\n\ndef test_tool_requires_raise_exception_if_exist_both_require_and_build_one():\n    \"\"\"\n    Testing if same dependency exists in both host and build context\n    \"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.files import save\n\n        class PkgBazelConan(ConanFile):\n\n            def package(self):\n                import os\n                libdirs = os.path.join(self.package_folder, \"lib\")\n                save(self, os.path.join(libdirs, \"libtool.lib\"), \"\")\n            def package_info(self):\n                self.cpp_info.libs = [\"libtool\"]\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . --name=tool --version=1.0\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.google import BazelDeps\n\n        class PkgBazelConan(ConanFile):\n            name = \"demo\"\n            version = \"1.0\"\n\n            def requirements(self):\n                self.requires(\"tool/1.0\")\n\n            def build_requirements(self):\n                self.tool_requires(\"tool/1.0\")\n\n            def generate(self):\n                tc = BazelDeps(self)\n                tc.build_context_activated = [\"tool\"]\n                tc.generate()\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile}, clean_first=True)\n    client.run(\"install . -pr:h default -pr:b default\")\n    # Different Bazel repository names, same target names\n    assert 'name = \"tool\"' in client.load(\"build-tool/BUILD.bazel\")\n    assert 'name = \"tool\"' in client.load(\"tool/BUILD.bazel\")\n\n\ndef test_error_missing_bazel_build_files_in_build_context():\n    \"\"\"\n    BazelDeps should generate BUILD files in the build context for a\n    test_package that both requires(example/1.0) and tool_requires(example/1.0),\n    which depends on other requirements\n    * Issue related: https://github.com/conan-io/conan/issues/12664\n    \"\"\"\n    c = TestClient()\n    example = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        class Example(ConanFile):\n            name = \"example\"\n            version = \"1.0\"\n            requires = \"game/1.0\"\n            generators = \"BazelDeps\"\n            settings = \"build_type\"\n            def build(self):\n                context = \"build-\" if self.context == \"build\" else \"\"\n                assert os.path.exists(os.path.join(f\"{context}math\", \"BUILD.bazel\"))\n                assert os.path.exists(os.path.join(f\"{context}engine\", \"BUILD.bazel\"))\n                assert os.path.exists(os.path.join(f\"{context}game\", \"BUILD.bazel\"))\n            \"\"\")\n    c.save({\"math/conanfile.py\": GenConanfile(\"math\", \"1.0\").with_settings(\"build_type\"),\n            \"engine/conanfile.py\": GenConanfile(\"engine\", \"1.0\").with_settings(\"build_type\")\n                                                                .with_require(\"math/1.0\"),\n            \"game/conanfile.py\": GenConanfile(\"game\", \"1.0\").with_settings(\"build_type\")\n                                                            .with_requires(\"engine/1.0\"),\n            \"example/conanfile.py\": example,\n            # With ``with_test()`` it already generates a requires(example/1.0)\n            \"example/test_package/conanfile.py\": GenConanfile().with_build_requires(\"example/1.0\")\n                                                               .with_test(\"pass\")})\n    c.run(\"create math\")\n    c.run(\"create engine\")\n    c.run(\"create game\")\n    # This used to crash because of the assert inside the build() method\n    c.run(\"create example -pr:b=default -pr:h=default\")\n    # Now make sure we can actually build with build!=host context\n    # The debug binaries are missing, so adding --build=missing\n    c.run(\"create example -pr:b=default -pr:h=default -s:h build_type=Debug --build=missing \"\n          \"--build=example\")\n    c.assert_listed_require({\"example/1.0\": \"Cache\"})\n    c.assert_listed_require({\"example/1.0\": \"Cache\"}, build=True)\n\n\nclass TestBazelGenerationBuildContext:\n    \"\"\"\n    https://github.com/conan-io/conan/issues/15764\n    \"\"\"\n    def test_bazel_generate(self):\n        c = TestClient()\n        tool = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.google import BazelDeps\n            class Example(ConanFile):\n                name = \"tool\"\n                version = \"1.0\"\n                requires = \"wayland/1.0\"\n                tool_requires = \"wayland/1.0\"\n                def generate(self):\n                    tc = BazelDeps(self)\n                    tc.build_context_activated = [\"wayland\", \"dep\"]\n                    tc.generate()\n                def build(self):\n                    # Build context\n                    assert os.path.exists(os.path.join(\"build-wayland\", \"BUILD.bazel\"))\n                    # Revisit this after investigation -> build_req = conanfile.dependencies.direct_build\n                    # assert os.path.exists(os.path.join(\"build-dep\", \"BUILD.bazel\"))\n                    # Host context\n                    assert os.path.exists(os.path.join(\"wayland\", \"BUILD.bazel\"))\n                    assert os.path.exists(os.path.join(\"dep\", \"BUILD.bazel\"))\n                \"\"\")\n        c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"1.0\").with_package_type(\"shared-library\"),\n                \"wayland/conanfile.py\": GenConanfile(\"wayland\", \"1.0\").with_requires(\"dep/1.0\"),\n                \"tool/conanfile.py\": tool,\n                \"app/conanfile.py\": GenConanfile().with_tool_requires(\"tool/1.0\")})\n        c.run(\"export dep\")\n        c.run(\"export wayland\")\n        c.run(\"export tool\")\n        c.run(\"install app --build=missing\")\n        assert \"Install finished successfully\" in c.out  # the asserts in build() didn't fail\n        # Now make sure we can actually build with build!=host context\n        c.run(\"install app -s:h build_type=Debug --build=missing\")\n        assert \"Install finished successfully\" in c.out  # the asserts in build() didn't fail\n\n    def test_bazel_generate_components(self):\n        c = TestClient()\n        tool = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.google import BazelDeps\n            class Example(ConanFile):\n                name = \"tool\"\n                version = \"1.0\"\n                requires = \"wayland/1.0\"\n                tool_requires = \"wayland/1.0\"\n                def generate(self):\n                    tc = BazelDeps(self)\n                    tc.build_context_activated = [\"wayland\", \"dep\"]\n                    tc.generate()\n                def build(self):\n                    # Build context\n                    assert os.path.exists(os.path.join(\"build-wayland\", \"BUILD.bazel\"))\n                    # Revisit this after investigation -> build_req = conanfile.dependencies.direct_build\n                    # assert os.path.exists(os.path.join(\"build-dep\", \"BUILD.bazel\"))\n                    # Host context\n                    assert os.path.exists(os.path.join(\"wayland\", \"BUILD.bazel\"))\n                    assert os.path.exists(os.path.join(\"dep\", \"BUILD.bazel\"))\n                \"\"\")\n        wayland = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Pkg(ConanFile):\n                name = \"wayland\"\n                version = \"1.0\"\n                requires = \"dep/1.0\"\n                def package_info(self):\n                    self.cpp_info.components[\"client\"].libs = []\n                    self.cpp_info.components[\"server\"].libs = []\n            \"\"\")\n        c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"1.0\").with_package_type(\"shared-library\"),\n                \"wayland/conanfile.py\": wayland,\n                \"tool/conanfile.py\": tool,\n                \"app/conanfile.py\": GenConanfile().with_tool_requires(\"tool/1.0\")})\n        c.run(\"export dep\")\n        c.run(\"export wayland\")\n        c.run(\"export tool\")\n        c.run(\"install app --build=missing\")\n        assert \"Install finished successfully\" in c.out  # the asserts in build() didn't fail\n        # Now make sure we can actually build with build!=host context\n        c.run(\"install app -s:h build_type=Debug --build=missing\")\n        assert \"Install finished successfully\" in c.out  # the asserts in build() didn't fail\n\n\ndef test_shared_windows_find_libraries():\n    \"\"\"\n    Testing the ``_get_libs`` mechanism in Windows, the shared libraries and their\n    import ones are correctly found.\n\n    Note: simulating dependencies with openssl, libcurl, and zlib packages:\n\n    zlib:\n        - (zlib package) bin/zlib1.dll AND lib/zdll.lib\n    libcurl:\n        - (curl component) bin/libcurl.dll AND lib/libcurl_imp.lib\n    openssl:\n        - (crypto component) bin/libcrypto-3-x64.dll AND lib/libcrypto.lib\n        - (ssl component) bin/libssl-3-x64.dll AND lib/libssl.lib\n\n\n    Issue: https://github.com/conan-io/conan/issues/16691\n    \"\"\"\n    c = TestClient()\n    zlib = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import save\n        class Example(ConanFile):\n            name = \"zlib\"\n            version = \"1.0\"\n            options = {\"shared\": [True, False]}\n            default_options = {\"shared\": False}\n            def package(self):\n                bindirs = os.path.join(self.package_folder, \"bin\")\n                libdirs = os.path.join(self.package_folder, \"lib\")\n                save(self, os.path.join(bindirs, \"zlib1.dll\"), \"\")\n                save(self, os.path.join(libdirs, \"zdll.lib\"), \"\")\n            def package_info(self):\n                self.cpp_info.libs = [\"zdll\"]\n            \"\"\")\n    libiconv = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import save\n        class Example(ConanFile):\n            name = \"libiconv\"\n            version = \"1.0\"\n            options = {\"shared\": [True, False]}\n            default_options = {\"shared\": False}\n            def package(self):\n                bindirs = os.path.join(self.package_folder, \"bin\")\n                libdirs = os.path.join(self.package_folder, \"lib\")\n                save(self, os.path.join(bindirs, \"charset-1.dll\"), \"\")\n                save(self, os.path.join(bindirs, \"iconv-2.dll\"), \"\")\n                save(self, os.path.join(libdirs, \"charset.lib\"), \"\")\n                save(self, os.path.join(libdirs, \"iconv.lib\"), \"\")\n            def package_info(self):\n                self.cpp_info.libs = [\"iconv\", \"charset\"]\n            \"\"\")\n    openssl = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import save\n        class Pkg(ConanFile):\n            name = \"openssl\"\n            version = \"1.0\"\n            options = {\"shared\": [True, False]}\n            default_options = {\"shared\": False}\n            def package(self):\n                bindirs = os.path.join(self.package_folder, \"bin\")\n                libdirs = os.path.join(self.package_folder, \"lib\")\n                save(self, os.path.join(bindirs, \"libcrypto-3-x64.dll\"), \"\")\n                save(self, os.path.join(bindirs, \"libssl-3-x64.dll\"), \"\")\n                save(self, os.path.join(libdirs, \"libcrypto.lib\"), \"\")\n                save(self, os.path.join(libdirs, \"libssl.lib\"), \"\")\n            def package_info(self):\n                self.cpp_info.components[\"crypto\"].libs = [\"libcrypto\"]\n                self.cpp_info.components[\"ssl\"].libs = [\"libssl\"]\n        \"\"\")\n    libcurl = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import save\n        class Example(ConanFile):\n            name = \"libcurl\"\n            version = \"1.0\"\n            options = {\"shared\": [True, False]}\n            default_options = {\"shared\": False}\n            def package(self):\n                bindirs = os.path.join(self.package_folder, \"bin\")\n                libdirs = os.path.join(self.package_folder, \"lib\")\n                save(self, os.path.join(bindirs, \"libcurl.dll\"), \"\")\n                save(self, os.path.join(libdirs, \"libcurl_imp.lib\"), \"\")\n            def package_info(self):\n                self.cpp_info.components[\"curl\"].libs = [\"libcurl_imp\"]\n            \"\"\")\n    consumer = textwrap.dedent(\"\"\"\n        [requires]\n        zlib/1.0\n        openssl/1.0\n        libcurl/1.0\n        libiconv/1.0\n        [options]\n        *:shared=True\n    \"\"\")\n    c.save({\"conanfile.txt\": consumer,\n            \"zlib/conanfile.py\": zlib,\n            \"openssl/conanfile.py\": openssl,\n            \"libcurl/conanfile.py\": libcurl,\n            \"libiconv/conanfile.py\": libiconv\n            })\n    c.run(\"export-pkg zlib -o:a shared=True\")\n    c.run(\"export-pkg openssl -o:a shared=True\")\n    c.run(\"export-pkg libcurl -o:a shared=True\")\n    c.run(\"export-pkg libiconv -o:a shared=True\")\n    c.run(\"install . -g BazelDeps\")\n    libcurl_bazel_build = load(None, os.path.join(c.current_folder, \"libcurl\", \"BUILD.bazel\"))\n    zlib_bazel_build = load(None, os.path.join(c.current_folder, \"zlib\", \"BUILD.bazel\"))\n    openssl_bazel_build = load(None, os.path.join(c.current_folder, \"openssl\", \"BUILD.bazel\"))\n    libiconv_bazel_build = load(None, os.path.join(c.current_folder, \"libiconv\", \"BUILD.bazel\"))\n    libcurl_expected = textwrap.dedent(\"\"\"\\\n    # Components precompiled libs\n    cc_import(\n        name = \"libcurl_imp_precompiled\",\n        shared_library = \"bin/libcurl.dll\",\n        interface_library = \"lib/libcurl_imp.lib\",\n    )\n    \"\"\")\n    openssl_expected = textwrap.dedent(\"\"\"\\\n    # Components precompiled libs\n    cc_import(\n        name = \"libcrypto_precompiled\",\n        shared_library = \"bin/libcrypto-3-x64.dll\",\n        interface_library = \"lib/libcrypto.lib\",\n    )\n\n    cc_import(\n        name = \"libssl_precompiled\",\n        shared_library = \"bin/libssl-3-x64.dll\",\n        interface_library = \"lib/libssl.lib\",\n    )\n    \"\"\")\n    zlib_expected = textwrap.dedent(\"\"\"\\\n    cc_import(\n        name = \"zdll_precompiled\",\n        shared_library = \"bin/zlib1.dll\",\n        interface_library = \"lib/zdll.lib\",\n    )\n    \"\"\")\n    iconv_expected = textwrap.dedent(\"\"\"\\\n    cc_import(\n        name = \"iconv_precompiled\",\n        shared_library = \"bin/iconv-2.dll\",\n        interface_library = \"lib/iconv.lib\",\n    )\n    \"\"\")\n    charset_expected = textwrap.dedent(\"\"\"\\\n    cc_import(\n        name = \"charset_precompiled\",\n        shared_library = \"bin/charset-1.dll\",\n        interface_library = \"lib/charset.lib\",\n    )\n    \"\"\")\n    assert libcurl_expected in libcurl_bazel_build\n    assert zlib_expected in zlib_bazel_build\n    assert openssl_expected in openssl_bazel_build\n    assert iconv_expected in libiconv_bazel_build and charset_expected in libiconv_bazel_build\n\n\ndef test_pkg_with_duplicated_component_requires():\n    \"\"\"\n    Testing that even having duplicated component requires, the PC does not include them.\n    Issue: https://github.com/conan-io/conan/issues/18283\n    \"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class PkgConfigConan(ConanFile):\n            def package_info(self):\n                self.cpp_info.components[\"mycomponent\"].libs = []\n                self.cpp_info.components[\"myfirstcomp\"].requires.append(\"mycomponent\")\n                # Duplicate one\n                self.cpp_info.components[\"myfirstcomp\"].requires.append(\"mycomponent\")\n\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile}, clean_first=True)\n    client.run(\"create . --name=mylib --version=0.1\")\n    client.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_require(\"mylib/0.1\")},\n                clean_first=True)\n    client.run(\"install . -g BazelDeps\")\n    build_content = load(None, os.path.join(client.current_folder, \"mylib\", \"BUILD.bazel\"))\n    myfirstcomp_expected = textwrap.dedent(\"\"\"\\\n    cc_library(\n        name = \"mylib-myfirstcomp\",\n        hdrs = glob([\n            \"include/**\",\n        ],\n        allow_empty = True\n        ),\n        includes = [\n            \"include\",\n        ],\n        visibility = [\"//visibility:public\"],\n        deps = [\n            # do not sort\n            \":mylib-mycomponent\",\n        ],\n    )\n    \"\"\")\n    assert myfirstcomp_expected in build_content\n\n\n@pytest.mark.skipif(platform.system() == \"Windows\", reason=\"Unix paths only\")\ndef test_apple_frameworks_and_frameworkdirs():\n    \"\"\"\n    Testing that Apple frameworks are included as linkopts\n    Issue: https://github.com/conan-io/conan/issues/18748\n    \"\"\"\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n\n        class PkgConfigConan(ConanFile):\n            def package_info(self):\n                self.cpp_info.frameworks = [\"CoreFoundation\", \"Cocoa\"]\n                self.cpp_info.frameworkdirs = [\"/my/path/to/frw1\"]\n\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile}, clean_first=True)\n    client.run(\"create . --name=mylib --version=0.1\")\n    client.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_require(\"mylib/0.1\")},\n                clean_first=True)\n    client.run(\"install . -g BazelDeps\")\n    build_content = load(None, os.path.join(client.current_folder, \"mylib\", \"BUILD.bazel\"))\n    build_file_expected = textwrap.dedent(\"\"\"\\\n    cc_library(\n        name = \"mylib\",\n        hdrs = glob([\n            \"include/**\",\n        ],\n        allow_empty = True\n        ),\n        includes = [\n            \"include\",\n        ],\n        linkopts = [\n            \"-framework\",\n            \"CoreFoundation\",\n            \"-framework\",\n            \"Cocoa\",\n            \"-F\",\n            \"/my/path/to/frw1\",\n        ],\n        visibility = [\"//visibility:public\"],\n    )\n    \"\"\")\n    assert build_file_expected in build_content\n\n\ndef test_shared_libs_and_unix_includes_rpath():\n    \"\"\"\n    Testing the RPATH flag is added to the BUILD.bazel file if these conditions\n    are given: shared library and UNIX systems.\n\n    Issue: https://github.com/conan-io/conan/issues/19190\n    Issue: https://github.com/conan-io/conan/issues/19135\n    \"\"\"\n    client = TestClient()\n    csm = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import save\n        class Pkg(ConanFile):\n            name = \"csm\"\n            version = \"1.0\"\n            settings = \"os\"\n            options = {\"shared\": [True, False]}\n            default_options = {\"shared\": False}\n            def package(self):\n                if self.settings.os == \"Windows\":\n                    save(self, os.path.join(self.package_folder, \"bin\", \"csmapi.dll\"), \"\")\n                    save(self, os.path.join(self.package_folder, \"lib\", \"csmapi.lib\"), \"\")\n                else:\n                    save(self, os.path.join(self.package_folder, \"lib\", \"libcsmapi.so\"), \"\")\n            def package_info(self):\n                self.cpp_info.libs = [\"csmapi\"]\n        \"\"\")\n    consumer = textwrap.dedent(\"\"\"\n        [requires]\n        csm/1.0\n        [options]\n        *:shared=True\n    \"\"\")\n    client.save({\"conanfile.txt\": consumer, \"csm/conanfile.py\": csm})\n    client.run(\"export-pkg csm -o '*:shared=True' -s 'os=Windows'\")\n    client.run(\"export-pkg csm -o '*:shared=True' -s 'os=Linux'\")\n    client.run(\"install . -g BazelDeps -s 'os=Windows'\")\n    build_content = load(None, os.path.join(client.current_folder, \"csm\", \"BUILD.bazel\"))\n    assert '\"-Wl,-rpath,' not in build_content\n    client.run(\"install . -g BazelDeps -s 'os=Linux'\")\n    build_content = load(None, os.path.join(client.current_folder, \"csm\", \"BUILD.bazel\"))\n    assert re.search('\"-Wl,-rpath,.*/p/lib\"', build_content.replace(\"\\\\\", \"/\"))\n"
  },
  {
    "path": "test/integration/toolchains/google/test_bazeltoolchain.py",
    "content": "import os\nimport textwrap\n\nimport pytest\n\nfrom conan.tools.files import load\nfrom conan.tools.google import BazelToolchain\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.fixture(scope=\"module\")\ndef conanfile():\n    return textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.google import BazelToolchain, bazel_layout\n        class ExampleConanIntegration(ConanFile):\n            settings = \"os\", \"arch\", \"build_type\", \"compiler\"\n            options = {\"shared\": [True, False], \"fPIC\": [True, False]}\n            default_options = {\"shared\": False, \"fPIC\": True}\n            generators = 'BazelToolchain'\n            def layout(self):\n                bazel_layout(self)\n    \"\"\")\n\n\ndef test_default_bazel_toolchain(conanfile):\n    profile = textwrap.dedent(\"\"\"\n    [settings]\n    arch=x86_64\n    build_type=Release\n    compiler=apple-clang\n    compiler.cppstd=gnu17\n    compiler.libcxx=libc++\n    compiler.version=13.0\n    os=Macos\n    \"\"\")\n\n    c = TestClient()\n    c.save({\"conanfile.py\": conanfile,\n            \"profile\": profile})\n    c.run(\"install . -pr profile\")\n    content = load(c, os.path.join(c.current_folder, \"conan\", BazelToolchain.bazelrc_name))\n    assert \"build:conan-config --cxxopt=-std=gnu++17\" in content\n    assert \"build:conan-config --force_pic=True\" in content\n    assert \"build:conan-config --dynamic_mode=off\" in content\n    assert \"build:conan-config --compilation_mode=opt\" in content\n\n\ndef test_bazel_toolchain_and_flags(conanfile):\n    profile = textwrap.dedent(\"\"\"\n    [settings]\n    arch=x86_64\n    build_type=Release\n    compiler=apple-clang\n    compiler.cppstd=gnu17\n    compiler.libcxx=libc++\n    compiler.version=13.0\n    os=Macos\n    [options]\n    shared=True\n    [conf]\n    tools.build:cxxflags=[\"--flag1\", \"--flag2\"]\n    tools.build:cflags+=[\"--flag3\", \"--flag4\"]\n    tools.build:sharedlinkflags+=[\"--flag5\"]\n    tools.build:exelinkflags+=[\"--flag6\"]\n    tools.build:linker_scripts+=[\"myscript.sh\"]\n    \"\"\")\n    c = TestClient()\n    c.save({\"conanfile.py\": conanfile,\n            \"profile\": profile})\n    c.run(\"install . -pr profile\")\n    content = load(c, os.path.join(c.current_folder, \"conan\", BazelToolchain.bazelrc_name))\n    assert \"build:conan-config --conlyopt=--flag3 --conlyopt=--flag4\" in content\n    assert \"build:conan-config --cxxopt=-std=gnu++17 --cxxopt=--flag1 --cxxopt=--flag2\" in content\n    assert \"build:conan-config --linkopt=--flag5 --linkopt=--flag6 --linkopt=-T'myscript.sh'\" in content\n    assert \"build:conan-config --force_pic=True\" not in content\n    assert \"build:conan-config --dynamic_mode=fully\" in content\n    assert \"build:conan-config --compilation_mode=opt\" in content\n\n\ndef test_bazel_toolchain_and_cross_compilation(conanfile):\n    profile = textwrap.dedent(\"\"\"\n    [settings]\n    arch=x86_64\n    build_type=Release\n    compiler=apple-clang\n    compiler.cppstd=gnu17\n    compiler.libcxx=libc++\n    compiler.version=13.0\n    os=Macos\n    \"\"\")\n    profile_host = textwrap.dedent(\"\"\"\n    [settings]\n    arch=armv8\n    build_type=Release\n    compiler=apple-clang\n    compiler.cppstd=gnu17\n    compiler.libcxx=libc++\n    compiler.version=13.0\n    os=Macos\n\n    \"\"\")\n    c = TestClient()\n    c.save({\"conanfile.py\": conanfile,\n            \"profile\": profile,\n            \"profile_host\": profile_host})\n    c.run(\"install . -pr:b profile -pr:h profile_host\")\n    content = load(c, os.path.join(c.current_folder, \"conan\", BazelToolchain.bazelrc_name))\n    assert \"build:conan-config --cpu=darwin_arm64\" in content\n\n\ndef test_toolchain_attributes_and_conf_priority():\n    \"\"\"\n    Tests that all the attributes are appearing correctly in the conan_bzl.rc even defining\n    some conf variables\n    \"\"\"\n    profile = textwrap.dedent(\"\"\"\n    [settings]\n    arch=x86_64\n    build_type=Release\n    compiler=apple-clang\n    compiler.cppstd=gnu17\n    compiler.libcxx=libc++\n    compiler.version=13.0\n    os=Macos\n    [conf]\n    tools.build:cxxflags=[\"--flag1\"]\n    tools.build:cflags+=[\"--flag3\"]\n    tools.build:sharedlinkflags+=[\"--linkflag5\"]\n    tools.build:exelinkflags+=[\"--linkflag6\"]\n    \"\"\")\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    from conan.tools.google import BazelToolchain\n    class ExampleConanIntegration(ConanFile):\n        settings = \"os\", \"arch\", \"build_type\", \"compiler\"\n        options = {\"shared\": [True, False], \"fPIC\": [True, False]}\n        default_options = {\"shared\": False, \"fPIC\": True}\n\n        def generate(self):\n            bz = BazelToolchain(self)\n            bz.copt = [\"copt1\"]\n            bz.conlyopt = [\"conly1\"]\n            bz.cxxopt = [\"cxxopt1\"]\n            bz.linkopt = [\"linkopt1\"]\n            bz.force_pic = True\n            bz.dynamic_mode = \"auto\"\n            bz.compilation_mode = \"fastbuild\"\n            bz.compiler = \"gcc\"\n            bz.cpu = \"armv8\"\n            bz.crosstool_top = \"my_crosstool\"\n            bz.generate()\n    \"\"\")\n    c = TestClient()\n    c.save({\"conanfile.py\": conanfile,\n            \"profile\": profile})\n    c.run(\"install . -pr profile\")\n    content = load(c, os.path.join(c.current_folder, BazelToolchain.bazelrc_name))\n    expected = textwrap.dedent(\"\"\"\\\n    # Automatic bazelrc file created by Conan\n    build:conan-config --copt=copt1\n    build:conan-config --conlyopt=conly1 --conlyopt=--flag3\n    build:conan-config --cxxopt=-std=gnu++17 --cxxopt=cxxopt1 --cxxopt=--flag1\n    build:conan-config --linkopt=linkopt1 --linkopt=--linkflag5 --linkopt=--linkflag6\n    build:conan-config --force_pic=True\n    build:conan-config --dynamic_mode=auto\n    build:conan-config --compilation_mode=fastbuild\n    build:conan-config --compiler=gcc\n    build:conan-config --cpu=armv8\n    build:conan-config --crosstool_top=my_crosstool\"\"\")\n    assert expected == content\n"
  },
  {
    "path": "test/integration/toolchains/intel/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/toolchains/intel/test_intel_cc.py",
    "content": "import os\nimport platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\nconanfile = textwrap.dedent(\"\"\"\\\n[generators]\nIntelCC\n\"\"\")\n\nintelprofile = textwrap.dedent(\"\"\"\\\n[settings]\nos=%s\narch=x86_64\ncompiler=intel-cc\ncompiler.mode=dpcpp\ncompiler.version=2021.3\ncompiler.libcxx=libstdc++\nbuild_type=Release\n\n[conf]\ntools.intel:installation_path=%s\n\"\"\")\n\n\ndef get_intel_cc_generator_file(os_, installation_path, filename):\n    profile = intelprofile % (os_, installation_path)\n    client = TestClient()\n    client.save({\n        \"conanfile.txt\": conanfile,\n        \"intelprofile\": profile,\n    })\n    client.run(\"install . -pr intelprofile\")\n    return client.load(filename)\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows\")\ndef test_intel_cc_generator_windows():\n    os_ = \"Windows\"\n    installation_path = \"C:\\\\Program Files (x86)\\\\Intel\\\\oneAPI\"\n    conanintelsetvars = get_intel_cc_generator_file(os_, installation_path, \"conanintelsetvars.bat\")\n    expected = textwrap.dedent(\"\"\"\\\n        @echo off\n        call \"C:\\\\Program Files (x86)\\\\Intel\\\\oneAPI\\\\setvars.bat\" intel64\n        \"\"\")\n    assert conanintelsetvars == expected\n\n\n@pytest.mark.skipif(platform.system() != \"Linux\", reason=\"Requires Linux\")\ndef test_intel_cc_generator_linux():\n    os_ = \"Linux\"\n    installation_path = \"/opt/intel/oneapi\"\n    conanintelsetvars = get_intel_cc_generator_file(os_, installation_path, \"conanintelsetvars.sh\")\n    expected = '. \"/opt/intel/oneapi/setvars.sh\" intel64'\n    assert conanintelsetvars == expected\n\n\ndef test_avoid_generation():\n    # The empty string for tools.intel:installation_path avoids the generation\n    profile = intelprofile % (\"Linux\", \"\")\n    client = TestClient()\n    client.save({\n        \"conanfile.txt\": conanfile,\n        \"intelprofile\": profile,\n    })\n    client.run(\"install . -pr intelprofile\")\n    files = os.listdir(client.current_folder)\n    assert \"conanintelsetvars\" not in \",\".join(files)\n"
  },
  {
    "path": "test/integration/toolchains/meson/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/toolchains/meson/test_mesontoolchain.py",
    "content": "import os\nimport platform\nimport re\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\nfrom conan.tools.meson import MesonToolchain\n\n\ndef test_apple_meson_keep_user_custom_flags():\n    default = textwrap.dedent(\"\"\"\n    [settings]\n    os=Macos\n    arch=x86_64\n    compiler=apple-clang\n    compiler.version=12.0\n    compiler.libcxx=libc++\n    build_type=Release\n    \"\"\")\n\n    cross = textwrap.dedent(\"\"\"\n    [settings]\n    os = iOS\n    os.version = 10.0\n    os.sdk = iphoneos\n    arch = armv8\n    compiler = apple-clang\n    compiler.version = 12.0\n    compiler.libcxx = libc++\n\n    [conf]\n    tools.apple:sdk_path=/my/sdk/path\n    \"\"\")\n\n    _conanfile_py = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    from conan.tools.meson import MesonToolchain\n\n    class App(ConanFile):\n        settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n\n        def generate(self):\n            tc = MesonToolchain(self)\n            # Customized apple flags\n            tc.apple_arch_flag = ['-arch', 'myarch']\n            tc.apple_isysroot_flag = ['-isysroot', '/other/sdk/path']\n            tc.apple_min_version_flag = ['-otherminversion=10.7']\n            tc.generate()\n    \"\"\")\n\n    t = TestClient()\n    t.save({\"conanfile.py\": _conanfile_py,\n            \"build_prof\": default,\n            \"host_prof\": cross})\n\n    t.run(\"install . -pr:h host_prof -pr:b build_prof\")\n    # Checking that the global conanbuild aggregator includes conanbuildenv-xxx file\n    # it should have been generated by implicit VirtualBuildEnv generator\n    env_file = t.load(\"conanbuild.sh\")\n    assert \"conanbuildenv\" in env_file\n    content = t.load(MesonToolchain.cross_filename)\n    assert \"c_args = ['-isysroot', '/other/sdk/path', '-arch', 'myarch', '-otherminversion=10.7']\" in content\n    assert \"c_link_args = ['-isysroot', '/other/sdk/path', '-arch', 'myarch', '-otherminversion=10.7']\" in content\n    assert \"cpp_args = ['-isysroot', '/other/sdk/path', '-arch', 'myarch', '-otherminversion=10.7', '-stdlib=libc++']\" in content\n    assert \"cpp_link_args = ['-isysroot', '/other/sdk/path', '-arch', 'myarch', '-otherminversion=10.7', '-stdlib=libc++']\" in content\n\n\ndef test_apple_meson_cross_building_subsystem():\n    \"\"\"\n    Issue related: https://github.com/conan-io/conan/issues/17873\n    \"\"\"\n    default = textwrap.dedent(\"\"\"\n    [settings]\n    os=Macos\n    arch=x86_64\n    compiler=apple-clang\n    compiler.version=12.0\n    compiler.libcxx=libc++\n    build_type=Release\n    \"\"\")\n    cross = textwrap.dedent(\"\"\"\n    [settings]\n    os = iOS\n    os.version = 10.0\n    os.sdk = iphoneos\n    arch = armv8\n    compiler = apple-clang\n    compiler.version = 12.0\n    compiler.libcxx = libc++\n\n    [conf]\n    tools.apple:sdk_path=/my/sdk/path\n    \"\"\")\n    t = TestClient()\n    t.save({\"conanfile.py\": GenConanfile(name=\"app\", version=\"1.0\")\n                            .with_settings(\"os\", \"arch\", \"compiler\", \"build_type\")\n                            .with_generator(\"MesonToolchain\"),\n            \"build\": default,\n            \"host\": cross})\n    t.run(\"install . -pr:h host -pr:b build\")\n    content = t.load(MesonToolchain.cross_filename)\n    machines_settings = textwrap.dedent(\"\"\"\\\n    [build_machine]\n    system = 'darwin'\n    subsystem = 'macos'\n    cpu_family = 'x86_64'\n    cpu = 'x86_64'\n    endian = 'little'\n    [host_machine]\n    system = 'darwin'\n    subsystem = 'ios'\n    cpu_family = 'aarch64'\n    cpu = 'armv8'\n    endian = 'little'\"\"\")\n    assert machines_settings in content\n    # Let's check that it does not appear if cross-compiling to other non-Apple-OS\n    cross = textwrap.dedent(\"\"\"\n    [settings]\n    arch=armv8\n    build_type=Release\n    compiler=gcc\n    compiler.cppstd=gnu17\n    compiler.libcxx=libstdc++11\n    compiler.version=13\n    os=Linux\n    \"\"\")\n    t.save({\"host\": cross})\n    t.run(\"install . -pr:h host -pr:b build\")\n    content = t.load(MesonToolchain.cross_filename)\n    assert \"subsystem =\" not in content\n\n\ndef test_extra_flags_via_conf():\n    profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=Windows\n        arch=x86_64\n        compiler=gcc\n        compiler.version=9\n        compiler.cppstd=17\n        compiler.libcxx=libstdc++\n        build_type=Release\n\n        [buildenv]\n        CFLAGS=-flag0 -other=val\n        CXXFLAGS=-flag0 -other=val\n        LDFLAGS=-flag0 -other=val\n\n        [conf]\n        tools.build:cxxflags=[\"-flag1\", \"-flag2\"]\n        tools.build:cflags=[\"-flag3\", \"-flag4\"]\n        tools.build:sharedlinkflags+=[\"-flag5\"]\n        tools.build:exelinkflags+=[\"-flag6\"]\n        # Issue related: https://github.com/conan-io/conan/issues/16169\n        tools.build:defines=[\"define1=0\"]\n   \"\"\")\n    t = TestClient()\n    t.save({\"conanfile.txt\": \"[generators]\\nMesonToolchain\",\n            \"profile\": profile})\n\n    t.run(\"install . -pr:h=profile -pr:b=profile\")\n    content = t.load(MesonToolchain.native_filename)\n    assert \"cpp_args = ['-flag0', '-other=val', '-m64', '-flag1', '-flag2', '-Ddefine1=0', '-D_GLIBCXX_USE_CXX11_ABI=0']\" in content\n    assert \"c_args = ['-flag0', '-other=val', '-m64', '-flag3', '-flag4', '-Ddefine1=0']\" in content\n    assert \"c_link_args = ['-flag0', '-other=val', '-m64', '-flag5', '-flag6']\" in content\n    assert \"cpp_link_args = ['-flag0', '-other=val', '-m64', '-flag5', '-flag6']\" in content\n\n\ndef test_extra_flags_via_toolchain():\n    profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=Windows\n        arch=x86_64\n        compiler=gcc\n        compiler.version=9\n        compiler.cppstd=17\n        compiler.libcxx=libstdc++\n        build_type=Release\n\n        [buildenv]\n        CFLAGS=-flag0 -other=val\n        CXXFLAGS=-flag0 -other=val\n        LDFLAGS=-flag0 -other=val\n   \"\"\")\n    t = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    from conan.tools.meson import MesonToolchain\n    class Pkg(ConanFile):\n        settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n        def generate(self):\n            tc = MesonToolchain(self)\n            tc.extra_cxxflags = [\"-flag1\", \"-flag2\"]\n            tc.extra_cflags = [\"-flag3\", \"-flag4\"]\n            tc.extra_ldflags = [\"-flag5\", \"-flag6\"]\n            tc.extra_defines = [\"define1=0\"]\n            tc.generate()\n    \"\"\")\n    t.save({\"conanfile.py\": conanfile,\n            \"profile\": profile})\n    t.run(\"install . -pr:h=profile -pr:b=profile\")\n    content = t.load(MesonToolchain.native_filename)\n    assert \"cpp_args = ['-flag0', '-other=val', '-m64', '-flag1', '-flag2', '-Ddefine1=0', '-D_GLIBCXX_USE_CXX11_ABI=0']\" in content\n    assert \"c_args = ['-flag0', '-other=val', '-m64', '-flag3', '-flag4', '-Ddefine1=0']\" in content\n    assert \"c_link_args = ['-flag0', '-other=val', '-m64', '-flag5', '-flag6']\" in content\n    assert \"cpp_link_args = ['-flag0', '-other=val', '-m64', '-flag5', '-flag6']\" in content\n\n\ndef test_custom_arch_flag_via_toolchain():\n    t = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    from conan.tools.meson import MesonToolchain\n    class Pkg(ConanFile):\n        settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n        def generate(self):\n            tc = MesonToolchain(self)\n            tc.arch_flag = \"-mmy-flag\"\n            tc.generate()\n    \"\"\")\n    t.save({\"conanfile.py\": conanfile})\n    t.run(\"install .\")\n    content = t.load(MesonToolchain.native_filename)\n    assert re.search(r\"c_args =.+-mmy-flag.+\", content)\n    assert re.search(r\"c_link_args =.+-mmy-flag.+\", content)\n    assert re.search(r\"cpp_args =.+-mmy-flag.+\", content)\n    assert re.search(r\"cpp_link_args =.+-mmy-flag.+\", content)\n\n\ndef test_linker_scripts_via_conf():\n    profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=Windows\n        arch=x86_64\n        compiler=gcc\n        compiler.version=9\n        compiler.cppstd=17\n        compiler.libcxx=libstdc++\n        build_type=Release\n\n        [buildenv]\n        LDFLAGS=-flag0 -other=val\n\n        [conf]\n        tools.build:sharedlinkflags+=[\"-flag5\"]\n        tools.build:exelinkflags+=[\"-flag6\"]\n        tools.build:linker_scripts+=[\"/linker/scripts/flash.ld\", \"/linker/scripts/extra_data.ld\"]\n   \"\"\")\n    t = TestClient()\n    t.save({\"conanfile.txt\": \"[generators]\\nMesonToolchain\",\n            \"profile\": profile})\n\n    t.run(\"install . -pr:b=profile -pr=profile\")\n    content = t.load(MesonToolchain.native_filename)\n    assert (\"c_link_args = ['-flag0', '-other=val', '-m64', '-flag5', '-flag6', \"\n            \"'-T/linker/scripts/flash.ld', '-T/linker/scripts/extra_data.ld']\") in content\n    assert (\"cpp_link_args = ['-flag0', '-other=val', '-m64', '-flag5', '-flag6', \"\n            \"'-T/linker/scripts/flash.ld', '-T/linker/scripts/extra_data.ld']\") in content\n\n\ndef test_correct_quotes():\n    profile = textwrap.dedent(\"\"\"\n       [settings]\n       os=Windows\n       arch=x86_64\n       compiler=gcc\n       compiler.version=9\n       compiler.cppstd=17\n       compiler.libcxx=libstdc++11\n       build_type=Release\n       \"\"\")\n    t = TestClient()\n    t.save({\"conanfile.txt\": \"[generators]\\nMesonToolchain\",\n            \"profile\": profile})\n\n    t.run(\"install . -pr:h=profile -pr:b=profile\")\n    content = t.load(MesonToolchain.native_filename)\n    assert \"cpp_std = 'c++17'\" in content\n    assert \"backend = 'ninja'\" in content\n    assert \"buildtype = 'release'\" in content\n\n\ndef test_c_std():\n    profile = textwrap.dedent(\"\"\"\n       [settings]\n       os=Windows\n       arch=x86_64\n       compiler=gcc\n       compiler.version=9\n       compiler.cstd=11\n       build_type=Release\n       \"\"\")\n    t = TestClient()\n    t.save({\"conanfile.py\": GenConanfile().with_settings(\"os\", \"compiler\", \"build_type\", \"arch\")\n                                          .with_generator(\"MesonToolchain\")\n                                          .with_class_attribute(\"languages='C'\"),\n            \"profile\": profile})\n\n    t.run(\"install . -pr:h=profile -pr:b=profile\")\n    content = t.load(MesonToolchain.native_filename)\n    assert \"c_std = 'c11'\" in content\n    assert \"backend = 'ninja'\" in content\n    assert \"buildtype = 'release'\" in content\n\n\ndef test_deactivate_nowrap():\n    # https://github.com/conan-io/conan/issues/10671\n    t = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.meson import MesonToolchain\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            def generate(self):\n                tc = MesonToolchain(self)\n                tc.project_options.pop(\"wrap_mode\")\n                tc.generate()\n        \"\"\")\n    t.save({\"conanfile.py\": conanfile})\n    t.run(\"install .\")\n    content = t.load(MesonToolchain.native_filename)\n    assert \"wrap_mode \" not in content\n    assert \"nofallback\" not in content\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"requires Win\")\n@pytest.mark.parametrize(\"build_type,runtime,vscrt\", [\n    (\"Debug\", \"dynamic\", \"mdd\"),\n    (\"Debug\", \"static\", \"mtd\"),\n    (\"Release\", \"dynamic\", \"md\"),\n    (\"Release\", \"static\", \"mt\")\n])\ndef test_clang_cl_vscrt(build_type, runtime, vscrt):\n    profile = textwrap.dedent(f\"\"\"\n        [settings]\n        os=Windows\n        arch=x86_64\n        build_type={build_type}\n        compiler=clang\n        compiler.runtime={runtime}\n        compiler.runtime_version=v143\n        compiler.version=16\n\n        [conf]\n        tools.cmake.cmaketoolchain:generator=Visual Studio 17\n\n        [buildenv]\n        CC=clang-cl\n        CXX=clang-cl\n   \"\"\")\n    t = TestClient()\n    t.save({\"conanfile.txt\": \"[generators]\\nMesonToolchain\",\n            \"profile\": profile})\n\n    t.run(\"install . -pr:h=profile -pr:b=profile\")\n    content = t.load(MesonToolchain.native_filename)\n    assert f\"b_vscrt = '{vscrt}'\" in content\n\n\ndef test_env_vars_from_build_require():\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    import os\n\n    class HelloConan(ConanFile):\n        name = 'hello_compiler'\n        version = '1.0'\n        def package_info(self):\n            self.buildenv_info.define(\"CC\", \"CC_VALUE\")\n            self.buildenv_info.define(\"CC_LD\", \"CC_LD_VALUE\")\n            self.buildenv_info.define(\"CXX\", \"CXX_VALUE\")\n            self.buildenv_info.define(\"CXX_LD\", \"CXX_LD_VALUE\")\n            self.buildenv_info.define(\"AR\", \"AR_VALUE\")\n            self.buildenv_info.define(\"STRIP\", \"STRIP_VALUE\")\n            self.buildenv_info.define(\"AS\", \"AS_VALUE\")\n            self.buildenv_info.define(\"WINDRES\", \"WINDRES_VALUE\")\n            self.buildenv_info.define(\"PKG_CONFIG\", \"PKG_CONFIG_VALUE\")\n            self.buildenv_info.define(\"LD\", \"LD_VALUE\")\n    \"\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create .\")\n\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    class HelloConan(ConanFile):\n        name = 'consumer'\n        version = '1.0'\n        generators = \"MesonToolchain\"\n        settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n\n        def requirements(self):\n            self.tool_requires(\"hello_compiler/1.0\", )\n    \"\"\")\n    # Now, let's check how all the build env variables are applied at consumer side\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"install . -pr:h=default -pr:b=default\")\n    content = client.load(\"conan_meson_native.ini\")\n    assert \"c = 'CC_VALUE'\" in content\n    assert \"cpp = 'CXX_VALUE'\" in content\n    assert \"ld = 'LD_VALUE'\" in content\n    assert \"c_ld = 'CC_LD_VALUE'\" in content\n    assert \"cpp_ld = 'CXX_LD_VALUE'\" in content\n    assert \"ar = 'AR_VALUE'\" in content\n    assert \"strip = 'STRIP_VALUE'\" in content\n    assert \"as = 'AS_VALUE'\" in content\n    assert \"windres = 'WINDRES_VALUE'\" in content\n    assert \"pkgconfig = 'PKG_CONFIG_VALUE'\" in content\n    assert \"pkg-config = 'PKG_CONFIG_VALUE'\" in content\n\n\ndef test_check_c_cpp_ld_list_formats():\n    # Issue related: https://github.com/conan-io/conan/issues/14028\n    profile = textwrap.dedent(\"\"\"\n       [settings]\n       os=Windows\n       arch=x86_64\n       compiler=gcc\n       compiler.version=9\n       compiler.cppstd=17\n       compiler.libcxx=libstdc++11\n       build_type=Release\n       [buildenv]\n       CC=aarch64-poky-linux-gcc  -mcpu=cortex-a53 -march=armv8-a+crc+crypto\n       CXX=aarch64-poky-linux-g++  -mcpu=cortex-a53 -march=armv8-a+crc+crypto\n       LD=aarch64-poky-linux-ld  --sysroot=/opt/sysroots/cortexa53-crypto-poky-linux\n       \"\"\")\n    t = TestClient()\n    t.save({\"conanfile.txt\": \"[generators]\\nMesonToolchain\",\n            \"profile\": profile})\n    t.run(\"install . -pr:h=profile -pr:b=profile\")\n    content = t.load(MesonToolchain.native_filename)\n    assert \"c = ['aarch64-poky-linux-gcc', '-mcpu=cortex-a53', '-march=armv8-a+crc+crypto']\" in content\n    assert \"cpp = ['aarch64-poky-linux-g++', '-mcpu=cortex-a53', '-march=armv8-a+crc+crypto']\" in content\n    assert \"ld = ['aarch64-poky-linux-ld', '--sysroot=/opt/sysroots/cortexa53-crypto-poky-linux']\" in content\n\n\ndef test_check_pkg_config_paths():\n    # Issue: https://github.com/conan-io/conan/issues/12342\n    # Issue: https://github.com/conan-io/conan/issues/14935\n    t = TestClient()\n    t.save({\"conanfile.txt\": \"[generators]\\nMesonToolchain\"})\n    t.run(\"install .\")\n    content = t.load(MesonToolchain.native_filename)\n    assert f\"pkg_config_path = '{t.current_folder}'\" in content\n    assert f\"build.pkg_config_path = \" not in content\n    conanfile = textwrap.dedent(\"\"\"\n    import os\n    from conan import ConanFile\n    from conan.tools.meson import MesonToolchain\n    class Pkg(ConanFile):\n        settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n        def generate(self):\n            tc = MesonToolchain(self)\n            tc.build_pkg_config_path = os.path.join(self.generators_folder, \"build\")\n            tc.generate()\n    \"\"\")\n    t.save({\"conanfile.py\": conanfile}, clean_first=True)\n    t.run(\"install .\")\n    content = t.load(MesonToolchain.native_filename)\n    base_folder = t.current_folder\n    assert f\"pkg_config_path = '{base_folder}'\" in content\n    assert f\"build.pkg_config_path = '{os.path.join(base_folder, 'build')}'\" in content\n\n\ndef test_toolchain_and_compilers_build_context():\n    \"\"\"\n    Tests how MesonToolchain manages the build context profile if the build profile is\n    specifying another compiler path (using conf).\n\n    It should create both native and cross files.\n\n    Issue related: https://github.com/conan-io/conan/issues/15878\n    \"\"\"\n    host = textwrap.dedent(\"\"\"\n    [settings]\n    arch=armv8\n    build_type=Release\n    compiler=gcc\n    compiler.cppstd=gnu17\n    compiler.libcxx=libstdc++11\n    compiler.version=11\n    os=Linux\n\n    [conf]\n    tools.build:compiler_executables={\"c\": \"gcc\", \"cpp\": \"g++\"}\n    \"\"\")\n    build = textwrap.dedent(\"\"\"\n    [settings]\n    os=Linux\n    arch=x86_64\n    compiler=clang\n    compiler.version=12\n    compiler.libcxx=libc++\n    compiler.cppstd=11\n\n    [conf]\n    tools.build:compiler_executables={\"c\": \"clang\", \"cpp\": \"clang++\"}\n    \"\"\")\n    tool = textwrap.dedent(\"\"\"\n    import os\n    from conan import ConanFile\n    from conan.tools.files import load\n\n    class toolRecipe(ConanFile):\n        name = \"tool\"\n        version = \"1.0\"\n        # Binary configuration\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n        generators = \"MesonToolchain\"\n\n        def build(self):\n            toolchain = os.path.join(self.generators_folder, \"conan_meson_native.ini\")\n            content = load(self, toolchain)\n            assert \"c = 'clang'\" in content\n            assert \"cpp = 'clang++'\" in content\n    \"\"\")\n    consumer = textwrap.dedent(\"\"\"\n    import os\n    from conan import ConanFile\n    from conan.tools.files import load\n\n    class consumerRecipe(ConanFile):\n        name = \"consumer\"\n        version = \"1.0\"\n        # Binary configuration\n        settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n        generators = \"MesonToolchain\"\n        tool_requires = \"tool/1.0\"\n\n        def build(self):\n            toolchain = os.path.join(self.generators_folder, \"conan_meson_cross.ini\")\n            content = load(self, toolchain)\n            assert \"c = 'gcc'\" in content\n            assert \"cpp = 'g++'\" in content\n    \"\"\")\n    client = TestClient()\n    client.save({\n        \"host\": host,\n        \"build\": build,\n        \"tool/conanfile.py\": tool,\n        \"consumer/conanfile.py\": consumer\n    })\n    client.run(\"export tool\")\n    client.run(\"create consumer -pr:h host -pr:b build --build=missing\")\n\n\ndef test_subproject_options():\n    t = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.meson import MesonToolchain\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n            def generate(self):\n                tc = MesonToolchain(self)\n                tc.subproject_options[\"subproject1\"] = [{\"option1\": \"enabled\"}, {\"option2\": \"disabled\"}]\n                tc.subproject_options[\"subproject2\"] = [{\"option3\": \"enabled\"}]\n                tc.subproject_options[\"subproject2\"].append({\"option4\": \"disabled\"})\n                tc.generate()\n        \"\"\")\n    t.save({\"conanfile.py\": conanfile})\n    t.run(\"install .\")\n    content = t.load(MesonToolchain.native_filename)\n    assert \"[subproject1:project options]\" in content\n    assert \"[subproject2:project options]\" in content\n    assert \"option1 = 'enabled'\" in content\n    assert \"option2 = 'disabled'\" in content\n    assert \"option3 = 'enabled'\" in content\n    assert \"option4 = 'disabled'\" in content\n\n\ndef test_native_attribute():\n    \"\"\"\n    Tests that native file only has the build context (not as a build require) content.\n    \"\"\"\n    host = textwrap.dedent(\"\"\"\n    [settings]\n    arch=armv8\n    build_type=Release\n    compiler=gcc\n    compiler.cppstd=gnu17\n    compiler.libcxx=libstdc++11\n    compiler.version=11\n    os=Linux\n\n    [buildenv]\n    STRIP=False\n    PKG_CONFIG=/usr/bin/pkg-config\n\n    [conf]\n    tools.build:compiler_executables={\"c\": \"gcc\", \"cpp\": \"g++\"}\n    \"\"\")\n    build = textwrap.dedent(\"\"\"\n    [settings]\n    os=Linux\n    arch=x86_64\n    compiler=clang\n    compiler.version=12\n    compiler.libcxx=libc++\n    compiler.cppstd=11\n\n    [buildenv]\n    STRIP=True\n    PKG_CONFIG=/usr/lib/meson/pkgconfig\n\n    [conf]\n    tools.build:compiler_executables={\"c\": \"clang\", \"cpp\": \"clang++\"}\n    \"\"\")\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    from conan.tools.meson import MesonToolchain\n    class Pkg(ConanFile):\n        settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n        def generate(self):\n            tc = MesonToolchain(self)\n            tc.generate()\n            # We're cross-building, no need to check it\n            tc = MesonToolchain(self, native=True)\n            tc.generate()\n    \"\"\")\n    client.save({\"host\": host,\n                 \"build\": build,\n                 \"conanfile.py\": conanfile})\n    client.run(\"install . -pr:h host -pr:b build\")\n    native_content = client.load(MesonToolchain.native_filename)\n    cross_content = client.load(MesonToolchain.cross_filename)\n    expected_native = textwrap.dedent(\"\"\"\n    [binaries]\n    c = 'clang'\n    cpp = 'clang++'\n    strip = 'True'\n    pkgconfig = '/usr/lib/meson/pkgconfig'\n    pkg-config = '/usr/lib/meson/pkgconfig'\n    \"\"\")\n    expected_cross = textwrap.dedent(\"\"\"\n    [binaries]\n    c = 'gcc'\n    cpp = 'g++'\n    strip = 'False'\n    pkgconfig = '/usr/bin/pkg-config'\n    pkg-config = '/usr/bin/pkg-config'\n    \"\"\")\n    assert expected_native in native_content\n    assert \"[host_machine]\" not in native_content\n    assert \"[build_machine]\" not in native_content\n    assert expected_cross in cross_content\n    assert \"[build_machine]\" in cross_content\n    assert \"[host_machine]\" in cross_content\n\n\ndef test_native_attribute_error():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    from conan.tools.meson import MesonToolchain\n    class Pkg(ConanFile):\n        settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n        def generate(self):\n            tc = MesonToolchain(self)\n            tc.generate()\n            tc = MesonToolchain(self, native=True)\n            tc.generate()\n    \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"install .\", assert_error=True)\n    assert \"You can only pass native=True if you're cross-building\" in client.out\n\n\ndef test_compiler_path_with_spaces():\n    profile = textwrap.dedent(\"\"\"\n        include(default)\n        [conf]\n        tools.build:compiler_executables={\"c\":\"c compiler path with spaces\", \"cpp\":\"cpp compiler path with spaces\"}\n    \"\"\")\n    client = TestClient()\n    client.save(\n        {\"conanfile.py\": GenConanfile().with_generator(\"MesonToolchain\").with_settings(\"compiler\"),\n         \"meson-profile\": profile})\n    client.run(\"install . -pr:h=meson-profile\")\n    conan_meson_native = client.load(\"conan_meson_native.ini\")\n    assert \"c = 'c compiler path with spaces'\" in conan_meson_native\n    assert \"cpp = 'cpp compiler path with spaces'\" in conan_meson_native\n\n\ndef test_meson_sysroot_app():\n    \"\"\"Testing when users pass tools.build:sysroot on the profile with Meson\n\n    * The generated conan_meson_cross.ini does not fill the \"sys_root\" property (see https://github.com/conan-io/conan/issues/16468)\n    * It adds the compiler flags with --sysroot.\n\n    When cross-building, Meson needs both compiler_executables in the config, otherwise it will fail\n    when running setup.\n    \"\"\"\n    sysroot = \"/my/new/sysroot/path\"\n    client = TestClient()\n    profile = textwrap.dedent(f\"\"\"\n    [settings]\n    os = Macos\n    arch = armv8\n    compiler = apple-clang\n    compiler.version = 13.0\n    compiler.libcxx = libc++\n\n    [conf]\n    tools.build:sysroot={sysroot}\n    tools.build:verbosity=verbose\n    tools.compilation:verbosity=verbose\n    tools.apple:sdk_path=/my/sdk/path\n    \"\"\")\n    profile_build = textwrap.dedent(f\"\"\"\n    [settings]\n    os = Macos\n    arch = x86_64\n    compiler = apple-clang\n    compiler.version = 13.0\n    compiler.libcxx = libc++\n    \"\"\")\n    client.save({\"conanfile.py\": GenConanfile(name=\"hello\", version=\"0.1\")\n                .with_settings(\"os\", \"arch\", \"compiler\", \"build_type\")\n                .with_generator(\"MesonToolchain\"),\n                 \"build\": profile_build,\n                 \"host\": profile})\n    client.run(\"install . -pr:h host -pr:b build\")\n    # Check the meson configuration file\n    conan_meson = client.load(\"conan_meson_cross.ini\")\n    assert f\"sys_root = '{sysroot}'\\n\" not in conan_meson\n    assert re.search(r\"c_args =.+--sysroot={}.+\".format(sysroot), conan_meson)\n    assert re.search(r\"c_link_args =.+--sysroot={}.+\".format(sysroot), conan_meson)\n    assert re.search(r\"cpp_args =.+--sysroot={}.+\".format(sysroot), conan_meson)\n    assert re.search(r\"cpp_link_args =.+--sysroot={}.+\".format(sysroot), conan_meson)\n\n\ndef test_cross_x86_64_to_x86():\n    \"\"\"\n    https://github.com/conan-io/conan/issues/17261\n    \"\"\"\n\n    c = TestClient()\n    c.save({\"conanfile.py\": GenConanfile().with_settings(\"os\", \"compiler\", \"arch\", \"build_type\")})\n    c.run(\"install . -g MesonToolchain -s arch=x86 -s:b arch=x86_64\")\n    assert not os.path.exists(os.path.join(c.current_folder, MesonToolchain.native_filename))\n    cross = c.load(MesonToolchain.cross_filename)\n    assert \"cpu = 'x86_64'\" in cross  # This is the build machine\n    assert \"cpu = 'x86'\" in cross  # This is the host machine\n\n\ndef test_cross_x86_64_to_riscv32():\n    \"\"\"\n    https://github.com/conan-io/conan/issues/18490\n    \"\"\"\n    c = TestClient()\n    c.save({\"conanfile.py\": GenConanfile().with_settings(\"os\", \"compiler\", \"arch\", \"build_type\")})\n    c.run(\"install . -g MesonToolchain -s os=Linux -s arch=riscv32 -s:b arch=x86_64\")\n    assert not os.path.exists(os.path.join(c.current_folder, MesonToolchain.native_filename))\n    cross = c.load(MesonToolchain.cross_filename)\n    assert \"cpu = 'x86_64'\" in cross  # This is the build machine\n    assert \"cpu = 'riscv32'\" in cross  # This is the host machine\n\n\ndef test_cross_x86_64_to_riscv64():\n    \"\"\"\n    https://github.com/conan-io/conan/issues/18490\n    \"\"\"\n    c = TestClient()\n    c.save({\"conanfile.py\": GenConanfile().with_settings(\"os\", \"compiler\", \"arch\", \"build_type\")})\n    c.run(\"install . -g MesonToolchain -s os=Linux -s arch=riscv64 -s:b arch=x86_64\")\n    assert not os.path.exists(os.path.join(c.current_folder, MesonToolchain.native_filename))\n    cross = c.load(MesonToolchain.cross_filename)\n    assert \"cpu = 'x86_64'\" in cross  # This is the build machine\n    assert \"cpu = 'riscv64'\" in cross  # This is the host machine\n\n\ndef test_conf_extra_apple_flags():\n    host = textwrap.dedent(\"\"\"\n    [settings]\n    arch=x86_64\n    os=Macos\n    compiler=apple-clang\n    compiler.version=14.0\n    [conf]\n    tools.apple:enable_bitcode = True\n    tools.apple:enable_arc = True\n    tools.apple:enable_visibility = True\n    \"\"\")\n\n    c = TestClient()\n    c.save({\"conanfile.txt\": f\"[generators]\\nMesonToolchain\",\n            \"host\": host})\n    c.run(\"install . -pr:a host\")\n    f = \"conan_meson_native.ini\"\n    tc = c.load(f)\n    for flags in [\"c_args\", \"cpp_args\", \"c_link_args\", \"cpp_link_args\"]:\n        assert f\"{flags} = ['-m64', '-fembed-bitcode', '-fvisibility=default']\" in tc\n    for flags in [\"objcpp_args\", \"objc_args\"]:\n        assert f\"{flags} = ['-fobjc-arc', '-m64', '-fembed-bitcode', '-fvisibility=default']\" in tc\n    c.run(\"install . -pr:a host -s build_type=Debug\")\n    tc = c.load(f)\n    for flags in [\"c_args\", \"cpp_args\", \"c_link_args\", \"cpp_link_args\"]:\n        assert f\"{flags} = ['-m64', '-fembed-bitcode-marker', '-fvisibility=default']\" in tc\n    for flags in [\"objcpp_args\", \"objc_args\"]:\n        assert f\"{flags} = ['-fobjc-arc', '-m64', '-fembed-bitcode-marker', '-fvisibility=default']\" in tc\n\n    host = textwrap.dedent(\"\"\"\n        [settings]\n        arch=x86_64\n        os=Macos\n        compiler=apple-clang\n        compiler.version=14.0\n        [conf]\n        tools.apple:enable_bitcode = False\n        tools.apple:enable_arc = False\n        tools.apple:enable_visibility = False\n        \"\"\")\n\n    c.save({\"host\": host})\n    c.run(\"install . -pr:a host\")\n    tc = c.load(f)\n    for flags in [\"c_args\", \"cpp_args\", \"c_link_args\", \"cpp_link_args\"]:\n        assert f\"{flags} = ['-m64', '-fvisibility=hidden', '-fvisibility-inlines-hidden']\" in tc\n    for flags in [\"objcpp_args\", \"objc_args\"]:\n        assert f\"{flags} = ['-fno-objc-arc', '-m64', '-fvisibility=hidden', '-fvisibility-inlines-hidden']\" in tc\n\n\n@pytest.mark.parametrize(\n    \"threads, flags\",\n    [(\"posix\", \"-pthread\"), (\"wasm_workers\", \"-sWASM_WORKERS=1\")],\n)\ndef test_thread_flags(threads, flags):\n    client = TestClient()\n    profile = textwrap.dedent(f\"\"\"\n        [settings]\n        arch=wasm\n        build_type=Release\n        compiler=emcc\n        compiler.cppstd=17\n        compiler.threads={threads}\n        compiler.libcxx=libc++\n        compiler.version=4.0.10\n        os=Emscripten\n        \"\"\")\n    client.save(\n        {\n            \"conanfile.py\": GenConanfile(\"pkg\", \"1.0\")\n            .with_settings(\"os\", \"arch\", \"compiler\", \"build_type\")\n            .with_generator(\"MesonToolchain\"),\n            \"profile\": profile,\n        }\n    )\n    client.run(\"install . -pr=./profile\")\n    toolchain = client.load(\"conan_meson_cross.ini\")\n    assert f\"c_args = ['{flags}']\" in toolchain\n    assert f\"c_link_args = ['{flags}']\" in toolchain\n    assert f\"cpp_args = ['{flags}', '-stdlib=libc++']\" in toolchain\n    assert f\"cpp_link_args = ['{flags}', '-stdlib=libc++']\" in toolchain\n\n\ndef test_new_public_attributes():\n    host = textwrap.dedent(f\"\"\"\n    [settings]\n    arch=armv8\n    build_type=Release\n    compiler=gcc\n    compiler.cppstd=gnu17\n    compiler.libcxx=libstdc++11\n    compiler.version=11\n    os=Linux\n    [conf]\n    tools.meson.mesontoolchain:backend=xcode\n    \"\"\")\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n    from conan import ConanFile\n    from conan.tools.meson import MesonToolchain\n    class Pkg(ConanFile):\n        settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n        def generate(self):\n            tc = MesonToolchain(self)\n            tc.backend = \"vs2022\"  # conf has more prio\n            tc.b_staticpic = True\n            tc.buildtype = \"Debug\"\n            tc.default_library = \"shared\"\n            tc.cpp_std=\"c++20\"\n            tc.c_std=\"c20\"\n            tc.b_vscrt=\"MD\"\n            tc.generate()\n    \"\"\")\n    client.save({\"conanfile.py\": conanfile,\n                 \"host\": host})\n    client.run(\"install . -pr:a host\")\n    content = client.load(MesonToolchain.native_filename)\n    expected = textwrap.dedent(\"\"\"\\\n    buildtype = 'Debug'\n    default_library = 'shared'\n    b_vscrt = 'MD'\n    b_ndebug = 'true'\n    b_staticpic = true\n    cpp_std = 'c++20'\n    c_std = 'c20'\n    backend = 'xcode'\n    \"\"\")\n    assert expected in content\n\n\ndef test_needs_exe_wrapper():\n    \"\"\"\n    Tests needs_exe_wrapper depends on `can_run()` function instead of\n    simply checking the cross_building() one.\n\n    Issue: https://github.com/conan-io/conan/issues/19217\n    \"\"\"\n    host = textwrap.dedent(\"\"\"\n    [settings]\n    arch=x86_64\n    build_type=Release\n    compiler=apple-clang\n    compiler.cppstd=gnu17\n    compiler.libcxx=libc++\n    compiler.version=16\n    os=Macos\n    [conf]\n    tools.apple:sdk_path=/my/sdk/path\n    tools.build.cross_building:can_run=True\n    \"\"\")\n    build = textwrap.dedent(\"\"\"\n    [settings]\n    arch=armv8\n    build_type=Release\n    compiler=apple-clang\n    compiler.cppstd=gnu17\n    compiler.libcxx=libc++\n    compiler.version=16\n    os=Macos\n    \"\"\")\n    client = TestClient()\n    client.save({\n        \"host\": host,\n        \"build\": build,\n        \"conanfile.py\": GenConanfile(\"pkg\", \"1.0\")\n                        .with_settings(\"os\", \"arch\", \"compiler\", \"build_type\")\n                        .with_generator(\"MesonToolchain\")\n    })\n    client.run(\"install . -pr:h host -pr:b build\")\n    content = client.load(MesonToolchain.cross_filename)\n    assert \"needs_exe_wrapper = false\" in content\n"
  },
  {
    "path": "test/integration/toolchains/microsoft/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/toolchains/microsoft/test_msbuild_toolchain.py",
    "content": "import platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Only for windows\")\n@pytest.mark.parametrize(\n    \"compiler, version\",\n    [\n        (\"msvc\", \"190\"),\n        (\"msvc\", \"191\"),\n        (\"clang\", \"16\")\n    ],\n)\n@pytest.mark.parametrize(\"runtime\", [\"dynamic\", \"static\"])\n@pytest.mark.parametrize(\"runtime_type\", [\"Release\", \"Debug\"])\ndef test_toolchain_win(compiler, version, runtime, runtime_type):\n    client = TestClient(path_with_spaces=False)\n    settings = {\"compiler\": compiler,\n                \"compiler.version\": version,\n                \"compiler.cppstd\": \"14\",\n                \"compiler.runtime\": runtime,\n                \"compiler.runtime_type\": runtime_type,\n                \"build_type\": \"Release\",\n                \"arch\": \"x86_64\"}\n    if compiler == \"clang\":\n        settings[\"compiler.runtime_version\"] = \"v144\"\n\n    # Build the profile according to the settings provided\n    settings = \" \".join('-s %s=\"%s\"' % (k, v) for k, v in settings.items() if v)\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.microsoft import MSBuildToolchain\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            def generate(self):\n                msbuild = MSBuildToolchain(self)\n                msbuild.properties[\"IncludeExternals\"] = \"true\"\n                msbuild.generate()\n            \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(f\"install . {settings} -c tools.microsoft.msbuild:installation_path=\")\n    props = client.load(\"conantoolchain_release_x64.props\")\n    assert \"<IncludeExternals>true</IncludeExternals>\" in props\n    assert \"<LanguageStandard>stdcpp14</LanguageStandard>\" in props\n    if compiler == \"msvc\":\n        if version == \"190\":\n            assert \"<PlatformToolset>v140</PlatformToolset>\" in props\n        elif version == \"191\":\n            assert \"<PlatformToolset>v141</PlatformToolset>\" in props\n    elif compiler == \"clang\":\n        assert \"<PlatformToolset>ClangCl</PlatformToolset>\" in props\n    if runtime == \"dynamic\":\n        if runtime_type == \"Release\":\n            assert \"<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\" in props\n        else:\n            assert \"<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\" in props\n    else:\n        if runtime_type == \"Release\":\n            assert \"<RuntimeLibrary>MultiThreaded</RuntimeLibrary>\" in props\n        else:\n            assert \"<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\" in props\n"
  },
  {
    "path": "test/integration/toolchains/microsoft/test_msbuilddeps.py",
    "content": "import glob\nimport os\nimport platform\nimport textwrap\nfrom xml.dom import minidom\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.parametrize(\n    \"arch,exp_platform\",\n    [\n        (\"x86\", \"Win32\"),\n        (\"x86_64\", \"x64\"),\n        (\"armv7\", \"ARM\"),\n        (\"armv8\", \"ARM64\"),\n    ],\n)\ndef test_msbuilddeps_maps_architecture_to_platform(arch, exp_platform):\n    client = TestClient()\n    client.run(\"new msbuild_lib -d name=hello -d version=0.1\")\n    client.run(f\"install . -g MSBuildDeps -s arch={arch} -pr:b=default\")\n    toolchain = client.load(os.path.join(\"conan\", \"conantoolchain.props\"))\n    expected_import = f\"\"\"<Import Condition=\"'$(Configuration)' == 'Release' And '$(Platform)' == '{exp_platform}'\" Project=\"conantoolchain_release_{exp_platform.lower()}.props\"/>\"\"\"\n    assert expected_import in toolchain\n\n\n@pytest.mark.parametrize(\n    \"build_type,arch,configuration,exp_platform\",\n    [\n        (\"Release\", \"x86\", \"Release - Test\", \"Win32\"),\n        (\"Debug\", \"x86_64\", \"Debug - Test\", \"x64\"),\n    ],\n)\n@pytest.mark.parametrize(\n    \"config_key,platform_key\",\n    [\n        (\"GlobalConfiguration\", \"GlobalPlatform\"),\n        (None, None),\n    ],\n)\ndef test_msbuilddeps_import_condition(build_type, arch, configuration, exp_platform, config_key, platform_key):\n    client = TestClient()\n    app = textwrap.dedent(f\"\"\"\n        from conan import ConanFile\n        from conan.tools.microsoft import MSBuildDeps\n        class App(ConanFile):\n            requires = (\"lib/0.1\")\n            settings = \"arch\", \"build_type\"\n            options = {{\"configuration\": [\"ANY\"],\n                       \"platform\": [\"Win32\", \"x64\"]}}\n\n            def generate(self):\n                ms = MSBuildDeps(self)\n                ms.configuration_key = \"{config_key}\"\n                ms.configuration = self.options.configuration\n                ms.platform_key = \"{platform_key}\"\n                ms.platform = self.options.platform\n                ms.generate()\n        \"\"\")\n\n    # Remove custom set of keys to test default values\n    app = app.replace(f'ms.configuration_key = \"{config_key}\"', \"\") if config_key is None else app\n    app = app.replace(f'ms.platform_key = \"{platform_key}\"', \"\") if platform_key is None else app\n    config_key_expected = \"Configuration\" if config_key is None else config_key\n    platform_key_expected = \"Platform\" if platform_key is None else platform_key\n\n    client.save({\"app/conanfile.py\": app,\n                 \"lib/conanfile.py\": GenConanfile(\"lib\", \"0.1\").with_package_type(\"header-library\")})\n    client.run(\"create lib\")\n    client.run(f'install app -s build_type={build_type} -s arch={arch} -o *:platform={exp_platform} -o *:configuration=\"{configuration}\"')\n\n    assert os.path.exists(os.path.join(client.current_folder, \"app\", \"conan_lib.props\"))\n    dep = client.load(os.path.join(client.current_folder, \"app\", \"conan_lib.props\"))\n    expected_import = f\"\"\"<Import Condition=\"'$({config_key_expected})' == '{configuration}' And '$({platform_key_expected})' == '{exp_platform}'\" Project=\"conan_lib_{configuration.lower()}_{exp_platform.lower()}.props\"/>\"\"\"\n    assert expected_import in dep\n\n\ndef test_msbuilddeps_format_names():\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            name = \"pkg.name-more+\"\n            version = \"1.0\"\n\n            def package_info(self):\n                self.cpp_info.components[\"libmpdecimal++\"].libs = [\"libmp++\"]\n                self.cpp_info.components[\"mycomp.some-comp+\"].libs = [\"mylib\"]\n                self.cpp_info.components[\"libmpdecimal++\"].requires = [\"mycomp.some-comp+\"]\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"create . -s arch=x86_64\")\n    # Issue: https://github.com/conan-io/conan/issues/11822\n    c.run(\"install --require=pkg.name-more+/1.0@ -g MSBuildDeps -s build_type=Release -s arch=x86_64\")\n    # Checking that MSBuildDeps builds correctly the XML file\n    # loading all .props and xml parse them to check no errors\n    pkg_more = c.load(\"conan_pkg_name-more_.props\")\n    assert \"$(conan_pkg_name-more__libmpdecimal___props_imported)\" in pkg_more\n    assert \"$(conan_pkg_name-more__mycomp_some-comp__props_imported)\" in pkg_more\n\n    some_comp = c.load(\"conan_pkg_name-more__mycomp_some-comp_.props\")\n    assert \"<conan_pkg_name-more__mycomp_some-comp__props_imported>\" in some_comp\n\n    libmpdecimal = c.load(\"conan_pkg_name-more__libmpdecimal__.props\")\n    assert \"<conan_pkg_name-more__libmpdecimal___props_imported>\" in libmpdecimal\n\n    libmpdecimal_release = c.load(\"conan_pkg_name-more__libmpdecimal___release_x64.props\")\n    assert \"$(conan_pkg_name-more__mycomp_some-comp__props_imported)\" in libmpdecimal_release\n\n    counter = 0\n    for f in os.listdir(c.current_folder):\n        if f.endswith(\".props\"):\n            content = c.load(f)\n            minidom.parseString(content)\n            counter += 1\n    assert counter == 8\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows\")\nclass TestMSBuildDepsSkips:\n    # https://github.com/conan-io/conan/issues/15624\n    def test_msbuilddeps_skipped_deps(self):\n        c = TestClient()\n        c.save({\"liba/conanfile.py\": GenConanfile(\"liba\", \"0.1\").with_package_type(\"header-library\"),\n                \"libb/conanfile.py\": GenConanfile(\"libb\", \"0.1\").with_package_type(\"static-library\")\n                                                                .with_requires(\"liba/0.1\"),\n                \"app/conanfile.py\": GenConanfile().with_requires(\"libb/0.1\")\n                                                  .with_settings(\"arch\", \"build_type\")})\n        c.run(\"create liba\")\n        c.run(\"create libb\")\n        c.run(\"install app -g MSBuildDeps\")\n        assert not os.path.exists(os.path.join(c.current_folder, \"app\", \"conan_liba.props\"))\n        assert os.path.exists(os.path.join(c.current_folder, \"app\", \"conan_libb.props\"))\n        libb = c.load(\"app/conan_libb.props\")\n        assert \"conan_liba\" not in libb\n        libb = c.load(\"app/conan_libb_release_x64.props\")\n        assert \"conan_liba\" not in libb\n        libb = c.load(\"app/conan_libb_vars_release_x64.props\")\n        assert \"conan_liba\" not in libb\n\n    def test_msbuilddeps_skipped_deps_components(self):\n        c = TestClient()\n        libb = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Libb(ConanFile):\n                name = \"libb\"\n                version = \"0.1\"\n                package_type = \"static-library\"\n                requires = \"liba/0.1\"\n                def package_info(self):\n                    self.cpp_info.components[\"mycomp\"].libs = [\"mycomplib\"]\n                    self.cpp_info.components[\"mycomp\"].requires = [\"liba::liba\"]\n            \"\"\")\n\n        c.save({\"liba/conanfile.py\": GenConanfile(\"liba\", \"0.1\").with_package_type(\"header-library\"),\n                \"libb/conanfile.py\": libb,\n                \"app/conanfile.py\": GenConanfile().with_requires(\"libb/0.1\")\n                                                  .with_settings(\"arch\", \"build_type\")})\n        c.run(\"create liba\")\n        c.run(\"create libb\")\n        c.run(\"install app -g MSBuildDeps\")\n        assert not os.path.exists(os.path.join(c.current_folder, \"app\", \"conan_liba.props\"))\n        assert os.path.exists(os.path.join(c.current_folder, \"app\", \"conan_libb.props\"))\n        libb = c.load(\"app/conan_libb.props\")\n        assert \"conan_liba\" not in libb\n        libb = c.load(\"app/conan_libb_mycomp.props\")\n        assert \"conan_liba\" not in libb\n        libb = c.load(\"app/conan_libb_mycomp_release_x64.props\")\n        assert \"conan_liba\" not in libb\n        libb = c.load(\"app/conan_libb_mycomp_vars_release_x64.props\")\n        assert \"conan_liba\" not in libb\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"MSBuildDeps broken with POSIX paths\")\n@pytest.mark.parametrize(\"withdepl\", [False, True])\ndef test_msbuilddeps_relocatable(withdepl):\n    c = TestClient()\n    c.save({\n        \"libh/conanfile.py\": GenConanfile(\"libh\", \"0.1\").with_package_type(\"header-library\"),\n        \"libs/conanfile.py\": GenConanfile(\"libs\", \"0.2\").with_package_type(\"static-library\")\n                                                        .with_requires(\"libh/0.1\"),\n        \"libd/conanfile.py\": GenConanfile(\"libd\", \"0.3\").with_package_type(\"shared-library\"),\n        \"app/conanfile.py\": GenConanfile().with_requires(\"libh/0.1\", \"libs/0.2\", \"libd/0.3\")\n                                          .with_settings(\"arch\", \"build_type\"),\n    })\n\n    c.run(\"create libh\")\n    c.run(\"create libs\")\n    c.run(\"create libd\")\n    c.run(\"install app -g MSBuildDeps\" + (\" -d full_deploy\" if withdepl else \"\"))\n\n    for dep in [\"libh\", \"libs\", \"libd\"]:\n        text = c.load(f\"app/conan_{dep}_vars_release_x64.props\")\n        marker = f\"Conan{dep}RootFolder\"\n        value = text.split(f\"<{marker}>\")[1].split(f\"</{marker}>\")[0]\n        if withdepl:\n            # path should be relative, since artifacts are moved along with project\n            prefix = '$(MSBuildThisFileDirectory)\\\\'\n            assert value.startswith(prefix)\n            tail = value[len(prefix):]\n            assert not os.path.isabs(tail)\n        else:\n            # path should be absolute, since conan cache does not move with project\n            assert os.path.isabs(value)\n            assert '$(' not in value\n\n    if withdepl:\n        # extra checks: no absolute paths allowed anywhere in props\n        propsfiles = glob.glob(os.path.join(c.current_folder, \"app/*.props\"))\n        assert len(propsfiles) > 0\n        for fn in propsfiles:\n            text = c.load(fn)\n            text = text.replace('\\\\', '/')\n            folder = c.current_folder.replace('\\\\', '/')\n            assert folder not in text\n\n\ndef test_msbuilddeps_consume_meson():\n    c = TestClient()\n    pkga = textwrap.dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.files import save\n        class Pkg(ConanFile):\n            name = \"pkga\"\n            version = \"0.1\"\n            package_type = \"static-library\"\n            def package(self):\n                save(self, os.path.join(self.package_folder, \"lib\", \"libpkga.a\"), \"\")\n            def package_info(self):\n                self.cpp_info.libs = [\"pkga\"]\n        \"\"\")\n\n    c.save({\"pkga/conanfile.py\": pkga,\n            \"app/conanfile.py\": GenConanfile().with_requires(\"pkga/0.1\")\n                                              .with_settings(\"arch\", \"build_type\")})\n    c.run(\"create pkga -s arch=x86_64\")\n    c.run(\"install app -g MSBuildDeps -s arch=x86_64\")\n    deps = c.load(\"app/conan_pkga_vars_release_x64.props\")\n    assert \"<ConanpkgaLibraries>libpkga.a;</ConanpkgaLibraries>\" in deps\n\n\ndef test_build_requires_transitives_with_components():\n    c = TestClient()\n    c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\")\n                                    .with_package_type(\"shared-library\")\n                                    .with_package_info(cpp_info={\n                                        \"components\": {\n                                            \"core\": {\"libs\": [\"depcore\"]},\n                                            \"extra\": {\"requires\": [\"core\"]}\n                                        }\n                                    }),\n        \"tool/conanfile.py\": GenConanfile(\"tool\", \"0.1\")\n                                 .with_requires(\"dep/0.1\")\n                                 .with_package_info(cpp_info={\n                                     \"components\": {\n                                         \"a\": {\"requires\": [\"dep::core\"]},\n                                         \"b\": {\"requires\": [\"dep::dep\"]}\n                                     }\n                                 }),\n            \"consumer/conanfile.py\":\n                GenConanfile().with_settings(\"os\", \"compiler\", \"build_type\", \"arch\")\n                              .with_build_requires(\"tool/0.1\")})\n    c.run(\"create dep -s arch=x86_64\")\n    c.run(\"create tool -s arch=x86_64\")\n    c.run(\"install consumer -g MSBuildDeps -of=. -s arch=x86_64\")\n\n    dep_extra = c.load(\"conan_dep_build_extra_release_x64.props\")\n    assert \"conan_dep_build_core.props\" in dep_extra\n    assert \"conan_dep_core.props\" not in dep_extra\n\n    tool_a = c.load(\"conan_tool_build_a_release_x64.props\")\n    assert \"conan_dep_build_core.props\" in tool_a\n    assert \"conan_dep_core.props\" not in tool_a\n\n    tool_b = c.load(\"conan_tool_build_b_release_x64.props\")\n    assert \"conan_dep_build.props\" in tool_b\n    assert \"conan_dep.props\" not in tool_b\n"
  },
  {
    "path": "test/integration/toolchains/microsoft/test_msbuildtoolchain.py",
    "content": "import os\nimport textwrap\n\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_msbuildtoolchain_props_with_extra_flags():\n    \"\"\"\n    Simple test checking that conantoolchain_release_x64.props is adding all the expected\n    flags and preprocessor definitions\n    \"\"\"\n    profile = textwrap.dedent(\"\"\"\\\n    include(default)\n    [settings]\n    arch=x86_64\n    [conf]\n    tools.build:cxxflags=[\"--flag1\", \"--flag2\"]\n    tools.build:cflags+=[\"--flag3\", \"--flag4\"]\n    tools.build:sharedlinkflags+=[\"--flag5\"]\n    tools.build:exelinkflags+=[\"--flag6\"]\n    tools.build:defines+=[\"DEF1\", \"DEF2\"]\n    \"\"\")\n    client = TestClient()\n    client.run(\"new msbuild_lib -d name=hello -d version=0.1\")\n    client.save({\n        \"myprofile\": profile\n    })\n    # Local flow works\n    client.run(\"install . -pr myprofile\")\n    toolchain = client.load(os.path.join(\"conan\", \"conantoolchain_release_x64.props\"))\n    expected_cl_compile = \"\"\"\n    <ClCompile>\n      <PreprocessorDefinitions>DEF1;DEF2;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalOptions>--flag1 --flag2 --flag3 --flag4 %(AdditionalOptions)</AdditionalOptions>\"\"\"\n    expected_link = \"\"\"\n    <Link>\n      <AdditionalOptions>--flag5 --flag6 %(AdditionalOptions)</AdditionalOptions>\n    </Link>\"\"\"\n    expected_resource_compile = \"\"\"\n    <ResourceCompile>\n      <PreprocessorDefinitions>DEF1;DEF2;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ResourceCompile>\"\"\"\n    assert expected_cl_compile in toolchain\n    assert expected_link in toolchain\n    assert expected_resource_compile in toolchain\n\n\ndef test_msbuildtoolchain_rcflags():\n    \"\"\"Test that tools.build:rcflags is applied to ResourceCompile AdditionalOptions\"\"\"\n    profile = textwrap.dedent(\"\"\"\\\n    include(default)\n    [settings]\n    arch=x86_64\n    [conf]\n    tools.build:rcflags=[\"/flag-rc1\", \"/flag-rc2\"]\n    \"\"\")\n    client = TestClient()\n    client.run(\"new msbuild_lib -d name=hello -d version=0.1\")\n    client.save({\"myprofile\": profile})\n    client.run(\"install . -pr myprofile\")\n    toolchain = client.load(os.path.join(\"conan\", \"conantoolchain_release_x64.props\"))\n    expected_resource_compile = (\"<AdditionalOptions>/flag-rc1 /flag-rc2 %(AdditionalOptions)\"\n                                 \"</AdditionalOptions>\")\n    assert expected_resource_compile in toolchain\n"
  },
  {
    "path": "test/integration/toolchains/microsoft/test_nmakedeps.py",
    "content": "import platform\nimport re\nimport textwrap\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Only for windows\")\ndef test_nmakedeps():\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n            name = \"test-nmakedeps\"\n            version = \"1.0\"\n\n            def package_info(self):\n                self.cpp_info.components[\"pkg-1\"].libs = [\"pkg-1\"]\n                self.cpp_info.components[\"pkg-1\"].defines = [\"TEST_DEFINITION1\"]\n                self.cpp_info.components[\"pkg-1\"].system_libs = [\"ws2_32\"]\n                self.cpp_info.components[\"pkg-2\"].libs = [\"pkg-2\"]\n                self.cpp_info.components[\"pkg-2\"].defines = [\"TEST_DEFINITION2=0\"]\n                self.cpp_info.components[\"pkg-2\"].requires = [\"pkg-1\"]\n                self.cpp_info.components[\"pkg-3\"].libs = [\"pkg-3\"]\n                self.cpp_info.components[\"pkg-3\"].defines = [\"TEST_DEFINITION3=\"]\n                self.cpp_info.components[\"pkg-3\"].requires = [\"pkg-1\", \"pkg-2\"]\n                self.cpp_info.components[\"pkg-4\"].libs = [\"pkg-4\"]\n                self.cpp_info.components[\"pkg-4\"].defines = [\"TEST_DEFINITION4=foo\",\n                                                            \"TEST_DEFINITION5=__declspec(dllexport)\",\n                                                            \"TEST_DEFINITION6=foo bar\",\n                                                            \"TEST_DEFINITION7=7\"]\n    \"\"\")\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . -s arch=x86_64\")\n    client.run(\"install --requires=test-nmakedeps/1.0\"\n               \" -g NMakeDeps -s build_type=Release -s arch=x86_64\")\n    # Checking that NMakeDeps builds correctly .bat file\n    bat_file = client.load(\"conannmakedeps.bat\")\n    # Checking that defines are added to CL\n    for flag in (\n        r'/D\"TEST_DEFINITION1\"', '/D\"TEST_DEFINITION2#0\"',\n        r'/D\"TEST_DEFINITION3#\"', '/D\"TEST_DEFINITION4#\"foo\"\"',\n        r'/D\"TEST_DEFINITION5#\"__declspec\\(dllexport\\)\"\"',\n        r'/D\"TEST_DEFINITION6#\"foo bar\"\"',\n        r'/D\"TEST_DEFINITION7#7\"'\n    ):\n        assert re.search(fr'set \"CL=%CL%.*\\s{flag}(?:\\s|\")', bat_file)\n    # Checking that libs and system libs are added to _LINK_\n    for flag in (r\"pkg-1\\.lib\", r\"pkg-2\\.lib\", r\"pkg-3\\.lib\", r\"pkg-4\\.lib\", r\"ws2_32\\.lib\"):\n        assert re.search(fr'set \"_LINK_=%_LINK_%.*\\s{flag}(?:\\s|\")', bat_file)\n"
  },
  {
    "path": "test/integration/toolchains/microsoft/test_nmaketoolchain.py",
    "content": "import os\nimport platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"NMake toolchain is Windows-only\")\ndef test_nmaketoolchain_rcflags():\n    \"\"\"Test that tools.build:rcflags is applied to RCFLAGS in the NMake toolchain environment.\"\"\"\n    profile = textwrap.dedent(\"\"\"\\\n        include(default)\n        [settings]\n        arch=x86_64\n        [conf]\n        tools.build:rcflags=[\"/nologo\", \"/flag-rc1\"]\n        \"\"\")\n    client = TestClient()\n    conanfile = GenConanfile().with_settings(\"os\", \"arch\", \"compiler\", \"build_type\").with_generator(\"NMakeToolchain\")\n    client.save({\"conanfile.py\": conanfile, \"profile\": profile})\n    client.run(\"install . -pr profile\")\n    script = client.load(\"conannmaketoolchain.bat\")\n    assert \"RCFLAGS\" in script\n    assert \"/nologo\" in script or \"nologo\" in script\n    assert \"/flag-rc1\" in script or \"flag-rc1\" in script\n"
  },
  {
    "path": "test/integration/toolchains/microsoft/test_vs_layout.py",
    "content": "import os\nimport textwrap\n\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_vs_layout_subproject():\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.microsoft import vs_layout\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"MSBuildToolchain\"\n            def layout(self):\n                self.folders.root = \"..\"\n                self.folders.subproject = \"pkg\"\n                vs_layout(self)\n        \"\"\")\n    c.save({\"pkg/conanfile.py\": conanfile})\n    c.run(\"install pkg\")\n    assert os.path.isfile(os.path.join(c.current_folder, \"pkg\", \"conan\", \"conantoolchain.props\"))\n\n\ndef test_vs_layout_error():\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.microsoft import vs_layout\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"arch\"\n            def layout(self):\n                vs_layout(self)\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"install .\", assert_error=True)\n    assert \"The 'vs_layout' requires the 'build_type' setting\" in c.out\n    conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.microsoft import vs_layout\n            class Pkg(ConanFile):\n                settings = \"os\", \"compiler\", \"build_type\"\n                def layout(self):\n                    vs_layout(self)\n            \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"install .\", assert_error=True)\n    assert \"The 'vs_layout' requires the 'arch' setting\" in c.out\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.microsoft import vs_layout\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            def layout(self):\n                vs_layout(self)\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"install . -s arch=riscv64\", assert_error=True)\n    assert \"The 'vs_layout' doesn't work with the arch 'riscv64'\" in c.out\n    assert \"Accepted architectures: 'x86', 'x86_64', 'armv7', 'armv8'\" in c.out\n"
  },
  {
    "path": "test/integration/toolchains/microsoft/vcvars_test.py",
    "content": "import platform\nimport textwrap\nimport os\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.skipif(platform.system() not in [\"Windows\"], reason=\"Requires Windows\")\n@pytest.mark.parametrize(\"scope\", [\"build\", \"run\", None])\ndef test_vcvars_generator(scope):\n    client = TestClient(path_with_spaces=False)\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.microsoft import VCVars\n\n        class TestConan(ConanFile):\n            settings = \"os\", \"compiler\", \"arch\", \"build_type\"\n\n            def generate(self):\n                VCVars(self).generate({})\n    \"\"\".format('scope=\"{}\"'.format(scope) if scope else \"\"))\n\n    client.save({\"conanfile.py\": conanfile})\n    client.run('install . -s os=Windows -s compiler=\"msvc\" -s compiler.version=191 '\n               '-s compiler.cppstd=14 -s compiler.runtime=static')\n\n    assert os.path.exists(os.path.join(client.current_folder, \"conanvcvars.bat\"))\n    assert r\"VC\\Auxiliary\\Build\\vcvarsall.bat\" in client.load(\"conanvcvars.bat\")\n    bat_contents = client.load(\"conanbuild.bat\")\n    if scope in (\"build\", None):\n        assert \"conanvcvars.bat\" in bat_contents\n\n\n@pytest.mark.skipif(platform.system() not in [\"Windows\"], reason=\"Requires Windows\")\ndef test_vcvars_generator_skip():\n    \"\"\"\n    tools.microsoft.msbuild:installation_path=disabled avoids creation of conanvcvars.bat\n    \"\"\"\n    client = TestClient()\n    client.save({\"conanfile.py\": GenConanfile().with_generator(\"VCVars\")\n                                               .with_settings(\"os\", \"compiler\",\n                                                              \"arch\", \"build_type\"),\n                 \"profile\": 'include(default)\\n[conf]\\ntools.microsoft.msbuild:installation_path='})\n\n    client.run('install . -c tools.microsoft.msbuild:installation_path=\"\"')\n    assert not os.path.exists(os.path.join(client.current_folder, \"conanvcvars.bat\"))\n    client.run('install . -pr=profile')\n    assert not os.path.exists(os.path.join(client.current_folder, \"conanvcvars.bat\"))\n\n\n@pytest.mark.skipif(platform.system() not in [\"Linux\"], reason=\"Requires Linux\")\ndef test_vcvars_generator_skip_on_linux():\n    \"\"\"\n    Skip creation of conanvcvars.bat on Linux build systems\n    \"\"\"\n    client = TestClient()\n    client.save({\"conanfile.txt\": \"[generators]\\nVCVars\"})\n\n    client.run('install . -s os=Windows -s compiler=msvc -s compiler.version=193 '\n               '-s compiler.runtime=dynamic')\n    assert not os.path.exists(os.path.join(client.current_folder, \"conanvcvars.bat\"))\n\n\n@pytest.mark.skipif(platform.system() not in [\"Windows\"], reason=\"Requires Windows\")\ndef test_vcvars_generator_string():\n    client = TestClient(path_with_spaces=False)\n    client.save({\"conanfile.txt\": \"[generators]\\nVCVars\"})\n    client.run('install . -s os=Windows -s compiler=\"msvc\" -s compiler.version=191 '\n               '-s compiler.cppstd=14 -s compiler.runtime=static')\n\n    assert os.path.exists(os.path.join(client.current_folder, \"conanvcvars.bat\"))\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows\")\ndef test_vcvars_platform_x86():\n    # https://github.com/conan-io/conan/issues/11144\n    client = TestClient(path_with_spaces=False)\n    client.save({\"conanfile.txt\": \"[generators]\\nVCVars\"})\n    client.run('install . -s os=Windows -s compiler=\"msvc\" -s compiler.version=193 '\n               '-s compiler.cppstd=14 -s compiler.runtime=static -s:b arch=x86')\n\n    vcvars = client.load(\"conanvcvars.bat\")\n    assert 'vcvarsall.bat\"  x86_amd64' in vcvars\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows\")\ndef test_vcvars_winsdk_version():\n    client = TestClient(path_with_spaces=False)\n    client.save({\"conanfile.txt\": \"[generators]\\nVCVars\"})\n    client.run('install . -s os=Windows -s compiler=msvc -s compiler.version=193 '\n               '-s compiler.cppstd=14 -s compiler.runtime=static '\n               '-c tools.microsoft:winsdk_version=10.0')\n\n    vcvars = client.load(\"conanvcvars.bat\")\n    assert 'vcvarsall.bat\"  amd64 10.0 -vcvars_ver=14.3' in vcvars\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows\")\ndef test_vcvars_compiler_update():\n    client = TestClient(path_with_spaces=False)\n    client.save({\"conanfile.txt\": \"[generators]\\nVCVars\"})\n    client.run('install . -s os=Windows -s compiler=msvc -s compiler.version=193 '\n               '-s compiler.cppstd=14 -s compiler.runtime=static '\n               '-s compiler.update=3')\n\n    vcvars = client.load(\"conanvcvars.bat\")\n    assert 'vcvarsall.bat\"  amd64 -vcvars_ver=14.33' in vcvars\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows\")\ndef test_vcvars_conf_msvc_update():\n    client = TestClient(path_with_spaces=False)\n    client.save({\"conanfile.txt\": \"[generators]\\nVCVars\"})\n    client.run('install . -s os=Windows -s compiler=msvc -s compiler.version=193 '\n               '-s compiler.cppstd=14 -s compiler.runtime=static '\n               '-c tools.microsoft:msvc_update=8.29910')\n\n    vcvars = client.load(\"conanvcvars.bat\")\n    assert 'vcvarsall.bat\"  amd64 -vcvars_ver=14.38.29910' in vcvars\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows\")\ndef test_vcvars_armv8_windows_store():\n    client = TestClient(path_with_spaces=False)\n    client.save({\"conanfile.txt\": \"[generators]\\nVCVars\"})\n    client.run('install . -s:b os=Windows -s compiler=\"msvc\" -s compiler.version=194 '\n               '-s compiler.cppstd=14 -s compiler.runtime=static -s:h arch=armv8 '\n               '-s:h os=WindowsStore -s:h os.version=10.0')\n\n    vcvars = client.load(\"conanvcvars.bat\")\n    assert 'vcvarsall.bat\"  amd64_arm64' in vcvars\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows\")\ndef test_vcvars_clang_visual2026():\n    client = TestClient(path_with_spaces=False)\n    client.save({\"conanfile.txt\": \"[generators]\\nVCVars\"})\n    client.run('install . -s:b os=Windows -s compiler=clang -s compiler.version=20 '\n               '-s compiler.cppstd=14 -s compiler.runtime=static -s arch=x86_64 '\n               '-s compiler.runtime_version=v145 '\n               # Using a known existing path to avoid auto-detection via vswhere\n               '-c tools.microsoft.msbuild:installation_path=C:/')\n\n    vcvars = client.load(\"conanvcvars.bat\")\n    assert '-vcvars_ver=14.5' in vcvars\n"
  },
  {
    "path": "test/integration/toolchains/premake/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/toolchains/premake/test_premake.py",
    "content": "import textwrap\n\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_premake_args_without_toolchain():\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.premake import Premake\n\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            def run(self, cmd, *args, **kwargs):\n                self.output.info(f\"Running {cmd}!!\")\n            def build(self):\n                premake = Premake(self)\n                premake.luafile = \"myproject.lua\"\n                premake.arguments = {\"myarg\": \"myvalue\"}\n                premake.configure()\n                \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\n        \"build . -s compiler=msvc -s compiler.version=193 -s compiler.runtime=dynamic\"\n    )\n    assert (\n        'conanfile.py: Running premake5 --file=\"myproject.lua\" vs2022 --myarg=myvalue!!'\n        in c.out\n    )\n\n\ndef test_premake_build_without_toolchain():\n    tc = TestClient()\n    conanfile = textwrap.dedent(\n        \"\"\"\n        from conan import ConanFile\n        from conan.tools.premake import Premake, PremakeToolchain\n\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            def run(self, cmd, *args, **kwargs):\n                self.output.info(f\"Running {cmd}!!\")\n            def build(self):\n                premake = Premake(self)\n                premake.configure()\n                premake.build(workspace=\"App\")\n                \"\"\"\n    )\n    tc.save({\"conanfile.py\": conanfile})\n    tc.run(\n        \"build . -s compiler=msvc -s compiler.version=193 -s compiler.runtime=dynamic\",\n        assert_error=True,\n    )\n    assert \"Premake.build() method requires PremakeToolchain to work properly\" in tc.out\n\n\ndef test_premake_build():\n    tc = TestClient()\n    conanfile = textwrap.dedent(\n        \"\"\"\n        from conan import ConanFile\n        from conan.tools.premake import Premake, PremakeToolchain\n\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"PremakeToolchain\"\n            def run(self, cmd, *args, **kwargs):\n                self.output.info(f\"Running {cmd}!!\")\n            def build(self):\n                premake = Premake(self)\n                premake.configure()\n                premake.build(workspace=\"App\")\n                \"\"\"\n    )\n    tc.save({\"conanfile.py\": conanfile})\n    tc.run(\n        \"build . -s compiler=gcc -s compiler.version=13 -s compiler.libcxx=libstdc++ -s arch=x86_64 -c tools.build:jobs=4\",\n    )\n    assert 'conanfile.premake5.lua\" gmake --arch=x86_64!!' in tc.out\n    assert \"Running make config=release all -j4!!\" in tc.out\n\n\ndef test_premake_build_with_targets():\n    tc = TestClient()\n    conanfile = textwrap.dedent(\n        \"\"\"\n        from conan import ConanFile\n        from conan.tools.premake import Premake, PremakeToolchain\n\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"PremakeToolchain\"\n            def run(self, cmd, *args, **kwargs):\n                self.output.info(f\"Running {cmd}!!\")\n            def build(self):\n                premake = Premake(self)\n                premake.configure()\n                premake.build(workspace=\"App\", targets=[\"app\", \"test\"])\n                \"\"\"\n    )\n    tc.save({\"conanfile.py\": conanfile})\n    tc.run(\n        \"build . -s compiler=gcc -s compiler.version=13 -s compiler.libcxx=libstdc++ -s arch=armv8 -c tools.build:jobs=42\",\n    )\n    assert 'conanfile.premake5.lua\" gmake --arch=arm64!!' in tc.out\n    assert \"Running make config=release app test -j42!!\" in tc.out\n\n\ndef test_premake_msbuild_platform():\n    tc = TestClient()\n    windows_profile = textwrap.dedent(\"\"\"\n        [settings]\n        arch=x86_64\n        build_type=Release\n        compiler=msvc\n        compiler.cppstd=14\n        compiler.runtime=dynamic\n        compiler.version=194\n        os=Windows\n    \"\"\")\n\n    conanfile = textwrap.dedent(\n        \"\"\"\n        from conan import ConanFile\n        from conan.tools.premake import Premake, PremakeToolchain\n\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"PremakeToolchain\"\n            def run(self, cmd, *args, **kwargs):\n                self.output.info(f\"Running {cmd}!!\")\n            def build(self):\n                premake = Premake(self)\n                premake.configure()\n                premake.build(workspace=\"App\", msbuild_platform=\"Win64\")\n                \"\"\"\n    )\n    tc.save({\"conanfile.py\": conanfile, \"win\": windows_profile})\n    tc.run(\"build . -pr win\")\n    assert 'conanfile.premake5.lua\" vs2022 --arch=x86_64!!' in tc.out\n    assert 'Running msbuild.exe \"App.sln\" -p:Configuration=\"Release\" -p:Platform=\"Win64\"!!' in tc.out\n\n\ndef test_premake_build_with_custom_configuration():\n    tc = TestClient()\n    conanfile = textwrap.dedent(\n        \"\"\"\n        from conan import ConanFile\n        from conan.tools.premake import Premake, PremakeDeps, PremakeToolchain\n\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            generators = \"PremakeToolchain\"\n            def run(self, cmd, *args, **kwargs):\n                self.output.info(f\"Running {cmd}!!\")\n            def generate(self):\n                deps = PremakeDeps(self)\n                deps.configuration = \"ReleaseDLL\"\n            def build(self):\n                premake = Premake(self)\n                premake.configure()\n                premake.build(workspace=\"App\", configuration=\"ReleaseDLL\")\n                \"\"\"\n    )\n    tc.save({\"conanfile.py\": conanfile})\n    tc.run(\n        \"build . -s compiler=gcc -s compiler.version=13 -s compiler.libcxx=libstdc++ -s arch=armv8 -c tools.build:jobs=4\",\n    )\n    assert 'conanfile.premake5.lua\" gmake --arch=arm64!!' in tc.out\n    assert \"Running make config=releasedll all -j4!!\" in tc.out\n\n"
  },
  {
    "path": "test/integration/toolchains/premake/test_premakedeps.py",
    "content": "import textwrap\nimport pytest\nimport os\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef assert_vars_file(client, configuration):\n    contents = client.load(f\"conan_pkg.name-more+_vars_{configuration}_x86_64.premake5.lua\")\n    assert f'include \"conanutils.premake5.lua\"' in contents\n    assert f't_conandeps = {{}}' in contents\n    assert f't_conandeps[\"{configuration}_x86_64\"] = {{}}' in contents\n    assert f't_conandeps[\"{configuration}_x86_64\"][\"pkg.name-more+\"] = {{}}' in contents\n    assert f't_conandeps[\"{configuration}_x86_64\"][\"pkg.name-more+\"][\"includedirs\"]' in contents\n    assert f't_conandeps[\"{configuration}_x86_64\"][\"pkg.name-more+\"][\"libdirs\"]' in contents\n    assert f't_conandeps[\"{configuration}_x86_64\"][\"pkg.name-more+\"][\"bindirs\"]' in contents\n    assert f't_conandeps[\"{configuration}_x86_64\"][\"pkg.name-more+\"][\"libs\"]' in contents\n    assert f't_conandeps[\"{configuration}_x86_64\"][\"pkg.name-more+\"][\"system_libs\"]' in contents\n    assert f't_conandeps[\"{configuration}_x86_64\"][\"pkg.name-more+\"][\"defines\"]' in contents\n    assert f't_conandeps[\"{configuration}_x86_64\"][\"pkg.name-more+\"][\"cxxflags\"]' in contents\n    assert f't_conandeps[\"{configuration}_x86_64\"][\"pkg.name-more+\"][\"cflags\"]' in contents\n    assert f't_conandeps[\"{configuration}_x86_64\"][\"pkg.name-more+\"][\"sharedlinkflags\"]' in contents\n    assert f't_conandeps[\"{configuration}_x86_64\"][\"pkg.name-more+\"][\"exelinkflags\"]' in contents\n    assert f't_conandeps[\"{configuration}_x86_64\"][\"pkg.name-more+\"][\"frameworks\"]' in contents\n    assert f'if conandeps == nil then conandeps = {{}} end' in contents\n    assert f'conan_premake_tmerge(conandeps, t_conandeps)' in contents\n\n\ndef test_premakedeps():\n    # Create package\n    client = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            name = \"pkg.name-more+\"\n            version = \"1.0\"\n\n            def package_info(self):\n                self.cpp_info.components[\"libmpdecimal++\"].libs = [\"libmp++\"]\n                self.cpp_info.components[\"mycomp.some-comp+\"].libs = [\"mylib\"]\n                self.cpp_info.components[\"libmpdecimal++\"].requires = [\"mycomp.some-comp+\"]\n        \"\"\")\n    client.save({\"conanfile.py\": conanfile}, clean_first=True)\n    client.run(\"create . -s arch=x86_64 -s build_type=Debug\")\n    client.run(\"create . -s arch=x86_64 -s build_type=Release\")\n\n    # Run conan\n    client.run(\"install --require=pkg.name-more+/1.0@ -g PremakeDeps -s arch=x86_64 -s build_type=Debug\")\n    client.run(\"install --require=pkg.name-more+/1.0@ -g PremakeDeps -s arch=x86_64 -s build_type=Release\")\n\n    # Assert root lua file\n    contents = client.load(\"conandeps.premake5.lua\")\n    assert 'include \"conan_pkg.name-more+.premake5.lua\"' in contents\n    assert 'function conan_setup_build(conf, pkg)' in contents\n    assert 'function conan_setup_link(conf, pkg)' in contents\n    assert 'function conan_setup(conf, pkg)' in contents\n\n    # Assert package root file\n    contents = client.load(\"conan_pkg.name-more+.premake5.lua\")\n    assert 'include \"conan_pkg.name-more+_vars_debug_x86_64.premake5.lua\"' in contents\n    assert 'include \"conan_pkg.name-more+_vars_release_x86_64.premake5.lua\"' in contents\n\n    # Assert package per configuration files\n    assert_vars_file(client, 'debug')\n    assert_vars_file(client, 'release')\n\n\ndef test_premakedeps_link_order():\n    client = TestClient()\n    profile = textwrap.dedent(\n        \"\"\"\n        [settings]\n        os=Linux\n        arch=x86_64\n        compiler=gcc\n        compiler.version=9\n        compiler.cppstd=17\n        compiler.libcxx=libstdc++\n        build_type=Release\n        \"\"\")\n    client.save(\n        {\n            \"liba/conanfile.py\": GenConanfile(\"liba\")\n            .with_settings(\"os\", \"compiler\", \"build_type\", \"arch\")\n            .with_version(\"1.0\")\n            .with_generator(\"PremakeDeps\")\n            .with_generator(\"PremakeToolchain\")\n            .with_package_info(cpp_info={\"libs\": [\"liba\"]}),\n\n            \"libb/conanfile.py\": GenConanfile(\"libb\")\n            .with_settings(\"os\", \"compiler\", \"build_type\", \"arch\")\n            .with_version(\"1.0\")\n            .with_requires(\"liba/1.0\")\n            .with_generator(\"PremakeDeps\")\n            .with_package_info(\n                cpp_info={\n                    \"components\": {\n                        \"libb1\": {\"requires\": [\"liba::liba\"]},\n                        \"libb2\": {\"requires\": [\"libb1\"]},\n                    }\n                }\n            ),\n\n            \"libc/conanfile.py\": GenConanfile(\"libc\")\n            .with_settings(\"os\", \"compiler\", \"build_type\", \"arch\")\n            .with_version(\"1.0\")\n            .with_requires(\"libb/1.0\")\n            .with_generator(\"PremakeDeps\")\n            .with_package_info(cpp_info={\"libs\": [\"libc\"]}),\n\n            \"consumer/conanfile.py\": GenConanfile(\"consumer\")\n            .with_settings(\"os\", \"compiler\", \"build_type\", \"arch\")\n            .with_version(\"1.0\")\n            .with_requires(\"libc/1.0\")\n            .with_generator(\"PremakeDeps\"),\n\n            \"profile\": profile\n        }\n    )\n    client.run(\"create liba -pr profile\")\n    client.run(\"create libb -pr profile\")\n    client.run(\"create libc -pr profile\")\n    client.run(\"install consumer -pr profile\")\n    contents = client.load(\"consumer/conanconfig.premake5.lua\")\n    assert 'include \"conanconfig_release_x86_64.premake5.lua\"' in contents\n    contents = client.load(\"consumer/conanconfig_release_x86_64.premake5.lua\")\n    # Check correct order of dependencies: more dependent libs should be linked first\n    assert 't_conan_deps_order[\"release_x86_64\"] = {\"libc\", \"libb\", \"liba\"}' in contents\n\n    # Check previous configurations are preserved when installing new configuration\n    client.run(\"install consumer -pr profile -s build_type=Debug --build=missing\")\n    contents = client.load(\"consumer/conanconfig.premake5.lua\")\n    assert 'include \"conanconfig_release_x86_64.premake5.lua\"' in contents\n    assert 'include \"conanconfig_debug_x86_64.premake5.lua\"' in contents\n    contents = client.load(\"consumer/conanconfig_debug_x86_64.premake5.lua\")\n    assert 't_conan_deps_order[\"debug_x86_64\"] = {\"libc\", \"libb\", \"liba\"}' in contents\n\n\n@pytest.mark.parametrize(\"transitive_headers\", [True, False])\n@pytest.mark.parametrize(\"transitive_libs\", [True, False])\n@pytest.mark.parametrize(\"brotli_package_type\", [\"unknown\", \"static-library\", \"shared-library\"])\n@pytest.mark.parametrize(\"lib_package_type\", [\"unknown\", \"static-library\", \"shared-library\"])\ndef test_premakedeps_traits(transitive_headers, transitive_libs, brotli_package_type,\n                            lib_package_type):\n    client = TestClient()\n    profile = textwrap.dedent(\n        \"\"\"\n        [settings]\n        os=Linux\n        arch=x86_64\n        compiler=gcc\n        compiler.version=9\n        compiler.cppstd=17\n        compiler.libcxx=libstdc++\n        build_type=Release\n        \"\"\")\n\n    client.save(\n        {\n            \"brotli/conanfile.py\": GenConanfile(\"brotli\", \"1.0\")\n            .with_package_type(brotli_package_type)\n            .with_package_info(\n                {\"libs\": [\"brotlienc2\"]}\n            ),\n            \"lib/conanfile.py\": GenConanfile(\"lib\", \"1.0\")\n            .with_package_type(lib_package_type)\n            .with_requirement(\n                \"brotli/1.0\",\n                transitive_headers=transitive_headers,\n                transitive_libs=transitive_libs,\n            ),\n            \"conanfile.py\": GenConanfile(\"app\", \"1.0\")\n            .with_settings(\"os\", \"compiler\", \"build_type\", \"arch\")\n            .with_require(\"lib/1.0\")\n            .with_generator(\"PremakeDeps\"),\n            \"profile\": profile,\n        }\n    )\n    client.run(\"create brotli -pr profile\")\n    brotli_layout = client.created_layout()\n    client.run(\"create lib -pr profile\")\n    client.run(\"install . -pr profile\")\n\n    if not transitive_headers and not transitive_libs and brotli_package_type != \"shared-library\":\n        assert not os.path.exists(os.path.join(client.current_folder, \"conan_brotli_vars_release_x86_64.premake5.lua\"))\n        return\n\n    brotli_vars = client.load(\"conan_brotli_vars_release_x86_64.premake5.lua\")\n    if transitive_libs:\n        assert 't_conandeps[\"release_x86_64\"][\"brotli\"][\"libs\"] = {\"brotlienc2\"}' in brotli_vars\n    else:\n        assert 't_conandeps[\"release_x86_64\"][\"brotli\"][\"libs\"] = {}' in brotli_vars\n\n    if transitive_headers:\n        include_path = os.path.join(brotli_layout.package(), \"include\").replace(\"\\\\\", \"/\")\n        assert f't_conandeps[\"release_x86_64\"][\"brotli\"][\"includedirs\"] = {{\"{include_path}\"}}' in brotli_vars\n    else:\n        assert 't_conandeps[\"release_x86_64\"][\"brotli\"][\"includedirs\"] = {}' in brotli_vars\n"
  },
  {
    "path": "test/integration/toolchains/premake/test_premaketoolchain.py",
    "content": "import textwrap\nfrom conan.test.assets.genconanfile import GenConanfile\nimport pytest\n\nfrom conan.test.utils.tools import TestClient\nfrom conan.tools.premake.toolchain import PremakeToolchain\n\n\ndef test_extra_flags_via_conf():\n    profile = textwrap.dedent(\n        \"\"\"\n        [settings]\n        os=Linux\n        arch=x86_64\n        compiler=gcc\n        compiler.version=9\n        compiler.cppstd=17\n        compiler.libcxx=libstdc++\n        build_type=Release\n\n        [conf]\n        tools.build:cxxflags=[\"-flag1\", \"-flag2\"]\n        tools.build:cflags=[\"-flag3\", \"-flag4\"]\n        tools.build:sharedlinkflags+=[\"-flag5\"]\n        tools.build:exelinkflags+=[\"-flag6\"]\n        tools.build:defines=[\"define1=0\"]\n    \"\"\"\n    )\n    tc = TestClient()\n    tc.save(\n        {\n            \"conanfile.txt\": \"[generators]\\nPremakeToolchain\",\n            \"profile\": profile,\n        }\n    )\n\n    tc.run(\"install . -pr:a=profile\")\n    content = tc.load(PremakeToolchain.filename)\n    assert 'cppdialect \"c++17\"' in content\n\n    assert (\n        \"\"\"\n        filter { files { \"**.c\" } }\n            buildoptions { \"-flag3\", \"-flag4\", \"-m64\" }\n        filter {}\n        \"\"\"\n        in content\n    )\n\n    assert (\n        \"\"\"\n        filter { files { \"**.cpp\", \"**.cxx\", \"**.cc\" } }\n            buildoptions { \"-flag1\", \"-flag2\", \"-m64\" }\n        filter {}\n        \"\"\"\n        in content\n    )\n\n    assert 'linkoptions { \"-flag5\", \"-flag6\", \"-m64\" }' in content\n    assert 'defines { \"define1=0\", \"_GLIBCXX_USE_CXX11_ABI=0\" }' in content\n\n\ndef test_premaketoolchain_rcflags():\n    \"\"\"Test that tools.build:rcflags is applied to buildoptions for **.rc files.\"\"\"\n    profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=Linux\n        arch=x86_64\n        compiler=gcc\n        compiler.version=9\n        compiler.libcxx=libstdc++\n        build_type=Release\n\n        [conf]\n        tools.build:rcflags=[\"-rcflag1\", \"-rcflag2\"]\n        \"\"\")\n    tc = TestClient()\n    tc.save({\n        \"conanfile.txt\": \"[generators]\\nPremakeToolchain\",\n        \"profile\": profile,\n    })\n    tc.run(\"install . -pr:a=profile\")\n    content = tc.load(PremakeToolchain.filename)\n    assert '**.rc' in content\n    assert \"-rcflag1\" in content\n    assert \"-rcflag2\" in content\n\n\ndef test_project_configuration():\n    tc = TestClient(path_with_spaces=False)\n    profile = textwrap.dedent(\n        \"\"\"\n        [settings]\n        arch=armv8\n        build_type=Release\n        compiler=apple-clang\n        compiler.cppstd=gnu17\n        compiler.cstd=gnu11\n        compiler.libcxx=libc++\n        compiler.version=17\n        os=Macos\n    \"\"\"\n    )\n    conanfile = textwrap.dedent(\n        \"\"\"\n        from conan import ConanFile\n        from conan.tools.layout import basic_layout\n        from conan.tools.premake import Premake, PremakeDeps, PremakeToolchain\n        import os\n\n        class Pkg(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n            name = \"pkg\"\n            version = \"1.0\"\n            options = {\"fPIC\": [True, False]}\n            default_options = {\"fPIC\": True}\n\n            def layout(self):\n                basic_layout(self, src_folder=\"src\")\n\n            def generate(self):\n                tc = PremakeToolchain(self)\n                tc.extra_defines = [\"VALUE=2\"]\n                tc.extra_cflags = [\"-Wextra\"]\n                tc.extra_cxxflags = [\"-Wall\", \"-Wextra\"]\n                tc.extra_ldflags = [\"-lm\"]\n                tc.project(\"main\").extra_defines = [\"TEST=False\"]\n                tc.project(\"test\").disable = True\n                tc.project(\"main\").extra_cxxflags = [\"-FS\"]\n                tc.generate()\n    \"\"\"\n    )\n    tc.save({\"conanfile.py\": conanfile, \"profile\": profile})\n    tc.run(\"install . -pr:a profile\")\n\n    toolchain = tc.load(\"build-release/conan/conantoolchain.premake5.lua\")\n\n    assert 'pic \"On\"' in toolchain\n    assert (\n        \"\"\"\n        filter { files { \"**.c\" } }\n            buildoptions { \"-Wextra\" }\n        filter {}\n        \"\"\"\n        in toolchain\n    )\n    assert (\n        \"\"\"\n        filter { files { \"**.cpp\", \"**.cxx\", \"**.cc\" } }\n            buildoptions { \"-stdlib=libc++\", \"-Wall\", \"-Wextra\" }\n        filter {}\n        \"\"\"\n        in toolchain\n    )\n    assert 'linkoptions { \"-lm\" }' in toolchain\n    assert 'defines { \"VALUE=2\" }' in toolchain\n    assert 'linkoptions { \"-Wl,-rpath,@loader_path\" }' in toolchain\n    assert (\n        textwrap.dedent(\n            \"\"\"\n    project \"main\"\n        -- CXX flags retrieved from CXXFLAGS environment, conan.conf(tools.build:cxxflags), extra_cxxflags and compiler settings\n        filter { files { \"**.cpp\", \"**.cxx\", \"**.cc\" } }\n            buildoptions { \"-stdlib=libc++\", \"-FS\" }\n        filter {}\n        -- Defines retrieved from DEFINES environment, conan.conf(tools.build:defines) and extra_defines\n        defines { \"TEST=False\" }\n        \"\"\"\n        )\n        in toolchain\n    )\n    assert (\n        textwrap.dedent(\n            \"\"\"\n        project \"test\"\n            kind \"None\"\n        \"\"\"\n        )\n        in toolchain\n    )\n\n\n@pytest.mark.parametrize(\n    \"threads, flags\",\n    [(\"posix\", \"-pthread\"), (\"wasm_workers\", \"-sWASM_WORKERS=1\")],\n)\ndef test_thread_flags(threads, flags):\n    client = TestClient()\n    profile = textwrap.dedent(f\"\"\"\n        [settings]\n        arch=wasm64\n        build_type=Release\n        compiler=emcc\n        compiler.cppstd=17\n        compiler.threads={threads}\n        compiler.libcxx=libc++\n        compiler.version=4.0.10\n        os=Emscripten\n        \"\"\")\n    client.save(\n        {\n            \"conanfile.py\": GenConanfile(\"pkg\", \"1.0\")\n            .with_settings(\"os\", \"arch\", \"compiler\", \"build_type\")\n            .with_generator(\"PremakeToolchain\"),\n            \"profile\": profile,\n        }\n    )\n    client.run(\"install . -pr=./profile\")\n    toolchain = client.load(\"conantoolchain.premake5.lua\")\n    assert (\n        \"\"\"\n        filter { files { \"**.c\" } }\n            buildoptions { \"-sMEMORY64=1\", \"%s\" }\n        filter {}\n        \"\"\"\n        % flags\n        in toolchain\n    )\n    assert (\n        \"\"\"\n        filter { files { \"**.cpp\", \"**.cxx\", \"**.cc\" } }\n            buildoptions { \"-stdlib=libc++\", \"-sMEMORY64=1\", \"%s\" }\n        filter {}\n        \"\"\"\n        % flags\n        in toolchain\n    )\n    assert 'linkoptions { \"-sMEMORY64=1\", \"%s\" }' % flags in toolchain\n"
  },
  {
    "path": "test/integration/toolchains/qbs/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/toolchains/qbs/test_qbsdeps.py",
    "content": "import json\nimport os\nimport platform\n\nimport pytest\nimport textwrap\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import load\n\n\ndef test_empty_package():\n    # Checks default values generated by conan for cpp_info\n    client = TestClient()\n    client.save({'conanfile.py': GenConanfile(\"mylib\", \"0.1\")})\n    client.run('create .')\n    client.run('install --requires=mylib/0.1@ -g QbsDeps')\n\n    module_path = os.path.join(client.current_folder, 'conan-qbs-deps', 'mylib.json')\n    module_content = json.loads(load(module_path))\n\n    assert module_content.get('package_name') == 'mylib'\n    assert module_content.get('version') == '0.1'\n\n    package_dir = module_content['package_dir']\n    cpp_info = module_content['cpp_info']\n    package_dir = package_dir.replace(\"/\", \"\\\\\") if platform.system() == \"Windows\" else package_dir\n    assert cpp_info.get('includedirs') == [os.path.join(package_dir, 'include')]\n    assert cpp_info.get('libdirs') == [os.path.join(package_dir, 'lib')]\n    assert cpp_info.get('bindirs') == [os.path.join(package_dir, 'bin')]\n    assert cpp_info.get('libs') == []\n    assert cpp_info.get('frameworkdirs') == []\n    assert cpp_info.get('frameworks') == []\n    assert cpp_info.get('defines') == []\n    assert cpp_info.get('cflags') == []\n    assert cpp_info.get('cxxflags') == []\n\n    assert module_content.get('settings') == {}\n    assert module_content.get('options') == {}\n\n\ndef test_empty_dirs():\n    # Checks that we can override default values with empty directories\n    conanfile = textwrap.dedent('''\n        from conan import ConanFile\n\n        class Recipe(ConanFile):\n            name = 'mylib'\n            version = '0.1'\n\n            def package_info(self):\n                self.cpp_info.includedirs = []\n                self.cpp_info.libdirs = []\n                self.cpp_info.bindirs = []\n                self.cpp_info.libs = []\n                self.cpp_info.frameworkdirs = []\n        ''')\n    client = TestClient()\n    client.save({'conanfile.py': conanfile})\n    client.run('create .')\n    client.run('install --requires=mylib/0.1@ -g QbsDeps')\n\n    module_path = os.path.join(client.current_folder, 'conan-qbs-deps', 'mylib.json')\n    assert os.path.exists(module_path)\n    module_content = json.loads(load(module_path))\n\n    assert module_content.get('package_name') == 'mylib'\n    assert module_content.get('version') == '0.1'\n\n    assert 'cpp_info' in module_content\n    cpp_info = module_content['cpp_info']\n    assert cpp_info.get('includedirs') == []\n    assert cpp_info.get('libdirs') == []\n    assert cpp_info.get('bindirs') == []\n    assert cpp_info.get('libs') == []\n    assert cpp_info.get('frameworkdirs') == []\n    assert cpp_info.get('frameworks') == []\n    assert cpp_info.get('defines') == []\n    assert cpp_info.get('cflags') == []\n    assert cpp_info.get('cxxflags') == []\n\n    assert module_content.get('settings') == {}\n    assert module_content.get('options') == {}\n\n\ndef test_pkg_config_name():\n    # Checks we can override module name using the \"pkg_config_name\" property\n    conanfile = textwrap.dedent('''\n        from conan import ConanFile\n\n        class Recipe(ConanFile):\n            name = 'mylib'\n            version = '0.1'\n            def package_info(self):\n                self.cpp_info.set_property(\"pkg_config_name\", \"myfirstlib\")\n        ''')\n    client = TestClient()\n    client.save({'conanfile.py': conanfile})\n    client.run('create .')\n    client.run('install --requires=mylib/0.1@ -g QbsDeps')\n\n    module_path = os.path.join(client.current_folder, 'conan-qbs-deps', 'myfirstlib.json')\n    assert os.path.exists(module_path)\n\n\n@pytest.mark.parametrize('host_os, arch, build_type', [\n    ('Linux', 'x86_64', 'Debug'),\n    ('Linux', 'x86_64', 'Release'),\n    ('Linux', 'armv8', 'Debug'),\n    ('Windows', 'x86_64', 'Debug'),\n    ('Macos', 'armv8', 'Release'),\n])\ndef test_settings(host_os, arch, build_type):\n\n    conanfile = textwrap.dedent('''\n    from conan import ConanFile\n    class Recipe(ConanFile):\n        settings = \"os\", \"arch\", \"build_type\"\n        name = \"mylib\"\n        version = \"0.1\"\n    ''')\n\n    client = TestClient()\n    client.save({'conanfile.py': conanfile})\n    common_cmd = '-s:h os={os} -s:h arch={arch} -s:h build_type={build_type}'.format(\n        os=host_os, arch=arch, build_type=build_type\n    )\n    client.run('create . ' + common_cmd)\n    client.run('install --requires=mylib/0.1@ -g QbsDeps ' + common_cmd)\n\n    module_path = os.path.join(client.current_folder, 'conan-qbs-deps', 'mylib.json')\n    assert os.path.exists(module_path)\n    module_content = json.loads(load(module_path))\n\n    assert 'settings' in module_content\n    # Qbs only cares about os and arch (and maybe build type)\n    assert module_content['settings'].get('os') == host_os\n    assert module_content['settings'].get('arch') == arch\n    assert module_content['settings'].get('build_type') == build_type\n\n\n@pytest.mark.parametrize('shared', ['False', 'True'])\ndef test_options(shared):\n    conanfile = textwrap.dedent('''\n    from conan import ConanFile\n    class Recipe(ConanFile):\n        options = {\"shared\": [True, False]}\n        default_options = {\"shared\": False}\n        name = 'mylib'\n        version = '0.1'\n    ''')\n\n    client = TestClient()\n    client.save({'conanfile.py': conanfile})\n    common_cmd = '-o:h shared={shared}'.format(shared=shared)\n    client.run('create . ' + common_cmd)\n    client.run('install --requires=mylib/0.1@ -g QbsDeps ' + common_cmd)\n\n    module_path = os.path.join(client.current_folder, 'conan-qbs-deps', 'mylib.json')\n    assert os.path.exists(module_path)\n    module_content = json.loads(load(module_path))\n\n    assert 'options' in module_content\n    assert module_content['options'].get('shared') == shared\n\n\ndef test_components():\n    \"\"\"\n        Checks a package with multiple components.\n        Here we test component name and version override as well as the defaults.\n    \"\"\"\n    conanfile = textwrap.dedent('''\n    from conan import ConanFile\n\n    class Recipe(ConanFile):\n\n        name = 'mylib'\n        version = '0.1'\n        def package_info(self):\n            self.cpp_info.components[\"mycomponent1\"].set_property(\"pkg_config_name\",\n                                                                  \"mycomponent\")\n            self.cpp_info.components[\"mycomponent2\"].set_property(\"component_version\",\n                                                                  \"19.8.199\")\n    ''')\n\n    client = TestClient()\n    client.save({'conanfile.py': conanfile})\n    client.run('create .')\n    client.run('install --requires=mylib/0.1@ -g QbsDeps')\n\n    module1_path = os.path.join(client.current_folder, 'conan-qbs-deps', 'mycomponent.json')\n    assert os.path.exists(module1_path)\n    module1_content = json.loads(load(module1_path))\n\n    assert module1_content.get('package_name') == 'mylib'\n    assert module1_content.get('version') == '0.1'\n    assert module1_content.get('dependencies') == []\n\n    module2_path = os.path.join(client.current_folder, 'conan-qbs-deps', 'mycomponent2.json')\n    assert os.path.exists(module2_path)\n    module2_content = json.loads(load(module2_path))\n\n    assert module2_content.get('package_name') == 'mylib'\n    assert module2_content.get('version') == '19.8.199'\n    assert module2_content.get('dependencies') == []\n\n    main_module_path = os.path.join(client.current_folder, 'conan-qbs-deps', 'mylib.json')\n    assert os.path.exists(main_module_path)\n    main_module_content = json.loads(load(main_module_path))\n\n    assert main_module_content.get('package_name') == 'mylib'\n    assert main_module_content.get('version') == '0.1'\n    assert main_module_content.get('dependencies') == [\n        {\"name\": \"mycomponent\", \"version\": \"0.1\"},  # name overriden, version default\n        {\"name\": \"mycomponent2\", \"version\": \"19.8.199\"}  # name default, version overriden\n    ]\n\n\ndef test_cpp_info_requires():\n    \"\"\"\n    Testing a complex structure like:\n\n    * first/0.1\n        - Global pkg_config_name == \"myfirstlib\"\n        - Components: \"cmp1\"\n    * other/0.1\n    * second/0.2\n        - Requires: \"first/0.1\"\n        - Components: \"mycomponent\", \"myfirstcomp\"\n            + \"mycomponent\" requires \"first::cmp1\"\n            + \"myfirstcomp\" requires \"mycomponent\"\n    * third/0.4\n        - Requires: \"second/0.2\", \"other/0.1\"\n\n    Expected file structure after running QbsDeps as generator:\n        - other.json\n        - myfirstlib-cmp1.json\n        - myfirstlib.json\n        - second-mycomponent.json\n        - second-myfirstcomp.json\n        - second.json\n        - third.json\n    \"\"\"\n\n    client = TestClient()\n    # first\n    conanfile = textwrap.dedent('''\n        from conan import ConanFile\n\n        class Recipe(ConanFile):\n            name = \"first\"\n            version = \"0.1\"\n            def package_info(self):\n                self.cpp_info.set_property(\"pkg_config_name\", \"myfirstlib\")\n                self.cpp_info.components[\"cmp1\"].libs = [\"libcmp1\"]\n    ''')\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create .\")\n    # other\n    client.save({\"conanfile.py\": GenConanfile(\"other\", \"0.1\")}, clean_first=True)\n    client.run(\"create .\")\n\n    # second\n    conanfile = textwrap.dedent('''\n    from conan import ConanFile\n\n    class PkgConfigConan(ConanFile):\n        name = \"second\"\n        version = \"0.2\"\n        requires = \"first/0.1\"\n\n        def package_info(self):\n            self.cpp_info.components[\"mycomponent\"].requires.append(\"first::cmp1\")\n            self.cpp_info.components[\"myfirstcomp\"].requires.append(\"mycomponent\")\n    ''')\n    client.save({\"conanfile.py\": conanfile}, clean_first=True)\n    client.run(\"create .\")\n\n    # third\n    client.save({\"conanfile.py\": GenConanfile(\"third\", \"0.3\").with_require(\"second/0.2\")\n                                                             .with_require(\"other/0.1\")},\n                clean_first=True)\n    client.run(\"create .\")\n\n    client2 = TestClient(cache_folder=client.cache_folder)\n    conanfile = textwrap.dedent(\"\"\"\n        [requires]\n        third/0.3\n        other/0.1\n\n        [generators]\n        QbsDeps\n    \"\"\")\n    client2.save({\"conanfile.txt\": conanfile})\n    client2.run(\"install .\")\n\n    # first\n    module_path = os.path.join(client2.current_folder, 'conan-qbs-deps', 'cmp1.json')\n    assert os.path.exists(module_path)\n    module_content = json.loads(load(module_path))\n\n    assert module_content.get('package_name') == 'first'\n    assert module_content.get('version') == '0.1'\n    assert module_content.get('dependencies') == []\n\n    module_path = os.path.join(client2.current_folder, 'conan-qbs-deps', 'myfirstlib.json')\n    assert os.path.exists(module_path)\n    module_content = json.loads(load(module_path))\n\n    assert module_content.get('package_name') == 'first'\n    assert module_content.get('version') == '0.1'\n    assert module_content.get('dependencies') == [{'name': 'cmp1', 'version': '0.1'}]\n\n    # other\n    module_path = os.path.join(client2.current_folder, 'conan-qbs-deps', 'other.json')\n    assert os.path.exists(module_path)\n    module_content = json.loads(load(module_path))\n\n    assert module_content.get('package_name') == 'other'\n    assert module_content.get('version') == '0.1'\n    assert module_content.get('dependencies') == []\n\n    # second.mycomponent\n    module_path = os.path.join(client2.current_folder, 'conan-qbs-deps', 'mycomponent.json')\n    assert os.path.exists(module_path)\n    module_content = json.loads(load(module_path))\n\n    assert module_content.get('package_name') == 'second'\n    assert module_content.get('version') == '0.2'\n    assert module_content.get('dependencies') == [{'name': 'cmp1', 'version': '0.1'}]\n\n    # second.myfirstcomp\n    module_path = os.path.join(client2.current_folder, 'conan-qbs-deps', 'myfirstcomp.json')\n    assert os.path.exists(module_path)\n    module_content = json.loads(load(module_path))\n\n    assert module_content.get('package_name') == 'second'\n    assert module_content.get('version') == '0.2'\n    assert module_content.get('dependencies') == [{'name': 'mycomponent', 'version': '0.2'}]\n\n    # second\n    module_path = os.path.join(client2.current_folder, 'conan-qbs-deps', 'second.json')\n    assert os.path.exists(module_path)\n    module_content = json.loads(load(module_path))\n\n    assert module_content.get('package_name') == 'second'\n    assert module_content.get('version') == '0.2'\n    assert module_content.get('dependencies') == [\n        {'name': 'mycomponent', 'version': '0.2'},\n        {'name': 'myfirstcomp', 'version': '0.2'}\n    ]\n\n    # third\n    module_path = os.path.join(client2.current_folder, 'conan-qbs-deps', 'third.json')\n    assert os.path.exists(module_path)\n    module_content = json.loads(load(module_path))\n\n    assert module_content.get('package_name') == 'third'\n    assert module_content.get('version') == '0.3'\n    assert module_content.get('dependencies') == [\n        {'name': 'second', 'version': '0.2'},\n        {'name': 'other', 'version': '0.1'}\n    ]\n\n\n# see https://github.com/conan-io/conan/issues/10341\ndef test_components_conflict():\n    \"\"\" If component has the same name as the root package, skip root package\n    \"\"\"\n    conanfile = textwrap.dedent('''\n    from conan import ConanFile\n\n    class Recipe(ConanFile):\n\n        name = 'mylib'\n        version = '0.1'\n        def package_info(self):\n            self.cpp_info.set_property(\"pkg_config_name\", \"mycoollib\")\n            self.cpp_info.components[\"_mycoollib\"].defines = [\"MAGIC_DEFINE\"]\n            self.cpp_info.components[\"_mycoollib\"].set_property(\"pkg_config_name\",\n                                                               \"mycoollib\")\n    ''')\n\n    client = TestClient()\n    client.save({'conanfile.py': conanfile})\n    client.run('create .')\n    client.run('install --requires=mylib/0.1@ -g QbsDeps')\n\n    module_path = os.path.join(client.current_folder, 'conan-qbs-deps', 'mycoollib.json')\n    assert os.path.exists(module_path)\n    module_content = json.loads(load(module_path))\n\n    assert module_content.get('package_name') == 'mylib'\n    assert module_content.get('version') == '0.1'\n    assert 'cpp_info' in module_content\n    cpp_info = module_content['cpp_info']\n    assert cpp_info.get('defines') == [\"MAGIC_DEFINE\"]\n"
  },
  {
    "path": "test/integration/toolchains/qbs/test_qbsprofile.py",
    "content": "import os\nimport platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.skipif(platform.system() == \"Windows\", reason=\"QbsProfile requires host compiler (gcc) to be found\")\ndef test_qbsprofile_rcflags():\n    \"\"\"Test that tools.build:rcflags is applied to cpp.rcFlags in qbs_settings.txt.\"\"\"\n    profile = textwrap.dedent(\"\"\"\n        [settings]\n        os=Linux\n        arch=x86_64\n        compiler=gcc\n        compiler.version=9\n        compiler.libcxx=libstdc++\n        build_type=Release\n\n        [conf]\n        tools.build:rcflags=[\"-rcflag1\", \"-rcflag2\"]\n        \"\"\")\n    client = TestClient()\n    conanfile = GenConanfile().with_settings(\"os\", \"arch\", \"compiler\", \"build_type\").with_generator(\"QbsProfile\")\n    client.save({\"conanfile.py\": conanfile, \"profile\": profile})\n    client.run(\"install . --profile:build=profile --profile:host=profile\")\n    settings_path = os.path.join(client.current_folder, \"qbs_settings.txt\")\n    assert os.path.exists(settings_path)\n    content = client.load(\"qbs_settings.txt\")\n    assert \"cpp.rcFlags\" in content\n    assert \"-rcflag1\" in content\n    assert \"-rcflag2\" in content\n"
  },
  {
    "path": "test/integration/toolchains/scons/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/toolchains/scons/test_scondeps.py",
    "content": "import re\nimport textwrap\n\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_sconsdeps():\n    dep = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class ExampleConanIntegration(ConanFile):\n            name = \"{dep}\"\n            version = \"0.1\"\n            def package_info(self):\n                self.cpp_info.includedirs = [\"{dep}_includedir\"]\n                self.cpp_info.libdirs = [\"{dep}_libdir\"]\n                self.cpp_info.bindirs = [\"{dep}_bindir\"]\n                self.cpp_info.libs = [\"{dep}_lib\"]\n                self.cpp_info.frameworks = [\"{dep}_frameworks\"]\n                self.cpp_info.frameworkdirs = [\"{dep}_frameworkdirs\"]\n                self.cpp_info.defines = [\"{dep}_defines\"]\n                self.cpp_info.cxxflags = [\"{dep}_cxxflags\"]\n                self.cpp_info.cflags = [\"{dep}_cflags\"]\n                self.cpp_info.sharedlinkflags = [\"{dep}_sharedlinkflags\"]\n                self.cpp_info.exelinkflags = [\"{dep}_exelinkflags\"]\n        \"\"\")\n\n    consumer = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.layout import basic_layout\n\n        class ExampleConanIntegration(ConanFile):\n            generators = 'SConsDeps'\n            requires = 'dep1/0.1', 'dep2/0.1'\n        \"\"\")\n\n    c = TestClient()\n    c.save({\"dep1/conanfile.py\": dep.format(dep=\"dep1\"),\n            \"dep2/conanfile.py\": dep.format(dep=\"dep2\"),\n            \"consumer/conanfile.py\": consumer})\n    c.run(\"create dep1\")\n    c.run(\"create dep2\")\n    c.run(\"install consumer\")\n    sconsdeps = c.load(\"consumer/SConscript_conandeps\")\n\n    # remove all cache paths from the output but the last component\n    def clean_paths(text):\n        text = text.replace(\"\\\\\", \"/\")\n        pattern = r\"'[A-Za-z]?[:]?[/]?[^']+/([^'/]+)'\"\n        return re.sub(pattern, r\"'\\1'\", text)\n\n    expected_content = [\"\"\"\n        \"conandeps\" : {\n            \"CPPPATH\"     : ['dep2_includedir', 'dep1_includedir'],\n            \"LIBPATH\"     : ['dep2_libdir', 'dep1_libdir'],\n            \"BINPATH\"     : ['dep2_bindir', 'dep1_bindir'],\n            \"LIBS\"        : ['dep2_lib', 'dep1_lib'],\n            \"FRAMEWORKS\"  : ['dep2_frameworks', 'dep1_frameworks'],\n            \"FRAMEWORKPATH\" : ['dep2_frameworkdirs', 'dep1_frameworkdirs'],\n            \"CPPDEFINES\"  : ['dep2_defines', 'dep1_defines'],\n            \"CXXFLAGS\"    : ['dep2_cxxflags', 'dep1_cxxflags'],\n            \"CCFLAGS\"     : ['dep2_cflags', 'dep1_cflags'],\n            \"SHLINKFLAGS\" : ['dep2_sharedlinkflags', 'dep1_sharedlinkflags'],\n            \"LINKFLAGS\"   : ['dep2_exelinkflags', 'dep1_exelinkflags'],\n        },\n        \"\"\", \"\"\"\n        \"dep1\" : {\n            \"CPPPATH\"     : ['dep1_includedir'],\n            \"LIBPATH\"     : ['dep1_libdir'],\n            \"BINPATH\"     : ['dep1_bindir'],\n            \"LIBS\"        : ['dep1_lib'],\n            \"FRAMEWORKS\"  : ['dep1_frameworks'],\n            \"FRAMEWORKPATH\" : ['dep1_frameworkdirs'],\n            \"CPPDEFINES\"  : ['dep1_defines'],\n            \"CXXFLAGS\"    : ['dep1_cxxflags'],\n            \"CCFLAGS\"     : ['dep1_cflags'],\n            \"SHLINKFLAGS\" : ['dep1_sharedlinkflags'],\n            \"LINKFLAGS\"   : ['dep1_exelinkflags'],\n        },\n        \"dep1_version\" : \"0.1\",\n        \"\"\", \"\"\"\n        \"dep2\" : {\n            \"CPPPATH\"     : ['dep2_includedir'],\n            \"LIBPATH\"     : ['dep2_libdir'],\n            \"BINPATH\"     : ['dep2_bindir'],\n            \"LIBS\"        : ['dep2_lib'],\n            \"FRAMEWORKS\"  : ['dep2_frameworks'],\n            \"FRAMEWORKPATH\" : ['dep2_frameworkdirs'],\n            \"CPPDEFINES\"  : ['dep2_defines'],\n            \"CXXFLAGS\"    : ['dep2_cxxflags'],\n            \"CCFLAGS\"     : ['dep2_cflags'],\n            \"SHLINKFLAGS\" : ['dep2_sharedlinkflags'],\n            \"LINKFLAGS\"   : ['dep2_exelinkflags'],\n        },\n        \"dep2_version\" : \"0.1\",\n        \"\"\"]\n\n    clean_sconsdeps = clean_paths(sconsdeps)\n    for block in expected_content:\n        assert block in clean_sconsdeps\n"
  },
  {
    "path": "test/integration/toolchains/test_raise_on_universal_binaries.py",
    "content": "import platform\nimport textwrap\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.parametrize(\"toolchain\", [\"MesonToolchain\", \"BazelToolchain\"])\ndef test_create_universal_binary(toolchain):\n    client = TestClient()\n    conanfile = (GenConanfile().with_settings(\"os\", \"arch\", \"compiler\", \"build_type\")\n                 .with_generator(toolchain))\n    client.save({\"conanfile.py\": conanfile})\n\n    client.run('create . --name=foo --version=1.0 -s=\"arch=armv8|armv8.3|x86_64\"',\n               assert_error=True)\n    assert (f\"Error in generator '{toolchain}': \"\n            f\"Universal binaries not supported by toolchain.\") in client.out\n\n\n@pytest.mark.parametrize(\"toolchain\", [\"AutotoolsToolchain\", \"GnuToolchain\"])\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only OSX\")\ndef test_toolchain_universal_binary_support(toolchain):\n    \"\"\"Test that toolchain now supports universal binaries on macOS\"\"\"\n    client = TestClient()\n    conanfile = (GenConanfile().with_settings(\"os\", \"arch\", \"compiler\", \"build_type\")\n                 .with_generator(toolchain))\n    client.save({\"conanfile.py\": conanfile})\n\n    client.run('install . --name=foo --version=1.0 -s=\"arch=armv8|x86_64\"')\n\n    script_name = f\"conan{toolchain.lower()}.sh\"\n    toolchain_content = client.load(script_name)\n    assert \"-arch arm64\" in toolchain_content\n    assert \"-arch x86_64\" in toolchain_content\n    # Verify isysroot flag is NOT present when sdk_path is not configured\n    assert \"-isysroot\" not in toolchain_content\n\n\n@pytest.mark.parametrize(\"toolchain\", [\"AutotoolsToolchain\", \"GnuToolchain\"])\ndef test_toolchain_universal_binary_non_macos(toolchain):\n    \"\"\"Test that toolchain still raises error for universal binaries on non-macOS\"\"\"\n    client = TestClient()\n    conanfile = (GenConanfile().with_settings(\"os\", \"arch\", \"compiler\", \"build_type\")\n                 .with_generator(toolchain))\n    client.save({\"conanfile.py\": conanfile})\n\n    # This should still raise an error on non-macOS platforms\n    client.run('create . --name=foo --version=1.0 -s=\"os=Linux\" -s=\"arch=armv8|x86_64\"',\n               assert_error=True)\n    assert \"Universal arch 'armv8|x86_64' is only supported in Apple OSes\" in client.out\n\n\n@pytest.mark.parametrize(\"toolchain\", [\"AutotoolsToolchain\", \"GnuToolchain\"])\n@pytest.mark.skipif(platform.system() != \"Darwin\", reason=\"Only OSX\")\ndef test_toolchain_universal_binary_with_sdk_path(toolchain):\n    \"\"\"Test that toolchain sets isysroot when sdk_path is configured for universal binaries\"\"\"\n    client = TestClient()\n    conanfile = (GenConanfile().with_settings(\"os\", \"arch\", \"compiler\", \"build_type\")\n                 .with_generator(toolchain))\n    client.save({\"conanfile.py\": conanfile})\n\n    client.run('install . --name=foo --version=1.0 -s=\"arch=armv8|x86_64\" -c=\"tools.apple:sdk_path=mysdkpath\"')\n\n    script_name = f\"conan{toolchain.lower()}.sh\"\n    toolchain_content = client.load(script_name)\n\n    assert \"-arch arm64\" in toolchain_content\n    assert \"-arch x86_64\" in toolchain_content\n\n    assert \"-isysroot\" in toolchain_content\n    assert \"mysdkpath\" in toolchain_content\n\n\ndef test_create_universal_binary_test_package_folder():\n    # https://github.com/conan-io/conan/issues/18820\n    # While multi-arch is Darwin specific, this was a cmake_layout issue, so it can be\n    # tested in any platform\n    c = TestClient()\n    test_conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan.tools.cmake import cmake_layout\n\n        class mylibraryTestConan(ConanFile):\n            settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n\n            def requirements(self):\n                self.requires(self.tested_reference_str)\n\n            def layout(self):\n                cmake_layout(self)\n\n            def test(self):\n                pass\n            \"\"\")\n    c.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_settings(\"arch\"),\n            \"test_package/conanfile.py\": test_conanfile})\n\n    c.run('create . -s=\"arch=armv8|x86_64\"')\n    c.run(\"list *:*\")\n    assert \"arch: armv8|x86_64\" in c.out\n"
  },
  {
    "path": "test/integration/toolchains/test_toolchain_namespaces.py",
    "content": "import os\nimport textwrap\n\nfrom conan.tools.build import load_toolchain_args, CONAN_TOOLCHAIN_ARGS_FILE\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_autotools_namespace():\n    client = TestClient()\n    namespace = \"somename\"\n    conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.gnu import AutotoolsToolchain, Autotools\n\n            class Conan(ConanFile):\n                settings = \"os\", \"arch\", \"compiler\", \"build_type\"\n                def generate(self):\n                    autotools = AutotoolsToolchain(self, namespace='{0}')\n                    autotools.configure_args = ['a', 'b']\n                    autotools.make_args = ['c', 'd']\n                    autotools.generate()\n                def build(self):\n                    autotools = Autotools(self, namespace='{0}')\n                    self.output.info(autotools._configure_args)\n                    self.output.info(autotools._make_args)\n            \"\"\".format(namespace))\n\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"install .\")\n    assert os.path.isfile(os.path.join(client.current_folder,\n                                       \"{}_{}\".format(namespace, CONAN_TOOLCHAIN_ARGS_FILE)))\n    content = load_toolchain_args(generators_folder=client.current_folder, namespace=namespace)\n    at_configure_args = content.get(\"configure_args\")\n    at_make_args = content.get(\"make_args\")\n    client.run(\"build .\")\n    assert at_configure_args in client.out\n    assert at_make_args in client.out\n"
  },
  {
    "path": "test/integration/tools/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/tools/conan_version_test.py",
    "content": "import textwrap\n\nfrom conan.test.utils.tools import TestClient\nfrom conan import __version__\n\n\ndef test_conan_version():\n\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        from conan import conan_version\n        from conan.tools.scm import Version\n        from conan import __version__\n\n        class pkg(ConanFile):\n\n            def generate(self):\n                assert __version__ == str(conan_version)\n                assert isinstance(conan_version, Version)\n                print(f\"current version: {conan_version}\")\n        \"\"\")\n\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"install .\")\n    assert f\"current version: {__version__}\" in client.out\n"
  },
  {
    "path": "test/integration/tools/cppstd_minimum_version_test.py",
    "content": "import pytest\nfrom textwrap import dedent\n\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestCppStdMinimumVersion:\n\n    CONANFILE = dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.build import check_min_cppstd, valid_min_cppstd\n\n        class Fake(ConanFile):\n            name = \"fake\"\n            version = \"0.1\"\n            settings = \"compiler\"\n\n            def validate(self):\n                check_min_cppstd(self, \"17\", False)\n                self.output.info(\"valid standard\")\n                assert valid_min_cppstd(self, \"17\", False)\n        \"\"\")\n\n    PROFILE = dedent(\"\"\"\n        [settings]\n        compiler=gcc\n        compiler.version=9\n        compiler.libcxx=libstdc++\n        {}\n        \"\"\")\n\n    @pytest.fixture(autouse=True)\n    def setup(self):\n        self.client = TestClient()\n        self.client.save({\"conanfile.py\": TestCppStdMinimumVersion.CONANFILE})\n\n    @pytest.mark.parametrize(\"cppstd\", [\"17\", \"gnu17\"])\n    def test_cppstd_from_settings(self, cppstd):\n        profile = TestCppStdMinimumVersion.PROFILE.replace(\"{}\", \"compiler.cppstd=%s\" % cppstd)\n        self.client.save({\"myprofile\":  profile})\n        self.client.run(\"create . --user=user --channel=channel -pr myprofile\")\n        assert \"valid standard\" in self.client.out\n\n    @pytest.mark.parametrize(\"cppstd\", [\"11\", \"gnu11\"])\n    def test_invalid_cppstd_from_settings(self, cppstd):\n        profile = TestCppStdMinimumVersion.PROFILE.replace(\"{}\", \"compiler.cppstd=%s\" % cppstd)\n        self.client.save({\"myprofile\": profile})\n        self.client.run(\"create . --user=user --channel=channel -pr myprofile\", assert_error=True)\n        assert \"Invalid: Current cppstd (%s) is lower than the required C++ standard (17).\" \\\n                      % cppstd in self.client.out\n\n\ndef test_header_only_check_min_cppstd():\n    \"\"\"\n    Check that for a header only package you can check self.info in the validate\n    Related to: https://github.com/conan-io/conan/issues/11786\n    \"\"\"\n    conanfile = dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.build import check_min_cppstd\n\n        class Fake(ConanFile):\n            name = \"fake\"\n            version = \"0.1\"\n            settings = \"compiler\"\n            def package_id(self):\n                self.info.clear()\n            def validate(self):\n                check_min_cppstd(self, \"11\")\n        \"\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . -s compiler.cppstd=14\")\n    client.run(\"install --require=fake/0.1@ -s compiler.cppstd=14\")\n    assert \"fake/0.1: Already installed!\" in client.out\n\n\ndef test_validate_build_check_min_cppstd():\n    \"\"\"\n    Check the case that a package needs certain cppstd to build but can be consumed with a lower\n    cppstd or even not cppstd defined at all\n    \"\"\"\n    conanfile = dedent(\"\"\"\n        import os\n        from conan import ConanFile\n        from conan.tools.build import check_min_cppstd\n\n        class Fake(ConanFile):\n            name = \"fake\"\n            version = \"0.1\"\n            settings = \"compiler\"\n            def validate_build(self):\n                check_min_cppstd(self, \"17\")\n            def validate(self):\n                print(\"validated\")\n            def build(self):\n                print(\"built\")\n            def package_id(self):\n                del self.info.settings.compiler.cppstd\n        \"\"\")\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"create . -s compiler.cppstd=14\", assert_error=True)\n    assert \"fake/0.1: Cannot build for this configuration: \" \\\n           \"Current cppstd (14) is lower than the required C++ standard (17).\" in client.out\n    client.run(\"create . -s compiler.cppstd=17\")\n    client.run(\"install --require=fake/0.1@\")\n    assert \"fake/0.1: Already installed!\" in client.out\n    assert \"validated\" in client.out\n"
  },
  {
    "path": "test/integration/tools/cpu_count_test.py",
    "content": "import textwrap\n\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestNJobs:\n\n    def test_cpu_count_override(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.build import build_jobs\n\n            class Conan(ConanFile):\n                name = \"hello0\"\n                version = \"0.1\"\n\n                def build(self):\n                    self.output.warning(\"CPU COUNT=> %s\" % build_jobs(self))\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . -c tools.build:jobs=5\")\n        assert \"CPU COUNT=> 5\" in client.out\n"
  },
  {
    "path": "test/integration/tools/file_tools_test.py",
    "content": "import os\nimport textwrap\n\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_file_tools():\n\n    conanfile = textwrap.dedent(\"\"\"\n\n    from conan import ConanFile\n    from conan.tools.files import rmdir, mkdir\n\n    class pkg(ConanFile):\n\n        def layout(self):\n            self.folders.generators = \"gen\"\n\n        def generate(self):\n            mkdir(self, \"folder1\")\n            mkdir(self, \"folder2\")\n            rmdir(self, \"folder2\")\n\n    \"\"\")\n\n    client = TestClient()\n    client.save({\"conanfile.py\": conanfile})\n    client.run(\"install . \")\n    assert os.path.exists(os.path.join(client.current_folder, \"gen\", \"folder1\"))\n    assert not os.path.exists(os.path.join(client.current_folder, \"gen\", \"folder2\"))\n"
  },
  {
    "path": "test/integration/tools/fix_symlinks_test.py",
    "content": "import os\nimport platform\nimport textwrap\n\nimport pytest\n\nfrom conan.api.model import RecipeReference\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.skipif(platform.system() == \"Windows\", reason=\"symlink need admin privileges\")\nclass TestFixSymlinks:\n    name_ref = RecipeReference.loads(\"name/version\")\n\n    conanfile = textwrap.dedent(\"\"\"\n        import os\n        import shutil\n        from conan import ConanFile\n        from conan.tools.files import save\n        from conan.tools.files.symlinks import (absolute_to_relative_symlinks,\n                                                remove_external_symlinks,\n                                                remove_broken_symlinks)\n\n        class Recipe(ConanFile):\n\n            def build(self):\n                save(self, os.path.join(self.build_folder, \"build.txt\"), \"contents\")\n\n            def package(self):\n                os.symlink('/dev/null', os.path.join(self.package_folder, \"black_hole\"))\n\n                # Files: Symlink to file outside the package\n                os.symlink(os.path.join(self.build_folder, \"build.txt\"),\n                           os.path.join(self.package_folder, \"outside_symlink.txt\"))\n\n                # Files: A regular file with symlinks to it\n                save(self, os.path.join(self.package_folder, \"regular.txt\"), \"contents\")\n                os.symlink(os.path.join(self.package_folder, \"regular.txt\"),\n                           os.path.join(self.package_folder, \"absolute_symlink.txt\"))\n                os.symlink(\"regular.txt\", os.path.join(self.package_folder, \"relative_symlink.txt\"))\n\n                # Files: A broken symlink\n                save(self, os.path.join(self.package_folder, \"file.txt\"), \"contents\")\n                os.symlink(os.path.join(self.package_folder, \"file.txt\"),\n                           os.path.join(self.package_folder, \"broken.txt\"))\n                os.unlink(os.path.join(self.package_folder, \"file.txt\"))\n\n                # Folder: Symlink outside package\n                os.symlink(self.build_folder, os.path.join(self.package_folder, \"outside_folder\"))\n\n                # Folder: a regular folder and symlinks to it\n                save(self, os.path.join(self.package_folder, \"folder\", \"file.txt\"), \"contents\")\n                os.symlink(os.path.join(self.package_folder, \"folder\"),\n                           os.path.join(self.package_folder, \"absolute\"))\n                os.symlink(\"folder\", os.path.join(self.package_folder, \"relative\"))\n\n                # Folder: broken symlink\n                save(self, os.path.join(self.package_folder, \"tmp\", \"file.txt\"), \"contents\")\n                os.symlink(os.path.join(self.package_folder, \"tmp\"),\n                           os.path.join(self.package_folder, \"broken_folder\"))\n                shutil.rmtree(os.path.join(self.package_folder, \"tmp\"))\n\n                #\n                os.symlink(os.path.join(self.package_folder, \"folder\", \"file.txt\"),\n                           os.path.join(self.package_folder, \"abs_to_file_in_folder.txt\"))\n\n                # --> Run the tools\n                absolute_to_relative_symlinks(self, self.package_folder)\n                remove_external_symlinks(self, self.package_folder)\n                remove_broken_symlinks(self, self.package_folder)\n    \"\"\")\n\n    def test_error_reported(self):\n        t = TestClient()\n        t.save({'conanfile.py': self.conanfile})\n        t.run(\"create . --name=name --version=version\")\n        package_folder = t.created_layout().package()\n\n        assert sorted(os.listdir(package_folder)) == ['abs_to_file_in_folder.txt',\n                                                      'absolute',\n                                                      'absolute_symlink.txt',\n                                                      'conaninfo.txt',\n                                                      'conanmanifest.txt',\n                                                      'folder',\n                                                      'regular.txt',\n                                                      'relative',\n                                                      'relative_symlink.txt']\n        # All the links in the package_folder are relative and contained into it\n        for (dirpath, dirnames, filenames) in os.walk(package_folder):\n            for filename in filenames:\n                filename = os.path.join(dirpath, filename)\n                if os.path.islink(filename):\n                    rel_path = str(os.readlink(filename))\n                    assert not os.path.exists(os.path.abspath(rel_path))\n                    assert not rel_path.startswith('..')\n            for dirname in dirnames:\n                dirname = os.path.join(dirpath, dirname)\n                if os.path.islink(dirname):\n                    rel_path = str(os.readlink(dirname))\n                    assert not os.path.exists(os.path.abspath(rel_path))\n                    assert not rel_path.startswith('..')\n"
  },
  {
    "path": "test/integration/tools/ros/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/tools/ros/test_rosenv.py",
    "content": "import os\nimport textwrap\nimport platform\n\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\ndef test_rosenv():\n    \"\"\"\n    Test that the ROSEnv generator generates the environment files and that\n    the environment variables are correctly set.\n    \"\"\"\n    client = TestClient()\n    conanfile3 = textwrap.dedent('''\n        [requires]\n        [generators]\n        CMakeDeps\n        CMakeToolchain\n        ROSEnv\n        ''')\n    client.save({\n        \"conanfile3.txt\": conanfile3\n    })\n\n    if platform.system() == \"Windows\":\n        conanrosenv_file = \"conanrosenv.bat\"\n        conanrosenv_build = \"conanrosenv-build.bat\"\n        build_type = \"Release\"\n        cmd_source = \"call\"\n        cmd_env = \"set\"\n    else:\n        conanrosenv_file = \"conanrosenv.sh\"\n        conanrosenv_build = \"conanrosenv-build.sh\"\n        build_type = '\"Release\"'\n        cmd_source = \".\"\n        cmd_env = \"env\"\n\n    client.run(\"install conanfile3.txt --output-folder install/conan\")\n    assert f\"Generated ROSEnv Conan file: {conanrosenv_file}\" in client.out\n    install_folder = os.path.join(client.current_folder, \"install\", \"conan\")\n    conanrosenv_path = os.path.join(install_folder, conanrosenv_file)\n    assert os.path.exists(conanrosenv_path)\n    conanrosenvbuild_path = os.path.join(install_folder, conanrosenv_build)\n    assert os.path.exists(conanrosenvbuild_path)\n    toolchain_path = os.path.join(client.current_folder, \"install\", \"conan\",\n                                  \"conan_toolchain.cmake\")\n    content = client.load(conanrosenvbuild_path)\n    if platform.system() != \"Windows\":\n        assert f'CMAKE_TOOLCHAIN_FILE=\"{toolchain_path}\"' in content\n    else:\n        assert f'CMAKE_TOOLCHAIN_FILE={toolchain_path}' in content\n    assert f'CMAKE_BUILD_TYPE={build_type}' in content\n\n    client.run_command(f'{cmd_source} \"{conanrosenv_path}\" && {cmd_env}')\n    assert f\"CMAKE_TOOLCHAIN_FILE={toolchain_path}\" in client.out\n    assert \"CMAKE_BUILD_TYPE=Release\" in client.out\n\n\n@pytest.mark.skipif(platform.system() == \"Windows\", reason=\"Uses UNIX commands\")\ndef test_rosenv_shared_libraries():\n    \"\"\"\n    Test that the library paths env vars are set up correctly so that the executables built with\n    colcon can found the shared libraries of conan packages\n    \"\"\"\n    client = TestClient()\n    c1 = GenConanfile(\"lib1\", \"1.0\").with_shared_option(False).with_package_file(\"lib/lib1\", \"lib-content\")\n    c2 = GenConanfile(\"lib2\", \"1.0\").with_shared_option(False).with_requirement(\"lib1/1.0\").with_package_file(\"lib/lib2\", \"lib-content\")\n    c3 = textwrap.dedent('''\n           [requires]\n           lib2/1.0\n           [generators]\n           CMakeDeps\n           CMakeToolchain\n           ROSEnv\n           ''')\n    client.save({\n        \"conanfile1.py\": c1,\n        \"conanfile2.py\": c2,\n        \"conanfile3.txt\": c3\n    })\n\n    client.run(\"create conanfile1.py -o *:shared=True\")\n    client.run(\"create conanfile2.py -o *:shared=True\")\n    client.run(\"install conanfile3.txt -o *:shared=True --output-folder install/conan\")\n    conanrosenv_path = os.path.join(client.current_folder, \"install\", \"conan\", \"conanrosenv.sh\")\n    client.run_command(f\". \\\"{conanrosenv_path}\\\" && env\")\n    environment_content = client.out\n    client.run(\n        \"cache path lib1/1.0#58723f478a96866dcbd9456d8eefd7c4:1744785cb24e3bdca70e27041dc5abd20476f947\")\n    lib1_lib_path = os.path.join(client.out.strip(), \"lib\")\n    assert lib1_lib_path in environment_content\n    client.run(\n        \"cache path lib2/1.0#4b7a6063ba107d770458ce10385beb52:5c3c2e56259489f7ffbc8e494921eda4b747ef21\")\n    lib2_lib_path = os.path.join(client.out.strip(), \"lib\")\n    assert lib2_lib_path in environment_content\n"
  },
  {
    "path": "test/integration/tools/system/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/tools/system/package_manager_test.py",
    "content": "import platform\nfrom unittest.mock import MagicMock, patch\n\nfrom unittest import mock\nimport pytest\nfrom unittest.mock import PropertyMock\n\nfrom conan.tools.system.package_manager import Apt, Apk, Dnf, Yum, Brew, Pkg, PkgUtil, Chocolatey, \\\n    Zypper, PacMan, _SystemPackageManagerTool\nfrom conan.errors import ConanException\nfrom conan.internal.model.settings import Settings\nfrom conan.test.utils.mocks import ConanFileMock, MockSettings\n\n\n@pytest.mark.parametrize(\"system, tool\", [\n    (\"Linux\", \"apt-get\"),\n    (\"Windows\", \"choco\"),\n    (\"Darwin\", \"brew\"),\n    (\"Solaris\", \"pkgutil\"),\n])\n@pytest.mark.skipif(platform.system() != \"Linux\", reason=\"Only linux\")\ndef test_package_manager_platform(system, tool):\n    with mock.patch(\"platform.system\", return_value=system):\n        with mock.patch(\"distro.id\", return_value=''):\n            with mock.patch('conan.ConanFile.context', new_callable=PropertyMock) as context_mock:\n                context_mock.return_value = \"host\"\n                conanfile = ConanFileMock()\n                conanfile.settings = Settings()\n                manager = _SystemPackageManagerTool(conanfile)\n                assert tool == manager.get_default_tool()\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Only Windows\")\ndef test_msys2():\n    with mock.patch(\"platform.system\", return_value=\"Windows\"):\n        with mock.patch('conan.ConanFile.context', new_callable=PropertyMock) as context_mock:\n            context_mock.return_value = \"host\"\n            conanfile = ConanFileMock()\n            conanfile.settings = Settings({\"os\": {\"Windows\": {\"subsystem\": [\"msys2\"]}}})\n            conanfile.conf.define(\"tools.microsoft.bash:subsystem\", \"msys2\")\n            manager = _SystemPackageManagerTool(conanfile)\n            assert manager.get_default_tool() == \"choco\"\n\n            conanfile.settings.os = \"Windows\"\n            conanfile.settings.os.subsystem = \"msys2\"\n            manager = _SystemPackageManagerTool(conanfile)\n            assert manager.get_default_tool() == \"pacman\"\n\n\n@pytest.mark.parametrize(\"distro, tool\", [\n    (\"ubuntu\", \"apt-get\"),\n    (\"debian\", \"apt-get\"),\n    (\"linuxmint\", \"apt-get\"),\n    (\"pidora\", \"yum\"),\n    (\"rocky\", \"dnf\"),\n    (\"almalinux\", \"dnf\"),\n    (\"oracle\", \"dnf\"),\n    (\"fedora\", \"dnf\"),\n    (\"nobara\", \"dnf\"),\n    (\"arch\", \"pacman\"),\n    (\"opensuse\", \"zypper\"),\n    (\"sles\", \"zypper\"),\n    (\"opensuse\", \"zypper\"),\n    (\"opensuse-tumbleweed\", \"zypper\"),\n    (\"opensuse-leap\", \"zypper\"),\n    (\"opensuse-next_version\", \"zypper\"),\n    (\"freebsd\", \"pkg\"),\n    (\"alpine\", \"apk\"),\n    ('altlinux', \"apt-get\"),\n    (\"astra\", 'apt-get'),\n    ('elbrus', 'apt-get'),\n    ('pop', \"apt-get\"),\n])\n@pytest.mark.skipif(platform.system() != \"Linux\", reason=\"Only linux\")\ndef test_package_manager_distro(distro, tool):\n    with mock.patch(\"platform.system\", return_value=\"Linux\"):\n        with mock.patch(\"distro.id\", return_value=distro):\n            with mock.patch('conan.ConanFile.context', new_callable=PropertyMock) as context_mock:\n                context_mock.return_value = \"host\"\n                conanfile = ConanFileMock()\n                conanfile.settings = Settings()\n                manager = _SystemPackageManagerTool(conanfile)\n                assert tool == manager.get_default_tool()\n\n\n@pytest.mark.parametrize(\"sudo, sudo_askpass, expected_str\", [\n    (True, True, \"sudo -A \"),\n    (True, False, \"sudo \"),\n    (False, True, \"\"),\n    (False, False, \"\"),\n])\ndef test_sudo_str(sudo, sudo_askpass, expected_str):\n    conanfile = ConanFileMock()\n    conanfile.settings = Settings()\n    conanfile.conf.define(\"tools.system.package_manager:sudo\", sudo)\n    conanfile.conf.define(\"tools.system.package_manager:sudo_askpass\", sudo_askpass)\n    with mock.patch('conan.ConanFile.context', new_callable=PropertyMock) as context_mock:\n        context_mock.return_value = \"host\"\n        apt = Apt(conanfile)\n    assert apt.sudo_str == expected_str\n\n\n@pytest.mark.parametrize(\"recommends, recommends_str\", [\n    (False, \"--no-install-recommends \"),\n    (True, \"\"),\n])\ndef test_apt_install_recommends(recommends, recommends_str):\n    conanfile = ConanFileMock()\n    conanfile.settings = Settings()\n    conanfile.conf.define(\"tools.system.package_manager:tool\", \"apt-get\")\n    conanfile.conf.define(\"tools.system.package_manager:mode\", \"install\")\n    with mock.patch('conan.ConanFile.context', new_callable=PropertyMock) as context_mock:\n        context_mock.return_value = \"host\"\n        apt = Apt(conanfile)\n        apt.install([\"package1\", \"package2\"], recommends=recommends, check=False)\n    assert apt._conanfile.command == \"apt-get install -y {}package1 package2\".format(recommends_str)\n\n\n@pytest.mark.parametrize(\"tool_class\",\n                         [Apk, Apt, Yum, Dnf, Brew, Pkg, PkgUtil, Chocolatey, PacMan, Zypper])\ndef test_tools_install_mode_check(tool_class):\n    conanfile = ConanFileMock()\n    conanfile.settings = Settings()\n    conanfile.conf.define(\"tools.system.package_manager:tool\", tool_class.tool_name)\n    with mock.patch('conan.ConanFile.context', new_callable=PropertyMock) as context_mock:\n        context_mock.return_value = \"host\"\n        tool = tool_class(conanfile)\n        with pytest.raises(ConanException) as exc_info:\n            def fake_check(*args, **kwargs):\n                return [\"package1\", \"package2\"]\n            from conan.tools.system.package_manager import _SystemPackageManagerTool\n            with patch.object(_SystemPackageManagerTool, 'check', MagicMock(side_effect=fake_check)):\n                tool.install([\"package1\", \"package2\"])\n        assert exc_info.value.args[0] == \"System requirements: 'package1, package2' are missing but \" \\\n                                         \"can't install because tools.system.package_manager:mode is \" \\\n                                         \"'check'.Please update packages manually or set \" \\\n                                         \"'tools.system.package_manager:mode' to 'install' in the [conf] \" \\\n                                         \"section of the profile, or in the command line using \" \\\n                                         \"'-c tools.system.package_manager:mode=install'\"\n\n\n@pytest.mark.parametrize(\"tool_class, result\",\n[\n    (Apk, \"apk update\"),\n    (Apt, \"apt-get update\"),\n    (Yum, \"yum check-update -y\"),\n    (Dnf, \"dnf check-update -y\"),\n    (Brew, \"brew update\"),\n    (Pkg, \"pkg update\"),\n    (PkgUtil, \"pkgutil --catalog\"),\n    (Chocolatey, \"choco outdated\"),\n    (PacMan, \"pacman -Syyu --noconfirm\"),\n    (Zypper, \"zypper --non-interactive ref\"),\n])\ndef test_tools_update_mode_install(tool_class, result):\n    conanfile = ConanFileMock()\n    conanfile.settings = Settings()\n    conanfile.conf.define(\"tools.system.package_manager:tool\", tool_class.tool_name)\n    for mode in [\"check\", \"install\"]:\n        conanfile.conf.define(\"tools.system.package_manager:mode\", mode)\n        with mock.patch('conan.ConanFile.context', new_callable=PropertyMock) as context_mock:\n            context_mock.return_value = \"host\"\n            tool = tool_class(conanfile)\n            tool.update()\n            if mode == \"install\":\n                assert tool._conanfile.command == result\n            else:\n                # does not run the update when mode check\n                assert tool._conanfile.command is None\n\n\n@pytest.mark.parametrize(\"tool_class, result\", [\n    (Yum, \"yum check-update -y\"),\n    (Dnf, \"dnf check-update -y\"),\n])\ndef test_dnf_yum_return_code_100(tool_class, result):\n    # https://github.com/conan-io/conan/issues/11661\n    conanfile = ConanFileMock()\n    conanfile.settings = Settings()\n    conanfile.conf.define(\"tools.system.package_manager:tool\", tool_class.tool_name)\n    conanfile.conf.define(\"tools.system.package_manager:mode\", \"install\")\n    with mock.patch('conan.ConanFile.context', new_callable=PropertyMock) as context_mock:\n        context_mock.return_value = \"host\"\n        tool = tool_class(conanfile)\n\n        def fake_run(command, win_bash=False, subsystem=None, env=None, ignore_errors=False,\n                     quiet=False):\n            assert command == result\n            return 100 if \"check-update\" in command else 0\n\n        conanfile.run = fake_run\n        tool.update()\n\n    # check that some random return code fails\n    with mock.patch('conan.ConanFile.context', new_callable=PropertyMock) as context_mock:\n        context_mock.return_value = \"host\"\n        tool = tool_class(conanfile)\n\n        def fake_run(command, win_bash=False, subsystem=None, env=None, ignore_errors=False,\n                     quiet=False):\n            return 55 if \"check-update\" in command else 0\n\n        conanfile.run = fake_run\n        with pytest.raises(ConanException) as exc_info:\n            tool.update()\n        assert f\"Command '{result}' failed\" == str(exc_info.value)\n\n\n@pytest.mark.parametrize(\"tool_class, arch_host, result\", [\n    # Install host package and not cross-compile -> do not add host architecture\n    (Apk, 'x86_64', 'apk add --no-cache package1 package2'),\n    (Apt, 'x86_64', 'apt-get install -y --no-install-recommends package1 package2'),\n    (Yum, 'x86_64', 'yum install -y package1 package2'),\n    (Dnf, 'x86_64', 'dnf install -y package1 package2'),\n    (Brew, 'x86_64', 'brew install package1 package2'),\n    (Pkg, 'x86_64', 'pkg install -y package1 package2'),\n    (PkgUtil, 'x86_64', 'pkgutil --install --yes package1 package2'),\n    (Chocolatey, 'x86_64', 'choco install --yes package1 package2'),\n    (PacMan, 'x86_64', 'pacman -S --noconfirm package1 package2'),\n    (Zypper, 'x86_64', 'zypper --non-interactive in package1 package2'),\n    # Install host package and cross-compile -> add host architecture\n    (Apt, 'x86', 'apt-get install -y --no-install-recommends package1:i386 package2:i386'),\n    (Yum, 'x86', 'yum install -y package1.i?86 package2.i?86'),\n    (Dnf, 'x86', 'dnf install -y package1.i?86 package2.i?86'),\n    (Brew, 'x86', 'brew install package1 package2'),\n    (Pkg, 'x86', 'pkg install -y package1 package2'),\n    (PkgUtil, 'x86', 'pkgutil --install --yes package1 package2'),\n    (Chocolatey, 'x86', 'choco install --yes package1 package2'),\n    (PacMan, 'x86', 'pacman -S --noconfirm package1-lib32 package2-lib32'),\n    (Zypper, 'x86', 'zypper --non-interactive in package1 package2'),\n])\ndef test_tools_install_mode_install_different_archs(tool_class, arch_host, result):\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\"arch\": arch_host})\n    conanfile.settings_build = MockSettings({\"arch\": \"x86_64\"})\n    conanfile.conf.define(\"tools.system.package_manager:tool\", tool_class.tool_name)\n    conanfile.conf.define(\"tools.system.package_manager:mode\", \"install\")\n    with mock.patch('conan.ConanFile.context', new_callable=PropertyMock) as context_mock:\n        context_mock.return_value = \"host\"\n        tool = tool_class(conanfile)\n\n        def fake_check(*args, **kwargs):\n            return [\"package1\", \"package2\"]\n        from conan.tools.system.package_manager import _SystemPackageManagerTool\n        with patch.object(_SystemPackageManagerTool, 'check', MagicMock(side_effect=fake_check)):\n            tool.install([\"package1\", \"package2\"])\n\n    assert tool._conanfile.command == result\n\n\n@pytest.mark.parametrize(\"tool_class, arch_host, result\", [\n    # Install host package and not cross-compile -> do not add host architecture\n    (Apk, 'x86_64', 'apk add --no-cache package1=0.1 package2=0.2'),\n    (Apt, 'x86_64', 'apt-get install -y --no-install-recommends package1=0.1 package2=0.2'),\n    (Yum, 'x86_64', 'yum install -y package1-0.1 package2-0.2'),\n    (Dnf, 'x86_64', 'dnf install -y package1-0.1 package2-0.2'),\n    (Brew, 'x86_64', 'brew install package1@0.1 package2@0.2'),\n    (Pkg, 'x86_64', 'pkg install -y package1-0.1 package2-0.2'),\n    (PkgUtil, 'x86_64', 'pkgutil --install --yes package1@0.1 package2@0.2'),\n    (Chocolatey, 'x86_64', 'choco install --yes package1 --version 0.1 package2 --version 0.2'),\n    (PacMan, 'x86_64', 'pacman -S --noconfirm package1 package2'),\n    (Zypper, 'x86_64', 'zypper --non-interactive in package1=0.1 package2=0.2'),\n    # Install host package and cross-compile -> add host architecture\n    (Apt, 'x86', 'apt-get install -y --no-install-recommends package1:i386=0.1 package2:i386=0.2'),\n    (Yum, 'x86', 'yum install -y package1-0.1.i?86 package2-0.2.i?86'),\n    (Dnf, 'x86', 'dnf install -y package1-0.1.i?86 package2-0.2.i?86'),\n    (Brew, 'x86', 'brew install package1@0.1 package2@0.2'),\n    (Pkg, 'x86', 'pkg install -y package1-0.1 package2-0.2'),\n    (PkgUtil, 'x86', 'pkgutil --install --yes package1@0.1 package2@0.2'),\n    (Chocolatey, 'x86', 'choco install --yes package1 --version 0.1 package2 --version 0.2'),\n    (PacMan, 'x86', 'pacman -S --noconfirm package1-lib32 package2-lib32'),\n    (Zypper, 'x86', 'zypper --non-interactive in package1=0.1 package2=0.2'),\n])\ndef test_tools_install_mode_install_different_archs_with_version(tool_class, arch_host, result):\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\"arch\": arch_host})\n    conanfile.settings_build = MockSettings({\"arch\": \"x86_64\"})\n    conanfile.conf.define(\"tools.system.package_manager:tool\", tool_class.tool_name)\n    conanfile.conf.define(\"tools.system.package_manager:mode\", \"install\")\n    with mock.patch('conan.ConanFile.context', new_callable=PropertyMock) as context_mock:\n        context_mock.return_value = \"host\"\n        tool = tool_class(conanfile)\n\n        def fake_check(*args, **kwargs):\n            return [\"package1=0.1\", \"package2=0.2\"]\n        from conan.tools.system.package_manager import _SystemPackageManagerTool\n        with patch.object(_SystemPackageManagerTool, 'check', MagicMock(side_effect=fake_check)):\n            tool.install([\"package1=0.1\", \"package2=0.2\"])\n    assert tool._conanfile.command == result\n\n\n@pytest.mark.parametrize(\"tool_class, arch_host, result\", [\n    # Install build machine package and not cross-compile -> do not add host architecture\n    (Apk, 'x86_64', 'apk add --no-cache package1 package2'),\n    (Apt, 'x86_64', 'apt-get install -y --no-install-recommends package1 package2'),\n    (Yum, 'x86_64', 'yum install -y package1 package2'),\n    (Dnf, 'x86_64', 'dnf install -y package1 package2'),\n    (Brew, 'x86_64', 'brew install package1 package2'),\n    (Pkg, 'x86_64', 'pkg install -y package1 package2'),\n    (PkgUtil, 'x86_64', 'pkgutil --install --yes package1 package2'),\n    (Chocolatey, 'x86_64', 'choco install --yes package1 package2'),\n    (PacMan, 'x86_64', 'pacman -S --noconfirm package1 package2'),\n    (Zypper, 'x86_64', 'zypper --non-interactive in package1 package2'),\n    # Install build machine package and cross-compile -> do not add host architecture\n    (Apt, 'x86', 'apt-get install -y --no-install-recommends package1 package2'),\n    (Yum, 'x86', 'yum install -y package1 package2'),\n    (Dnf, 'x86', 'dnf install -y package1 package2'),\n    (Brew, 'x86', 'brew install package1 package2'),\n    (Pkg, 'x86', 'pkg install -y package1 package2'),\n    (PkgUtil, 'x86', 'pkgutil --install --yes package1 package2'),\n    (Chocolatey, 'x86', 'choco install --yes package1 package2'),\n    (PacMan, 'x86', 'pacman -S --noconfirm package1 package2'),\n    (Zypper, 'x86', 'zypper --non-interactive in package1 package2'),\n])\ndef test_tools_install_mode_install_to_build_machine_arch(tool_class, arch_host, result):\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\"arch\": arch_host})\n    conanfile.settings_build = MockSettings({\"arch\": \"x86_64\"})\n    conanfile.conf.define(\"tools.system.package_manager:tool\", tool_class.tool_name)\n    conanfile.conf.define(\"tools.system.package_manager:mode\", \"install\")\n    with mock.patch('conan.ConanFile.context', new_callable=PropertyMock) as context_mock:\n        context_mock.return_value = \"host\"\n        tool = tool_class(conanfile)\n\n        def fake_check(*args, **kwargs):\n            return [\"package1\", \"package2\"]\n        from conan.tools.system.package_manager import _SystemPackageManagerTool\n        with patch.object(_SystemPackageManagerTool, 'check', MagicMock(side_effect=fake_check)):\n            tool.install([\"package1\", \"package2\"], host_package=False)\n\n    assert tool._conanfile.command == result\n\n\n@pytest.mark.parametrize(\"tool_class, arch_host, result\", [\n    # Install build machine package and not cross-compile -> do not add host architecture\n    (Apk, 'x86_64', 'apk add --no-cache package1=0.1 package2=0.2'),\n    (Apt, 'x86_64', 'apt-get install -y --no-install-recommends package1=0.1 package2=0.2'),\n    (Yum, 'x86_64', 'yum install -y package1-0.1 package2-0.2'),\n    (Dnf, 'x86_64', 'dnf install -y package1-0.1 package2-0.2'),\n    (Brew, 'x86_64', 'brew install package1@0.1 package2@0.2'),\n    (Pkg, 'x86_64', 'pkg install -y package1-0.1 package2-0.2'),\n    (PkgUtil, 'x86_64', 'pkgutil --install --yes package1@0.1 package2@0.2'),\n    (Chocolatey, 'x86_64', 'choco install --yes package1 --version 0.1 package2 --version 0.2'),\n    (PacMan, 'x86_64', 'pacman -S --noconfirm package1 package2'),\n    (Zypper, 'x86_64', 'zypper --non-interactive in package1=0.1 package2=0.2'),\n    # Install build machine package and cross-compile -> do not add host architecture\n    (Apt, 'x86', 'apt-get install -y --no-install-recommends package1=0.1 package2=0.2'),\n    (Yum, 'x86', 'yum install -y package1-0.1 package2-0.2'),\n    (Dnf, 'x86', 'dnf install -y package1-0.1 package2-0.2'),\n    (Brew, 'x86', 'brew install package1@0.1 package2@0.2'),\n    (Pkg, 'x86', 'pkg install -y package1-0.1 package2-0.2'),\n    (PkgUtil, 'x86', 'pkgutil --install --yes package1@0.1 package2@0.2'),\n    (Chocolatey, 'x86', 'choco install --yes package1 --version 0.1 package2 --version 0.2'),\n    (PacMan, 'x86', 'pacman -S --noconfirm package1 package2'),\n    (Zypper, 'x86', 'zypper --non-interactive in package1=0.1 package2=0.2'),\n])\ndef test_tools_install_mode_install_to_build_machine_arch_with_version(tool_class, arch_host, result):\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\"arch\": arch_host})\n    conanfile.settings_build = MockSettings({\"arch\": \"x86_64\"})\n    conanfile.conf.define(\"tools.system.package_manager:tool\", tool_class.tool_name)\n    conanfile.conf.define(\"tools.system.package_manager:mode\", \"install\")\n    with mock.patch('conan.ConanFile.context', new_callable=PropertyMock) as context_mock:\n        context_mock.return_value = \"host\"\n        tool = tool_class(conanfile)\n\n        def fake_check(*args, **kwargs):\n            return [\"package1=0.1\", \"package2=0.2\"]\n        from conan.tools.system.package_manager import _SystemPackageManagerTool\n        with patch.object(_SystemPackageManagerTool, 'check', MagicMock(side_effect=fake_check)):\n            tool.install([\"package1=0.1\", \"package2=0.2\"], host_package=False)\n\n    assert tool._conanfile.command == result\n\n\n@pytest.mark.parametrize(\"tool_class, result\", [\n    # cross-compile but arch_names=None -> do not add host architecture\n    # https://github.com/conan-io/conan/issues/12320 because the package is archless\n    (Apt, 'apt-get install -y --no-install-recommends package1 package2'),\n    (Yum, 'yum install -y package1 package2'),\n    (Dnf, 'dnf install -y package1 package2'),\n    (PacMan, 'pacman -S --noconfirm package1 package2'),\n])\ndef test_tools_install_archless(tool_class, result):\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\"arch\": \"x86\"})\n    conanfile.settings_build = MockSettings({\"arch\": \"x86_64\"})\n    conanfile.conf.define(\"tools.system.package_manager:tool\", tool_class.tool_name)\n    conanfile.conf.define(\"tools.system.package_manager:mode\", \"install\")\n    with mock.patch('conan.ConanFile.context', new_callable=PropertyMock) as context_mock:\n        context_mock.return_value = \"host\"\n        tool = tool_class(conanfile, arch_names={})\n\n        def fake_check(*args, **kwargs):\n            return [\"package1\", \"package2\"]\n        from conan.tools.system.package_manager import _SystemPackageManagerTool\n        with patch.object(_SystemPackageManagerTool, 'check', MagicMock(side_effect=fake_check)):\n            tool.install([\"package1\", \"package2\"])\n\n    assert tool._conanfile.command == result\n\n\n@pytest.mark.parametrize(\"tool_class, result\", [\n    # cross-compile but arch_names=None -> do not add host architecture\n    # https://github.com/conan-io/conan/issues/12320 because the package is archless\n    (Apt, 'apt-get install -y --no-install-recommends package1=0.1 package2=0.2'),\n    (Yum, 'yum install -y package1-0.1 package2-0.2'),\n    (Dnf, 'dnf install -y package1-0.1 package2-0.2'),\n    (PacMan, 'pacman -S --noconfirm package1 package2'),\n])\ndef test_tools_install_archless_with_version(tool_class, result):\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\"arch\": \"x86\"})\n    conanfile.settings_build = MockSettings({\"arch\": \"x86_64\"})\n    conanfile.conf.define(\"tools.system.package_manager:tool\", tool_class.tool_name)\n    conanfile.conf.define(\"tools.system.package_manager:mode\", \"install\")\n    with mock.patch('conan.ConanFile.context', new_callable=PropertyMock) as context_mock:\n        context_mock.return_value = \"host\"\n        tool = tool_class(conanfile, arch_names={})\n\n        def fake_check(*args, **kwargs):\n            return [\"package1=0.1\", \"package2=0.2\"]\n        from conan.tools.system.package_manager import _SystemPackageManagerTool\n        with patch.object(_SystemPackageManagerTool, 'check', MagicMock(side_effect=fake_check)):\n            tool.install([\"package1=0.1\", \"package2=0.2\"])\n\n    assert tool._conanfile.command == result\n\n\n@pytest.mark.parametrize(\"tool_class, result\", [\n    (Apk, 'apk info -e package'),\n    (Apt, r\"dpkg-query -W -f='${Architecture}\\n' package | grep -qEx '(amd64|all)'\"),\n    (Yum, 'rpm -q package'),\n    (Dnf, 'rpm -q package'),\n    (Brew, 'test -n \"$(brew ls --versions package)\"'),\n    (Pkg, 'pkg info package'),\n    (PkgUtil, 'test -n \"`pkgutil --list package`\"'),\n    (Chocolatey, 'choco list --exact package | findstr /c:\"1 packages installed.\"'),\n    (PacMan, 'pacman -Qi package'),\n    (Zypper, 'rpm -q package'),\n])\ndef test_tools_check(tool_class, result):\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\"arch\": \"x86_64\"})\n    conanfile.conf.define(\"tools.system.package_manager:tool\", tool_class.tool_name)\n    with mock.patch('conan.ConanFile.context', new_callable=PropertyMock) as context_mock:\n        context_mock.return_value = \"host\"\n        tool = tool_class(conanfile)\n        tool.check([\"package\"])\n\n    assert tool._conanfile.command == result\n\n\n@pytest.mark.parametrize(\"tool_class, result\", [\n    (Apk, 'apk info package | grep \"0.1\"'),\n    (Apt, r\"dpkg-query -W -f='${Architecture} ${Version}\\n' package | grep -qEx '(amd64|all) 0.1'\"),\n    (Yum, 'rpm -q package-0.1'),\n    (Dnf, 'rpm -q package-0.1'),\n    (Brew, 'brew list --versions package | grep \"0.1\"'),\n    (Pkg, 'pkg info package | grep \"Version: 0.1\"'),\n    (PkgUtil, 'test -n \"`pkgutil --list package`\"'),\n    (Chocolatey, 'choco list --local-only package | findstr /i \"0.1\"'),\n    (PacMan, 'pacman -Qi package'),\n    (Zypper, 'rpm -q package-0.1'),\n])\ndef test_tools_check_with_version(tool_class, result):\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\"arch\": \"x86_64\"})\n    conanfile.conf.define(\"tools.system.package_manager:tool\", tool_class.tool_name)\n    with mock.patch('conan.ConanFile.context', new_callable=PropertyMock) as context_mock:\n        context_mock.return_value = \"host\"\n        tool = tool_class(conanfile)\n        tool.check([\"package=0.1\"])\n\n    assert tool._conanfile.command == result\n\n\n@pytest.mark.parametrize(\"tool_class, result\", [\n    (Apt, r\"dpkg-query -W -f='${Architecture}\\n' package | grep -qEx '(amd64|all)'\"),\n])\n@pytest.mark.parametrize(\"arch_host\", [\n    'x86_64',\n    'x86',\n])\ndef test_tools_apt_check_install_to_build_machine_arch(tool_class, arch_host, result):\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\"arch\": arch_host})\n    conanfile.settings_build = MockSettings({\"arch\": \"x86_64\"})\n    conanfile.conf.define(\"tools.system.package_manager:tool\", tool_class.tool_name)\n    with mock.patch('conan.ConanFile.context', new_callable=PropertyMock) as context_mock:\n        context_mock.return_value = \"host\"\n        tool = tool_class(conanfile)\n        tool.check([\"package\"], host_package=False)\n\n    assert tool._conanfile.command == result\n\n\n@pytest.mark.parametrize(\"tool_class, result\", [\n    (Apt, r\"dpkg-query -W -f='${Architecture} ${Version}\\n' package | grep -qEx '(amd64|all) 0.1'\"),\n])\n@pytest.mark.parametrize(\"arch_host\", [\n    'x86_64',\n    'x86',\n])\ndef test_tools_apt_check_install_to_build_machine_arch_with_version(tool_class, arch_host, result):\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\"arch\": arch_host})\n    conanfile.settings_build = MockSettings({\"arch\": \"x86_64\"})\n    conanfile.conf.define(\"tools.system.package_manager:tool\", tool_class.tool_name)\n    with mock.patch('conan.ConanFile.context', new_callable=PropertyMock) as context_mock:\n        context_mock.return_value = \"host\"\n        tool = tool_class(conanfile)\n        tool.check([\"package=0.1\"], host_package=False)\n\n    assert tool._conanfile.command == result\n"
  },
  {
    "path": "test/integration/workspace/__init__.py",
    "content": ""
  },
  {
    "path": "test/integration/workspace/test_workspace.py",
    "content": "import json\nimport os\nimport shutil\nimport textwrap\n\nimport pytest\n\nfrom conan.api.model import RecipeReference\nfrom conan.api.subapi.workspace import WorkspaceAPI\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.mocks import ConanFileMock\nfrom conan.test.utils.scm import create_local_git_repo\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import save_files\nfrom conan.tools.files import replace_in_file\n\nWorkspaceAPI.TEST_ENABLED = \"will_break_next\"\n\n\nclass TestWorkspaceRoot:\n\n    def test_workspace_root(self):\n        c = TestClient(light=True)\n        # Just check the root command works\n        c.run(\"workspace root\", assert_error=True)\n        assert \"ERROR: Workspace not defined, please create\" in c.out\n\n        # error, conanws/ folder does not contain conanws.[py | yml]\n        c.save({\"conanws/test.txt\": \"\"})\n        with c.chdir(\"conanws\"):\n            c.run(\"workspace root\", assert_error=True)\n            assert \"ERROR: Workspace not defined, please create\" in c.out\n            c.save({\"conanws.yml\": \"\"})\n            c.run(\"workspace root\")\n            assert c.current_folder in c.stdout\n\n        # error, empty .py\n        c.save({\"conanws.py\": \"\"}, clean_first=True)\n        c.run(\"workspace root\", assert_error=True)\n        assert \"Error loading conanws.py\" in c.out\n        assert \"No subclass of Workspace\" in c.out\n\n        c.save({\"conanws.yml\": \"\"}, clean_first=True)\n        c.run(\"workspace root\")\n        assert c.current_folder in c.stdout\n\n\nclass TestAddRemove:\n\n    def test_add(self):\n        c = TestClient(light=True)\n        c.save({\"conanws.yml\": \"\",\n                \"dep1/conanfile.py\": GenConanfile(\"dep1\", \"0.1\"),\n                \"dep2/conanfile.py\": GenConanfile(\"dep2\", \"0.1\"),\n                \"dep3/conanfile.py\": GenConanfile(\"dep3\", \"0.1\")})\n        c.run(\"workspace add dep1\")\n        assert \"Reference 'dep1/0.1' added to workspace\" in c.out\n        c.run(\"workspace info\")\n        assert \"dep1/0.1\" in c.out\n        assert \"dep2\" not in c.out\n        c.run(\"editable list\")  # No editables in global\n        assert \"dep1\" not in c.out\n        assert \"dep2\" not in c.out\n        c.run(\"workspace add dep2\")\n        assert \"Reference 'dep2/0.1' added to workspace\" in c.out\n        c.run(\"workspace info\")\n        assert \"dep1/0.1\" in c.out\n        assert \"dep2/0.1\" in c.out\n\n        with c.chdir(temp_folder()):  # If we move to another folder, outside WS, no editables\n            c.run(\"editable list\")\n            assert \"dep1\" not in c.out\n            assert \"dep2\" not in c.out\n\n        c.run(\"workspace info\")\n        assert \"dep1/0.1\" in c.out\n        assert \"dep2/0.1\" in c.out\n\n        c.run(\"workspace remove dep1\")\n        c.run(\"workspace info\")\n        assert \"dep1/0.1\" not in c.out\n        assert \"dep2/0.1\" in c.out\n\n        c.run(\"workspace remove dep2\")\n        c.run(\"workspace info\")\n        assert \"dep1/0.1\" not in c.out\n        assert \"dep2/0.1\" not in c.out\n\n    def test_add_from_outside(self):\n        c = TestClient(light=True)\n        c.save({\"sub/conanws.yml\": \"\",\n                \"sub/dep1/conanfile.py\": GenConanfile(\"dep1\", \"0.1\"),\n                \"sub/dep2/conanfile.py\": GenConanfile(\"dep2\", \"0.1\")})\n        with c.chdir(\"sub\"):\n            c.run(\"workspace add dep1\")\n            assert \"Reference 'dep1/0.1' added to workspace\" in c.out\n            c.run(\"workspace add dep2\")\n            assert \"Reference 'dep2/0.1' added to workspace\" in c.out\n            c.run(\"workspace info\")\n            assert \"dep1/0.1\" in c.out\n            assert \"dep2/0.1\" in c.out\n        assert c.load_home(\"editable_packages.json\") is None\n\n        c.run(\"editable list\")\n        assert \"dep1\" not in c.out\n        assert \"dep2\" not in c.out\n        assert c.load_home(\"editable_packages.json\") is None\n        with c.chdir(\"sub\"):\n            c.run(\"editable add dep1\")\n            assert c.load_home(\"editable_packages.json\") is not None\n            c.run(\"editable list\")\n            assert \"dep1/0.1\" in c.out\n            assert \"dep2/0.1\" not in c.out\n            c.run(\"workspace info\")\n            assert \"dep1\" in c.out\n            assert \"dep2\" in c.out\n\n        c.run(\"editable list\")\n        assert \"dep1/0.1\" in c.out\n        assert \"dep2\" not in c.out\n\n    def test_add_modified(self):\n        # https://github.com/conan-io/conan/issues/18942\n        c = TestClient(light=True)\n        c.save({\"conanws.yml\": \"\",\n                \"dep1/conanfile.py\": GenConanfile(\"dep1\", \"0.1\")})\n        c.run(\"workspace add dep1\")\n        assert \"Reference 'dep1/0.1' added to workspace\" in c.out\n        c.run(\"workspace info\")\n        assert \"dep1/0.1\" in c.out\n        c.save({\"dep1/conanfile.py\": GenConanfile(\"dep1\", \"0.2\")})\n        c.run(\"workspace add dep1\")\n        assert \"Package dep1 already exists, updating its reference\" in c.out\n        assert \"Reference 'dep1/0.2' added to workspace\" in c.out\n        c.run(\"workspace info\")\n        assert \"dep1/0.2\" in c.out\n        assert \"dep1/0.1\" not in c.out\n\n    @pytest.mark.parametrize(\"api\", [False, True])\n    def test_dynamic_editables(self, api):\n        c = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n            import os\n            from conan import ConanFile\n            from conan.tools.files import load\n            class Lib(ConanFile):\n                def set_name(self):\n                    self.name = load(self, os.path.join(self.recipe_folder, \"name.txt\"))\n                def set_version(self):\n                    self.version = load(self, os.path.join(self.recipe_folder, \"version.txt\"))\n            \"\"\")\n        if not api:\n            workspace = textwrap.dedent(\"\"\"\\\n                import os\n                from conan import Workspace\n\n                class MyWorkspace(Workspace):\n                    def packages(self):\n                        result = []\n                        for f in os.listdir(self.folder):\n                            if os.path.isdir(os.path.join(self.folder, f)):\n                                full_path = os.path.join(self.folder, f, \"name.txt\")\n                                name = open(full_path).read().strip()\n                                version = open(os.path.join(self.folder, f,\n                                                            \"version.txt\")).read().strip()\n                                result.append({\"path\": f, \"ref\": f\"{name}/{version}\"})\n                        return result\n                \"\"\")\n        else:\n            workspace = textwrap.dedent(\"\"\"\\\n                import os\n                from conan import Workspace\n\n                class MyWorkspace(Workspace):\n                    def packages(self):\n                        result = []\n                        for f in os.listdir(self.folder):\n                            if os.path.isdir(os.path.join(self.folder, f)):\n                                conanfile = self.load_conanfile(f)\n                                result.append({\"path\": f,\n                                               \"ref\": f\"{conanfile.name}/{conanfile.version}\"})\n                        return result\n               \"\"\")\n\n        c.save({\"conanws.py\": workspace,\n                \"dep1/conanfile.py\": conanfile,\n                \"dep1/name.txt\": \"pkg\",\n                \"dep1/version.txt\": \"2.1\"})\n        c.run(\"workspace info --format=json\")\n        info = json.loads(c.stdout)\n        assert info[\"packages\"] == [{\"ref\": \"pkg/2.1\", \"path\": \"dep1\"}]\n        c.save({\"dep1/name.txt\": \"other\",\n                \"dep1/version.txt\": \"14.5\"})\n        c.run(\"workspace info --format=json\")\n        info = json.loads(c.stdout)\n        assert info[\"packages\"] == [{\"ref\": \"other/14.5\", \"path\": \"dep1\"}]\n        c.run(\"install --requires=other/14.5\")\n        # Doesn't fail\n        assert \"other/14.5 - Editable\" in c.out\n        with c.chdir(\"dep1\"):\n            c.run(\"install --requires=other/14.5\")\n            # Doesn't fail\n            assert \"other/14.5 - Editable\" in c.out\n\n    def test_api_dynamic_version_run(self):\n        # https://github.com/conan-io/conan/issues/17306\n        c = TestClient(light=True)\n        conanfile = textwrap.dedent(\"\"\"\n            from io import StringIO\n            from conan import ConanFile\n            class Lib(ConanFile):\n                name= \"pkg\"\n                def set_version(self):\n                    my_buf = StringIO()\n                    self.run('echo 2.1', stdout=my_buf)\n                    self.version = my_buf.getvalue().strip()\n            \"\"\")\n\n        workspace = textwrap.dedent(\"\"\"\\\n            import os\n            from conan import Workspace\n\n            class MyWorkspace(Workspace):\n                def packages(self):\n                    conanfile = self.load_conanfile(\"dep1\")\n                    return [{\"path\": \"dep1\", \"ref\": f\"{conanfile.name}/{conanfile.version}\"}]\n            \"\"\")\n\n        c.save({\"conanws.py\": workspace,\n                \"dep1/conanfile.py\": conanfile})\n        c.run(\"workspace info --format=json\")\n        info = json.loads(c.stdout)\n        assert info[\"packages\"] == [{\"ref\": \"pkg/2.1\", \"path\": \"dep1\"}]\n        c.run(\"install --requires=pkg/2.1\")\n        # it will not fail\n\n    def test_api_dynamic_any_version(self):\n        # For workspace, the version of the conanfile can be ignored if the\n        # workspace define a different version.\n        c = TestClient(light=True)\n        workspace = textwrap.dedent(\"\"\"\\\n            import os\n            from conan import Workspace\n\n            class MyWorkspace(Workspace):\n                def packages(self):\n                    return [{\"path\": \"dep1\", \"ref\": \"pkg/1.2.3\"}]\n            \"\"\")\n\n        c.save({\"conanws.py\": workspace,\n                \"dep1/conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n        c.run(\"workspace info --format=json\")\n        info = json.loads(c.stdout)\n        assert info[\"packages\"] == [{\"ref\": \"pkg/1.2.3\", \"path\": \"dep1\"}]\n        c.run(\"install --requires=pkg/1.2.3\")\n        # it will not fail\n\n    def test_replace_requires(self):\n        c = TestClient(light=True)\n        c.save({\"conanws.yml\": \"\",\n                \"pkga/conanfile.py\": GenConanfile(\"pkga\", \"0.1\"),\n                \"pkgb/conanfile.py\": GenConanfile(\"pkgb\", \"0.1\").with_requires(\"pkga/develop\"),\n                \"pkgc/conanfile.py\": GenConanfile(\"pkgc\", \"0.1\").with_requires(\"pkgb/0.1\",\n                                                                               \"pkga/0.1\"),\n                \"myreplaces\": \"[replace_requires]\\npkga/develop: pkga/0.1\"})\n        c.run(\"workspace add pkga\")\n        c.run(\"workspace add pkgb\")\n        c.run(\"workspace add pkgc\")\n        c.run(\"workspace info --format=json\")\n\n        info = json.loads(c.stdout)\n        assert info[\"packages\"] == [{'path': 'pkga', 'ref': 'pkga/0.1'},\n                                    {'path': 'pkgb', 'ref': 'pkgb/0.1'},\n                                    {'path': 'pkgc', 'ref': 'pkgc/0.1'}]\n        c.run(\"install --requires=pkgc/0.1\", assert_error=True)\n        assert \"Version conflict: Conflict between pkga/develop and pkga/0.1 in the graph\" in c.out\n        # it will not fail\n        c.run(\"install --requires=pkgc/0.1 -pr=default -pr=myreplaces\")\n        assert \"pkga/0.1 - Editable\" in c.out\n        assert \"pkga/develop: pkga/0.1\" in c.out\n\n    def test_error_uppercase(self):\n        c = TestClient(light=True)\n        c.save({\"conanws.yml\": \"\",\n                \"conanfile.py\": GenConanfile(\"Pkg\", \"0.1\")})\n        c.run(\"workspace add .\", assert_error=True)\n        assert \"ERROR: Conan packages names 'Pkg/0.1' must be all lowercase\" in c.out\n        c.save({\"conanfile.py\": GenConanfile()})\n        c.run(\"workspace add . --name=Pkg --version=0.1\", assert_error=True)\n        assert \"ERROR: Conan packages names 'Pkg/0.1' must be all lowercase\" in c.out\n\n    def test_add_open_error(self):\n        c = TestClient(light=True)\n        c.save({\"conanws.yml\": \"\",\n                \"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\")})\n        c.run(\"workspace add dep\")\n        c.run(\"workspace open dep/0.1\", assert_error=True)\n        assert \"ERROR: Can't open a dependency that is already an editable: dep/0.1\" in c.out\n\n    def test_remove_product(self):\n        c = TestClient(light=True)\n        c.save({\"conanws.yml\": \"\",\n                \"mydeppkg/conanfile.py\": GenConanfile(\"mydeppkg\", \"0.1\")})\n        c.run(\"workspace add mydeppkg\")\n        c.run(\"workspace remove mydeppkg\")\n        c.run(\"workspace info\")\n        assert \"mydeppkg\" not in c.out\n\n    def test_remove_removed_folder(self):\n        c = TestClient(light=True)\n        c.save({\"conanws.yml\": \"\",\n                \"mydeppkg/conanfile.py\": GenConanfile(\"mydeppkg\", \"0.1\")})\n        c.run(\"workspace add mydeppkg\")\n        # If we now remove the folder\n        shutil.rmtree(os.path.join(c.current_folder, \"mydeppkg\"))\n        # It can still be removed by path, even if the path doesn't exist\n        c.run(\"workspace remove mydeppkg\")\n        assert \"Removed from workspace: mydeppkg\" in c.out\n        c.run(\"workspace info\")\n        assert \"mydeppkg\" not in c.out\n\n    def test_custom_add_remove(self):\n        c = TestClient(light=True)\n\n        workspace = textwrap.dedent(\"\"\"\\\n            import os\n            from conan import Workspace\n\n            class MyWorkspace(Workspace):\n                def name(self):\n                    return \"myws\"\n\n                def add(self, ref, path, *args, **kwargs):\n                    self.output.info(f\"Adding {ref} at {path}\")\n                    super().add(ref, path, *args, **kwargs)\n\n                def remove(self, path, *args, **kwargs):\n                    self.output.info(f\"Removing {path}\")\n                    return super().remove(path, *args, **kwargs)\n            \"\"\")\n\n        c.save({\"conanws.py\": workspace,\n                \"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\")})\n        c.run(\"workspace add dep\")\n        assert \"Workspace 'myws': Adding dep/0.1\" in c.out\n        c.run(\"workspace info\")\n        assert \"dep/0.1\" in c.out\n        c.run(\"workspace remove dep\")\n        assert \"Workspace 'myws': Removing\" in c.out\n        c.run(\"workspace info\")\n        assert \"dep/0.1\" not in c.out\n\n    def test_remove_non_existing_error(self):\n        c = TestClient(light=True)\n        c.save({\"conanws.yml\": \"\"})\n        c.run(\"workspace remove kk\", assert_error=True)\n        assert \"ERROR: No editable package to remove from this path: kk\" in c.out\n\n\nclass TestOpenAdd:\n    def test_without_git(self):\n        t = TestClient(default_server_user=True, light=True)\n        t.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\")})\n        t.run(\"create .\")\n        t.run(\"upload * -r=default -c\")\n\n        c = TestClient(servers=t.servers, light=True)\n        c.run(f\"workspace open pkg/0.1\")\n        assert \"name = 'pkg'\" in c.load(\"pkg/conanfile.py\")\n\n        # The add should work the same\n        c2 = TestClient(servers=t.servers, light=True)\n        c2.save({\"conanws.yml\": \"\"})\n        c2.run(f\"workspace add --ref=pkg/0.1\")\n        assert \"name = 'pkg'\" in c2.load(\"pkg/conanfile.py\")\n        c2.run(\"workspace info\")\n        assert \"pkg/0.1\" in c2.out\n\n    def test_without_git_export_sources(self):\n        t = TestClient(default_server_user=True, light=True)\n        t.save({\"conanfile.py\": GenConanfile(\"pkg\", \"0.1\").with_exports_sources(\"*.txt\"),\n                \"CMakeLists.txt\": \"mycmake\"})\n        t.run(\"create .\")\n        t.run(\"upload * -r=default -c\")\n\n        c = TestClient(servers=t.servers)\n        c.run(\"workspace open pkg/0.1\")\n        assert \"name = 'pkg'\" in c.load(\"pkg/conanfile.py\")\n        assert \"mycmake\" in c.load(\"pkg/CMakeLists.txt\")\n\n    def test_workspace_git_scm(self):\n        folder = temp_folder()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.scm import Git\n\n            class Pkg(ConanFile):\n                name = \"pkg\"\n                version = \"0.1\"\n                def export(self):\n                    git = Git(self)\n                    git.coordinates_to_conandata()\n            \"\"\")\n        url, commit = create_local_git_repo(files={\"conanfile.py\": conanfile}, folder=folder,\n                                            branch=\"mybranch\")\n        t1 = TestClient(default_server_user=True, light=True)\n        t1.run_command('git clone \"file://{}\" .'.format(url))\n        t1.run(\"create .\")\n        t1.run(\"upload * -r=default -c\")\n\n        c = TestClient(servers=t1.servers, light=True)\n        c.run(\"workspace open pkg/0.1\")\n        assert c.load(\"pkg/conanfile.py\") == conanfile\n\n        c2 = TestClient(servers=t1.servers, light=True)\n        c2.save({\"conanws.yml\": \"\"})\n        c2.run(f\"workspace add --ref=pkg/0.1\")\n        assert 'name = \"pkg\"' in c2.load(\"pkg/conanfile.py\")\n        c2.run(\"workspace info\")\n        assert \"pkg/0.1\" in c2.out\n\n    def test_workspace_build_editables(self):\n        c = TestClient(light=True)\n        c.save({\"conanws.yml\": \"\"})\n\n        c.save({\"pkga/conanfile.py\": GenConanfile(\"pkga\", \"0.1\").with_build_msg(\"BUILD PKGA!\"),\n                \"pkgb/conanfile.py\": GenConanfile(\"pkgb\", \"0.1\").with_build_msg(\"BUILD PKGB!\")\n                                                                .with_requires(\"pkga/0.1\")})\n        c.run(\"workspace add pkga\")\n        c.run(\"workspace add pkgb\")\n\n        c.run(\"install --requires=pkgb/0.1 --build=editable\")\n        c.assert_listed_binary({\"pkga/0.1\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\",\n                                             \"EditableBuild\"),\n                                \"pkgb/0.1\": (\"47a5f20ec8fb480e1c5794462089b01a3548fdc5\",\n                                             \"EditableBuild\")})\n        assert \"pkga/0.1: WARN: BUILD PKGA!\" in c.out\n        assert \"pkgb/0.1: WARN: BUILD PKGB!\" in c.out\n\n\nclass TestComplete:\n    def test_complete_add(self):\n        c = TestClient(light=True)\n        c.save({\"conanws.yml\": \"\",\n                \"pkga/conanfile.py\": GenConanfile(\"pkga\", \"0.1\"),\n                \"pkgx/conanfile.py\": GenConanfile(\"pkgx\", \"0.1\"),\n                \"pkgb/conanfile.py\": GenConanfile(\"pkgb\", \"0.1\").with_requires(\"pkga/0.1\"),\n                \"pkgc/conanfile.py\": GenConanfile(\"pkgc\", \"0.1\").with_requires(\"pkga/0.1\",\n                                                                               \"pkgx/0.1\"),\n                \"pkgd/conanfile.py\": GenConanfile(\"pkgd\", \"0.1\").with_requires(\"pkgb/0.1\",\n                                                                               \"pkgc/0.1\")})\n\n        c.run(\"workspace complete\")  # Does nothing, but it doesn't fail\n        assert \"There are no packages in this workspace, nothing to complete\" in c.out\n        c.run(\"workspace info\")\n        assert \"packages: (empty)\" in c.out\n\n        for pkg in (\"pkga\", \"pkgx\", \"pkgb\", \"pkgc\", \"pkgd\"):\n            c.run(f\"export {pkg}\")\n\n        c.run(\"workspace add pkgd\")\n        c.run(\"workspace complete\")  # Does nothing, but it doesn't fail\n        assert \"There are no intermediate packages to add to the workspace\" in c.out\n        c.run(\"workspace info\")\n        assert \"pkgd/0.1\" in c.out\n        assert \"pkga/0.1\" not in c.out\n\n        c.run(\"workspace add pkga\")\n        c.run(\"workspace install --build=missing\", assert_error=True)\n        assert \"Workspace definition error. Package pkgb/0.1 in the Conan cache\" in c.out\n        c.run(\"workspace info\")\n        assert \"pkgb/0.1\" not in c.out\n        assert \"pkgc/0.1\" not in c.out\n\n        c.run(\"workspace complete\")\n        c.run(\"workspace info\")\n        assert \"pkgb/0.1\" in c.out\n        assert \"pkgc/0.1\" in c.out\n        assert \"pkgx/0.1\" not in c.out\n\n    def test_complete_open(self):\n        c = TestClient(light=True)\n        c.save({\"pkgx/conanfile.py\": GenConanfile(\"pkgx\", \"0.1\"),\n                \"pkgb/conanfile.py\": GenConanfile(\"pkgb\", \"0.1\").with_requires(\"pkga/0.1\"),\n                \"pkgc/conanfile.py\": GenConanfile(\"pkgc\", \"0.1\").with_requires(\"pkga/0.1\",\n                                                                               \"pkgx/0.1\")})\n\n        for pkg in (\"pkgx\", \"pkgb\", \"pkgc\"):\n            c.run(f\"export {pkg}\")\n\n        c.save({\"conanws.yml\": \"\",\n                \"pkga/conanfile.py\": GenConanfile(\"pkga\", \"0.1\"),\n                \"pkgd/conanfile.py\": GenConanfile(\"pkgd\", \"0.1\").with_requires(\"pkgb/0.1\",\n                                                                               \"pkgc/0.1\")},\n               clean_first=True)\n\n        c.run(\"workspace add pkgd\")\n        c.run(\"workspace add pkga\")\n        c.run(\"workspace install --build=missing\", assert_error=True)\n        assert \"Workspace definition error. Package pkgb/0.1 in the Conan cache\" in c.out\n        c.run(\"workspace info\")\n        assert \"pkgb/0.1\" not in c.out\n        assert \"pkgc/0.1\" not in c.out\n\n        c.run(\"workspace complete\")\n        c.run(\"workspace info\")\n        assert \"pkgb/0.1\" in c.out\n        assert \"pkgc/0.1\" in c.out\n        assert \"pkgx/0.1\" not in c.out\n\n\nclass TestWorkspaceBuild:\n\n    def test_build(self):\n        c = TestClient(light=True)\n        c.save({\"conanws.yml\": \"\"})\n\n        c.save({\"pkga/conanfile.py\": GenConanfile(\"pkga\", \"0.1\").with_build_msg(\"BUILD PKGA!\"),\n                \"pkgb/conanfile.py\": GenConanfile(\"pkgb\", \"0.1\").with_build_msg(\"BUILD PKGB!\")\n               .with_requires(\"pkga/0.1\")})\n        c.run(\"workspace add pkga\")\n        c.run(\"workspace add pkgb\")\n        c.run(\"workspace build\")\n        c.assert_listed_binary({\"pkga/0.1\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\",\n                                             \"EditableBuild\")})\n        assert \"conanfile.py (pkga/0.1): WARN: BUILD PKGA!\" in c.out\n        assert \"conanfile.py (pkgb/0.1): WARN: BUILD PKGB!\" in c.out\n\n        # It is also possible to build a specific package by path\n        # equivalent to ``conan build <path> --build=editable``\n        # This can be done even if it is not a product\n        c.run(\"workspace build --pkg=pkgc/*\", assert_error=True)\n        assert \"ERROR: There are no selected packages defined in the workspace\" in c.out\n        c.run(\"workspace build --pkg=pkgb/*\")\n        c.assert_listed_binary({\"pkga/0.1\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\",\n                                             \"EditableBuild\")})\n        assert \"conanfile.py (pkga/0.1): WARN: BUILD PKGA!\" in c.out\n        assert \"conanfile.py (pkgb/0.1): WARN: BUILD PKGB!\" in c.out\n\n        c.run(\"workspace build --pkg=pkga/*\")\n        assert \"conanfile.py (pkga/0.1): Calling build()\" in c.out\n        assert \"conanfile.py (pkga/0.1): WARN: BUILD PKGA!\" in c.out\n\n    def test_error_if_no_products(self):\n        c = TestClient(light=True)\n        c.save({\"conanws.yml\": \"\"})\n        c.run(\"workspace build\", assert_error=True)\n        assert \"ERROR: There are no selected packages defined in the workspace\" in c.out\n\n    def test_build_external_missing(self):\n        c = TestClient(light=True)\n        c.save({\"conanws.yml\": \"\"})\n\n        c.save({\"mymath/conanfile.py\": GenConanfile(\"mymath\", \"0.1\").with_build_msg(\"MyMATH!!\"),\n                \"pkga/conanfile.py\": GenConanfile(\"pkga\", \"0.1\").with_build_msg(\"BUILD PKGA!\")\n                                                                .with_requires(\"mymath/0.1\"),\n                \"pkgb/conanfile.py\": GenConanfile(\"pkgb\", \"0.1\").with_build_msg(\"BUILD PKGB!\")\n               .with_requires(\"pkga/0.1\")})\n        c.run(\"export mymath\")\n        c.run(\"workspace add pkga\")\n        c.run(\"workspace add pkgb\")\n        c.run(\"workspace build\", assert_error=True)\n        assert \"ERROR: Missing prebuilt package for 'mymath/0.1'\" in c.out\n        c.run(\"workspace build --build=missing\")\n        assert \"Workspace building external mymath/0.1\" in c.out\n\n    def test_build_dynamic_name_version(self):\n        conanfile = textwrap.dedent(\"\"\"\\\n            from conan import ConanFile\n            class MyConan(ConanFile):\n                def build(self):\n                    self.output.info(f\"Building {self.name} AND {self.version}!!!\")\n            \"\"\")\n        workspace = textwrap.dedent(\"\"\"\\\n            import os\n            from conan import Workspace\n\n            class MyWorkspace(Workspace):\n                def packages(self):\n                    result = []\n                    for f in os.listdir(self.folder):\n                        if os.path.isdir(os.path.join(self.folder, f)):\n                            result.append({\"path\": f, \"ref\": f\"{f}/0.1\",\n                                           \"output_folder\": f\"{f}/myout\"})\n                    return result\n           \"\"\")\n        c = TestClient(light=True)\n        c.save({\"conanws.py\": workspace,\n                \"pkga/conanfile.py\": conanfile})\n        c.run(\"workspace info\")\n        assert \"pkga/0.1\" in c.out\n        c.run(\"workspace build\")\n        assert \"metadata\" in os.listdir(os.path.join(c.current_folder, \"pkga\", \"myout\"))\n        assert \"conanfile.py (pkga/0.1): Building pkga AND 0.1!!!\" in c.out\n\n    def test_build_with_external_editable_python_requires(self):\n        c = TestClient(light=True)\n        c.save({\"conanws.yml\": \"\",\n                \"ext/conanfile.py\": GenConanfile(\"ext\", \"0.1\").with_package_type(\"python-require\"),\n                \"pkga/conanfile.py\": GenConanfile(\"pkga\", \"0.1\").with_python_requires(\"ext/0.1\")\n                })\n        c.run(\"editable add ext\")\n        c.run(\"workspace add pkga\")\n        c.run(\"workspace build\")\n        c.assert_listed_binary({\"pkga/0.1\": (\"8bca2eae7cd0d6b6da8d14f8c86069d89d265bd4\",\n                                             \"EditableBuild\")})\n        c.assert_listed_require({\"ext/0.1\": \"Editable\"}, python=True)\n\n    def test_build_with_external_editable(self):\n        c = TestClient(light=True)\n        c.save({\"conanws.yml\": \"\",\n                \"ext/conanfile.py\": GenConanfile(\"ext\", \"0.1\").with_build_msg(\"BUILD EXT!\"),\n                \"pkga/conanfile.py\": GenConanfile(\"pkga\", \"0.1\").with_requires(\"ext/0.1\")\n                })\n        c.run(\"editable add ext\")\n        c.run(\"workspace add pkga\")\n        c.run(\"workspace build\")\n        assert \"ext/0.1: WARN: BUILD EXT!\" in c.out\n        c.assert_listed_binary({\"pkga/0.1\": (\"38f8a554b1b3c2cbb44321f0e731b3863359126c\",\n                                             \"EditableBuild\"),\n                                \"ext/0.1\": (\"da39a3ee5e6b4b0d3255bfef95601890afd80709\",\n                                            \"EditableBuild\")})\n\n\nclass TestNew:\n    def test_new(self):\n        # Very basic workspace for testing\n        c = TestClient(light=True)\n        c.run(\"new workspace\")\n        assert 'name = \"liba\"' in c.load(\"liba/conanfile.py\")\n        c.run(\"workspace info\")\n        assert \"liba/0.1\" in c.out\n        assert \"libb/0.1\" in c.out\n        assert \"app1/0.1\" in c.out\n\n    def test_new_dep(self):\n        c = TestClient(light=True)\n        c.run(\"new workspace -d requires=dep/0.1\")\n        assert 'self.requires(\"dep/0.1\")' in c.load(\"liba/conanfile.py\")\n        assert 'name = \"liba\"' in c.load(\"liba/conanfile.py\")\n        c.run(\"workspace info\")\n        assert \"liba/0.1\" in c.out\n        assert \"libb/0.1\" in c.out\n        assert \"app1/0.1\" in c.out\n\n\nclass TestMeta:\n    def test_install(self):\n        c = TestClient()\n        c.save({\"dep/conanfile.py\": GenConanfile()})\n        c.run(\"create dep --name=dep1 --version=0.1\")\n        c.run(\"create dep --name=dep2 --version=0.1\")\n        c.save({\"conanws.yml\": \"\",\n                \"liba/conanfile.py\": GenConanfile(\"liba\", \"0.1\").with_requires(\"dep1/0.1\",\n                                                                               \"dep2/0.1\"),\n                \"libb/conanfile.py\": GenConanfile(\"libb\", \"0.1\").with_requires(\"liba/0.1\",\n                                                                               \"dep1/0.1\")},\n               clean_first=True)\n        c.run(\"workspace add liba\")\n        c.run(\"workspace add libb\")\n        c.run(\"workspace super-install -g CMakeDeps -g CMakeToolchain -of=build \"\n              \"--envs-generation=false\")\n        assert \"Packages build order:\\n    liba/0.1: liba\\n    libb/0.1: libb\" in c.out\n        assert \"Workspace conanws.py not found in the workspace folder, using default\" in c.out\n        files = os.listdir(os.path.join(c.current_folder, \"build\"))\n        assert \"conan_toolchain.cmake\" in files\n        assert \"dep1-config.cmake\" in files\n        assert \"dep2-config.cmake\" in files\n        assert \"liba-config.cmake\" not in files\n        assert \"libb-config.cmake\" not in files\n        assert \"conanbuild.bat\" not in files\n        assert \"conanbuild.sh\" not in files\n\n    def test_conanfilews_custom(self):\n        c = TestClient()\n        conanfilews = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan import Workspace\n\n            class MyWs(ConanFile):\n                settings = \"arch\", \"build_type\"\n                generators = \"MSBuildDeps\"\n\n                def generate(self):\n                    self.run(\"echo myhello world!!!!\")\n\n            class Ws(Workspace):\n                def root_conanfile(self):\n                    return MyWs\n            \"\"\")\n\n        c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\"),\n                \"conanws.py\": conanfilews})\n        c.run(\"workspace add dep\")\n        c.run(\"workspace super-install -of=build\")\n        assert \"myhello world!!!!\" in c.out\n        files = os.listdir(os.path.join(c.current_folder, \"build\"))\n        assert \"conandeps.props\" in files\n\n    def test_conanfilews_errors(self):\n        c = TestClient()\n        conanfilews = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan import Workspace\n            class MyWs(ConanFile):\n                requires = \"dep/0.1\"\n\n            class Ws(Workspace):\n                def root_conanfile(self):\n                    return MyWs\n            \"\"\")\n\n        c.save({\"conanws.yml\": \"conanfilews: myconanfilews.py\",\n                \"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\"),\n                \"conanws.py\": conanfilews})\n        c.run(\"workspace super-install\", assert_error=True)\n        assert \"ERROR: There are no selected packages defined in the workspace\" in c.out\n        c.run(\"workspace add dep\")\n        c.run(\"workspace super-install\", assert_error=True)\n        assert \"ERROR: Conanfile in conanws.py shouldn't have 'requires'\" in c.out\n\n    def test_install_partial(self):\n        # If we want to install only some part of the workspace\n        c = TestClient()\n        c.save({\"dep/conanfile.py\": GenConanfile()})\n        c.run(\"create dep --name=dep1 --version=0.1\")\n        c.run(\"create dep --name=dep2 --version=0.1\")\n        c.save({\"conanws.yml\": \"\",\n                \"liba/conanfile.py\": GenConanfile(\"liba\", \"0.1\").with_requires(\"dep1/0.1\"),\n                \"libb/conanfile.py\": GenConanfile(\"libb\", \"0.1\").with_requires(\"liba/0.1\"),\n                \"libc/conanfile.py\": GenConanfile(\"libc\", \"0.1\").with_requires(\"libb/0.1\",\n                                                                               \"dep2/0.1\")},\n               clean_first=True)\n        c.run(\"workspace add liba\")\n        c.run(\"workspace add libb\")\n        c.run(\"workspace add libc\")\n        for arg in (\"--pkg=libb/*\", \"--pkg=libb/* --pkg=liba/*\"):\n            c.run(f\"workspace super-install {arg} -g CMakeDeps -of=build\")\n            assert \"dep1/0.1\" in c.out\n            assert \"dep2/0.1\" not in c.out\n            assert \"libc/0.1\" not in c.out\n            files = os.listdir(os.path.join(c.current_folder, \"build\"))\n            assert \"dep1-config.cmake\" in files\n            assert \"dep2-config.cmake\" not in files\n\n    def test_workspace_options(self):\n        c = TestClient()\n        conanfilews = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan import Workspace\n            class MyWs(ConanFile):\n                settings = \"arch\", \"build_type\"\n                options = {\"myoption\": [1, 2, 3]}\n                def generate(self):\n                    self.output.info(f\"Generating with my option {self.options.myoption}!!!!\")\n\n            class Ws(Workspace):\n                def root_conanfile(self):\n                    return MyWs\n            \"\"\")\n\n        c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\"),\n                \"conanws.py\": conanfilews})\n        c.run(\"workspace add dep\")\n        c.run(\"workspace super-install -of=build\")\n        assert \"conanws.py base project Conanfile: Generating with my option None!!!!\" in c.out\n        c.run(\"workspace super-install -of=build -o *:myoption=1\")\n        assert \"conanws.py base project Conanfile: Generating with my option 1!!!!\" in c.out\n\n    def test_workspace_common_shared_options(self):\n        c = TestClient()\n        conanfilews = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan import Workspace\n            class MyWs(ConanFile):\n                settings = \"os\"\n                options = {\"shared\": [True, False],\n                           \"fPIC\": [True, False]}\n                default_options = {\"shared\": False, \"fPIC\": True}\n                implements = \"auto_shared_fpic\"\n\n                def generate(self):\n                    self.output.info(f\"OS={self.settings.os}!!!!\")\n                    self.output.info(f\"shared={self.options.shared}!!!!\")\n                    self.output.info(f\"fPIC={self.options.get_safe('fPIC')}!!!!\")\n\n            class Ws(Workspace):\n                def root_conanfile(self):\n                    return MyWs\n            \"\"\")\n\n        c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\"),\n                \"conanws.py\": conanfilews})\n        c.run(\"workspace add dep\")\n        c.run(\"workspace super-install -of=build -s os=Windows\")\n        assert \"conanws.py base project Conanfile: OS=Windows!!!!\" in c.out\n        assert \"conanws.py base project Conanfile: shared=False!!!!\" in c.out\n        assert \"conanws.py base project Conanfile: fPIC=None!!!!\" in c.out\n        c.run(\"workspace super-install -of=build -s os=Linux -o *:shared=True\")\n        assert \"conanws.py base project Conanfile: OS=Linux!!!!\" in c.out\n        assert \"conanws.py base project Conanfile: shared=True!!!!\" in c.out\n        assert \"conanws.py base project Conanfile: fPIC=None!!!!\" in c.out\n        c.run(\"workspace super-install -of=build -s os=Linux -o *:shared=False\")\n        assert \"conanws.py base project Conanfile: OS=Linux!!!!\" in c.out\n        assert \"conanws.py base project Conanfile: shared=False!!!!\" in c.out\n        assert \"conanws.py base project Conanfile: fPIC=True!!!!\" in c.out\n\n    def test_workspace_pkg_options(self):\n        c = TestClient()\n        conanfilews = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan import Workspace\n\n            class MyWs(ConanFile):\n                settings = \"arch\", \"build_type\"\n                def generate(self):\n                    for pkg, dep in self.workspace_packages.items():\n                        for k, v in dep.options.items():\n                            self.output.info(f\"Generating with opt {pkg}:{k}={v}!!!!\")\n\n            class Ws(Workspace):\n                def root_conanfile(self):\n                    return MyWs\n            \"\"\")\n\n        c.save({\"dep/conanfile.py\": GenConanfile(\"dep\", \"0.1\").with_option(\"myoption\", [1, 2, 3]),\n                \"conanws.py\": conanfilews})\n        c.run(\"workspace add dep\")\n        c.run(\"workspace super-install -of=build\")\n        assert \"project Conanfile: Generating with opt dep/0.1:myoption=None!!!!\" in c.out\n        c.run(\"workspace super-install -of=build -o *:myoption=1\")\n        assert \"project Conanfile: Generating with opt dep/0.1:myoption=1!!!!\" in c.out\n\n    def test_workspace_pkg_definitions(self):\n        c = TestClient()\n        conanfilews = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan import Workspace\n            from conan.tools.cmake import CMakeToolchain\n\n            class MyWs(ConanFile):\n                settings = \"arch\", \"build_type\"\n                def generate(self):\n                    tc = CMakeToolchain(self)\n                    for ref, dep in self.workspace_packages.items():\n                        dep.configure_toolchain(tc)\n                    tc.generate()\n\n            class Ws(Workspace):\n                def root_conanfile(self):\n                    return MyWs\n            \"\"\")\n        dep = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Dep(ConanFile):\n                name = \"dep\"\n                version = \"1.2.3\"\n\n                def configure_toolchain(self, tc):\n                    tc.preprocessor_definitions[\"DEP_SOME_DEFINITION\"] = self.version\n\n                def generate(self):\n                    tc = CMakeToolchain(self)\n                    self.configure_toolchain(tc)\n                    tc.generate()\n            \"\"\")\n        pkg = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Dep(ConanFile):\n                name = \"pkg\"\n                version = \"2.3.4\"\n\n                def configure_toolchain(self, tc):\n                    tc.preprocessor_definitions[\"SOME_PKG_DEFINE\"] = self.version\n\n                def generate(self):\n                    tc = CMakeToolchain(self)\n                    self.configure_toolchain(tc)\n                    tc.generate()\n            \"\"\")\n        c.save({\"dep/conanfile.py\": dep,\n                \"pkg/conanfile.py\": pkg,\n                \"conanws.py\": conanfilews})\n        c.run(\"workspace add dep\")\n        c.run(\"workspace add pkg\")\n        c.run(\"workspace super-install\")\n        tc = c.load(\"conan_toolchain.cmake\")\n        assert 'add_compile_definitions(\"SOME_PKG_DEFINE=2.3.4\")' in tc\n        assert 'add_compile_definitions(\"DEP_SOME_DEFINITION=1.2.3\")' in tc\n\n    def test_intermediate_non_editable(self):\n        c = TestClient(light=True)\n\n        c.save({\"liba/conanfile.py\": GenConanfile(\"liba\", \"0.1\"),\n                \"libb/conanfile.py\": GenConanfile(\"libb\", \"0.1\").with_requires(\"liba/0.1\"),\n                \"libc/conanfile.py\": GenConanfile(\"libc\", \"0.1\").with_requires(\"libb/0.1\")})\n\n        c.run(\"workspace init\")\n        c.run(\"workspace add liba\")\n        c.run(\"export libb\")\n        c.run(\"workspace add libc\")\n        c.run(\"workspace super-install\", assert_error=True)\n        assert (\"Workspace definition error. Package libb/0.1 in the Conan cache \"\n                \"has dependencies to packages in the workspace: [liba/0.1]\") in c.out\n\n    def test_install_create_use_lockfile(self):\n        c = TestClient()\n        c.save({\"dep/conanfile.py\": GenConanfile(),\n                \"ws/conanws.yml\": \"\",\n                \"ws/liba/conanfile.py\": GenConanfile(\"liba\").with_requires(\"dep1/[*]\", \"dep2/[*]\"),\n                \"ws/libb/conanfile.py\": GenConanfile(\"libb\").with_requires(\"liba/[*]\", \"dep1/[*]\")},\n               )\n        c.run(\"create dep --name=dep1 --version=0.1\")\n        c.run(\"create dep --name=dep2 --version=0.1\")\n        with c.chdir(\"ws\"):\n            c.run(\"workspace add liba --version=0.1\")\n            c.run(\"workspace add libb --version=0.1\")\n            c.run(\"workspace super-install --lockfile-out=ws.lock\")\n            lock = json.loads(c.load(\"ws.lock\"))\n        refs = [RecipeReference.loads(r).repr_notime() for r in lock[\"requires\"]]\n        # Liba and libb are NOT in the lockfile for this\n        assert refs == ['libb/0.1',\n                        'liba/0.1',\n                        'dep2/0.1#4d670581ccb765839f2239cc8dff8fbd',\n                        'dep1/0.1#4d670581ccb765839f2239cc8dff8fbd']\n        c.run(\"create dep --name=dep1 --version=0.2\")\n        c.run(\"create dep --name=dep2 --version=0.2\")\n        with c.chdir(\"ws\"):\n            c.run(\"workspace super-install --lockfile=ws.lock\")\n            assert \"dep1/0.1\" in c.out\n            assert \"dep2/0.1\" in c.out\n            assert \"dep1/0.2\" not in c.out\n            assert \"dep2/0.2\" not in c.out\n\n            # bump the workspace versions themselves\n            c.run(\"workspace add liba --version=0.2\")\n            assert \"Workspace 'ws': WARN: Package liba already exists, updating\" in c.out\n            c.run(\"workspace add libb --version=0.2\")\n\n            c.run(\"workspace super-install --lockfile=ws.lock\", assert_error=True)\n            assert \"ERROR: Requirement 'liba/0.2' not in lockfile 'requires'\" in c.out\n\n            c.run(\"workspace super-install --lockfile=ws.lock --lockfile-partial \"\n                  \"--lockfile-clean --lockfile-out=ws2.lock\")\n            assert \"dep1/0.1\" in c.out\n            assert \"dep2/0.1\" in c.out\n            lock = json.loads(c.load(\"ws2.lock\"))\n            refs = [RecipeReference.loads(r).repr_notime() for r in lock[\"requires\"]]\n            # Liba and libb are NOT in the lockfile for this\n            assert refs == ['libb/0.2',\n                            'liba/0.2',\n                            'dep2/0.1#4d670581ccb765839f2239cc8dff8fbd',\n                            'dep1/0.1#4d670581ccb765839f2239cc8dff8fbd']\n\n    def test_deployers_json(self):\n        c = TestClient()\n        dep = textwrap.dedent(\"\"\"\n            import os\n            from conan.tools.files import save\n            from conan import ConanFile\n            class Dep(ConanFile):\n                name = \"dep\"\n                version = \"1.0\"\n\n                def package(self):\n                    save(self, os.path.join(self.package_folder, \"myfile.txt\"), \"content\")\n            \"\"\")\n        pkg = textwrap.dedent(\"\"\"\n            import os\n            from conan.tools.files import save\n            from conan import ConanFile\n            class Dep(ConanFile):\n                name = \"pkg\"\n                version = \"1.0\"\n                requires = \"dep/1.0\"\n\n                def package(self):\n                    save(self, os.path.join(self.package_folder, \"myfile.txt\"), \"content\")\n            \"\"\")\n        c.save({\"dep/conanfile.py\": dep,\n                \"pkg/conanfile.py\": pkg})\n        c.run(\"workspace init\")\n        c.run(\"create dep\")\n        c.run(\"workspace add pkg\")\n        c.run(\"workspace super-install --format=json --deployer=full_deploy\")\n        graph = json.loads(c.stdout)\n        # Only 1 node, pkg is not a node in the graph!\n        assert graph[\"graph\"][\"nodes\"][\"1\"][\"name\"] == \"dep\"\n        deploy_folder = os.path.join(c.current_folder, \"full_deploy\", \"host\")\n        folders = os.listdir(deploy_folder)\n        assert \"dep\" in folders\n        assert \"pkg\" not in folders\n        assert os.path.isfile(os.path.join(deploy_folder, \"dep\", \"1.0\", \"myfile.txt\"))\n\n    def test_customize_generator_per_package(self):\n        # https://github.com/conan-io/conan/issues/19326\n        c = TestClient(light=True)\n\n        pkg = GenConanfile(\"pkg\", \"0.1\")\n        workspace = textwrap.dedent(\"\"\"\\\n            from conan import Workspace, ConanFile\n\n            class MyWs(ConanFile):\n                pass\n\n            class Ws(Workspace):\n                def root_conanfile(self):\n                    return MyWs\n           \"\"\")\n        c.save({\"pkg/conanfile.py\": pkg,\n                \"conanws.py\": workspace})\n        c.run(\"workspace add pkg\")\n        c.run(\"workspace super-install -c acme*:tools.cmake.cmaketoolchain:generator=Ninja\")\n        # It no longer crashes\n        assert \"Install finished successfully\" in c.out\n\n\ndef test_workspace_with_local_recipes_index():\n    c3i_folder = temp_folder()\n    recipes_folder = os.path.join(c3i_folder, \"recipes\")\n    zlib_config = textwrap.dedent(\"\"\"\n       versions:\n         \"1.2.11\":\n           folder: all\n       \"\"\")\n    save_files(recipes_folder, {\"zlib/config.yml\": zlib_config,\n                                \"zlib/all/conanfile.py\": str(GenConanfile(\"zlib\")),\n                                \"zlib/all/conandata.yml\": \"\"})\n\n    c = TestClient(light=True)\n    c.save({\".conanrc\": 'conan_home=deps\\n'})\n    c.run(f'remote add local \"{c3i_folder}\"')\n\n    c.run(\"list zlib/1.2.11#* -r=local\")\n    assert \"zlib/1.2.11\" in c.out  # It doesn't crash\n    c.run(\"list zlib/1.2.11#*\")\n    assert \"zlib/1.2.11\" not in c.out\n\n\nclass TestClean:\n    def test_clean(self):\n        # Using cmake_layout, we can clean the build folders\n        c = TestClient()\n        c.save({\"conanws.yml\": \"name: my_workspace\"})\n        pkga = GenConanfile(\"pkga\", \"0.1\").with_settings(\"build_type\")\n        pkgb = GenConanfile(\"pkgb\", \"0.1\").with_requires(\"pkga/0.1\").with_settings(\"build_type\")\n        c.save({\"pkga/conanfile.py\": pkga,\n                \"pkgb/conanfile.py\": pkgb,\n                \"pkgc/conanfile.py\": GenConanfile(\"pkgc\", \"0.1\").with_requires(\"pkgb/0.1\")})\n        c.run(\"workspace add pkga -of=build/pkga\")\n        c.run(\"workspace add pkgb -of=build/pkgb\")\n        c.run(\"workspace add pkgc\")\n        c.run(\"workspace build\")\n        assert os.path.exists(os.path.join(c.current_folder, \"build\", \"pkga\"))\n        assert os.path.exists(os.path.join(c.current_folder, \"build\", \"pkgb\"))\n        c.run(\"workspace clean\")\n        assert \"Workspace 'my_workspace': Removing pkga/0.1 output folder\" in c.out\n        assert \"Workspace 'my_workspace': Removing pkgb/0.1 output folder\" in c.out\n        assert \"Editable pkgc/0.1 doesn't have an output_folder defined\" in c.out\n        assert not os.path.exists(os.path.join(c.current_folder, \"build\", \"pkga\"))\n        assert not os.path.exists(os.path.join(c.current_folder, \"build\", \"pkgb\"))\n\n    def test_custom_clean(self):\n        conanfilews = textwrap.dedent(\"\"\"\n            from conan import Workspace\n\n            class Ws(Workspace):\n                def name(self):\n                    return \"my_workspace\"\n                def clean(self):\n                    self.output.info(\"MY CLEAN!!!!\")\n            \"\"\")\n        c = TestClient()\n        c.save({\"conanws.py\": conanfilews})\n        c.run(\"workspace clean\")\n        assert \"Workspace 'my_workspace': MY CLEAN!!!\" in c.out\n\n\ndef test_relative_paths():\n    # This is using the meta-project\n    c = TestClient()\n    c.run(\"new cmake_lib -d name=liba --output=liba\")\n    c.run(\"new cmake_exe -d name=app1 -d requires=liba/0.1 --output=app1\")\n    c.run(\"new cmake_lib -d name=libb --output=other/libb\")\n    c.run(\"new cmake_exe -d name=app2 -d requires=libb/0.1 --output=other/app2\")\n    c.run(\"workspace init mywks\")\n    c.run(\"workspace init otherwks\")\n    # cd mywks\n    with c.chdir(\"mywks\"):\n        c.run(\"workspace add ../liba\")\n        c.run(\"workspace add ../app1\")\n        c.run(\"workspace info\")\n        expected = textwrap.dedent(\"\"\"\\\n        packages\n          - path: ../liba\n            ref: liba/0.1\n          - path: ../app1\n            ref: app1/0.1\n        \"\"\")\n        assert expected in c.out\n        c.run(\"graph info --requires=app1/0.1\")\n        c.assert_listed_require({\"app1/0.1\": \"Editable\", \"liba/0.1\": \"Editable\"})\n    # cd otherwks\n    with c.chdir(\"otherwks\"):\n        c.run(\"workspace add ../other/libb\")\n        c.run(\"workspace add ../other/app2\")\n        c.run(\"workspace info\")\n        expected = textwrap.dedent(\"\"\"\\\n        packages\n          - path: ../other/libb\n            ref: libb/0.1\n          - path: ../other/app2\n            ref: app2/0.1\n        \"\"\")\n        assert expected in c.out\n        c.run(\"graph info --requires=app2/0.1\")\n        c.assert_listed_require({\"app2/0.1\": \"Editable\", \"libb/0.1\": \"Editable\"})\n\n\ndef test_host_build_require():\n    c = TestClient()\n    protobuf = textwrap.dedent(\"\"\"\\\n        from conan import ConanFile\n        from conan.tools.files import save, copy\n        class Protobuf(ConanFile):\n            name = \"protobuf\"\n            version = \"0.1\"\n            settings = \"os\"\n\n            def layout(self):\n                self.folders.build = f\"mybuild/folder_{self.settings.os}\"\n                self.cpp.build.bindirs = [\".\"]\n\n            def build(self):\n                save(self, \"myprotobuf.txt\", f\"MYOS={self.settings.os}!!!\")\n\n            def package(self):\n                copy(self, \"myprotobuf.txt\", src=self.build_folder, dst=self.package_folder)\n\n            def package_info(self):\n                self.cpp_info.bindirs = [\".\"]\n        \"\"\")\n    app = textwrap.dedent(\"\"\"\\\n        import os\n        from conan import ConanFile\n        from conan.tools.files import load\n        class Protobuf(ConanFile):\n            name = \"app\"\n            version = \"0.1\"\n            requires = \"protobuf/0.1\"\n            tool_requires = \"protobuf/0.1\"\n\n            def build(self):\n                binhost = self.dependencies.host[\"protobuf\"].cpp_info.bindir\n                binbuild = self.dependencies.build[\"protobuf\"].cpp_info.bindir\n                host = load(self, os.path.join(binhost, \"myprotobuf.txt\"))\n                build = load(self, os.path.join(binbuild, \"myprotobuf.txt\"))\n                self.output.info(f\"BUILDING WITH BINHOST: {host}\")\n                self.output.info(f\"BUILDING WITH BINBUILD: {build}\")\n        \"\"\")\n    c.save({\"protobuf/conanfile.py\": protobuf,\n            \"app/conanfile.py\": app})\n    c.run(\"workspace init .\")\n    c.run(\"workspace add protobuf\")\n    c.run(\"workspace add app\")\n    c.run(\"install app --build=editable -s:b os=Linux -s:h os=Windows\")\n\n    assert c.load(\"protobuf/mybuild/folder_Linux/myprotobuf.txt\") == \"MYOS=Linux!!!\"\n    assert c.load(\"protobuf/mybuild/folder_Windows/myprotobuf.txt\") == \"MYOS=Windows!!!\"\n\n    shutil.rmtree(os.path.join(c.current_folder, \"protobuf\", \"mybuild\"))\n    assert not os.path.exists(os.path.join(c.current_folder, \"protobuf\", \"mybuild\"))\n    c.run(\"workspace build -s:b os=Linux -s:h os=Windows\")\n    assert \"conanfile.py (app/0.1): BUILDING WITH BINHOST: MYOS=Windows!!!\" in c.out\n    assert \"conanfile.py (app/0.1): BUILDING WITH BINBUILD: MYOS=Linux!!!\" in c.out\n    assert c.load(\"protobuf/mybuild/folder_Linux/myprotobuf.txt\") == \"MYOS=Linux!!!\"\n    assert c.load(\"protobuf/mybuild/folder_Windows/myprotobuf.txt\") == \"MYOS=Windows!!!\"\n\n    shutil.rmtree(os.path.join(c.current_folder, \"protobuf\", \"mybuild\"))\n    assert not os.path.exists(os.path.join(c.current_folder, \"protobuf\", \"mybuild\"))\n    c.run(\"workspace create -s:b os=Linux -s:h os=Windows\")\n    assert \"app/0.1: BUILDING WITH BINHOST: MYOS=Windows!!!\" in c.out\n    assert \"app/0.1: BUILDING WITH BINBUILD: MYOS=Linux!!!\" in c.out\n\n\nclass TestCreate:\n    def test_create(self):\n        c = TestClient(light=True, default_server_user=True)\n        c.save({\"conanfile.py\": GenConanfile(\"zlib\", \"0.1\").with_build_msg(\"BUILD ZLIB!\")})\n        c.run(\"export .\")\n        c.save({\"conanws.yml\": \"\"}, clean_first=True)\n        c.save({\"pkga/conanfile.py\": GenConanfile(\"pkga\", \"0.1\").with_requires(\"zlib/0.1\")\n                                                                .with_build_msg(\"BUILD PKGA!\"),\n                \"pkga/test_package/conanfile.py\": GenConanfile().with_test(\"pass\"),\n                \"pkgb/conanfile.py\": GenConanfile(\"pkgb\", \"0.1\").with_build_msg(\"BUILD PKGB!\")\n               .with_requires(\"pkga/0.1\"),\n                \"pkgb/test_package/conanfile.py\": GenConanfile().with_test(\"pass\"),\n                \"pkgc/conanfile.py\": GenConanfile(\"pkgc\", \"0.1\").with_build_msg(\"BUILD PKGC!\")\n               .with_requires(\"pkgb/0.1\"),\n                \"pkgc/test_package/conanfile.py\": GenConanfile().with_test(\"pass\"),\n                })\n        c.run(\"workspace add pkga\")\n        c.run(\"workspace add pkgb\")\n        c.run(\"workspace add pkgc\")\n        c.run(\"workspace create --build=zlib/*\")\n        assert str(c.out).count(\"zlib/0.1: WARN: BUILD ZLIB!\") == 1\n        assert str(c.out).count(\"pkga/0.1: WARN: BUILD PKGA!\") == 1\n        assert str(c.out).count(\"pkgb/0.1: WARN: BUILD PKGB!\") == 1\n        assert str(c.out).count(\"pkgc/0.1: WARN: BUILD PKGC!\") == 1\n        assert \"pkga/0.1 (test package): Running test()\" in c.out\n        assert \"pkgb/0.1 (test package): Running test()\" in c.out\n        assert \"pkgc/0.1 (test package): Running test()\" in c.out\n\n        # A second conan workspace create will not re-build\n        c.run(\"workspace create\")\n        assert \"WARN: BUILD ZLIB!\" not in c.out\n        assert \"WARN: BUILD PKGA!\" not in c.out\n        assert \"WARN: BUILD PKGB!\" not in c.out\n        assert \"WARN: BUILD PKBC!\" not in c.out\n        assert \"pkga/0.1 (test package): Running test()\" not in c.out\n        assert \"pkgb/0.1 (test package): Running test()\" not in c.out\n        assert \"pkgc/0.1 (test package): Running test()\" not in c.out\n\n        c.run(\"upload zlib/* -r=default -c\")\n        c.run(\"remove zlib/* -c\")\n        c.run(\"remove pkgc/* -c\")\n        c.run(\"workspace create\")\n        assert \"WARN: BUILD ZLIB!\" not in c.out\n        assert \"pkgc/0.1: WARN: BUILD PKGC!\" in c.out\n\n    def test_create_dynamic_name(self):\n        workspace = textwrap.dedent(\"\"\"\\\n            import os\n            from conan import Workspace\n\n            class MyWorkspace(Workspace):\n                def packages(self):\n                    result = []\n                    for f in os.listdir(self.folder):\n                        if os.path.isdir(os.path.join(self.folder, f)):\n                            result.append({\"path\": f, \"ref\": f\"{f}/0.1\"})\n                    return result\n           \"\"\")\n        c = TestClient(light=True)\n        c.save({\"conanws.py\": workspace,\n                \"pkga/conanfile.py\": GenConanfile()})\n        c.run(\"workspace info\")\n        assert \"pkga/0.1\" in c.out\n        c.run(\"workspace create\")\n        assert \"Workspace create pkga/0.1\" in c.out\n\n    def test_host_build_require(self):\n        c = TestClient()\n        protobuf = textwrap.dedent(\"\"\"\\\n            from conan import ConanFile\n            class Protobuf(ConanFile):\n                name = \"protobuf\"\n                version = \"0.1\"\n                settings = \"os\"\n\n                def build(self):\n                    self.output.info(f\"Building for: {self.settings.os}!!!\")\n            \"\"\")\n        app = textwrap.dedent(\"\"\"\\\n            from conan import ConanFile\n            class Protobuf(ConanFile):\n                name = \"app\"\n                version = \"0.1\"\n                requires = \"protobuf/0.1\"\n                tool_requires = \"protobuf/0.1\"\n            \"\"\")\n        c.save({\"protobuf/conanfile.py\": protobuf,\n                \"app/conanfile.py\": app})\n        c.run(\"workspace init .\")\n        c.run(\"workspace add protobuf\")\n        c.run(\"workspace add app\")\n\n        c.run(\"workspace create -s:b os=Linux -s:h os=Windows\")\n\n        assert \"protobuf/0.1: Building for: Windows!!!\" in c.out\n        assert \"protobuf/0.1: Building for: Linux!!!\" in c.out\n\n\nclass TestSource:\n    def test_source(self):\n        c = TestClient(light=True)\n        c.save({\"conanws.yml\": \"\"})\n\n        pkga = textwrap.dedent(\"\"\"\\\n            from conan import ConanFile\n            class TestPackage(ConanFile):\n                name = \"pkga\"\n                version = \"0.1\"\n                def source(self):\n                    self.output.info(\"Executing SOURCE!!!\")\n            \"\"\")\n        pkgb = textwrap.dedent(\"\"\"\\\n            from conan import ConanFile\n            class TestPackage(ConanFile):\n                name = \"pkgb\"\n                version = \"0.1\"\n                requires = \"pkga/0.1\"\n                def source(self):\n                    self.output.info(\"Executing SOURCE!!!\")\n            \"\"\")\n        pkgc = textwrap.dedent(\"\"\"\\\n            from conan import ConanFile\n            class TestPackage(ConanFile):\n                name = \"pkgc\"\n                version = \"0.1\"\n                requires = \"pkgb/0.1\"\n                def source(self):\n                    self.output.info(\"Executing SOURCE!!!\")\n            \"\"\")\n        c.save({\"pkga/conanfile.py\": pkga,\n                \"pkgb/conanfile.py\": pkgb,\n                \"pkgc/conanfile.py\": pkgc})\n        c.run(\"workspace add pkga\")\n        c.run(\"workspace add pkgb\")\n        c.run(\"workspace add pkgc\")\n        c.run(\"workspace source\")\n        assert \"conanfile.py (pkga/0.1): Executing SOURCE!!!\" in c.out\n        assert \"conanfile.py (pkgb/0.1): Executing SOURCE!!!\" in c.out\n        assert \"conanfile.py (pkgc/0.1): Executing SOURCE!!!\" in c.out\n\n\nclass TestInstall:\n    def test_install(self):\n        c = TestClient()\n        c.save({\"conanws.yml\": \"\"})\n\n        pkg = textwrap.dedent(\"\"\"\\\n            from conan import ConanFile\n            class Package(ConanFile):\n                name = \"{}\"\n                version = \"0.1\"\n                settings = \"os\", \"build_type\"\n                {}\n                generators = \"CMakeToolchain\"\n            \"\"\")\n\n        c.save({\"pkga/conanfile.py\": pkg.format(\"pkga\", ''),\n                \"pkgb/conanfile.py\": pkg.format(\"pkgb\", 'requires=\"pkga/0.1\"'),\n                \"pkgc/conanfile.py\": pkg.format(\"pkgc\", 'requires=\"pkgb/0.1\"')})\n        c.run(\"workspace add pkga\")\n        c.run(\"workspace add pkgb\")\n        c.run(\"workspace add pkgc\")\n        c.run(\"workspace install\")\n        assert \"conanfile.py (pkga/0.1): CMakeToolchain generated\" in c.out\n        assert \"conanfile.py (pkgb/0.1): CMakeToolchain generated\" in c.out\n        assert \"conanfile.py (pkgc/0.1): CMakeToolchain generated\" in c.out\n\n    def test_install_lockfile_out_error(self):\n        # it is not possible to generate a lockfile for an orchestrated\n        # \"conan workspace install/build\" command\n        c = TestClient()\n        c.save({\"conanws.yml\": \"\"})\n        c.run(\"workspace install --lockfile-out=conan.lock\", assert_error=True)\n        assert \"error: unrecognized arguments: --lockfile-out=conan.lock\" in c.out\n\n        c.run(\"workspace create --lockfile-out=conan.lock\", assert_error=True)\n        assert \"error: unrecognized arguments: --lockfile-out=conan.lock\" in c.out\n\n\ndef test_keep_core_conf():\n    c = TestClient()\n    myprofile = textwrap.dedent(\"\"\"\\\n        [settings]\n        os=FreeBSD\n        arch=armv7\n        \"\"\")\n    conanfile = textwrap.dedent(\"\"\"\\\n        from conan import ConanFile\n\n        class Pkg(ConanFile):\n            name = \"pkga\"\n            version = \"0.1\"\n            settings = \"os\", \"arch\"\n\n            def generate(self):\n                self.output.info(f\"Generating!: {self.settings.os}-{self.settings.arch}!!!!\")\n        \"\"\")\n    c.save_home({\"profiles/myprofile\": myprofile})\n    c.run(\"profile show \")\n    c.save({\"conanws.yml\": \"\",\n            \"pkga/conanfile.py\": conanfile})\n    c.run(\"workspace add pkga\")\n    # The injected -cc is still applied to every \"conan install\"\n    c.run(\"workspace install -cc core:default_profile=myprofile\")\n    assert \"conanfile.py (pkga/0.1): Generating!: FreeBSD-armv7!!!!\" in c.out\n    # also the global.conf\n    c.save_home({\"global.conf\": \"core:default_profile=myprofile\"})\n    c.run(\"workspace install\")\n    assert \"conanfile.py (pkga/0.1): Generating!: FreeBSD-armv7!!!!\" in c.out\n\n\ndef test_workspace_defining_only_paths():\n    c = TestClient()\n    c.run(\"new workspace\")\n    conanws_with_labels = textwrap.dedent(\"\"\"\\\n    packages:\n      - path: liba\n      - path: libb\n      - path: app1\n    \"\"\")\n    c.save({\"conanws.yml\": conanws_with_labels})\n    # liba with user and channel too\n    replace_in_file(ConanFileMock(), os.path.join(c.current_folder, \"liba\", \"conanfile.py\"),\n                    'version = \"0.1\"',\n                    'version = \"0.1\"\\n    user = \"myuser\"\\n    channel = \"mychannel\"')\n    replace_in_file(ConanFileMock(), os.path.join(c.current_folder, \"libb\", \"conanfile.py\"),\n                    'self.requires(\"liba/0.1\")',\n                    'self.requires(\"liba/0.1@myuser/mychannel\")')\n    c.run(\"workspace info\")\n    expected = textwrap.dedent(\"\"\"\\\n    packages\n      - path: liba\n      - path: libb\n      - path: app1\n    \"\"\")\n    assert expected in c.out\n    c.run(\"workspace install\")\n    assert \"conanfile.py (app1/0.1)\" in c.out\n    assert \"liba/0.1@myuser/mychannel - Editable\" in c.out\n    assert \"libb/0.1 - Editable\" in c.out\n\n    c.run(\"workspace super-install\")\n    assert \"app1/0.1 - Editable\" in c.out\n    assert \"liba/0.1@myuser/mychannel - Editable\" in c.out\n    assert \"libb/0.1 - Editable\" in c.out\n\n\ndef test_workspace_defining_duplicate_references():\n    \"\"\"\n    Testing duplicate references but different paths\n    \"\"\"\n    c = TestClient(light=True)\n    conanws_with_labels = textwrap.dedent(\"\"\"\\\n    packages:\n      - path: liba\n      - path: liba1\n      - path: liba2\n    \"\"\")\n    c.save({\n        \"conanws.yml\": conanws_with_labels,\n        \"liba/conanfile.py\": GenConanfile(name=\"liba\", version=\"0.1\"),\n        \"liba1/conanfile.py\": GenConanfile(name=\"liba\", version=\"0.1\"),\n        \"liba2/conanfile.py\": GenConanfile(name=\"liba\", version=\"0.1\"),\n    })\n    c.run(\"workspace install\", assert_error=True)\n    assert \"Workspace package 'liba/0.1' already exists.\" in c.out\n\n\ndef test_workspace_reference_error():\n    c = TestClient(light=True)\n    conanws_with_labels = textwrap.dedent(\"\"\"\\\n    packages:\n      - path: libx\n    \"\"\")\n    c.save({\"conanws.yml\": conanws_with_labels,\n            \"libx/conanfile.py\": \"\"})\n    c.run(\"workspace install\", assert_error=True)\n    assert (\"Workspace package reference could not be deduced by libx/conanfile.py or it is not\"\n            \" correctly defined in the conanws.yml file\") in c.out\n\n\ndef test_workspace_python_error():\n    c = TestClient()\n    workspace = textwrap.dedent(\"\"\"\\\n       from conan import Workspace\n\n       class MyWorkspace(Workspace):\n           def packages(self):\n               os.listdir(self.folder)\n      \"\"\")\n    c.save({\"conanws.yml\": \"\",\n            \"conanws.py\": \"bad\"})\n    c.run(\"workspace info\", assert_error=True)\n    assert \"ERROR: Error loading conanws.py at\" in c.out\n    c.save({\"conanws.yml\": \"\",\n            \"conanws.py\": workspace})\n    c.run(\"workspace info\", assert_error=True)\n    assert \"ERROR: Workspace conanws.py file: Error in packages() method, line 5\" in c.out\n"
  },
  {
    "path": "test/performance/.gitignore",
    "content": "cache/\n"
  },
  {
    "path": "test/performance/__init__.py",
    "content": ""
  },
  {
    "path": "test/performance/test_compatibility_performance.py",
    "content": "import textwrap\nimport time\n\nimport pytest\n\nfrom conan.test.utils.tools import TestClient, GenConanfile\n\nRUN_COUNT = 2\n\n\n@pytest.mark.skip(reason=\"Compatibility performance test\")\nclass TestCompatibilityPerformance:\n\n    results = []\n\n    @pytest.fixture(scope=\"module\", autouse=True)\n    def timings(self):\n        results = []\n        yield results\n\n        import matplotlib.pyplot as plt\n\n        fig = plt.figure()\n        ax = fig.add_subplot()\n\n        ax.set_title(\"Compatibility performance in real Artifactory server (last match, unoptimized)\")\n\n        #ax_tot = ax.twinx()\n\n        # Plot a basic wireframe.\n\n        grouping = {}\n        x, y, y_tot_opt, y_tot_non = [], [], [], []\n        stderr_opt, stderr_non = [], []\n        for factors, run, with_optimization, duration in results:\n            group = grouping.setdefault(factors, {\"opt\": [], \"non\": []})\n            if with_optimization:\n                group[\"opt\"].append(duration)\n            else:\n                group[\"non\"].append(duration)\n\n        def ssd(values, mean):\n            return sum((v - mean) ** 2 for v in values) / (len(values) - 1)\n\n        for factors, durations in sorted(grouping.items()):\n            x.append(factors)\n            y.append(0)\n\n            mean_opt = sum(durations[\"opt\"]) / RUN_COUNT\n            mean_non = sum(durations[\"non\"]) / RUN_COUNT\n            y_tot_opt.append(mean_opt)\n            y_tot_non.append(mean_non)\n\n            # ssd_opt = ssd(durations[\"opt\"], mean_opt)\n            # ssd_non = ssd(durations[\"non\"], mean_non)\n            # stderr_opt.append(ssd_opt / (RUN_COUNT ** 0.5))\n            # stderr_non.append(ssd_non / (RUN_COUNT ** 0.5))\n\n        max_diff_y = max(y)\n        min_diff_y = min(min(y), 0)\n        # ax_tot.set_ylim(ymin=min_diff_y-0.1*min_diff_y, ymax=max_diff_y+0.1*max_diff_y)\n\n        max_tot_y = max(max(y_tot_non), max(y_tot_opt))\n        ax.set_ylim(ymin=0, ymax=max_tot_y+0.1*max_tot_y)\n\n        ax.grid(visible=True, which=\"major\", axis=\"y\", linestyle=\"--\")\n        # ax_tot.set_xticks(x)\n\n        ax.set_xticks(x)\n        ax.plot(x, y_tot_non, 'red', marker='x', label=\"Without optimization\", linestyle=\":\")\n        # ax.errorbar(x, y_tot_non, yerr=stderr_non)\n        ax.plot(x, y_tot_opt, 'blue', marker='x', label=\"With optimization\", linestyle=\":\")\n        # ax.errorbar(x, y_tot_opt, yerr=stderr_opt)\n\n        # ax_tot.plot(x, y, 'gray', marker='o', linestyle=\"--\", label=\"Difference total\")\n        # ax_tot.set_ylabel(\"Total time diff (s)\")\n\n        ax.set_xlabel(\"Number of compatible configurations in server\")\n        ax.set_ylabel(\"Total time (s)\")\n        ax.legend(loc=\"upper left\")\n\n        # ax_tot.legend(loc=\"upper right\")\n\n        plt.show()\n\n    @pytest.mark.parametrize(\"runs\", range(RUN_COUNT))\n    @pytest.mark.parametrize(\"with_optimization\", [True, False])\n    @pytest.mark.parametrize(\"factors\", [pow(2, n) for n in range(1, 6)])\n    def test_list_only_compatibility(self, timings, with_optimization, factors, runs):\n        tc = TestClient(light=True)\n        tc.run(\"remote add default https://conandev.jfrog.io/artifactory/api/conan/abril-tests\")\n        tc.run(\"remote login default abril\")\n        tc.run(\"remove * -c -r=default\")\n        cppstds = [7 + i*3 for i in range(factors+1)]\n        compiler_settings = textwrap.dedent(f\"\"\"\n                compiler:\n                    foo:\n                        version: [1]\n                        cppstd: {cppstds}\"\"\")\n        tc.run(\"version\")\n        tc.save_home({\"settings_user.yml\": compiler_settings})\n        compat = tc.load_home(\"extensions/plugins/compatibility/compatibility.py\")\n        compat = compat.replace(\"cppstd_possible_values = supported_cppstd(conanfile)\",\n                                f\"cppstd_possible_values = {cppstds}\")\n        tc.save_home({\"extensions/plugins/compatibility/compatibility.py\": compat})\n        threshold = -1 if with_optimization else 1\n        tc.save_home({\"global.conf\": f\"user.graph:compatibility_optimization_threshold={factors + threshold}\"})\n\n        compiler_args = \"-s compiler=foo -s compiler.version=1\"\n        pkg_name = str(time.time())\n        tc.save({\"conanfile.py\": GenConanfile(pkg_name, \"0.1\").with_settings(\"compiler\")})\n\n        if with_optimization:\n            for i in range(factors-1):\n                tc.run(f\"create . {compiler_args} -s compiler.cppstd={7 + i*3} -nr\")\n        tc.run(f\"create . {compiler_args} -s compiler.cppstd={7 + (factors-1)*3} -nr\")\n\n        tc.run(\"upload * -r=default -c\")\n        tc.run(\"remove *:* -c\")\n\n        start_time = time.time()\n        tc.run(f\"install --requires={pkg_name}/0.1 {compiler_args} -s compiler.cppstd={7 + factors*3}\")\n        end_time = time.time()\n        if with_optimization:\n            assert f\"Found {factors} compatible configurations in remotes\" in tc.out\n        else:\n            assert f\"compatible configurations in remotes\" not in tc.out\n        duration = end_time - start_time\n        timings.append((factors, runs, with_optimization, duration))\n"
  },
  {
    "path": "test/performance/test_db_performance.py",
    "content": "import os\nimport time\n\nimport pytest\n\nfrom conan.api.model import RecipeReference\nfrom conan.internal.cache.db.cache_database import CacheDatabase\nfrom conan.test.utils.test_files import temp_folder\n\n\n@pytest.mark.skip(reason=\"This is a performance test, skip for normal runs\")\ndef test_db_performance():\n    f = temp_folder()\n    # f = r\"C:\\conan_tests\\tmp_o0846cmconans\\path with spaces\"\n    print(\"Tempt folder: \", f)\n    db = CacheDatabase(os.path.join(f, \"mytest.sqlite\"))\n\n    num_refs = 1000\n    splits = 10\n    for num_split in range(10):\n        init = time.time()\n        for i in range(int(num_refs / splits)):\n            index = num_split * int(num_refs / splits) + i\n            ref = RecipeReference.loads(f\"pkg/1.{index}#rev1%1\")\n            path = os.path.join(f, f\"folder{index}\")\n            db.create_recipe(path, ref)\n        creation_time = time.time() - init\n        print(f\"Creation time {num_split}:\", creation_time)\n        print(\"    Avg:\", creation_time/num_refs)\n\n    experiments = 10\n    texp = time.time()\n    for experiment in range(experiments):\n        ret = db.list_references()\n        assert len(ret) == num_refs\n    exp_time = time.time() - texp\n    print(\"SEARCH RECIPES time:\", exp_time)\n    print(\"    Avg:\", exp_time / experiments)\n\n    texp = time.time()\n    specific_ref = RecipeReference.loads(f\"pkg/1.1#rev1%1\")\n    for experiment in range(experiments):\n        db.get_recipe(specific_ref)\n    exp_time = time.time() - texp\n    print(\"GET RECIPE time:\", exp_time)\n    print(\"    Avg:\", exp_time / experiments)\n\n    texp = time.time()\n    specific_ref = RecipeReference.loads(f\"pkg/1.1#rev1%1\")\n    for experiment in range(experiments):\n        db.get_latest_recipe(specific_ref)\n    exp_time = time.time() - texp\n    print(\"GET LATEST RECIPE time:\", exp_time)\n    print(\"    Avg:\", exp_time / experiments)\n\n    texp = time.time()\n    for experiment in range(experiments):\n        db.update_recipes_lru([specific_ref])\n    exp_time = time.time() - texp\n    print(\"UPDATE LRU:\", exp_time)\n    print(\"    Avg:\", exp_time / experiments)\n\n    updates = 50\n    texp = time.time()\n    for experiment in range(experiments):\n        refs = [RecipeReference.loads(f\"pkg/1.{index}#rev1%1\") for index in range(updates)]\n        db.update_recipes_lru(refs)\n    exp_time = time.time() - texp\n    print(\"UPDATE LRU BATCH:\", exp_time)\n    print(\"    Avg:\", exp_time / experiments)\n    print(\"    Avg:\", exp_time / (experiments * updates))\n\n\n\n"
  },
  {
    "path": "test/performance/test_large_graph.py",
    "content": "import cProfile\nimport os\nimport pstats\nimport time\nfrom pstats import SortKey\nimport pytest\n\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\n\n@pytest.mark.skip(reason=\"This is a performance test, skip for normal runs\")\ndef test_large_graph():\n    c = TestClient(cache_folder=os.path.join(os.path.dirname(__file__), \"cache\"))\n    num_test = 40\n    num_pkgs = 40\n\n    \"\"\"for i in range(num_test):\n        conanfile = GenConanfile(f\"test{i}\", \"0.1\")\n        if i > 0:\n            conanfile.with_requires(f\"test{i-1}/0.1\")\n        c.save({\"conanfile.py\": conanfile})\n        c.run(\"create .\")\n\n    for i in range(num_pkgs):\n        conanfile = GenConanfile(f\"pkg{i}\", \"0.1\").with_test_requires(f\"test{num_test-1}/0.1\")\n        if i > 0:\n            conanfile.with_requires(f\"pkg{i-1}/0.1\")\n        c.save({\"conanfile.py\": conanfile})\n        c.run(\"create .\")\n\n    \"\"\"\n    t = time.time()\n    pr = cProfile.Profile()\n    pr.enable()\n    c.run(f\"install --requires=pkg{num_pkgs - 1}/0.1\")\n    pr.disable()\n    print(time.time()-t)\n\n    sortby = SortKey.CUMULATIVE\n    ps = pstats.Stats(pr).sort_stats(sortby)\n    ps.print_stats()\n\n    #graph = json.loads(c.stdout)\n    #assert len(graph[\"graph\"][\"nodes\"]) == 1 + num_pkgs + num_test * num_pkgs\n\n\n@pytest.mark.skip(reason=\"This is a performance test, skip for normal runs\")\ndef test_large_graph2():\n    c = TestClient(cache_folder=os.path.join(os.path.dirname(__file__), \"cache\"))\n    num_test = 20\n    num_pkgs = 20\n    branches = [\"a\", \"b\", \"c\"]\n\n    c.save({\"conanfile.py\": GenConanfile(\"testbase\", \"0.1\")})\n    c.run(\"export .\")\n    for i in range(num_test):\n        for branch in branches:\n            conanfile = GenConanfile(f\"test{branch}{i}\", \"0.1\")\n            if i > 0:\n                conanfile.with_requires(f\"test{branch}{i-1}/0.1\", \"testbase/0.1\")\n            else:\n                conanfile.with_requires(\"testbase/0.1\")\n            c.save({\"conanfile.py\": conanfile})\n            c.run(\"export .\")\n\n    for i in range(num_pkgs):\n        conanfile = GenConanfile(f\"pkg{i}\", \"0.1\")\n        for branch in branches:\n            conanfile.with_test_requires(f\"test{branch}{num_test-1}/0.1\")\n        if i > 0:\n            conanfile.with_requires(f\"pkg{i-1}/0.1\")\n        c.save({\"conanfile.py\": conanfile})\n        c.run(\"export .\")\n\n    t = time.time()\n    pr = cProfile.Profile()\n    pr.enable()\n    c.run(f\"graph info --requires=pkg{num_pkgs - 1}/0.1\")\n    pr.disable()\n    print(time.time()-t)\n\n    sortby = SortKey.CUMULATIVE\n    ps = pstats.Stats(pr).sort_stats(sortby)\n    ps.print_stats()\n"
  },
  {
    "path": "test/unittests/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/cli/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/cli/common_test.py",
    "content": "import os\nfrom unittest.mock import MagicMock\n\nimport pytest\n\nfrom conan.api.conan_api import ConanAPI\nfrom conan.internal.cache.home_paths import HomePaths\nfrom conan.errors import ConanException\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.internal.util.files import save\n\n\n@pytest.fixture()\ndef conan_api():\n    tmp_folder = temp_folder()\n    home_path = HomePaths(tmp_folder)\n    save(os.path.join(home_path.profiles_path, \"default\"), \"\")\n    return ConanAPI(tmp_folder)\n\n\n@pytest.fixture()\ndef argparse_args():\n    return MagicMock(\n        profile_build=None,\n        profile_host=None,\n        profile_all=None,\n        settings_build=None,\n        settings_host=None,\n        settings_all=None,\n        options_build=None,\n        options_host=None,\n        options_all=None,\n        conf_build=None,\n        conf_host=None,\n        conf_all=None,\n    )\n\n\n@pytest.mark.parametrize(\"conf_name\", [\n    \"core.doesnotexist:never\",\n    \"core:doesnotexist\"\n])\ndef test_core_confs_not_allowed_via_cli(conan_api, argparse_args, conf_name):\n    argparse_args.conf_build = [conf_name]\n    argparse_args.conf_host = [conf_name]\n\n    with pytest.raises(ConanException) as exc:\n        conan_api.profiles.get_profiles_from_args(argparse_args)\n    assert \"[conf] 'core.*' configurations are not allowed in profiles\" in str(exc.value)\n"
  },
  {
    "path": "test/unittests/cli/test_cli_ref_matching.py",
    "content": "import pytest\n\nfrom conan.api.model import ListPattern\nfrom conan.errors import ConanException\n\n\n@pytest.mark.parametrize(\"pattern, result\",\n                         [(\"*\",                  (\"*\", \"latest\", None, \"latest\")),\n                          (\"zlib/1.2.11\",        (\"zlib/1.2.11\", \"latest\", None, \"latest\")),\n                          (\"zlib/1.2.11#rev1\",   (\"zlib/1.2.11\", \"rev1\", None, \"latest\")),\n                          (\"zlib/1.2.11:pid1\",   (\"zlib/1.2.11\", \"latest\", \"pid1\", \"latest\"))])\ndef test_cli_pattern_matching(pattern, result):\n    pattern = ListPattern(pattern)\n    assert result == (pattern.ref, pattern.rrev, pattern.package_id, pattern.prev)\n\n\ndef test_list_pattern():\n    with pytest.raises(ConanException) as e:\n        ListPattern(\"*:*\", only_recipe=True)\n    assert \"Do not specify 'package_id' with 'only-recipe'\" in str(e.value)\n"
  },
  {
    "path": "test/unittests/client/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/client/build/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/client/build/c_std_flags_test.py",
    "content": "from conan.internal.api.detect.detect_api import default_cstd\nfrom conan.internal.model.version import Version\nfrom conan.test.utils.mocks import ConanFileMock, MockSettings\nfrom conan.tools.build.flags import cstd_flag\n\n\ndef _make_cstd_flag(compiler, compiler_version, cstd=None):\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\"compiler\": compiler,\n                                       \"compiler.version\": compiler_version,\n                                       \"compiler.cstd\": cstd})\n    return cstd_flag(conanfile)\n\n\ndef test_gcc_cstd_flags():\n    assert _make_cstd_flag(\"gcc\", \"4.2\", \"99\") == \"-std=c99\"\n    assert _make_cstd_flag(\"clang\", \"4.2\", \"99\") == \"-std=c99\"\n    assert _make_cstd_flag(\"apple-clang\", \"4.2\", \"99\") == \"-std=c99\"\n    assert _make_cstd_flag(\"msvc\", \"192\", \"11\") == \"/std:c11\"\n    assert _make_cstd_flag(\"msvc\", \"192\", \"17\") == \"/std:c17\"\n    assert _make_cstd_flag(\"msvc\", \"191\", \"11\") is None\n    assert _make_cstd_flag(\"msvc\", \"191\", \"17\") is None\n\n\ndef _make_cstd_default(compiler, compiler_version):\n    return default_cstd(compiler, Version(compiler_version))\n\n\ndef test_gcc_cstd_defaults():\n    assert _make_cstd_default(\"gcc\", \"4\") == \"gnu99\"\n    assert _make_cstd_default(\"gcc\", \"5\") == \"gnu11\"\n    assert _make_cstd_default(\"gcc\", \"6\") == \"gnu11\"\n    assert _make_cstd_default(\"gcc\", \"6.1\") == \"gnu11\"\n    assert _make_cstd_default(\"gcc\", \"7.3\") == \"gnu11\"\n    assert _make_cstd_default(\"gcc\", \"8.1\") == \"gnu17\"\n    assert _make_cstd_default(\"gcc\", \"11\") == \"gnu17\"\n    assert _make_cstd_default(\"gcc\", \"11.1\") == \"gnu17\"\n    assert _make_cstd_default(\"gcc\", \"15.1\") == \"gnu23\"\n\n\ndef test_clang_cstd_defaults():\n    assert _make_cstd_default(\"clang\", \"2\") == \"gnu99\"\n    assert _make_cstd_default(\"clang\", \"2.1\") == \"gnu99\"\n    assert _make_cstd_default(\"clang\", \"3.0\") == \"gnu99\"\n    assert _make_cstd_default(\"clang\", \"3.1\") == \"gnu99\"\n    assert _make_cstd_default(\"clang\", \"3.4\") == \"gnu99\"\n    assert _make_cstd_default(\"clang\", \"3.5\") == \"gnu99\"\n    assert _make_cstd_default(\"clang\", \"5\") == \"gnu11\"\n    assert _make_cstd_default(\"clang\", \"5.1\") == \"gnu11\"\n    assert _make_cstd_default(\"clang\", \"6\") == \"gnu11\"\n    assert _make_cstd_default(\"clang\", \"7\") == \"gnu11\"\n    assert _make_cstd_default(\"clang\", \"8\") == \"gnu11\"\n    assert _make_cstd_default(\"clang\", \"9\") == \"gnu11\"\n    assert _make_cstd_default(\"clang\", \"10\") == \"gnu11\"\n    assert _make_cstd_default(\"clang\", \"11\") == \"gnu17\"\n    assert _make_cstd_default(\"clang\", \"12\") == \"gnu17\"\n    assert _make_cstd_default(\"clang\", \"13\") == \"gnu17\"\n    assert _make_cstd_default(\"clang\", \"14\") == \"gnu17\"\n    assert _make_cstd_default(\"clang\", \"15\") == \"gnu17\"\n    assert _make_cstd_default(\"clang\", \"16\") == \"gnu17\"\n    assert _make_cstd_default(\"clang\", \"17\") == \"gnu17\"\n    assert _make_cstd_default(\"clang\", \"18\") == \"gnu17\"\n    assert _make_cstd_default(\"clang\", \"19\") == \"gnu17\"\n    assert _make_cstd_default(\"clang\", \"20\"), \"gnu17\"\n\n\ndef test_apple_clang_cppstd_defaults():\n    assert _make_cstd_default(\"apple-clang\", \"9\") == \"gnu99\"\n    assert _make_cstd_default(\"apple-clang\", \"10\") == \"gnu11\"\n    assert _make_cstd_default(\"apple-clang\", \"11\") == \"gnu11\"\n    assert _make_cstd_default(\"apple-clang\", \"12\") == \"gnu17\"\n    assert _make_cstd_default(\"apple-clang\", \"13\") == \"gnu17\"\n    assert _make_cstd_default(\"apple-clang\", \"14\") == \"gnu17\"\n    assert _make_cstd_default(\"apple-clang\", \"15\") == \"gnu17\"\n"
  },
  {
    "path": "test/unittests/client/build/compiler_flags_test.py",
    "content": "import pytest\n\nfrom conan.tools.build import default_cppstd, default_cstd\nfrom conan.tools.build.flags import architecture_flag, build_type_flags, threads_flags\nfrom conan.test.utils.mocks import MockSettings, ConanFileMock\n\n\nclass TestCompilerFlags:\n\n    @pytest.mark.parametrize(\"compiler,arch,the_os,flag\",\n                             [(\"gcc\", \"x86\", None, \"-m32\"),\n                              (\"clang\", \"x86\", None, \"-m32\"),\n                              (\"sun-cc\", \"x86\", None, \"-m32\"),\n                              (\"gcc\", \"x86_64\", None, \"-m64\"),\n                              (\"clang\", \"x86_64\", None, \"-m64\"),\n                              (\"sun-cc\", \"x86_64\", None, \"-m64\"),\n                              (\"sun-cc\", \"sparc\", None, \"-m32\"),\n                              (\"sun-cc\", \"sparcv9\", None, \"-m64\"),\n                              (\"gcc\", \"armv7\", None, \"\"),\n                              (\"clang\", \"armv7\", None, \"\"),\n                              (\"sun-cc\", \"armv7\", None, \"\"),\n                              (\"gcc\", \"s390\", None, \"-m31\"),\n                              (\"clang\", \"s390\", None, \"-m31\"),\n                              (\"sun-cc\", \"s390\", None, \"-m31\"),\n                              (\"gcc\", \"s390x\", None, \"-m64\"),\n                              (\"clang\", \"s390x\", None, \"-m64\"),\n                              (\"sun-cc\", \"s390x\", None, \"-m64\"),\n                              (\"msvc\", \"x86\", None, \"\"),\n                              (\"msvc\", \"x86_64\", None, \"\"),\n                              (\"gcc\", \"ppc32\", \"AIX\", \"-maix32\"),\n                              (\"gcc\", \"ppc64\", \"AIX\", \"-maix64\"),\n                              ])\n    def test_arch_flag(self, compiler, arch, the_os, flag):\n        settings = MockSettings({\"compiler\": compiler,\n                                 \"arch\": arch,\n                                 \"os\": the_os})\n        conanfile = ConanFileMock()\n        conanfile.settings = settings\n        assert architecture_flag(conanfile) == flag\n\n    @pytest.mark.parametrize(\"compiler,threads,flag\",\n                             [(\"clang\", None, []),\n                              (\"emcc\", None, []),\n                              (\"emcc\", \"posix\", [\"-pthread\"]),\n                              (\"emcc\", \"wasm_workers\", [\"-sWASM_WORKERS=1\"]),\n                              ])\n    def test_threads_flag(self, compiler, threads, flag):\n        settings = MockSettings({\"compiler\": compiler,\n                                 \"compiler.threads\": threads})\n        conanfile = ConanFileMock()\n        conanfile.settings = settings\n        assert threads_flags(conanfile) == flag\n\n    @pytest.mark.parametrize(\"compiler,arch,the_os,flag\",\n                             [(\"clang\", \"x86\", \"Windows\", \"\"),\n                              (\"clang\", \"x86_64\", \"Windows\", \"\")\n                             ])\n    def test_arch_flag_clangcl(self,  compiler, arch, the_os, flag):\n        settings = MockSettings({\"compiler\": compiler,\n                                 \"arch\": arch,\n                                 \"os\": the_os})\n        conanfile = ConanFileMock()\n        conanfile.conf.define(\"tools.build:compiler_executables\", {\"c\": \"clang-cl\"})\n        conanfile.settings = settings\n        assert architecture_flag(conanfile) == flag\n\n    def test_catalyst(self):\n        settings = MockSettings({\"compiler\": \"apple-clang\",\n                                 \"arch\": \"x86_64\",\n                                 \"os\": \"Macos\",\n                                 \"os.subsystem\": \"catalyst\",\n                                 \"os.subsystem.ios_version\": \"13.1\"})\n        conanfile = ConanFileMock()\n        conanfile.settings = settings\n        assert architecture_flag(conanfile) == \"--target=x86_64-apple-ios13.1-macabi\"\n\n        settings = MockSettings({\"compiler\": \"apple-clang\",\n                                 \"arch\": \"armv8\",\n                                 \"os\": \"Macos\",\n                                 \"os.subsystem\": \"catalyst\",\n                                 \"os.subsystem.ios_version\": \"13.1\"})\n        conanfile = ConanFileMock()\n        conanfile.settings = settings\n        assert architecture_flag(conanfile) == \"--target=arm64-apple-ios13.1-macabi\"\n\n    @pytest.mark.parametrize(\"os_,arch,flag\",\n                             [(\"Linux\", \"x86\", \"-m32\"),\n                              (\"Linux\", \"x86_64\", \"-m64\"),\n                              (\"Windows\", \"x86\", \"/Qm32\"),\n                              (\"Windows\", \"x86_64\", \"/Qm64\"),\n                              ])\n    def test_arch_flag_intel(self, os_, arch, flag):\n        settings = MockSettings({\"compiler\": \"intel-cc\",\n                                 \"os\": os_,\n                                 \"arch\": arch})\n        conanfile = ConanFileMock()\n        conanfile.settings = settings\n        assert architecture_flag(conanfile) == flag\n\n    @pytest.mark.parametrize(\"arch,flag\",\n                             [(\"e2k-v2\", \"-march=elbrus-v2\"),\n                              (\"e2k-v3\", \"-march=elbrus-v3\"),\n                              (\"e2k-v4\", \"-march=elbrus-v4\"),\n                              (\"e2k-v5\", \"-march=elbrus-v5\"),\n                              (\"e2k-v6\", \"-march=elbrus-v6\"),\n                              (\"e2k-v7\", \"-march=elbrus-v7\"),\n                              ])\n    def test_arch_flag_mcst_lcc(self, arch, flag):\n        conanfile = ConanFileMock()\n        settings = MockSettings({\"compiler\": \"mcst-lcc\",\n                                 \"arch\": arch})\n        conanfile.settings = settings\n        assert architecture_flag(conanfile) == flag\n\n    @pytest.mark.parametrize(\"compiler,build_type,vs_toolset,flags\",\n                             [(\"msvc\", \"Debug\", None, \"-Zi -Ob0 -Od\"),\n                              (\"msvc\", \"Release\", None, \"-O2 -Ob2\"),\n                              (\"msvc\", \"RelWithDebInfo\", None, \"-Zi -O2 -Ob1\"),\n                              (\"msvc\", \"MinSizeRel\", None, \"-O1 -Ob1\"),\n                              (\"msvc\", \"Debug\", \"v140_clang_c2\",\n                               \"-gline-tables-only -fno-inline -O0\"),\n                              (\"msvc\", \"Release\", \"v140_clang_c2\", \"-O2\"),\n                              (\"msvc\", \"RelWithDebInfo\", \"v140_clang_c2\",\n                               \"-gline-tables-only -O2 -fno-inline\"),\n                              (\"msvc\", \"MinSizeRel\", \"v140_clang_c2\", \"\"),\n                              (\"gcc\", \"Debug\", None, \"-g\"),\n                              (\"gcc\", \"Release\", None, \"-O3\"),\n                              (\"gcc\", \"RelWithDebInfo\", None, \"-O2 -g\"),\n                              (\"gcc\", \"MinSizeRel\", None, \"-Os\"),\n                              (\"clang\", \"Debug\", None, \"-g\"),\n                              (\"clang\", \"Release\", None, \"-O3\"),\n                              (\"clang\", \"RelWithDebInfo\", None, \"-O2 -g\"),\n                              (\"clang\", \"MinSizeRel\", None, \"-Os\"),\n                              (\"apple-clang\", \"Debug\", None, \"-g\"),\n                              (\"apple-clang\", \"Release\", None, \"-O3\"),\n                              (\"apple-clang\", \"RelWithDebInfo\", None, \"-O2 -g\"),\n                              (\"apple-clang\", \"MinSizeRel\", None, \"-Os\"),\n                              (\"sun-cc\", \"Debug\", None, \"-g\"),\n                              (\"sun-cc\", \"Release\", None, \"-xO3\"),\n                              (\"sun-cc\", \"RelWithDebInfo\", None, \"-xO2 -g\"),\n                              (\"sun-cc\", \"MinSizeRel\", None, \"-xO2 -xspace\"),\n                              ])\n    def test_build_type_flags(self, compiler, build_type, vs_toolset, flags):\n        settings = MockSettings({\"compiler\": compiler,\n                                 \"build_type\": build_type,\n                                 \"compiler.toolset\": vs_toolset})\n        conanfile = ConanFileMock()\n        conanfile.settings = settings\n        assert ' '.join(build_type_flags(conanfile)) == flags\n\n    @pytest.mark.parametrize(\"compiler,build_type,flags\",\n                             [(\"clang\", \"Debug\", \"-Zi -Ob0 -Od\"),\n                              (\"clang\", \"Release\", \"-O2 -Ob2\"),\n                              (\"clang\", \"RelWithDebInfo\", \"-Zi -O2 -Ob1\"),\n                              (\"clang\", \"MinSizeRel\", \"-O1 -Ob1\"),\n                              ])\n    def test_build_type_flags_clangcl(self, compiler, build_type, flags):\n        settings = MockSettings({\"compiler\": compiler,\n                                 \"build_type\": build_type})\n        conanfile = ConanFileMock()\n        conanfile.conf.define(\"tools.build:compiler_executables\", {\"c\": \"clang-cl\"})\n        conanfile.settings = settings\n        assert ' '.join(build_type_flags(conanfile)) == flags\n\n    @pytest.mark.parametrize(\"compiler,version,flags\",\n                             [(\"clang\", \"8\", \"gnu14\"),\n                              (\"gcc\", \"15\", \"gnu17\")\n                              ])\n    def test_default_cppstd(self, compiler, version, flags):\n        settings = MockSettings({\"compiler\": compiler,\n                                 \"compiler.version\": version})\n        conanfile = ConanFileMock()\n        conanfile.settings = settings\n        assert default_cppstd(conanfile) == flags\n\n    @pytest.mark.parametrize(\"compiler,version,flags\",\n                             [(\"clang\", \"8\", \"gnu11\"),\n                              (\"gcc\", \"15\", \"gnu23\")\n                              ])\n    def test_default_cstd(self, compiler, version, flags):\n        settings = MockSettings({\"compiler\": compiler,\n                                 \"compiler.version\": version})\n        conanfile = ConanFileMock()\n        conanfile.settings = settings\n        assert default_cstd(conanfile) == flags\n"
  },
  {
    "path": "test/unittests/client/build/cpp_std_flags_test.py",
    "content": "from conan.internal.api.detect.detect_api import default_cppstd\nfrom conan.tools.build import cppstd_flag\nfrom conan.internal.model.version import Version\nfrom conan.test.utils.mocks import MockSettings, ConanFileMock\n\n\ndef _make_cppstd_flag(compiler, compiler_version, cppstd=None):\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\"compiler\": compiler,\n                                       \"compiler.version\": compiler_version,\n                                       \"compiler.cppstd\": cppstd})\n    return cppstd_flag(conanfile)\n\n\ndef _make_cppstd_default(compiler, compiler_version):\n    return default_cppstd(compiler, Version(compiler_version))\n\n\nclass TestCompilerFlags:\n\n    def test_gcc_cppstd_flags(self):\n        assert _make_cppstd_flag(\"gcc\", \"4.2\", \"98\") == \"-std=c++98\"\n        assert _make_cppstd_flag(\"gcc\", \"4.2\", \"gnu98\") == \"-std=gnu++98\"\n        assert _make_cppstd_flag(\"gcc\", \"4.2\", \"11\") is None\n        assert _make_cppstd_flag(\"gcc\", \"4.2\", \"14\") is None\n\n        assert _make_cppstd_flag(\"gcc\", \"4.3\", \"98\") == \"-std=c++98\"\n        assert _make_cppstd_flag(\"gcc\", \"4.3\", \"gnu98\") == \"-std=gnu++98\"\n        assert _make_cppstd_flag(\"gcc\", \"4.3\", \"11\") == \"-std=c++0x\"\n        assert _make_cppstd_flag(\"gcc\", \"4.3\", \"14\") is None\n\n        assert _make_cppstd_flag(\"gcc\", \"4.6\", \"11\") == '-std=c++0x'\n        assert _make_cppstd_flag(\"gcc\", \"4.6\", \"14\") is None\n\n        assert _make_cppstd_flag(\"gcc\", \"4.7\", \"11\") == '-std=c++11'\n        assert _make_cppstd_flag(\"gcc\", \"4.7\", \"14\") is None\n\n        assert _make_cppstd_flag(\"gcc\", \"4.8\", \"11\") == '-std=c++11'\n        assert _make_cppstd_flag(\"gcc\", \"4.8\", \"14\") == '-std=c++1y'\n        assert _make_cppstd_flag(\"gcc\", \"4.8\", \"17\") is None\n\n        assert _make_cppstd_flag(\"gcc\", \"4.9\", \"11\") == '-std=c++11'\n        assert _make_cppstd_flag(\"gcc\", \"4.9\", \"14\") == '-std=c++14'\n        assert _make_cppstd_flag(\"gcc\", \"4.9\", \"17\") is None\n\n        assert _make_cppstd_flag(\"gcc\", \"5\", \"11\") == '-std=c++11'\n        assert _make_cppstd_flag(\"gcc\", \"5\", \"14\") == '-std=c++14'\n        assert _make_cppstd_flag(\"gcc\", \"5\", \"gnu14\") == '-std=gnu++14'\n        assert _make_cppstd_flag(\"gcc\", \"5\", \"17\") == '-std=c++1z'\n        assert _make_cppstd_flag(\"gcc\", \"5\", \"gnu17\") == '-std=gnu++1z'\n\n        assert _make_cppstd_flag(\"gcc\", \"5.1\", \"11\") == '-std=c++11'\n        assert _make_cppstd_flag(\"gcc\", \"5.1\", \"14\") == '-std=c++14'\n        assert _make_cppstd_flag(\"gcc\", \"5.1\", \"17\") == '-std=c++1z'\n\n        assert _make_cppstd_flag(\"gcc\", \"7\", \"11\") == '-std=c++11'\n        assert _make_cppstd_flag(\"gcc\", \"7\", \"14\") == '-std=c++14'\n        assert _make_cppstd_flag(\"gcc\", \"7\", \"17\") == '-std=c++17'\n\n        assert _make_cppstd_flag(\"gcc\", \"8\", \"11\") == '-std=c++11'\n        assert _make_cppstd_flag(\"gcc\", \"8\", \"14\") == '-std=c++14'\n        assert _make_cppstd_flag(\"gcc\", \"8\", \"17\") == '-std=c++17'\n        assert _make_cppstd_flag(\"gcc\", \"8\", \"20\") == '-std=c++2a'\n        assert _make_cppstd_flag(\"gcc\", \"8\", \"23\") is None\n\n        assert _make_cppstd_flag(\"gcc\", \"11\", \"11\") == '-std=c++11'\n        assert _make_cppstd_flag(\"gcc\", \"11\", \"14\") == '-std=c++14'\n        assert _make_cppstd_flag(\"gcc\", \"11\", \"17\") == '-std=c++17'\n        assert _make_cppstd_flag(\"gcc\", \"11\", \"20\") == '-std=c++20'\n        assert _make_cppstd_flag(\"gcc\", \"11\", \"23\") == '-std=c++23'\n        assert _make_cppstd_flag(\"gcc\", \"11\", \"26\") is None\n\n        assert _make_cppstd_flag(\"gcc\", \"14\", \"11\") == '-std=c++11'\n        assert _make_cppstd_flag(\"gcc\", \"14\", \"14\") == '-std=c++14'\n        assert _make_cppstd_flag(\"gcc\", \"14\", \"17\") == '-std=c++17'\n        assert _make_cppstd_flag(\"gcc\", \"14\", \"20\") == '-std=c++20'\n        assert _make_cppstd_flag(\"gcc\", \"14\", \"23\") == '-std=c++23'\n        assert _make_cppstd_flag(\"gcc\", \"14\", \"26\") == '-std=c++26'\n\n        assert _make_cppstd_flag(\"gcc\", \"15\", \"11\") == '-std=c++11'\n        assert _make_cppstd_flag(\"gcc\", \"15\", \"14\") == '-std=c++14'\n        assert _make_cppstd_flag(\"gcc\", \"15\", \"17\") == '-std=c++17'\n        assert _make_cppstd_flag(\"gcc\", \"15\", \"20\") == '-std=c++20'\n        assert _make_cppstd_flag(\"gcc\", \"15\", \"23\") == '-std=c++23'\n        assert _make_cppstd_flag(\"gcc\", \"15\", \"26\") == '-std=c++26'\n\n    def test_gcc_cppstd_defaults(self):\n        assert _make_cppstd_default(\"gcc\", \"4\") == \"gnu98\"\n        assert _make_cppstd_default(\"gcc\", \"5\") == \"gnu98\"\n        assert _make_cppstd_default(\"gcc\", \"6\") == \"gnu14\"\n        assert _make_cppstd_default(\"gcc\", \"6.1\") == \"gnu14\"\n        assert _make_cppstd_default(\"gcc\", \"7.3\") == \"gnu14\"\n        assert _make_cppstd_default(\"gcc\", \"8.1\") == \"gnu14\"\n        assert _make_cppstd_default(\"gcc\", \"11\") == \"gnu17\"\n        assert _make_cppstd_default(\"gcc\", \"11.1\") == \"gnu17\"\n        assert _make_cppstd_default(\"gcc\", \"15.1\") == \"gnu17\"\n\n    def test_clang_cppstd_flags(self):\n        assert _make_cppstd_flag(\"clang\", \"2.0\", \"98\") is None\n        assert _make_cppstd_flag(\"clang\", \"2.0\", \"gnu98\") is None\n        assert _make_cppstd_flag(\"clang\", \"2.0\", \"11\") is None\n        assert _make_cppstd_flag(\"clang\", \"2.0\", \"14\") is None\n\n        assert _make_cppstd_flag(\"clang\", \"2.1\", \"98\") == \"-std=c++98\"\n        assert _make_cppstd_flag(\"clang\", \"2.1\", \"gnu98\") == \"-std=gnu++98\"\n        assert _make_cppstd_flag(\"clang\", \"2.1\", \"11\") == \"-std=c++0x\"\n        assert _make_cppstd_flag(\"clang\", \"2.1\", \"14\") is None\n\n        assert _make_cppstd_flag(\"clang\", \"3.0\", \"11\") == '-std=c++0x'\n        assert _make_cppstd_flag(\"clang\", \"3.0\", \"14\") is None\n\n        assert _make_cppstd_flag(\"clang\", \"3.1\", \"11\") == '-std=c++11'\n        assert _make_cppstd_flag(\"clang\", \"3.1\", \"14\") is None\n\n        assert _make_cppstd_flag(\"clang\", \"3.4\", \"11\") == '-std=c++11'\n        assert _make_cppstd_flag(\"clang\", \"3.4\", \"14\") == '-std=c++1y'\n        assert _make_cppstd_flag(\"clang\", \"3.4\", \"17\") is None\n\n        assert _make_cppstd_flag(\"clang\", \"3.5\", \"11\") == '-std=c++11'\n        assert _make_cppstd_flag(\"clang\", \"3.5\", \"14\") == '-std=c++14'\n        assert _make_cppstd_flag(\"clang\", \"3.5\", \"17\") == '-std=c++1z'\n\n        assert _make_cppstd_flag(\"clang\", \"5\", \"11\") == '-std=c++11'\n        assert _make_cppstd_flag(\"clang\", \"5\", \"14\") == '-std=c++14'\n        assert _make_cppstd_flag(\"clang\", \"5\", \"gnu14\") == '-std=gnu++14'\n        assert _make_cppstd_flag(\"clang\", \"5\", \"17\") == '-std=c++17'\n\n        assert _make_cppstd_flag(\"clang\", \"5.1\", \"11\") == '-std=c++11'\n        assert _make_cppstd_flag(\"clang\", \"5.1\", \"14\") == '-std=c++14'\n        assert _make_cppstd_flag(\"clang\", \"5.1\", \"17\") == '-std=c++17'\n\n        for version in [\"6\", \"7\", \"8\", \"9\", \"10\", \"11\"]:\n            assert _make_cppstd_flag(\"clang\", version, \"11\") == '-std=c++11'\n            assert _make_cppstd_flag(\"clang\", version, \"14\") == '-std=c++14'\n            assert _make_cppstd_flag(\"clang\", version, \"17\") == '-std=c++17'\n            assert _make_cppstd_flag(\"clang\", version, \"20\") == '-std=c++2a'\n            assert _make_cppstd_flag(\"clang\", version, \"23\") is None\n\n        assert _make_cppstd_flag(\"clang\", \"12\", \"11\") == '-std=c++11'\n        assert _make_cppstd_flag(\"clang\", \"12\", \"14\") == '-std=c++14'\n        assert _make_cppstd_flag(\"clang\", \"12\", \"17\") == '-std=c++17'\n        assert _make_cppstd_flag(\"clang\", \"12\", \"20\") == '-std=c++20'\n        assert _make_cppstd_flag(\"clang\", \"12\", \"23\") == '-std=c++2b'\n        assert _make_cppstd_flag(\"clang\", \"12\", \"26\") is None\n\n        assert _make_cppstd_flag(\"clang\", \"17\", \"11\") == '-std=c++11'\n        assert _make_cppstd_flag(\"clang\", \"17\", \"14\") == '-std=c++14'\n        assert _make_cppstd_flag(\"clang\", \"17\", \"17\") == '-std=c++17'\n        assert _make_cppstd_flag(\"clang\", \"17\", \"20\") == '-std=c++20'\n        assert _make_cppstd_flag(\"clang\", \"17\", \"23\") == '-std=c++23'\n        assert _make_cppstd_flag(\"clang\", \"17\", \"26\") == '-std=c++26'\n\n    def test_clang_cppstd_defaults(self):\n        assert _make_cppstd_default(\"clang\", \"2\") == \"gnu98\"\n        assert _make_cppstd_default(\"clang\", \"2.1\") == \"gnu98\"\n        assert _make_cppstd_default(\"clang\", \"3.0\") == \"gnu98\"\n        assert _make_cppstd_default(\"clang\", \"3.1\") == \"gnu98\"\n        assert _make_cppstd_default(\"clang\", \"3.4\") == \"gnu98\"\n        assert _make_cppstd_default(\"clang\", \"3.5\") == \"gnu98\"\n        assert _make_cppstd_default(\"clang\", \"5\") == \"gnu98\"\n        assert _make_cppstd_default(\"clang\", \"5.1\") == \"gnu98\"\n        assert _make_cppstd_default(\"clang\", \"6\") == \"gnu14\"\n        assert _make_cppstd_default(\"clang\", \"7\") == \"gnu14\"\n        assert _make_cppstd_default(\"clang\", \"8\") == \"gnu14\"\n        assert _make_cppstd_default(\"clang\", \"9\") == \"gnu14\"\n        assert _make_cppstd_default(\"clang\", \"10\") == \"gnu14\"\n        assert _make_cppstd_default(\"clang\", \"11\") == \"gnu14\"\n        assert _make_cppstd_default(\"clang\", \"12\") == \"gnu14\"\n        assert _make_cppstd_default(\"clang\", \"13\") == \"gnu14\"\n        assert _make_cppstd_default(\"clang\", \"14\") == \"gnu14\"\n        assert _make_cppstd_default(\"clang\", \"15\") == \"gnu14\"\n        assert _make_cppstd_default(\"clang\", \"16\") == \"gnu17\"\n\n    def test_apple_clang_cppstd_flags(self):\n        assert _make_cppstd_flag(\"apple-clang\", \"3.9\", \"98\") is None\n        assert _make_cppstd_flag(\"apple-clang\", \"3.9\", \"gnu98\") is None\n        assert _make_cppstd_flag(\"apple-clang\", \"3.9\", \"11\") is None\n        assert _make_cppstd_flag(\"apple-clang\", \"3.9\", \"14\") is None\n\n        assert _make_cppstd_flag(\"apple-clang\", \"4.0\", \"98\") == \"-std=c++98\"\n        assert _make_cppstd_flag(\"apple-clang\", \"4.0\", \"gnu98\") == \"-std=gnu++98\"\n        assert _make_cppstd_flag(\"apple-clang\", \"4.0\", \"11\") == \"-std=c++11\"\n        assert _make_cppstd_flag(\"apple-clang\", \"4.0\", \"14\") is None\n\n        assert _make_cppstd_flag(\"apple-clang\", \"5.0\", \"98\") == \"-std=c++98\"\n        assert _make_cppstd_flag(\"apple-clang\", \"5.0\", \"gnu98\") == \"-std=gnu++98\"\n        assert _make_cppstd_flag(\"apple-clang\", \"5.0\", \"11\") == \"-std=c++11\"\n        assert _make_cppstd_flag(\"apple-clang\", \"5.0\", \"14\") is None\n\n        assert _make_cppstd_flag(\"apple-clang\", \"5.1\", \"98\") == \"-std=c++98\"\n        assert _make_cppstd_flag(\"apple-clang\", \"5.1\", \"gnu98\") == \"-std=gnu++98\"\n        assert _make_cppstd_flag(\"apple-clang\", \"5.1\", \"11\") == \"-std=c++11\"\n        assert _make_cppstd_flag(\"apple-clang\", \"5.1\", \"14\") == \"-std=c++1y\"\n\n        assert _make_cppstd_flag(\"apple-clang\", \"6.1\", \"11\") == '-std=c++11'\n        assert _make_cppstd_flag(\"apple-clang\", \"6.1\", \"14\") == '-std=c++14'\n        assert _make_cppstd_flag(\"apple-clang\", \"6.1\", \"17\") == \"-std=c++1z\"\n\n        assert _make_cppstd_flag(\"apple-clang\", \"7\", \"11\") == '-std=c++11'\n        assert _make_cppstd_flag(\"apple-clang\", \"7\", \"14\") == '-std=c++14'\n        assert _make_cppstd_flag(\"apple-clang\", \"7\", \"17\") == \"-std=c++1z\"\n\n        assert _make_cppstd_flag(\"apple-clang\", \"8\", \"11\") == '-std=c++11'\n        assert _make_cppstd_flag(\"apple-clang\", \"8\", \"14\") == '-std=c++14'\n        assert _make_cppstd_flag(\"apple-clang\", \"8\", \"17\") == \"-std=c++1z\"\n\n        assert _make_cppstd_flag(\"apple-clang\", \"9\", \"11\") == '-std=c++11'\n        assert _make_cppstd_flag(\"apple-clang\", \"9\", \"14\") == '-std=c++14'\n        assert _make_cppstd_flag(\"apple-clang\", \"9\", \"17\") == \"-std=c++1z\"\n\n        assert _make_cppstd_flag(\"apple-clang\", \"9.1\", \"11\") == '-std=c++11'\n        assert _make_cppstd_flag(\"apple-clang\", \"9.1\", \"14\") == '-std=c++14'\n        assert _make_cppstd_flag(\"apple-clang\", \"9.1\", \"17\") == \"-std=c++17\"\n        assert _make_cppstd_flag(\"apple-clang\", \"9.1\", \"20\") is None\n\n        assert _make_cppstd_flag(\"apple-clang\", \"10.0\", \"17\") == \"-std=c++17\"\n        assert _make_cppstd_flag(\"apple-clang\", \"10.0\", \"20\") == \"-std=c++2a\"\n        assert _make_cppstd_flag(\"apple-clang\", \"11.0\", \"17\") == \"-std=c++17\"\n        assert _make_cppstd_flag(\"apple-clang\", \"11.0\", \"20\") == \"-std=c++2a\"\n\n        assert _make_cppstd_flag(\"apple-clang\", \"12.0\", \"17\") == \"-std=c++17\"\n        assert _make_cppstd_flag(\"apple-clang\", \"12.0\", \"20\") == \"-std=c++2a\"\n        assert _make_cppstd_flag(\"apple-clang\", \"12.0\", \"23\") is None\n\n        assert _make_cppstd_flag(\"apple-clang\", \"13.0\", \"17\") == \"-std=c++17\"\n        assert _make_cppstd_flag(\"apple-clang\", \"13.0\", \"gnu17\") == \"-std=gnu++17\"\n        assert _make_cppstd_flag(\"apple-clang\", \"13.0\", \"20\") == \"-std=c++20\"\n        assert _make_cppstd_flag(\"apple-clang\", \"13.0\", \"gnu20\") == \"-std=gnu++20\"\n        assert _make_cppstd_flag(\"apple-clang\", \"13.0\", \"23\") == \"-std=c++2b\"\n        assert _make_cppstd_flag(\"apple-clang\", \"13.0\", \"gnu23\") == \"-std=gnu++2b\"\n\n        assert _make_cppstd_flag(\"apple-clang\", \"14.0\", \"17\") == \"-std=c++17\"\n        assert _make_cppstd_flag(\"apple-clang\", \"14.0\", \"gnu17\") == \"-std=gnu++17\"\n        assert _make_cppstd_flag(\"apple-clang\", \"14.0\", \"20\") == \"-std=c++20\"\n        assert _make_cppstd_flag(\"apple-clang\", \"14.0\", \"gnu20\") == \"-std=gnu++20\"\n        assert _make_cppstd_flag(\"apple-clang\", \"14.0\", \"23\") == \"-std=c++2b\"\n        assert _make_cppstd_flag(\"apple-clang\", \"14.0\", \"gnu23\") == \"-std=gnu++2b\"\n\n        assert _make_cppstd_flag(\"apple-clang\", \"15.0\", \"17\") == \"-std=c++17\"\n        assert _make_cppstd_flag(\"apple-clang\", \"15.0\", \"gnu17\") == \"-std=gnu++17\"\n        assert _make_cppstd_flag(\"apple-clang\", \"15.0\", \"20\") == \"-std=c++20\"\n        assert _make_cppstd_flag(\"apple-clang\", \"15.0\", \"gnu20\") == \"-std=gnu++20\"\n        assert _make_cppstd_flag(\"apple-clang\", \"15.0\", \"23\") == \"-std=c++2b\"\n        assert _make_cppstd_flag(\"apple-clang\", \"15.0\", \"gnu23\") == \"-std=gnu++2b\"\n        assert _make_cppstd_flag(\"apple-clang\", \"15.0\", \"26\") is None\n\n        assert _make_cppstd_flag(\"apple-clang\", \"16.0\", \"17\") == \"-std=c++17\"\n        assert _make_cppstd_flag(\"apple-clang\", \"16.0\", \"gnu17\") == \"-std=gnu++17\"\n        assert _make_cppstd_flag(\"apple-clang\", \"16.0\", \"20\") == \"-std=c++20\"\n        assert _make_cppstd_flag(\"apple-clang\", \"16.0\", \"gnu20\") == \"-std=gnu++20\"\n        assert _make_cppstd_flag(\"apple-clang\", \"16.0\", \"23\") == \"-std=c++23\"\n        assert _make_cppstd_flag(\"apple-clang\", \"16.0\", \"gnu23\") == \"-std=gnu++23\"\n        assert _make_cppstd_flag(\"apple-clang\", \"16.0\", \"26\") == \"-std=c++26\"\n        assert _make_cppstd_flag(\"apple-clang\", \"16.0\", \"gnu26\") == \"-std=gnu++26\"\n\n        assert _make_cppstd_flag(\"apple-clang\", \"17.0\", \"17\") == \"-std=c++17\"\n        assert _make_cppstd_flag(\"apple-clang\", \"17.0\", \"gnu17\") == \"-std=gnu++17\"\n        assert _make_cppstd_flag(\"apple-clang\", \"17.0\", \"20\") == \"-std=c++20\"\n        assert _make_cppstd_flag(\"apple-clang\", \"17.0\", \"gnu20\") == \"-std=gnu++20\"\n        assert _make_cppstd_flag(\"apple-clang\", \"17.0\", \"23\") == \"-std=c++23\"\n        assert _make_cppstd_flag(\"apple-clang\", \"17.0\", \"gnu23\") == \"-std=gnu++23\"\n        assert _make_cppstd_flag(\"apple-clang\", \"17.0\", \"26\") == \"-std=c++26\"\n        assert _make_cppstd_flag(\"apple-clang\", \"17.0\", \"gnu26\") == \"-std=gnu++26\"\n\n    def test_apple_clang_cppstd_defaults(self):\n        assert _make_cppstd_default(\"apple-clang\", \"2\") == \"gnu98\"\n        assert _make_cppstd_default(\"apple-clang\", \"3\") == \"gnu98\"\n        assert _make_cppstd_default(\"apple-clang\", \"4\") == \"gnu98\"\n        assert _make_cppstd_default(\"apple-clang\", \"5\") == \"gnu98\"\n        assert _make_cppstd_default(\"apple-clang\", \"6\") == \"gnu98\"\n        assert _make_cppstd_default(\"apple-clang\", \"7\") == \"gnu98\"\n        assert _make_cppstd_default(\"apple-clang\", \"8\") == \"gnu98\"\n        assert _make_cppstd_default(\"apple-clang\", \"9\") == \"gnu98\"\n        assert _make_cppstd_default(\"apple-clang\", \"10\") == \"gnu98\"\n        assert _make_cppstd_default(\"apple-clang\", \"11\") == \"gnu98\"\n        assert _make_cppstd_default(\"apple-clang\", \"12\") == \"gnu98\"\n        assert _make_cppstd_default(\"apple-clang\", \"13\") == \"gnu98\"\n        assert _make_cppstd_default(\"apple-clang\", \"14\") == \"gnu98\"\n        assert _make_cppstd_default(\"apple-clang\", \"15\") == \"gnu98\"\n        assert _make_cppstd_default(\"apple-clang\", \"16\") == \"gnu98\"\n        assert _make_cppstd_default(\"apple-clang\", \"17\") == \"gnu14\"\n\n    def test_visual_cppstd_flags(self):\n        assert _make_cppstd_flag(\"msvc\", \"170\", \"11\") is None\n        assert _make_cppstd_flag(\"msvc\", \"170\", \"14\") is None\n        assert _make_cppstd_flag(\"msvc\", \"170\", \"17\") is None\n\n        assert _make_cppstd_flag(\"msvc\", \"180\", \"11\") is None\n\n        assert _make_cppstd_flag(\"msvc\", \"190\", \"14\") == '/std:c++14'\n        assert _make_cppstd_flag(\"msvc\", \"190\", \"17\") == '/std:c++latest'\n\n        assert _make_cppstd_flag(\"msvc\", \"191\", \"11\") is None\n        assert _make_cppstd_flag(\"msvc\", \"191\", \"14\") == '/std:c++14'\n        assert _make_cppstd_flag(\"msvc\", \"191\", \"17\") == '/std:c++17'\n        assert _make_cppstd_flag(\"msvc\", \"191\", \"20\") == '/std:c++latest'\n\n        assert _make_cppstd_flag(\"msvc\", \"192\", \"17\") == '/std:c++17'\n        assert _make_cppstd_flag(\"msvc\", \"192\", \"20\") == '/std:c++20'\n\n        assert _make_cppstd_flag(\"msvc\", \"193\", \"20\") == '/std:c++20'\n        assert _make_cppstd_flag(\"msvc\", \"193\", \"23\") == '/std:c++latest'\n\n    def test_visual_cppstd_defaults(self):\n        assert _make_cppstd_default(\"msvc\", \"170\") is None\n        assert _make_cppstd_default(\"msvc\", \"180\") is None\n        assert _make_cppstd_default(\"msvc\", \"190\") == \"14\"\n        assert _make_cppstd_default(\"msvc\", \"191\") == \"14\"\n        assert _make_cppstd_default(\"msvc\", \"192\") == \"14\"\n        assert _make_cppstd_default(\"msvc\", \"193\") == \"14\"\n\n    def test_intel_cppstd_flag(self):\n        assert _make_cppstd_flag(\"intel-cc\", \"2024.1\", \"gnu98\") == '-std=gnu++98'\n        assert _make_cppstd_flag(\"intel-cc\", \"2024.1\", \"11\") == '-std=c++11'\n        assert _make_cppstd_flag(\"intel-cc\", \"2024.1\", \"14\") == '-std=c++14'\n        assert _make_cppstd_flag(\"intel-cc\", \"2024.1\", \"17\") == '-std=c++17'\n        assert _make_cppstd_flag(\"intel-cc\", \"2024.1\", \"20\") == '-std=c++20'\n\n        assert _make_cppstd_flag(\"intel-cc\", \"2025.1\", \"17\") == '-std=c++17'\n        assert _make_cppstd_flag(\"intel-cc\", \"2025.1\", \"20\") == '-std=c++20'\n        assert _make_cppstd_flag(\"intel-cc\", \"2025.1\", \"23\") == '-std=c++2b'\n\n    def test_mcst_lcc_cppstd_defaults(self):\n        assert _make_cppstd_default(\"mcst-lcc\", \"1.19\") == \"gnu98\"\n        assert _make_cppstd_default(\"mcst-lcc\", \"1.20\") == \"gnu98\"\n        assert _make_cppstd_default(\"mcst-lcc\", \"1.21\") == \"gnu98\"\n        assert _make_cppstd_default(\"mcst-lcc\", \"1.22\") == \"gnu98\"\n        assert _make_cppstd_default(\"mcst-lcc\", \"1.23\") == \"gnu98\"\n        assert _make_cppstd_default(\"mcst-lcc\", \"1.24\") == \"gnu14\"\n        assert _make_cppstd_default(\"mcst-lcc\", \"1.25\") == \"gnu14\"\n\n    def test_mcst_lcc_cppstd_flag(self):\n        assert _make_cppstd_flag(\"mcst-lcc\", \"1.19\", \"98\") == \"-std=c++98\"\n        assert _make_cppstd_flag(\"mcst-lcc\", \"1.19\", \"11\") is None\n        assert _make_cppstd_flag(\"mcst-lcc\", \"1.19\", \"14\") is None\n        assert _make_cppstd_flag(\"mcst-lcc\", \"1.19\", \"17\") is None\n        assert _make_cppstd_flag(\"mcst-lcc\", \"1.19\", \"20\") is None\n\n        assert _make_cppstd_flag(\"mcst-lcc\", \"1.20\", \"98\") == \"-std=c++98\"\n        assert _make_cppstd_flag(\"mcst-lcc\", \"1.20\", \"11\") is None\n        assert _make_cppstd_flag(\"mcst-lcc\", \"1.20\", \"14\") is None\n        assert _make_cppstd_flag(\"mcst-lcc\", \"1.20\", \"17\") is None\n        assert _make_cppstd_flag(\"mcst-lcc\", \"1.20\", \"20\") is None\n\n        assert _make_cppstd_flag(\"mcst-lcc\", \"1.21\", \"98\") == \"-std=c++98\"\n        assert _make_cppstd_flag(\"mcst-lcc\", \"1.21\", \"11\") == \"-std=c++11\"\n        assert _make_cppstd_flag(\"mcst-lcc\", \"1.21\", \"14\") == \"-std=c++14\"\n        assert _make_cppstd_flag(\"mcst-lcc\", \"1.21\", \"17\") is None\n        assert _make_cppstd_flag(\"mcst-lcc\", \"1.21\", \"20\") is None\n\n        assert _make_cppstd_flag(\"mcst-lcc\", \"1.22\", \"98\") == \"-std=c++98\"\n        assert _make_cppstd_flag(\"mcst-lcc\", \"1.22\", \"11\") == \"-std=c++11\"\n        assert _make_cppstd_flag(\"mcst-lcc\", \"1.22\", \"14\") == \"-std=c++14\"\n        assert _make_cppstd_flag(\"mcst-lcc\", \"1.22\", \"17\") is None\n        assert _make_cppstd_flag(\"mcst-lcc\", \"1.22\", \"20\") is None\n\n        assert _make_cppstd_flag(\"mcst-lcc\", \"1.23\", \"98\") == \"-std=c++98\"\n        assert _make_cppstd_flag(\"mcst-lcc\", \"1.23\", \"11\") == \"-std=c++11\"\n        assert _make_cppstd_flag(\"mcst-lcc\", \"1.23\", \"14\") == \"-std=c++14\"\n        assert _make_cppstd_flag(\"mcst-lcc\", \"1.23\", \"17\") is None\n        assert _make_cppstd_flag(\"mcst-lcc\", \"1.23\", \"20\") is None\n\n        assert _make_cppstd_flag(\"mcst-lcc\", \"1.24\", \"98\") == \"-std=c++98\"\n        assert _make_cppstd_flag(\"mcst-lcc\", \"1.24\", \"11\") == \"-std=c++11\"\n        assert _make_cppstd_flag(\"mcst-lcc\", \"1.24\", \"14\") == \"-std=c++14\"\n        assert _make_cppstd_flag(\"mcst-lcc\", \"1.24\", \"17\") == \"-std=c++17\"\n        assert _make_cppstd_flag(\"mcst-lcc\", \"1.24\", \"20\") is None\n\n        assert _make_cppstd_flag(\"mcst-lcc\", \"1.25\", \"98\") == \"-std=c++98\"\n        assert _make_cppstd_flag(\"mcst-lcc\", \"1.25\", \"11\") == \"-std=c++11\"\n        assert _make_cppstd_flag(\"mcst-lcc\", \"1.25\", \"14\") == \"-std=c++14\"\n        assert _make_cppstd_flag(\"mcst-lcc\", \"1.25\", \"17\") == \"-std=c++17\"\n        assert _make_cppstd_flag(\"mcst-lcc\", \"1.25\", \"20\") == \"-std=c++2a\"\n"
  },
  {
    "path": "test/unittests/client/command/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/client/command/parse_arguments_test.py",
    "content": "import argparse\nimport pytest\n\nfrom conan.cli.args import add_profiles_args\n\n\n@pytest.mark.parametrize(\"argument\", [\n    [\"options\", \"-o\", \"--options\"],\n    [\"profile\", \"-pr\", \"--profile\"],\n    [\"settings\", \"-s\", \"--settings\"],\n    [\"conf\", \"-c\", \"--conf\"]\n])\nclass TestArgsParseProfile:\n    \"\"\" Check argparse for profile arguments \"\"\"\n\n    @pytest.fixture(autouse=True)\n    def setup(self, argument):\n        self.argument = argument\n        self.item, self.short_arg, self.long_arg = self.argument\n        self.args_dest_build = '{}_build'.format(self.item)\n        self.args_dest_host = '{}_host'.format(self.item)\n\n    def _run_parse(self, *args):\n        parser = argparse.ArgumentParser()\n        add_profiles_args(parser)\n        parsed_args = parser.parse_args(*args)\n        build = getattr(parsed_args, self.args_dest_build)\n        host = getattr(parsed_args, self.args_dest_host)\n        return build, host\n\n    def test_default(self):\n        \"\"\" The old '--settings', '--profile',... refers to the build machine \"\"\"\n        build, host = self._run_parse([self.long_arg, \"it1\"])\n        assert host == [\"it1\"]\n        assert build is None\n\n        build, host = self._run_parse([self.long_arg, \"it1\", self.short_arg, \"it2\"])\n        assert host == [\"it1\", \"it2\"]\n        assert build is None\n\n    def test_build_machine(self):\n        \"\"\" If provided with build suffix (':b', ':build'), those correspond to the build machine \"\"\"\n        long_arg = \"{}:build\".format(self.long_arg)\n        short_arg = \"{}:b\".format(self.short_arg)\n\n        build, host = self._run_parse([long_arg, \"it1\"])\n        assert build == [\"it1\"]\n        assert host is None\n\n        build, host = self._run_parse([long_arg, \"it1\", short_arg, \"it2\"])\n        assert build == [\"it1\", \"it2\"]\n        assert host is None\n\n    def test_mix_old_and_host_machine(self):\n        \"\"\" Old arguments and new ':host' ones are composable \"\"\"\n        new_long_arg = \"{}:host\".format(self.long_arg)\n        new_short_arg = \"{}:h\".format(self.short_arg)\n\n        build, host = self._run_parse([new_long_arg, \"it1\", self.long_arg, \"it2\",\n                                       new_short_arg, \"it3\", self.short_arg, \"it4\"])\n        assert host == [\"it1\", \"it2\", \"it3\", \"it4\"]\n        assert build is None\n\n    def test_host_machine(self):\n        \"\"\" If provided with host suffix (':h', ':host'), those correspond to the host machine \"\"\"\n        long_arg = \"{}:host\".format(self.long_arg)\n        short_arg = \"{}:h\".format(self.short_arg)\n\n        build, host = self._run_parse([long_arg, \"it1\"])\n        assert host == [\"it1\"]\n        assert build is None\n\n        build, host = self._run_parse([long_arg, \"it1\", short_arg, \"it2\"])\n        assert host == [\"it1\", \"it2\"]\n        assert build is None\n\n    def test_build_and_host(self):\n        \"\"\" Of course, we can provide build and host in the same command line \"\"\"\n        build, host = self._run_parse([\"{}:build\".format(self.long_arg), \"b1\",\n                                       \"{}:host\".format(self.long_arg), \"h1\"])\n        assert build == [\"b1\"]\n        assert host == [\"h1\"]\n"
  },
  {
    "path": "test/unittests/client/conan_output_test.py",
    "content": "import sys\nfrom unittest import mock\n\nimport pytest\n\nfrom conan.api.output import ConanOutput, init_colorama\nfrom conan.test.utils.mocks import RedirectedTestOutput\nfrom conan.test.utils.tools import redirect_output\n\n\nclass TestConanOutput:\n\n    @pytest.mark.parametrize(\"isatty, env\", [(True, {\"NO_COLOR\": \"1\"}),\n                                             (True, {\"NO_COLOR\": \"0\"})])\n    def test_output_color_prevent_strip(self, isatty, env):\n        with mock.patch(\"colorama.init\") as init:\n            with mock.patch(\"sys.stderr.isatty\", return_value=isatty), \\\n                 mock.patch.dict(\"os.environ\", env, clear=True):\n                init_colorama(sys.stderr)\n                out = ConanOutput()\n                assert out.color is False\n                init.assert_not_called()\n\n\n@pytest.mark.parametrize(\"force\", [\"1\", \"0\", \"foo\"])\ndef test_output_forced(force):\n    env = {\"CLICOLOR_FORCE\": force}\n    forced = force != \"0\"\n    with mock.patch(\"colorama.init\") as init:\n        with mock.patch(\"sys.stderr.isatty\", return_value=False), \\\n             mock.patch.dict(\"os.environ\", env, clear=True):\n            init_colorama(sys.stderr)\n            out = ConanOutput()\n\n            assert out.color is forced\n            if not forced:\n                init.assert_not_called()\n\n\ndef test_output_chainable():\n    stderr = RedirectedTestOutput()\n    with redirect_output(stderr):\n        ConanOutput(scope=\"My package\")\\\n            .title(\"My title\")\\\n            .highlight(\"Worked\")\\\n            .info(\"But there was more that needed to be said\")\n    assert \"My package\" in stderr.getvalue()\n    assert \"My title\" in stderr.getvalue()\n    assert \"Worked\" in stderr.getvalue()\n    assert \"But there was more that needed to be said\" in stderr.getvalue()\n"
  },
  {
    "path": "test/unittests/client/conanfile_loader_test.py",
    "content": "import os\nimport sys\nimport textwrap\n\nimport pytest\n\nfrom conan.internal.loader import ConanFileLoader, ConanFileTextLoader, load_python_file\nfrom conan.errors import ConanException\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.internal.util.files import save, chdir\n\n\nclass TestConanLoaderTxt:\n    def test_conanfile_txt_errors(self):\n        # Invalid content\n        file_content = '''[requires}\nOpenCV/2.4.10@phil/stable # My requirement for CV\n'''\n        with pytest.raises(ConanException, match=\"Bad syntax\"):\n            ConanFileTextLoader(file_content)\n\n        file_content = '{hello}'\n        with pytest.raises(ConanException, match=\"Unexpected line\"):\n            ConanFileTextLoader(file_content)\n\n    def test_plain_text_parser(self):\n        # Valid content\n        file_content = '''[requires]\nOpenCV/2.4.10@phil/stable # My requirement for CV\nOpenCV2/2.4.10@phil/stable #\nOpenCV3/2.4.10@phil/stable\n[generators]\none # My generator for this\ntwo\n[options]\nOpenCV:use_python=True # Some option\nOpenCV:other_option=False\nOpenCV2:use_python2=1\nOpenCV2:other_option=Cosa #\n'''\n        parser = ConanFileTextLoader(file_content)\n        exp = ['OpenCV/2.4.10@phil/stable',\n               'OpenCV2/2.4.10@phil/stable',\n               'OpenCV3/2.4.10@phil/stable']\n        assert parser.requirements == exp\n\n    def test_revision_parsing(self):\n        # Valid content\n        file_content = '''[requires]\nOpenCV/2.4.10@user/stable#RREV1 # My requirement for CV\n'''\n        parser = ConanFileTextLoader(file_content)\n        exp = ['OpenCV/2.4.10@user/stable#RREV1']\n        assert parser.requirements == exp\n\n    def test_load_conan_txt(self):\n        file_content = '''[requires]\nOpenCV/2.4.10@phil/stable\nOpenCV2/2.4.10@phil/stable\n[tool_requires]\nMypkg/1.0.0@phil/stable\n[generators]\none\ntwo\n[options]\nOpenCV/*:use_python=True\nOpenCV/*:other_option=False\nOpenCV2/*:use_python2=1\nOpenCV2/*:other_option=Cosa\n'''\n        tmp_dir = temp_folder()\n        file_path = os.path.join(tmp_dir, \"file.txt\")\n        save(file_path, file_content)\n        loader = ConanFileLoader(None, None)\n        ret = loader.load_conanfile_txt(file_path)\n\n        assert len(ret.requires.values()) == 3\n        assert ret.generators == [\"one\", \"two\"]\n        assert ret.options.dumps() == 'OpenCV/*:other_option=False\\n' \\\n                                              'OpenCV/*:use_python=True\\n' \\\n                                              'OpenCV2/*:other_option=Cosa\\n' \\\n                                              'OpenCV2/*:use_python2=1'\n\n    def test_load_options_error(self):\n        conanfile_txt = textwrap.dedent(\"\"\"\n            [options]\n            myoption: myvalue\n        \"\"\")\n        tmp_dir = temp_folder()\n        file_path = os.path.join(tmp_dir, \"file.txt\")\n        save(file_path, conanfile_txt)\n        loader = ConanFileLoader(None, None)\n        with pytest.raises(ConanException,\n                                    match=r\"Error while parsing \\[options\\] in conanfile.txt\\n\" \\\n                                    r\"Options should be specified as 'pkg/\\*:option=value'\"):\n            loader.load_conanfile_txt(file_path)\n\n    def test_layout_not_predefined(self):\n        txt = textwrap.dedent(\"\"\"\n                    [layout]\n                    missing\n                \"\"\")\n        tmp_dir = temp_folder()\n        file_path = os.path.join(tmp_dir, \"conanfile.txt\")\n        save(file_path, txt)\n        with pytest.raises(ConanException) as exc:\n            loader = ConanFileLoader(None, None)\n            loader.load_conanfile_txt(file_path)\n        assert \"Unknown predefined layout 'missing'\" in str(exc.value)\n\n    def test_layout_multiple(self):\n        txt = textwrap.dedent(\"\"\"\n                    [layout]\n                    cmake_layout\n                    vs_layout\n                \"\"\")\n        tmp_dir = temp_folder()\n        file_path = os.path.join(tmp_dir, \"conanfile.txt\")\n        save(file_path, txt)\n        with pytest.raises(ConanException) as exc:\n            loader = ConanFileLoader(None, None)\n            loader.load_conanfile_txt(file_path)\n        assert \"Only one layout can be declared in the [layout] section of the conanfile.txt\" \\\n               in str(exc.value)\n\n\nclass TestImportModuleLoader:\n    @staticmethod\n    def _create_and_load(myfunc, value, subdir_name, add_subdir_init):\n        subdir_content = textwrap.dedent(\"\"\"\n            def get_value():\n                return {value}\n            def {myfunc}():\n                return \"{myfunc}\"\n        \"\"\")\n\n        side_content = textwrap.dedent(\"\"\"\n            def get_side_value():\n                return {value}\n            def side_{myfunc}():\n                return \"{myfunc}\"\n        \"\"\")\n\n        conanfile = textwrap.dedent(\"\"\"\n            import pickle\n            from {subdir}.api import get_value, {myfunc}\n            from file import get_side_value, side_{myfunc}\n            from fractions import Fraction\n            def conanfile_func():\n                return get_value(), {myfunc}(), get_side_value(), side_{myfunc}(), str(Fraction(1,1))\n        \"\"\")\n        expected_return = (value, myfunc, value, myfunc, \"1\")\n\n        tmp = temp_folder()\n        with chdir(tmp):\n            save(\"conanfile.py\", conanfile.format(value=value, myfunc=myfunc, subdir=subdir_name))\n            save(\"file.py\", side_content.format(value=value, myfunc=myfunc))\n            save(\"{}/api.py\".format(subdir_name), subdir_content.format(value=value, myfunc=myfunc))\n            if add_subdir_init:\n                save(\"__init__.py\", \"\")\n                save(\"{}/__init__.py\".format(subdir_name), \"\")\n\n        loaded, module_id = load_python_file(os.path.join(tmp, \"conanfile.py\"))\n        return loaded, module_id, expected_return\n\n    @pytest.mark.parametrize(\"sub1,sub2\", [(True, False), (False, True), (False, False)])\n    def test_py3_recipe_colliding_init_filenames(self, sub1, sub2):\n        myfunc1, value1 = \"recipe1\", 42\n        myfunc2, value2 = \"recipe2\", 23\n        loaded1, module_id1, exp_ret1 = self._create_and_load(myfunc1, value1, \"subdir\", sub1)\n        loaded2, module_id2, exp_ret2 = self._create_and_load(myfunc2, value2, \"subdir\", sub2)\n\n        assert module_id1 != module_id2\n        assert loaded1.conanfile_func() == exp_ret1\n        assert loaded2.conanfile_func() == exp_ret2\n\n    def test_recipe_colliding_filenames(self):\n        myfunc1, value1 = \"recipe1\", 42\n        myfunc2, value2 = \"recipe2\", 23\n        loaded1, module_id1, exp_ret1 = self._create_and_load(myfunc1, value1, \"subdir\", True)\n        loaded2, module_id2, exp_ret2 = self._create_and_load(myfunc2, value2, \"subdir\", True)\n\n        assert module_id1 != module_id2\n        assert loaded1.conanfile_func() == exp_ret1\n        assert loaded2.conanfile_func() == exp_ret2\n\n    @pytest.mark.parametrize(\"add_subdir_init\", [(True, ), (False, )])\n    def test_wrong_imports(self, add_subdir_init):\n        myfunc1, value1 = \"recipe1\", 42\n\n        # Item imported does not exist, but file exists\n        # We use some existing and imported Python stdlib import\n        with pytest.raises(ConanException, match=\"Unable to load conanfile in\"):\n            self._create_and_load(myfunc1, value1, \"textwrap\", add_subdir_init)\n\n        # File does not exists in already existing module\n        with pytest.raises(ConanException, match=\"Unable to load conanfile in\"):\n            self._create_and_load(myfunc1, value1, \"conans\", add_subdir_init)\n\n    def test_helpers_python_library(self):\n        mylogger = \"\"\"\nvalue = \"\"\ndef append(data):\n    global value\n    value += data\n\"\"\"\n        temp = temp_folder()\n        save(os.path.join(temp, \"myconanlogger.py\"), mylogger)\n\n        conanfile = \"import myconanlogger\"\n        temp1 = temp_folder()\n        save(os.path.join(temp1, \"conanfile.py\"), conanfile)\n        temp2 = temp_folder()\n        save(os.path.join(temp2, \"conanfile.py\"), conanfile)\n\n        try:\n            sys.path.append(temp)\n            loaded1, _ = load_python_file(os.path.join(temp1, \"conanfile.py\"))\n            loaded2, _ = load_python_file(os.path.join(temp2, \"conanfile.py\"))\n            assert loaded1.myconanlogger == loaded2.myconanlogger\n            assert loaded1.myconanlogger.value == loaded2.myconanlogger.value\n        finally:\n            sys.path.remove(temp)\n"
  },
  {
    "path": "test/unittests/client/conf/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/client/conf/config_installer/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/client/conf/config_installer/test_install_folder.py",
    "content": "import os\n\nfrom conan.internal.api.config.config_installer import tmp_config_install_folder\nfrom conan.test.utils.test_files import temp_folder\n\n\nclass TestInstallFolder:\n\n    def test_unique_install_folder(self):\n        \"\"\" Validate if tmp_config_install_folder is removing old folder before creating a new one\n\n        tmp_config_install_folder must create the same folder, but all items must be exclude when a\n        new folder is created.\n        \"\"\"\n        cache_folder = temp_folder()\n\n        with tmp_config_install_folder(cache_folder) as tmp_folder_first:\n            temp_file = os.path.join(tmp_folder_first, \"foobar.txt\")\n            open(temp_file, \"w+\")\n            with tmp_config_install_folder(cache_folder) as tmp_folder_second:\n                assert tmp_folder_first == tmp_folder_second\n                assert not os.path.exists(temp_file)\n"
  },
  {
    "path": "test/unittests/client/conf/detect/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/client/conf/detect/test_gcc_compiler.py",
    "content": "\nfrom unittest import mock\nimport pytest\n\nfrom conan.internal.api.detect.detect_api import detect_gcc_compiler\n\n@pytest.mark.parametrize(\"version\", [\"10\", \"4.2\", '7', \"8.12\"])\ndef test_detect_gcc_10(version):\n    with mock.patch(\"platform.system\", return_value=\"Linux\"):\n        with mock.patch(\"conan.internal.api.detect.detect_api.detect_runner\", return_value=(0, version)):\n            compiler, installed_version, compiler_exe = detect_gcc_compiler()\n    assert compiler == 'gcc'\n    assert installed_version == version\n    assert compiler_exe == 'gcc'\n"
  },
  {
    "path": "test/unittests/client/file_copier/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/client/file_copier/test_report_copied_files.py",
    "content": "\nfrom conan.api.output import ConanOutput\nfrom conan.internal.model.manifest import FileTreeManifest\nfrom conan.test.utils.mocks import RedirectedTestOutput\nfrom conan.test.utils.tools import redirect_output\n\n\nclass TestReportCopiedFiles:\n\n    def test_output_string(self):\n        manifest = FileTreeManifest(0,\n                                    file_sums={'/abs/path/to/file.pdf': \"\",\n                                               '../rel/path/to/file2.pdf': \"\",\n                                               '../rel/path/to/file3.pdf': \"\",\n                                               '../rel/path/to/file4.pdf': \"\",\n                                               '../rel/path/to/file5.pdf': \"\",\n                                               '../rel/path/to/file6.pdf': \"\",\n                                               '../rel/path/to/file7.pdf': \"\",\n                                               '/without/ext/no_ext1': \"\",\n                                               'no_ext2': \"\",\n                                               'a/other.txt': \"\"})\n        output = RedirectedTestOutput()\n        with redirect_output(output):\n            manifest.report_summary(ConanOutput())\n            lines = sorted(str(output).splitlines())\n            assert \"Copied 7 '.pdf' files\" == lines[2]\n            assert \"Copied 2 files: no_ext1, no_ext2\" == lines[1]\n            assert \"Copied 1 '.txt' file: other.txt\" == lines[0]\n"
  },
  {
    "path": "test/unittests/client/graph/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/client/graph/build_mode_test.py",
    "content": "import pytest\n\nfrom conan.internal.graph.build_mode import BuildMode\nfrom conan.errors import ConanException\nfrom conan.api.model import RecipeReference\nfrom conan.test.utils.mocks import ConanFileMock, RedirectedTestOutput\nfrom conan.test.utils.tools import redirect_output\n\n\n@pytest.fixture\ndef conanfile():\n    return ConanFileMock(None)\n\n\ndef test_skip_package(conanfile):\n    build_mode = BuildMode([\"!zlib/*\", \"other*\"])\n    assert not build_mode.forced(conanfile, RecipeReference.loads(\"zlib/1.2.11#23423423\"))\n    assert build_mode.forced(conanfile, RecipeReference.loads(\"other/1.2\"))\n\n    build_mode = BuildMode([\"!zlib/*\", \"*\"])\n    assert not build_mode.forced(conanfile, RecipeReference.loads(\"zlib/1.2.11#23423423\"))\n    assert build_mode.forced(conanfile, RecipeReference.loads(\"other/1.2\"))\n\n    build_mode = BuildMode([\"!zlib/*\"])\n    assert not build_mode.forced(conanfile, RecipeReference.loads(\"zlib/1.2.11#23423423\"))\n    assert not build_mode.forced(conanfile, RecipeReference.loads(\"other/1.2\"))\n\n\ndef test_invalid_configuration():\n    for mode in [\"missing\", \"cascade\"]:\n        with pytest.raises(ConanException, match=r\"--build=never not compatible \"\n                                                 r\"with other options\"):\n            BuildMode([mode, \"never\"])\n\n\ndef test_common_build_force(conanfile):\n    output = RedirectedTestOutput()\n    with redirect_output(output):\n        reference = RecipeReference.loads(\"hello/0.1@user/testing\")\n        build_mode = BuildMode([\"hello/*\"])\n        assert build_mode.forced(conanfile, reference) is True\n\n\ndef test_no_user_channel(conanfile):\n    output = RedirectedTestOutput()\n    with redirect_output(output):\n        reference = RecipeReference.loads(\"hello/0.1@\")\n        build_mode = BuildMode([\"hello/0.1@\"])\n        assert build_mode.forced(conanfile, reference) is True\n\n\ndef test_revision_included(conanfile):\n    output = RedirectedTestOutput()\n    with redirect_output(output):\n        reference = RecipeReference.loads(\"hello/0.1@user/channel#rrev1\")\n        build_mode = BuildMode([\"hello/0.1@user/channel#rrev1\"])\n        assert build_mode.forced(conanfile, reference) is True\n\n\ndef test_no_user_channel_revision_included(conanfile):\n    output = RedirectedTestOutput()\n    with redirect_output(output):\n        reference = RecipeReference.loads(\"hello/0.1@#rrev1\")\n        build_mode = BuildMode([\"hello/0.1@#rrev1\"])\n        assert build_mode.forced(conanfile, reference) is True\n\n\ndef test_non_matching_build_force(conanfile):\n    output = RedirectedTestOutput()\n    with redirect_output(output):\n        reference = RecipeReference.loads(\"Bar/0.1@user/testing\")\n        build_mode = BuildMode([\"hello\"])\n        assert build_mode.forced(conanfile, reference) is False\n\n\ndef test_full_reference_build_force(conanfile):\n    output = RedirectedTestOutput()\n    with redirect_output(output):\n        reference = RecipeReference.loads(\"bar/0.1@user/testing\")\n        build_mode = BuildMode([\"bar/0.1@user/testing\"])\n        assert build_mode.forced(conanfile, reference) is True\n\n\ndef test_non_matching_full_reference_build_force(conanfile):\n    output = RedirectedTestOutput()\n    with redirect_output(output):\n        reference = RecipeReference.loads(\"bar/0.1@user/stable\")\n        build_mode = BuildMode([\"bar/0.1@user/testing\"])\n        assert build_mode.forced(conanfile, reference) is False\n\n\ndef test_multiple_builds(conanfile):\n    output = RedirectedTestOutput()\n    with redirect_output(output):\n        reference = RecipeReference.loads(\"bar/0.1@user/stable\")\n        build_mode = BuildMode([\"bar/*\", \"Foo/*\"])\n        assert build_mode.forced(conanfile, reference) is True\n\n\ndef test_allowed(conanfile):\n    build_mode = BuildMode([\"missing\"])\n    assert build_mode.allowed(conanfile) is True\n\n    build_mode = BuildMode(None)\n    assert build_mode.allowed(conanfile) is False\n\n\ndef test_casing(conanfile):\n    output = RedirectedTestOutput()\n    with redirect_output(output):\n        reference = RecipeReference.loads(\"boost/1.69.0@user/stable\")\n\n        build_mode = BuildMode([\"boost*\"])\n        assert build_mode.forced(conanfile, reference) is True\n        build_mode = BuildMode([\"bo*\"])\n        assert build_mode.forced(conanfile, reference) is True\n\n        output.clear()\n        build_mode = BuildMode([\"Boost*\"])\n        assert build_mode.forced(conanfile, reference) is False\n        build_mode = BuildMode([\"Bo*\"])\n        assert build_mode.forced(conanfile, reference) is False\n\n\ndef test_pattern_matching(conanfile):\n    output = RedirectedTestOutput()\n    with redirect_output(output):\n        build_mode = BuildMode([\"boost*\"])\n        reference = RecipeReference.loads(\"boost/1.69.0@user/stable\")\n        assert (build_mode.forced(conanfile, reference)) is True\n        reference = RecipeReference.loads(\"boost_addons/1.0.0@user/stable\")\n        assert (build_mode.forced(conanfile, reference)) is True\n        reference = RecipeReference.loads(\"myboost/1.0@user/stable\")\n        assert (build_mode.forced(conanfile, reference)) is False\n        reference = RecipeReference.loads(\"foo/boost@user/stable\")\n        assert (build_mode.forced(conanfile, reference)) is False\n        reference = RecipeReference.loads(\"foo/1.0@boost/stable\")\n        assert (build_mode.forced(conanfile, reference)) is False\n        reference = RecipeReference.loads(\"foo/1.0@user/boost\")\n        assert build_mode.forced(conanfile, reference) is False\n\n        build_mode = BuildMode([\"foo/*@user/stable\"])\n        reference = RecipeReference.loads(\"foo/1.0.0@user/stable\")\n        assert build_mode.forced(conanfile, reference) is True\n        reference = RecipeReference.loads(\"foo/1.0@user/stable\")\n        assert build_mode.forced(conanfile, reference) is True\n        reference = RecipeReference.loads(\"foo/1.0.0-abcdefg@user/stable\")\n        assert build_mode.forced(conanfile, reference) is True\n\n        build_mode = BuildMode([\"*@user/stable\"])\n        reference = RecipeReference.loads(\"foo/1.0.0@user/stable\")\n        assert build_mode.forced(conanfile, reference) is True\n        reference = RecipeReference.loads(\"bar/1.0@user/stable\")\n        assert build_mode.forced(conanfile, reference) is True\n        reference = RecipeReference.loads(\"foo/1.0.0-abcdefg@user/stable\")\n        assert build_mode.forced(conanfile, reference) is True\n        reference = RecipeReference.loads(\"foo/1.0.0@NewUser/stable\")\n        assert build_mode.forced(conanfile, reference) is False\n\n        build_mode = BuildMode([\"*tool*\"])\n        reference = RecipeReference.loads(\"tool/0.1@lasote/stable\")\n        assert build_mode.forced(conanfile, reference) is True\n        reference = RecipeReference.loads(\"pythontool/0.1@lasote/stable\")\n        assert build_mode.forced(conanfile, reference) is True\n        reference = RecipeReference.loads(\"sometool/1.2@user/channel\")\n        assert build_mode.forced(conanfile, reference) is True\n\n        build_mode = BuildMode([\"tool/*\"])\n        reference = RecipeReference.loads(\"tool/0.1@lasote/stable\")\n        assert build_mode.forced(conanfile, reference) is True\n        reference = RecipeReference.loads(\"tool/1.1@user/testing\")\n        assert build_mode.forced(conanfile, reference) is True\n        reference = RecipeReference.loads(\"pythontool/0.1@lasote/stable\")\n        assert build_mode.forced(conanfile, reference) is False\n"
  },
  {
    "path": "test/unittests/client/graph/deps_graph_test.py",
    "content": "from unittest.mock import Mock\n\nfrom conan.internal.graph.graph import CONTEXT_HOST\nfrom conan.internal.graph.graph_builder import DepsGraph, Node\nfrom conan.internal.model.conan_file import ConanFile\nfrom conan.api.model import RecipeReference\n\n\nclass TestDepsGraph:\n\n    def test_node(self):\n        \"\"\" nodes are different even if contain same values,\n        so they can be repeated if necessary in the graph (common\n        static libraries)\n        \"\"\"\n        ref1 = RecipeReference.loads(\"hello/0.1@user/stable\")\n        ref2 = RecipeReference.loads(\"hello/0.1@user/stable\")\n\n        conanfile1 = ConanFile(None)\n        conanfile2 = ConanFile(None)\n        n1 = Node(ref1, conanfile1, context=CONTEXT_HOST)\n        n2 = Node(ref2, conanfile2, context=CONTEXT_HOST)\n\n        assert n1 != n2\n\n    def test_basic_levels(self):\n        ref1 = RecipeReference.loads(\"hello/1.0@user/stable\")\n        ref2 = RecipeReference.loads(\"hello/2.0@user/stable\")\n        ref3 = RecipeReference.loads(\"hello/3.0@user/stable\")\n\n        deps = DepsGraph()\n        n1 = Node(ref1, Mock(), context=CONTEXT_HOST)\n        n2 = Node(ref2, Mock(), context=CONTEXT_HOST)\n        n3 = Node(ref3, Mock(), context=CONTEXT_HOST)\n        deps.add_node(n1)\n        deps.add_node(n2)\n        deps.add_node(n3)\n        deps.add_edge(n1, n2, None)\n        deps.add_edge(n2, n3, None)\n        assert [[n3], [n2], [n1]] == deps.by_levels()\n\n    def test_multi_levels(self):\n        ref1 = RecipeReference.loads(\"hello/1.0@user/stable\")\n        ref2 = RecipeReference.loads(\"hello/2.0@user/stable\")\n        ref31 = RecipeReference.loads(\"hello/31.0@user/stable\")\n        ref32 = RecipeReference.loads(\"hello/32.0@user/stable\")\n\n        deps = DepsGraph()\n        n1 = Node(ref1, Mock(), context=CONTEXT_HOST)\n        n2 = Node(ref2, Mock(), context=CONTEXT_HOST)\n        n31 = Node(ref31, Mock(), context=CONTEXT_HOST)\n        n32 = Node(ref32, Mock(), context=CONTEXT_HOST)\n        deps.add_node(n1)\n        deps.add_node(n2)\n        deps.add_node(n32)\n        deps.add_node(n31)\n        deps.add_edge(n1, n2, None)\n        deps.add_edge(n2, n31, None)\n        deps.add_edge(n2, n32, None)\n        assert [[n31, n32], [n2], [n1]] == deps.by_levels()\n\n    def test_multi_levels_2(self):\n\n        ref1 = RecipeReference.loads(\"hello/1.0@user/stable\")\n        ref2 = RecipeReference.loads(\"hello/2.0@user/stable\")\n        ref5 = RecipeReference.loads(\"hello/5.0@user/stable\")\n        ref31 = RecipeReference.loads(\"hello/31.0@user/stable\")\n        ref32 = RecipeReference.loads(\"hello/32.0@user/stable\")\n\n        deps = DepsGraph()\n        n1 = Node(ref1, Mock(), context=CONTEXT_HOST)\n        n2 = Node(ref2, Mock(), context=CONTEXT_HOST)\n        n5 = Node(ref5, Mock(), context=CONTEXT_HOST)\n        n31 = Node(ref31, Mock(), context=CONTEXT_HOST)\n        n32 = Node(ref32, Mock(), context=CONTEXT_HOST)\n        deps.add_node(n1)\n        deps.add_node(n5)\n        deps.add_node(n2)\n        deps.add_node(n32)\n        deps.add_node(n31)\n        deps.add_edge(n1, n2, None)\n        deps.add_edge(n1, n5, None)\n        deps.add_edge(n2, n31, None)\n        deps.add_edge(n2, n32, None)\n        assert [[n31, n32, n5], [n2], [n1]] == deps.by_levels()\n\n    def test_multi_levels_3(self):\n\n        ref1 = RecipeReference.loads(\"hello/1.0@user/stable\")\n        ref2 = RecipeReference.loads(\"hello/2.0@user/stable\")\n        ref5 = RecipeReference.loads(\"hello/5.0@user/stable\")\n        ref31 = RecipeReference.loads(\"hello/31.0@user/stable\")\n        ref32 = RecipeReference.loads(\"hello/32.0@user/stable\")\n\n        deps = DepsGraph()\n        n1 = Node(ref1, Mock(), context=CONTEXT_HOST)\n        n2 = Node(ref2, Mock(), context=CONTEXT_HOST)\n        n5 = Node(ref5, Mock(), context=CONTEXT_HOST)\n        n31 = Node(ref31, Mock(), context=CONTEXT_HOST)\n        n32 = Node(ref32, Mock(), context=CONTEXT_HOST)\n        deps.add_node(n1)\n        deps.add_node(n5)\n        deps.add_node(n2)\n        deps.add_node(n32)\n        deps.add_node(n31)\n        deps.add_edge(n1, n2, None)\n        deps.add_edge(n1, n5, None)\n        deps.add_edge(n2, n31, None)\n        deps.add_edge(n2, n32, None)\n        deps.add_edge(n32, n5, None)\n        assert [[n31, n5], [n32], [n2], [n1]] == deps.by_levels()\n"
  },
  {
    "path": "test/unittests/client/migrations/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/client/migrations/test_migrator.py",
    "content": "import os\nimport platform\n\nimport pytest\n\nfrom conan.errors import ConanMigrationError\nfrom conans.migrations import Migrator\nfrom conan.test.utils.test_files import temp_folder\n\n\nclass FakeMigrator(Migrator):\n\n    def __init__(self, cache_folder, current_version):\n        self.cache_folder = cache_folder\n        super(FakeMigrator, self).__init__(cache_folder, current_version)\n\n\nclass TestMigratorPermissionTest:\n\n    @pytest.mark.skipif(platform.system() == \"Windows\", reason=\"Can't apply chmod on Windows\")\n    def test_invalid_permission(self):\n        conf_path = temp_folder(False)\n        os.chmod(conf_path, 0o444)\n        conf_path = os.path.join(conf_path, \"foo\")\n        migrator = FakeMigrator(conf_path, \"latest\")\n        with pytest.raises(ConanMigrationError) as error:\n            migrator.migrate()\n        assert f\"Can't write version file in '{conf_path}/version.txt'\" in str(error.value)\n"
  },
  {
    "path": "test/unittests/client/optimize_conanfile_load_test.py",
    "content": "\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestOptimizeConanFileLoad:\n\n    def test_multiple_load(self):\n        \"\"\" when a conanfile is used more than once in a dependency graph, the python file\n        should be read and interpreted just once, then instance 2 different ConanFile\n        objects. The module global value \"mycounter\" is global to all instances, this\n        should be discouraged to use as if it was an instance value.\n        In this test there are 2 nodes \"build/0.1\" as it is a build-requires of both the\n        conanfile.py and the test_package/conanfile.py\n        \"\"\"\n        client = TestClient()\n        conanfile = \"\"\"from conan import ConanFile\nmycounter = 0\nclass Pkg(ConanFile):\n    mycounter2 = 0\n    def configure(self):\n        global mycounter\n        mycounter += 1\n        self.mycounter2 += 1\n        self.output.info(\"MyCounter1 %s, MyCounter2 %s\" % (mycounter, self.mycounter2))\n\"\"\"\n        client.save({\"conanfile.py\": conanfile})\n\n        client.run(\"create . --name=build --version=0.1 --user=user --channel=testing\")\n\n        test_conanfile = conanfile + \"\"\"\n    def requirements(self):\n        self.requires(self.tested_reference_str)\n\n    def test(self):\n        pass\n        \"\"\"\n        client.save({\"conanfile.py\": conanfile,\n                     \"test_package/conanfile.py\": test_conanfile,\n                     \"myprofile\": \"[tool_requires]\\nbuild/0.1@user/testing\"})\n\n        client.run(\"create . --name=pkg --version=0.1 --user=user --channel=testing -pr=myprofile\")\n        assert \"build/0.1@user/testing: MyCounter1 2, MyCounter2 1\" in client.out\n"
  },
  {
    "path": "test/unittests/client/pkg_sign_test.py",
    "content": "import json\nimport os\n\nimport pytest\n\nfrom conan.test.utils.tools import temp_folder, save_files, load\n\nfrom conan.internal.rest.pkg_sign import _save_manifest, _save_signatures, _verify_files_checksums\nfrom conan.errors import ConanException\n\n\n@pytest.fixture\ndef pkg_sign_tools():\n    main_folder = temp_folder()\n    artifacts_folder = os.path.join(main_folder, \"af\")\n    os.mkdir(artifacts_folder)\n    signature_folder = os.path.join(main_folder, \"sf\")\n    os.mkdir(signature_folder)\n    save_files(artifacts_folder, {\"conan_package.tgz\": \"\", \"conanmanifest.txt\": \"\"})\n    return artifacts_folder, signature_folder\n\n\ndef test_save_manifest_content_with_empty_files(pkg_sign_tools):\n    \"\"\"Test that _create_manifest_content correctly creates manifest for empty files.\"\"\"\n    artifacts_folder, signature_folder = pkg_sign_tools\n    _save_manifest(artifacts_folder, signature_folder)\n    content = json.loads(load(os.path.join(signature_folder, \"pkgsign-manifest.json\")))\n\n    # Verify structure\n    assert \"files\" in content\n    assert isinstance(content[\"files\"], list)\n    assert len(content[\"files\"]) == 2\n\n    # Files should be sorted alphabetically\n    files = content[\"files\"]\n    assert files[0][\"file\"] == \"conan_package.tgz\"\n    assert files[1][\"file\"] == \"conanmanifest.txt\"\n\n    # Empty file SHA256\n    empty_file_sha256 = \"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\"\n    assert files[0][\"sha256\"] == empty_file_sha256\n    assert files[1][\"sha256\"] == empty_file_sha256\n\n\ndef test_create_manifest_content_ignores_directories(pkg_sign_tools):\n    \"\"\"Test that _save_manifest creates a json file that only includes files, not directories.\"\"\"\n    artifacts_folder, signature_folder = pkg_sign_tools\n    # Create a subdirectory\n    subdir = os.path.join(artifacts_folder, \"subdir\")\n    os.mkdir(subdir)\n\n    _save_manifest(artifacts_folder, signature_folder)\n    content = json.loads(load(os.path.join(signature_folder, \"pkgsign-manifest.json\")))\n    filenames = [f[\"file\"] for f in content[\"files\"]]\n\n    # Should not include the directory\n    assert \"subdir\" not in filenames\n    assert len(content[\"files\"]) == 2  # Only the two original files\n\n\ndef test_save_load_manifest(pkg_sign_tools):\n    \"\"\"Test that saving and loading manifest preserves all data correctly.\"\"\"\n    artifacts_folder, signature_folder = pkg_sign_tools\n    _save_manifest(artifacts_folder, signature_folder)\n\n    # Verify file exists\n    manifest_path = os.path.join(signature_folder, \"pkgsign-manifest.json\")\n    assert os.path.isfile(manifest_path)\n\n    # Load and verify content\n    manifest = json.loads(load(manifest_path))\n    assert \"files\" in manifest\n    assert isinstance(manifest[\"files\"], list)\n    assert len(manifest[\"files\"]) == 2\n\n    # Verify files are sorted and contain expected data\n    filenames = [f[\"file\"] for f in manifest[\"files\"]]\n    assert filenames == [\"conan_package.tgz\", \"conanmanifest.txt\"]\n\n    # Verify each file entry has required fields\n    for file_entry in manifest[\"files\"]:\n        assert \"file\" in file_entry\n        assert \"sha256\" in file_entry\n        assert len(file_entry[\"sha256\"]) == 64\n\n\ndef test_save_load_signatures(pkg_sign_tools):\n    \"\"\"Test that saving and loading signatures preserves all data correctly.\"\"\"\n    artifacts_folder, signature_folder = pkg_sign_tools\n    # Manifest must exist before saving signatures\n    _save_manifest(artifacts_folder, signature_folder)\n\n    signatures = [{\n        \"method\": \"openssl-dgst\",\n        \"provider\": \"my-organization\",\n        \"sign_artifacts\": {\n            \"manifest\": \"pkgsign-manifest.json\",\n            \"conan_package.tgz\": \"conan_package.tgz.sig\",\n            \"conanmanifest.txt\": \"conanmanifest.txt.sig\"\n        }\n    }]\n    _save_signatures(signature_folder, signatures)\n\n    # Verify file exists\n    signatures_path = os.path.join(signature_folder, \"pkgsign-signatures.json\")\n    assert os.path.isfile(signatures_path)\n\n    # Load and verify content\n    loaded = json.loads(load(signatures_path))\n    assert len(loaded[\"signatures\"]) == 1\n\n    signature = loaded[\"signatures\"][0]\n    assert signature[\"method\"] == \"openssl-dgst\"\n    assert signature[\"provider\"] == \"my-organization\"\n    assert signature[\"sign_artifacts\"][\"manifest\"] == \"pkgsign-manifest.json\"\n    assert signature[\"sign_artifacts\"][\"conan_package.tgz\"] == \"conan_package.tgz.sig\"\n    assert signature[\"sign_artifacts\"][\"conanmanifest.txt\"] == \"conanmanifest.txt.sig\"\n\n\ndef test_save_signatures_with_multiple_signatures(pkg_sign_tools):\n    \"\"\"Test that _save_signatures can handle multiple signature entries.\"\"\"\n    artifacts_folder, signature_folder = pkg_sign_tools\n    _save_manifest(artifacts_folder, signature_folder)\n\n    signatures = [\n        {\n            \"method\": \"gpg\",\n            \"provider\": \"my-organization\",\n            \"sign_artifacts\": {\"signature\": \"pkgsign-manifest.json.gpg\"}\n        },\n        {\n            \"method\": \"cosign\",\n            \"provider\": \"my-organization\",\n            \"sign_artifacts\": {\"signature\": \"pkgsign-manifest.json.sig\"}\n        }\n    ]\n    _save_signatures(signature_folder, signatures)\n\n    signatures_path = os.path.join(signature_folder, \"pkgsign-signatures.json\")\n    loaded = json.loads(load(signatures_path))\n    assert len(loaded[\"signatures\"]) == 2\n    assert loaded[\"signatures\"][0][\"method\"] == \"gpg\"\n    assert loaded[\"signatures\"][0][\"sign_artifacts\"][\"signature\"] == \"pkgsign-manifest.json.gpg\"\n    assert loaded[\"signatures\"][1][\"method\"] == \"cosign\"\n    assert loaded[\"signatures\"][1][\"sign_artifacts\"][\"signature\"] == \"pkgsign-manifest.json.sig\"\n\n\ndef test_save_signatures_validates_required_fields(pkg_sign_tools):\n    \"\"\"Test that _save_signatures validates required signature fields.\"\"\"\n    artifacts_folder, signature_folder = pkg_sign_tools\n    _save_manifest(artifacts_folder, signature_folder)\n\n    # Missing method\n    with pytest.raises(ConanException, match=\"'method' is missing in signature data\"):\n        _save_signatures(signature_folder,\n                         [{\"provider\": \"my-organization\",\"sign_artifacts\": {}}])\n\n    # Missing provider\n    with pytest.raises(ConanException, match=\"'provider' is missing in signature data\"):\n        _save_signatures(signature_folder, [{\"method\": \"gpg\", \"sign_artifacts\": {}}])\n\n    # Missing sign_artifacts\n    with pytest.raises(ConanException, match=\"'sign_artifacts' is missing in signature data\"):\n        _save_signatures(signature_folder,\n                         [{\"method\": \"gpg\", \"provider\": \"my-organization\"}])\n\n    # sign_artifacts not a dict\n    with pytest.raises(ConanException, match=\"'sign_artifacts' must be a dict\"):\n        _save_signatures(signature_folder,\n                         [{\"method\": \"gpg\", \"provider\": \"my-organization\",\n                                    \"sign_artifacts\": \"not a dict\"}])\n\n\ndef test_verify_files_checksums_success(pkg_sign_tools):\n    \"\"\"Test that verify_files_checksums succeeds when all checksums match.\"\"\"\n    artifacts_folder, signature_folder = pkg_sign_tools\n    _save_manifest(artifacts_folder, signature_folder)\n\n    files = {\n        \"conan_package.tgz\": os.path.join(artifacts_folder, \"conan_package.tgz\"),\n        \"conanmanifest.txt\": os.path.join(artifacts_folder, \"conanmanifest.txt\")\n    }\n    # Should not raise an exception\n    _verify_files_checksums(signature_folder, files)\n\n\ndef test_verify_files_checksums_partial_files(pkg_sign_tools):\n    \"\"\"Test that verify_files_checksums works with a subset of files. This is to test in case that conan_sources.tgz is not present.\"\"\"\n    artifacts_folder, signature_folder = pkg_sign_tools\n    _save_manifest(artifacts_folder, signature_folder)\n\n    # Verify only one file\n    files = {\n        \"conanmanifest.txt\": os.path.join(artifacts_folder, \"conanmanifest.txt\")\n    }\n    # Should not raise an exception\n    _verify_files_checksums(signature_folder, files)\n\n\ndef test_verify_files_checksums_mismatch(pkg_sign_tools):\n    \"\"\"Test that verify_files_checksums raises exception when checksums don't match.\"\"\"\n    artifacts_folder, signature_folder = pkg_sign_tools\n    _save_manifest(artifacts_folder, signature_folder)\n\n    # Modify file content to cause checksum mismatch\n    modified_file = os.path.join(artifacts_folder, \"conan_package.tgz\")\n    with open(modified_file, \"w\") as f:\n        f.write(\"modified content\")\n\n    files = {\n        \"conan_package.tgz\": modified_file,\n        \"conanmanifest.txt\": os.path.join(artifacts_folder, \"conanmanifest.txt\")\n    }\n\n    with pytest.raises(ConanException, match=\"Checksum mismatch for file conan_package.tgz\"):\n        _verify_files_checksums(signature_folder, files)\n\n\ndef test_verify_files_checksums_missing_file_in_manifest(pkg_sign_tools):\n    \"\"\"Test that verify_files_checksums handles files not in manifest.\"\"\"\n    artifacts_folder, signature_folder = pkg_sign_tools\n    _save_manifest(artifacts_folder, signature_folder)\n\n    # Try to verify a file that doesn't exist in manifest\n    new_file = os.path.join(artifacts_folder, \"new_file.txt\")\n    with open(new_file, \"w\") as f:\n        f.write(\"content\")\n\n    files = {\"new_file.txt\": new_file}\n\n    # Should raise exception because file is not in manifest (expected_checksum is None)\n    with pytest.raises(ConanException, match=\"Checksum mismatch\"):\n        _verify_files_checksums(signature_folder, files)\n"
  },
  {
    "path": "test/unittests/client/profile_loader/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/client/profile_loader/compiler_cppstd_test.py",
    "content": "import os\nimport textwrap\n\nimport yaml\nimport pytest\nfrom jinja2 import Template\n\nfrom conan.internal.cache.cache import PkgCache\nfrom conan.internal.cache.home_paths import HomePaths\nfrom conan.internal.api.profile.profile_loader import ProfileLoader\nfrom conan.internal.default_settings import default_settings_yml\nfrom conan.errors import ConanException\nfrom conan.internal.model.conf import ConfDefinition\nfrom conan.internal.model.settings import Settings\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.internal.util.files import save\n\n\nclass TestSettingsCppStd:\n\n    @pytest.fixture(autouse=True)\n    def setup(self):\n        self.cache_folder = temp_folder()\n        self.cache = PkgCache(self.cache_folder, ConfDefinition())\n        self.home_paths = HomePaths(self.cache_folder)\n        save(self.home_paths.profile_plugin_path, \"\")\n\n    def _save_profile(self, compiler_cppstd=None, filename=\"default\"):\n        fullpath = os.path.join(self.home_paths.profiles_path, filename)\n\n        t = Template(textwrap.dedent(\"\"\"\n            [settings]\n            os=Macos\n            arch=x86_64\n            compiler=apple-clang\n            {% if compiler_cppstd %}compiler.cppstd={{ compiler_cppstd }}{% endif %}\n            compiler.libcxx=libc++\n            compiler.version=10.0\n            \"\"\"))\n\n        save(fullpath, t.render(compiler_cppstd=compiler_cppstd))\n        return filename\n\n    def test_no_compiler_cppstd(self):\n        # https://github.com/conan-io/conan/issues/5128\n        fullpath = os.path.join(self.home_paths.profiles_path, \"default\")\n        t = textwrap.dedent(\"\"\"\n            [settings]\n            os=Macos\n            arch=x86_64\n            compiler=apple-clang\n            compiler.libcxx=libc++\n            compiler.version=10.0\n            compiler.cppstd = 14\n            \"\"\")\n        save(fullpath, t)\n        profile_loader = ProfileLoader(self.cache_folder)\n        with pytest.raises(ConanException,\n                                    match=\"'settings.compiler.cppstd' doesn't exist for 'apple-clang'\"):\n            profile = profile_loader.from_cli_args([\"default\"], None, None, None, None)\n            settings = Settings(yaml.safe_load(default_settings_yml.replace(\"cppstd\", \"foobar\")))\n            profile.process_settings(settings)\n\n    def test_no_value(self):\n        self._save_profile()\n        profile_loader = ProfileLoader(self.cache_folder)\n        r = profile_loader.from_cli_args([\"default\"], None, None, None, None)\n        assert \"compiler.cppstd\" not in r.settings\n\n    def test_value_none(self):\n        self._save_profile(compiler_cppstd=\"None\")\n        profile_loader = ProfileLoader(self.cache_folder)\n        # It is incorrect to assign compiler.cppstd=None in the profile\n        with pytest.raises(ConanException, match=\"Invalid setting\"):\n            r = profile_loader.from_cli_args([\"default\"], None, None, None, None)\n            settings = Settings(yaml.safe_load(default_settings_yml))\n            r.process_settings(settings)\n\n    def test_value_valid(self):\n        self._save_profile(compiler_cppstd=\"11\")\n        profile_loader = ProfileLoader(self.cache_folder)\n        r = profile_loader.from_cli_args([\"default\"], None, None, None, None)\n        assert r.settings[\"compiler.cppstd\"] == \"11\"\n        assert \"cppstd\" not in r.settings\n\n    def test_value_invalid(self):\n        self._save_profile(compiler_cppstd=\"13\")\n        profile_loader = ProfileLoader(self.cache_folder)\n        with pytest.raises(ConanException, match=\"Invalid setting '13' is not a valid \"\n                                                    \"'settings.compiler.cppstd' value\"):\n            r = profile_loader.from_cli_args([\"default\"], None, None, None, None)\n            settings = Settings(yaml.safe_load(default_settings_yml))\n            r.process_settings(settings)\n"
  },
  {
    "path": "test/unittests/client/profile_loader/profile_loader_test.py",
    "content": "import os\nimport textwrap\n\nimport pytest\n\nfrom conan.internal.api.profile.profile_loader import _ProfileParser, ProfileLoader\nfrom conan.errors import ConanException\nfrom conan.api.model import RecipeReference\nfrom conan.test.utils.mocks import ConanFileMock, MockSettings\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.internal.util.files import save\n\n\ndef test_profile_parser():\n    txt = textwrap.dedent(r\"\"\"\n        include(a/path/to\\profile.txt)\n        include(other/path/to/file.txt)\n\n        [settings]\n        os=2\n        \"\"\")\n    a = _ProfileParser(txt)\n    assert a.includes == [r\"a/path/to\\profile.txt\", \"other/path/to/file.txt\"]\n    assert a.profile_text == textwrap.dedent(\"\"\"[settings]\nos=2\"\"\")\n\n    txt = \"\"\n    a = _ProfileParser(txt)\n    assert a.includes == []\n    assert a.profile_text == \"\"\n\n    txt = textwrap.dedent(r\"\"\"\n        includes(a/path/to\\profile.txt)\n        \"\"\")\n\n    with pytest.raises(ConanException):\n        try:\n            _ProfileParser(txt)\n        except Exception as error:\n            assert \"Error while parsing line 1\" in error.args[0]\n            raise\n\n\ndef test_profiles_includes():\n    tmp = temp_folder()\n\n    def save_profile(txt, name):\n        abs_profile_path = os.path.join(tmp, name)\n        save(abs_profile_path, txt)\n\n    os.mkdir(os.path.join(tmp, \"subdir\"))\n\n    profile0 = textwrap.dedent(\"\"\"\n            {% set ROOTVAR=0 %}\n\n\n            [tool_requires]\n            one/1.{{ROOTVAR}}@lasote/stable\n            two/1.2@lasote/stable\n        \"\"\")\n    save_profile(profile0, \"subdir/profile0.txt\")\n\n    profile1 = textwrap.dedent(\"\"\"\n            # Include in subdir, curdir\n            include(./profile0.txt)\n\n            [settings]\n            os=Windows\n            [options]\n            zlib*:aoption=1\n            zlib*:otheroption=1\n        \"\"\")\n\n    save_profile(profile1, \"subdir/profile1.txt\")\n\n    profile2 = textwrap.dedent(\"\"\"\n            #  Include in subdir\n            {% set MYVAR=1 %}\n            include(./subdir/profile1.txt)\n            [settings]\n            os={{MYVAR}}\n        \"\"\")\n\n    save_profile(profile2, \"profile2.txt\")\n    profile3 = textwrap.dedent(\"\"\"\n            [tool_requires]\n            one/1.5@lasote/stable\n        \"\"\")\n\n    save_profile(profile3, \"profile3.txt\")\n\n    profile4 = textwrap.dedent(\"\"\"\n            include(./profile2.txt)\n            include(./profile3.txt)\n\n            [options]\n            zlib*:otheroption=12\n        \"\"\")\n\n    save_profile(profile4, \"profile4.txt\")\n\n    profile_loader = ProfileLoader(cache_folder=temp_folder())  # If not used cache, will not error\n    profile = profile_loader.load_profile(\"./profile4.txt\", tmp)\n\n    assert profile.settings == {\"os\": \"1\"}\n    assert profile.options[\"zlib*\"].aoption == 1\n    assert profile.options[\"zlib*\"].otheroption == 12\n    assert profile.tool_requires == {\"*\": [RecipeReference.loads(\"one/1.5@lasote/stable\"),\n                                           RecipeReference.loads(\"two/1.2@lasote/stable\")]}\n\n\ndef test_profile_compose_platform_tool_requires():\n    tmp = temp_folder()\n    save(os.path.join(tmp, \"profile0\"), \"[platform_tool_requires]\\ntool1/1.0\")\n    save(os.path.join(tmp, \"profile1\"), \"[platform_tool_requires]\\ntool2/2.0\")\n    save(os.path.join(tmp, \"profile2\"), \"include(./profile0)\\n[platform_tool_requires]\\ntool3/3.0\")\n    save(os.path.join(tmp, \"profile3\"), \"include(./profile0)\\n[platform_tool_requires]\\ntool1/1.1\")\n\n    profile_loader = ProfileLoader(cache_folder=temp_folder())  # If not used cache, will not error\n    profile2 = profile_loader.load_profile(\"./profile2\", tmp)\n    assert profile2.platform_tool_requires == [RecipeReference.loads(\"tool1/1.0\"),\n                                               RecipeReference.loads(\"tool3/3.0\")]\n    profile3 = profile_loader.load_profile(\"./profile3\", tmp)\n    assert profile3.platform_tool_requires == [RecipeReference.loads(\"tool1/1.1\")]\n    profile0 = profile_loader.load_profile(\"./profile0\", tmp)\n    profile1 = profile_loader.load_profile(\"./profile1\", tmp)\n    profile0.compose_profile(profile1)\n    assert profile0.platform_tool_requires == [RecipeReference.loads(\"tool1/1.0\"),\n                                               RecipeReference.loads(\"tool2/2.0\")]\n\n\ndef test_profile_compose_tool_requires():\n    tmp = temp_folder()\n    save(os.path.join(tmp, \"profile0\"), \"[tool_requires]\\ntool1/1.0\")\n    save(os.path.join(tmp, \"profile1\"), \"[tool_requires]\\ntool2/2.0\")\n    save(os.path.join(tmp, \"profile2\"), \"include(./profile0)\\n[tool_requires]\\ntool3/3.0\")\n    save(os.path.join(tmp, \"profile3\"), \"include(./profile0)\\n[tool_requires]\\ntool1/1.1\")\n\n    profile_loader = ProfileLoader(cache_folder=temp_folder())  # If not used cache, will not error\n    profile2 = profile_loader.load_profile(\"./profile2\", tmp)\n    assert profile2.tool_requires == {\"*\": [RecipeReference.loads(\"tool1/1.0\"),\n                                            RecipeReference.loads(\"tool3/3.0\")]}\n    profile3 = profile_loader.load_profile(\"./profile3\", tmp)\n    assert profile3.tool_requires == {\"*\": [RecipeReference.loads(\"tool1/1.1\")]}\n\n    profile0 = profile_loader.load_profile(\"./profile0\", tmp)\n    profile1 = profile_loader.load_profile(\"./profile1\", tmp)\n    profile0.compose_profile(profile1)\n    assert profile0.tool_requires == {\"*\": [RecipeReference.loads(\"tool1/1.0\"),\n                                            RecipeReference.loads(\"tool2/2.0\")]}\n\n\ndef test_profile_include_order():\n    tmp = temp_folder()\n\n    save(os.path.join(tmp, \"profile1.txt\"), '{% set MYVAR=\"fromProfile1\" %}')\n\n    profile2 = textwrap.dedent(\"\"\"\n            include(./profile1.txt)\n            {% set MYVAR=\"fromProfile2\" %}\n            [settings]\n            os={{MYVAR}}\n        \"\"\")\n    save(os.path.join(tmp, \"profile2.txt\"), profile2)\n    profile_loader = ProfileLoader(cache_folder=temp_folder())  # If not used cache, will not error\n    profile = profile_loader.load_profile(\"./profile2.txt\", tmp)\n\n    assert profile.settings[\"os\"] == \"fromProfile2\"\n\n\ndef test_profile_load_absolute_path():\n    \"\"\" When passing absolute path as profile file, it MUST be used.\n        read_profile(/abs/path/profile, /abs, /.conan/profiles)\n        /abs/path/profile MUST be consumed as target profile\n    \"\"\"\n    current_profile_folder = temp_folder()\n    current_profile_path = os.path.join(current_profile_folder, \"default\")\n    save(current_profile_path, \"[settings]\\nos=Windows\")\n\n    profile_loader = ProfileLoader(cache_folder=temp_folder())  # If not used cache, will not error\n    profile = profile_loader.load_profile(current_profile_path)\n    assert \"Windows\" == profile.settings[\"os\"]\n\n\ndef test_profile_load_relative_path_dot():\n    \"\"\" When passing relative ./path as profile file, it MUST be used\n        read_profile(./profiles/profile, /tmp, /.conan/profiles)\n        /tmp/profiles/profile MUST be consumed as target profile\n    \"\"\"\n    current_profile_folder = temp_folder()\n    current_profile_path = os.path.join(current_profile_folder, \"profiles\", \"default\")\n    save(current_profile_path, \"[settings]\\nos=Windows\")\n\n    profile_loader = ProfileLoader(cache_folder=temp_folder())  # If not used cache, will not error\n    profile = profile_loader.load_profile(\"./profiles/default\", current_profile_folder)\n    assert \"Windows\" == profile.settings[\"os\"]\n\n\ndef test_profile_load_relative_path_pardir():\n    \"\"\" When passing relative ../path as profile file, it MUST be used\n        read_profile(../profiles/profile, /tmp/current, /.conan/profiles)\n        /tmp/profiles/profile MUST be consumed as target profile\n    \"\"\"\n    tmp = temp_folder()\n    current_profile_path = os.path.join(tmp, \"profiles\", \"default\")\n    cwd = os.path.join(tmp, \"user_folder\")\n    save(current_profile_path, \"[settings]\\nos=Windows\")\n\n    profile_loader = ProfileLoader(cache_folder=temp_folder())  # If not used cache, will not error\n    profile = profile_loader.load_profile(\"../profiles/default\", cwd)\n    assert \"Windows\" == profile.settings[\"os\"]\n\n\ndef test_profile_buildenv():\n    tmp = temp_folder()\n    txt = textwrap.dedent(\"\"\"\n        [buildenv]\n        MyVar1=My Value; 11\n        MyVar1+=MyValue12\n        MyPath1=(path)/some/path11\n        MyPath1+=(path)/other path/path12\n        \"\"\")\n    current_profile_path = os.path.join(tmp, \"default\")\n    save(current_profile_path, txt)\n\n    profile_loader = ProfileLoader(cache_folder=temp_folder())  # If not used cache, will not error\n    profile = profile_loader.load_profile(current_profile_path)\n    buildenv = profile.buildenv\n    env = buildenv.get_profile_env(None)\n    conanfile = ConanFileMock()\n    conanfile.settings_build = MockSettings({\"os\": \"Linux\", \"arch\": \"x86_64\"})\n    env_vars = env.vars(conanfile)\n    assert env_vars.get(\"MyVar1\") == \"My Value; 11 MyValue12\"\n    assert env_vars.get(\"MyPath1\") == \"/some/path11:/other path/path12\"\n\n    conanfile.settings_build = MockSettings({\"os\": \"Windows\", \"arch\": \"x86_64\"})\n    env_vars = env.vars(conanfile)\n    assert env_vars.get(\"MyPath1\") == \"/some/path11;/other path/path12\"\n\n\n@pytest.mark.parametrize(\"conf_name\", [\n    \"core.gzip:compresslevel=5\",\n    \"core.gzip:compresslevel\"\n])\ndef test_profile_core_confs_error(conf_name):\n    tmp = temp_folder()\n    current_profile_path = os.path.join(tmp, \"default\")\n    save(current_profile_path, \"\")\n\n    profile_loader = ProfileLoader(cache_folder=temp_folder())  # If not used cache, will not error\n\n    with pytest.raises(ConanException) as exc:\n        profile_loader.from_cli_args([], [], [], [conf_name], None)\n    assert \"[conf] 'core.*' configurations are not allowed in profiles\" in str(exc.value)\n\n\ndef test_profile_compose_numbers():\n    tmp = temp_folder()\n    txt = textwrap.dedent(\"\"\"\n            [conf]\n            user.version:value=8.1\n            pkg/*:user.version:value=10\n            \"\"\")\n    current_profile_path = os.path.join(tmp, \"default\")\n    save(current_profile_path, txt)\n\n    profile_loader = ProfileLoader(cache_folder=temp_folder())  # If not used cache, will not error\n    profile = profile_loader.load_profile(current_profile_path)\n    assert profile.conf.get(\"user.version:value\") == 8.1\n    assert profile.conf.get(\"pkg/*:user.version:value\") == 10\n"
  },
  {
    "path": "test/unittests/client/remote_manager_test.py",
    "content": "import os\nimport sys\n\nimport pytest\n\nfrom conan.internal.api.uploader import compress_files\nfrom conan.internal.rest.remote_manager import uncompress_file\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.internal.util.files import save\n\n\nclass TestRemoteManager:\n\n    def test_compress_files_tgz(self):\n        folder = temp_folder()\n        save(os.path.join(folder, \"one_file.txt\"), \"The contents\")\n        save(os.path.join(folder, \"Two_file.txt\"), \"Two contents\")\n\n        files = {\n            \"one_file.txt\": os.path.join(folder, \"one_file.txt\"),\n            \"Two_file.txt\": os.path.join(folder, \"Two_file.txt\"),\n        }\n\n        path = compress_files(files, \"conan_package.tgz\", dest_dir=folder)\n        assert os.path.exists(path)\n        expected_path = os.path.join(folder, \"conan_package.tgz\")\n        assert path == expected_path\n\n    def test_compress_and_uncompress_xz_files(self):\n        folder = temp_folder()\n        save(os.path.join(folder, \"one_file.txt\"), \"The contents\")\n        save(os.path.join(folder, \"Two_file.txt\"), \"Two contents\")\n\n        files = {\n            \"one_file.txt\": os.path.join(folder, \"one_file.txt\"),\n            \"Two_file.txt\": os.path.join(folder, \"Two_file.txt\"),\n        }\n\n        path = compress_files(files, \"conan_package.txz\", dest_dir=folder)\n        assert os.path.exists(path)\n        expected_path = os.path.join(folder, \"conan_package.txz\")\n        assert path == expected_path\n\n        extract_dir = os.path.join(folder, \"extracted\")\n        uncompress_file(path, extract_dir)\n\n        extract_files = list(sorted(os.listdir(extract_dir)))\n        expected_files = sorted(files.keys())\n        assert extract_files == expected_files\n\n        for name, path in files.items():\n            extract_path = os.path.join(extract_dir, name)\n            with open(path, \"r\") as f1, open(extract_path, \"r\") as f2:\n                assert f1.read() == f2.read()\n\n    @pytest.mark.skipif(sys.version_info.minor < 14, reason=\"zstd needs Python >= 3.14\")\n    def test_compress_and_uncompress_zst_files(self):\n        folder = temp_folder()\n        save(os.path.join(folder, \"one_file.txt\"), \"The contents\")\n        save(os.path.join(folder, \"Two_file.txt\"), \"Two contents\")\n\n        files = {\n            \"one_file.txt\": os.path.join(folder, \"one_file.txt\"),\n            \"Two_file.txt\": os.path.join(folder, \"Two_file.txt\"),\n        }\n\n        path = compress_files(files, \"conan_package.tzst\", dest_dir=folder)\n        assert os.path.exists(path)\n        expected_path = os.path.join(folder, \"conan_package.tzst\")\n        assert path == expected_path\n\n        extract_dir = os.path.join(folder, \"extracted\")\n        uncompress_file(path, extract_dir)\n\n        extract_files = list(sorted(os.listdir(extract_dir)))\n        expected_files = sorted(files.keys())\n        assert extract_files == expected_files\n\n        for name, path in sorted(files.items()):\n            extract_path = os.path.join(extract_dir, name)\n            with open(path, \"r\") as f1, open(extract_path, \"r\") as f2:\n                assert f1.read() == f2.read()\n"
  },
  {
    "path": "test/unittests/client/rest/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/client/rest/downloader_test.py",
    "content": "import os\nimport re\nimport tempfile\n\nimport pytest\n\nfrom conan.internal.rest.file_downloader import FileDownloader\nfrom conan.errors import ConanException\n\n\nclass MockResponse:\n    def __init__(self, data, headers, status_code=200):\n        self.data = data\n        self.ok = True\n        self.status_code = status_code\n        self.headers = headers.copy()\n        self.headers.update({key.lower(): value for key, value in headers.items()})\n\n    def iter_content(self, size):\n        for i in range(0, len(self.data), size):\n            yield self.data[i:i + size]\n\n    def close(self):\n        pass\n\n\nclass MockRequester:\n\n    def __init__(self, data, chunk_size=None, accept_ranges=True, echo_header=None):\n        self._data = data\n        self._chunk_size = chunk_size if chunk_size is not None else len(data)\n        self._accept_ranges = accept_ranges\n        self._echo_header = echo_header.copy() if echo_header else {}\n\n    def get(self, *_args, **kwargs):\n        start = 0\n        headers = kwargs.get(\"headers\") or {}\n        transfer_range = headers.get(\"range\", \"\")\n        match = re.match(r\"bytes=([0-9]+)-\", transfer_range)\n        status = 200\n        headers = {\"Content-Length\": len(self._data), \"Accept-Ranges\": \"bytes\"}\n        if match and self._accept_ranges:\n            start = int(match.groups()[0])\n            assert start < len(self._data)\n            status = 206\n            headers.update({\"Content-Length\": str(len(self._data) - start),\n                            \"Content-Range\": \"bytes {}-{}/{}\".format(start, len(self._data) - 1,\n                                                                     len(self._data))})\n        else:\n            headers.update(self._echo_header)\n        response = MockResponse(self._data[start:start + self._chunk_size], status_code=status,\n                                headers=headers)\n        return response\n\n\nclass TestDownloaderUnit:\n    @pytest.fixture(autouse=True)\n    def setup(self):\n        d = tempfile.mkdtemp()\n        self.target = os.path.join(d, \"target\")\n\n    def test_succeed_download_to_file_if_not_interrupted(self):\n        expected_content = b\"some data\"\n        requester = MockRequester(expected_content)\n        downloader = FileDownloader(requester=requester)\n        downloader.download(\"fake_url\", file_path=self.target)\n        actual_content = open(self.target, \"rb\").read()\n        assert expected_content == actual_content\n\n    def test_resume_download_to_file_if_interrupted(self):\n        expected_content = b\"some data\"\n        requester = MockRequester(expected_content, chunk_size=4)\n        downloader = FileDownloader(requester=requester)\n        downloader.download(\"fake_url\", file_path=self.target, verify_ssl=None,\n                            retry=0, retry_wait=0)\n        actual_content = open(self.target, \"rb\").read()\n        assert expected_content == actual_content\n\n    def test_fail_interrupted_download_to_file_if_no_progress(self):\n        expected_content = b\"some data\"\n        requester = MockRequester(expected_content, chunk_size=0)\n        downloader = FileDownloader(requester=requester)\n        with pytest.raises(ConanException, match=r\"Download failed\"):\n            downloader.download(\"fake_url\", file_path=self.target)\n\n    def test_fail_interrupted_download_if_server_not_accepting_ranges(self):\n        expected_content = b\"some data\"\n        requester = MockRequester(expected_content, chunk_size=4, accept_ranges=False)\n        downloader = FileDownloader(requester=requester)\n        with pytest.raises(ConanException, match=r\"Incorrect Content-Range header\"):\n            downloader.download(\"fake_url\", file_path=self.target)\n\n    def test_download_with_compressed_content_and_bigger_content_length(self):\n        expected_content = b\"some data\"\n        echo_header = {\"Content-Encoding\": \"gzip\", \"Content-Length\": len(expected_content) + 1}\n        requester = MockRequester(expected_content, echo_header=echo_header)\n        downloader = FileDownloader(requester=requester)\n        downloader.download(\"fake_url\", file_path=self.target)\n        actual_content = open(self.target, \"rb\").read()\n        assert expected_content == actual_content\n\n    def test_download_with_compressed_content_and_smaller_content_length(self):\n        expected_content = b\"some data\"\n        echo_header = {\"Content-Encoding\": \"gzip\", \"Content-Length\": len(expected_content) - 1}\n        requester = MockRequester(expected_content, echo_header=echo_header)\n        downloader = FileDownloader(requester=requester)\n        downloader.download(\"fake_url\", file_path=self.target)\n        actual_content = open(self.target, \"rb\").read()\n        assert expected_content == actual_content\n"
  },
  {
    "path": "test/unittests/client/rest/requester_test.py",
    "content": "import os\n\nfrom conan.api.conan_api import ConanAPI\nfrom conan.internal.cache.home_paths import HomePaths\nfrom conan.internal.util.files import save\nfrom conan.test.utils.test_files import temp_folder\n\n\ndef test_requester_reinit():\n    \"\"\" Ensure the reinitialization of the requester gets the new global configuration \"\"\"\n    tmp_folder = temp_folder()\n    home_path = HomePaths(tmp_folder)\n    save(os.path.join(home_path.profiles_path, \"default\"), \"\")\n    conan_api = ConanAPI(tmp_folder)\n    save(os.path.join(home_path.global_conf_path), \"core.net.http:timeout=(10, 20)\")\n    conan_api.reinit()\n    assert conan_api._api_helpers.requester._timeout == (10, 20)\n"
  },
  {
    "path": "test/unittests/client/rest/response_test.py",
    "content": "from collections import namedtuple\nfrom conan.internal import rest\n\n\nclass TestRestString:\n\n    def _get_html_response(self):\n        headers = {\"content-type\": \"text/html;charset=utf-8\"}\n        return namedtuple(\"Response\", \"status_code headers reason content\")(\n            404,\n            headers,\n            \"Not Found\",\n            b'\\n<!doctype html>\\n<!--[if IE 9]><html class=\"lt-ie10\" lang=\"en\" >\\n</html>\\n')\n\n    def _get_json_response(self):\n        headers = {\"content-type\": \"application/json\"}\n        return namedtuple(\"Response\", \"status_code headers reason content\")(\n            404,\n            headers,\n            \"Not Found\",\n            b'Could not find the artifact')\n\n    def test_html_error(self):\n        response = self._get_html_response()\n        result = rest.response_to_str(response)\n        assert \"404: Not Found\" == result\n\n    def test_json_error(self):\n        response = self._get_json_response()\n        result = rest.response_to_str(response)\n        assert \"Could not find the artifact\" == result\n"
  },
  {
    "path": "test/unittests/client/rest/rest_client_v2/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/client/rest/rest_client_v2/rest_client_v2_test.py",
    "content": "from conan.internal.rest.rest_client_v2 import RestV2Methods\nfrom unittest.mock import MagicMock, patch\n\n\n@patch(\"conan.internal.rest.conan_requester.ConanRequester\")\ndef test_check_credentials_set_token_to_unset_with_force_auth_true_and_token_none(requester_mock):\n    return_status = MagicMock()\n    return_status.status_code = 200\n    requester_mock.get = MagicMock(return_value=return_status)\n\n    rest_v2_methods = RestV2Methods(\"foo\", None, requester_mock, None, True)\n    rest_v2_methods.check_credentials(True)\n\n    assert requester_mock.get.call_args[1][\"auth\"].bearer == \"Bearer unset\"\n\n\n@patch(\"conan.internal.rest.conan_requester.ConanRequester\")\ndef test_check_credentials_keep_token_none_with_force_auth_false_and_token_none(requester_mock):\n    return_status = MagicMock()\n    return_status.status_code = 200\n    requester_mock.get = MagicMock(return_value=return_status)\n\n    rest_v2_methods = RestV2Methods(\"foo\", None, requester_mock, None, True)\n    rest_v2_methods.check_credentials(False)\n\n    assert requester_mock.get.call_args[1][\"auth\"].bearer is None\n"
  },
  {
    "path": "test/unittests/client/rest/uploader_test.py",
    "content": "import tempfile\nfrom collections import namedtuple\n\nimport pytest\n\nfrom conan.internal.rest.file_uploader import FileUploader\nfrom conan.internal.errors import InternalErrorException, AuthenticationException, ForbiddenException\nfrom conan.internal.util.files import save\n\n\nclass _ConfigMock:\n    def get(self, name, default=None, check_type=None):\n        return default\n\n\nclass MockRequester:\n    retry = 0\n    retry_wait = 0\n\n    def __init__(self, response):\n        self._response = response\n\n    def put(self, *args, **kwargs):\n        return namedtuple(\"response\", \"status_code content\")(self._response, \"tururu\")\n\n\nclass TestUploaderUnit:\n    @pytest.fixture(autouse=True)\n    def setup(self):\n        _, self.f = tempfile.mkstemp()\n        save(self.f, \"some contents\")\n\n    def test_401_raises_unauthoirzed_exception(self):\n        uploader = FileUploader(MockRequester(401), verify=False, config=_ConfigMock())\n        with pytest.raises(AuthenticationException, match=\"tururu\"):\n            uploader.upload(\"fake_url\", self.f)\n\n    def test_403_raises_unauthoirzed_exception_if_no_token(self):\n        auth = namedtuple(\"auth\", \"bearer\")(None)\n        uploader = FileUploader(MockRequester(403), verify=False, config=_ConfigMock())\n        with pytest.raises(AuthenticationException, match=\"tururu\"):\n            uploader.upload(\"fake_url\", self.f, auth=auth)\n\n    def test_403_raises_unauthorized_exception_if_no_auth(self):\n        uploader = FileUploader(MockRequester(403), verify=False, config=_ConfigMock())\n        with pytest.raises(AuthenticationException, match=\"tururu\"):\n            uploader.upload(\"fake_url\", self.f)\n\n    def test_403_raises_forbidden_exception_if_token(self):\n        auth = namedtuple(\"auth\", \"bearer\")(\"SOMETOKEN\")\n        uploader = FileUploader(MockRequester(403), verify=False, config=_ConfigMock())\n        with pytest.raises(ForbiddenException, match=\"tururu\"):\n            uploader.upload(\"fake_url\", self.f, auth=auth)\n\n    def test_500_raises_internal_error(self):\n        uploader = FileUploader(MockRequester(500), verify=False, config=_ConfigMock())\n        _, f = tempfile.mkstemp()\n        save(f, \"some contents\")\n        with pytest.raises(InternalErrorException, match=\"tururu\"):\n            uploader.upload(\"fake_url\", self.f, dedup=True)\n"
  },
  {
    "path": "test/unittests/client/source/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/client/tools/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/client/tools/cppstd_required_test.py",
    "content": "import pytest\nfrom unittest import mock\n\nfrom conan.tools.build import check_max_cppstd, check_min_cppstd, valid_max_cppstd, valid_min_cppstd, \\\n    valid_min_cstd, valid_max_cstd\nfrom conan.test.utils.mocks import MockSettings, ConanFileMock\nfrom conan.errors import ConanException, ConanInvalidConfiguration\n\n\ndef _create_conanfile(compiler, version, os, cppstd, libcxx=None):\n    settings = MockSettings({\"arch\": \"x86_64\",\n                             \"build_type\": \"Debug\",\n                             \"os\": os,\n                             \"compiler\": compiler,\n                             \"compiler.version\": version,\n                             \"compiler.cppstd\": cppstd})\n    if libcxx:\n        settings.values[\"compiler.libcxx\"] = libcxx\n    conanfile = ConanFileMock(settings)\n    return conanfile\n\n\nclass TestUserInput:\n\n    def test_check_cppstd_type(self):\n        \"\"\" cppstd must be a number\n        \"\"\"\n        conanfile = ConanFileMock(MockSettings({}))\n        with pytest.raises(ConanException) as raises:\n            check_min_cppstd(conanfile, \"gnu17\", False)\n        assert \"cppstd parameter must be a number\" == str(raises.value)\n\n\nclass TestCheckMinCppStd:\n\n    @pytest.mark.parametrize(\"cppstd\", [\"98\", \"11\", \"14\", \"17\"])\n    def test_check_min_cppstd_from_settings(self, cppstd):\n        \"\"\" check_min_cppstd must accept cppstd less/equal than cppstd in settings\n        \"\"\"\n        conanfile = _create_conanfile(\"gcc\", \"9\", \"Linux\", \"17\", \"libstdc++\")\n        check_min_cppstd(conanfile, cppstd, False)\n\n    @pytest.mark.parametrize(\"cppstd\", [\"98\", \"11\", \"14\"])\n    def test_check_min_cppstd_from_outdated_settings(self, cppstd):\n        \"\"\" check_min_cppstd must raise when cppstd is greater when supported on settings\n        \"\"\"\n        conanfile = _create_conanfile(\"gcc\", \"9\", \"Linux\", cppstd, \"libstdc++\")\n        with pytest.raises(ConanInvalidConfiguration) as raises:\n            check_min_cppstd(conanfile, \"17\", False)\n        assert \"Current cppstd ({}) is lower than the required C++ standard (17).\".format(cppstd) == str(raises.value)\n\n    @pytest.mark.parametrize(\"cppstd\", [\"98\", \"11\", \"14\", \"17\"])\n    def test_check_min_cppstd_from_settings_with_extension(self, cppstd):\n        \"\"\" current cppstd in settings must has GNU extension when extensions is enabled\n        \"\"\"\n        conanfile = _create_conanfile(\"gcc\", \"9\", \"Linux\", \"gnu17\", \"libstdc++\")\n        check_min_cppstd(conanfile, cppstd, True)\n\n        conanfile.settings.values[\"compiler.cppstd\"] = \"17\"\n        with pytest.raises(ConanException) as raises:\n            check_min_cppstd(conanfile, cppstd, True)\n        assert \"The cppstd GNU extension is required\" == str(raises.value)\n\n    def test_check_min_cppstd_unsupported_standard(self):\n        \"\"\" check_min_cppstd must raise when the compiler does not support a standard\n        \"\"\"\n        conanfile = _create_conanfile(\"gcc\", \"9\", \"Linux\", \"gnu14\", \"libstdc++\")\n        with pytest.raises(ConanInvalidConfiguration) as raises:\n            check_min_cppstd(conanfile, \"42\", False)\n        assert \"Current cppstd (gnu14) is lower than the required C++ standard (42).\" == str(raises.value)\n\n    def test_check_min_cppstd_gnu_compiler_extension(self):\n        \"\"\" Current compiler must support GNU extension on Linux when extensions is required\n        \"\"\"\n        conanfile = _create_conanfile(\"gcc\", \"9\", \"Linux\", \"17\", \"libstdc++\")\n        with mock.patch(\"platform.system\", mock.MagicMock(return_value=\"Linux\")):\n            with pytest.raises(ConanException) as raises:\n                check_min_cppstd(conanfile, \"17\", True)\n            assert \"The cppstd GNU extension is required\" == str(raises.value)\n\n\nclass TestValidMinCppstd:\n\n    @pytest.mark.parametrize(\"cppstd\", [\"98\", \"11\", \"14\", \"17\"])\n    def test_valid_min_cppstd_from_settings(self, cppstd):\n        \"\"\" valid_min_cppstd must accept cppstd less/equal than cppstd in settings\n        \"\"\"\n        conanfile = _create_conanfile(\"gcc\", \"9\", \"Linux\", \"17\", \"libstdc++\")\n        assert valid_min_cppstd(conanfile, cppstd, False)\n\n    @pytest.mark.parametrize(\"cppstd\", [\"98\", \"11\", \"14\"])\n    def test_valid_min_cppstd_from_outdated_settings(self, cppstd):\n        \"\"\" valid_min_cppstd returns False when cppstd is greater when supported on settings\n        \"\"\"\n        conanfile = _create_conanfile(\"gcc\", \"9\", \"Linux\", cppstd, \"libstdc++\")\n        assert not valid_min_cppstd(conanfile, \"17\", False)\n\n    @pytest.mark.parametrize(\"cppstd\", [\"98\", \"11\", \"14\", \"17\"])\n    def test_valid_min_cppstd_from_settings_with_extension(self, cppstd):\n        \"\"\" valid_min_cppstd must returns True when current cppstd in settings has GNU extension and\n            extensions is enabled\n        \"\"\"\n        conanfile = _create_conanfile(\"gcc\", \"9\", \"Linux\", \"gnu17\", \"libstdc++\")\n        assert valid_min_cppstd(conanfile, cppstd, True)\n\n        conanfile.settings.values[\"compiler.cppstd\"] = \"17\"\n        assert not valid_min_cppstd(conanfile, cppstd, True)\n\n    def test_valid_min_cppstd_unsupported_standard(self):\n        \"\"\" valid_min_cppstd must returns False when the compiler does not support a standard\n        \"\"\"\n        conanfile = _create_conanfile(\"gcc\", \"9\", \"Linux\", \"17\", \"libstdc++\")\n        assert not valid_min_cppstd(conanfile, \"42\", False)\n\n    def test_valid_min_cppstd_gnu_compiler_extension(self):\n        \"\"\" valid_min_cppstd must returns False when current compiler does not support GNU extension\n            on Linux and extensions is required\n        \"\"\"\n        conanfile = _create_conanfile(\"gcc\", \"9\", \"Linux\", \"gnu1z\", \"libstdc++\")\n        with mock.patch(\"platform.system\", mock.MagicMock(return_value=\"Linux\")):\n            assert not valid_min_cppstd(conanfile, \"20\", True)\n\n    @pytest.mark.parametrize(\"cppstd\", [\"98\", \"11\", \"14\", \"17\"])\n    def test_min_cppstd_mingw_windows(self, cppstd):\n        \"\"\" GNU extensions HAS effect on Windows when running a cross-building for Linux\n        \"\"\"\n        with mock.patch(\"platform.system\", mock.MagicMock(return_value=\"Windows\")):\n            conanfile = _create_conanfile(\"gcc\", \"9\", \"Linux\", \"gnu17\", \"libstdc++\")\n            assert valid_min_cppstd(conanfile, cppstd, True)\n\n            conanfile.settings.values[\"compiler.cppstd\"] = \"17\"\n            assert not valid_min_cppstd(conanfile, cppstd, True)\n\n\nclass TestCheckMaxCppStd:\n\n    @pytest.mark.parametrize(\"cppstd\", [\"98\", \"11\", \"14\", \"17\"])\n    def test_check_max_cppstd_from_settings(self, cppstd):\n        \"\"\" check_max_cppstd must accept cppstd higher/equal than cppstd in settings\n        \"\"\"\n        conanfile = _create_conanfile(\"gcc\", \"9\", \"Linux\", \"98\", \"libstdc++\")\n        check_max_cppstd(conanfile, cppstd, False)\n\n    @pytest.mark.parametrize(\"cppstd\", [\"11\", \"14\", \"17\"])\n    def test_check_max_cppstd_from_outdated_settings(self, cppstd):\n        \"\"\" check_max_cppstd must raise when cppstd is higher when supported on settings\n        \"\"\"\n        conanfile = _create_conanfile(\"gcc\", \"9\", \"Linux\", cppstd, \"libstdc++\")\n        with pytest.raises(ConanInvalidConfiguration) as raises:\n            check_max_cppstd(conanfile, \"98\", False)\n        assert \"Current cppstd ({}) is higher than the required C++ standard (98).\".format(cppstd) == str(raises.value)\n\n    @pytest.mark.parametrize(\"cppstd\", [\"98\", \"11\", \"14\", \"17\"])\n    def test_check_max_cppstd_from_settings_with_extension(self, cppstd):\n        \"\"\" current cppstd in settings must have GNU extension when extensions is enabled\n        \"\"\"\n        conanfile = _create_conanfile(\"gcc\", \"9\", \"Linux\", \"gnu98\", \"libstdc++\")\n        check_max_cppstd(conanfile, cppstd, True)\n\n        conanfile.settings.values[\"compiler.cppstd\"] = \"98\"\n        with pytest.raises(ConanException) as raises:\n            check_max_cppstd(conanfile, cppstd, True)\n        assert \"The cppstd GNU extension is required\" == str(raises.value)\n\n    def test_check_max_cppstd_unsupported_standard(self):\n        \"\"\" check_max_cppstd must raise when the compiler does not support a standard\n        \"\"\"\n        conanfile = _create_conanfile(\"gcc\", \"9\", \"Linux\", \"gnu17\", \"libstdc++\")\n        with pytest.raises(ConanInvalidConfiguration) as raises:\n            check_max_cppstd(conanfile, \"16\", False)\n        assert \"Current cppstd (gnu17) is higher than the required C++ standard (16).\" == str(raises.value)\n\n    def test_check_max_cppstd_gnu_compiler_extension(self):\n        \"\"\" Current compiler must support GNU extension on Linux when extensions is required\n        \"\"\"\n        conanfile = _create_conanfile(\"gcc\", \"9\", \"Linux\", \"17\", \"libstdc++\")\n        with mock.patch(\"platform.system\", mock.MagicMock(return_value=\"Linux\")):\n            with pytest.raises(ConanException) as raises:\n                check_max_cppstd(conanfile, \"17\", True)\n            assert \"The cppstd GNU extension is required\" == str(raises.value)\n\n\nclass TestValidMaxCppstd:\n\n    @pytest.mark.parametrize(\"cppstd\", [\"98\", \"11\", \"14\", \"17\"])\n    def test_valid_max_cppstd_from_settings(self, cppstd):\n        \"\"\" valid_max_cppstd must accept cppstd higher/equal than cppstd in settings\n        \"\"\"\n        conanfile = _create_conanfile(\"gcc\", \"9\", \"Linux\", \"98\", \"libstdc++\")\n        assert valid_max_cppstd(conanfile, cppstd, False)\n\n    @pytest.mark.parametrize(\"cppstd\", [\"11\", \"14\", \"17\"])\n    def test_valid_max_cppstd_from_outdated_settings(self, cppstd):\n        \"\"\" valid_max_cppstd return False when cppstd is greater when supported on settings\n        \"\"\"\n        conanfile = _create_conanfile(\"gcc\", \"9\", \"Linux\", cppstd, \"libstdc++\")\n        assert not valid_max_cppstd(conanfile, \"98\", False)\n\n    @pytest.mark.parametrize(\"cppstd\", [\"98\", \"11\", \"14\", \"17\"])\n    def test_valid_max_cppstd_from_settings_with_extension(self, cppstd):\n        \"\"\" valid_max_cppstd must return True when current cppstd in settings has GNU extension and\n            extensions is enabled\n        \"\"\"\n        conanfile = _create_conanfile(\"gcc\", \"9\", \"Linux\", \"gnu98\", \"libstdc++\")\n        assert valid_max_cppstd(conanfile, cppstd, True)\n\n        conanfile.settings.values[\"compiler.cppstd\"] = \"98\"\n        assert not valid_max_cppstd(conanfile, cppstd, True)\n\n    def test_valid_max_cppstd_unsupported_standard(self):\n        \"\"\" valid_max_cppstd must return False when the compiler does not support a standard\n        \"\"\"\n        conanfile = _create_conanfile(\"gcc\", \"9\", \"Linux\", \"17\", \"libstdc++\")\n        assert not valid_max_cppstd(conanfile, \"16\", False)\n\n    def test_valid_max_cppstd_gnu_compiler_extension(self):\n        \"\"\" valid_max_cppstd must return False when current compiler does not support GNU extension\n            on Linux and extensions is required\n        \"\"\"\n        conanfile = _create_conanfile(\"gcc\", \"9\", \"Linux\", \"gnu17\", \"libstdc++\")\n        with mock.patch(\"platform.system\", mock.MagicMock(return_value=\"Linux\")):\n            assert not valid_max_cppstd(conanfile, \"14\", True)\n\n    @pytest.mark.parametrize(\"cppstd\", [\"98\", \"11\", \"14\", \"17\"])\n    def test_max_cppstd_mingw_windows(self, cppstd):\n        \"\"\" GNU extensions HAS effect on Windows when running a cross-building for Linux\n        \"\"\"\n        with mock.patch(\"platform.system\", mock.MagicMock(return_value=\"Windows\")):\n            conanfile = _create_conanfile(\"gcc\", \"9\", \"Linux\", \"gnu98\", \"libstdc++\")\n            assert valid_max_cppstd(conanfile, cppstd, True)\n\n            conanfile.settings.values[\"compiler.cppstd\"] = \"98\"\n            assert not valid_max_cppstd(conanfile, cppstd, True)\n\n\nclass TestCstd:\n\n    @pytest.mark.parametrize(\"compiler, cstd, mincstd, valid\",\n                             [[\"gcc\",  \"99\", \"99\", True],\n                              [\"gcc\",  \"gnu99\", \"99\", True],\n                              [\"gcc\", \"99\", \"11\", False]\n                              ])\n    def test_valid_min(self, compiler, cstd, mincstd, valid):\n        settings = MockSettings({\"arch\": \"x86_64\",\n                                 \"build_type\": \"Debug\",\n                                 \"os\": \"Linux\",\n                                 \"compiler\": compiler,\n                                 \"compiler.cstd\": cstd})\n        conanfile = ConanFileMock(settings)\n        if valid:\n            assert valid_min_cstd(conanfile, mincstd, False)\n        else:\n            assert not valid_min_cstd(conanfile, mincstd, False)\n\n    @pytest.mark.parametrize(\"compiler, cstd, maxcstd, valid\",\n                             [[\"gcc\", \"99\", \"11\", True],\n                              [\"gcc\", \"gnu99\", \"11\", True],\n                              [\"gcc\", \"17\", \"11\", False]\n                              ])\n    def test_valid_max(self, compiler, cstd, maxcstd, valid):\n        settings = MockSettings({\"arch\": \"x86_64\",\n                                 \"build_type\": \"Debug\",\n                                 \"os\": \"Linux\",\n                                 \"compiler\": compiler,\n                                 \"compiler.cstd\": cstd})\n        conanfile = ConanFileMock(settings)\n        if valid:\n            assert valid_max_cstd(conanfile, maxcstd, False)\n        else:\n            assert not valid_max_cstd(conanfile, maxcstd, False)\n\n    def test_error(self):\n        conanfile = ConanFileMock()\n        with pytest.raises(ConanException) as e:\n            valid_min_cstd(conanfile, \"potato\")\n        assert \"cstd parameter must be a number\" in str(e.value)\n"
  },
  {
    "path": "test/unittests/client/tools/files/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/client/tools/files/rename_test.py",
    "content": "import os\n\nfrom conan.tools.files import rename\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import chdir\n\n\nclass TestRename:\n\n    def test_rename(self):\n        client = TestClient()\n        folder = client.current_folder\n\n        sub_space_dir = \"sub dir\"\n        with chdir(folder):\n            os.makedirs(sub_space_dir)\n            os.makedirs(os.path.join(sub_space_dir, \"dir.pdb\"))\n            os.makedirs(os.path.join(sub_space_dir, \"middir\"))\n            os.makedirs(os.path.join(sub_space_dir, \"middir\", \"deepdir\"))\n\n        client.save({os.path.join(sub_space_dir, \"1.txt\"): \"\",\n                     os.path.join(sub_space_dir, \"1.pdb\"): \"\",\n                     os.path.join(sub_space_dir, \"1.pdb1\"): \"\",\n                     os.path.join(sub_space_dir, \"dir.pdb\", \"2.txt\"): \"\",\n                     os.path.join(sub_space_dir, \"dir.pdb\", \"2.pdb\"): \"\",\n                     os.path.join(sub_space_dir, \"dir.pdb\", \"2.pdb1\"): \"\",\n                     os.path.join(sub_space_dir, \"middir\", \"3.txt\"): \"\",\n                     os.path.join(sub_space_dir, \"middir\", \"3.pdb\"): \"\",\n                     os.path.join(sub_space_dir, \"middir\", \"3.pdb1\"): \"\",\n                     os.path.join(sub_space_dir, \"middir\", \"deepdir\", \"4.txt\"): \"\",\n                     os.path.join(sub_space_dir, \"middir\", \"deepdir\", \"4.pdb\"): \"\",\n                     os.path.join(sub_space_dir, \"middir\", \"deepdir\", \"4.pdb1\"): \"\"\n                     })\n\n        def verify_dir(basedir):\n            assert os.path.isdir(basedir)\n\n            assert os.path.isfile(os.path.join(basedir, \"1.txt\"))\n            assert os.path.isfile(os.path.join(basedir, \"1.pdb\"))\n            assert os.path.isfile(os.path.join(basedir, \"1.pdb1\"))\n\n            assert os.path.isdir(os.path.join(basedir, \"dir.pdb\"))\n            assert os.path.isfile(os.path.join(basedir, \"dir.pdb\", \"2.txt\"))\n            assert os.path.isfile(os.path.join(basedir, \"dir.pdb\", \"2.pdb\"))\n            assert os.path.isfile(os.path.join(basedir, \"dir.pdb\", \"2.pdb1\"))\n\n            assert os.path.isdir(os.path.join(basedir, \"middir\"))\n            assert os.path.isfile(os.path.join(basedir, \"middir\", \"3.txt\"))\n            assert os.path.isfile(os.path.join(basedir, \"middir\", \"3.pdb\"))\n            assert os.path.isfile(os.path.join(basedir, \"middir\", \"3.pdb1\"))\n\n            assert os.path.isdir(os.path.join(basedir, \"middir\", \"deepdir\"))\n            assert os.path.isfile(os.path.join(basedir, \"middir\", \"deepdir\", \"4.txt\"))\n            assert os.path.isfile(os.path.join(basedir, \"middir\", \"deepdir\", \"4.pdb\"))\n            assert os.path.isfile(os.path.join(basedir, \"middir\", \"deepdir\", \"4.pdb1\"))\n\n        verify_dir(os.path.join(folder, sub_space_dir))\n\n        with chdir(folder):\n            rename(None, sub_space_dir, \"dst dir\")\n            verify_dir(os.path.join(folder, \"dst dir\"))\n\n            rename(None, \"dst dir\", \"subdir\")\n            verify_dir(os.path.join(folder, \"subdir\"))\n\n            rename(None, os.path.join(\"subdir\", \"1.txt\"), \"t.txt\")\n            assert os.path.isfile(os.path.join(folder, \"t.txt\"))\n            assert not os.path.isfile(os.path.join(folder, \"subdir\", \"1.txt\"))\n\n    def test_rename_empty_folder(self):\n        client = TestClient()\n        old_folder = os.path.join(client.current_folder, \"old_folder\")\n        os.mkdir(old_folder)\n        new_folder = os.path.join(client.current_folder, \"new_folder\")\n        rename(None, old_folder, new_folder)\n        assert not os.path.exists(old_folder)\n        assert os.path.exists(new_folder)\n"
  },
  {
    "path": "test/unittests/client/tools/test_env.py",
    "content": "import os\nfrom unittest import mock\n\nimport conan.test.utils.env\n\n\nclass TestToolsEnv:\n    def test_environment_update_variables(self):\n        with mock.patch.dict('os.environ', {}), conan.test.utils.env.environment_update({'env_var1': 'value',\n                                                                        'env_var2': 'value2'}):\n            assert os.environ['env_var1'] == 'value'\n            assert os.environ['env_var2'] == 'value2'\n\n    def test_environment_update_variables_without_values(self):\n        with mock.patch.dict('os.environ', {'env_var1': 'value',\n                                            'env_var2': 'value2'}), conan.test.utils.env.environment_update({}):\n            assert os.environ['env_var1'] == 'value'\n            assert os.environ['env_var2'] == 'value2'\n\n    def test_environment_update_overwriting(self):\n        with mock.patch.dict('os.environ', {'env_var1': 'value'}),\\\n             conan.test.utils.env.environment_update({'env_var1': 'new_value'}):\n            assert os.environ['env_var1'] == 'new_value'\n\n    def test_environment_update_unsetting_some_variables(self):\n        with mock.patch.dict('os.environ', {'env_var1': 'value'}),\\\n             conan.test.utils.env.environment_update({'env_var1': None, 'env_var2': 'value2'}):\n            assert 'env_var1' not in os.environ\n            assert os.environ['env_var2'] == 'value2'\n\n    def test_environment_update_unsetting_all_variables(self):\n        with mock.patch.dict('os.environ',\n                             {'env_var1': 'value',\n                              'env_var2': 'value2'}),\\\n             conan.test.utils.env.environment_update({'env_var1': None}):\n            assert 'env_var1' not in os.environ\n\n    def test_environment_update_unsetting_non_existing_variables(self):\n        with mock.patch.dict('os.environ',\n                             {'env_var2': 'value2'}),\\\n             conan.test.utils.env.environment_update({'env_var1': None}):\n            assert 'env_var1' not in os.environ\n"
  },
  {
    "path": "test/unittests/client/userio_test.py",
    "content": "from unittest.mock import patch\n\nfrom conan.api.input import UserInput\n\n\nclass TestUserInput:\n\n    @patch(\"conan.api.input.UserInput.get_username\", return_value=\"username\")\n    @patch(\"conan.api.input.UserInput.get_password\", return_value=\"passwd\")\n    def test_request_login(self, m1, m2):\n        user_input = UserInput(non_interactive=False)\n\n        # Use mocked ones\n        u, p = user_input.request_login(remote_name=\"lol\")\n        assert u == \"username\"\n        assert p == \"passwd\"\n\n        # Use from argument\n        username = \"it's me!\"\n        u, p = user_input.request_login(remote_name=\"lol\", username=username)\n        assert u == username\n        assert p == \"passwd\"\n"
  },
  {
    "path": "test/unittests/client/util/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/client/util/time_test.py",
    "content": "import datetime\n\nfrom dateutil.tz import tzutc\n\nfrom conan.internal.util.dates import from_timestamp_to_iso8601, _from_iso8601_to_datetime, \\\n    from_iso8601_to_timestamp\n\n\nclass TestTime:\n\n    def test_time_conversions(self):\n        timestamp = 1547138099\n        iso = from_timestamp_to_iso8601(timestamp)\n        assert iso == \"2019-01-10T16:34:59+00:00\"\n\n        dt = _from_iso8601_to_datetime(iso)\n        expected = datetime.datetime(year=2019, month=1, day=10, hour=16, minute=34, second=59,\n                                     tzinfo=tzutc())\n        assert dt == expected\n\n        artifactory_ret = '2019-02-20T13:54:47.543+0000'\n        dt = _from_iso8601_to_datetime(artifactory_ret)\n        expected = datetime.datetime(year=2019, month=2, day=20, hour=13, minute=54, second=47,\n                                     microsecond=543000, tzinfo=tzutc())\n        assert dt == expected\n\n        artifactory_ret = '2019-05-14T16:52:28.383+0100'\n        dt = _from_iso8601_to_datetime(artifactory_ret)  # UTC one hour less\n        expected = datetime.datetime(year=2019, month=5, day=14, hour=15, minute=52, second=28,\n                                     microsecond=383000, tzinfo=tzutc())\n        assert dt == expected\n\n        artifactory_ret = \"2024-01-23T08:39:53.776+0000\"\n        ts = from_iso8601_to_timestamp(artifactory_ret)\n        assert ts == 1705999193.776\n\n        artifactory_ret = \"2024-01-23T08:39:53.776+00:00\"\n        ts = from_iso8601_to_timestamp(artifactory_ret)\n        assert ts == 1705999193.776\n"
  },
  {
    "path": "test/unittests/model/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/model/build_info/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/model/build_info/components_test.py",
    "content": "from conan.internal.model.cpp_info import CppInfo\n\n\nclass TestCppInfoComponents:\n\n    def test_components_set(self):\n        cpp_info = CppInfo(set_defaults=True)\n        cpp_info.components[\"liba\"].libs = [\"liba\"]\n        cpp_info.components[\"libb\"].includedirs.append(\"includewhat\")\n        cpp_info.components[\"libc\"].libs.append(\"thelibc\")\n        assert list(cpp_info.components.keys()) == [\"liba\", \"libb\", \"libc\"]\n\n        assert cpp_info.components[\"libb\"].includedirs == [\"include\", \"includewhat\"]\n        assert cpp_info.components[\"libc\"].libs == [\"thelibc\"]\n\n        import pytest\n        with pytest.raises(AttributeError):\n            cpp_info.required_components = [\"liba::liba\"]  # noqa\n\n    def test_no_components_inside_components(self):\n        cpp_info = CppInfo()\n        import pytest\n        with pytest.raises(AttributeError):\n            _ = cpp_info.components[\"libb\"].components\n\n    def test_cppinfo_components_dirs(self):\n        info = CppInfo()\n        info.components[\"OpenSSL\"].includedirs = [\"include\"]\n        info.components[\"OpenSSL\"].libdirs = [\"lib\"]\n        info.components[\"OpenSSL\"].builddirs = [\"build\"]\n        info.components[\"OpenSSL\"].bindirs = [\"bin\"]\n        info.components[\"OpenSSL\"].resdirs = [\"res\"]\n        info.components[\"Crypto\"].includedirs = [\"headers\"]\n        info.components[\"Crypto\"].libdirs = [\"libraries\"]\n        info.components[\"Crypto\"].builddirs = [\"build_scripts\"]\n        info.components[\"Crypto\"].bindirs = [\"binaries\"]\n        info.components[\"Crypto\"].resdirs = [\"resources\"]\n        assert [\"include\"] == info.components[\"OpenSSL\"].includedirs\n        assert [\"lib\"] == info.components[\"OpenSSL\"].libdirs\n        assert [\"build\"] == info.components[\"OpenSSL\"].builddirs\n        assert [\"bin\"] == info.components[\"OpenSSL\"].bindirs\n        assert [\"res\"] == info.components[\"OpenSSL\"].resdirs\n        assert [\"headers\"] == info.components[\"Crypto\"].includedirs\n        assert [\"libraries\"] == info.components[\"Crypto\"].libdirs\n        assert [\"build_scripts\"] == info.components[\"Crypto\"].builddirs\n        assert [\"binaries\"] == info.components[\"Crypto\"].bindirs\n        assert [\"resources\"] == info.components[\"Crypto\"].resdirs\n\n        info.components[\"Crypto\"].includedirs = [\"different_include\"]\n        info.components[\"Crypto\"].libdirs = [\"different_lib\"]\n        info.components[\"Crypto\"].builddirs = [\"different_build\"]\n        info.components[\"Crypto\"].bindirs = [\"different_bin\"]\n        info.components[\"Crypto\"].resdirs = [\"different_res\"]\n        assert [\"different_include\"] == info.components[\"Crypto\"].includedirs\n        assert [\"different_lib\"] == info.components[\"Crypto\"].libdirs\n        assert [\"different_build\"] == info.components[\"Crypto\"].builddirs\n        assert [\"different_bin\"] == info.components[\"Crypto\"].bindirs\n        assert [\"different_res\"] == info.components[\"Crypto\"].resdirs\n\n        info.components[\"Crypto\"].includedirs.extend([\"another_include\"])\n        info.components[\"Crypto\"].includedirs.append(\"another_other_include\")\n        info.components[\"Crypto\"].libdirs.extend([\"another_lib\"])\n        info.components[\"Crypto\"].libdirs.append(\"another_other_lib\")\n        info.components[\"Crypto\"].builddirs.extend([\"another_build\"])\n        info.components[\"Crypto\"].builddirs.append(\"another_other_build\")\n        info.components[\"Crypto\"].bindirs.extend([\"another_bin\"])\n        info.components[\"Crypto\"].bindirs.append(\"another_other_bin\")\n        info.components[\"Crypto\"].resdirs.extend([\"another_res\"])\n        info.components[\"Crypto\"].resdirs.append(\"another_other_res\")\n        assert [\"different_include\", \"another_include\", \"another_other_include\"] == \\\n                         info.components[\"Crypto\"].includedirs\n        assert [\"different_lib\", \"another_lib\", \"another_other_lib\"] == \\\n                         info.components[\"Crypto\"].libdirs\n        assert [\"different_build\", \"another_build\", \"another_other_build\"] == \\\n                         info.components[\"Crypto\"].builddirs\n        assert [\"different_bin\", \"another_bin\", \"another_other_bin\"] == \\\n                         info.components[\"Crypto\"].bindirs\n        assert [\"different_res\", \"another_res\", \"another_other_res\"] == \\\n                         info.components[\"Crypto\"].resdirs\n"
  },
  {
    "path": "test/unittests/model/build_info/generic_properties_test.py",
    "content": "from conan.internal.model.cpp_info import CppInfo\n\n\ndef test_set_get_properties():\n    cpp_info = CppInfo()\n\n    assert not cpp_info.get_property(\"my_property\")\n\n    cpp_info.set_property(\"my_property\", \"default_value\")\n    assert cpp_info.get_property(\"my_property\") == \"default_value\"\n    # can you do a get_property for just a family without generator?\n    assert cpp_info.get_property(\"my_property\") == \"default_value\"\n\n    cpp_info.set_property(\"my_property\", \"pkg_config_value\")\n    assert cpp_info.get_property(\"my_property\") == \"pkg_config_value\"\n    cpp_info.set_property(\"other_property\", \"other_pkg_config_value\")\n    assert cpp_info.get_property(\"other_property\") == \"other_pkg_config_value\"\n"
  },
  {
    "path": "test/unittests/model/build_info/new_build_info_test.py",
    "content": "import pytest\n\nfrom conan.internal.model.cpp_info import CppInfo, _DIRS_VAR_NAMES, _FIELD_VAR_NAMES\n\n\ndef test_components_order():\n    cppinfo = CppInfo()\n    cppinfo.components[\"c1\"].requires = [\"c4\", \"OtherPackage::OtherComponent2\"]\n    cppinfo.components[\"c2\"].requires = [\"OtherPackage::OtherComponent\"]\n    cppinfo.components[\"c3\"].requires = [\"c2\"]\n    cppinfo.components[\"c4\"].requires = [\"c3\"]\n    sorted_c = list(cppinfo.get_sorted_components().keys())\n    assert sorted_c == [\"c2\", \"c3\", \"c4\", \"c1\"]\n\n\ndef test_component_aggregation():\n    cppinfo = CppInfo()\n\n    cppinfo.includedirs = [\"includedir\"]\n    cppinfo.libdirs = [\"libdir\"]\n    cppinfo.srcdirs = [\"srcdir\"]\n    cppinfo.bindirs = [\"bindir\"]\n    cppinfo.builddirs = [\"builddir\"]\n    cppinfo.frameworkdirs = [\"frameworkdir\"]\n    cppinfo.set_property(\"foo\", \"bar\")\n\n    cppinfo.components[\"c2\"].includedirs = [\"includedir_c2\"]\n    cppinfo.components[\"c2\"].libdirs = [\"libdir_c2\"]\n    cppinfo.components[\"c2\"].srcdirs = [\"srcdir_c2\"]\n    cppinfo.components[\"c2\"].bindirs = [\"bindir_c2\"]\n    cppinfo.components[\"c2\"].builddirs = [\"builddir_c2\"]\n    cppinfo.components[\"c2\"].frameworkdirs = [\"frameworkdir_c2\"]\n    cppinfo.components[\"c2\"].cxxflags = [\"cxxflags_c2\"]\n    cppinfo.components[\"c2\"].defines = [\"defines_c2\"]\n    cppinfo.components[\"c2\"].set_property(\"my_foo\", [\"bar\", \"bar2\"])\n    cppinfo.components[\"c2\"].set_property(\"cmake_build_modules\", [\"build_module_c2\",\n                                                                  \"build_module_c22\"])\n\n    cppinfo.components[\"c1\"].requires = [\"c2\", \"LIB_A::C1\"]\n    cppinfo.components[\"c1\"].includedirs = [\"includedir_c1\"]\n    cppinfo.components[\"c1\"].libdirs = [\"libdir_c1\"]\n    cppinfo.components[\"c1\"].srcdirs = [\"srcdir_c1\"]\n    cppinfo.components[\"c1\"].bindirs = [\"bindir_c1\"]\n    cppinfo.components[\"c1\"].builddirs = [\"builddir_c1\"]\n    cppinfo.components[\"c1\"].frameworkdirs = [\"frameworkdir_c1\"]\n    cppinfo.components[\"c1\"].cxxflags = [\"cxxflags_c1\"]\n    cppinfo.components[\"c1\"].defines = [\"defines_c1\"]\n    cppinfo.components[\"c1\"].set_property(\"my_foo\", \"jander\")\n    cppinfo.components[\"c1\"].set_property(\"my_foo2\", \"bar2\")\n\n    ret = cppinfo.aggregated_components()\n\n    assert ret.get_property(\"foo\") == \"bar\"\n    assert ret.includedirs == [\"includedir_c1\", \"includedir_c2\"]\n    assert ret.libdirs == [\"libdir_c1\", \"libdir_c2\"]\n    assert ret.srcdirs == [\"srcdir_c1\", \"srcdir_c2\"]\n    assert ret.bindirs == [\"bindir_c1\", \"bindir_c2\"]\n    assert ret.builddirs == [\"builddir_c1\", \"builddir_c2\"]\n    assert ret.frameworkdirs == [\"frameworkdir_c1\", \"frameworkdir_c2\"]\n    assert ret.cxxflags == [\"cxxflags_c1\", \"cxxflags_c2\"]\n    assert ret.defines == [\"defines_c1\", \"defines_c2\"]\n    # The properties are not aggregated because we cannot generalize the meaning of a property\n    # that belongs to a component, it could make sense to aggregate it or not, \"cmake_target_name\"\n    # for example, cannot be aggregated. But \"cmake_build_modules\" is aggregated.\n    assert ret.get_property(\"my_foo\") is None\n    assert ret.get_property(\"my_foo2\") is None\n    assert ret.get_property(\"cmake_build_modules\") is None\n\n    # If we change the internal graph the order is different\n    cppinfo.components[\"c1\"].requires = []\n    cppinfo.components[\"c2\"].requires = [\"c1\"]\n\n    cppinfo._aggregated = None  # Dirty, just to force recomputation\n    ret = cppinfo.aggregated_components()\n\n    assert ret.includedirs == [\"includedir_c2\", \"includedir_c1\"]\n    assert ret.libdirs == [\"libdir_c2\", \"libdir_c1\"]\n    assert ret.srcdirs == [\"srcdir_c2\", \"srcdir_c1\"]\n    assert ret.bindirs == [\"bindir_c2\", \"bindir_c1\"]\n    assert ret.builddirs == [\"builddir_c2\", \"builddir_c1\"]\n    assert ret.frameworkdirs == [\"frameworkdir_c2\", \"frameworkdir_c1\"]\n\n\ndef test_cpp_info_sysroot_merge():\n    # If the value was already set is kept in the merge\n    one = CppInfo()\n    one.sysroot = \"sys1\"\n    two = CppInfo()\n    two.sysroot = \"sys2\"\n    one.merge(two)\n    assert one.sysroot == \"sys1\"\n\n    # If the value was not set it is assigned\n    one = CppInfo()\n    two = CppInfo()\n    two.sysroot = \"sys2\"\n    one.merge(two)\n    assert one.sysroot == \"sys2\"\n\n\n@pytest.mark.parametrize(\"aggregate_first\", [True, False])\ndef test_cpp_info_merge_aggregating_components_first(aggregate_first):\n    cppinfo = CppInfo()\n    for n in _DIRS_VAR_NAMES + _FIELD_VAR_NAMES:\n        setattr(cppinfo.components[\"foo\"], n, [\"var_{}_1\".format(n), \"var_{}_2\".format(n)])\n        setattr(cppinfo.components[\"foo2\"], n, [\"var2_{}_1\".format(n), \"var2_{}_2\".format(n)])\n\n    cppinfo.components[\"foo\"].requires = [\"foo2\"]  # Deterministic order\n\n    other = CppInfo()\n    for n in _DIRS_VAR_NAMES + _FIELD_VAR_NAMES:\n        setattr(other.components[\"boo\"], n, [\"jar_{}_1\".format(n), \"jar_{}_2\".format(n)])\n        setattr(other.components[\"boo2\"], n, [\"jar2_{}_1\".format(n), \"jar2_{}_2\".format(n)])\n\n    other.components[\"boo\"].requires = [\"boo2\"]  # Deterministic order\n\n    if aggregate_first:\n        cppinfo = cppinfo.aggregated_components()\n        other = other.aggregated_components()\n\n    cppinfo.merge(other)\n\n    if aggregate_first:\n        for n in _DIRS_VAR_NAMES + _FIELD_VAR_NAMES:\n            assert getattr(cppinfo, n) == [\"var_{}_1\".format(n), \"var_{}_2\".format(n),\n                                           \"var2_{}_1\".format(n), \"var2_{}_2\".format(n),\n                                           \"jar_{}_1\".format(n), \"jar_{}_2\".format(n),\n                                           \"jar2_{}_1\".format(n), \"jar2_{}_2\".format(n)]\n    else:\n        for n in _DIRS_VAR_NAMES + _FIELD_VAR_NAMES:\n            assert getattr(cppinfo.components[\"foo\"], n) == [\"var_{}_1\".format(n),\n                                                             \"var_{}_2\".format(n)]\n            assert getattr(cppinfo.components[\"foo2\"], n) == [\"var2_{}_1\".format(n),\n                                                              \"var2_{}_2\".format(n)]\n            assert getattr(cppinfo.components[\"boo\"], n) == [\"jar_{}_1\".format(n),\n                                                             \"jar_{}_2\".format(n)]\n            assert getattr(cppinfo.components[\"boo2\"], n) == [\"jar2_{}_1\".format(n),\n                                                              \"jar2_{}_2\".format(n)]\n            assert getattr(cppinfo, n) is None\n"
  },
  {
    "path": "test/unittests/model/build_info/test_deduce_locations.py",
    "content": "import os\nimport platform\nfrom unittest.mock import MagicMock\n\nimport pytest\n\nfrom conan.test.utils.mocks import ConanFileMock, RedirectedTestOutput\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import redirect_output\nfrom conan.tools.files import save\nfrom conan.internal.model.cpp_info import CppInfo\nfrom conan.internal.model.pkg_type import PackageType\nfrom conan.api.model import RecipeReference\nfrom conan.internal.util.files import save\n\n\n@pytest.fixture\ndef conanfile():\n    c = ConanFileMock()\n    c._conan_node = MagicMock(ref=RecipeReference(\"\"))\n    return c\n\n\n@pytest.mark.parametrize(\"lib_name, libs\", [\n    (\"myliblin.a\", [\"myliblin\"]),\n    (\"libmyliblin.a\", [\"myliblin\"]),\n    (\"mylibmac.a\", [\"mylibmac\"]),\n    (\"mylibwin.lib\", [\"mylibwin\"]),\n    (\"libmylibwin.lib\", [\"libmylibwin\"]),\n    (\"mylibwin2.if.lib\", [\"mylibwin2.if.lib\"]),\n    (\"mylibwin2.if.lib\", [\"mylibwin2\"])\n])\ndef test_simple_deduce_locations_static(lib_name, libs, conanfile):\n    folder = temp_folder()\n    location = os.path.join(folder, \"libdir\", lib_name)\n    save(location, \"\")\n\n    cppinfo = CppInfo()\n    cppinfo.libdirs = [\"libdir\"]\n    cppinfo.libs = libs\n    cppinfo.set_relative_base_folder(folder)\n\n    result = cppinfo.deduce_full_cpp_info(conanfile)\n    assert result.location == location.replace(\"\\\\\", \"/\")\n    assert result.link_location is None\n    assert result.type == \"static-library\"\n\n\ndef test_deduce_shared_link_locations(conanfile):\n    folder = temp_folder()\n    imp_location = os.path.join(folder, \"libdir\", \"mylib.lib\")\n    save(imp_location, \"\")\n    location = os.path.join(folder, \"bindir\", \"mylib.dll\")\n    save(location, \"\")\n\n    cppinfo = CppInfo()\n    cppinfo.libdirs = [\"libdir\"]\n    cppinfo.bindirs = [\"bindir\"]\n    cppinfo.libs = [\"mylib\"]\n    cppinfo.set_relative_base_folder(folder)\n\n    result = cppinfo.deduce_full_cpp_info(conanfile)\n    assert result.location == location.replace(\"\\\\\", \"/\")\n    assert result.link_location == imp_location.replace(\"\\\\\", \"/\")\n    assert result.type == \"shared-library\"\n\n\n@pytest.mark.parametrize(\"lib_name, libs\", [\n    (\"liblog4cxx.so.15.2.0\", [\"log4cxx\"]),\n    (\"libapr-1.0.dylib\", [\"apr-1\"]),\n    (\"libapr-1.so.0.7.4\", [\"apr-1\"]),\n    (\"libgrpc++_alts.so.1.67.1\", [\"grpc++_alts\"])\n])\ndef test_complex_deduce_locations_shared(lib_name, libs, conanfile):\n    \"\"\"\n    Tests real examples of shared library names in Linux/MacOS,\n    e.g., log4cxx, apr-1, etc.\n\n    Related issue: https://github.com/conan-io/conan/issues/16990\n    \"\"\"\n    folder = temp_folder()\n    location = os.path.join(folder, \"libdir\", lib_name)\n    save(location, \"\")\n\n    cppinfo = CppInfo()\n    cppinfo.libdirs = [\"libdir\"]\n    cppinfo.libs = libs\n    cppinfo.set_relative_base_folder(folder)\n\n    result = cppinfo.deduce_full_cpp_info(conanfile)\n    assert result.location == location.replace(\"\\\\\", \"/\")\n    assert result.link_location is None\n    assert result.type == \"shared-library\"\n\n\n@pytest.mark.parametrize(\"lib_name, dll_name, libs, pkg_name\", [\n    (\"libcurl_imp.lib\", \"libcurl.dll\", [\"libcurl_imp\"], \"libcurl\"),\n    (\"libcrypto.lib\", \"libcrypto-3-x64.dll\", [\"libcrypto\"], \"crypto\"),\n    (\"libssl.lib\", \"libssl-3-x64.dll\", [\"libssl\"], \"ssl\"),\n    (\"zdll.lib\", \"zlib1.dll\", [\"zdll\"], \"zlib\")\n])\ndef test_windows_shared_link_locations(lib_name, dll_name, libs, pkg_name, conanfile):\n    \"\"\"\n    Tests real examples of shared library names in Windows,\n    e.g., openssl, zlib, libcurlb, etc.\n    \"\"\"\n    folder = temp_folder()\n    imp_location = os.path.join(folder, \"libdir\", lib_name)\n    save(imp_location, \"\")\n    location = os.path.join(folder, \"bindir\", dll_name)\n    save(location, \"\")\n\n    cppinfo = CppInfo()\n    cppinfo.libdirs = [\"libdir\"]\n    cppinfo.bindirs = [\"bindir\"]\n    cppinfo.libs = libs\n    cppinfo.set_relative_base_folder(folder)\n\n    conanfile._conan_node.ref = RecipeReference(name=pkg_name)\n    result = cppinfo.deduce_full_cpp_info(conanfile)\n    assert result.location == location.replace(\"\\\\\", \"/\")\n    assert result.link_location == imp_location.replace(\"\\\\\", \"/\")\n    assert result.type == \"shared-library\"\n\n\n@pytest.mark.parametrize(\"lib_info\", [\n    {\"charset\": [\"charset.lib\", \"charset-1.dll\"],\n     \"iconv\": [\"iconv.lib\", \"iconv-2.dll\"]},\n    {\"charset\": [\"libcharset.so.1.0.0\"],\n     \"iconv\": [\"libiconv.so.2.6.1\"]},\n])\ndef test_windows_several_shared_link_locations(lib_info, conanfile):\n    \"\"\"\n    Tests a real model as LIBICONV with several libs defined in the root component\n    \"\"\"\n    folder = temp_folder()\n    locations = {}\n    is_windows = False\n    for lib_name, lib_files in lib_info.items():\n        imp_location = os.path.join(folder, \"libdir\", lib_files[0])\n        save(imp_location, \"\")\n        if len(lib_files) > 1:\n            is_windows = True\n            location = os.path.join(folder, \"bindir\", lib_files[1])\n            save(location, \"\")\n        else:\n            location = imp_location  # Linux\n        locations[lib_name] = (location, imp_location)\n\n    cppinfo = CppInfo()\n    cppinfo.libdirs = [\"libdir\"]\n    cppinfo.bindirs = [\"bindir\"]\n    cppinfo.libs = list(lib_info.keys())\n    cppinfo.set_relative_base_folder(folder)\n\n    result = cppinfo.deduce_full_cpp_info(conanfile)\n    for lib_name in lib_info:\n        assert result.components[f\"_{lib_name}\"].location == locations[lib_name][0].replace(\"\\\\\", \"/\")\n        if is_windows:\n            assert result.components[f\"_{lib_name}\"].link_location == locations[lib_name][1].replace(\"\\\\\", \"/\")\n        assert result.components[f\"_{lib_name}\"].type == \"shared-library\"\n\n\n@pytest.mark.parametrize(\"lib, symlinks\", [\n    # symlinks == \"real_file <- symlink1 <- symlink2 <- ... <- symlinkN\"\n    # Issue related: https://github.com/conan-io/conan/issues/17417\n    (\"png\", \"libpng16.so.16.44.0 <- libpng16.so.16 <- libpng16.so <- libpng.so\")\n])\n@pytest.mark.skipif(platform.system() == \"Windows\", reason=\"Can't apply symlink on Windows\")\ndef test_shared_link_locations_symlinks(lib, symlinks, conanfile):\n    \"\"\"\n    Tests auto deduce location is not resolving symlinks by default. For instance:\n        .\n        ├── libpng.so -> libpng16.so  (exact match)\n        ├── libpng16.so -> libpng16.so.16\n        ├── libpng16.so.16 -> libpng16.so.16.44.0\n        └── libpng16.so.16.44.0  (real one)\n\n\n    Issues related:\n        - https://github.com/conan-io/conan/issues/17417\n        - https://github.com/conan-io/conan/issues/17721\n    \"\"\"\n    folder = temp_folder()\n    all_files = symlinks.split(\" <- \")  # [real_one, sym1, sym2, ...]\n    # Real one (first item from list)\n    real_location = os.path.join(folder, \"libdir\", all_files.pop(0))\n    save(real_location, \"\")\n    # Symlinks\n    prev_path = real_location\n    for file in all_files:\n        sym = os.path.join(folder, \"libdir\", file)\n        os.symlink(prev_path, sym)\n        prev_path = sym\n    # Exact match and symlink (latest item from list)\n    exact_match = os.path.join(folder, \"libdir\", all_files[-1])\n\n    cppinfo = CppInfo()\n    cppinfo.libdirs = [\"libdir\"]\n    cppinfo.libs = [lib]\n    cppinfo.set_relative_base_folder(folder)\n\n    result = cppinfo.deduce_full_cpp_info(conanfile)\n    assert result.location == exact_match\n    assert result.type == \"shared-library\"\n\n\n@pytest.mark.parametrize(\"static\", [True, False])\ndef test_error_if_shared_and_static_found(static, conanfile):\n    folder = temp_folder()\n    save(os.path.join(folder, \"libdir\", \"libmylib.a\"), \"\")\n    save(os.path.join(folder, \"libdir\", \"libmylib.so\"), \"\")\n\n    cppinfo = CppInfo()\n    cppinfo.libdirs = [\"libdir\"]\n    cppinfo.libs = [\"mylib\"]\n    cppinfo.set_relative_base_folder(folder)\n    folder = folder.replace(\"\\\\\", \"/\")\n    if static:\n        conanfile.package_type = PackageType.STATIC\n    result = cppinfo.deduce_full_cpp_info(conanfile)\n    ext = \"a\" if static else \"so\"\n    assert result.location == f\"{folder}/libdir/libmylib.{ext}\"\n    assert result.type == (PackageType.STATIC if static else PackageType.SHARED)\n\n\ndef test_warning_windows_if_more_than_one_dll(conanfile):\n    folder = temp_folder()\n    save(os.path.join(folder, \"libdir\", \"mylib.a\"), \"\")\n    save(os.path.join(folder, \"bindir\", \"libx.dll\"), \"\")\n    save(os.path.join(folder, \"bindir\", \"liby.dll\"), \"\")\n\n    cppinfo = CppInfo()\n    cppinfo.libdirs = [\"libdir\"]\n    cppinfo.bindirs = [\"bindir\"]\n    cppinfo.libs = [\"mylib\"]\n    cppinfo.set_relative_base_folder(folder)\n    folder = folder.replace(\"\\\\\", \"/\")\n    output = RedirectedTestOutput()  # Initialize each command\n    with redirect_output(output):\n        result = cppinfo.deduce_full_cpp_info(conanfile)\n    assert \"WARN: There were several matches for Lib mylib\" in output\n    assert result.location == f\"{folder}/bindir/libx.dll\"\n    assert result.type == \"shared-library\"\n\n\n@pytest.mark.parametrize(\"prefix\", [True, False])\ndef test_multiple_matches_exact_match(prefix, conanfile):\n    # If the match is perfect, do not warn\n    folder = temp_folder()\n    prefix = \"lib\" if prefix else \"\"\n    save(os.path.join(folder, \"libdir\", f\"{prefix}mylib.a\"), \"\")\n    save(os.path.join(folder, \"libdir\", f\"{prefix}mylib_imp.a\"), \"\")\n    save(os.path.join(folder, \"libdir\", f\"{prefix}mylib_other.a\"), \"\")\n\n    cppinfo = CppInfo()\n    cppinfo.libdirs = [\"libdir\"]\n    cppinfo.libs = [\"mylib\"]\n    cppinfo.set_relative_base_folder(folder)\n    folder = folder.replace(\"\\\\\", \"/\")\n    output = RedirectedTestOutput()  # Initialize each command\n    with redirect_output(output):\n        result = cppinfo.deduce_full_cpp_info(conanfile)\n    assert \"WARN: There were several matches for Lib mylib\" not in output\n    assert result.location == f\"{folder}/libdir/{prefix}mylib.a\"\n    assert result.type == \"static-library\"\n\n\n\n@pytest.mark.parametrize(\"lib_name, libs\", [\n    (\"harfbuzz\", [\"harfbuzz-icu.lib\", \"harfbuzz.lib\"]),\n])\ndef test_several_libs_and_exact_match(lib_name, libs, conanfile):\n    \"\"\"\n    Testing that we're keeping the exact match at first instead the similar one\n\n    Issue related: https://github.com/conan-io/conan/issues/17974\n    \"\"\"\n    folder = temp_folder()\n    for lib in libs:\n        save(os.path.join(folder, \"libdir\", lib), \"\")\n\n    cppinfo = CppInfo()\n    cppinfo.libdirs = [\"libdir\"]\n    cppinfo.libs = [lib_name]\n    cppinfo.set_relative_base_folder(folder)\n    folder = folder.replace(\"\\\\\", \"/\")\n    result = cppinfo.deduce_full_cpp_info(conanfile)\n    assert result.location == f\"{folder}/libdir/{lib_name}.lib\"\n    assert result.type == \"static-library\"\n\n\ndef test_sources(conanfile):\n    folder = temp_folder()\n    save(os.path.join(folder, \"src\", \"mylib.cpp\"), \"\")\n    cppinfo = CppInfo()\n    cppinfo.sources = [\"src/mylib.cpp\"]\n    cppinfo.set_relative_base_folder(folder)\n    result = cppinfo.deduce_full_cpp_info(conanfile)\n    assert result.location is None\n    assert result.type == \"header-library\"\n"
  },
  {
    "path": "test/unittests/model/conanfile_test.py",
    "content": "import textwrap\n\nfrom conan.internal.model.conan_file import ConanFile\nfrom conan.test.utils.tools import TestClient\n\n\nclass TestConanFile:\n    def test_conanfile_naming(self):\n        for member in vars(ConanFile):\n            if member.startswith('_') and not member.startswith(\"__\"):\n                assert member.startswith('_conan')\n\n        conanfile = ConanFile(None)\n\n        for member in vars(conanfile):\n            if member.startswith('_') and not member.startswith(\"__\"):\n                assert member.startswith('_conan')\n\n    def test_conanfile_naming_complete(self):\n        client = TestClient()\n        conanfile = \"\"\"from conan import ConanFile\nclass Pkg(ConanFile):\n    pass\n    def package_info(self):\n        for member in Pkg.__dict__:\n            if member.startswith('_') and not member.startswith(\"__\"):\n                assert(member.startswith('_conan'))\n        for member in vars(self):\n            if member.startswith('_') and not member.startswith(\"__\"):\n                assert(member.startswith('_conan'))\n\"\"\"\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --name=pkga --version=0.1 --user=user --channel=testing\")\n        client.save({\"conanfile.py\": conanfile.replace(\"pass\",\n                                                       \"requires = 'pkga/0.1@user/testing'\")})\n        client.run(\"create . --name=pkgb --version=0.1 --user=user --channel=testing\")\n        client.save({\"conanfile.py\": conanfile.replace(\"pass\",\n                                                       \"requires = 'pkgb/0.1@user/testing'\")})\n        client.run(\"create . --name=pkgc --version=0.1 --user=user --channel=testing\")\n\n    def test_conanfile_new_print(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            import sys\n            class Pkg(ConanFile):\n                def source(self):\n                    print(\"Test1\", file=sys.stderr)\n                    print(\"Test2\")\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"source .\")\n        assert \"Test1\" in client.stderr\n        assert \"Test2\" in client.stderr\n        assert \"\" == client.stdout\n\n    def test_conanfile_new_print_save(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            import sys\n            class Pkg(ConanFile):\n                def source(self):\n                    with open(\"myfile.txt\", \"w\") as f:\n                        print(\"Test1\", file=f)\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"source .\")\n        assert \"Test1\" in client.load(\"myfile.txt\")\n"
  },
  {
    "path": "test/unittests/model/info_test.py",
    "content": "from conan.internal.model.info import ConanInfo, RequirementsInfo, PythonRequiresInfo\nfrom conan.internal.model.options import Options\nfrom conan.internal.model.settings import Settings\n\n\ndef test_false_values_affect_none():\n    \"\"\" False value do become part of conaninfo.txt and package_id\n    Only \"None\" Python values are discarded from conaninfo.txt\n    \"\"\"\n    reqs = RequirementsInfo({})\n    build_reqs = RequirementsInfo({})\n    python_reqs = PythonRequiresInfo({}, default_package_id_mode=None)\n    options = Options({\"shared\": [True, False], \"other\": [None, \"1\"]}, {\"shared\": False})\n    settings = Settings({\"mysetting\": [1, 2, 3]})\n    c = ConanInfo(settings, options, reqs, build_reqs, python_reqs)\n    conaninfo = c.dumps()\n    assert \"shared=False\" in conaninfo\n    assert \"other\" not in conaninfo\n    assert \"mysetting\" not in conaninfo\n\n    settings.mysetting = 1\n    conaninfo = c.dumps()\n    assert \"mysetting=1\" in conaninfo\n"
  },
  {
    "path": "test/unittests/model/manifest_test.py",
    "content": "import os\nimport platform\n\nimport pytest\n\nfrom conan.internal.model.manifest import FileTreeManifest\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.internal.util.files import load, md5, save\n\n\n@pytest.mark.skipif(platform.system() == \"Windows\", reason=\"decent symlinks only\")\ndef test_symlinks_manifest():\n    \"\"\" The symlinks are coded in the manifest, the key is the path of the symlink and the hash\n        is the hash of the contents or empty string if this is a broken symlink\"\"\"\n    tmp_dir = temp_folder()\n    save(os.path.join(tmp_dir, \"foo.txt\"), \"bar\")\n    os.symlink(\"foo.txt\", os.path.join(tmp_dir, \"foofake.txt\"))\n    os.symlink(\"foo_missing.txt\", os.path.join(tmp_dir, \"var.txt\"))\n    manifest = FileTreeManifest.create(tmp_dir)\n\n    manifest.save(tmp_dir)\n    read_manifest = FileTreeManifest.load(tmp_dir)\n    assert read_manifest.file_sums == {'foo.txt': '37b51d194a7513e45b56f6524f2d51f2',\n                                       'foofake.txt': '4fd8cc85ca9eebd2fa3c550069ce2846',\n                                       'var.txt': '6cc1cda38d517f2e5e47a803a343d17d'}\n\n\ndef test_tree_manifest():\n    tmp_dir = temp_folder()\n    files = {\"one.ext\": \"aalakjshdlkjahsdlkjahsdljkhsadljkhasljkdhlkjashd\",\n             \"path/to/two.txt\": \"asdas13123\",\n             \"two.txt\": \"asdasdasdasdasdasd\",\n             \"folder/damn.pyc\": \"binarythings\",\n             \"folder/damn.pyo\": \"binarythings2\",\n             \"pythonfile.pyc\": \"binarythings3\"}\n    for filename, content in files.items():\n        save(os.path.join(tmp_dir, filename), content)\n\n    manifest = FileTreeManifest.create(tmp_dir)\n\n    manifest.save(tmp_dir)\n    readed_manifest = FileTreeManifest.load(tmp_dir)\n\n    assert readed_manifest.time == manifest.time\n    assert readed_manifest == manifest\n    # Not included the pycs or pyo\n    assert set(manifest.file_sums.keys()) == {'folder/damn.pyc', 'folder/damn.pyo', 'one.ext',\n                                              'path/to/two.txt', 'pythonfile.pyc', 'two.txt'}\n\n    for filepath, md5readed in manifest.file_sums.items():\n        content = files[filepath]\n        assert md5(content), md5readed\n\n\ndef test_already_pyc_in_manifest():\n    tmp_dir = temp_folder()\n    save(os.path.join(tmp_dir, \"man.txt\"), \"1478122267\\nconanfile.pyc: \"\n                                           \"2bcac725a0e6843ef351f4d18cf867ec\\n\"\n                                           \"conanfile.py: 2bcac725a0e6843ef351f4d18cf867ec\\n\"\n                                           \"conanfile.pyo: 2bcac725a0e6843ef351f4d18cf867ec\\n\")\n\n    read_manifest = FileTreeManifest.loads(load(os.path.join(tmp_dir, \"man.txt\")))\n    # Not included the pycs or pyo\n    assert set(read_manifest.file_sums.keys()) == {\"conanfile.py\", \"conanfile.pyc\", \"conanfile.pyo\"}\n\n\ndef test_special_chars():\n    tmp_dir = temp_folder()\n    save(os.path.join(tmp_dir, \"conanmanifest.txt\"), \"1478122267\\nsome: file.py: 123\\n\")\n    read_manifest = FileTreeManifest.load(tmp_dir)\n    assert read_manifest.file_sums[\"some: file.py\"] == \"123\"\n\n\ndef test_pycache_included():\n    tmp_dir = temp_folder()\n    files = {\"__pycache__/damn.py\": \"binarythings\",\n             \"pythonfile.pyc\": \"binarythings3\"}\n    for filename, content in files.items():\n        save(os.path.join(tmp_dir, filename), content)\n\n    manifest = FileTreeManifest.create(tmp_dir)\n    manifest = repr(manifest)\n    assert \"pythonfile.pyc\" in manifest\n    assert \"__pycache__/damn.py\" in manifest\n"
  },
  {
    "path": "test/unittests/model/options_test.py",
    "content": "import textwrap\n\nimport pytest\n\nfrom conan.errors import ConanException\nfrom conan.internal.model.options import Options\nfrom conan.api.model import RecipeReference\n\n\nclass TestOptions:\n\n    @pytest.fixture(autouse=True)\n    def _setup(self):\n        options = {\"static\": [True, False], \"optimized\": [2, 3, 4], \"path\": [\"ANY\"]}\n        values = {\"static\": True, \"optimized\": 3, \"path\": \"mypath\"}\n        self.sut = Options(options, values)\n\n    def test_booleans(self):\n        assert self.sut.static\n        assert self.sut.static == True  # noqa\n        assert self.sut.static != False  # noqa\n        assert bool(self.sut.static)\n\n        assert self.sut.optimized\n        assert self.sut.optimized == 3\n        assert self.sut.optimized != 2\n\n        assert self.sut.path == \"mypath\"\n        assert self.sut.path != \"otherpath\"\n\n    def test_invalid_value(self):\n        with pytest.raises(ConanException) as e:\n            assert self.sut.static != 1\n        assert \"'1' is not a valid 'options.static' value\" in str(e.value)\n\n        with pytest.raises(ConanException) as e:\n            assert self.sut.optimized != 5\n        assert \"'5' is not a valid 'options.optimized' value\" in str(e.value)\n\n        with pytest.raises(ConanException) as e:\n            self.sut.static = 1\n        assert \"'1' is not a valid 'options.static' value\" in str(e.value)\n\n        with pytest.raises(ConanException) as e:\n            self.sut.optimized = 5\n        assert \"'5' is not a valid 'options.optimized' value\" in str(e.value)\n\n    def test_non_existing_option(self):\n        with pytest.raises(ConanException) as e:\n            assert self.sut.potato\n        assert \"option 'potato' doesn't exist\" in str(e.value)\n\n    def test_int(self):\n        assert 3 == int(self.sut.optimized)\n\n    def test_in(self):\n        assert \"static\" in self.sut\n        assert \"potato\" not in self.sut\n        assert \"optimized\" in self.sut\n        assert \"path\" in self.sut\n\n    def test_assign(self):\n        self.sut.static = False\n        self.sut.optimized = 2\n        self.sut.optimized = \"4\"\n        self.sut.path = \"otherpath\"\n\n        assert not self.sut.static\n        assert self.sut.optimized == 4\n        assert self.sut.path == \"otherpath\"\n\n    def test_dumps(self):\n        text = self.sut.dumps()\n        # Output is ordereded alphabetically\n        expected = textwrap.dedent(\"\"\"\\\n            optimized=3\n            path=mypath\n            static=True\"\"\")\n        assert text == expected\n\n    def test_freeze(self):\n        assert self.sut.static\n\n        self.sut.freeze()\n        # Should be freezed now\n        # same value should not raise\n        self.sut.static = True\n\n        # Different value should raise\n        with pytest.raises(ConanException) as e:\n            self.sut.static = False\n        assert \"Incorrect attempt to modify option 'static'\" in str(e.value)\n        assert \"static=True\" in self.sut.dumps()\n\n        # Removal of options with values doesn't raise anymore\n        del self.sut.static\n        assert \"static\" not in self.sut.dumps()\n\n        # Test None is possible to change\n        sut2 = Options({\"static\": [True, False],\n                        \"other\": [True, False]})\n        sut2.freeze()\n        sut2.static = True\n        assert \"static=True\" in sut2.dumps()\n        # But not twice\n        with pytest.raises(ConanException) as e:\n            sut2.static = False\n        assert \"Incorrect attempt to modify option 'static'\" in str(e.value)\n        assert \"static=True\" in sut2.dumps()\n\n        # can remove other, removing is always possible, even if freeze\n        del sut2.other\n        assert \"other\" not in sut2.dumps()\n\n    def test_items(self):\n        assert self.sut.items() == [(\"optimized\", \"3\"), (\"path\", \"mypath\"), (\"static\", \"True\")]\n        assert self.sut.items() == [(\"optimized\", \"3\"), (\"path\", \"mypath\"), (\"static\", \"True\")]\n\n    def test_get_safe_options(self):\n        assert True == self.sut.get_safe(\"static\")  # noqa\n        assert 3 == self.sut.get_safe(\"optimized\")\n        assert \"mypath\" == self.sut.get_safe(\"path\")\n        assert None == self.sut.get_safe(\"unknown\")  # noqa\n        self.sut.path = \"None\"\n        self.sut.static = False\n        assert False == self.sut.get_safe(\"static\")  # noqa\n        assert \"None\" == self.sut.get_safe(\"path\")\n        assert False == self.sut.get_safe(\"static\", True)  # noqa\n        assert \"None\" == self.sut.get_safe(\"path\", True)\n        assert True == self.sut.get_safe(\"unknown\", True)  # noqa\n\n\nclass TestOptionsLoad:\n    def test_load(self):\n        text = textwrap.dedent(\"\"\"\\\n            optimized=3\n            path=mypath\n            static=True\n            zlib*:option=8\n            *:common=value\n            \"\"\")\n        sut = Options.loads(text)\n        assert sut.optimized == 3\n        assert sut.optimized != \"whatever\"  # Non validating\n        assert sut.path == \"mypath\"\n        assert sut.path != \"whatever\"  # Non validating\n        assert sut.static == \"True\"\n        assert sut.static != \"whatever\"  # Non validating\n        assert sut[\"zlib*\"].option == 8\n        assert sut[\"zlib*\"].option != \"whatever\"  # Non validating\n        assert sut[\"*\"].common == \"value\"\n        assert sut[\"*\"].common != \"whatever\"  # Non validating\n\n\nclass TestOptionsPropagate:\n    def test_basic(self):\n        options = {\"static\": [True, False]}\n        values = {\"static\": True}\n        sut = Options(options, values)\n        assert sut.static\n\n        ref = RecipeReference.loads(\"boost/1.0\")\n        # if ref!=None option MUST be preceded by boost:\n        down_options = Options(options_values={\"zlib/2.0:other\": 1, \"boost/1.0:static\": False})\n        sut.apply_downstream(down_options, Options(), ref, False)\n        assert not sut.static\n\n        # Should be freezed now\n        with pytest.raises(ConanException) as e:\n            sut.static = True\n        assert \"Incorrect attempt to modify option 'static'\" in str(e.value)\n\n        self_options, up_options, up_private = sut.get_upstream_options(down_options, ref, False)\n        assert up_options.dumps() == \"zlib/2.0:other=1\"\n        assert self_options.dumps() == \"boost/1.0:static=False\\nzlib/2.0:other=1\"\n        assert up_private.dumps() == \"\"\n\n\nclass TestOptionsNone:\n    @pytest.fixture(autouse=True)\n    def _setup(self):\n        options = {\"static\": [None, 1, 2], \"other\": [None, \"ANY\"], \"more\": [\"None\", 1]}\n        self.sut = Options(options)\n\n    def test_booleans(self):\n        assert self.sut.static == None  # noqa\n        assert not self.sut.static\n        assert self.sut.static != 1\n        assert self.sut.static != 2\n        with pytest.raises(ConanException) as e:\n            self.sut.static == 3  # noqa\n        assert \"'3' is not a valid 'options.static' value\" in str(e.value)\n\n        with pytest.raises(ConanException) as e:\n            self.sut.static == \"None\"  # noqa\n        assert \"'None' is not a valid 'options.static' value\" in str(e.value)\n\n        assert self.sut.other == None  # noqa\n        assert self.sut.other != \"whatever\"  # dont raise, ANY\n        self.sut.other = None\n        assert self.sut.other == None  # noqa\n\n        assert not self.sut.more\n        assert self.sut.more == None  # noqa\n        assert self.sut.more != 1\n        with pytest.raises(ConanException) as e:\n            self.sut.more == 2  # noqa\n        assert \"'2' is not a valid 'options.more' value\" in str(e.value)\n        with pytest.raises(ConanException) as e:\n            self.sut.more = None\n        assert \"'None' is not a valid 'options.more' value\" in str(e.value)\n        self.sut.more = \"None\"\n        assert not self.sut.more  # This is still evaluated to false, like OFF, 0, FALSE, etc\n        assert self.sut.more == \"None\"\n        assert self.sut.more != None  # noqa\n\n    def test_assign(self):\n        self.sut.static = 1\n        assert self.sut.static == 1\n\n    def test_dumps(self):\n        text = self.sut.dumps()\n        assert text == \"\"\n\n    def test_boolean_none(self):\n        options = Options({\"static\": [None, \"None\", 1, 2]})\n        assert options.static != 1\n        assert not (options.static == 1)\n        assert options.static != \"None\"\n        assert not (options.static == \"None\")\n        assert options.static == None  # noqa\n        assert not (options.static != None)  # noqa\n\n        options.static = \"None\"\n        assert options.static == \"None\"\n        assert not (options.static != \"None\")\n        assert not (options.static == None)  # noqa\n        assert options.static != None  # noqa\n\n    def test_undefined_value(self):\n        \"\"\" Not assigning a value to options will raise an error at validate() step\n        \"\"\"\n        package_options = Options({\"path\": [\"ANY\"]})\n        with pytest.raises(ConanException):\n            package_options.validate()\n        package_options.path = \"Something\"\n        package_options.validate()\n\n    def test_undefined_value_none(self):\n        \"\"\" The value None is allowed as default, not necessary to default to it\n        \"\"\"\n        package_options = Options({\"path\": [None, \"Other\"]})\n        package_options.validate()\n        package_options = Options({\"path\": [\"None\", \"Other\"]})\n        with pytest.raises(ConanException):  # Literal \"None\" string not good to be undefined\n            package_options.validate()\n"
  },
  {
    "path": "test/unittests/model/other_settings_test.py",
    "content": "import os\nimport textwrap\n\nfrom conan.internal.model.info import load_binary_info\nfrom conan.api.model import RecipeReference\nfrom conan.internal.paths import CONANFILE\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import load, save\n\n\nclass TestSettings:\n\n    @staticmethod\n    def _get_conaninfo(reference, client):\n        ref = client.cache.get_latest_recipe_revision(RecipeReference.loads(reference))\n        pkg_ids = client.cache.get_package_references(ref)\n        pref = client.cache.get_latest_package_revision(pkg_ids[0])\n        pkg_folder = client.cache.pkg_layout(pref).package()\n        return load_binary_info(client.load(os.path.join(pkg_folder, \"conaninfo.txt\")))\n\n    def test_wrong_settings(self):\n        settings = textwrap.dedent(\"\"\"\\\n            os:\n                null:\n                    subsystem: [null, msys]\n            \"\"\")\n        client = TestClient()\n        save(client.paths.settings_path, settings)\n        client.save_home({\"profiles/default\": \"\"})\n        client.save({\"conanfile.py\": GenConanfile().with_settings(\"os\", \"compiler\")})\n        client.run(\"create . --name=pkg --version=0.1\", assert_error=True)\n        assert \"ERROR: settings.yml: null setting can't have subsettings\" in client.out\n\n    def test_settings_constraint_error_type(self):\n        # https://github.com/conan-io/conan/issues/3022\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            class Test(ConanFile):\n                settings = \"os\"\n                def build(self):\n                    self.output.info(\"OS!!: %s\" % self.settings.os)\n            \"\"\")\n        client = TestClient()\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --name=pkg --version=0.1 --user=user --channel=testing -s os=Linux\")\n        assert \"pkg/0.1@user/testing: OS!!: Linux\" in client.out\n\n    def test_settings_as_a_str(self):\n        client = TestClient()\n        client.save({CONANFILE: GenConanfile(\"say\", \"0.1\").with_settings(\"os\")})\n        client.run(\"create . -s os=Windows --build missing\")\n        # Now read the conaninfo and verify that settings applied is only os and value is windows\n        conan_info = self._get_conaninfo(\"say/0.1@\", client)\n        assert conan_info[\"settings\"][\"os\"] == \"Windows\"\n\n        client.run(\"remove say/0.1 -c\")\n        client.run(\"create . -s os=Linux --build missing\")\n        # Now read the conaninfo and verify that settings applied is only os and value is windows\n        conan_info = self._get_conaninfo(\"say/0.1@\", client)\n        assert conan_info[\"settings\"][\"os\"] == \"Linux\"\n\n    def test_settings_as_a_list_conanfile(self):\n        # Now with conanfile as a list\n        client = TestClient()\n        client.save({CONANFILE: GenConanfile(\"say\", \"0.1\").with_settings(\"os\", \"arch\")})\n        client.run(\"create . -s os=Windows --build missing\")\n        conan_info = self._get_conaninfo(\"say/0.1@\", client)\n        assert conan_info[\"settings\"][\"os\"] == \"Windows\"\n\n    def test_settings_as_a_dict_conanfile(self):\n        # Now with conanfile as a set\n        content = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class SayConan(ConanFile):\n                name = \"say\"\n                version = \"0.1\"\n                settings = {\"os\", \"arch\"}\n            \"\"\")\n        client = TestClient()\n        client.save({CONANFILE: content})\n        client.run(\"create . -s os=Windows --build missing\")\n        conan_info = self._get_conaninfo(\"say/0.1@\", client)\n        assert conan_info[\"settings\"][\"os\"] == \"Windows\"\n\n    def test_invalid_settings3(self):\n        client = TestClient()\n        # Test wrong settings in conanfile\n        client.save({CONANFILE: GenConanfile().with_settings(\"invalid\")})\n        client.run(\"install . --build missing\", assert_error=True)\n        assert \"'settings.invalid' doesn't exist\" in client.out\n\n        # Test wrong values in conanfile\n    def test_invalid_settings4(self):\n        client = TestClient()\n        client.save({CONANFILE: GenConanfile(\"say\", \"0.1\").with_settings(\"os\")})\n        client.run(\"create . -s os=ChromeOS --build missing\", assert_error=True)\n        assert \"ERROR: Invalid setting 'ChromeOS' is not a valid 'settings.os' value.\" in client.out\n        assert \"Possible values are ['Windows', 'WindowsStore', 'WindowsCE', 'Linux'\" in client.out\n\n        # Now add new settings to config and try again\n        config = load(client.paths.settings_path)\n        config = config.replace(\"Windows:\",\n                                \"Windows:\\n    ChromeOS:\\n\")\n\n        save(client.paths.settings_path, config)\n        client.run(\"create . -s os=ChromeOS --build missing\")\n\n        # Settings is None\n        content = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class SayConan(ConanFile):\n                name = \"say\"\n                version = \"0.1\"\n                settings = None\n            \"\"\")\n        client.save({CONANFILE: content})\n        client.run(\"remove say/0.1 -c\")\n        client.run(\"create . --build missing\")\n        conan_info = self._get_conaninfo(\"say/0.1\", client)\n        assert conan_info.get(\"settings\") == None  # noqa\n\n        # Settings is {}\n        content = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class SayConan(ConanFile):\n                name = \"say\"\n                version = \"0.1\"\n                settings = {}\n            \"\"\")\n        client.save({CONANFILE: content})\n        client.run(\"remove say/0.1 -c\")\n        client.run(\"create . --build missing\")\n        conan_info = self._get_conaninfo(\"say/0.1\", client)\n\n        assert conan_info.get(\"settings\") == None  # noqa\n"
  },
  {
    "path": "test/unittests/model/profile_test.py",
    "content": "from collections import OrderedDict\n\nfrom conan.tools.env.environment import ProfileEnvironment\nfrom conan.internal.model.profile import Profile\n\n\nclass TestProfile:\n\n    def test_profile_settings_update(self):\n        new_profile = Profile()\n        new_profile.update_settings(OrderedDict([(\"os\", \"Windows\")]))\n\n        new_profile.update_settings(OrderedDict([(\"OTHER\", \"2\")]))\n        assert new_profile.settings == OrderedDict([(\"os\", \"Windows\"), (\"OTHER\", \"2\")])\n\n        new_profile.update_settings(OrderedDict([(\"compiler\", \"2\"), (\"compiler.version\", \"3\")]))\n        assert new_profile.settings == OrderedDict([(\"os\", \"Windows\"), (\"OTHER\", \"2\"),\n                                      (\"compiler\", \"2\"), (\"compiler.version\", \"3\")])\n\n    def test_profile_subsettings_update(self):\n        new_profile = Profile()\n        new_profile.update_settings(OrderedDict([(\"os\", \"Windows\"),\n                                                (\"compiler\", \"Visual Studio\"),\n                                                (\"compiler.runtime\", \"MT\")]))\n\n        new_profile.update_settings(OrderedDict([(\"compiler\", \"gcc\")]))\n        assert dict(new_profile.settings) == {\"compiler\": \"gcc\", \"os\": \"Windows\"}\n\n        new_profile = Profile()\n        new_profile.update_settings(OrderedDict([(\"os\", \"Windows\"),\n                                                 (\"compiler\", \"Visual Studio\"),\n                                                 (\"compiler.runtime\", \"MT\")]))\n\n        new_profile.update_settings(OrderedDict([(\"compiler\", \"Visual Studio\"),\n                                                 (\"compiler.subsetting\", \"3\"),\n                                                 (\"other\", \"value\")]))\n\n        assert dict(new_profile.settings) == {\"compiler\": \"Visual Studio\",\n                                                      \"os\": \"Windows\",\n                                                      \"compiler.runtime\": \"MT\",\n                                                      \"compiler.subsetting\": \"3\",\n                                                      \"other\": \"value\"}\n\n    def test_package_settings_update(self):\n        np = Profile()\n        np.update_package_settings({\"MyPackage\": [(\"os\", \"Windows\")]})\n\n        np.update_package_settings({\"MyPackage\": [(\"OTHER\", \"2\")]})\n        assert np.package_settings_values == {\"MyPackage\": [(\"os\", \"Windows\"), (\"OTHER\", \"2\")]}\n\n        np._package_settings_values = None  # invalidate caching\n        np.update_package_settings({\"MyPackage\": [(\"compiler\", \"2\"), (\"compiler.version\", \"3\")]})\n        assert np.package_settings_values == {\"MyPackage\": [(\"os\", \"Windows\"), (\"OTHER\", \"2\"),\n                                        (\"compiler\", \"2\"), (\"compiler.version\", \"3\")]}\n\n    def test_profile_dump_order(self):\n        # Settings\n        profile = Profile()\n        profile.package_settings[\"zlib\"] = {\"compiler\": \"gcc\"}\n        profile.settings[\"arch\"] = \"x86_64\"\n        profile.settings[\"compiler\"] = \"Visual Studio\"\n        profile.settings[\"compiler.version\"] = \"12\"\n        profile.tool_requires[\"*\"] = [\"zlib/1.2.8@lasote/testing\"]\n        profile.tool_requires[\"zlib/*\"] = [\"aaaa/1.2.3@lasote/testing\",\n                                                 \"bb/1.2@lasote/testing\"]\n        assert \"\"\"[settings]\narch=x86_64\ncompiler=Visual Studio\ncompiler.version=12\nzlib:compiler=gcc\n[tool_requires]\n*: zlib/1.2.8@lasote/testing\nzlib/*: aaaa/1.2.3@lasote/testing, bb/1.2@lasote/testing\n\"\"\".splitlines() == profile.dumps().splitlines()\n\n    def test_apply(self):\n        # Settings\n        profile = Profile()\n        profile.settings[\"arch\"] = \"x86_64\"\n        profile.settings[\"compiler\"] = \"Visual Studio\"\n        profile.settings[\"compiler.version\"] = \"12\"\n\n        profile.update_settings(OrderedDict([(\"compiler.version\", \"14\")]))\n\n        assert '[settings]\\narch=x86_64\\ncompiler=Visual Studio\\ncompiler.version=14\\n' == profile.dumps()\n\n\ndef test_update_build_requires():\n    # https://github.com/conan-io/conan/issues/8205#issuecomment-775032229\n    profile = Profile()\n    profile.tool_requires[\"*\"] = [\"zlib/1.2.8\"]\n\n    profile2 = Profile()\n    profile2.tool_requires[\"*\"] = [\"zlib/1.2.8\"]\n\n    profile.compose_profile(profile2)\n    assert profile.tool_requires[\"*\"] == [\"zlib/1.2.8\"]\n\n    profile3 = Profile()\n    profile3.tool_requires[\"*\"] = [\"zlib/1.2.11\"]\n\n    profile.compose_profile(profile3)\n    assert profile.tool_requires[\"*\"] == [\"zlib/1.2.11\"]\n\n    profile4 = Profile()\n    profile4.tool_requires[\"*\"] = [\"cmake/2.7\"]\n\n    profile.compose_profile(profile4)\n    assert profile.tool_requires[\"*\"] == [\"zlib/1.2.11\", \"cmake/2.7\"]\n\n\ndef test_profile_serialize():\n    profile = Profile()\n    profile.options.loads(\"zlib*:aoption=1\\nzlib*:otheroption=1\")\n    profile.buildenv = ProfileEnvironment.loads(\"VAR1=1\\nVAR2=2\")\n    profile.conf.update(\"user.myfield:value\", \"MyVal\")\n    profile.settings[\"arch\"] = \"x86_64\"\n    profile.settings[\"compiler\"] = \"Visual Studio\"\n    profile.settings[\"compiler.version\"] = \"12\"\n    profile.tool_requires[\"*\"] = [\"zlib/1.2.8\"]\n    profile.update_package_settings({\"MyPackage\": [(\"os\", \"Windows\")]})\n    expected_json = {\n        \"settings\": {\"arch\": \"x86_64\", \"compiler\": \"Visual Studio\", \"compiler.version\": \"12\"},\n        \"package_settings\": {\"MyPackage\": {\"os\": \"Windows\"}}, \"options\": {},\n        \"tool_requires\": {\"*\": [\"'zlib/1.2.8'\"]}, \"conf\": {\"user.myfield:value\": \"MyVal\"},\n        \"build_env\": \"VAR1=1\\nVAR2=2\\n\"}\n    assert expected_json == profile.serialize()\n\n    profile.replace_requires.update({\"cmake/*\": \"cmake/3.29.0\"})\n    profile.platform_tool_requires = [\"cmake/3.29.0\"]\n    expected_json = {\n        \"settings\": {\"arch\": \"x86_64\", \"compiler\": \"Visual Studio\", \"compiler.version\": \"12\"},\n        \"package_settings\": {\"MyPackage\": {\"os\": \"Windows\"}}, \"options\": {},\n        \"replace_requires\": {\"cmake/*\": \"cmake/3.29.0\"},\n        \"platform_tool_requires\": [\"cmake/3.29.0\"],\n        \"tool_requires\": {\"*\": [\"'zlib/1.2.8'\"]}, \"conf\": {\"user.myfield:value\": \"MyVal\"},\n        \"build_env\": \"VAR1=1\\nVAR2=2\\n\"}\n    assert expected_json == profile.serialize()\n"
  },
  {
    "path": "test/unittests/model/settings_test.py",
    "content": "import textwrap\nimport pytest\n\nfrom conan.internal.default_settings import default_settings_yml\nfrom conan.errors import ConanException\nfrom conan.internal.model.settings import Settings, bad_value_msg, undefined_field\n\n\ndef undefined_value(v):\n    return \"'%s' value not defined\" % v\n\n\nclass TestSettingsLoads:\n\n    def test_none_value(self):\n        yml = \"os: [null, Windows]\"\n        settings = Settings.loads(yml)\n        settings.validate()\n        assert settings.os == None\n        assert \"\" == settings.dumps()\n        settings.os = \"Windows\"\n        assert settings.os == \"Windows\"\n        assert \"os=Windows\" == settings.dumps()\n\n    def test_any(self):\n        yml = \"os: [ANY]\"\n        settings = Settings.loads(yml)\n        with pytest.raises(ConanException, match=\"'settings.os' value not defined\"):\n            settings.validate()  # Raise exception if unset\n        settings.os = \"some-os\"\n        settings.validate()\n        assert settings.os == \"some-os\"\n        assert \"os=some-os\" in settings.dumps()\n        settings.os = \"Windows\"\n        assert settings.os == \"Windows\"\n        assert \"os=Windows\" == settings.dumps()\n\n    def test_none_any(self):\n        yml = \"os: [null, ANY]\"\n        settings = Settings.loads(yml)\n        settings.validate()\n        settings.os = \"None\"\n        settings.validate()\n        assert settings.os == \"None\"\n        assert \"os=None\" in settings.dumps()\n        settings.os = \"Windows\"\n        assert settings.os == \"Windows\"\n        assert \"os=Windows\" == settings.dumps()\n\n    def test_nested_any(self):\n        yml = textwrap.dedent(\"\"\"\\\n            os:\n                ANY:\n                    version: [null, ANY]\n                Ubuntu:\n                    version: [\"18.04\", \"20.04\"]\n            \"\"\")\n        settings = Settings.loads(yml)\n        settings.os = \"Windows\"\n        settings.validate()\n        assert settings.os == \"Windows\"\n        assert \"os=Windows\" in settings.dumps()\n        settings.os.version = 2\n        assert settings.os == \"Windows\"\n        assert \"os=Windows\\nos.version=2\" == settings.dumps()\n        settings.os = \"Ubuntu\"\n        with pytest.raises(ConanException, match=\"'settings.os.version' value not defined\"):\n            settings.validate()\n        with pytest.raises(ConanException, match=\"Invalid setting '3' is not a valid 'settings.os.version'\"):\n            settings.os.version = 3\n        settings.os.version = \"20.04\"\n        assert \"os=Ubuntu\\nos.version=20.04\" == settings.dumps()\n        assert settings.os.version == \"20.04\"\n\n    def test_getattr_none(self):\n        yml = \"os: [None, Windows]\"\n        settings = Settings.loads(yml)\n        assert settings.os == None\n        _os = getattr(settings, \"os\")\n        assert _os == None\n        assert str(_os) == \"None\"\n\n    def test_get_safe(self):\n        yml = \"os: [None, Windows]\"\n        settings = Settings.loads(yml)\n        settings.os = \"Windows\"\n        assert settings.os == \"Windows\"\n        assert settings.get_safe(\"compiler.version\") == None\n        assert settings.get_safe(\"build_type\") == None\n        assert \"Release\" == settings.get_safe(\"build_type\", \"Release\")\n        assert False == settings.get_safe(\"build_type\", False)\n        assert \"Windows\" == settings.get_safe(\"os\", \"Linux\")\n\n    def test_none_subsetting(self):\n        yml = \"\"\"os:\n    null:\n    Windows:\n        subsystem: [null, cygwin]\n\"\"\"\n        settings = Settings.loads(yml)\n        settings.validate()\n        assert settings.os == None\n        assert \"\" == settings.dumps()\n        settings.os = \"Windows\"\n        assert settings.os.subsystem == None\n        assert \"os=Windows\" == settings.dumps()\n        settings.os.subsystem = \"cygwin\"\n        settings.validate()\n        assert \"os=Windows\\nos.subsystem=cygwin\" == settings.dumps()\n\n    def test_none__sub_subsetting(self):\n        yml = \"\"\"os:\n    null:\n        subsystem: [null, cygwin]\n    Windows:\n\"\"\"\n        with pytest.raises(ConanException, match=\"settings.yml: null setting can't have subsettings\"):\n            Settings.loads(yml)\n\n\nclass TestSettings:\n\n    @pytest.fixture(autouse=True)\n    def setup(self):\n        data = {\"compiler\": {\n                            \"Visual Studio\": {\n                                             \"version\": [\"10\", \"11\", \"12\"],\n                                             \"runtime\": [\"MD\", \"MT\"]},\n                            \"gcc\": {\n                                   \"version\": [\"4.8\", \"4.9\"],\n                                   \"arch\": {\"x86\": {\"speed\": [\"A\", \"B\"]},\n                                            \"x64\": {\"speed\": [\"C\", \"D\"]}}}\n                                   },\n                \"os\": [\"Windows\", \"Linux\"]}\n        self.sut = Settings(data)\n\n    def test_in_contains(self):\n        self.sut.compiler = \"Visual Studio\"\n        assert \"Visual\" in self.sut.compiler\n        assert not (\"Visual\" not in self.sut.compiler)\n\n    def test_os_split(self):\n        settings = Settings.loads(\"\"\"os:\n    Windows:\n    Linux:\n    Macos:\n        version: [1, 2]\n    Android:\n\"\"\")\n        other_settings = Settings.loads(\"os: [Windows, Linux]\")\n        settings.os = \"Windows\"\n        other_settings.os = \"Windows\"\n        assert settings.dumps() == other_settings.dumps()\n\n    def test_any(self):\n        data = {\"target\": [\"ANY\"]}\n        sut = Settings(data)\n        sut.target = \"native\"\n        assert sut.target == \"native\"\n\n    def test_multi_os(self):\n        settings = Settings.loads(\"\"\"os:\n            Windows:\n            Linux:\n                distro: [RH6, RH7]\n            Macos:\n                codename: [Mavericks, Yosemite]\n        \"\"\")\n        settings.os = \"Windows\"\n        assert settings.os == \"Windows\"\n        settings.os = \"Linux\"\n        settings.os.distro = \"RH6\"\n        assert settings.os.distro == \"RH6\"\n        with pytest.raises(ConanException):\n            settings.os.distro = \"Other\"\n        with pytest.raises(ConanException):\n            settings.os.codename = \"Yosemite\"\n        settings.os = \"Macos\"\n        settings.os.codename = \"Yosemite\"\n        assert settings.os.codename == \"Yosemite\"\n\n    def test_remove(self):\n        del self.sut.compiler\n        self.sut.os = \"Windows\"\n        self.sut.validate()\n        assert self.sut.dumps() == \"os=Windows\"\n\n    def test_loads_default(self):\n        settings = Settings.loads(\"\"\"os: [Windows, Linux, Macos, Android, FreeBSD, SunOS]\narch: [x86, x86_64, arm]\ncompiler:\n    sun-cc:\n        version: [\"5.10\", \"5.11\", \"5.12\", \"5.13\", \"5.14\"]\n    gcc:\n        version: [\"4.8\", \"4.9\", \"5.0\"]\n    msvc:\n        runtime: [None, MD, MT, MTd, MDd]\n        version: [\"10\", \"11\", \"12\"]\n    clang:\n        version: [\"3.5\", \"3.6\", \"3.7\"]\n\nbuild_type: [None, Debug, Release]\"\"\")\n        settings.compiler = \"clang\"\n        settings.compiler.version = \"3.5\"\n        assert settings.compiler == \"clang\"\n        assert settings.compiler.version == \"3.5\"\n\n    def test_loads(self):\n        settings = Settings.loads(\"\"\"\ncompiler:\n    msvc:\n        runtime: [MD, MT]\n        version:\n            '10':\n                arch: [\"32\"]\n            '11':\n                &id1\n                arch: [\"32\", \"64\"]\n            '12':\n                *id1\n    gcc:\n        arch:\n            x64:\n                speed: [C, D]\n            x86:\n                speed: [A, B]\n        version: ['4.8', '4.9']\nos: [Windows, Linux]\n\"\"\")\n        settings.update_values([('compiler', 'msvc'),\n                                ('compiler.version', '10'),\n                                ('compiler.version.arch', '32')])\n        assert settings.values_list == [('compiler', 'msvc'),\n                          ('compiler.version', '10'),\n                          ('compiler.version.arch', '32')]\n\n        settings.compiler.version = \"10\"\n        settings.compiler.version.arch = \"32\"\n        settings.compiler.version = \"11\"\n        settings.compiler.version.arch = \"64\"\n        settings.compiler.version = \"12\"\n        settings.compiler.version.arch = \"64\"\n\n        assert settings.values_list == [('compiler', 'msvc'),\n                          ('compiler.version', '12'),\n                          ('compiler.version.arch', '64')]\n\n    def test_set_value(self):\n        self.sut.update_values([(\"compiler\", \"Visual Studio\")])\n        assert self.sut.compiler == \"Visual Studio\"\n        self.sut.update_values([(\"compiler.version\", \"12\")])\n        assert self.sut.compiler.version == \"12\"\n        self.sut.update_values([(\"compiler\", \"gcc\")])\n        assert self.sut.compiler == \"gcc\"\n        self.sut.update_values([(\"compiler.version\", \"4.8\")])\n        assert self.sut.compiler.version == \"4.8\"\n        self.sut.update_values([(\"compiler.arch\", \"x86\")])\n        assert self.sut.compiler.arch == \"x86\"\n        self.sut.update_values([(\"compiler.arch.speed\", \"A\")])\n        assert self.sut.compiler.arch.speed == \"A\"\n\n    def test_constraint(self):\n        s2 = [\"os\"]\n        self.sut.constrained(s2)\n        with pytest.raises(ConanException) as cm:\n            self.sut.compiler  # noqa\n        assert str(cm.value) == str(undefined_field(\"settings\", \"compiler\", [\"os\"], \"settings\"))\n        self.sut.os = \"Windows\"\n        self.sut.os = \"Linux\"\n\n    def test_constraint2(self):\n        s2 = [\"os2\"]\n        with pytest.raises(ConanException) as cm:\n            self.sut.constrained(s2)\n        assert str(cm.value) == str(undefined_field(\"settings\", \"os2\", [\"compiler\", \"os\"],\n                                                    \"settings\"))\n\n    def test_constraint6(self):\n        s2 = {\"os\", \"compiler\"}\n        self.sut.constrained(s2)\n        self.sut.compiler = \"Visual Studio\"\n        with pytest.raises(ConanException) as cm:\n            self.sut.compiler.arch  # noqa\n        assert str(cm.value) == str(undefined_field(\"settings.compiler\", \"arch\",\n                                                    ['runtime', 'version'], \"Visual Studio\"))\n        self.sut.os = \"Windows\"\n        self.sut.compiler.version = \"11\"\n        self.sut.compiler.version = \"12\"\n\n    def test_validate(self):\n        with pytest.raises(ConanException, match=str(undefined_value(\"settings.compiler\"))):\n            self.sut.validate()\n\n        self.sut.compiler = \"gcc\"\n        with pytest.raises(ConanException, match=\"value not defined\"):\n            self.sut.validate()\n\n        self.sut.compiler.arch = \"x86\"\n        with pytest.raises(ConanException, match=\"value not defined\"):\n            self.sut.validate()\n\n        self.sut.compiler.arch.speed = \"A\"\n        with pytest.raises(ConanException, match=\"value not defined\"):\n            self.sut.validate()\n\n        self.sut.compiler.version = \"4.8\"\n        with pytest.raises(ConanException, match=\"value not defined\"):\n            self.sut.validate()\n\n        self.sut.os = \"Windows\"\n        self.sut.validate()\n        assert self.sut.values_list == [(\"compiler\", \"gcc\"),\n                                        (\"compiler.arch\", \"x86\"),\n                                        (\"compiler.arch.speed\", \"A\"),\n                                        (\"compiler.version\", \"4.8\"),\n                                        (\"os\", \"Windows\")]\n\n    def test_validate2(self):\n        self.sut.os = \"Windows\"\n        self.sut.compiler = \"Visual Studio\"\n        with pytest.raises(ConanException, match=\"value not defined\"):\n            self.sut.validate()\n\n        self.sut.compiler.runtime = \"MD\"\n        with pytest.raises(ConanException, match=\"value not defined\"):\n            self.sut.validate()\n\n        self.sut.compiler.version = \"10\"\n        self.sut.validate()\n\n        assert self.sut.values_list == [(\"compiler\", \"Visual Studio\"),\n                                                (\"compiler.runtime\", \"MD\"),\n                                                (\"compiler.version\", \"10\"),\n                                                (\"os\", \"Windows\")]\n\n    def test_basic(self):\n        s = Settings({\"os\": [\"Windows\", \"Linux\"]})\n        s.os = \"Windows\"\n        with pytest.raises(ConanException) as cm:\n            self.sut.compiler = \"kk\"\n        assert str(cm.value) == bad_value_msg(\"settings.compiler\", \"kk\", ['Visual Studio', 'gcc'])\n\n    def test_my(self):\n        assert self.sut.compiler == None\n\n        with pytest.raises(ConanException) as cm:\n            self.sut.compiler = \"kk\"\n        assert str(cm.value) == bad_value_msg(\"settings.compiler\", \"kk\", ['Visual Studio', 'gcc'])\n\n        self.sut.compiler = \"Visual Studio\"\n        assert str(self.sut.compiler) == \"Visual Studio\"\n        assert self.sut.compiler == \"Visual Studio\"\n\n        with pytest.raises(ConanException) as cm:\n            self.sut.compiler.kk  # noqa\n        assert str(cm.value) == str(undefined_field(\"settings.compiler\", \"kk\",\n                                                    ['runtime', 'version'], \"Visual Studio\"))\n\n        assert self.sut.compiler.version == None  # noqa\n\n        with pytest.raises(ConanException) as cm:\n            self.sut.compiler.version = \"123\"\n        assert str(cm.value) == bad_value_msg(\"settings.compiler.version\", \"123\", ['10', '11', '12'])\n\n        self.sut.compiler.version = \"12\"\n        assert self.sut.compiler.version == \"12\"\n        assert str(self.sut.compiler.version) == \"12\"\n\n        with pytest.raises(ConanException) as cm:\n            assert self.sut.compiler == \"kk\"\n        assert str(cm.value) == bad_value_msg(\"settings.compiler\", \"kk\", ['Visual Studio', 'gcc'])\n\n        assert not (self.sut.compiler == \"gcc\")\n        assert self.sut.compiler == \"Visual Studio\"\n\n        assert self.sut.compiler.version == \"12\"\n        assert not (self.sut.compiler.version == \"11\")\n\n        with pytest.raises(ConanException) as cm:\n            assert self.sut.compiler.version == \"13\"\n        assert str(cm.value) == bad_value_msg(\"settings.compiler.version\", \"13\", ['10', '11', '12'])\n\n        self.sut.compiler = \"gcc\"\n        with pytest.raises(ConanException) as cm:\n            self.sut.compiler.runtime  # noqa\n        assert str(cm.value) == str(undefined_field(\"settings.compiler\", \"runtime\",\n                                                    \"['arch', 'version']\", \"gcc\"))\n\n        self.sut.compiler.arch = \"x86\"\n        self.sut.compiler.arch.speed = \"A\"\n        assert self.sut.compiler.arch.speed == \"A\"\n\n        with pytest.raises(ConanException) as cm:\n            self.sut.compiler.arch.speed = \"D\"\n        assert str(cm.value) == bad_value_msg(\"settings.compiler.arch.speed\", \"D\", ['A', 'B'])\n\n        self.sut.compiler.arch = \"x64\"\n        self.sut.compiler.arch.speed = \"C\"\n        assert self.sut.compiler.arch.speed == \"C\"\n\n        with pytest.raises(ConanException) as cm:\n            self.sut.compiler.arch.speed = \"A\"\n        assert str(cm.value) == bad_value_msg(\"settings.compiler.arch.speed\", \"A\", ['C', 'D'])\n\n        self.sut.compiler.arch.speed = \"D\"\n        assert self.sut.compiler.arch.speed == \"D\"\n\n\ndef test_possible_values():\n    settings = Settings.loads(default_settings_yml)\n    settings.compiler = \"gcc\"\n    sot = settings.compiler.cppstd.possible_values()\n    assert sot == [None, '98', 'gnu98', '11', 'gnu11', '14', 'gnu14', '17', 'gnu17', '20',\n                   'gnu20', '23', 'gnu23', '26', 'gnu26']\n\n    # We cannot access the child definition of a non declared setting\n    with pytest.raises(Exception) as e:\n        settings.os.version.possible_values()\n\n    assert \"'settings.os' value not defined\" in str(e.value)\n\n    # But if we have it declared, we can\n    settings.os = \"watchOS\"\n    sot = settings.os.version.possible_values()\n    assert \"4.0\" in sot\n\n    # We can get the whole settings definition and explore the dict\n    sot = settings.possible_values()\n    assert [None, \"cygwin\", \"msys\", \"msys2\", \"wsl\"] == sot[\"os\"][\"Windows\"][\"subsystem\"]\n\n\ndef test_rm_safe():\n    settings = Settings.loads(default_settings_yml)\n    settings.rm_safe(\"compiler.cppstd\")\n    settings.rm_safe(\"compiler.libcxx\")\n    settings.compiler = \"gcc\"\n    with pytest.raises(Exception) as e:\n        settings.compiler.cppstd = \"14\"\n    assert \"'settings.compiler.cppstd' doesn't exist for 'gcc'\" in str(e.value)\n    with pytest.raises(Exception) as e:\n        settings.compiler.libcxx = \"libstdc++\"\n    assert \"'settings.compiler.libcxx' doesn't exist for 'gcc'\" in str(e.value)\n\n    settings.compiler = \"clang\"\n    with pytest.raises(Exception) as e:\n        settings.compiler.cppstd = \"14\"\n    assert \"'settings.compiler.cppstd' doesn't exist for 'clang'\" in str(e.value)\n    with pytest.raises(Exception) as e:\n        settings.compiler.libcxx = \"libstdc++\"\n    assert \"'settings.compiler.libcxx' doesn't exist for 'clang'\" in str(e.value)\n\n\ndef test_rm_safe_wildcard():\n    settings = Settings.loads(default_settings_yml)\n    settings.compiler = \"gcc\"\n    settings.compiler.version = \"4.8\"\n    settings.compiler.libcxx = \"libstdc++\"\n    settings.rm_safe(\"compiler.*\")\n    assert settings.compiler == \"gcc\"\n    assert settings.get_safe(\"compiler.version\") is None\n    assert settings.get_safe(\"compiler.libcxx\") is None\n\n\ndef test_settings_intel_cppstd_03():\n    settings = Settings.loads(default_settings_yml)\n    settings.compiler = \"intel-cc\"\n    # This doesn't crash, it used to crash due to \"03\" not quoted in setting.yml\n    settings.compiler.cppstd = \"03\"\n\n\ndef test_set_value_non_existing_values():\n    data = {\n        \"compiler\": {\n            \"gcc\": {\n                \"version\": [\"4.8\", \"4.9\"],\n                \"arch\": {\"x86\": {\"speed\": [\"A\", \"B\"]},\n                         \"x64\": {\"speed\": [\"C\", \"D\"]}}}\n        },\n        \"os\": [\"Windows\", \"Linux\"]\n    }\n    settings = Settings(data)\n    with pytest.raises(ConanException) as cm:\n        settings.update_values([(\"foo\", \"A\")])\n    assert \"'settings.foo' doesn't exist for 'settings'\" in str(cm.value)\n    with pytest.raises(ConanException) as cm:\n        settings.update_values([(\"foo.bar\", \"A\")])\n    assert \"'settings.foo' doesn't exist for 'settings'\" in str(cm.value)\n    # it does not raise any error\n    settings.update_values([(\"foo\", \"A\")], raise_undefined=False)\n    settings.update_values([(\"foo.bar\", \"A\")], raise_undefined=False)\n"
  },
  {
    "path": "test/unittests/model/test_conf.py",
    "content": "import textwrap\n\nimport pytest\n\nfrom conan.api.model import RecipeReference\nfrom conan.errors import ConanException\nfrom conan.internal.model.conf import ConfDefinition\n\n\n@pytest.fixture()\ndef conf_definition():\n    text = textwrap.dedent(\"\"\"\\\n        tools.build:verbosity=quiet\n        user.company.toolchain:flags=someflags\n    \"\"\")\n    c = ConfDefinition()\n    c.loads(text)\n    return c, text\n\n\ndef test_conf_definition(conf_definition):\n    c, text = conf_definition\n    # Round trip\n    assert c.dumps() == text\n    # access\n    assert c.get(\"tools.build:verbosity\") == \"quiet\"\n    assert c.get(\"user.company.toolchain:flags\") == \"someflags\"\n    assert c.get(\"user.microsoft.msbuild:nonexist\") is None\n    assert c.get(\"user:nonexist\") is None\n    # bool\n    assert bool(c)\n    assert not bool(ConfDefinition())\n\n\n@pytest.mark.parametrize(\"conf_name\", [\n    \"tools.doesnotexist:never\",\n    \"tools:doesnotexist\",\n    \"core.doesnotexist:never\",\n    \"core:doesnotexist\"\n])\ndef test_conf_definition_error(conf_definition, conf_name):\n    c, text = conf_definition\n    with pytest.raises(ConanException):\n        c.get(conf_name)\n\n\ndef test_conf_update(conf_definition):\n    c, _ = conf_definition\n    text = textwrap.dedent(\"\"\"\\\n        user.company.toolchain:flags=newvalue\n        user.something:key=value\n    \"\"\")\n    c2 = ConfDefinition()\n    c2.loads(text)\n    c.update_conf_definition(c2)\n    result = textwrap.dedent(\"\"\"\\\n        tools.build:verbosity=quiet\n        user.company.toolchain:flags=newvalue\n        user.something:key=value\n    \"\"\")\n    assert c.dumps() == result\n\n\ndef test_conf_rebase(conf_definition):\n    c, _ = conf_definition\n    text = textwrap.dedent(\"\"\"\\\n       user.company.toolchain:flags=newvalue\n       tools.build:verbosity=verbose\"\"\")\n    c2 = ConfDefinition()\n    c2.loads(text)\n    c.rebase_conf_definition(c2)\n    # The c profile will have precedence, and \"\n    result = textwrap.dedent(\"\"\"\\\n        tools.build:verbosity=quiet\n        user.company.toolchain:flags=someflags\n    \"\"\")\n    assert c.dumps() == result\n\n\ndef test_conf_rebase_patterns():\n    text = textwrap.dedent(\"\"\"\\\n        user.company:conf1=value1\n        user.company:conf2=[1, 2, 3]\n        &:user.company:conf1=value2\n        &:user.company:conf2+=[4, 5]\n        \"\"\")\n    global_conf = ConfDefinition()\n    global_conf.loads(text)\n    text = textwrap.dedent(\"\"\"\\\n        user.company:conf1=newvalue1\n        user.company:conf2=[6, 7]\n        \"\"\")\n    profile = ConfDefinition()\n    profile.loads(text)\n    profile.rebase_conf_definition(global_conf)\n    # TODO: at the moment dumps() doesn't print += append\n    result = textwrap.dedent(\"\"\"\\\n        user.company:conf1=newvalue1\n        user.company:conf2=[6, 7]\n        &:user.company:conf1=value2\n        &:user.company:conf2=[4, 5]\n    \"\"\")\n    assert profile.dumps() == result\n\n    text = textwrap.dedent(\"\"\"\\\n        &:user.company:conf1=newvalue1\n        &:user.company:conf2=[6, 7]\n        \"\"\")\n    profile = ConfDefinition()\n    profile.loads(text)\n    profile.rebase_conf_definition(global_conf)\n    result = textwrap.dedent(\"\"\"\\\n        user.company:conf1=value1\n        user.company:conf2=[1, 2, 3]\n        &:user.company:conf1=newvalue1\n        &:user.company:conf2=[6, 7]\n       \"\"\")\n    assert profile.dumps() == result\n\n    text = \"user.company:conf2+=[6, 7]\"\n    profile = ConfDefinition()\n    profile.loads(text)\n    profile.rebase_conf_definition(global_conf)\n    result = textwrap.dedent(\"\"\"\\\n        user.company:conf1=value1\n        user.company:conf2=[1, 2, 3, 6, 7]\n        &:user.company:conf1=value2\n        &:user.company:conf2=[4, 5]\n        \"\"\")\n    assert profile.dumps() == result\n\n    text = \"&:user.company:conf2=+[6, 7]\"\n    profile = ConfDefinition()\n    profile.loads(text)\n    profile.rebase_conf_definition(global_conf)\n    result = textwrap.dedent(\"\"\"\\\n        user.company:conf1=value1\n        user.company:conf2=[1, 2, 3]\n        &:user.company:conf1=value2\n        &:user.company:conf2=[6, 7, 4, 5]\n        \"\"\")\n    assert profile.dumps() == result\n\n\ndef test_conf_error_per_package():\n    text = \"*:core:non_interactive=minimal\"\n    c = ConfDefinition()\n    with pytest.raises(ConanException,\n                       match=r\"Conf '\\*:core:non_interactive' cannot have a package pattern\"):\n        c.loads(text)\n\n\ndef test_conf_error_uppercase():\n    text = \"tools.something:Verbosity=minimal\"\n    c = ConfDefinition()\n    with pytest.raises(ConanException, match=r\"Conf 'tools.something:Verbosity' must be lowercase\"):\n        c.loads(text)\n    text = \"tools.Something:verbosity=minimal\"\n    c = ConfDefinition()\n    with pytest.raises(ConanException,\n                       match=r\"Conf 'tools.Something:verbosity' must be lowercase\"):\n        c.loads(text)\n\n\ndef test_parse_spaces():\n    text = \"core:non_interactive = minimal\"\n    c = ConfDefinition()\n    c.loads(text)\n    assert c.get(\"core:non_interactive\") == \"minimal\"\n\n\n@pytest.mark.parametrize(\"text, expected\", [\n    (\"user.company.cpu:jobs=!\", None),\n    (\"user.company.cpu:jobs=10\", 10),\n    (\"user.company.build:ccflags=--m superflag\", \"--m superflag\"),\n    (\"zlib:user.company.check:shared=True\", True),\n    (\"zlib:user.company.check:shared_str='True'\", \"'True'\"),\n    (\"user.company.list:objs=[1, 2, 3, 4, 'mystr', {'a': 1}]\", [1, 2, 3, 4, 'mystr', {'a': 1}]),\n    (\"user.company.network:proxies={'url': 'http://api.site.com/api', 'dataType': 'json', 'method': 'GET'}\",\n     {'url': 'http://api.site.com/api', 'dataType': 'json', 'method': 'GET'})\n])\ndef test_conf_get_different_type_input_objects(text, expected):\n    \"\"\"\n    Testing any possible Python-evaluable-input-format introduced\n    by the user\n    \"\"\"\n    c = ConfDefinition()\n    c.loads(text)\n    assert c.get(text.split(\"=\")[0]) == expected\n\n\n@pytest.mark.parametrize(\"text1, text2, expected\", [\n    (\"user.company.list:objs=[2, 3]\", \"user.company.list:objs=+[0, 1]\", [0, 1, 2, 3]),\n    (\"user.company.list:objs=[2, 3]\", \"user.company.list:objs+=[4, 5]\", [2, 3, 4, 5]),\n    (\"user.company.list:objs=[2, 3]\", \"user.company.list:objs+={'a': 1}\", [2, 3, {'a': 1}]),\n    (\"user.company.list:objs=[2, 3]\", \"user.company.list:objs=+start\", [\"start\", 2, 3]),\n    (\"user.company.list:objs=[2, 3]\", \"user.company.list:objs=[0, 1]\", [0, 1]),\n])\ndef test_conf_list_operations(text1, text2, expected):\n    c1 = ConfDefinition()\n    c1.loads(text1)\n    c2 = ConfDefinition()\n    c2.loads(text2)\n    c1.update_conf_definition(c2)\n    assert c1.get(text1.split(\"=\")[0]) == expected\n\n\n@pytest.mark.parametrize(\"text1, text2\", [\n    (\"user.company.list:objs=value\", \"user.company.list:objs=['value']\"),\n    (\"user.company.list:objs='value'\", \"user.company.list:objs=+[0, 1]\"),\n    (\"user.company.list:objs={'a': 1}\", \"user.company.list:objs+={'b': 1}\"),\n    (\"user.company.list:objs=True\", \"user.company.list:objs+=False\"),\n    (\"user.company.list:objs=10\", \"user.company.list:objs=+11\")\n])\ndef test_conf_list_operations_fails_with_wrong_types(text1, text2):\n    c1 = ConfDefinition()\n    c1.loads(text1)\n    c1_value_type = type(c1.get(\"user.company.list:objs\")).__name__\n    c2 = ConfDefinition()\n    c2.loads(text2)\n    with pytest.raises(ConanException) as exc_info:\n        c1.update_conf_definition(c2)\n    assert \"It's not possible to compose list values and %s ones\" % c1_value_type \\\n           in str(exc_info.value)\n\n\ndef test_compose_conf_complex():\n    \"\"\"\n    Testing the composition between several ConfDefiniton objects and with\n    different value types\n    \"\"\"\n    text = textwrap.dedent(\"\"\"\\\n        user.company.cpu:jobs=10\n        user.company.build:ccflags=--m superflag\n        zlib:user.company.check:shared=True\n        zlib:user.company.check:shared_str=\"True\"\n        user.company.list:objs=[1, 2, 3, 4, 'mystr', {'a': 1}]\n        user.company.network:proxies={'url': 'http://api.site.com/api', 'dataType': 'json', 'method': 'GET'}\n    \"\"\")\n    c = ConfDefinition()\n    c.loads(text)\n    text = textwrap.dedent(\"\"\"\\\n        user.company.cpu:jobs=5\n        user.company.build:ccflags=--m otherflag\n        zlib:user.company.check:shared=!\n        zlib:user.company.check:shared_str=\"False\"\n        user.company.list:objs+=[5, 6]\n        user.company.list:objs=+0\n        user.company.list:objs+={'b': 2}\n        user.company.network:proxies={'url': 'http://api.site.com/apiv2'}\n        \"\"\")\n    c2 = ConfDefinition()\n    c2.loads(text)\n    c.update_conf_definition(c2)\n    expected_text = textwrap.dedent(\"\"\"\\\n        user.company.build:ccflags=--m otherflag\n        user.company.cpu:jobs=5\n        user.company.list:objs=[0, 1, 2, 3, 4, 'mystr', {'a': 1}, 5, 6, {'b': 2}]\n        user.company.network:proxies={'url': 'http://api.site.com/apiv2'}\n        zlib:user.company.check:shared=!\n        zlib:user.company.check:shared_str=\"False\"\n    \"\"\")\n\n    assert c.dumps() == expected_text\n\n\ndef test_compose_conf_dict_updates():\n    c = ConfDefinition()\n    c.loads(\"user.company:mydict={'1': 'a'}\\n\"\n            \"user.company:mydict2={'1': 'a'}\")\n    c2 = ConfDefinition()\n    c2.loads(\"user.company:mydict={'2': 'b'}\\n\"\n             \"user.company:mydict2*={'2': 'b'}\")\n    c.update_conf_definition(c2)\n    assert c.dumps() == (\"user.company:mydict={'2': 'b'}\\n\"\n                         \"user.company:mydict2={'1': 'a', '2': 'b'}\\n\")\n\n\ndef test_compose_conf_numbers():\n    c = ConfDefinition()\n    c.loads(\"user.version:value=8.1\\n\"\n            \"foo/*:user.version:value=10\")\n    assert c.get(\"user.version:value\") == 8.1\n    assert c.get_conanfile_conf(RecipeReference.loads(\"foo/1.0\")).get(\"user.version:value\") == 10\n\n\ndef test_conf_get_check_type_and_default():\n    text = textwrap.dedent(\"\"\"\\\n        user.company.cpu:jobs=5\n        user.company.build:ccflags=--m otherflag\n        user.company.list:objs=[0, 1, 2, 3, 4, 'mystr', {'a': 1}, 5, 6]\n        user.company.network:proxies={'url': 'http://api.site.com/apiv2', 'dataType': 'json', 'method': 'GET'}\n        zlib:user.company.check:shared=!\n        zlib:user.company.check:shared_str=\"False\"\n        zlib:user.company.check:static_str=off\n        user.company.list:newnames+=myname\n        core.download:parallel=True\n        user:bad_value_0=Fasle\n        user:bad_value_1=ture\n        user:bad_value_2=10\n        user:bad_value_3='00'\n    \"\"\")\n    c = ConfDefinition()\n    c.loads(text)\n    assert c.get(\"user.company.cpu:jobs\", check_type=int) == 5\n    assert c.get(\"user.company.cpu:jobs\", check_type=None) == 5\n    assert c.get(\"user.company.cpu:jobs\", check_type=str) == \"5\"  # smart conversion\n    with pytest.raises(ConanException) as exc_info:\n        c.get(\"user.company.cpu:jobs\", check_type=list)\n    assert \"[conf] user.company.cpu:jobs must be a list-like object.\" in str(exc_info.value)\n    # Check type does not affect to default value\n    assert c.get(\"user.non:existing\", default=0, check_type=dict) == 0\n    assert c.get(\"zlib:user.company.check:shared\") is None  # unset value\n    assert c.get(\"zlib:user.company.check:shared\", default=[]) == []  # returning default\n    assert c.get(\"zlib:user.company.check:shared\", default=[], check_type=list) == []  # not raising exception\n    assert c.get(\"zlib:user.company.check:shared_str\") == '\"False\"'\n    assert c.get(\"zlib:user.company.check:shared_str\", check_type=bool) is False  # smart conversion\n    assert c.get(\"zlib:user.company.check:static_str\") == \"off\"\n    assert c.get(\"zlib:user.company.check:static_str\", check_type=bool) is False  # smart conversion\n    assert c.get(\"user.company.list:newnames\") == [\"myname\"]  # Placeholder is removed\n    with pytest.raises(ConanException) as exc_info:\n        c.get(\"core.download:parallel\", check_type=int)\n    assert (\"[conf] core.download:parallel must be a int-like object. \"\n            \"The value 'True' introduced is a bool object\") in str(exc_info.value)\n    with pytest.raises(ConanException) as exc_info:\n        c.get(\"user:bad_value_0\", check_type=bool)\n    assert \"[conf] user:bad_value_0 must be a boolean-like object (true/false, 1/0, on/off) and value 'Fasle' does not match it.\" in str(exc_info.value)\n    with pytest.raises(ConanException) as exc_info:\n        c.get(\"user:bad_value_1\", check_type=bool)\n    assert \"[conf] user:bad_value_1 must be a boolean-like object (true/false, 1/0, on/off) and value 'ture' does not match it.\" in str(exc_info.value)\n    with pytest.raises(ConanException) as exc_info:\n        c.get(\"user:bad_value_2\", check_type=bool)\n    assert \"[conf] user:bad_value_2 must be a boolean-like object (true/false, 1/0, on/off) and value '10' does not match it.\" in str(exc_info.value)\n    with pytest.raises(ConanException) as exc_info:\n        c.get(\"user:bad_value_3\", check_type=bool)\n    assert \"[conf] user:bad_value_3 must be a boolean-like object (true/false, 1/0, on/off) and value '\\'00\\'' does not match it.\" in str(exc_info.value)\n\n\ndef test_conf_pop():\n    text = textwrap.dedent(\"\"\"\\\n        user.company.cpu:jobs=5\n        user.company.build:ccflags=--m otherflag\n        user.company.list:objs=[0, 1, 2, 3, 4, 'mystr', {'a': 1}, 5, 6]\n        user.company.network:proxies={'url': 'http://api.site.com/apiv2', 'dataType': 'json', 'method': 'GET'}\n        zlib:user.company.check:shared=!\n        zlib:user.company.check:shared_str=\"False\"\n    \"\"\")\n    c = ConfDefinition()\n    c.loads(text)\n\n    assert c.pop(\"user.company.network:proxies\") == {'url': 'http://api.site.com/apiv2', 'dataType': 'json', 'method': 'GET'}\n    assert c.pop(\"user.microsoft.msbuild:missing\") is None\n    assert c.pop(\"user.microsoft.msbuild:missing\", default=\"fake\") == \"fake\"\n    assert c.pop(\"zlib:user.company.check:shared_str\") == '\"False\"'\n\n\ndef test_conf_choices():\n    confs = textwrap.dedent(\"\"\"\n    user.category:option1=1\n    user.category:option2=3\"\"\")\n    c = ConfDefinition()\n    c.loads(confs)\n    assert c.get(\"user.category:option1\", choices=[1, 2]) == 1\n    with pytest.raises(ConanException):\n        c.get(\"user.category:option2\", choices=[1, 2])\n\n\ndef test_conf_choices_default():\n    # Does not conflict with the default value\n    confs = textwrap.dedent(\"\"\"\n        user.category:option1=1\"\"\")\n    c = ConfDefinition()\n    c.loads(confs)\n    assert c.get(\"user.category:option1\", choices=[1, 2], default=7) == 1\n    assert c.get(\"user.category:option2\", choices=[1, 2], default=7) == 7\n\n\n@pytest.mark.parametrize(\"scope\", [\"\", \"pkg/1.0:\"])\n@pytest.mark.parametrize(\"conf\", [\n    \"user.foo:bar=1\",\n    \"user:bar=1\"\n])\ndef test_conf_scope_patterns_ok(scope, conf):\n    final_conf = scope + conf\n    c = ConfDefinition()\n    c.loads(final_conf)\n    # Check it doesn't raise\n    c.validate()\n\n\n@pytest.mark.parametrize(\"conf\", [\"user.foo.bar=1\"])\n@pytest.mark.parametrize(\"scope, assert_message\", [\n    (\"\", \"User conf 'user.foo.bar' invalid format, not 'user.org.group:conf'\"),\n    (\"pkg/1.0:\", \"'pkg/1.0:user.foo.bar' does not exist in configuration list\"),\n])\ndef test_conf_scope_patterns_bad(scope, conf, assert_message):\n    final_conf = scope + conf\n    c = ConfDefinition()\n    with pytest.raises(ConanException) as exc_info:\n        c.loads(final_conf)\n        c.validate()\n    assert assert_message in str(exc_info.value)\n\n\n@pytest.mark.parametrize(\"choices\", [None, [\"Foo\", \"Bar\"]])\ndef test_unset_basic_same_behaviour(choices):\n    c = ConfDefinition()\n    assert c.get(\"user.company.cpu:jobs\", choices=choices) is None\n\n    c2 = ConfDefinition()\n    c2.loads(\"user.company.cpu:jobs=!\")\n    assert c2.get(\"user.company.cpu:jobs\", choices=choices) is None\n\n    c3 = ConfDefinition()\n    c3.loads(\"user.company.cpu:jobs=4\")\n\n    c4 = ConfDefinition()\n    c4.loads(\"user.company.cpu:jobs=!\")\n    c3.update_conf_definition(c4)\n\n    assert c3.get(\"user.company.cpu:jobs\", choices=choices) is None\n"
  },
  {
    "path": "test/unittests/model/test_list.py",
    "content": "from conan.api.model import PackagesList\n\n\ndef test_package_list_only_recipes():\n    data = {\n        \"foobar/0.1.0\": {'revisions':\n                             {'85eb0587a3c12b90216c72070e9eef3e':\n                                  {'timestamp': 1740151190.975,\n                                   'packages': {'c29f32beda3c361f536ba35aae5e876faf970169':\n                                       {'revisions': {\n                                           '9a0569c04839fff6a6e8f40e10434bc6':\n                                               {'timestamp': 1742417567.684486}},\n                                           'info': {}}}}}},\n        \"qux/0.2.1\": {'revisions':\n                          {'71c3c11b98a6f2ae11f0f391f5e62e2b':\n                               {'timestamp': 1740151186.976, 'packages':\n                                   {'13be611585c95453f1cbbd053cea04b3e64470ca':\n                                        {'revisions': {'5c7e0c0788cd4d89249ad251f0868787':\n                                                           {'timestamp': 1740152032.884}},\n                                         'info':\n                                             {'settings':\n                                                  {'arch': 'x86_64',\n                                                   'build_type': 'Release',\n                                                   'compiler': 'gcc',\n                                                   'compiler.cppstd': '17',\n                                                   'compiler.libcxx': 'libstdc++11',\n                                                   'compiler.version': '11', 'os': 'Linux'},\n                                              'options': {'fPIC': 'True', 'shared': 'False'}}},\n                                    '30652ea35b512fa3fe0f4dcd39ad217e4e60bd01':\n                                        {'revisions': {'8f363f1d95ad766ac400e1f1f5406599':\n                                                           {'timestamp': 1741861639.2198145}},\n                                         'info': {}},\n                                    'fc491156b442836722612d1aa8a8c57e406447b6':\n                                        {'revisions': {'62e9e2659596c97cd1dd313d4394e947':\n                                                           {'timestamp': 1740151900.394}},\n                                         'info': {\n                                             'settings':\n                                                 {'arch': 'x86_64', 'build_type': 'Release',\n                                                  'compiler': 'gcc', 'compiler.cppstd': '17',\n                                                  'compiler.libcxx': 'libstdc++11',\n                                                  'compiler.version': '11', 'os': 'Linux'},\n                                             'options': {'shared': 'True'}}}}}}}\n    }\n    pl = PackagesList.deserialize(data)\n    pl.only_recipes()\n    assert pl.serialize() == {'foobar/0.1.0': {\n        'revisions': {'85eb0587a3c12b90216c72070e9eef3e': {'timestamp': 1740151190.975}}},\n                       'qux/0.2.1': {'revisions': {\n                           '71c3c11b98a6f2ae11f0f391f5e62e2b': {'timestamp': 1740151186.976}}}}\n"
  },
  {
    "path": "test/unittests/model/test_package_reference.py",
    "content": "from conan.api.model import PkgReference\n\n\ndef test_package_reference():\n    r = PkgReference.loads(\"pkg/0.1:pkgid1\")\n    assert r.ref.name == \"pkg\"\n    assert r.ref.version == \"0.1\"\n    assert r.ref.user is None\n    assert r.ref.channel is None\n    assert r.ref.revision is None\n    assert r.package_id == \"pkgid1\"\n    assert r.revision is None\n    assert str(r) == \"pkg/0.1:pkgid1\"\n    assert repr(r) == \"pkg/0.1:pkgid1\"\n\n    r = PkgReference.loads(\"pkg/0.1@user:pkgid1\")\n    assert r.ref.name == \"pkg\"\n    assert r.ref.version == \"0.1\"\n    assert r.ref.user == \"user\"\n    assert r.ref.channel is None\n    assert r.ref.revision is None\n    assert r.package_id == \"pkgid1\"\n    assert r.revision is None\n    assert str(r) == \"pkg/0.1@user:pkgid1\"\n    assert repr(r) == \"pkg/0.1@user:pkgid1\"\n"
  },
  {
    "path": "test/unittests/model/test_recipe_reference.py",
    "content": "import pytest\n\nfrom conan.errors import ConanException\nfrom conan.api.model import RecipeReference\n\n\ndef test_recipe_reference():\n    r = RecipeReference.loads(\"pkg/0.1\")\n    assert r.name == \"pkg\"\n    assert r.version == \"0.1\"\n    assert r.user is None\n    assert r.channel is None\n    assert r.revision is None\n    assert str(r) == \"pkg/0.1\"\n    assert repr(r) == \"pkg/0.1\"\n\n    r = RecipeReference.loads(\"pkg/0.1@\")\n    assert r.name == \"pkg\"\n    assert r.version == \"0.1\"\n    assert r.user is None\n    assert r.channel is None\n    assert r.revision is None\n    assert str(r) == \"pkg/0.1\"\n    assert repr(r) == \"pkg/0.1\"\n\n    r = RecipeReference.loads(\"pkg/0.1@user\")\n    assert r.name == \"pkg\"\n    assert r.version == \"0.1\"\n    assert r.user == \"user\"\n    assert r.channel is None\n    assert r.revision is None\n    assert str(r) == \"pkg/0.1@user\"\n    assert repr(r) == \"pkg/0.1@user\"\n\n\ndef test_recipe_reference_revisions():\n    r = RecipeReference.loads(\"pkg/0.1#r1\")\n    assert r.name == \"pkg\"\n    assert r.version == \"0.1\"\n    assert r.user is None\n    assert r.channel is None\n    assert r.revision == \"r1\"\n    assert str(r) == \"pkg/0.1\"\n    assert repr(r) == \"pkg/0.1#r1\"\n\n    r = RecipeReference.loads(\"pkg/0.1@user#r1\")\n    assert r.name == \"pkg\"\n    assert r.version == \"0.1\"\n    assert r.user == \"user\"\n    assert r.channel is None\n    assert r.revision == \"r1\"\n    assert str(r) == \"pkg/0.1@user\"\n    assert repr(r) == \"pkg/0.1@user#r1\"\n\n\ndef test_recipe_reference_timestamp():\n    r = RecipeReference.loads(\"pkg/0.1#r1%123\")\n    assert r.name == \"pkg\"\n    assert r.version == \"0.1\"\n    assert r.user is None\n    assert r.channel is None\n    assert r.revision == \"r1\"\n    assert str(r) == \"pkg/0.1\"\n    assert repr(r) == \"pkg/0.1#r1%123.0\"\n    # TODO: Improve the time format\n    assert r.repr_humantime() == \"pkg/0.1#r1 (1970-01-01 00:02:03 UTC)\"\n\n    r = RecipeReference.loads(\"pkg/0.1@user#r1%123\")\n    assert r.name == \"pkg\"\n    assert r.version == \"0.1\"\n    assert r.user == \"user\"\n    assert r.channel is None\n    assert r.revision == \"r1\"\n    assert str(r) == \"pkg/0.1@user\"\n    assert repr(r) == \"pkg/0.1@user#r1%123.0\"\n    assert r.repr_humantime() == \"pkg/0.1@user#r1 (1970-01-01 00:02:03 UTC)\"\n\n\ndef test_recipe_reference_compare():\n    r1 = RecipeReference.loads(\"pkg/1.3#1\")\n    r2 = RecipeReference.loads(\"pkg/1.22#2\")\n    assert r1 < r2\n    assert sorted([r2, r1]) == [r1, r2]\n\n\ndef test_error_pref():\n    r1 = RecipeReference.loads(\"pkg/1.0#rrev1:pid#rrev2\")\n    with pytest.raises(ConanException) as exc:\n        r1.validate_ref()\n    assert \"Invalid recipe reference 'pkg/1.0#rrev1:pid#rrev2' is a package reference\" in str(exc)\n\n    r1 = RecipeReference.loads(\"pkg/1.0:pid\")\n    with pytest.raises(ConanException) as exc:\n        r1.validate_ref()\n    assert \"Invalid recipe reference 'pkg/1.0:pid' is a package reference\" in str(exc)\n"
  },
  {
    "path": "test/unittests/model/version/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/model/version/test_version_bump.py",
    "content": "import pytest\n\nfrom conan.internal.model.version import Version\n\nvalues = [\n    ['1.0.0',       0, \"2.0.0\"],\n    ['1.1.0',       0, \"2.0.0\"],\n    ['1.1.1-pre',   0, \"2.0.0\"],\n    ['1.1.1',       1, \"1.2.0\"],\n    ['1.1.1',       2, \"1.1.2\"],\n]\n\n\n@pytest.mark.parametrize(\"version, index, result\", values)\ndef test_version_bump(version, index, result):\n    r = Version(version)\n    bumped = r.bump(index)\n    assert bumped == result\n"
  },
  {
    "path": "test/unittests/model/version/test_version_comparison.py",
    "content": "import pytest\n\nfrom conan.internal.model.version import Version\n\nd = [(\"1\", \"2\"),\n     (\"1.0\", \"1.1\"),\n     (\"1.0.2\", \"1.1.0\"),\n     (\"1.3\", \"1.22\"),\n     (\"1.1.3\", \"1.1.22\"),\n     (\"1.1.1.3\", \"1.1.1.22\"),\n     (\"1.1.1.1.3\", \"1.1.1.1.22\"),\n     # Different lengths\n     (\"1.0\", \"2\"),\n     (\"1.2\", \"1.3.1\"),\n     (\"1.0.2\", \"1.1\"),\n     (\"1.2.3\", \"1.11\"),\n     (\"1.2\", \"1.2.3\"),\n     (\"1.2.2.2\", \"1.2.3\"),\n     (\"1.2.3\", \"1.2.3.2\"),\n     (\"4\", \"4.0.1\"),\n     (\"4\", \"4.0.0.1\"),\n     # Now with letters\n     (\"1.1.a\", \"1.1.b\"),\n     (\"1.1.1.abc\", \"1.1.1.abz\"),\n     (\"a.b.c\", \"b.c\"),\n     (\"1.1\", \"1.a\"),\n     (\"1.1\", \"1.1a\"),\n     (\"1.1\", \"1.1.a\"),\n     (\"1.1.a\", \"1.2\"),\n     # Arterisk are before digits\n     (\"1.1*\", \"1.20\"),\n     (\"1.1.*\", \"1.20\"),\n     (\"1.2.2\", \"1.3.*\"),\n     (\"1.2.2\", \"1.2.3*\"),\n     # build is easy\n     (\"1.1+b1\", \"1.1+b2\"),\n     (\"1.1\", \"1.1+b2\"),\n     (\"1.1+b1\", \"1.2\"),\n     (\"1.1+b.3\", \"1.1+b.22\"),\n     # pre-release is challenging\n     (\"1.1-pre1\", \"1.1-pre2\"),\n     (\"1.1-alpha.3\", \"1.1-alpha.22\"),\n     (\"1.1-alpha.3+b1\", \"1.1-alpha.3+b2\"),\n     (\"1.1-alpha.1\", \"1.1\"),\n     (\"1.1\", \"1.2-alpha1\"),\n     (\"1.1-alpha.1\", \"1.1.0\"),  # pre to the generic 1.1 is earlier than 1.1.0\n     (\"1.0.0-\", \"1.0.0-alpha1\"),\n     (\"1.2-rc1\", \"1.2.0\"),\n     (\"1.1.9\", \"1.2-rc1\"),\n     # development versions\n     (\"1.2.1-dev\", \"1.2.1\"),\n     (\"1.2.1-dev\", \"1.2.2\"),\n     (\"1.2.1-dev\", \"1.3\"),\n     (\"1.2.1-dev\", \"1.3-alpha\"),\n     (\"1.2.0\", \"1.2.1-dev\"),\n     (\"1.2\", \"1.2.1-dev\"),\n     (\"1.2-alpha\", \"1.2.1-dev\"),\n     (\"0.0.1-3\", \"0.0.1\"),\n     (\"0.0.1-3-1\", \"0.0.1\"),\n     (\"0.0.1-3-1\", \"0.0.1-4\"),\n     (\"0.0.1-3\", \"0.0.1-3-1\"),  # 3 is less than 3-1, pure alphanumeric ID \"3-1\"\n     # build + prerelease\n     (\"1.1-pre.1\", \"1.1+b.1\"),\n     (\"1.1-pre.1\", \"1.1-pre.1+b.1\"),\n     (\"1.1-pre.1+b.1\", \"1.1-pre.1+b.2\"),\n     (\"1.1+b.1\", \"1.2-pre.1+b.2\"),\n     (\"1.0.0-+2\", \"1.0.0+2\"),  # Note it is not the number, but the prerelease\n     (\"1.0.0-+2\", \"1.0.0+1\"),  # Even if the build metadata is lower the first one is pre-release\n     # cci. schema used in CCI\n     (\"cci.20230101\", \"cci.20240101\"),\n     ]\n\n\n@pytest.mark.parametrize(\"v1, v2\", d)\ndef test_comparison(v1, v2):\n    v1 = Version(v1)\n    v2 = Version(v2)\n    assert v1 < v2\n    assert v2 > v1\n    assert v1 != v2\n    assert v1 <= v2\n    assert v2 >= v1\n\n\ndef test_build_metadata_is_not_equal():\n    # https://github.com/conan-io/conan/issues/5900\n    # Shouldn't be an \"official\" order for build metadata, but as they cannot be equal\n    # the order is alphabetic\n    assert Version(\"4.0.0+abc\") != Version(\"4.0.0+xyz\")\n    assert Version(\"4.0.0+xyz\") != Version(\"4.0.0+abc\")\n\n\ndef test_comparison_with_none():\n    assert Version(\"1.2.3\") > None\n\n\ndef test_comparison_with_integer():\n    v1 = Version(\"13.0\")\n    # Issue: https://github.com/conan-io/conan/issues/12907\n    assert v1 > 5\n    assert v1 >= 5\n    assert v1 < 20\n    assert v1 <= 20\n    assert v1 == 13\n    assert v1 != 14\n\n\ne = [(\"1\", \"1.0\"),\n     (\"1\", \"1.0.0\"),\n     (\"1.0\", \"1.0.0\"),\n     (\"1.0\", \"1.0.0.0\"),\n     (\"1-pre1\", \"1.0-pre1\"),\n     (\"1-pre1\", \"1.0.0-pre1\"),\n     (\"1.0-pre1\", \"1.0.0-pre1\"),\n     (\"1.0-pre1.0\", \"1.0.0-pre1\"),\n     (\"1-pre1+b1\", \"1.0-pre1+b1\"),\n     (\"1-pre1+b1\", \"1.0.0-pre1+b1\"),\n     (\"1.0-pre1+b1\", \"1.0.0-pre1+b1\"),\n     (\"1+b1\", \"1.0+b1\"),\n     (\"1+b1\", \"1.0+b1.0\"),\n     (\"1+b1\", \"1.0.0+b1\"),\n     (\"1.0+b1\", \"1.0.0+b1\"),\n     (\"1.2.3\", \"1.2.3\"),\n     ]\n\n\n@pytest.mark.parametrize(\"v1, v2\", e)\ndef test_equality(v1, v2):\n    v1 = Version(v1)\n    v2 = Version(v2)\n    assert v1 == v2\n    assert not v1 != v2\n    assert not v1 < v2\n    assert not v2 < v1\n    assert v1 <= v2\n    assert v2 <= v1\n\n\ndef test_elem_comparison():\n    v1 = Version(\"1.2.3b.4-pre.1.2b+build.1.1b\")\n    major = v1.major\n    assert major < 2\n    assert major < \"2\"\n    assert major == 1\n    assert major != 3\n    assert major > 0\n    assert str(major) == \"1\"\n    patch = v1.patch\n    assert patch < 4\n    assert patch > 2\n    assert patch < \"3c\"\n    assert patch > \"3a\"\n    assert patch == \"3b\"\n    micro = v1.micro\n    assert micro > 3\n    assert micro < 5\n    assert micro == 4\n\n\ndef test_version_in_range():\n    v = Version(\"1.0\")\n    assert not v.in_range(\">1.0 <2\")\n    assert v.in_range(\">=1.0 <2\")\n\n    assert not Version(\"1.0-rc\").in_range(\">=1.0 <2.0\")\n    assert Version(\"1.0-rc\").in_range(\">=1.0 <2.0\", resolve_prerelease=True)\n"
  },
  {
    "path": "test/unittests/model/version/test_version_parse.py",
    "content": "import pytest\n\nfrom conan.internal.model.version import Version\n\nv = [(\"1.2.3\",\n      (1, 2, 3), None, None),\n     (\"1.2.3\",\n      ('1', '2', '3'), None, None),\n     (\"master+build2\",\n      'master', None, \"build2\"),\n     (\"1.2.3-alpha1+build2\",\n      (1, 2, 3), \"alpha1\", \"build2\"),\n     (\"1.2.3+build2\",\n      (1, 2, 3), None, \"build2\"),\n     (\"1.2.3b.4-pre.1.2b+build.1.1b\",\n      (1, 2, \"3b\", 4), \"pre.1.2b\", \"build.1.1b\"),\n     (\"0.2.3+b178\",\n      (0, 2, 3), None, \"b178\"),\n     (\"1.2.3.4.5\",\n      (1, 2, 3, 4, 5), None, None),\n     (9,\n      9, None, None),\n     (1.2,\n      (1, 2), None, None),\n     (\"\",\n      '', None, None),\n     (\"+build2\",\n      '', None, \"build2\"),\n     (\"1.2.3-pre.4-5-6+build.7-8-9\",\n      \"1.2.3\", \"pre.4-5-6\", \"build.7-8-9\"),\n     (\"1-\", \"1\", \"\", None)\n     ]\n\n\n@pytest.mark.parametrize(\"v_str, main, pre, build\", v)\ndef test_parse(v_str, main, pre, build):\n    v1 = Version(v_str)\n    assert v1.main == main if type(main) is tuple else tuple([main])\n    assert v1.pre == pre\n    assert v1.build == build\n    assert str(v1) == str(v_str)\n"
  },
  {
    "path": "test/unittests/model/version/test_version_range.py",
    "content": "import textwrap\n\nimport pytest\n\nfrom conan.errors import ConanException\nfrom conan.internal.model.version import Version\nfrom conan.internal.model.version_range import VersionRange\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.tools import TestClient\n\nvalues = [\n    ['=1.0.0',  [[['=', '1.0.0']]],                   [\"1.0.0\"],          [\"0.1\"]],\n    ['>1.0.0',  [[['>', '1.0.0']]],                   [\"1.0.1\"],          [\"0.1\"]],\n    ['<2.0',    [[['<', '2.0-']]],                     [\"1.0.1\"],          [\"2.1\"]],\n    ['>1 <2.0', [[['>', '1'], ['<', '2.0-']]],         [\"1.5.1\"],          [\"0.1\", \"2.1\"]],\n    # tilde\n    ['~2.5',    [[['>=', '2.5-'], ['<', '2.6-']]],      [\"2.5.0\", \"2.5.3\"], [\"2.7\", \"2.6.1\"]],\n    ['~2.5.1',  [[['>=', '2.5.1-'], ['<', '2.6.0-']]],  [\"2.5.1\", \"2.5.3\"], [\"2.5\", \"2.6.1\"]],\n    ['~2.5.1.3',  [[['>=', '2.5.1.3-'], ['<', '2.6.0-']]], [\"2.5.1.4\", \"2.5.3\"], [\"2.5.1\", \"2.6.1\"]],\n    ['~1',      [[['>=', '1-'], ['<', '2-']]],          [\"1.3\", \"1.8.1\"],   [\"0.8\", \"2.2\"]],\n    # caret\n    ['^1.2',    [[['>=', '1.2-'], ['<', '2.0-']]],      [\"1.2.1\", \"1.51\"],  [\"1\", \"2\", \"2.0.1\"]],\n    ['^1.2.3',\t[[['>=', '1.2.3-'], [\"<\", '2.0.0-']]],  [\"1.2.3\", \"1.2.4\"], [\"2\", \"2.1\", \"2.0.1\"]],\n    ['^0.1.2',  [[['>=', '0.1.2-'], ['<', '0.2.0-']]],  [\"0.1.3\", \"0.1.44\"], [\"1\", \"0.3\", \"0.2.1\"]],\n    # Identity\n    ['1.0.0',   [[[\"=\", \"1.0.0\"]]],                   [\"1.0.0\"],          [\"2\", \"1.0.1\"]],\n    ['=1.0.0',  [[[\"=\", \"1.0.0\"]]],                   [\"1.0.0\"],          [\"2\", \"1.0.1\"]],\n    # Any\n    ['*',       [[[\">=\", \"0.0.0-\"]]],                  [\"1.0\", \"a.b\"],          []],\n    ['',        [[[\">=\", \"0.0.0-\"]]],                  [\"1.0\", \"a.b\"],          []],\n    # Patterns\n    ['1.2.3.*',       [[[\"*\", \"1.2.3.\"]]],   [\"1.2.3.1\", \"1.2.3.A\"], [\"1.2.3\", \"1.2.31\", \"1.2.4\"]],\n    ['1.2.3+4.5.*',      [[[\"*\", \"1.2.3+4.5.\"]]],   [\"1.2.3+4.5.6\"], [\"1.2.3+4.7\"]],\n    # Unions\n    ['1.0.0 || 2.1.3',  [[[\"=\", \"1.0.0\"]], [[\"=\", \"2.1.3\"]]],  [\"1.0.0\", \"2.1.3\"],  [\"2\", \"1.0.1\"]],\n    ['>1 <2.0 || ^3.2 ',  [[['>', '1'], ['<', '2.0-']],\n                           [['>=', '3.2-'], ['<', '4.0-']]],   [\"1.5\", \"3.3\"],  [\"2.1\", \"0.1\", \"5\"]],\n    # pre-releases\n    ['',                             [[[\">=\", \"0.0.0-\"]]],    [\"1.0\"],                [\"1.0-pre.1\"]],\n    ['*, include_prerelease=True',   [[[\">=\", \"0.0.0-\"]]],    [\"1.0\", \"1.0-pre.1\", \"0.0.0\", \"0.0.0-pre.1\"],   []],\n    [', include_prerelease=True',   [[[\">=\", \"0.0.0-\"]]],    [\"1.0\", \"1.0-pre.1\", \"0.0.0\", \"0.0.0-pre.1\"],   []],\n    ['>1- <2.0',                     [[['>', '1-'], ['<', '2.0-']]],\n                                     [\"1.0\", \"1.1\", \"1.9\"],   [\"1-pre.1\", \"1.5.1-pre1\", \"2.1-pre1\"]],\n    ['>1- <2.0 || ^3.2 ',  [[['>', '1-'], ['<', '2.0-']], [['>=', '3.2-'], ['<', '4.0-']]],\n                           [\"1.0\", \"1.2\", \"3.3\"],  [\"1-pre.1\", \"1.5-a1\", \"3.3-a1\"]],\n    ['^1.1.2',  [[['>=', '1.1.2-'], ['<', '2.0.0-']]], [\"1.2.3\"],  [\"1.2.0-alpha1\", \"2.0.0-alpha1\"]],\n    ['^1.0.0, include_prerelease=True',  [[['>=', '1.0.0-'], ['<', '2.0.0-']]], [\"1.2.3\", \"1.2.0-alpha1\"],  [\"2.0.0-alpha1\"]],\n    ['~1.1.2',  [[['>=', '1.1.2-'], ['<', '1.2.0-']]], [\"1.1.3\"],  [\"1.1.3-alpha1\", \"1.2.0-alpha1\"]],\n    ['>=2.0-pre.0 <3', [[['>=', '2.0-pre.0'], ['<', '3-']]], [\"2.1\"], [\"2.0-pre.1\", \"2.0-alpha.1\"]],\n    # Build metadata\n    ['>=1.0.0+2', [[['>=', '1.0.0+2']]], [\"1.0.0+2\", \"1.0.0+3\"], [\"1.0.0+1\"]],\n    ['>=1.0.0', [[['>=', '1.0.0-']]], [\"1.0.0+2\", \"1.0.0+3\"], []],\n    # Build metadata and pre-releases\n    ['>=1.0.0-pre.1+2', [[['>=', '1.0.0-pre.1+2']]], [\"1.0.0+1\", \"1.0.0+2\"], [\"1.0.0-pre.1+3\"]],  # excluded 1+3 because is a pre-release!\n    ['>=1.0.0-pre.1+2, include_prerelease=True', [[['>=', '1.0.0-pre.1+2']]], [\"1.0.0+1\", \"1.0.0+2\", \"1.0.0-pre.1+3\"], [\"1.0.0-pre.1+1\"]],\n    ['<1.0.1-pre.1+2', [[['<', '1.0.1-pre.1+2']]], [\"1.0.0+1\", \"1.0.0+2\"], [\"1.0.0-pre.1+2\"]],\n    ['<1.0.1-pre.1+2, include_prerelease=True', [[['<', '1.0.1-pre.1+2']]], [\"1.0.0+1\", \"1.0.0+2\", \"1.0.1-pre.1+1\"], [\"1.0.1-pre.1+2\"]],\n    # Or explicitly\n    ['>=2.0-pre.0, include_prerelease', [[['>=', '2.0-pre.0']]], [\"2.1\", \"2.0-pre.1\"], [\"1.5\"]],\n    # Build metadata\n    ['>=1.0.0+2', [[['>=', '1.0.0+2']]], [\"1.0.0+2\", \"1.0.0+3\"], [\"1.0.0+1\"]],\n    ['>=2.2.0+build.en.305 <2.2.0+build.en.306', [[['>=', '2.2.0+build.en.305'], ['<', '2.2.0+build.en.306']]],\n                                                 [\"2.2.0+build.en.305\", \"2.2.0+build.en.305.1\", \"2.2.0+build.en.305.2\"], [\"2.2.0+build.en.306\"]]\n]\n\n\n@pytest.mark.parametrize(\"version_range, conditions, versions_in, versions_out\", values)\ndef test_range(version_range, conditions, versions_in, versions_out):\n    r = VersionRange(version_range)\n    assert len(r.condition_sets) == len(conditions), \\\n        f\"Expected {r} to have {len(conditions)} condition sets, but got {len(r.condition_sets)}\"\n    for condition_set, expected_condition_set in zip(r.condition_sets, conditions):\n        assert len(condition_set.conditions) == len(expected_condition_set), \\\n            f\"Expected {r} to have {len(expected_condition_set)} conditions, but got {len(condition_set.conditions)}\"\n        for condition, expected_condition in zip(condition_set.conditions, expected_condition_set):\n            assert condition.operator == expected_condition[0], f\"Expected {r} condition operator to be {expected_condition[0]}, but got {condition.operator}\"\n            assert condition.version == expected_condition[1], f\"Expected {r} condition version to be {expected_condition[1]}, but got {condition.version}\"\n\n    for v in versions_in:\n        assert r.contains(Version(v), None), f\"[{r}] must contain {v}\"\n\n    for v in versions_out:\n        assert not r.contains(Version(v), None), f\"[{r}] must not contain {v}\"\n\n\n@pytest.mark.parametrize(\"version_range, resolve_prereleases, versions_in, versions_out\", [\n    ['*', True, [\"1.5.1\", \"1.5.1-pre1\", \"2.1-pre1\"], []],\n    ['*', False, [\"1.5.1\"], [\"1.5.1-pre1\", \"2.1-pre1\"]],\n    ['*', None, [\"1.5.1\"], [\"1.5.1-pre1\", \"2.1-pre1\"]],\n\n    ['*, include_prerelease', True, [\"1.5.1\", \"1.5.1-pre1\", \"2.1-pre1\"], []],\n    ['*, include_prerelease', False, [\"1.5.1\"], [\"1.5.1-pre1\", \"2.1-pre1\"]],\n    ['*, include_prerelease', None, [\"1.5.1\", \"1.5.1-pre1\", \"2.1-pre1\"], []],\n\n    [', include_prerelease', True, [\"1.5.1\", \"1.5.1-pre1\", \"2.1-pre1\"], []],\n    [', include_prerelease', False, [\"1.5.1\"], [\"1.5.1-pre1\", \"2.1-pre1\"]],\n    [', include_prerelease', None, [\"1.5.1\", \"1.5.1-pre1\", \"2.1-pre1\"], []],\n\n    ['>1 <2.0', True, [\"1.5.1\", \"1.5.1-pre1\"], [\"1.0-pre.1\", \"2.1-pre1\"]],\n    ['>1 <2.0', False, [\"1.5.1\"], [\"1.5.1-pre1\", \"2.1-pre1\"]],\n    ['>1 <2.0', None, [\"1.5.1\"], [\"1.5.1-pre1\", \"2.1-pre1\"]],\n\n    ['>1- <2.0', True, [\"1.5.1\", \"1.5.1-pre1\"], [\"2.1-pre1\"]],\n    ['>1- <2.0', False, [\"1.5.1\"], [\"1.5.1-pre1\", \"2.1-pre1\"]],\n    ['>1- <2.0, include_prerelease', None, [\"1.5.1\", \"1.5.1-pre1\"], [\"2.1-pre1\"]],\n\n    ['>1 <2.0, include_prerelease', True, [\"1.5.1\", \"1.5.1-pre1\"], [\"1.0-pre.1\", \"2.1-pre1\"]],\n    ['>1 <2.0, include_prerelease', False, [\"1.5.1\"], [\"1.5.1-pre1\", \"2.1-pre1\"]],\n    ['>1 <2.0, include_prerelease', None, [\"1.5.1\", \"1.5.1-pre1\"], [\"2.1-pre1\"]],\n\n    # Limits\n    ['>=2.1.0-beta', False, [\"2.1.0\"], [\"2.1.0-beta\", \"2.1.0-alpha\"]],\n    ['>=2.1.0-beta', True, [\"2.1.0-beta\", \"2.1.0-gamma\"], [\"2.1.0-alpha\"]],\n\n    # Summary of new behaviors\n    ['>=1 <2.0', False, [\"1.0\", \"1.1\", \"1.9\"], [\"0.9\", \"1.0-pre.1\", \"1.1-pre.1\", \"2.0-pre\", \"2.0\"]],\n    # OLD\n    # ['>=1 <2.0', True, [\"1.0\", \"1.1-pre.1\", \"1.1\", \"1.9\", \"2.0-pre\"], [\"0.9\", \"1.0-pre.1\", \"2.0\"]],\n    # NEW\n    ['>=1 <2.0', True, [\"1.0-pre.1\", \"1.0\", \"1.1-pre.1\", \"1.1\", \"1.9\"], [\"0.9\", \"2.0\", \"2.0-pre\"]],\n    ['>1 <=2.0', False, [\"1.1\", \"1.9\", \"2.0\"], [\"0.9\", \"1.0-pre.1\", \"1.0\", \"1.1-pre.1\", \"2.0-pre\"]],\n    # This should be old and new behaviors remain the same\n    ['>1 <=2.0', True, [\"1.1-pre.1\", \"1.1\", \"1.9\", \"2.0\", \"2.0-pre\"], [\"0.9\", \"1.0\", \"1.0-pre.1\"]],\n\n    # Codified quirks\n    ['', False, [\"1.0\", \"2.0\"], [\"1.0-pre.1\", \"2.0-pre.1\"]],\n    ['', True, [\"1.0\", \"2.0\", \"1.0-pre.1\", \"2.0-pre.1\"], []],\n])\ndef test_range_prereleases_conf(version_range, resolve_prereleases, versions_in, versions_out):\n    r = VersionRange(version_range)\n\n    for v in versions_in:\n        assert r.contains(Version(v), resolve_prereleases), f\"Expected '{version_range}' to contain '{v}' (conf.ranges_resolve_prereleases={resolve_prereleases})\"\n\n    for v in versions_out:\n        assert not r.contains(Version(v), resolve_prereleases), f\"Expected '{version_range}' NOT to contain '{v}' (conf.ranges_resolve_prereleases={resolve_prereleases})\"\n\n\n@pytest.mark.parametrize(\"version_range\", [\n    \">= 1.0\",  # https://github.com/conan-io/conan/issues/12692\n    \">=0.0.1 < 1.0\",  # https://github.com/conan-io/conan/issues/14612\n    \"==1.0\",  \"~=1.0\",  \"^=1.0\", \"v=1.0\"  # https://github.com/conan-io/conan/issues/16066\n])\ndef test_wrong_range_syntax(version_range):\n    with pytest.raises(ConanException):\n        VersionRange(version_range)\n\n\n@pytest.mark.parametrize(\"version_range\", [\n    \">=0.1, include_prerelease\",\n    \">=0.1, include_prerelease=True\",\n    \">=0.1, include_prerelease=False\",\n])\ndef test_wrong_range_option_syntax(version_range):\n    \"\"\"We don't error out on bad options, maybe we should,\n    but for now this test ensures we don't change it without realizing\"\"\"\n    vr = VersionRange(version_range)\n    assert all(cs.prerelease for cs in vr.condition_sets)\n\n\ndef test_version_range_error_ux():\n    # https://github.com/conan-io/conan/issues/16288\n    c = TestClient()\n    conanfile = textwrap.dedent(\"\"\"\n        from conan import ConanFile\n        class Pkg(ConanFile):\n            requires = \"mydep/[>1.0 < 3]\"\n        \"\"\")\n    c.save({\"conanfile.py\": conanfile})\n    c.run(\"install .\", assert_error=True)\n    assert \"Recipe 'conanfile' requires 'mydep/[>1.0 < 3]' version-range definition error\" in c.out\n    c.run(\"export . --name=mypkg --version=0.1\")\n    c.run(\"install --requires=mypkg/0.1\", assert_error=True)\n    assert \"Recipe 'mypkg/0.1' requires 'mydep/[>1.0 < 3]' version-range definition error\" in c.out\n\n\ndef test_version_range_with_pinned_revision_warn():\n    tc = TestClient()\n    tc.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\")})\n    tc.run(\"export .\")\n    rrev1 = tc.exported_recipe_revision()\n    tc.save({\"conanfile.py\": GenConanfile(\"pkg\", \"1.0\").with_class_attribute(\"# a comment\")})\n    tc.run(\"export .\")\n    rrev2 = tc.exported_recipe_revision()\n    assert rrev1 != rrev2\n\n    tc.run(f\"install --requires=pkg/[>=1.0]#{rrev1} --build=missing -vv\")\n    assert f\"WARN: risk: Specifying a revision for requirement 'pkg/[>=1.0]#{rrev1}' together with a version range has no effect\" in tc.out\n    # Note, rrev2 instead of the requested rrev1\n    assert f\"pkg/1.0#{rrev2} - Cache\" in tc.out\n"
  },
  {
    "path": "test/unittests/model/version/test_version_range_intersection.py",
    "content": "import pytest\n\nfrom conan.internal.model.version_range import VersionRange\n\nvalues = [\n    # empty / any ranges\n    ['', \"\", \">=0.0.0\"],\n    ['*', \"*\", \">=0.0.0\"],\n    # single lower limits bounds\n    ['>1.0', \">1.0\", \">1.0\"],\n    ['>=1.0', \">1.0\", \">1.0\"],\n    ['>1.0', \">1.1\", \">1.1\"],\n    ['>1.0', \">=1.1\", \">=1.1\"],\n    ['>=1.0', \">=1.1\", \">=1.1\"],\n    ['', \">1.0\", \">1.0\"],\n    ['>1.0', \"\", \">1.0\"],\n    # single upper limits bounds\n    ['<2.0', \"<2.0\", \"<2.0\"],\n    ['<=1.0', \"<1.0\", \"<1.0\"],\n    ['<2.0', \"<2.1\", \"<2.0\"],\n    ['<2.0', \"<=1.1\", \"<=1.1\"],\n    ['<=1.0', \"<=1.1\", \"<=1.0\"],\n    ['', \"<2.0\", \">=0.0.0 <2.0\"],\n    ['<2.0', \"\", \">=0.0.0 <2.0\"],\n    # One lower limit, one upper\n    ['>=1.0', \"<2.0\", \">=1.0 <2.0\"],\n    ['>=1', '<=1', \">=1 <=1\"],\n    [\">=1\", \"<=1-\", \">=1 <=1-\"],\n    [\">=1-\", \"<=1\", \">=1- <=1\"],\n    # Two lower, one upper\n    ['>=1.0', \">1.0 <2.0\", \">1.0 <2.0\"],\n    ['>=1.0', \">1.1 <2.0\", \">1.1 <2.0\"],\n    ['>1.0', \">1.1 <=2.0\", \">1.1 <=2.0\"],\n    ['>1.0', \">=1.1 <=2.0\", \">=1.1 <=2.0\"],\n    # one lower, two upper\n    ['<3.0', \">1.0 <2.0\", \">1.0 <2.0\"],\n    ['<=2.0', \">1.1 <2.0\", \">1.1 <2.0\"],\n    ['<1.9', \">1.1 <=2.0\", \">1.1 <1.9\"],\n    ['<=1.9', \">=1.1 <=2.0\", \">=1.1 <=1.9\"],\n    # two lower, two upper\n    ['>0.1 <3.0', \">1.0 <2.0\", \">1.0 <2.0\"],\n    ['>1.2 <=2.0', \">1.1 <2.0\", \">1.2 <2.0\"],\n    ['>0.1 <1.9', \">1.1 <=2.0\", \">1.1 <1.9\"],\n    ['>=1.3 <=1.9', \">=1.1 <=2.0\", \">=1.3 <=1.9\"],\n    ['>=1.0 <=5.0', \">2 <2.5\", \">2 <2.5\"],\n    # equal limits\n    ['>=1.0 <3.0', \">0.0 <=1.0\", \">=1.0 <=1.0\"],\n    # prereleases\n    ['>1.0', \">1.0-\", \">1.0\"],\n    ['>=1.0- <3.0', \">=1.0 <3.0-\", \">=1.0 <3.0-\"],\n    ['>=1.0 <=3.0-', \"<3\", \">=1.0 <3\"],\n    # OR\n    ['>=1.0 <2.0 || >=2.1 <3', \">=2.3\", \">=2.3 <3\"],\n    ['>=1.3 <=1.9 || >2.1', \">=1.1 <=2.0 || >=2.1 <2.6\", \">=1.3 <=1.9 || >2.1 <2.6\"],\n    ['>=1.3 <=1.9 || >=2.2', \">=1.8- <2.3 || >=2.1 <2.6\", \">=1.8- <=1.9 || >=2.2 <2.3 || >=2.2 <2.6\"],\n]\n\n\n@pytest.mark.parametrize(\"range1, range2, result\", values)\ndef test_range_intersection(range1, range2, result):\n    r1 = VersionRange(range1)\n    r2 = VersionRange(range2)\n    inter = r1.intersection(r2)\n    result = f\"[{result}]\"\n    assert inter.version() == result\n    inter = r2.intersection(r1)  # Test reverse order, result should be the same\n    assert inter.version() == result\n\n\nincompatible_values = [\n    ['>1.0', \"<1.0\"],\n    ['>=1.0', \"<1.0\"],\n    ['>1.0', \"<=1.0\"],\n    ['>1.0 <2.0', \">2.0\"],\n    ['>1.0 <2.0', \"<1.0\"],\n    ['>1.0 <2.0', \">3.0 <4.0\"],\n    ['<1.0', \">3.0 <4.0\"],\n    ['>=1.0 <2 || >2 <3', \">4 <5\"]\n]\n\n\n@pytest.mark.parametrize(\"range1, range2\", incompatible_values)\ndef test_range_intersection_incompatible(range1, range2):\n    r1 = VersionRange(range1)\n    r2 = VersionRange(range2)\n    inter = r1.intersection(r2)\n    assert inter is None\n    inter = r2.intersection(r1)  # Test reverse order, result should be the same\n    assert inter is None\n\n\nprerelease_values = [\n    [\", include_prerelease\",\n     \">=1.0-pre.1 <1.0-pre.99, include_prerelease\",\n     \">=1.0-pre.1 <1.0-pre.99, include_prerelease\"],\n    [\">=1.0-pre.1 <1.0-pre.99, include_prerelease\",\n     \">=1.0-pre.1 <1.0-pre.99, include_prerelease\",\n     \">=1.0-pre.1 <1.0-pre.99, include_prerelease\"],\n    [\">=1.0-pre.1 <1.0-pre.99, include_prerelease\",\n     \">=1.0-pre.12 <1.0-pre.98, include_prerelease\",\n     \">=1.0-pre.12 <1.0-pre.98, include_prerelease\"],\n    [\">=1.0-pre.12 <1.0-pre.99, include_prerelease\",\n     \">=1.0-pre.1 <1.0-pre.98, include_prerelease\",\n     \">=1.0-pre.12 <1.0-pre.98, include_prerelease\"],\n    [\">=1.0-pre.1 <1.0-pre.99\",\n     \">=1.0-pre.1 <1.0-pre.99, include_prerelease\",\n     \">=1.0-pre.1 <1.0-pre.99\"],\n    [\">=1.0-pre.1 <1.0-pre.99, include_prerelease\",\n     \">=1.0-pre.12 <1.0-pre.98\",\n     \">=1.0-pre.12 <1.0-pre.98\"],\n    [\">=1.0-pre.12 <1.0-pre.99\",\n     \">=1.0-pre.1 <1.0-pre.98\",\n     \">=1.0-pre.12 <1.0-pre.98\"]\n]\n\n\n@pytest.mark.parametrize(\"range1, range2, result\", prerelease_values)\ndef test_range_intersection_prerelease(range1, range2, result):\n    r1 = VersionRange(range1)\n    r2 = VersionRange(range2)\n    inter = r1.intersection(r2)\n    assert str(inter.version()) == f'[{result}]'\n    inter = r2.intersection(r1)  # Test reverse order, result should be the same\n    assert str(inter.version()) == f'[{result}]'\n"
  },
  {
    "path": "test/unittests/model/versionrepr_test.py",
    "content": "from conan.internal.model.info import _VersionRepr\nfrom conan.internal.model.version import Version\n\n\nclass TestVersionRepr:\n\n    def test_text(self):\n        v1 = Version(\"master+build2\")\n        vr = _VersionRepr(v1)\n        assert vr.major() == \"master\"\n        assert vr.minor() == \"master\"\n        assert vr.patch() == \"master\"\n        assert vr.pre() == \"master\"\n        assert vr.build == \"build2\"\n        assert vr.stable() == \"master\"\n\n    def test_patch(self):\n        v1 = Version(\"1.2.3-alpha1+build2\")\n        vr = _VersionRepr(v1)\n        assert vr.major() == \"1.Y.Z\"\n        assert vr.minor() == \"1.2.Z\"\n        assert vr.patch() == \"1.2.3\"\n        assert vr.pre() == \"1.2.3-alpha1\"\n        assert vr.build == \"build2\"\n        assert vr.stable() == \"1.Y.Z\"\n\n        v1 = Version(\"1.2.3+build2\")\n        vr = _VersionRepr(v1)\n        assert vr.major() == \"1.Y.Z\"\n        assert vr.minor() == \"1.2.Z\"\n        assert vr.patch() == \"1.2.3\"\n        assert vr.pre() == \"1.2.3\"\n        assert vr.build == \"build2\"\n        assert vr.stable() == \"1.Y.Z\"\n\n        v1 = Version(\"0.2.3-alpha1+build2\")\n        vr = _VersionRepr(v1)\n        assert vr.major() == \"0.Y.Z\"\n        assert vr.minor() == \"0.2.Z\"\n        assert vr.patch() == \"0.2.3\"\n        assert vr.pre() == \"0.2.3-alpha1\"\n        assert vr.build == \"build2\"\n        assert vr.stable() == \"0.2.3-alpha1+build2\"\n\n        v1 = Version(\"+build2\")\n        vr = _VersionRepr(v1)\n        assert vr.major() == \"\"\n\n    def test_build(self):\n        v1 = Version(\"0.2.3-alpha1+build2\")\n        vr = _VersionRepr(v1)\n        assert vr.build == \"build2\"\n        v2 = Version(\"0.2.3+b178\")\n        vr = _VersionRepr(v2)\n        assert vr.build == \"b178\"\n"
  },
  {
    "path": "test/unittests/paths/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/paths/user_home_test.py",
    "content": "import os\nfrom pathlib import Path\n\nfrom conan.internal.paths import get_conan_user_home, find_file_walk_up\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.internal.util.files import chdir\n\n\nclass TestConanUserHome:\n    def test_conanrc_abs_path_get_conan_user_home(self):\n        _temp_folder = temp_folder(path_with_spaces=True)\n        folder_conan_runs = os.path.join(_temp_folder, \"folder_where_conan_runs\")\n        os.mkdir(folder_conan_runs)\n        with open(os.path.join(_temp_folder, \".conanrc\"), 'w+') as file:\n            file.write(f'conan_home={_temp_folder}\\n')\n        with chdir(folder_conan_runs):\n            conan_home = get_conan_user_home()\n            assert _temp_folder == conan_home\n\n\n    def test_conanrc_local_path_get_conan_user_home(self):\n        _temp_folder = temp_folder(path_with_spaces=True)\n        subfolder = \"subfolder inside temp\"\n        with chdir(_temp_folder):\n            with open(os.path.join(_temp_folder, \".conanrc\"), 'w+') as file:\n                file.write(f'conan_home=.{os.sep}{subfolder}\\n')\n            conan_home = get_conan_user_home()\n            assert str(os.path.join(_temp_folder, subfolder)) == conan_home\n\n\n    def test_conanrc_local_path_run_conan_subfolder_get_conan_user_home(self):\n        _temp_folder = temp_folder(path_with_spaces=True)\n        folder_conan_runs = os.path.join(_temp_folder, \"folder_where_conan_runs\")\n        os.mkdir(folder_conan_runs)\n        with open(os.path.join(_temp_folder, \".conanrc\"), 'w+') as file:\n            file.write(f'conan_home=.{os.sep}\\n')\n        with chdir(folder_conan_runs):\n            conan_home = get_conan_user_home()\n            assert str(os.path.join(_temp_folder)) == conan_home\n\n\n    def test_conanrc_local_outside_folder_path_get_conan_user_home(self):\n        _temp_folder = temp_folder(path_with_spaces=True)\n        folder1 = os.path.join(_temp_folder, \"folder1\")\n        os.mkdir(folder1)\n        with chdir(folder1):\n            with open(os.path.join(folder1, \".conanrc\"), 'w+') as file:\n                file.write(f'conan_home=..{os.sep}folder2\\n')\n            conan_home = get_conan_user_home()\n            this_path = Path(_temp_folder) / \"folder1\" / f\"..{os.sep}folder2\"\n            assert str(this_path) == str(conan_home)\n\n\n    def test_conanrc_comments(self):\n        _temp_folder = temp_folder(path_with_spaces=True)\n        with chdir(_temp_folder):\n            with open(os.path.join(_temp_folder, \".conanrc\"), 'w+') as file:\n                file.write(f'#commenting something\\nconan_home={_temp_folder}\\n')\n            conan_home = get_conan_user_home()\n            assert _temp_folder == conan_home\n\n\n    def test_conanrc_wrong_format(self):\n        _temp_folder = temp_folder(path_with_spaces=True)\n        with chdir(_temp_folder):\n            with open(os.path.join(_temp_folder, \".conanrc\"), 'w+') as file:\n                file.write(f'ronan_jome={_temp_folder}\\n')\n            conan_home = get_conan_user_home()\n            assert _temp_folder not in conan_home\n\n\n    def test_conanrc_not_existing(self):\n        _temp_folder = temp_folder(path_with_spaces=True)\n        with chdir(_temp_folder):\n            conan_home = get_conan_user_home()\n            assert _temp_folder not in conan_home\n\n\nclass TestFindWalkFileUp:\n    def test_find_file_walk_up(self):\n        _temp_folder = temp_folder(path_with_spaces=True)\n        leaf = os.path.join(_temp_folder, \"one\", \"two\", \"three\")\n        os.makedirs(leaf)\n        file_name = \"test.txt\"\n        file_path = os.path.join(leaf, file_name)\n        with open(file_path, 'w+') as file:\n            file.write(\"test\")\n        found_file = find_file_walk_up(leaf, file_name)\n        assert str(found_file) == file_path\n\n    def test_find_file_walk_up_no_file_end(self):\n        _temp_folder = temp_folder(path_with_spaces=True)\n        leaf = os.path.join(_temp_folder, \"one\", \"two\", \"three\")\n        os.makedirs(leaf)\n        file_name = \"test.txt\"\n        file_path = os.path.join(_temp_folder, file_name)\n        with open(file_path, 'w+') as file:\n            file.write(\"test\")\n        # We stop searching in \"one\", so we don't find the file one level above\n        found_file = find_file_walk_up(leaf, file_name, end=os.path.join(_temp_folder, \"one\"))\n        assert found_file is None\n\n    def test_find_file_walk_up_no_file_no_end(self):\n        _temp_folder = temp_folder(path_with_spaces=True)\n        leaf = os.path.join(_temp_folder, \"one\", \"two\", \"three\")\n        os.makedirs(leaf)\n        file_name = \"test.txt\"\n        found_file = find_file_walk_up(leaf, file_name)\n        assert found_file is None\n\n    def test_find_file_walk_up_no_file_end_outside_leaf(self):\n        _temp_folder = temp_folder(path_with_spaces=True)\n        leaf = os.path.join(_temp_folder, \"one\", \"two\", \"three\")\n        os.makedirs(leaf)\n        file_name = \"test.txt\"\n        _second_temp_folder = temp_folder(path_with_spaces=True)\n\n        found_file = find_file_walk_up(leaf, file_name, end=_second_temp_folder)\n        assert found_file is None\n"
  },
  {
    "path": "test/unittests/search/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/search/cache_db_search_test.py",
    "content": "class CacheDbSearchTest:\n    # TODO: cache2.0 add some unittests for serach in cache db\n    pass\n"
  },
  {
    "path": "test/unittests/search/search_query_parse_test.py",
    "content": "\nfrom conan.internal.api.list.query_parse import _evaluate_postfix, _infix_to_postfix\n\n\nclass TestQueryParse:\n\n    def test_get_postfix(self):\n        r = _infix_to_postfix(\"\")\n        assert r == []\n\n        r = _infix_to_postfix(\"a=2\")\n        assert r == [\"a=2\"]\n\n        r = _infix_to_postfix(\"a=2 OR b=3\")\n        assert r == [\"a=2\", \"b=3\", \"|\"]\n\n        r = _infix_to_postfix(\"a= OR b=\")\n        assert r == [\"a=\", \"b=\", \"|\"]  # Equivalent to \"\"\n\n        r = _infix_to_postfix(\"(a=2 OR b=3) AND (j=34 AND j=45) OR (a=1)\")\n        assert r == [\"a=2\", \"b=3\", \"|\", \"j=34\", \"j=45\", \"&\", \"a=1\", \"&\", \"|\"]\n\n        import pytest\n        with pytest.raises(Exception, match=\"Invalid expression: 2\"):\n            _infix_to_postfix(\"a= 2 OR b=3\")\n\n    def test_evaluate_postfix(self):\n\n        def evaluator(expr):\n            return expr in (\"a=2\", \"j=45\")\n\n        def evaluate(q):\n            r = _infix_to_postfix(q)\n            return _evaluate_postfix(r, evaluator)\n\n        assert evaluate(\"a=2\")\n        assert not evaluate(\"a=4\")\n        assert evaluate(\"a=2 OR a=3\")\n        assert evaluate(\"a=4 OR j=45\")\n        assert not evaluate(\"a=4 AND j=45\")\n        assert evaluate(\"a=2 AND (f=23 OR j=45)\")\n        assert not evaluate(\"a=2 AND (f=23 OR j=435)\")\n        assert evaluate(\"a=2 AND j=45 OR h=23\")\n        assert evaluate(\"a=2 AND j=45 OR (h=23 AND a=2)\")\n        assert evaluate(\"((((a=2 AND ((((f=23 OR j=45))))))))\")\n        assert not evaluate(\"((((a=2 AND ((((f=23 OR j=42))))))))\")\n"
  },
  {
    "path": "test/unittests/server/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/server/authenticator_plugin_test.py",
    "content": "import os\n\nfrom conans.server.plugin_loader import load_authentication_plugin\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.internal.util.files import save\n\n\nclass TestAuthenticatorPlugin:\n\n    def test_instance_authenticator(self):\n        folder = temp_folder()\n        plugin_path = os.path.join(folder, \"plugins\", \"authenticator\", \"my_auth.py\")\n        my_plugin = '''\n# import to test that they work\nimport os\n\ndef get_class():\n    return MyAuthenticator()\n\n\nclass MyAuthenticator(object):\n    def valid_user(self, username, plain_password):\n        os.path.exists(\"somepath\")  # dummy call, to test that os is not removed by GC\n        return username == \"foo\" and plain_password == \"bar\"\n'''\n        save(plugin_path, my_plugin)\n\n        plugin = load_authentication_plugin(folder, \"my_auth\")\n        assert plugin.valid_user(\"foo\", \"bar\")\n        assert not plugin.valid_user(\"foo2\", \"bar2\")\n"
  },
  {
    "path": "test/unittests/server/conan_server_config_parser_test.py",
    "content": "import os\nimport pytest\n\nfrom conan.errors import ConanException\nfrom conans.server.conf import ConanServerConfigParser\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.internal.util.files import mkdir, save\n\n\nclass TestServerConfigParse:\n\n    def test_not_allowed_encoding_password(self):\n        tmp_dir = temp_folder()\n        server_conf = \"\"\"\n[server]\njwt_secret: 534534534\njwt_expire_minutes: 120\nssl_enabled: False\nport: 9300\npublic_port:\nhost_name: localhost\nstore_adapter: disk\nauthorize_timeout: 1800\ndisk_storage_path: ~/.conan_server/data\ndisk_authorize_timeout: 1800\nupdown_secret: tbsiGzeEygYSCcNrSYcuzmZr\n\n\n[write_permissions]\n\n[users]\ndemo: %s\n        \"\"\"\n        server_dir = os.path.join(tmp_dir, \".conan_server\")\n        mkdir(server_dir)\n        conf_path = os.path.join(server_dir, \"server.conf\")\n\n        save(conf_path, server_conf % \"cönan\")\n\n        server_config = ConanServerConfigParser(tmp_dir)\n        with pytest.raises(ConanException, match=\"Password contains invalid characters. \"\n                                                 \"Only ASCII encoding is supported\"):\n            server_config.users   # noqa\n\n        save(conf_path, server_conf % \"manol ito!@\")\n        server_config = ConanServerConfigParser(tmp_dir)\n        assert server_config.users == {\"demo\": \"manol ito!@\"}\n\n        # Now test from ENV\n        server_config = ConanServerConfigParser(tmp_dir, environment={\"CONAN_SERVER_USERS\":\n                                                                      \"demo: cönan\"})\n        with pytest.raises(ConanException, match=\"Password contains invalid characters. \"\n                                                 \"Only ASCII encoding is supported\"):\n            server_config.users  # noqa\n\n        server_config = ConanServerConfigParser(tmp_dir, environment={\"CONAN_SERVER_USERS\":\n                                                                      \"demo:manolito!@\"})\n        assert server_config.users == {\"demo\": \"manolito!@\"}\n\n    def test_relative_public_url(self):\n        tmp_dir = temp_folder()\n        server_conf = \"\"\"\n[server]\n\n[write_permissions]\n\n[users]\n        \"\"\"\n        server_dir = os.path.join(tmp_dir, \".conan_server\")\n        mkdir(server_dir)\n        conf_path = os.path.join(server_dir, \"server.conf\")\n        save(conf_path, server_conf)\n\n        server_config = ConanServerConfigParser(tmp_dir)\n        assert server_config.public_url == \"v2\"\n\n    def test_custom_server_folder_path(self):\n        tmp_dir = temp_folder()\n        server_dir = os.path.join(tmp_dir, \".custom_conan_server\")\n        mkdir(server_dir)\n        conf_path = os.path.join(server_dir, \"server.conf\")\n        server_conf = \"\"\"\n[server]\n\n[write_permissions]\n\n[users]\n        \"\"\"\n        save(conf_path, server_conf)\n        server_config = ConanServerConfigParser(server_dir, is_custom_path=True)\n        assert server_config.conan_folder == server_dir\n\n    def test_custom_server_path_has_custom_data_path(self):\n        tmp_dir = temp_folder()\n        server_dir = os.path.join(tmp_dir, \".custom_conan_server\")\n        mkdir(server_dir)\n        conf_path = os.path.join(server_dir, \"server.conf\")\n        server_conf = \"\"\"\n[server]\ndisk_storage_path: ./custom_data\n\n[write_permissions]\n\n[users]\n        \"\"\"\n        save(conf_path, server_conf)\n        server_config = ConanServerConfigParser(server_dir, is_custom_path=True)\n        assert server_config.disk_storage_path == os.path.join(server_dir, \"custom_data\")\n"
  },
  {
    "path": "test/unittests/server/conf_test.py",
    "content": "import os\nimport pytest\nfrom datetime import timedelta\n\nfrom conan.errors import ConanException\nfrom conans.server.conf import ConanServerConfigParser\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.internal.util.config_parser import TextINIParse\nfrom conan.internal.util.files import save\n\nfileconfig = '''\n[server]\njwt_secret: mysecret\njwt_expire_minutes: 121\ndisk_storage_path: %s\nssl_enabled: true\nport: 9220\nhost_name: localhost\npublic_port: 12345\n\n\n[write_permissions]\nopenssl/2.0.1@lasote/testing: pepe\n\n[read_permissions]\n*/*@*/*: *\nopenssl/2.0.1@lasote/testing: pepe\n\n[users]\nlasote: defaultpass\npepe: pepepass\n'''\n\n\nclass TestServerConf:\n\n    @pytest.fixture(autouse=True)\n    def setup(self):\n        self.file_path = temp_folder()\n        server_conf = os.path.join(self.file_path, '.conan_server/server.conf')\n        self.storage_path = os.path.join(self.file_path, \"storage\")\n        save(server_conf, fileconfig % self.storage_path)\n        self.environ = {}\n\n    def test_unexpected_section(self):\n        text = \"\"\"\n[one]\ntext=value\n[two]\nother=var\n[three]\nvar\n[moon]\nvar=walker\n\"\"\"\n\n        with pytest.raises(ConanException):\n            TextINIParse(text, [\"one\", \"two\", \"three\"])\n        conf = TextINIParse(text)\n        assert conf.one == \"text=value\"\n        assert conf.two == \"other=var\"\n        assert conf.three == \"var\"\n        assert conf.moon == \"var=walker\"\n\n        # IF an old config file is readed but the section is in the list, just return it empty\n        text = \"\"\"\n[one]\ntext=value\n        \"\"\"\n        conf = TextINIParse(text)\n        assert conf.two == \"\"\n\n    def test_values(self):\n        config = ConanServerConfigParser(self.file_path, environment=self.environ)\n        assert config.jwt_secret == \"mysecret\"\n        assert config.jwt_expire_time == timedelta(minutes=121)\n        assert config.disk_storage_path == self.storage_path\n        assert config.ssl_enabled\n        assert config.port == 9220\n        assert config.write_permissions == [(\"openssl/2.0.1@lasote/testing\", \"pepe\")]\n        assert config.read_permissions == [(\"*/*@*/*\", \"*\"),\n                                                    (\"openssl/2.0.1@lasote/testing\", \"pepe\")]\n        assert config.users == {\"lasote\": \"defaultpass\", \"pepe\": \"pepepass\"}\n        assert config.host_name == \"localhost\"\n        assert config.public_port == 12345\n        assert config.public_url == \"https://localhost:12345/v2\"\n\n        # Now check with environments\n        tmp_storage = temp_folder()\n        self.environ[\"CONAN_STORAGE_PATH\"] = tmp_storage\n        self.environ[\"CONAN_JWT_SECRET\"] = \"newkey\"\n        self.environ[\"CONAN_JWT_EXPIRE_MINUTES\"] = \"123\"\n        self.environ[\"CONAN_SSL_ENABLED\"] = \"False\"\n        self.environ[\"CONAN_SERVER_PORT\"] = \"1233\"\n        self.environ[\"CONAN_SERVER_USERS\"] = \"lasote:lasotepass,pepe2:pepepass2\"\n        self.environ[\"CONAN_HOST_NAME\"] = \"remotehost\"\n        self.environ[\"CONAN_SERVER_PUBLIC_PORT\"] = \"33333\"\n\n        config = ConanServerConfigParser(self.file_path, environment=self.environ)\n        assert config.jwt_secret ==  \"newkey\"\n        assert config.jwt_expire_time == timedelta(minutes=123)\n        assert config.disk_storage_path == tmp_storage\n        assert not config.ssl_enabled\n        assert config.port == 1233\n        assert config.write_permissions == [(\"openssl/2.0.1@lasote/testing\", \"pepe\")]\n        assert config.read_permissions == [(\"*/*@*/*\", \"*\"),\n                                                    (\"openssl/2.0.1@lasote/testing\", \"pepe\")]\n        assert config.users == {\"lasote\": \"lasotepass\", \"pepe2\": \"pepepass2\"}\n        assert config.host_name == \"remotehost\"\n        assert config.public_port == 33333\n        assert config.public_url == \"http://remotehost:33333/v2\"\n"
  },
  {
    "path": "test/unittests/server/crypto/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/server/crypto/jwt_test.py",
    "content": "import time\nfrom datetime import timedelta\n\nimport jwt\nimport pytest\nfrom jwt import DecodeError\n\nfrom conans.server.crypto.jwt.jwt_credentials_manager import JWTCredentialsManager\n\n\ndef test_jwt_manager():\n    # Instance the manager to generate tokens that expires in 10 ms\n    manager = JWTCredentialsManager(secret=\"1234asdf\" * 4, expire_time=timedelta(seconds=1))\n\n    # Encrypt a profile\n    token = manager.get_token_for(\"myuser\")\n\n    # Decrypt the profile\n    assert \"myuser\" == manager.get_user(token)\n    with pytest.raises(DecodeError):\n        manager.get_user(\"invalid_user\")\n\n    # Now wait 2 seconds and check if its valid now\n    time.sleep(2)\n    with pytest.raises(jwt.ExpiredSignatureError):\n        manager.get_user(token)\n"
  },
  {
    "path": "test/unittests/server/revision_list_test.py",
    "content": "from math import floor\n\nimport time\n\nfrom conans.server.revision_list import RevisionList\n\n\nclass TestRevisionList:\n\n    def test_remove_latest(self):\n        rev = RevisionList()\n        rev.add_revision(\"rev1\")\n        rev.add_revision(\"rev2\")\n\n        dumped = rev.dumps()\n        loaded = RevisionList.loads(dumped)\n        assert rev == loaded\n        assert loaded.latest_revision().revision == \"rev2\"\n\n        loaded.remove_revision(\"rev2\")\n        assert loaded.latest_revision().revision == \"rev1\"\n\n    def test_remove_non_latest(self):\n        rev = RevisionList()\n        rev.add_revision(\"rev1\")\n        rev.add_revision(\"rev2\")\n\n        dumped = rev.dumps()\n        loaded = RevisionList.loads(dumped)\n        loaded.remove_revision(\"rev1\")\n        assert loaded.latest_revision().revision == \"rev2\"\n\n    def test_compatibility_with_timestamps(self):\n        the_time = floor(time.time())\n        old_contents = '{\"revisions\": [{\"revision\": \"rev1\", \"time\": %s}, ' \\\n                       '{\"revision\": \"rev2\", \"time\": %s}]}' % (the_time, the_time)\n        r_list = RevisionList.loads(old_contents)\n        when = r_list.get_time(\"rev1\")\n        assert when == the_time\n"
  },
  {
    "path": "test/unittests/server/service/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/server/service/authorizer_test.py",
    "content": "import pytest\n\nfrom conan.internal.errors import InternalErrorException, AuthenticationException, ForbiddenException\nfrom conan.api.model import PkgReference\nfrom conan.api.model import RecipeReference\nfrom conans.server.service.authorize import BasicAuthorizer\n\n\nclass TestAuthorizer:\n\n    @pytest.fixture(autouse=True)\n    def setup(self):\n        self.openssl_ref = RecipeReference.loads(\"openssl/2.0.1@lasote/testing\")\n        self.openssl_pref = PkgReference(self.openssl_ref, \"123123123\")\n        self.openssl_ref2 = RecipeReference.loads(\"openssl/2.0.2@lasote/testing\")\n        self.openssl_pref2 = PkgReference(self.openssl_ref2, \"123123123\")\n\n    def test_invalid_rule(self):\n        \"\"\"Invalid rule input\"\"\"\n        read_perms = [\"invalid_reference\", \"lasote\", (\"*/*@*/*\", \"\")]\n        write_perms = []\n\n        authorizer = BasicAuthorizer(read_perms, write_perms)\n        with pytest.raises(InternalErrorException):\n            authorizer.check_read_conan(\"pepe\", self.openssl_ref)\n\n    def test_check_wildcards(self):\n        # Only pepe can read openssl versions\n        read_perms = [(\"openssl/*@lasote/testing\", \"pepe\"), (\"*/*@*/*\", \"*\")]\n        # Only pepe (and lasote because its owner) can write it and no more users can write\n        write_perms = [(str(self.openssl_ref), \"pepe\")]\n\n        authorizer = BasicAuthorizer(read_perms, write_perms)\n        # Pepe can read all openssl versions\n        authorizer.check_read_conan(\"pepe\", self.openssl_ref)\n        authorizer.check_read_conan(\"pepe\", self.openssl_ref2)\n        # Other user can't\n        with pytest.raises(ForbiddenException):\n            authorizer.check_read_conan(\"juan\", self.openssl_ref)\n        with pytest.raises(ForbiddenException):\n            authorizer.check_read_conan(\"juan\", self.openssl_ref2)\n\n        # Only pepe can read versions 2.0.1 of lasote/testing\n        read_perms = [(\"*/2.0.2@lasote/testing\", \"pepe\"), (\"*/*@*/*\", \"*\")]\n        authorizer = BasicAuthorizer(read_perms, write_perms)\n        # Pepe can read openssl 2.0.1 version and 2.0.2 (only matches 2.0.2, so other is allowed)\n        authorizer.check_read_conan(\"pepe\", self.openssl_ref2)\n        authorizer.check_read_conan(\"pepe\", self.openssl_ref2)\n        # Other user can't read 2.0.2\n        authorizer.check_read_conan(\"juan\", self.openssl_ref)\n        with pytest.raises(ForbiddenException):\n            authorizer.check_read_conan(\"juan\", self.openssl_ref2)\n\n        # Only pepe can read openssl version 2.0.1 from any owner\n        read_perms = [(\"openssl/2.0.1@*/testing\", \"pepe\")]\n        # Only pepe (and lasote because its owner) can write it and no more users can write\n        write_perms = [(str(self.openssl_ref), \"pepe\")]\n\n        authorizer = BasicAuthorizer(read_perms, write_perms)\n        # Pepe can read any openssl/2.0.1\n        authorizer.check_read_conan(\"pepe\", self.openssl_ref)\n        tmp_ref = RecipeReference.loads(\"openssl/2.0.1@alfred/testing\")\n        authorizer.check_read_conan(\"pepe\", tmp_ref)\n        with pytest.raises(ForbiddenException):\n            authorizer.check_read_conan(\"juan\", self.openssl_ref)\n        with pytest.raises(ForbiddenException):\n            authorizer.check_read_conan(\"juan\", tmp_ref)\n\n        # Only pepe can read openssl version 2.0.1 from lasote/any channel\n        read_perms = [(\"openssl/2.0.1@lasote/*\", \"pepe\")]\n        # Only pepe (and lasote because its owner) can write it and no more users can write\n        write_perms = [(str(self.openssl_ref), \"pepe\")]\n\n        authorizer = BasicAuthorizer(read_perms, write_perms)\n        # Pepe can read openssl/2.0.1 from any channel but only from lasote\n        authorizer.check_read_conan(\"pepe\", self.openssl_ref)\n        tmp_ref = RecipeReference.loads(\"openssl/2.0.1@alfred/testing\")\n        with pytest.raises(ForbiddenException):\n            authorizer.check_read_conan(\"pepe\", tmp_ref)\n\n        tmp_ref = RecipeReference.loads(\"openssl/2.0.1@lasote/otherchannel\")\n        authorizer.check_read_conan(\"pepe\", tmp_ref)\n\n    def test_permissions(self):\n        \"\"\"Check that permissions logic is ok\"\"\"\n        # Only lasote can read it but other conans can be readed\n        read_perms = [(str(self.openssl_ref), \"lasote\"), (\"*/*@*/*\", \"*\")]\n        # Only pepe (and lasote because its owner) can write it and no more users can write\n        write_perms = [(str(self.openssl_ref), \"pepe, lasote\")]\n\n        authorizer = BasicAuthorizer(read_perms, write_perms)\n\n        # READ PERMISSIONS\n\n        # Pepe can't read conans\n        with pytest.raises(ForbiddenException):\n            authorizer.check_read_conan(\"pepe\", self.openssl_ref)\n\n        # Owner can read conans\n        authorizer.check_read_conan(\"lasote\", self.openssl_ref)\n\n        # Pepe can read other conans\n        authorizer.check_read_conan(\"pepe\", self.openssl_ref2)\n\n        # Pepe can't read package\n        with pytest.raises(ForbiddenException):\n            authorizer.check_read_package(\"pepe\", self.openssl_pref)\n\n        # Owner can read package\n        authorizer.check_read_package(\"lasote\", self.openssl_pref)\n\n        # Pepe can read other package\n        authorizer.check_read_package(\"pepe\", self.openssl_pref2)\n\n        # WRITE PERMISSIONS\n\n        # Pepe can write conans\n        authorizer.check_write_conan(\"pepe\", self.openssl_ref)\n\n        # Juan can't write conans\n        with pytest.raises(ForbiddenException):\n            authorizer.check_write_conan(\"juan\", self.openssl_ref)\n\n        # Owner can write conans\n        authorizer.check_write_conan(\"lasote\", self.openssl_ref)\n\n        # Pepe can't write other conans\n        with pytest.raises(ForbiddenException):\n            authorizer.check_write_conan(\"pepe\", self.openssl_ref2)\n\n        # Owner can write package\n        authorizer.check_write_package(\"lasote\", self.openssl_pref)\n\n        # Pepe can write package\n        authorizer.check_write_package(\"pepe\", self.openssl_pref)\n\n        # Pepe can't write other package\n        with pytest.raises(ForbiddenException):\n            authorizer.check_write_package(\"pepe\", self.openssl_pref2)\n\n    def test_authenticated_user_wildcard_permissions(self):\n        \"\"\"Check that authenciated user wildcard permissions logic is ok\"\"\"\n        # Only authenticated users can read openssl\n        read_perms = [(str(self.openssl_ref), \"?\"), (\"*/*@*/*\", \"*\")]\n        # Authenticated users can write any\n        write_perms = [(\"*/*@*/*\", \"?\")]\n\n        authorizer = BasicAuthorizer(read_perms, write_perms)\n\n        # READ PERMISSIONS\n\n        # Authenticated user can read conan\n        authorizer.check_read_conan(\"pepe\", self.openssl_ref)\n\n        # Authenticated user can read package\n        authorizer.check_read_package(\"pepe\", self.openssl_pref)\n\n        # Anonymous user can not read conan, they must authenticate\n        with pytest.raises(AuthenticationException):\n            authorizer.check_read_conan(None, self.openssl_ref)\n\n        # Anonymous user can not read package, they must authenticate\n        with pytest.raises(AuthenticationException):\n            authorizer.check_read_package(None, self.openssl_pref)\n\n        # WRITE PERMISSIONS\n\n        # Authenticated user can write conan\n        authorizer.check_write_conan(\"pepe\", self.openssl_ref)\n\n        # Authenticated user can write package\n        authorizer.check_write_package(\"pepe\", self.openssl_pref)\n\n        # Anonymous user can not write conan, they must authenticate\n        with pytest.raises(AuthenticationException):\n            authorizer.check_write_conan(None, self.openssl_ref)\n\n        # Anonymous user can not write package, they must authenticate\n        with pytest.raises(AuthenticationException):\n            authorizer.check_write_package(None, self.openssl_pref)\n\n    def test_users(self):\n        \"\"\"Check that lists of user names are parsed correctly\"\"\"\n\n        # Simple user list\n        read_perms = [(\"openssl/*@lasote/testing\", \"user1,user2,user3\")]\n        authorizer = BasicAuthorizer(read_perms, [])\n        for u in ['user1', 'user2', 'user3']:\n            authorizer.check_read_conan(u, self.openssl_ref)\n\n        # Spaces bewteen user names should be ignored\n        read_perms = [(\"openssl/*@lasote/testing\", \"user1 , user2,\\tuser3\")]\n        authorizer = BasicAuthorizer(read_perms, [])\n        for u in ['user1', 'user2', 'user3']:\n            authorizer.check_read_conan(u, self.openssl_ref)\n"
  },
  {
    "path": "test/unittests/server/service/service_test.py",
    "content": "import copy\nimport os\nimport pytest\n\nfrom conan.internal.errors import NotFoundException\nfrom conan.internal.model.manifest import FileTreeManifest\nfrom conan.api.model import PkgReference\nfrom conan.api.model import RecipeReference\nfrom conan.internal.paths import CONANINFO, CONAN_MANIFEST\nfrom conans.server.service.authorize import BasicAuthorizer\nfrom conans.server.service.v2.search import SearchService\nfrom conans.server.service.v2.service_v2 import ConanServiceV2\nfrom conans.server.store.disk_adapter import ServerDiskAdapter\nfrom conans.server.store.server_store import ServerStore\nfrom conan.test.assets.genconanfile import GenConanfile\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.internal.util.files import save, save_files\n\n\nDEFAULT_REVISION = \"1234\"\n\n\nclass TestConanService:\n\n    @pytest.fixture(autouse=True)\n    def setup(self):\n        self.ref = RecipeReference.loads(\"openssl/2.0.3@lasote/testing#%s\" % DEFAULT_REVISION)\n\n        self.pref = PkgReference(self.ref, \"123123123\", DEFAULT_REVISION)\n        self.tmp_dir = temp_folder()\n\n        read_perms = [(\"*/*@*/*\", \"*\")]\n        write_perms = [(\"*/*@*/*\", \"*\")]\n        authorizer = BasicAuthorizer(read_perms, write_perms)\n\n        self.fake_url = \"http://url\"\n        adapter = ServerDiskAdapter(self.fake_url, self.tmp_dir)\n        self.server_store = ServerStore(storage_adapter=adapter)\n        self.service = ConanServiceV2(authorizer, self.server_store)\n        self.search_service = SearchService(authorizer, self.server_store, \"lasote\")\n\n        files = {\"conanfile.py\": str(GenConanfile(\"test\"))}\n        save_files(self.server_store.export(self.ref), files)\n        self.server_store.update_last_revision(self.ref)\n        manifest = FileTreeManifest.create(self.server_store.export(self.ref))\n        conan_digest_path = os.path.join(self.server_store.export(self.ref), CONAN_MANIFEST)\n        save(conan_digest_path, repr(manifest))\n\n        files = {\"boost.lib\": \"\", \"boost2.lib\": \"\"}\n        save_files(self.server_store.package(self.pref), files)\n\n    def test_search(self):\n        \"\"\" check the dict is returned by get_packages_info service\n        \"\"\"\n        # Creating and saving conans, packages, and conans.vars\n        ref2 = RecipeReference(\"openssl\", \"3.0\", \"lasote\", \"stable\", DEFAULT_REVISION)\n        ref3 = RecipeReference(\"Assimp\", \"1.10\", \"fenix\", \"stable\", DEFAULT_REVISION)\n        ref4 = RecipeReference(\"assimpFake\", \"0.1\", \"phil\", \"stable\", DEFAULT_REVISION)\n\n        pref2 = PkgReference(ref2, \"12345587754\", DEFAULT_REVISION)\n        pref3 = PkgReference(ref3, \"77777777777\", DEFAULT_REVISION)\n\n        conan_vars = \"\"\"\n[options]\n    use_Qt=%s\n\"\"\"\n        conan_vars1 = conan_vars % \"True\"\n        conan_vars2 = conan_vars % \"False\"\n        conan_vars3 = conan_vars % \"True\"\n\n        save_files(self.server_store.package(self.pref), {CONANINFO: conan_vars1})\n        self.server_store.update_last_package_revision(self.pref)\n        save_files(self.server_store.package(pref2), {CONANINFO: conan_vars2})\n        self.server_store.update_last_package_revision(pref2)\n        save_files(self.server_store.package(pref3), {CONANINFO: conan_vars3})\n        self.server_store.update_last_package_revision(pref3)\n\n        save_files(self.server_store.export(ref4), {\"dummy.txt\": \"//\"})\n\n        info = self.search_service.search()\n        expected = [RecipeReference(r.name, r.version, r.user, r.channel, revision=None)\n                    for r in [ref3, ref4, self.ref, ref2]]\n        assert expected == info\n\n        info = self.search_service.search(pattern=\"Assimp*\", ignorecase=False)\n        ref3_norev = copy.copy(ref3)\n        ref3_norev.revision = None\n        assert info == [ref3_norev]\n\n        info = self.search_service.search_packages(ref2)\n        assert info == {'12345587754': {'content': '\\n[options]\\n    use_Qt=False\\n',\n                                                }}\n\n        info = self.search_service.search_packages(ref3)\n        assert info == {'77777777777': {'content': '\\n[options]\\n    use_Qt=True\\n'}\n                                }\n\n        info = self.search_service.search_packages(ref2, list_only=True)\n        assert info == {'12345587754': {}}\n\n        info = self.search_service.search_packages(ref3, list_only=True)\n        assert info == {'77777777777': {}}\n\n    def test_remove(self):\n        ref2 = RecipeReference(\"OpenCV\", \"3.0\", \"lasote\", \"stable\", DEFAULT_REVISION)\n        ref3 = RecipeReference(\"Assimp\", \"1.10\", \"lasote\", \"stable\", DEFAULT_REVISION)\n\n        pref2 = PkgReference(ref2, \"12345587754\", DEFAULT_REVISION)\n        pref3 = PkgReference(ref3, \"77777777777\", DEFAULT_REVISION)\n\n        save_files(self.server_store.export(ref2), {\"fake.txt\": \"//fake\"})\n        self.server_store.update_last_revision(ref2)\n        save_files(self.server_store.package(pref2), {\"fake.txt\": \"//fake\"})\n        self.server_store.update_last_package_revision(pref2)\n        save_files(self.server_store.package(pref3), {\"fake.txt\": \"//fake\"})\n        self.server_store.update_last_package_revision(pref3)\n\n        # Delete all the conans folder\n        self.service.remove_recipe(self.ref, \"lasote\")\n        conan_path = self.server_store.base_folder(self.ref)\n        assert not os.path.exists(conan_path)\n\n        # Raise an exception\n        with pytest.raises(NotFoundException):\n            self.service.remove_recipe(\n                              RecipeReference(\"Fake\", \"1.0\", \"lasote\", \"stable\"), \"lasote\")\n"
  },
  {
    "path": "test/unittests/server/test_utils.py",
    "content": "import os\n\nfrom conans.server.utils.files import path_exists\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.internal.util.files import mkdir\n\n\ndef test_path_exists():\n    \"\"\"\n    Unit test of path_exists\n    \"\"\"\n    tmp_dir = temp_folder()\n    tmp_dir = os.path.join(tmp_dir, \"WhatEver\")\n    new_path = os.path.join(tmp_dir, \"CapsDir\")\n    mkdir(new_path)\n    assert path_exists(new_path, tmp_dir)\n    assert not path_exists(os.path.join(tmp_dir, \"capsdir\"), tmp_dir)\n"
  },
  {
    "path": "test/unittests/source/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/source/merge_directories_test.py",
    "content": "import os\nimport shutil\nfrom os.path import join\n\nimport pytest\n\nfrom conan.errors import ConanException\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.internal.util.files import mkdir, save, merge_directories, load\n\n\nclass TestMergeDirectories:\n\n    @pytest.fixture(autouse=True)\n    def setup(self):\n        self.source = temp_folder()\n        self.dest = temp_folder()\n\n    def _save(self, folder, files, content=None):\n        for the_file in files:\n            save(join(folder, the_file), content or \"c\")\n\n    def _get_paths(self, folder):\n        ret = []\n        for root, dirs, files in os.walk(folder):\n            for the_file in files:\n                relpath = os.path.relpath(root, folder)\n                if relpath == \".\":\n                    relpath = \"\"\n                ret.append(join(relpath, the_file))\n            for the_dir in dirs:\n                if not os.listdir(join(root, the_dir)):\n                    relpath = os.path.relpath(join(root, the_dir), folder)\n                    ret.append(relpath)\n        return ret\n\n    def _assert_equals(self, list1, list2):\n        assert set([el.replace(\"/\", \"\\\\\") for el in list1]) == set([el.replace(\"/\", \"\\\\\") for el in list2])\n\n    def test_empty_dest_merge(self):\n        files = [\"file.txt\", \"subdir/file2.txt\"]\n        self._save(self.source, files)\n        merge_directories(self.source, self.dest)\n        self._assert_equals(self._get_paths(self.dest), files)\n\n    def test_non_empty_dest_merge(self):\n        files = [\"file.txt\", \"subdir/file2.txt\"]\n        self._save(self.source, files, \"fromsrc\")\n\n        files_dest = [\"file.txt\", \"subdir2/file2.txt\"]\n        self._save(self.dest, files_dest, \"fromdest\")\n\n        merge_directories(self.source, self.dest)\n        self._assert_equals(self._get_paths(self.dest), files + files_dest)\n        # File from src overrides file from dest\n        assert load(join(self.dest, \"file.txt\")) == \"fromsrc\"\n\n    def test_nested_directories(self):\n        self.dest = join(self.source, \"destination_dir\")\n        files_dest = [\"file.txt\", \"subdir2/file2.txt\"]\n        self._save(self.dest, files_dest, \"fromdest\")\n        mkdir(join(self.dest, \"empty_folder\", \"subempty_folder\"))\n\n        files = [\"file.txt\", \"subdir/file2.txt\"]\n        self._save(self.source, files, \"fromsrc\")\n\n        merge_directories(self.source, self.dest)\n        self._assert_equals(self._get_paths(self.dest), files + files_dest +\n                            ['empty_folder/subempty_folder', ])\n        assert load(join(self.dest, \"file.txt\")) == \"fromsrc\"\n        assert load(join(self.dest, \"subdir2/file2.txt\")) == \"fromdest\"\n        assert load(join(self.dest, \"subdir/file2.txt\")) == \"fromsrc\"\n\n    def test_same_directory(self):\n        # Same directory cannot be merged, this should never happen\n        with pytest.raises(ConanException):\n            merge_directories(self.source, self.source)\n\n    def test_parent_directory(self):\n        files_dest = [\"file.txt\", \"subdir2/file2.txt\"]\n        self._save(self.dest, files_dest, \"fromdest\")\n        self.source = join(self.dest, \"source_folder\")\n        files = [\"file.txt\", \"subdir/file2.txt\"]\n        self._save(self.source, files, \"fromsrc\")\n        merge_directories(self.source, self.dest)\n        shutil.rmtree(self.source)\n        self._assert_equals(self._get_paths(self.dest), files + files_dest)\n        assert load(join(self.dest, \"file.txt\")) == \"fromsrc\"\n        assert load(join(self.dest, \"subdir2/file2.txt\")) == \"fromdest\"\n        assert load(join(self.dest, \"subdir/file2.txt\")) == \"fromsrc\"\n"
  },
  {
    "path": "test/unittests/tools/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/tools/android/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/tools/android/test_android_tools.py",
    "content": "from conan.test.utils.mocks import ConanFileMock, MockSettings\nfrom conan.errors import ConanException\nfrom conan.tools.android import android_abi\n\nfrom pytest import raises\n\n\ndef test_tools_android_abi():\n    settings_linux = MockSettings({\"os\": \"Linux\", \"arch\": \"foo\"})\n\n    for (arch, expected) in [\n        (\"armv5el\", \"armeabi\"),\n        (\"armv5hf\", \"armeabi\"),\n        (\"armv5\", \"armeabi\"),\n        (\"armv6\", \"armeabi-v6\"),\n        (\"armv7\", \"armeabi-v7a\"),\n        (\"armv7hf\", \"armeabi-v7a\"),\n        (\"armv8\", \"arm64-v8a\"),\n        (\"x86\", \"x86\"),\n        (\"x86_64\", \"x86_64\"),\n        (\"mips\", \"mips\"),\n        (\"mips_64\", \"mips_64\"),\n    ]:\n        conanfile = ConanFileMock()\n        settings_android = MockSettings({\"os\": \"Android\", \"arch\": arch})\n\n        # 2 profiles\n        ## native build\n        conanfile.settings = settings_android\n        conanfile.settings_host = settings_android\n        conanfile.settings_build = settings_android\n\n        assert android_abi(conanfile) == expected\n        assert android_abi(conanfile, context=\"host\") == expected\n        assert android_abi(conanfile, context=\"build\") == expected\n\n        with raises(ConanException):\n            assert android_abi(conanfile, context=\"target\") == expected\n\n        ## cross-build from Android to Linux (quite hypothetical)\n        conanfile.settings = settings_linux\n        conanfile.settings_host = settings_linux\n        conanfile.settings_build = settings_android\n        assert android_abi(conanfile) != expected\n        assert android_abi(conanfile, context=\"host\") != expected\n        assert android_abi(conanfile, context=\"build\") == expected\n\n        with raises(ConanException):\n            assert android_abi(conanfile, context=\"target\")\n\n        ## cross-build a recipe from Linux to Android:\n        ### test android_abi in recipe itself\n        conanfile.settings = settings_android\n        conanfile.settings_host = settings_android\n        conanfile.settings_build = settings_linux\n        assert android_abi(conanfile) == expected\n        assert android_abi(conanfile, context=\"host\") == expected\n        assert android_abi(conanfile, context=\"build\") != expected\n        with raises(ConanException):\n            android_abi(conanfile, context=\"target\")\n\n        ### test android_abi in \"compiler recipe\" (ie a android-ndk recipe in tool_requires of recipe being cross-build)\n        conanfile.settings = settings_linux\n        conanfile.settings_host = settings_linux\n        conanfile.settings_build = settings_linux\n        conanfile.settings_target = settings_android\n        assert android_abi(conanfile) != expected\n        assert android_abi(conanfile, context=\"host\") != expected\n        assert android_abi(conanfile, context=\"build\") != expected\n        assert android_abi(conanfile, context=\"target\") == expected\n"
  },
  {
    "path": "test/unittests/tools/apple/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/tools/apple/test_apple_tools.py",
    "content": "from unittest import mock\nimport pytest\nimport textwrap\n\nfrom conan.internal.internal_tools import is_universal_arch\nfrom conan.errors import ConanException\nfrom conan.test.utils.mocks import ConanFileMock, MockSettings, MockOptions\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.tools.apple import is_apple_os, to_apple_arch, fix_apple_shared_install_name, XCRun\nfrom conan.tools.apple.apple import _get_dylib_install_name\n\n\ndef test_tools_apple_is_apple_os():\n    conanfile = ConanFileMock()\n\n    conanfile.settings = MockSettings({\"os\": \"Macos\"})\n    assert is_apple_os(conanfile)\n\n    conanfile.settings = MockSettings({\"os\": \"watchOS\"})\n    assert is_apple_os(conanfile)\n\n    conanfile.settings = MockSettings({\"os\": \"Windows\"})\n    assert not is_apple_os(conanfile)\n\n\ndef test_tools_apple_to_apple_arch():\n    conanfile = ConanFileMock()\n\n    conanfile.settings = MockSettings({\"arch\": \"armv8\"})\n    assert to_apple_arch(conanfile) == \"arm64\"\n\n    conanfile.settings = MockSettings({\"arch\": \"x86_64\"})\n    assert to_apple_arch(conanfile) == \"x86_64\"\n\n\ndef test_fix_shared_install_name_no_libraries():\n    conanfile = ConanFileMock()\n    conanfile.options = MockOptions({\"shared\": True})\n    conanfile.settings = MockSettings({\"os\": \"Macos\"})\n    conanfile.folders.set_base_package(temp_folder())\n\n    with pytest.raises(Exception) as e:\n        fix_apple_shared_install_name(conanfile)\n    assert \"not found inside package folder\" in str(e.value)\n\n\ndef test_xcrun_public_settings():\n    # https://github.com/conan-io/conan/issues/12485\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\"os\": \"watchOS\"})\n\n    xcrun = XCRun(conanfile, use_settings_target=True)\n    settings = xcrun.settings\n\n    assert settings.os == \"watchOS\"\n\n\ndef test_get_dylib_install_name():\n    # https://github.com/conan-io/conan/issues/13014\n    single_arch = textwrap.dedent(\"\"\"\n    /path/to/libwebp.7.dylib:\n    /absolute/path/lib/libwebp.7.dylib\n    \"\"\")\n\n    universal_binary = textwrap.dedent(\"\"\"\n    /.conan/data/package/lib/libwebp.7.dylib (architecture x86_64):\n    /absolute/path/lib/libwebp.7.dylib\n    /.conan/data/package/lib/libwebp.7.dylib (architecture arm64):\n    /absolute/path/lib/libwebp.7.dylib\n    \"\"\")\n\n    for mock_output in (single_arch, universal_binary):\n        with mock.patch(\"conan.tools.apple.apple.check_output_runner\") as mock_output_runner:\n            mock_output_runner.return_value = mock_output\n            install_name = _get_dylib_install_name(\"otool\", \"/path/to/libwebp.7.dylib\")\n            assert \"/absolute/path/lib/libwebp.7.dylib\" == install_name\n\n\n@pytest.mark.parametrize(\"settings_value,valid_definitions,result\", [\n    (\"arm64|x86_64\", [\"arm64\", \"x86_64\", \"armv7\", \"x86\"], True),\n    (\"x86_64|arm64\", [\"arm64\", \"x86_64\", \"armv7\", \"x86\"], None),\n    (\"armv7|x86\", [\"arm64\", \"x86_64\", \"armv7\", \"x86\"], True),\n    (\"x86|armv7\", [\"arm64\", \"x86_64\", \"armv7\", \"x86\"], None),\n    (None, [\"arm64\", \"x86_64\", \"armv7\", \"x86\"], False),\n    (\"arm64|armv7|x86_64\", [\"arm64\", \"x86_64\", \"armv7\", \"x86\"], True),\n    (\"x86|arm64\", [\"arm64\", \"x86_64\", \"armv7\", \"x86\"], None),\n    (\"arm64|ppc32\", None, False),\n    (None, None, False),\n    (\"armv7|x86\", None, False),\n    (\"arm64\", [\"arm64\", \"x86_64\"], False),\n])\n# None is for the exception case\ndef test_is_universal_arch(settings_value, valid_definitions, result):\n    if result is None:\n        with pytest.raises(ConanException):\n            is_universal_arch(settings_value, valid_definitions)\n    else:\n        assert is_universal_arch(settings_value, valid_definitions) == result\n"
  },
  {
    "path": "test/unittests/tools/apple/test_xcodebuild.py",
    "content": "import pytest\n\nfrom conan.tools.apple import XcodeBuild\nfrom conan.internal.model.conf import ConfDefinition\nfrom conan.test.utils.mocks import ConanFileMock, MockSettings\n\n\n@pytest.mark.parametrize(\"mode\", [\"quiet\", None, \"verbose\"])\ndef test_verbosity_global(mode):\n    conanfile = ConanFileMock()\n    conf = ConfDefinition()\n    if mode is not None:\n        conf.loads(f\"tools.build:verbosity={mode}\")\n    conanfile.conf = conf\n    conanfile.settings = MockSettings({})\n    xcodebuild = XcodeBuild(conanfile)\n\n    xcodebuild.build(\"app.xcodeproj\")\n    if mode == \"verbose\":\n        assert \"-verbose\" in conanfile.command\n        assert \"-quiet\" not in conanfile.command\n    elif mode == \"quiet\":\n        assert \"-verbose\" not in conanfile.command\n        assert \"-quiet\" in conanfile.command\n    else:\n        assert \"-verbose\" not in conanfile.command\n        assert \"-quiet\" not in conanfile.command\n\n\ndef test_sdk_path():\n    conanfile = ConanFileMock()\n    conf = ConfDefinition()\n    conf.loads(\"tools.apple:sdk_path=mypath\")\n    conanfile.conf = conf\n    conanfile.settings = MockSettings({})\n    xcodebuild = XcodeBuild(conanfile)\n    xcodebuild.build(\"app.xcodeproj\")\n    assert \"SDKROOT=mypath \" in conanfile.command\n\n\ndef test_sdk():\n    conanfile = ConanFileMock()\n    conf = ConfDefinition()\n    conf.loads(\"tools.apple:sdk_path=mypath\")\n    conanfile.conf = conf\n    conanfile.settings = MockSettings({\"os\": \"Macos\",\n                                       \"os.sdk\": \"macosx\"})\n    xcodebuild = XcodeBuild(conanfile)\n    xcodebuild.build(\"app.xcodeproj\")\n    # sdk_path takes preference\n    assert \"SDKROOT=mypath \" in conanfile.command\n    conf = ConfDefinition()\n    conanfile.conf = conf\n    xcodebuild = XcodeBuild(conanfile)\n    xcodebuild.build(\"app.xcodeproj\")\n    assert \"SDKROOT=macosx \" in conanfile.command\n    conanfile.settings = MockSettings({\"os\": \"Macos\",\n                                       \"os.sdk\": \"macosx\",\n                                       \"os.sdk_version\": \"12.1\"})\n    xcodebuild = XcodeBuild(conanfile)\n    xcodebuild.build(\"app.xcodeproj\")\n    assert \"SDKROOT=macosx12.1 \" in conanfile.command\n    conanfile.settings = MockSettings({})\n    xcodebuild = XcodeBuild(conanfile)\n    xcodebuild.build(\"app.xcodeproj\")\n    assert \"SDKROOT\" not in conanfile.command\n\n\n@pytest.mark.parametrize(\"os_name, os_version, expected_key\", [\n    (\"Macos\", \"14.0\", \"MACOSX_DEPLOYMENT_TARGET\"),\n    (\"iOS\", \"15.1\", \"IPHONEOS_DEPLOYMENT_TARGET\"),\n    (\"watchOS\", \"8.0\", \"WATCHOS_DEPLOYMENT_TARGET\"),\n    (\"tvOS\", \"15.0\", \"TVOS_DEPLOYMENT_TARGET\"),\n    (\"visionOS\", \"1.0\", \"XROS_DEPLOYMENT_TARGET\")\n])\ndef test_deployment_target_and_quoting(os_name, os_version, expected_key):\n    \"\"\"\n    Checks that the correct deployment target is passed and that paths are quoted.\n    \"\"\"\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\"os\": os_name, \"os.version\": os_version})\n    xcodebuild = XcodeBuild(conanfile)\n\n    xcodebuild.build(\"My Project.xcodeproj\", target=\"My Target\")\n\n    expected_arg = f\" {expected_key}={os_version}\"\n    assert expected_arg in conanfile.command\n\n    assert \"-project 'My Project.xcodeproj'\" in conanfile.command\n    assert \"-target 'My Target'\" in conanfile.command\n\n\ndef test_no_deployment_target_if_version_is_missing():\n    \"\"\"\n    Checks that the deployment target argument is not added if os.version is missing.\n    \"\"\"\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\"os\": \"Macos\"})\n    xcodebuild = XcodeBuild(conanfile)\n    xcodebuild.build(\"app.xcodeproj\")\n\n    assert \"MACOSX_DEPLOYMENT_TARGET\" not in conanfile.command\n"
  },
  {
    "path": "test/unittests/tools/build/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/tools/build/test_can_run.py",
    "content": "import pytest\n\nfrom conan.test.utils.mocks import MockSettings, ConanFileMock\nfrom conan.tools.build import can_run\n\n\nclass ConfigMock:\n    def __init__(self, run=None):\n        self.can_run = run\n\n    def get(self, conf_name, default=None, check_type=None):  # noqa\n        return self.can_run\n\n\n@pytest.mark.parametrize(\"expected\", [False, True])\ndef test_can_run_explicit_config(expected):\n    \"\"\" When the config tools.build.cross_building:can_run is declared and evaluated (True|False),\n        can_run must return the same value.\n    \"\"\"\n    config = ConfigMock(expected)\n    settings = MockSettings({\"os\": \"Macos\",\n                             \"compiler\": \"apple-clang\",\n                             \"compiler.version\": \"11.0\",\n                             \"arch\": \"armv8\"})\n    conanfile = ConanFileMock(settings)\n    conanfile.conf = config\n    assert expected == can_run(conanfile)\n\n\n@pytest.mark.parametrize(\"arch, expected\", [(\"x86_64\", False), (\"armv8\", True)])\ndef test_can_run_cross_building(arch, expected):\n    \"\"\" When the config is None, and is cross-building, can_run must return False.\n    \"\"\"\n    config = ConfigMock(None)\n    settings_build = MockSettings({\"os\": \"Macos\",\n                                   \"compiler\": \"apple-clang\",\n                                   \"compiler.version\": \"11.0\",\n                                   \"arch\": \"armv8\"})\n    settings = MockSettings({\"os\": \"Macos\",\n                             \"compiler\": \"apple-clang\",\n                             \"compiler.version\": \"11.0\",\n                             \"arch\": arch})\n    conanfile = ConanFileMock()\n    conanfile.settings = settings\n    conanfile.settings_build = settings_build\n    conanfile.conf = config\n    assert expected == can_run(conanfile)\n\n\ndef test_can_run_cross_building_with_explicit():\n    \"\"\" When the config is True or False, and is cross-building, can_run must follow the config.\n    \"\"\"\n    config = ConfigMock(True)\n    settings_build = MockSettings({\"os\": \"Macos\",\n                                   \"compiler\": \"apple-clang\",\n                                   \"compiler.version\": \"11.0\",\n                                   \"arch\": \"armv8\"})\n    settings = MockSettings({\"os\": \"Macos\",\n                             \"compiler\": \"apple-clang\",\n                             \"compiler.version\": \"11.0\",\n                             \"arch\": \"x86_64\"})\n    conanfile = ConanFileMock()\n    conanfile.settings = settings\n    conanfile.settings_build = settings_build\n    conanfile.conf = config\n    assert True == can_run(conanfile)\n"
  },
  {
    "path": "test/unittests/tools/build/test_compiler.py",
    "content": "import pytest\n\nfrom conan.tools.build import check_min_compiler_version\nfrom conan.errors import ConanException, ConanInvalidConfiguration\nfrom conan.test.utils.mocks import MockSettings, ConanFileMock\n\n\n@pytest.mark.parametrize(\"compiler,compiler_version,restrictions,should_raise\", [\n    (\"clang\", \"14\", ((\"clang\", \"14\", \"coroutines\"), (\"gcc\", \"13\", \"alignas\")), False),\n    (\"gcc\", \"13\", ((\"clang\", \"14\", \"coroutines\"), (\"gcc\", \"13\", \"alignas\")), False),\n    (\"gcc\", \"14\", ((\"clang\", \"14\", \"coroutines\"), (\"gcc\", \"13\", \"alignas\")), False),\n    (\"msvc\", \"192\", ((\"msvc\", \"192\", \"reason\"), (\"clang\", \"14\", \"coroutines\")), False),\n\n    (\"clang\", \"13\", ((\"clang\", \"14\", \"coroutines\"), (\"gcc\", \"13\", \"alignas\")), True),\n    (\"gcc\", \"12\", ((\"clang\", \"14\", \"coroutines\"), (\"gcc\", \"13\", \"alignas\")), True),\n    (\"msvc\", \"191\", ((\"msvc\", \"192\", \"reason\"), (\"clang\", \"14\", \"coroutines\")), True),\n\n    (\"emcc\", \"1.0\", ((\"gcc\", \"13\", \"alignas\"),), False),\n    (None, \"12\", ((\"gcc\", \"13\", \"alignas\"),), True),\n    (\"gcc\", None, ((\"gcc\", \"13\", \"alignas\"),), True),\n])\ndef test_check_min_compiler_version(compiler, compiler_version, restrictions, should_raise):\n    settings = MockSettings({\"compiler\": compiler, \"compiler.version\": compiler_version})\n    conanfile = ConanFileMock(settings)\n\n    if should_raise:\n        if compiler is None or compiler_version is None:\n            with pytest.raises(ConanException):\n                check_min_compiler_version(conanfile, restrictions)\n        else:\n            with pytest.raises(ConanInvalidConfiguration):\n                check_min_compiler_version(conanfile, restrictions)\n    else:\n        check_min_compiler_version(conanfile, restrictions)\n"
  },
  {
    "path": "test/unittests/tools/build/test_cppstd.py",
    "content": "import pytest\n\nfrom conan.internal.api.detect.detect_api import detect_cppstd\nfrom conan.tools.build import supported_cppstd, check_min_cppstd, valid_min_cppstd\nfrom conan.errors import ConanException, ConanInvalidConfiguration\nfrom conan.internal.model.version import Version\nfrom conan.test.utils.mocks import MockSettings, ConanFileMock\n\n\n@pytest.mark.parametrize(\"compiler,compiler_version,values\", [\n    (\"clang\", \"2.0\", []),\n    (\"clang\", \"2.1\", ['98', 'gnu98', '11', 'gnu11']),\n    (\"clang\", \"2.2\", ['98', 'gnu98', '11', 'gnu11']),\n    (\"clang\", \"3.1\", ['98', 'gnu98', '11', 'gnu11']),\n    (\"clang\", \"3.4\", ['98', 'gnu98', '11', 'gnu11', \"14\", \"gnu14\"]),\n    (\"clang\", \"3.5\", ['98', 'gnu98', '11', 'gnu11', \"14\", \"gnu14\", \"17\", \"gnu17\"]),\n    (\"clang\", \"4.9\", ['98', 'gnu98', '11', 'gnu11', \"14\", \"gnu14\", \"17\", \"gnu17\"]),\n    (\"clang\", \"5\", ['98', 'gnu98', '11', 'gnu11', \"14\", \"gnu14\", \"17\", \"gnu17\"]),\n    (\"clang\", \"6\", ['98', 'gnu98', '11', 'gnu11', \"14\", \"gnu14\", \"17\", \"gnu17\", \"20\", \"gnu20\"]),\n    (\"clang\", \"12\", ['98', 'gnu98', '11', 'gnu11', \"14\", \"gnu14\", \"17\", \"gnu17\", \"20\",\n                     \"gnu20\", \"23\", \"gnu23\"])\n])\ndef test_supported_cppstd_clang(compiler, compiler_version, values):\n    settings = MockSettings({\"compiler\": compiler, \"compiler.version\": compiler_version})\n    conanfile = ConanFileMock(settings)\n    sot = supported_cppstd(conanfile)\n    assert sot == values\n\n\n@pytest.mark.parametrize(\"compiler,compiler_version,result\", [\n    (\"gcc\", \"5\", 'gnu98'),\n    (\"gcc\", \"8\", \"gnu14\"),\n    (\"gcc\", \"12\", \"gnu17\"),\n    (\"msvc\", \"190\", \"14\"),\n    (\"apple-clang\", \"10.0\", \"gnu98\"),\n    # We diverge from the default cppstd for apple-clang >= 11\n    (\"apple-clang\", \"12.0\", \"gnu17\"),\n    (\"clang\", \"4\", \"gnu98\"),\n    (\"clang\", \"6\", \"gnu14\"),\n    (\"clang\", \"17\", \"gnu17\")\n])\ndef test_detected_cppstd(compiler, compiler_version, result):\n    sot = detect_cppstd(compiler, Version(compiler_version))\n    assert sot == result\n\n\ndef test_supported_cppstd_with_specific_values():\n    settings = MockSettings({})\n    conanfile = ConanFileMock(settings)\n    sot = supported_cppstd(conanfile, \"clang\", \"3.1\")\n    assert sot == ['98', 'gnu98', '11', 'gnu11']\n\n\ndef test_supported_cppstd_error():\n    settings = MockSettings({})\n    conanfile = ConanFileMock(settings)\n    with pytest.raises(ConanException) as exc:\n        supported_cppstd(conanfile)\n    assert \"Called supported_cppstd with no compiler or no compiler.version\" in str(exc)\n\n\n@pytest.mark.parametrize(\"compiler,compiler_version,values\", [\n    (\"gcc\", \"2.0\", []),\n    (\"gcc\", \"3.4\", ['98', 'gnu98']),\n    (\"gcc\", \"4.2\", ['98', 'gnu98']),\n    (\"gcc\", \"4.3\", ['98', 'gnu98', '11', 'gnu11']),\n    (\"gcc\", \"4.8\", ['98', 'gnu98', '11', 'gnu11', \"14\", \"gnu14\"]),\n    (\"gcc\", \"5\", ['98', 'gnu98', '11', 'gnu11', \"14\", \"gnu14\", \"17\", \"gnu17\"]),\n    (\"gcc\", \"8\", ['98', 'gnu98', '11', 'gnu11', \"14\", \"gnu14\", \"17\", \"gnu17\", \"20\", \"gnu20\"]),\n    (\"gcc\", \"11\", ['98', 'gnu98', '11', 'gnu11', \"14\", \"gnu14\", \"17\", \"gnu17\", \"20\", \"gnu20\",\n                   \"23\", \"gnu23\"])\n])\ndef test_supported_cppstd_gcc(compiler, compiler_version, values):\n    settings = MockSettings({\"compiler\": compiler, \"compiler.version\": compiler_version})\n    conanfile = ConanFileMock(settings)\n    sot = supported_cppstd(conanfile)\n    assert sot == values\n\n\n@pytest.mark.parametrize(\"compiler,compiler_version,values\", [\n    (\"apple-clang\", \"3.9\", []),\n    (\"apple-clang\", \"4.0\", ['98', 'gnu98', '11', 'gnu11']),\n    (\"apple-clang\", \"5.0\", ['98', 'gnu98', '11', 'gnu11']),\n    (\"apple-clang\", \"5.1\", ['98', 'gnu98', '11', 'gnu11', \"14\", \"gnu14\"]),\n    (\"apple-clang\", \"6.1\", ['98', 'gnu98', '11', 'gnu11', \"14\", \"gnu14\", \"17\", \"gnu17\"]),\n    (\"apple-clang\", \"9.5\", ['98', 'gnu98', '11', 'gnu11', \"14\", \"gnu14\", \"17\", \"gnu17\"]),\n    (\"apple-clang\", \"10\", ['98', 'gnu98', '11', 'gnu11', \"14\", \"gnu14\", \"17\", \"gnu17\", \"20\",\n                           \"gnu20\"]),\n    (\"apple-clang\", \"13\", ['98', 'gnu98', '11', 'gnu11', \"14\", \"gnu14\", \"17\", \"gnu17\", \"20\",\n                           \"gnu20\", \"23\", \"gnu23\"]),\n])\ndef test_supported_cppstd_apple_clang(compiler, compiler_version, values):\n    settings = MockSettings({\"compiler\": compiler, \"compiler.version\": compiler_version})\n    conanfile = ConanFileMock(settings)\n    sot = supported_cppstd(conanfile)\n    assert sot == values\n\n\n@pytest.mark.parametrize(\"compiler,compiler_version,values\", [\n    (\"msvc\", \"180\", []),\n    (\"msvc\", \"190\", ['14']),\n    (\"msvc\", \"191\", ['14', '17']),\n    (\"msvc\", \"192\", ['14', '17', '20']),\n    (\"msvc\", \"193\", ['14', '17', '20', '23']),\n])\ndef test_supported_cppstd_msvc(compiler, compiler_version, values):\n    settings = MockSettings({\"compiler\": compiler, \"compiler.version\": compiler_version})\n    conanfile = ConanFileMock(settings)\n    sot = supported_cppstd(conanfile)\n    assert sot == values\n\n\n@pytest.mark.parametrize(\"compiler,compiler_version,values\", [\n    (\"mcst-lcc\", \"1.20\", ['98', 'gnu98']),\n    (\"mcst-lcc\", \"1.21\", ['98', 'gnu98', '11', 'gnu11', \"14\", \"gnu14\"]),\n    (\"mcst-lcc\", \"1.23\", ['98', 'gnu98', '11', 'gnu11', \"14\", \"gnu14\"]),\n    (\"mcst-lcc\", \"1.24\", ['98', 'gnu98', '11', 'gnu11', \"14\", \"gnu14\", \"17\", \"gnu17\"]),\n    (\"mcst-lcc\", \"1.25\", ['98', 'gnu98', '11', 'gnu11', \"14\", \"gnu14\", \"17\", \"gnu17\", \"20\", \"gnu20\"])\n])\ndef test_supported_cppstd_mcst(compiler, compiler_version, values):\n    settings = MockSettings({\"compiler\": compiler, \"compiler.version\": compiler_version})\n    conanfile = ConanFileMock(settings)\n    sot = supported_cppstd(conanfile)\n    assert sot == values\n\n\n@pytest.mark.parametrize(\"compiler,compiler_version,values\", [\n    (\"qcc\", \"4.4\", ['98', 'gnu98']),\n    (\"qcc\", \"5.4\", ['98', 'gnu98', '11', 'gnu11', \"14\", \"gnu14\", \"17\", \"gnu17\"]),\n    (\"qcc\", \"8.3\", ['98', 'gnu98', '11', 'gnu11', \"14\", \"gnu14\", \"17\", \"gnu17\"]),\n    (\"qcc\", \"12.2\", ['98', 'gnu98', '11', 'gnu11', \"14\", \"gnu14\", \"17\", \"gnu17\", \"20\", \"gnu20\"]),\n])\ndef test_supported_cppstd_qcc(compiler, compiler_version, values):\n    settings = MockSettings({\"compiler\": compiler, \"compiler.version\": compiler_version})\n    conanfile = ConanFileMock(settings)\n    sot = supported_cppstd(conanfile)\n    assert sot == values\n\n\n@pytest.mark.parametrize(\"compiler,compiler_version,values\", [\n    (\"emcc\", \"3\", [\"98\", \"gnu98\", \"11\", \"gnu11\", \"14\", \"gnu14\", \"17\", \"gnu17\",\n                   \"20\", \"gnu20\", \"23\", \"gnu23\"]),\n    (\"emcc\", \"3.1\", [\"98\", \"gnu98\", \"11\", \"gnu11\", \"14\", \"gnu14\", \"17\", \"gnu17\",\n                     \"20\", \"gnu20\", \"23\", \"gnu23\", \"26\", \"gnu26\"]),\n    (\"emcc\", \"3.3\", [\"98\", \"gnu98\", \"11\", \"gnu11\", \"14\", \"gnu14\", \"17\", \"gnu17\",\n                     \"20\", \"gnu20\", \"23\", \"gnu23\", \"26\", \"gnu26\"]),\n    (\"emcc\", \"4.1\", [\"98\", \"gnu98\", \"11\", \"gnu11\", \"14\", \"gnu14\", \"17\", \"gnu17\",\n                     \"20\", \"gnu20\", \"23\", \"gnu23\", \"26\", \"gnu26\"]),\n])\ndef test_supported_cppstd_emcc(compiler, compiler_version, values):\n    settings = MockSettings({\"compiler\": compiler, \"compiler.version\": compiler_version})\n    conanfile = ConanFileMock(settings)\n    sot = supported_cppstd(conanfile)\n    assert sot == values\n\n\ndef test_check_cppstd_type():\n    \"\"\" cppstd must be a number\n    \"\"\"\n    conanfile = ConanFileMock(MockSettings({}))\n    with pytest.raises(ConanException) as exc:\n        check_min_cppstd(conanfile, \"gnu17\", False)\n\n    assert \"cppstd parameter must be a number\", str(exc)\n\n\ndef _create_conanfile(compiler, version, os, cppstd, libcxx=None):\n    settings = MockSettings({\"arch\": \"x86_64\",\n                             \"build_type\": \"Debug\",\n                             \"os\": os,\n                             \"compiler\": compiler,\n                             \"compiler.version\": version,\n                             \"compiler.cppstd\": cppstd})\n    if libcxx:\n        settings.values[\"compiler.libcxx\"] = libcxx\n    conanfile = ConanFileMock(settings)\n    return conanfile\n\n\n@pytest.mark.parametrize(\"cppstd\", [\"98\", \"11\", \"14\", \"17\"])\ndef test_check_min_cppstd_from_settings(cppstd):\n    \"\"\" check_min_cppstd must accept cppstd less/equal than cppstd in settings\n    \"\"\"\n    conanfile = _create_conanfile(\"gcc\", \"9\", \"Linux\", \"17\", \"libstdc++\")\n    check_min_cppstd(conanfile, cppstd, False)\n\n\n@pytest.mark.parametrize(\"cppstd\", [\"98\", \"11\", \"14\"])\ndef test_check_min_cppstd_from_outdated_settings(cppstd):\n    \"\"\" check_min_cppstd must raise when cppstd is greater when supported on settings\n    \"\"\"\n    conanfile = _create_conanfile(\"gcc\", \"9\", \"Linux\", cppstd, \"libstdc++\")\n    with pytest.raises(ConanInvalidConfiguration) as exc:\n        check_min_cppstd(conanfile, \"17\", False)\n    assert \"Current cppstd ({}) is lower than the required C++ standard (17).\" \\\n           \"\".format(cppstd) == str(exc.value)\n\n\n@pytest.mark.parametrize(\"cppstd\", [\"98\", \"11\", \"14\", \"17\"])\ndef test_check_min_cppstd_from_settings_with_extension(cppstd):\n    \"\"\" current cppstd in settings must has GNU extension when extensions is enabled\n    \"\"\"\n    conanfile = _create_conanfile(\"gcc\", \"9\", \"Linux\", \"gnu17\", \"libstdc++\")\n    check_min_cppstd(conanfile, cppstd, True)\n\n    conanfile.settings.values[\"compiler.cppstd\"] = \"17\"\n    with pytest.raises(ConanException) as raises:\n        check_min_cppstd(conanfile, cppstd, True)\n    assert \"The cppstd GNU extension is required\" == str(raises.value)\n\n\n@pytest.mark.parametrize(\"cppstd\", [\"98\", \"11\", \"14\", \"17\"])\ndef test_valid_min_cppstd_from_settings(cppstd):\n    \"\"\" valid_min_cppstd must accept cppstd less/equal than cppstd in settings\n    \"\"\"\n    conanfile = _create_conanfile(\"gcc\", \"9\", \"Linux\", \"17\", \"libstdc++\")\n    assert valid_min_cppstd(conanfile, cppstd, False)\n\n\n@pytest.mark.parametrize(\"cppstd\", [\"98\", \"11\", \"14\"])\ndef test_valid_min_cppstd_from_outdated_settings(cppstd):\n    \"\"\" valid_min_cppstd returns False when cppstd is greater when supported on settings\n    \"\"\"\n    conanfile = _create_conanfile(\"gcc\", \"9\", \"Linux\", cppstd, \"libstdc++\")\n    assert not valid_min_cppstd(conanfile, \"17\", False)\n\n\n@pytest.mark.parametrize(\"cppstd\", [\"98\", \"11\", \"14\", \"17\"])\ndef test_valid_min_cppstd_from_settings_with_extension(cppstd):\n    \"\"\" valid_min_cppstd must returns True when current cppstd in settings has GNU extension and\n        extensions is enabled\n    \"\"\"\n    conanfile = _create_conanfile(\"gcc\", \"9\", \"Linux\", \"gnu17\", \"libstdc++\")\n    assert valid_min_cppstd(conanfile, cppstd, True)\n\n    conanfile.settings.values[\"compiler.cppstd\"] = \"17\"\n    assert not valid_min_cppstd(conanfile, cppstd, True)\n\n\ndef test_valid_min_cppstd_unsupported_standard():\n    \"\"\" valid_min_cppstd must returns False when the compiler does not support a standard\n    \"\"\"\n    conanfile = _create_conanfile(\"gcc\", \"9\", \"Linux\", None, \"libstdc++\")\n    assert not valid_min_cppstd(conanfile, \"42\", False)\n"
  },
  {
    "path": "test/unittests/tools/build/test_cross_building.py",
    "content": "import pytest\n\nfrom conan.tools.build import cross_building\nfrom conan.test.utils.mocks import ConanFileMock\n\n\n@pytest.mark.parametrize(\"cross_build\", (True, False))\ndef test_using_cross_build_conf(cross_build):\n    \"\"\"\n    Tests cross_building function is using the conf variable to force or not.\n\n    Issue related: https://github.com/conan-io/conan/issues/15392\n    \"\"\"\n    conanfile = ConanFileMock()\n    conanfile.conf.define(\"tools.build.cross_building:cross_build\", cross_build)\n    assert cross_building(conanfile) == cross_build\n"
  },
  {
    "path": "test/unittests/tools/build/test_cstd.py",
    "content": "import pytest\n\nfrom conan.tools.build import supported_cstd, check_min_cstd\nfrom conan.errors import ConanException\nfrom conan.test.utils.mocks import MockSettings, ConanFileMock\n\n\n@pytest.mark.parametrize(\"compiler,compiler_version,values\", [\n    (\"clang\", \"2.1\", ['99', 'gnu99']),\n    (\"clang\", \"5\", ['99', 'gnu99', '11', 'gnu11']),\n    (\"clang\", \"17\", ['99', 'gnu99', '11', 'gnu11', \"17\", \"gnu17\"]),\n    (\"clang\", \"18\", ['99', 'gnu99', '11', 'gnu11',  \"17\", \"gnu17\", \"23\", \"gnu23\"])\n])\ndef test_supported_cstd_clang(compiler, compiler_version, values):\n    settings = MockSettings({\"compiler\": compiler, \"compiler.version\": compiler_version})\n    conanfile = ConanFileMock(settings)\n    sot = supported_cstd(conanfile)\n    assert sot == values\n\n\ndef test_supported_cstd_with_specific_values():\n    settings = MockSettings({})\n    conanfile = ConanFileMock(settings)\n    sot = supported_cstd(conanfile, \"clang\", \"5\")\n    assert sot == ['99', 'gnu99', '11', 'gnu11']\n\n\ndef test_supported_cstd_error():\n    settings = MockSettings({})\n    conanfile = ConanFileMock(settings)\n    with pytest.raises(ConanException) as exc:\n        supported_cstd(conanfile)\n    assert \"Called supported_cstd with no compiler or no compiler.version\" in str(exc)\n\n\n@pytest.mark.parametrize(\"compiler,compiler_version,values\", [\n    (\"gcc\", \"4.6\", ['99', 'gnu99']),\n    (\"gcc\", \"5\", ['99', 'gnu99', '11', 'gnu11']),\n    (\"gcc\", \"13\", [\"99\", \"gnu99\", \"11\", \"gnu11\", \"17\", \"gnu17\"]),\n    (\"gcc\", \"14\", [\"99\", \"gnu99\", \"11\", \"gnu11\", \"17\", \"gnu17\", \"23\", \"gnu23\"])\n])\ndef test_supported_cppstd_gcc(compiler, compiler_version, values):\n    settings = MockSettings({\"compiler\": compiler, \"compiler.version\": compiler_version})\n    conanfile = ConanFileMock(settings)\n    sot = supported_cstd(conanfile)\n    assert sot == values\n\n\n@pytest.mark.parametrize(\"compiler,compiler_version,values\", [\n    (\"msvc\", \"191\", []),\n    (\"msvc\", \"193\", ['11', '17']),\n])\ndef test_supported_cstd_msvc(compiler, compiler_version, values):\n    settings = MockSettings({\"compiler\": compiler, \"compiler.version\": compiler_version})\n    conanfile = ConanFileMock(settings)\n    sot = supported_cstd(conanfile)\n    assert sot == values\n\n\n@pytest.mark.parametrize(\"compiler,compiler_version,values\", [\n    (\"emcc\", \"3\", [\"99\", \"gnu99\", \"11\", \"gnu11\", \"17\", \"gnu17\"]),\n    (\"emcc\", \"3.1\", [\"99\", \"gnu99\", \"11\", \"gnu11\", \"17\", \"gnu17\", \"23\", \"gnu23\"]),\n    (\"emcc\", \"3.3\", [\"99\", \"gnu99\", \"11\", \"gnu11\", \"17\", \"gnu17\", \"23\", \"gnu23\"]),\n    (\"emcc\", \"4.1\", [\"99\", \"gnu99\", \"11\", \"gnu11\", \"17\", \"gnu17\", \"23\", \"gnu23\"]),\n])\ndef test_supported_cstd_emcc(compiler, compiler_version, values):\n    settings = MockSettings({\"compiler\": compiler, \"compiler.version\": compiler_version})\n    conanfile = ConanFileMock(settings)\n    sot = supported_cstd(conanfile)\n    assert sot == values\n\n\ndef test_check_cstd_type():\n    \"\"\" cppstd must be a number\n    \"\"\"\n    conanfile = ConanFileMock(MockSettings({}))\n    with pytest.raises(ConanException) as exc:\n        check_min_cstd(conanfile, \"gnu17\", False)\n\n    assert \"cstd parameter must be a number\", str(exc)\n"
  },
  {
    "path": "test/unittests/tools/build/test_stdcpp_library.py",
    "content": "import pytest\nfrom conan.tools.build import stdcpp_library\nfrom conan.test.utils.mocks import MockSettings, ConanFileMock\n\n\n@pytest.mark.parametrize(\"libcxx,expected_library\", [\n    (\"libstdc++\", \"stdc++\"),\n    (\"libstdc++11\", \"stdc++\"),\n    (\"libc++\", \"c++\"),\n    (\"c++_shared\", \"c++_shared\"),\n    (\"c++_static\", \"c++_static\"),\n    (\"foobar\", None)\n])\ndef test_stdcpp_library(libcxx, expected_library):\n    settings = MockSettings({\"compiler.libcxx\": libcxx})\n    conanfile = ConanFileMock(settings)\n\n    assert stdcpp_library(conanfile) == expected_library\n"
  },
  {
    "path": "test/unittests/tools/cmake/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/tools/cmake/test_cmake_cmd_line_args.py",
    "content": "import textwrap\n\nimport pytest\n\nfrom conan.tools.cmake.cmake import _cmake_cmd_line_args\nfrom conan.internal.model.conf import ConfDefinition\nfrom conan.test.utils.mocks import ConanFileMock\n\n\n@pytest.fixture\ndef conanfile():\n    c = ConfDefinition()\n    c.loads(textwrap.dedent(\"\"\"\\\n        tools.build:jobs=10\n        tools.microsoft.msbuild:max_cpu_count=23\n    \"\"\"))\n\n    conanfile = ConanFileMock()\n    conanfile.conf = c.get_conanfile_conf(None)\n    return conanfile\n\n\ndef test_no_generator(conanfile):\n    args = _cmake_cmd_line_args(conanfile, None)\n    assert not len(args)\n\n\ndef test_makefiles(conanfile):\n    args = _cmake_cmd_line_args(conanfile, 'Unix Makefiles')\n    assert args == ['-j10']\n\n    args = _cmake_cmd_line_args(conanfile, 'NMake Makefiles')\n    assert not len(args)\n\n\ndef test_ninja(conanfile):\n    args = _cmake_cmd_line_args(conanfile, 'Ninja')\n    assert ['-j10'] == args\n\n\ndef test_visual_studio(conanfile):\n    args = _cmake_cmd_line_args(conanfile, 'Visual Studio 16 2019')\n    assert [\"/m:23\"] == args\n\n    args = _cmake_cmd_line_args(conanfile, 'Ninja')\n    assert args == ['-j10']\n\n\ndef test_maxcpucount_zero():\n    c = ConfDefinition()\n    c.loads(\"tools.microsoft.msbuild:max_cpu_count=0\")\n\n    conanfile = ConanFileMock()\n    conanfile.conf = c.get_conanfile_conf(None)\n    args = _cmake_cmd_line_args(conanfile, 'Visual Studio 16 2019')\n    assert [\"/m\"] == args\n"
  },
  {
    "path": "test/unittests/tools/cmake/test_cmake_install.py",
    "content": "import pytest\n\nfrom conan.internal.default_settings import default_settings_yml\nfrom conan.tools.cmake import CMake\nfrom conan.tools.cmake.presets import write_cmake_presets\nfrom conan.internal.model.conf import Conf\nfrom conan.internal.model.settings import Settings\nfrom conan.test.utils.mocks import ConanFileMock, RedirectedTestOutput\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import redirect_output\n\n\ndef test_run_install_component():\n    \"\"\"\n    Testing that the proper component is installed.\n    Issue related: https://github.com/conan-io/conan/issues/10359\n    \"\"\"\n    # Load some generic windows settings\n    settings = Settings.loads(default_settings_yml)\n    settings.os = \"Windows\"\n    settings.arch = \"x86\"\n    settings.build_type = \"Release\"\n    settings.compiler = \"msvc\"\n    settings.compiler.runtime = \"dynamic\"\n    settings.compiler.version = \"190\"\n\n    conanfile = ConanFileMock()\n    conanfile.conf = Conf()\n    conanfile.folders.generators = \".\"\n    conanfile.folders.set_base_generators(temp_folder())\n    conanfile.settings = settings\n    conanfile.folders.set_base_package(temp_folder())\n\n    # Choose generator to match generic settings\n    write_cmake_presets(conanfile, \"toolchain\", \"Visual Studio 14 2015\", {})\n    cmake = CMake(conanfile)\n    cmake.install(component=\"foo\")\n\n    assert \"--component foo\" in conanfile.command\n\n\n@pytest.mark.parametrize(\"config, deprecated\",\n                         [(\"tools.cmake:install_strip\", True),\n                          (\"tools.build:install_strip\", False),])\ndef test_run_install_strip(config, deprecated):\n    \"\"\"\n    Testing that the install/strip rule is called\n    Issue related: https://github.com/conan-io/conan/issues/14166\n    \"\"\"\n\n    settings = Settings.loads(default_settings_yml)\n    settings.os = \"Linux\"\n    settings.arch = \"x86_64\"\n    settings.build_type = \"Release\"\n    settings.compiler = \"gcc\"\n    settings.compiler.version = \"11\"\n\n    conanfile = ConanFileMock()\n\n    conanfile.conf = Conf()\n    conanfile.conf.define(config, True)\n\n    conanfile.folders.generators = \".\"\n    conanfile.folders.set_base_generators(temp_folder())\n    conanfile.settings = settings\n    conanfile.folders.set_base_package(temp_folder())\n\n    write_cmake_presets(conanfile, \"toolchain\", \"Unix Makefiles\", {})\n    cmake = CMake(conanfile)\n    stdout = RedirectedTestOutput()  # Initialize each command\n    stderr = RedirectedTestOutput()\n    with redirect_output(stderr, stdout):\n        cmake.install(stdout=stdout, stderr=stderr)\n\n    if deprecated:\n        assert \"WARN: deprecated: The 'tools.cmake:install_strip' configuration is deprecated, use\"\\\n               \" 'tools.build:install_strip' instead\" in stderr\n    else:\n        assert \"tools.cmake:install_strip\" not in stderr\n    assert \"--strip\" in conanfile.command\n\n\ndef test_run_install_cli_args():\n    \"\"\"\n    Testing that the passing cli_args to install works\n    Issue related: https://github.com/conan-io/conan/issues/14235\n    \"\"\"\n\n    settings = Settings.loads(default_settings_yml)\n    settings.os = \"Linux\"\n    settings.arch = \"x86_64\"\n    settings.build_type = \"Release\"\n    settings.compiler = \"gcc\"\n    settings.compiler.version = \"11\"\n\n    conanfile = ConanFileMock()\n\n    conanfile.conf = Conf()\n\n    conanfile.folders.generators = \".\"\n    conanfile.folders.set_base_generators(temp_folder())\n    conanfile.settings = settings\n    conanfile.folders.set_base_package(temp_folder())\n\n    write_cmake_presets(conanfile, \"toolchain\", \"Unix Makefiles\", {})\n    cmake = CMake(conanfile)\n    cmake.install(cli_args=[\"--prefix=/tmp\"])\n    assert \"--prefix=/tmp\" in conanfile.command\n\n\ndef test_run_install_cli_args_strip():\n    \"\"\"\n    Testing that the install/strip rule is called when using cli_args\n    Issue related: https://github.com/conan-io/conan/issues/14235\n    \"\"\"\n\n    settings = Settings.loads(default_settings_yml)\n    settings.os = \"Linux\"\n    settings.arch = \"x86_64\"\n    settings.build_type = \"Release\"\n    settings.compiler = \"gcc\"\n    settings.compiler.version = \"11\"\n\n    conanfile = ConanFileMock()\n\n    conanfile.conf = Conf()\n\n    conanfile.folders.generators = \".\"\n    conanfile.folders.set_base_generators(temp_folder())\n    conanfile.settings = settings\n    conanfile.folders.set_base_package(temp_folder())\n\n    write_cmake_presets(conanfile, \"toolchain\", \"Unix Makefiles\", {})\n    cmake = CMake(conanfile)\n    cmake.install(cli_args=[\"--strip\"])\n    assert \"--strip\" in conanfile.command\n"
  },
  {
    "path": "test/unittests/tools/cmake/test_cmake_presets_definitions.py",
    "content": "import pytest\nfrom unittest import mock\n\nfrom conan.tools.cmake import CMake\nfrom conan.tools.cmake.presets import write_cmake_presets\nfrom conan.internal.model.conan_file import ConanFile\nfrom conan.internal.model.conf import Conf\nfrom conan.internal.model.settings import Settings\nfrom conan.test.utils.test_files import temp_folder\n\n\n@pytest.fixture(scope=\"module\")\ndef conanfile():\n    c = ConanFile(\"\")\n    c.settings = Settings({\"os\": [\"Windows\"],\n                           \"compiler\": {\"gcc\": {\"libcxx\": [\"libstdc++\"]}},\n                           \"build_type\": [\"Release\"],\n                           \"arch\": [\"x86\"]})\n    c.settings.build_type = \"Release\"\n    c.settings.arch = \"x86\"\n    c.settings.compiler = \"gcc\"\n    c.settings.compiler.libcxx = \"libstdc++\"\n    c.settings.os = \"Windows\"\n    c.conf = Conf()\n    tmp_folder = temp_folder()\n    c.folders.set_base_generators(tmp_folder)\n    c.folders.generators = \".\"\n    c.folders.set_base_build(tmp_folder)\n    return c\n\n\ndef test_cmake_cmake_program(conanfile):\n    mycmake = \"C:\\\\mycmake.exe\"\n    conanfile.conf.define(\"tools.cmake:cmake_program\", mycmake)\n\n    with mock.patch(\"platform.system\", mock.MagicMock(return_value='Windows')):\n        write_cmake_presets(conanfile, \"the_toolchain.cmake\", \"MinGW Makefiles\", {})\n\n    cmake = CMake(conanfile)\n    assert cmake._cmake_program == mycmake\n\n\ndef test_cmake_make_program(conanfile):\n    def run(command, **kwargs):\n        assert '-DCMAKE_MAKE_PROGRAM=\"C:/mymake.exe\"' in command\n\n    conanfile.run = run\n    conanfile.folders.set_base_source(temp_folder())\n    conanfile.conf.define(\"tools.gnu:make_program\", \"C:\\\\mymake.exe\")\n\n    with mock.patch(\"platform.system\", mock.MagicMock(return_value='Windows')):\n        write_cmake_presets(conanfile, \"the_toolchain.cmake\", \"MinGW Makefiles\", {})\n\n    cmake = CMake(conanfile)\n    cmake.configure()\n"
  },
  {
    "path": "test/unittests/tools/cmake/test_cmake_test.py",
    "content": "import pytest\n\nfrom conan.internal.default_settings import default_settings_yml\nfrom conan.tools.cmake import CMake\nfrom conan.tools.cmake.presets import write_cmake_presets\nfrom conan.internal.model.conf import Conf\nfrom conan.internal.model.settings import Settings\nfrom conan.test.utils.mocks import ConanFileMock\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.tools.cmake.utils import cmake_escape_value\n\n\n@pytest.mark.parametrize(\"generator,target\", [\n    (\"NMake Makefiles\", \"test\"),\n    (\"Ninja Makefiles\", \"test\"),\n    (\"Ninja Multi-Config\", \"test\"),\n    (\"Unix Makefiles\", \"test\"),\n    (\"Visual Studio 14 2015\", \"RUN_TESTS\"),\n    (\"Xcode\", \"RUN_TESTS\"),\n])\ndef test_run_tests(generator, target):\n    \"\"\"\n    Testing that the proper test target is picked for different generators, especially\n    multi-config ones.\n    Issue related: https://github.com/conan-io/conan/issues/11405\n    \"\"\"\n    settings = Settings.loads(default_settings_yml)\n    settings.os = \"Windows\"\n    settings.arch = \"x86\"\n    settings.build_type = \"Release\"\n    settings.compiler = \"msvc\"\n    settings.compiler.runtime = \"dynamic\"\n    settings.compiler.version = \"193\"\n\n    conanfile = ConanFileMock()\n    conanfile.conf = Conf()\n    conanfile.folders.generators = \".\"\n    conanfile.folders.set_base_generators(temp_folder())\n    conanfile.settings = settings\n\n    write_cmake_presets(conanfile, \"toolchain\", generator, {})\n    cmake = CMake(conanfile)\n    cmake.test()\n\n    search_pattern = \"--target {}\"\n    assert search_pattern.format(target) in conanfile.command\n\n\ndef test_cli_args_configure():\n    settings = Settings.loads(default_settings_yml)\n\n    conanfile = ConanFileMock()\n    conanfile.conf = Conf()\n    conanfile.folders.generators = \".\"\n    conanfile.folders.set_base_generators(temp_folder())\n    conanfile.settings = settings\n\n    write_cmake_presets(conanfile, \"toolchain\", \"Unix Makefiles\", {})\n    cmake = CMake(conanfile)\n    cmake.configure(cli_args=[\"--graphviz=foo.dot\"])\n    assert \"--graphviz=foo.dot\" in conanfile.command\n\n\ndef test_run_ctest():\n    settings = Settings.loads(default_settings_yml)\n    settings.os = \"Windows\"\n    settings.arch = \"x86\"\n    settings.build_type = \"Release\"\n    settings.compiler = \"msvc\"\n    settings.compiler.runtime = \"dynamic\"\n    settings.compiler.version = \"193\"\n\n    conanfile = ConanFileMock()\n    conanfile.conf = Conf()\n    conanfile.conf.define(\"tools.cmake:ctest_args\", [\"--debug\", \"--output-junit myfile\"])\n    conanfile.conf.define(\"tools.build:verbosity\", \"verbose\")\n\n    conanfile.folders.generators = \".\"\n    conanfile.folders.set_base_generators(temp_folder())\n    conanfile.settings = settings\n\n    write_cmake_presets(conanfile, \"toolchain\", \"Ninja\", {})\n    cmake = CMake(conanfile)\n    cmake.ctest(cli_args=[\"--schedule-random\", \"--quiet\"])\n    assert \"--schedule-random --quiet --verbose --debug --output-junit myfile\" in conanfile.command\n"
  },
  {
    "path": "test/unittests/tools/cmake/test_cmaketoolchain.py",
    "content": "import types\n\nimport pytest\nfrom unittest.mock import Mock\n\nfrom conan import ConanFile\nfrom conan.internal.default_settings import default_settings_yml\nfrom conan.tools.cmake import CMakeToolchain\nfrom conan.tools.cmake.toolchain.blocks import Block\nfrom conan.errors import ConanException\nfrom conan.internal.model.conf import Conf\nfrom conan.internal.model.options import Options\nfrom conan.internal.model.settings import Settings\n\n\n@pytest.fixture\ndef base_conanfile():\n    c = ConanFile()\n    settings = Settings.loads(default_settings_yml)\n    c.settings = settings\n    c.settings.build_type = \"Release\"\n    c.settings.arch = \"x86\"\n    c.settings.compiler = \"clang\"\n    c.settings.compiler.libcxx = \"libstdc++\"\n    c.settings_build = c.settings\n    c.settings.os = \"Windows\"\n    c.conf = Conf()\n    c.folders.set_base_generators(\".\")  # non-existing to not relativize\n    conan_node = Mock()\n    conan_node.dependencies = []\n    conan_node.transitive_deps = {}\n    conan_node.replaced_requires = {}\n    c._conan_node = conan_node\n    return c\n\n\n@pytest.fixture\ndef conanfile(base_conanfile):\n    c = base_conanfile\n    c.conf.define(\"tools.cmake.cmaketoolchain:system_name\", \"potato\")\n    return c\n\n\nclass TestGenericBlocks:\n    \"\"\" Tests general toolchain blocks operations, enabling, disabling, customizing\n    \"\"\"\n    def test_remove(self, conanfile):\n        toolchain = CMakeToolchain(conanfile)\n        toolchain.blocks.remove(\"generic_system\")\n        content = toolchain.content\n        assert 'CMAKE_SYSTEM_NAME' not in content\n        assert \"CMAKE_CXX_FLAGS_INIT\" in content\n        assert \"_CMAKE_IN_TRY_COMPILE\" in content\n\n        # remove multiple\n        toolchain = CMakeToolchain(conanfile)\n        toolchain.blocks.remove(\"generic_system\", \"cmake_flags_init\")\n        content = toolchain.content\n        assert 'CMAKE_SYSTEM_NAME' not in content\n        assert \"CMAKE_CXX_FLAGS_INIT\" not in content\n        assert \"_CMAKE_IN_TRY_COMPILE\" in content\n\n    def test_select_blocks(self, conanfile):\n        toolchain = CMakeToolchain(conanfile)\n        toolchain.blocks.select(\"generic_system\")\n        content = toolchain.content\n        assert \"########## 'generic_system' block #############\" in content\n        assert \"########## 'cmake_flags_init' block #############\" not in content\n        assert \"########## 'libcxx' block #############\" not in content\n        # These are not removed by default, to not break behavior\n        assert \"########## 'variables' block #############\" in content\n        assert \"########## 'preprocessor' block #############\" in content\n        assert 'CMAKE_SYSTEM_NAME' in content\n        assert \"CMAKE_CXX_FLAGS_INIT\" not in content\n        assert \"_CMAKE_IN_TRY_COMPILE\" not in content\n\n        # remove multiple\n        toolchain = CMakeToolchain(conanfile)\n        toolchain.blocks.select(\"generic_system\", \"cmake_flags_init\")\n        content = toolchain.content\n        assert \"########## 'generic_system' block #############\" in content\n        assert \"########## 'cmake_flags_init' block #############\" in content\n        assert \"########## 'libcxx' block #############\" not in content\n        # These are not removed by default, to not break behavior\n        assert \"########## 'variables' block #############\" in content\n        assert \"########## 'preprocessor' block #############\" in content\n        assert 'CMAKE_SYSTEM_NAME' in content\n        assert \"CMAKE_CXX_FLAGS_INIT\" in content\n        assert \"_CMAKE_IN_TRY_COMPILE\" not in content\n\n        # remove multiple\n        toolchain = CMakeToolchain(conanfile)\n        toolchain.blocks.enabled(\"generic_system\")\n        content = toolchain.content\n        assert \"########## 'generic_system' block #############\" in content\n        assert \"########## 'variables' block #############\" not in content\n        assert \"########## 'preprocessor' block #############\" not in content\n\n    def test_enabled_blocks_conf(self, conanfile):\n        conanfile.conf.define(\"tools.cmake.cmaketoolchain:enabled_blocks\", [\"generic_system\"])\n        toolchain = CMakeToolchain(conanfile)\n        content = toolchain.content\n        assert \"########## 'generic_system' block #############\" in content\n        assert \"########## 'cmake_flags_init' block #############\" not in content\n        assert \"########## 'libcxx' block #############\" not in content\n        assert \"########## 'variables' block #############\" not in content\n        assert \"########## 'preprocessor' block #############\" not in content\n\n        # remove multiple\n        conanfile.conf.define(\"tools.cmake.cmaketoolchain:enabled_blocks\",\n                              [\"generic_system\", \"cmake_flags_init\"])\n        toolchain = CMakeToolchain(conanfile)\n        content = toolchain.content\n        assert \"########## 'generic_system' block #############\" in content\n        assert \"########## 'cmake_flags_init' block #############\" in content\n        assert \"########## 'libcxx' block #############\" not in content\n        assert \"########## 'variables' block #############\" not in content\n        assert \"########## 'preprocessor' block #############\" not in content\n\n        conanfile.conf.define(\"tools.cmake.cmaketoolchain:enabled_blocks\", [\"potato\"])\n        toolchain = CMakeToolchain(conanfile)\n        with pytest.raises(ConanException) as e:\n            _ = toolchain.content\n        assert \"Block 'potato' defined in tools.cmake.cmaketoolchain:enabled_blocks\" in str(e)\n\n    def test_dict_keys(self, conanfile):\n        toolchain = CMakeToolchain(conanfile)\n        assert \"generic_system\" in toolchain.blocks.keys()\n        items = dict(toolchain.blocks.items())\n        assert \"generic_system\" in items\n\n    def test_template_remove(self, conanfile):\n        toolchain = CMakeToolchain(conanfile)\n        toolchain.blocks[\"generic_system\"].template = \"\"\n        content = toolchain.content\n        assert 'CMAKE_SYSTEM_NAME' not in content\n\n    def test_template_change(self, conanfile):\n        toolchain = CMakeToolchain(conanfile)\n        tmp = toolchain.blocks[\"generic_system\"].template\n        toolchain.blocks[\"generic_system\"].template = tmp.replace(\"CMAKE_SYSTEM_NAME\", \"OTHER_THING\")\n        content = toolchain.content\n        assert 'set(OTHER_THING potato)' in content\n\n    def test_context_change(self, conanfile):\n        toolchain = CMakeToolchain(conanfile)\n        tmp = toolchain.blocks[\"generic_system\"]\n\n        def context(self_):\n            assert self_\n            return {\"cmake_system_name\": None}\n\n        tmp.context = types.MethodType(context, tmp)\n        content = toolchain.content\n        assert 'CMAKE_SYSTEM_NAME' not in content\n\n    def test_context_update(self, conanfile):\n        toolchain = CMakeToolchain(conanfile)\n        cmake_system_name = toolchain.blocks[\"generic_system\"].values[\"cmake_system_name\"]\n        toolchain.blocks[\"generic_system\"].values[\"cmake_system_name\"] = \"Super\" + cmake_system_name\n        content = toolchain.content\n        assert 'set(CMAKE_SYSTEM_NAME Superpotato)' in content\n\n    def test_context_replace(self, conanfile):\n        toolchain = CMakeToolchain(conanfile)\n        toolchain.blocks[\"generic_system\"].values = {\"cmake_system_name\": \"SuperPotato\"}\n        content = toolchain.content\n        assert 'set(CMAKE_SYSTEM_NAME SuperPotato)' in content\n\n    def test_replace_block(self, conanfile):\n        toolchain = CMakeToolchain(conanfile)\n\n        class MyBlock(Block):\n            template = \"HelloWorld\"\n\n            def context(self):\n                return {}\n\n        toolchain.blocks[\"generic_system\"] = MyBlock\n        content = toolchain.content\n        assert 'HelloWorld' in content\n        assert 'set(CMAKE_SYSTEM_NAME potato)' not in content\n\n    def test_add_new_block(self, conanfile):\n        toolchain = CMakeToolchain(conanfile)\n\n        class MyBlock(Block):\n            template = \"Hello {{myvar}}!!!\"\n\n            def context(self):\n                return {\"myvar\": \"World\"}\n\n        toolchain.blocks[\"mynewblock\"] = MyBlock\n        content = toolchain.content\n        assert 'Hello World!!!' in content\n        assert 'set(CMAKE_SYSTEM_NAME potato)' in content\n\n    def test_user_toolchain(self, conanfile):\n        toolchain = CMakeToolchain(conanfile)\n        toolchain.blocks[\"user_toolchain\"].values[\"paths\"] = [\"myowntoolchain.cmake\"]\n        content = toolchain.content\n        assert 'include(\"myowntoolchain.cmake\")' in content\n\n\nclass TestBlocksFunctionality:\n    def test_cmake_toolchain(self, conanfile):\n        toolchain = CMakeToolchain(conanfile)\n        content = toolchain.content\n        assert 'set(CMAKE_SYSTEM_NAME potato)' in content\n\n    def test_compilers_block(self, conanfile):\n        cmake_mapping = {\"c\": \"C\", \"cuda\": \"CUDA\", \"cpp\": \"CXX\", \"objc\": \"OBJC\",\n                         \"objcpp\": \"OBJCXX\", \"rc\": \"RC\", 'fortran': \"Fortran\", 'asm': \"ASM\",\n                         \"hip\": \"HIP\", \"ispc\": \"ISPC\"}\n        compilers = {\"c\": \"path_to_c\", \"cuda\": \"path_to_cuda\", \"cpp\": \"path_to_cpp\",\n                     \"objc\": \"path_to_objc\", \"objcpp\": \"path_to_objcpp\", \"rc\": \"path_to_rc\",\n                     'fortran': \"path_to_fortran\", 'asm': \"path_to_asm\", \"hip\": \"path_to_hip\",\n                     \"ispc\": \"path_to_ispc\"}\n        conanfile.conf.define(\"tools.build:compiler_executables\", compilers)\n        toolchain = CMakeToolchain(conanfile)\n        content = toolchain.content\n        for compiler, lang in cmake_mapping.items():\n            assert f'set(CMAKE_{lang}_COMPILER \"path_to_{compiler}\")' in content\n\n    def test_linker_scripts_block(self, conanfile):\n        conanfile.conf.define(\"tools.build:linker_scripts\",\n                              [\"path_to_first_linker_script\", \"path_to_second_linker_script\"])\n        toolchain = CMakeToolchain(conanfile)\n        content = toolchain.content\n        assert r'string(APPEND CONAN_EXE_LINKER_FLAGS \" -T\\\"path_to_first_linker_script\\\" ' \\\n               r'-T\\\"path_to_second_linker_script\\\"\")' in content\n\n    def test_libcxx_abi_flag(self, base_conanfile):\n        c = base_conanfile\n        c.settings.build_type = \"Release\"\n        c.settings.arch = \"x86_64\"\n        c.settings.compiler = \"gcc\"\n        c.settings.compiler.version = \"11\"\n        c.settings.compiler.cstd = \"gnu17\"\n        c.settings.compiler.libcxx = \"libstdc++\"\n        c.settings.os = \"Linux\"\n\n        toolchain = CMakeToolchain(c)\n        content = toolchain.content\n        assert '_GLIBCXX_USE_CXX11_ABI=0' in content\n        assert 'CMAKE_C_STANDARD 17' in toolchain.content\n        assert 'CMAKE_C_EXTENSIONS ON' in toolchain.content\n        c.settings.compiler.libcxx = \"libstdc++11\"\n        toolchain = CMakeToolchain(c)\n        content = toolchain.content\n        # by default, no flag is output anymore, it is assumed the compiler default\n        assert 'GLIBCXX_USE_CXX11_ABI' not in content\n        # recipe workaround for older distros\n        toolchain.blocks[\"libcxx\"].values[\"glibcxx\"] = \"_GLIBCXX_USE_CXX11_ABI=1\"\n        content = toolchain.content\n        assert '_GLIBCXX_USE_CXX11_ABI=1' in content\n\n        # but maybe the conf is better\n        c.conf.define(\"tools.gnu:define_libcxx11_abi\", True)\n        toolchain = CMakeToolchain(c)\n        content = toolchain.content\n        assert '_GLIBCXX_USE_CXX11_ABI=1' in content\n\n\nclass TestMSVCToolset:\n    @pytest.fixture\n    def conanfile_msvc(self, base_conanfile):\n        c = base_conanfile\n        c.settings.build_type = \"Release\"\n        c.settings.arch = \"x86\"\n        c.settings.compiler = \"msvc\"\n        c.settings.compiler.version = \"194\"\n        c.settings.compiler.cppstd = \"20\"\n        c.settings.compiler.cstd = \"17\"\n        c.settings.os = \"Windows\"\n        return c\n\n    def test_toolset(self, conanfile_msvc):\n        toolchain = CMakeToolchain(conanfile_msvc)\n        assert 'set(CMAKE_GENERATOR_TOOLSET \"v143\" CACHE STRING \"\" FORCE)' in toolchain.content\n        assert 'Visual Studio 17 2022' in toolchain.generator\n        assert 'CMAKE_CXX_STANDARD 20' in toolchain.content\n        assert 'CMAKE_C_STANDARD 17' in toolchain.content\n\n    def test_toolset_latest_generator(self, conanfile_msvc):\n        conanfile_msvc.settings.compiler.version = \"195\"\n        toolchain = CMakeToolchain(conanfile_msvc)\n        assert 'set(CMAKE_GENERATOR_TOOLSET \"v145\" CACHE STRING \"\" FORCE)' in toolchain.content\n        assert 'Visual Studio 18 2026' in toolchain.generator\n\n    def test_toolset_update_version(self, conanfile_msvc):\n        conanfile_msvc.settings.compiler.version = \"193\"\n        conanfile_msvc.settings.compiler.update = \"8\"\n        c = CMakeToolchain(conanfile_msvc)\n        assert 'set(CMAKE_GENERATOR_TOOLSET \"v143,version=14.38\" CACHE STRING \"\" FORCE)' in c.content\n\n    def test_toolset_update_version_conf(self, conanfile_msvc):\n        conanfile_msvc.settings.compiler.version = \"193\"\n        conanfile_msvc.conf.define(\"tools.microsoft:msvc_update\", \"7\")\n        c = CMakeToolchain(conanfile_msvc)\n        assert 'set(CMAKE_GENERATOR_TOOLSET \"v143,version=14.37\" CACHE STRING \"\" FORCE)' in c.content\n\n    def test_toolset_update_version_forced_conf(self, conanfile_msvc):\n        conanfile_msvc.settings.compiler.version = \"193\"\n        conanfile_msvc.settings.compiler.update = \"8\"\n        conanfile_msvc.conf.define(\"tools.microsoft:msvc_update\", \"7\")\n        c = CMakeToolchain(conanfile_msvc)\n        assert 'set(CMAKE_GENERATOR_TOOLSET \"v143,version=14.37\" CACHE STRING \"\" FORCE)' in c.content\n\n    def test_toolset_update_version_overflow(self, conanfile_msvc):\n        # https://github.com/conan-io/conan/issues/15583\n        conanfile_msvc.settings.compiler.version = \"194\"\n        conanfile_msvc.settings.compiler.update = \"8\"\n        c = CMakeToolchain(conanfile_msvc)\n        assert 'set(CMAKE_GENERATOR_TOOLSET \"v143,version=14.48\" CACHE STRING \"\" FORCE)' in c.content\n\n    def test_toolset_x64(self, conanfile_msvc):\n        # https://github.com/conan-io/conan/issues/11144\n        conanfile_msvc.conf.define(\"tools.cmake.cmaketoolchain:toolset_arch\", \"x64\")\n        c = CMakeToolchain(conanfile_msvc)\n        assert 'set(CMAKE_GENERATOR_TOOLSET \"v143,host=x64\" CACHE STRING \"\" FORCE)' in c.content\n        assert 'Visual Studio 17 2022' in c.generator\n        assert 'CMAKE_CXX_STANDARD 20' in c.content\n        assert 'CMAKE_C_STANDARD 17' in c.content\n\n    def test_toolset_cuda(self, conanfile_msvc):\n        conanfile_msvc.conf.define(\"tools.cmake.cmaketoolchain:toolset_cuda\", \"C:/Path/To/CUDA\")\n        c = CMakeToolchain(conanfile_msvc)\n        assert ('set(CMAKE_GENERATOR_TOOLSET \"v143,cuda=C:/Path/To/CUDA\" '\n                'CACHE STRING \"\" FORCE)') in c.content\n\n    def test_older_msvc_toolset(self, conanfile_msvc):\n        c = conanfile_msvc\n        c.settings.compiler.version = \"170\"\n        c.settings.compiler.cppstd = \"14\"\n        toolchain = CMakeToolchain(c)\n        content = toolchain.content\n        assert 'CMAKE_GENERATOR_TOOLSET \"v110\"' in content\n        # As by the CMake docs, this has no effect for VS < 2015\n        assert 'CMAKE_CXX_STANDARD 14' in content\n\n    def test_vs_clangcl(self, conanfile_msvc):\n        c = conanfile_msvc\n        c.settings.build_type = \"Release\"\n        c.settings.arch = \"x86_64\"\n        c.settings.compiler = \"clang\"\n        c.settings.compiler.runtime_version = \"v145\"\n        c.settings.compiler.version = \"20\"\n        c.settings.compiler.cppstd = \"14\"\n        c.settings.os = \"Windows\"\n        c.conf.define(\"tools.cmake.cmaketoolchain:generator\", \"Visual Studio 18\")\n        toolchain = CMakeToolchain(c)\n        content = toolchain.content\n        assert 'CMAKE_GENERATOR_TOOLSET \"ClangCL\"' in content\n        assert 'CMAKE_CXX_STANDARD 14' in content\n\n    def test_older_msvc_toolset_update(self, conanfile_msvc):\n        # https://github.com/conan-io/conan/issues/15787\n        c = conanfile_msvc\n        c.settings.arch = \"x86_64\"\n        c.settings.compiler = \"msvc\"\n        c.settings.compiler.version = \"192\"\n        c.settings.compiler.update = \"9\"\n        c.settings.compiler.cppstd = \"14\"\n        c.settings.os = \"Windows\"\n        toolchain = CMakeToolchain(c)\n        content = toolchain.content\n        assert 'CMAKE_GENERATOR_TOOLSET \"v142,version=14.29\"' in content\n\n    def test_msvc_xp_toolsets(self, conanfile_msvc):\n        c = conanfile_msvc\n        c.settings.build_type = \"Release\"\n        c.settings.arch = \"x86\"\n        c.settings.compiler = \"msvc\"\n        c.settings.compiler.version = \"170\"\n        c.settings.compiler.toolset = \"v110_xp\"\n        c.settings.compiler.cppstd = \"14\"\n        toolchain = CMakeToolchain(c)\n        content = toolchain.content\n        assert 'CMAKE_GENERATOR_TOOLSET \"v110_xp\"' in content\n        # As by the CMake docs, this has no effect for VS < 2015\n        assert 'CMAKE_CXX_STANDARD 14' in content\n\n\nclass TestFpic:\n    @pytest.fixture\n    def conanfile_linux(self, base_conanfile):\n        c = base_conanfile\n        c.settings.build_type = \"Release\"\n        c.settings.arch = \"x86_64\"\n        c.settings.compiler = \"gcc\"\n        c.settings.compiler.version = \"11\"\n        c.settings.compiler.cppstd = \"20\"\n        c.settings.os = \"Linux\"\n        return c\n\n    def test_no_fpic_when_not_an_option(self, conanfile_linux):\n        toolchain = CMakeToolchain(conanfile_linux)\n        content = toolchain.content\n        assert 'set(CMAKE_POSITION_INDEPENDENT_CODE' not in content\n\n    @pytest.fixture\n    def conanfile_linux_shared(self, conanfile_linux):\n        c = conanfile_linux\n        c.options = Options({\"fPIC\": [True, False],\n                             \"shared\": [True, False]},\n                            {\"fPIC\": False, \"shared\": True, })\n        return c\n\n    @pytest.mark.parametrize(\"fpic\", [True, False])\n    def test_fpic_when_shared_true(self, conanfile_linux_shared, fpic):\n        conanfile_linux_shared.options.fPIC = fpic\n        toolchain = CMakeToolchain(conanfile_linux_shared)\n        cmake_value = 'ON' if fpic else 'OFF'\n        content = toolchain.content\n        assert 'set(CMAKE_POSITION_INDEPENDENT_CODE {} CACHE BOOL'.format(cmake_value) in content\n\n    def test_fpic_when_not_shared(self, conanfile_linux_shared):\n        conanfile_linux_shared.options.shared = False\n        toolchain = CMakeToolchain(conanfile_linux_shared)\n        content = toolchain.content\n        assert 'set(CMAKE_POSITION_INDEPENDENT_CODE' in content\n\n    @pytest.fixture\n    def conanfile_windows_fpic(self, base_conanfile):\n        c = base_conanfile\n        c.options = Options({\"fPIC\": [True, False]},\n                            {\"fPIC\": True})\n        c.settings.build_type = \"Release\"\n        c.settings.arch = \"x86\"\n        c.settings.compiler = \"gcc\"\n        c.settings.compiler.libcxx = \"libstdc++\"\n        c.settings.os = \"Windows\"\n        return c\n\n    def test_no_fpic_on_windows(self, conanfile_windows_fpic):\n        toolchain = CMakeToolchain(conanfile_windows_fpic)\n        content = toolchain.content\n        assert 'set(CMAKE_POSITION_INDEPENDENT_CODE' not in content\n\n    @pytest.fixture\n    def conanfile_linux_fpic(self, base_conanfile):\n        c = base_conanfile\n        c.options = Options({\"fPIC\": [True, False]},\n                            {\"fPIC\": False})\n        c.settings.build_type = \"Release\"\n        c.settings.arch = \"x86_64\"\n        c.settings.compiler = \"gcc\"\n        c.settings.compiler.version = \"11\"\n        c.settings.compiler.cppstd = \"20\"\n        c.settings.os = \"Linux\"\n        return c\n\n    def test_fpic_disabled(self, conanfile_linux_fpic):\n        conanfile_linux_fpic.options.fPIC = False\n        toolchain = CMakeToolchain(conanfile_linux_fpic)\n        content = toolchain.content\n        assert 'set(CMAKE_POSITION_INDEPENDENT_CODE OFF' in content\n\n    def test_fpic_enabled(self, conanfile_linux_fpic):\n        conanfile_linux_fpic.options.fPIC = True\n        toolchain = CMakeToolchain(conanfile_linux_fpic)\n        content = toolchain.content\n        assert 'set(CMAKE_POSITION_INDEPENDENT_CODE ON' in content\n\n\nclass TestApple:\n    def test_osx_deployment_target(self, base_conanfile):\n        c = base_conanfile\n        c.settings.build_type = \"Release\"\n        c.settings.arch = \"x86\"\n        c.settings.compiler = \"apple-clang\"\n        c.settings.compiler.libcxx = \"libc++\"\n        c.settings.os = \"Macos\"\n        c.settings.os.version = \"10.15\"\n        toolchain = CMakeToolchain(c)\n        content = toolchain.content\n        assert 'set(CMAKE_OSX_DEPLOYMENT_TARGET \"10.15\" CACHE STRING \"\")' in content\n\n    @pytest.mark.parametrize(\"os,os_sdk,arch,expected_sdk\", [\n        (\"Macos\", None, \"x86_64\", \"macosx\"),\n        (\"Macos\", None, \"armv7\", \"macosx\"),\n        (\"iOS\", \"iphonesimulator\", \"armv8\", \"iphonesimulator\"),\n        (\"watchOS\", \"watchsimulator\", \"armv8\", \"watchsimulator\")\n    ])\n    def test_apple_cmake_osx_sysroot(self, base_conanfile, os, os_sdk, arch, expected_sdk):\n        \"\"\"\n        Testing if CMAKE_OSX_SYSROOT is correctly set.\n        Issue related: https://github.com/conan-io/conan/issues/10275\n        \"\"\"\n        c = base_conanfile\n        c.settings.os = os\n        if os_sdk:\n            c.settings.os.sdk = os_sdk\n        c.settings.build_type = \"Release\"\n        c.settings.arch = arch\n        c.settings.compiler = \"apple-clang\"\n        c.settings.compiler.version = \"13.0\"\n        c.settings.compiler.libcxx = \"libc++\"\n        c.settings.compiler.cppstd = \"17\"\n\n        toolchain = CMakeToolchain(c)\n        content = toolchain.content\n        assert 'set(CMAKE_OSX_SYSROOT %s CACHE STRING \"\" FORCE)' % expected_sdk in content\n\n    @pytest.mark.parametrize(\"os,arch,expected_sdk\", [\n        (\"iOS\", \"x86_64\", \"\"),\n        (\"watchOS\", \"armv8\", \"\"),\n        (\"tvOS\", \"x86_64\", \"\")\n    ])\n    def test_apple_cmake_osx_sysroot_sdk_mandatory(self, base_conanfile, os, arch, expected_sdk):\n        \"\"\"\n        Testing if CMAKE_OSX_SYSROOT is correctly set.\n        Issue related: https://github.com/conan-io/conan/issues/10275\n        \"\"\"\n        c = base_conanfile\n        c.settings.os = os\n        c.settings.build_type = \"Release\"\n        c.settings.arch = arch\n        c.settings.compiler = \"apple-clang\"\n        c.settings.compiler.version = \"13.0\"\n        c.settings.compiler.libcxx = \"libc++\"\n        c.settings.compiler.cppstd = \"17\"\n\n        with pytest.raises(ConanException) as excinfo:\n            _ = CMakeToolchain(c).content\n        assert \"Please, specify a suitable value for os.sdk.\" in str(excinfo.value)\n\n\nclass TestCrossBuild:\n    @pytest.fixture\n    def conanfile_cross(self, base_conanfile):\n        c = base_conanfile\n        c.settings.build_type = \"Release\"\n        c.settings.arch = \"armv8\"\n        c.settings.compiler = \"gcc\"\n        c.settings.compiler.version = \"11\"\n        c.settings.compiler.cppstd = \"20\"\n        c.settings.os = \"baremetal\"\n        c.settings_build = c.settings.copy()\n        c.settings_build.os = \"Linux\"\n        c.settings_build.arch = \"x86_64\"\n        return c\n\n    def test_cmake_system_name(self, conanfile_cross):\n        toolchain = CMakeToolchain(conanfile_cross)\n        content = toolchain.content\n        assert 'set(CMAKE_SYSTEM_NAME Generic)' in content\n"
  },
  {
    "path": "test/unittests/tools/env/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/tools/env/test_env.py",
    "content": "import os\nimport platform\nimport subprocess\nimport textwrap\n\nimport pytest\n\nfrom conan.errors import ConanException\nfrom conan.tools.env import Environment\nfrom conan.tools.env.environment import ProfileEnvironment\nfrom conan.internal.subsystems import WINDOWS\nfrom conan.api.model import RecipeReference\nfrom conan.test.utils.mocks import ConanFileMock, MockSettings\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.env import environment_update\nfrom conan.internal.util.files import save, chdir\n\n\ndef test_compose():\n    env = Environment()\n    env.define(\"MyVar\", \"MyValue\")\n    env.define(\"MyVar2\", \"MyValue2\")\n    env.define(\"MyVar3\", \"MyValue3\")\n    env.define(\"MyVar4\", \"MyValue4\")\n    env.unset(\"MyVar5\")\n\n    env2 = Environment()\n    env2.define(\"MyVar\", \"MyNewValue\")\n    env2.append(\"MyVar2\", \"MyNewValue2\")\n    env2.prepend(\"MyVar3\", \"MyNewValue3\")\n    env2.unset(\"MyVar4\")\n    env2.define(\"MyVar5\", \"MyNewValue5\")\n\n    env.compose_env(env2)\n    env = env.vars(ConanFileMock())\n    assert env.get(\"MyVar\") == \"MyValue\"\n    assert env.get(\"MyVar2\") == 'MyValue2'\n    assert env.get(\"MyVar3\") == 'MyValue3'\n    assert env.get(\"MyVar4\") == \"MyValue4\"\n    assert env.get(\"MyVar5\") == ''\n\n\ndef test_define_append():\n    env = Environment()\n    env.define(\"MyVar\", \"MyValue\")\n    env.append(\"MyVar\", \"MyValue1\")\n    env.append(\"MyVar\", [\"MyValue2\", \"MyValue3\"])\n    assert env.vars(ConanFileMock()).get(\"MyVar\") == \"MyValue MyValue1 MyValue2 MyValue3\"\n\n    env = Environment()\n    env.append(\"MyVar\", \"MyValue\")\n    env.append(\"MyVar\", \"MyValue1\")\n    env.define(\"MyVar\", \"MyValue2\")\n    assert env.vars(ConanFileMock()).get(\"MyVar\") == \"MyValue2\"\n\n\n@pytest.mark.parametrize(\"op1, v1, s1, op2, v2, s2, result\",\n                         [(\"define\", \"Val1\", \" \", \"define\", \"Val2\", \" \", \"Val1\"),\n                          (\"define\", \"Val1\", \" \", \"append\", \"Val2\", \" \", \"Val1\"),\n                          (\"define\", \"Val1\", \" \", \"prepend\", \"Val2\", \" \", \"Val1\"),\n                          (\"define\", \"Val1\", \" \", \"unset\", \"\", \" \", \"Val1\"),\n                          (\"append\", \"Val1\", \" \", \"define\", \"Val2\", \" \", \"Val2 Val1\"),\n                          (\"append\", \"Val1\", \" \", \"append\", \"Val2\", \" \", \"MyVar Val2 Val1\"),\n                          (\"append\", \"Val1\", \" \", \"prepend\", \"Val2\", \" \", \"Val2 MyVar Val1\"),\n                          (\"append\", \"Val1\", \" \", \"unset\", \"\", \" \", \"Val1\"),\n                          (\"prepend\", \"Val1\", \" \", \"define\", \"Val2\", \" \", \"Val1 Val2\"),\n                          (\"prepend\", \"Val1\", \" \", \"append\", \"Val2\", \" \", \"Val1 MyVar Val2\"),\n                          (\"prepend\", \"Val1\", \" \", \"prepend\", \"Val2\", \" \", \"Val1 Val2 MyVar\"),\n                          (\"prepend\", \"Val1\", \" \", \"unset\", \"\", \" \", \"Val1\"),\n                          (\"unset\", \"\", \" \", \"define\", \"Val2\", \" \", \"\"),\n                          (\"unset\", \"\", \" \", \"append\", \"Val2\", \" \", \"\"),\n                          (\"unset\", \"\", \" \", \"prepend\", \"Val2\", \" \", \"\"),\n                          (\"unset\", \"\", \" \", \"unset\", \"\", \" \", \"\"),\n                          # different separators\n                          (\"append\", \"Val1\", \"+\", \"append\", \"Val2\", \"-\", \"MyVar+Val2+Val1\"),\n                          (\"append\", \"Val1\", \"+\", \"prepend\", \"Val2\", \"-\", \"Val2+MyVar+Val1\"),\n                          (\"unset\", \"\", \" \", \"append\", \"Val2\", \"+\", \"\"),\n                          (\"unset\", \"\", \" \", \"prepend\", \"Val2\", \"+\", \"\"),\n                          ])\ndef test_compose_combinations(op1, v1, s1, op2, v2, s2, result):\n    env = Environment()\n    if op1 != \"unset\":\n        getattr(env, op1)(\"MyVar\", v1, s1)\n    else:\n        env.unset(\"MyVar\")\n    env2 = Environment()\n    if op2 != \"unset\":\n        getattr(env2, op2)(\"MyVar\", v2, s2)\n    else:\n        env2.unset(\"MyVar\")\n    env.compose_env(env2)\n    env = env.vars(ConanFileMock())\n    with environment_update({\"MyVar\": \"MyVar\"}):\n        assert env.get(\"MyVar\") == result\n    assert env._values[\"MyVar\"].get_str(\"{name}\", None, None) == result\n\n\n@pytest.mark.parametrize(\"op1, v1, op2, v2, result\",\n                         [(\"define\", \"/path1\", \"define\", \"/path2\", \"/path1\"),\n                          (\"define\", \"/path1\", \"append\", \"/path2\", \"/path1\"),\n                          (\"define\", \"/path1\", \"prepend\", \"/path2\", \"/path1\"),\n                          (\"define\", \"/path1\", \"unset\", \"\", \"/path1\"),\n                          (\"append\", \"/path1\", \"define\", \"/path2\", \"/path2:/path1\"),\n                          (\"append\", \"/path1\", \"append\", \"/path2\", \"MyVar:/path2:/path1\"),\n                          (\"append\", \"/path1\", \"prepend\", \"/path2\", \"/path2:MyVar:/path1\"),\n                          (\"append\", \"/path1\", \"unset\", \"\", \"/path1\"),\n                          (\"prepend\", \"/path1\", \"define\", \"/path2\", \"/path1:/path2\"),\n                          (\"prepend\", \"/path1\", \"append\", \"/path2\", \"/path1:MyVar:/path2\"),\n                          (\"prepend\", \"/path1\", \"prepend\", \"/path2\", \"/path1:/path2:MyVar\"),\n                          (\"prepend\", \"/path1\", \"unset\", \"\", \"/path1\"),\n                          (\"unset\", \"\", \"define\", \"/path2\", \"\"),\n                          (\"unset\", \"\", \"append\", \"/path2\", \"\"),\n                          (\"unset\", \"\", \"prepend\", \"/path2\", \"\"),\n                          (\"unset\", \"\", \"unset\", \"\", \"\"),\n                          ])\ndef test_compose_path_combinations(op1, v1, op2, v2, result):\n    env = Environment()\n    if op1 != \"unset\":\n        getattr(env, op1+\"_path\")(\"MyVar\", v1)\n    else:\n        env.unset(\"MyVar\")\n    env2 = Environment()\n    if op2 != \"unset\":\n        getattr(env2, op2+\"_path\")(\"MyVar\", v2)\n    else:\n        env2.unset(\"MyVar\")\n    env.compose_env(env2)\n    env = env.vars(ConanFileMock())\n    assert env._values[\"MyVar\"].get_str(\"{name}\", None, pathsep=\":\") == result\n\n\ndef test_profile():\n    myprofile = textwrap.dedent(\"\"\"\n        # define\n        MyVar1 =MyValue1\n        #  append\n        MyVar2+=MyValue2\n        #  multiple append works\n        MyVar2+=MyValue2_2\n        #  prepend\n        MyVar3=+MyValue3\n        # unset\n        MyVar4=!\n        # Empty\n        MyVar5=\n\n        # PATHS\n        # define\n        MyPath1=(path)/my/path1\n        #  append\n        MyPath2+=(path)/my/path2\n        #  multiple append works\n        MyPath2+=(path)/my/path2_2\n        #  prepend\n        MyPath3=+(path)/my/path3\n        # unset\n        MyPath4=!\n\n        # PER-PACKAGE\n        mypkg*:MyVar2=MyValue2\n        \"\"\")\n\n    profile_env = ProfileEnvironment.loads(myprofile)\n    env = profile_env.get_profile_env(\"\", is_consumer=True)\n    env = env.vars(ConanFileMock())\n    with environment_update({\"MyVar1\": \"$MyVar1\",\n                             \"MyVar2\": \"$MyVar2\",\n                             \"MyVar3\": \"$MyVar3\",\n                             \"MyVar4\": \"$MyVar4\"}):\n        assert env.get(\"MyVar1\") == \"MyValue1\"\n        assert env.get(\"MyVar2\", \"$MyVar2\") == '$MyVar2 MyValue2 MyValue2_2'\n        assert env.get(\"MyVar3\", \"$MyVar3\") == 'MyValue3 $MyVar3'\n        assert env.get(\"MyVar4\") == \"\"\n        assert env.get(\"MyVar5\") == ''\n\n        env = profile_env.get_profile_env(RecipeReference.loads(\"mypkg1/1.0\"))\n        env = env.vars(ConanFileMock())\n        assert env.get(\"MyVar1\") == \"MyValue1\"\n        assert env.get(\"MyVar2\", \"$MyVar2\") == 'MyValue2'\n\n\n@pytest.fixture\ndef envvars():\n    # Append and define operation over the same variable in Windows preserve order\n    env = Environment()\n    env.define(\"MyVar\", \"MyValueA\")\n    env.define(\"MYVAR\", \"MyValueB\")\n    env.define(\"MyVar1\", \"MyValue1A\")\n    env.append(\"MYVAR1\", \"MyValue1B\")\n    env.define(\"MyVar2\", \"MyNewValue2\")\n\n    conanfile = ConanFileMock()\n    conanfile.settings_build = MockSettings({\"os\": \"Windows\", \"arch\": \"x86_64\"})\n    env = env.vars(conanfile)\n    env._subsystem = WINDOWS\n\n    return env\n\n\ndef check_command_output(cmd, prevenv):\n    result, _ = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,\n                                 env=prevenv, shell=True).communicate()\n    out = result.decode()\n\n    assert \"MyVar=MyValueB!!\" in out\n    assert \"MyVar=!!\" in out\n    assert \"MyVar1=MyValue1A MyValue1B!!\" in out\n    assert \"MyVar1=!!\" in out\n    assert \"MyVar2=MyNewValue2!!\" in out\n    assert \"MyVar2=OldValue2!!\" in out\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows\")\ndef test_windows_case_insensitive_bat(envvars):\n    display = textwrap.dedent(\"\"\"\\\n        @echo off\n        echo MyVar=%MyVar%!!\n        echo MyVar1=%MyVar1%!!\n        echo MyVar2=%MyVar2%!!\n        \"\"\")\n\n    prevenv = {\n        \"MYVAR2\": \"OldValue2\",\n    }\n    prevenv.update(dict(os.environ.copy()))  # Necessary from Python 3.12, for SYSTEMROOT var\n\n    with chdir(temp_folder()):\n        envvars.save_bat(\"test.bat\")\n        save(\"display.bat\", display)\n        cmd = \"test.bat && display.bat && deactivate_test.bat && display.bat\"\n        check_command_output(cmd, prevenv)\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows\")\n@pytest.mark.parametrize(\"deactivation_mode\", [\"function\", None],)\ndef test_windows_case_insensitive_ps1(envvars, deactivation_mode):\n    display = textwrap.dedent(\"\"\"\\\n        echo \"MyVar=$env:MyVar!!\"\n        echo \"MyVar1=$env:MyVar1!!\"\n        echo \"MyVar2=$env:MyVar2!!\"\n        \"\"\")\n\n    prevenv = {\n        \"MYVAR2\": \"OldValue2\",\n    }\n    prevenv.update(dict(os.environ.copy()))\n\n    with chdir(temp_folder()):\n        envvars._deactivation_mode = deactivation_mode\n        envvars.save_ps1(\"test.ps1\")\n        save(\"display.ps1\", display)\n        deactivate_cmd = \"deactivate_test\" if deactivation_mode else \".\\\\deactivate_test.ps1\"\n        cmd = f\"powershell.exe .\\\\test.ps1 ; .\\\\display.ps1 ; {deactivate_cmd} ; .\\\\display.ps1\"\n        check_command_output(cmd, prevenv)\n\n\ndef test_dict_access():\n    env = Environment()\n    env.append(\"MyVar\", \"MyValue\", separator=\"@\")\n    ret = env.vars(ConanFileMock()).items()\n    assert dict(ret) == {\"MyVar\": \"MyValue\"}\n\n    env = Environment()\n    env.prepend(\"MyVar\", \"MyValue\", separator=\"@\")\n    env_vars = env.vars(ConanFileMock())\n    assert dict(env_vars.items()) == {\"MyVar\": \"MyValue\"}\n    assert env_vars[\"MyVar\"] == \"MyValue\"\n\n    env2 = Environment()\n    env2.define(\"MyVar\", \"MyValue2\")\n    env.compose_env(env2)\n    env_vars = env.vars(ConanFileMock())\n    assert dict(env_vars.items()) == {\"MyVar\": \"MyValue@MyValue2\"}\n\n    with pytest.raises(KeyError):\n        _ = env_vars[\"Missing\"]\n\n    # With previous values in the environment\n    env = Environment()\n    env.prepend(\"MyVar\", \"MyValue\", separator=\"@\")\n    with environment_update({\"MyVar\": \"PreviousValue\"}):\n        env_vars = env.vars(ConanFileMock())\n        assert env_vars[\"MyVar\"] == \"MyValue@PreviousValue\"\n\n    env = Environment()\n    env.append_path(\"MyVar\", \"MyValue\")\n    with environment_update({\"MyVar\": \"PreviousValue\"}):\n        env_vars = env.vars(ConanFileMock())\n        env_vars._subsystem = WINDOWS\n        assert env_vars[\"MyVar\"] == \"PreviousValue;MyValue\"\n        with env_vars.apply():\n            assert os.getenv(\"MyVar\") == \"PreviousValue;MyValue\"\n\n    assert list(env_vars.keys()) == [\"MyVar\"]\n    assert dict(env_vars.items()) == {\"MyVar\": \"MyValue\"}\n\n\ndef test_env_win_bash():\n    conanfile = ConanFileMock()\n    conanfile.settings_build = MockSettings({\"os\": \"Windows\"})\n    conanfile.win_bash = True\n    conanfile.conf.define(\"tools.microsoft.bash:subsystem\", \"msys2\")\n    folder = temp_folder()\n    conanfile.folders.generators = folder\n    env = Environment()\n    env.define(\"MyVar\", \"MyValue\")\n    env.define_path(\"MyPath\", \"c:/path/to/something\")\n    env.append(\"MyPath\", \"D:/Otherpath\")\n    env_vars = env.vars(conanfile)\n    env_vars.save_script(\"foo\")\n    content = open(os.path.join(folder, \"foo.sh\")).read()\n    assert 'MyVar=\"MyValue\"' in content\n    # Note the unit letter is lowercase\n    assert 'MyPath=\"/c/path/to/something:/d/otherpath\"' in content\n\n\ndef test_public_access():\n    env = Environment()\n    env.define(\"MyVar\", \"MyValue\")\n    env.append(\"MyVar\", \"MyValue2\")\n    env.define_path(\"MyPath\", \"c:/path/to/something\")\n    env.append_path(\"MyPath\", \"D:/Otherpath\")\n    env_vars = env.vars(ConanFileMock())\n    env_vars._subsystem = WINDOWS\n    for name, values in env_vars.items():\n        if name == \"MyVar\":\n            assert values == \"MyValue MyValue2\"\n        if name == \"MyPath\":\n            assert values == \"c:/path/to/something;D:/Otherpath\"\n\n    env.remove(\"MyPath\", \"D:/Otherpath\")\n    assert env_vars.get(\"MyPath\") == \"c:/path/to/something\"\n\n\nclass TestProfileEnvRoundTrip:\n\n    def test_define(self):\n        myprofile = textwrap.dedent(\"\"\"\n            # define\n            MyVar1=MyValue1\n            MyPath1 = (path)/my/path1\n            \"\"\")\n\n        env = ProfileEnvironment.loads(myprofile)\n        text = env.dumps()\n        assert text == textwrap.dedent(\"\"\"\\\n            MyVar1=MyValue1\n            MyPath1=(path)/my/path1\n            \"\"\")\n\n    def test_append(self):\n        myprofile = textwrap.dedent(\"\"\"\n            # define\n            MyVar1+=MyValue1\n            MyPath1 +=(path)/my/path1\n            \"\"\")\n\n        env = ProfileEnvironment.loads(myprofile)\n        text = env.dumps()\n        assert text == textwrap.dedent(\"\"\"\\\n            MyVar1+=MyValue1\n            MyPath1+=(path)/my/path1\n            \"\"\")\n\n    def test_append_multiple(self):\n        myprofile = textwrap.dedent(\"\"\"\n            # define\n            MyVar1+=MyValue1\n            MyVar1+=MyValue2\n            MyPath1 +=(path)/my/path1\n            MyPath1 +=(path)/my/path2\n            \"\"\")\n\n        env = ProfileEnvironment.loads(myprofile)\n        text = env.dumps()\n        assert text == textwrap.dedent(\"\"\"\\\n            MyVar1+=MyValue1\n            MyVar1+=MyValue2\n            MyPath1+=(path)/my/path1\n            MyPath1+=(path)/my/path2\n            \"\"\")\n\n    def test_prepend(self):\n        myprofile = textwrap.dedent(\"\"\"\n            # define\n            MyVar1=+MyValue1\n            MyPath1=+(path)/my/path1\n            \"\"\")\n\n        env = ProfileEnvironment.loads(myprofile)\n        text = env.dumps()\n        assert text == textwrap.dedent(\"\"\"\\\n            MyVar1=+MyValue1\n            MyPath1=+(path)/my/path1\n            \"\"\")\n\n    def test_prepend_multiple(self):\n        myprofile = textwrap.dedent(\"\"\"\n           # define\n           MyVar1=+MyValue1\n           MyVar1=+MyValue2\n           MyPath1=+(path)/my/path1\n           MyPath1=+(path)/my/path2\n           \"\"\")\n\n        env = ProfileEnvironment.loads(myprofile)\n        text = env.dumps()\n        assert text == textwrap.dedent(\"\"\"\\\n           MyVar1=+MyValue1\n           MyVar1=+MyValue2\n           MyPath1=+(path)/my/path1\n           MyPath1=+(path)/my/path2\n           \"\"\")\n\n    def test_combined(self):\n        myprofile = textwrap.dedent(\"\"\"\n            MyVar1=+MyValue11\n            MyVar1+=MyValue12\n            MyPath1=+(path)/my/path11\n            MyPath1+=(path)/my/path12\n            \"\"\")\n\n        env = ProfileEnvironment.loads(myprofile)\n        text = env.dumps()\n        assert text == textwrap.dedent(\"\"\"\\\n            MyVar1=+MyValue11\n            MyVar1+=MyValue12\n            MyPath1=+(path)/my/path11\n            MyPath1+=(path)/my/path12\n            \"\"\")\n\n    def test_combined_multiple(self):\n        myprofile = textwrap.dedent(\"\"\"\n            MyVar1=+MyValue11\n            MyVar1=+MyValue12\n            MyVar1+=MyValue13\n            MyVar1+=MyValue14\n            MyPath1=+(path)/my/path11\n            MyPath1=+(path)/my/path12\n            MyPath1+=(path)/my/path13\n            MyPath1+=(path)/my/path12\n            \"\"\")\n\n        env = ProfileEnvironment.loads(myprofile)\n        text = env.dumps()\n        assert text == textwrap.dedent(\"\"\"\\\n            MyVar1=+MyValue11\n            MyVar1=+MyValue12\n            MyVar1+=MyValue13\n            MyVar1+=MyValue14\n            MyPath1=+(path)/my/path11\n            MyPath1=+(path)/my/path12\n            MyPath1+=(path)/my/path13\n            MyPath1+=(path)/my/path12\n            \"\"\")\n\n    def test_combined_prepend_first(self):\n        myprofile = textwrap.dedent(\"\"\"\n            MyVar1+=MyValue11\n            MyVar1=+MyValue12\n            MyPath1+=(path)/my/path11\n            MyPath1=+(path)/my/path12\n            \"\"\")\n\n        env = ProfileEnvironment.loads(myprofile)\n        text = env.dumps()\n        # NOTE: This is reversed order compared to origin, prepend always first\n        assert text == textwrap.dedent(\"\"\"\\\n            MyVar1=+MyValue12\n            MyVar1+=MyValue11\n            MyPath1=+(path)/my/path12\n            MyPath1+=(path)/my/path11\n            \"\"\")\n\n    def test_combined_prepend_first_multiple(self):\n        myprofile = textwrap.dedent(\"\"\"\n            MyVar1+=MyValue11\n            MyVar1=+MyValue12\n            MyVar1+=MyValue13\n            MyVar1=+MyValue14\n            MyPath1+=(path)/my/path11\n            MyPath1=+(path)/my/path12\n            MyPath1+=(path)/my/path13\n            MyPath1=+(path)/my/path14\n            \"\"\")\n\n        env = ProfileEnvironment.loads(myprofile)\n        text = env.dumps()\n        # NOTE: This is reversed order compared to origin, prepend always first\n        assert text == textwrap.dedent(\"\"\"\\\n            MyVar1=+MyValue12\n            MyVar1=+MyValue14\n            MyVar1+=MyValue11\n            MyVar1+=MyValue13\n            MyPath1=+(path)/my/path12\n            MyPath1=+(path)/my/path14\n            MyPath1+=(path)/my/path11\n            MyPath1+=(path)/my/path13\n            \"\"\")\n\n\ndef test_custom_placeholder():\n    # https://github.com/conan-io/conan/issues/12427\n    env = Environment()\n    env.append_path(\"MyVar\", \"MyValue\")\n    env = env.vars(ConanFileMock())\n    assert env.get(\"MyVar\", variable_reference=\"$penv{{{name}}}\") == \\\n           f\"$penv{{MyVar}}:MyValue\"\n    items = {k: v for k, v in env.items(variable_reference=\"$penv{{{name}}}\")}\n    assert items == {\"MyVar\": f\"$penv{{MyVar}}:MyValue\"}\n\n\nclass TestProfileSeparators:\n\n    def test_define(self):\n        myprofile = \"MyPath1 = (sep=@)/my/path1\"\n        env = ProfileEnvironment.loads(myprofile).get_profile_env(ref=\"\")\n        assert env.dumps() == \"MyPath1=(sep=@)/my/path1\"\n        env.append(\"MyPath1\", \"/other/value\")\n        assert env.vars(ConanFileMock()).get(\"MyPath1\") == \"/my/path1@/other/value\"\n\n    def test_append(self):\n        myprofile = \"MyPath1 +=(sep=@)/my/path1\"\n        env = ProfileEnvironment.loads(myprofile).get_profile_env(ref=\"\")\n        assert env.dumps() == \"MyPath1+=(sep=@)/my/path1\"\n        env.append(\"MyPath1\", \"/other/value\")\n        assert env.vars(ConanFileMock()).get(\"MyPath1\") == \"/my/path1@/other/value\"\n\n    def test_error(self):\n        myprofile = \"MyPath1 = (sep=@) (path)/my/path1\"\n        with pytest.raises(ConanException) as e:\n            ProfileEnvironment.loads(myprofile)\n        assert \"Cannot use (sep) and (path) qualifiers simultaneously\" in str(e.value)\n"
  },
  {
    "path": "test/unittests/tools/env/test_env_files.py",
    "content": "import os\nimport platform\nimport shutil\nimport subprocess\nimport textwrap\n\nimport pytest\n\nfrom conan.tools.env import Environment\nfrom conan.internal.subsystems import WINDOWS\nfrom conan.test.utils.mocks import ConanFileMock\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.internal.util.files import save, chdir, load\n\n\n@pytest.fixture\ndef env():\n    env = Environment()\n    env.define(\"MyVar\", \"MyValue\")\n    env.define(\"MyVar1\", \"MyValue1\")\n    env.append(\"MyVar2\", \"MyValue2\")\n    env.prepend(\"MyVar3\", \"MyValue3\")\n    env.unset(\"MyVar4\")\n    env.define(\"MyVar5\", \"MyValue5 With Space5=More Space5;:More\")\n    env.append(\"MyVar6\", \"MyValue6\")  # Append, but previous not existing\n    env.define_path(\"MyPath1\", \"/Some/Path1/\")\n    env.append_path(\"MyPath2\", [\"/Some/Path2/\", \"/Other/Path2/\"])\n    env.prepend_path(\"MyPath3\", \"/Some/Path3/\")\n    env.unset(\"MyPath4\")\n    return env\n\n\n@pytest.fixture\ndef prevenv():\n    return {\n        \"MyVar1\": \"OldVar1\",\n        \"MyVar2\": \"OldVar2\",\n        \"MyVar3\": \"OldVar3 with spaces\",\n        \"MyVar4\": \"OldVar4 with (some) special @ characters\",\n        \"MyPath1\": \"OldPath1\",\n        \"MyPath2\": \"OldPath2\",\n        \"MyPath3\": \"OldPath3\",\n        \"MyPath4\": \"OldPath4\",\n    }\n\n\ndef check_env_files_output(cmd_, prevenv):\n    result, _ = subprocess.Popen(cmd_, stdout=subprocess.PIPE, stderr=subprocess.PIPE,\n                                 env=prevenv, shell=True).communicate()\n    out = result.decode()\n    assert \"MyVar=MyValue!!\" in out\n    assert \"MyVar1=MyValue1!!\" in out\n    assert \"MyVar2=OldVar2 MyValue2!!\" in out\n    assert \"MyVar3=MyValue3 OldVar3 with spaces!!\" in out\n    assert \"MyVar4=!!\" in out\n    assert \"MyVar5=MyValue5 With Space5=More Space5;:More!!\" in out\n    assert \"MyVar6=MyValue6!!\" in out  # Space is correctly trimmed here\n    assert \"MyPath1=/Some/Path1/!!\" in out\n    assert os.pathsep.join([\"MyPath2=OldPath2\", \"/Some/Path2/\", \"/Other/Path2/!!\"]) in out\n    assert os.pathsep.join([\"MyPath3=/Some/Path3/\", \"OldPath3!!\"]) in out\n    assert \"MyPath4=!!\" in out\n\n    # This should be output when deactivated\n    assert \"MyVar=!!\" in out\n    assert \"MyVar1=OldVar1!!\" in out\n    assert \"MyVar2=OldVar2!!\" in out\n    assert \"MyVar3=OldVar3 with spaces!!\" in out\n    assert \"MyVar4=OldVar4 with (some) special @ characters!!\" in out\n    assert \"MyVar5=!!\" in out\n    assert \"MyVar6=!!\" in out\n    assert \"MyPath1=OldPath1!!\" in out\n    assert \"MyPath2=OldPath2!!\" in out\n    assert \"MyPath3=OldPath3!!\" in out\n    assert \"MyPath4=OldPath4!!\" in out\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows\")\ndef test_env_files_bat(env, prevenv):\n    prevenv.update(dict(os.environ.copy()))  # Necessary from Python 3.12, for SYSTEMROOT var\n\n    display = textwrap.dedent(\"\"\"\\\n        @echo off\n        echo MyVar=%MyVar%!!\n        echo MyVar1=%MyVar1%!!\n        echo MyVar2=%MyVar2%!!\n        echo MyVar3=%MyVar3%!!\n        echo MyVar4=%MyVar4%!!\n        echo MyVar5=%MyVar5%!!\n        echo MyVar6=%MyVar6%!!\n        echo MyPath1=%MyPath1%!!\n        echo MyPath2=%MyPath2%!!\n        echo MyPath3=%MyPath3%!!\n        echo MyPath4=%MyPath4%!!\n        \"\"\")\n    t = temp_folder()\n    with chdir(t):\n        env = env.vars(ConanFileMock())\n        env._subsystem = WINDOWS\n        env.save_bat(\"test.bat\")\n        save(\"display.bat\", display)\n        cmd = \"test.bat && display.bat && deactivate_test.bat && display.bat\"\n        check_env_files_output(cmd, prevenv)\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows\")\n@pytest.mark.parametrize(\"deactivation_mode\", [\"function\", None])\ndef test_env_files_ps1(env, prevenv, deactivation_mode):\n    prevenv.update(dict(os.environ.copy()))\n\n    display = textwrap.dedent(\"\"\"\\\n        echo \"MyVar=$env:MyVar!!\"\n        echo \"MyVar1=$env:MyVar1!!\"\n        echo \"MyVar2=$env:MyVar2!!\"\n        echo \"MyVar3=$env:MyVar3!!\"\n        echo \"MyVar4=$env:MyVar4!!\"\n        echo \"MyVar5=$env:MyVar5!!\"\n        echo \"MyVar6=$env:MyVar6!!\"\n        echo \"MyPath1=$env:MyPath1!!\"\n        echo \"MyPath2=$env:MyPath2!!\"\n        echo \"MyPath3=$env:MyPath3!!\"\n        echo \"MyPath4=$env:MyPath4!!\"\n    \"\"\")\n\n    with chdir(temp_folder()):\n        conanfile = ConanFileMock()\n        if deactivation_mode:\n            conanfile.conf.define(\"tools.env:deactivation_mode\", deactivation_mode)\n        env = env.vars(conanfile)\n        env._subsystem = WINDOWS\n        env.save_ps1(\"test.ps1\")\n        save(\"display.ps1\", display)\n        deactivate_cmd = \"deactivate_test\" if deactivation_mode else \".\\\\deactivate_test.ps1\"\n        cmd = f\"powershell.exe .\\\\test.ps1 ; .\\\\display.ps1 ; {deactivate_cmd} ; .\\\\display.ps1\"\n        check_env_files_output(cmd, prevenv)\n\n\n@pytest.mark.skipif(platform.system() == \"Windows\", reason=\"Not in Windows\")\n@pytest.mark.parametrize(\"deactivation_mode\", [\"function\", None])\ndef test_env_files_sh(env, prevenv, deactivation_mode):\n    display = textwrap.dedent(\"\"\"\\\n        echo MyVar=$MyVar!!\n        echo MyVar1=$MyVar1!!\n        echo MyVar2=$MyVar2!!\n        echo MyVar3=$MyVar3!!\n        echo MyVar4=$MyVar4!!\n        echo MyVar5=$MyVar5!!\n        echo MyVar6=$MyVar6!!\n        echo MyPath1=$MyPath1!!\n        echo MyPath2=$MyPath2!!\n        echo MyPath3=$MyPath3!!\n        echo MyPath4=$MyPath4!!\n        \"\"\")\n\n    with chdir(temp_folder()):\n        conanfile = ConanFileMock()\n        if deactivation_mode:\n            conanfile.conf.define(\"tools.env:deactivation_mode\", deactivation_mode)\n        env = env.vars(conanfile)\n        env.save_sh(\"test.sh\")\n        save(\"display.sh\", display)\n        os.chmod(\"display.sh\", 0o777)\n        # We include the \"set -e\" to test it is robust against errors\n        deactivate_cmd = \"deactivate_test\" if deactivation_mode else \". ./deactivate_test.sh\"\n        cmd = f'set -e && . ./test.sh && ./display.sh && {deactivate_cmd} && ./display.sh'\n        check_env_files_output(cmd, prevenv)\n\n\ndef test_relative_paths():\n    folder = temp_folder()\n    scripts_folder = os.path.join(folder, \"myscripts\")\n    display = textwrap.dedent(\"\"\"\\\n        echo Hello MyWorld!!!\n        \"\"\")\n    save(os.path.join(scripts_folder, \"myhello.bat\"), display)\n    save(os.path.join(scripts_folder, \"myhello.sh\"), display)\n    os.chmod(os.path.join(scripts_folder, \"myhello.sh\"), 0o777)\n\n    with chdir(folder):\n        myenv = Environment()\n        myenv.define_path(\"PATH\", scripts_folder)\n        conanfile = ConanFileMock()\n        conanfile.folders._base_generators = folder\n        myenv = myenv.vars(conanfile)\n        myenv.save_bat(\"test.bat\")\n        myenv.save_sh(\"test.sh\")\n        if platform.system() == \"Windows\":\n            test_bat = load(\"test.bat\")\n            assert r'set \"PATH=%~dp0\\myscripts\"' in test_bat\n            cmd = \"test.bat && myhello.bat\"\n        else:\n            test_sh = load(\"test.sh\")\n            assert 'export PATH=\"$script_folder/myscripts\"' in test_sh\n            cmd = \". ./test.sh && myhello.sh\"\n        result, _ = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,\n                                     shell=True).communicate()\n        out = result.decode()\n        assert 'Hello MyWorld!!!' in out\n\n    new_folder = os.path.join(temp_folder(), \"new_folder\")\n    shutil.move(folder, new_folder)\n    with chdir(new_folder):\n        if platform.system() != \"Windows\":\n            # It is NOT possible to fully relativize shell scripts for sh (not bash)\n            # https://stackoverflow.com/questions/29832037/\n            # how-to-get-script-directory-in-posix-sh/29835459#29835459\n            script = load(\"test.sh\").replace(folder, new_folder)\n            save(\"test.sh\", script)\n        result, _ = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE,\n                                     shell=True).communicate()\n        out = result.decode()\n        assert 'Hello MyWorld!!!' in out\n\n\n@pytest.mark.parametrize(\"values, expected\",\n                         [(\"myscripts\", '\"$script_folder/myscripts\"'),\n                          (\"../myscripts\", '\"$script_folder/../myscripts\"'),\n                          (\"../my scripts\", '\"$script_folder/../my scripts\"'),\n                          ([\"../my scripts\", \"path/other\"],\n                           '\"$script_folder/../my scripts:$script_folder/path/other\"')])\ndef test_relativize(values, expected):\n    folder = os.path.join(temp_folder(), \"subfolder\")\n    os.makedirs(folder)\n    if isinstance(values, str):\n        value = os.path.join(folder, values) if not os.path.isabs(values) else values\n    else:\n        value = [os.path.join(folder, v) for v in values]\n    myenv = Environment()\n    myenv.define_path(\"PATH\", value)\n    myenv.prepend_path(\"OTHER\", value)\n    conanfile = ConanFileMock()\n    conanfile.folders._base_generators = folder\n    myenv = myenv.vars(conanfile)\n    with chdir(folder):\n        myenv.save_sh(\"test.sh\")\n        content = load(\"test.sh\")\n        content = content.replace(\"\\\\\", \"/\")\n        assert f'export PATH={expected}' in content\n        assert f'export OTHER=\"{expected}:$OTHER\"'\n"
  },
  {
    "path": "test/unittests/tools/files/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/tools/files/checksums_test.py",
    "content": "import os\n\nfrom conan.tools.files import check_md5, check_sha1, check_sha256\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.internal.util.files import save\n\n\ndef test_checksums():\n    tmp = temp_folder()\n    file_path = os.path.join(tmp, \"foo.txt\")\n    save(os.path.join(tmp, \"foo.txt\"), \"contents\")\n\n    check_md5(None, file_path, \"98bf7d8c15784f0a3d63204441e1e2aa\")\n    check_sha1(None, file_path, \"4a756ca07e9487f482465a99e8286abc86ba4dc7\")\n    check_sha256(None, file_path, \"d1b2a59fbea7e20077af9f91b27e95e865061b270be03ff539ab3b73587882e8\")\n\n"
  },
  {
    "path": "test/unittests/tools/files/collect_lib_test.py",
    "content": "import os\nimport platform\n\nimport pytest\n\nfrom conan.tools.files import collect_libs\nfrom conan.internal.model.cpp_info import CppInfo\nfrom conan.test.utils.mocks import ConanFileMock, RedirectedTestOutput\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import redirect_output\nfrom conan.internal.util.files import save\n\n\ndef test_collect_libs():\n    conanfile = ConanFileMock()\n    conanfile.cpp_info = CppInfo(set_defaults=True)\n    # Without package_folder\n    result = collect_libs(conanfile)\n    assert [] == result\n\n    # Default behavior\n    conanfile.folders.set_base_package(temp_folder())\n    mylib_path = os.path.join(conanfile.package_folder, \"lib\", \"mylib.lib\")\n    save(mylib_path, \"\")\n\n    result = collect_libs(conanfile)\n    assert [\"mylib\"] == result\n\n    # Custom folder\n    customlib_path = os.path.join(conanfile.package_folder, \"custom_folder\", \"customlib.lib\")\n    save(customlib_path, \"\")\n    result = collect_libs(conanfile, folder=\"custom_folder\")\n    assert [\"customlib\"] == result\n\n    # Custom folder doesn't exist\n    stdout = RedirectedTestOutput()  # Initialize each command\n    stderr = RedirectedTestOutput()\n    with redirect_output(stderr, stdout):\n        result = collect_libs(conanfile, folder=\"fake_folder\")\n        assert [] == result\n        assert \"Lib folder doesn't exist, can't collect libraries:\" in stderr\n\n    # Use cpp_info.libdirs\n    conanfile.cpp_info.libdirs = [\"lib\", \"custom_folder\"]\n    result = collect_libs(conanfile)\n    assert [\"customlib\", \"mylib\"] == result\n\n    # Custom folder with multiple libdirs should only collect from custom folder\n    assert [\"lib\", \"custom_folder\"] == conanfile.cpp_info.libdirs\n    result = collect_libs(conanfile, folder=\"custom_folder\")\n    assert [\"customlib\"] == result\n\n    # Warn lib folder does not exist with correct result\n    conanfile = ConanFileMock()\n    conanfile.folders.set_base_package(temp_folder())\n    conanfile.cpp_info = CppInfo(set_defaults=True)\n    lib_mylib_path = os.path.join(conanfile.package_folder, \"lib\", \"mylib.lib\")\n    save(lib_mylib_path, \"\")\n    no_folder_path = os.path.join(conanfile.package_folder, \"no_folder\")\n    conanfile.cpp_info.libdirs = [\"no_folder\", \"lib\"]  # 'no_folder' does NOT exist\n    stdout = RedirectedTestOutput()  # Initialize each command\n    stderr = RedirectedTestOutput()\n    with redirect_output(stderr, stdout):\n        result = collect_libs(conanfile)\n        assert [\"mylib\"] == result\n        assert \"WARN: Lib folder doesn't exist, can't collect libraries: %s\" % no_folder_path \\\n               in stderr\n\n\n@pytest.mark.skipif(platform.system() == \"Windows\", reason=\"Needs symlinks support\")\ndef test_collect_libs_symlinks():\n    # Keep only the shortest lib name per group of symlinks\n    conanfile = ConanFileMock()\n    conanfile.folders.set_base_package(temp_folder())\n    conanfile.cpp_info = CppInfo(set_defaults=True)\n    version_mylib_path = os.path.join(conanfile.package_folder, \"lib\", \"libmylib.1.0.0.dylib\")\n    soversion_mylib_path = os.path.join(conanfile.package_folder, \"lib\", \"libmylib.1.dylib\")\n    lib_mylib_path = os.path.join(conanfile.package_folder, \"lib\", \"libmylib.dylib\")\n    lib_mylib2_path = os.path.join(conanfile.package_folder, \"lib\", \"libmylib.2.dylib\")\n    lib_mylib3_path = os.path.join(conanfile.package_folder, \"custom_folder\", \"libmylib.3.dylib\")\n    save(version_mylib_path, \"\")\n    os.symlink(version_mylib_path, soversion_mylib_path)\n    os.symlink(soversion_mylib_path, lib_mylib_path)\n    save(lib_mylib2_path, \"\")\n    save(lib_mylib3_path, \"\")\n    conanfile.cpp_info.libdirs = [\"lib\", \"custom_folder\"]\n    result = collect_libs(conanfile)\n    assert [\"mylib\", \"mylib.2\", \"mylib.3\"] == result\n"
  },
  {
    "path": "test/unittests/tools/files/test_chmod.py",
    "content": "import os\nimport platform\nimport stat\nimport pytest\n\nfrom conan.errors import ConanException\nfrom conan.tools.files import chmod\nfrom conan.test.utils.mocks import ConanFileMock\nfrom conan.test.utils.tools import temp_folder, save_files\n\n\n@pytest.mark.skipif(platform.system() == \"Windows\", reason=\"validate full permissions only in Unix\")\n@pytest.mark.parametrize(\"read,write,execute,expected\", [\n    (True, True, True, 0o700),\n    (False, True, False, 0o200),\n    (False, False, True, 0o100),\n    (True, False, True, 0o500),\n    (True, True, False, 0o600),\n    (True, False, False, 0o400),\n    (False, False, False, 0o000),])\ndef test_chmod_single_file(read, write, execute, expected):\n    \"\"\"\n    The chmod should be able to change the permissions of a single file.\n    \"\"\"\n    tmp = temp_folder()\n    save_files(tmp, {\"file.txt\": \"foobar\"})\n    file_path = os.path.join(tmp, \"file.txt\")\n    os.chmod(file_path, 0o000)\n    conanfile = ConanFileMock()\n    chmod(conanfile, file_path, read=read, write=write, execute=execute, recursive=False)\n    file_mode = os.stat(file_path).st_mode\n    assert stat.S_IMODE(file_mode) == expected\n\n\n@pytest.mark.skipif(platform.system() == \"Windows\", reason=\"validate full permissions only in Unix\")\n@pytest.mark.parametrize(\"read,write,execute,expected\", [\n    (True, True, True, 0o700),\n    (False, True, False, 0o200),\n    (False, False, True, 0o100),\n    (True, False, True, 0o500),\n    (True, True, False, 0o600),\n    (True, False, False, 0o400),\n    (False, False, False, 0o000),])\ndef test_chmod_recursive(read, write, execute, expected):\n    \"\"\"\n    The chmod should be able to change the permissions of all files in a folder when recursive is set to True.\n    \"\"\"\n    tmp = temp_folder()\n    files = {\"foobar/qux/file.txt\": \"foobar\",\n             \"foobar/file.txt\": \"qux\",\n             \"foobar/foo/file.txt\": \"foobar\"}\n    save_files(tmp, files)\n    folder_path = os.path.join(tmp, \"foobar\")\n    for file in files.keys():\n        file_path = os.path.join(tmp, file)\n        os.chmod(file_path, 0o000)\n    conanfile = ConanFileMock()\n    chmod(conanfile, folder_path, read=read, write=write, execute=execute, recursive=True)\n    for file in files.keys():\n        file_mode = os.stat(os.path.join(tmp, file)).st_mode\n        assert stat.S_IMODE(file_mode) == expected\n\n\n@pytest.mark.skipif(platform.system() == \"Windows\", reason=\"Validate default permissions only in Unix\")\ndef test_chmod_default_values():\n    \"\"\"\n    When not passing a permission parameter, chmod should not change the specific permission.\n    \"\"\"\n    tmp = temp_folder()\n    save_files(tmp, {\"file.txt\": \"foobar\"})\n    file_path = os.path.join(tmp, \"file.txt\")\n    os.chmod(file_path, 0o111)\n    conanfile = ConanFileMock()\n    chmod(conanfile, file_path, read=True)\n    file_mode = os.stat(file_path).st_mode\n    assert stat.S_IMODE(file_mode) == 0o511\n\n\ndef test_missing_permission_arguments():\n    \"\"\"\n    The chmod should raise an exception if no new permission is provided.\n    \"\"\"\n    conanfile = ConanFileMock()\n    with pytest.raises(ConanException) as error:\n        chmod(conanfile, \"invalid_path\")\n    assert 'Could not change permission: At least one of the permissions should be set.' in str(error.value)\n\n\ndef test_invalid_path():\n    \"\"\"\n    The chmod should raise an exception if the path does not exist.\n    \"\"\"\n    conanfile = ConanFileMock()\n    with pytest.raises(ConanException) as error:\n        chmod(conanfile, \"invalid_path\", read=True, write=True, execute=True, recursive=False)\n    assert 'Could not change permission: Path \"invalid_path\" does not exist.' in str(error.value)\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Validate read-only permissions only in Windows\")\ndef test_chmod_windows():\n    \"\"\"\n    The chmod should be able to change read-only state in Windows.\n    \"\"\"\n    tmp = temp_folder()\n    save_files(tmp, {\"file.txt\": \"foobar\"})\n    file_path = os.path.join(tmp, \"file.txt\")\n    os.chmod(file_path, 0o000)\n    conanfile = ConanFileMock()\n    chmod(conanfile, file_path, read=True, write=True, execute=True, recursive=False)\n    assert os.access(file_path, os.W_OK)\n"
  },
  {
    "path": "test/unittests/tools/files/test_downloads.py",
    "content": "import os\nimport shutil\nfrom unittest import mock\n\nimport pytest\n\nfrom conan.tools.files import ftp_download, download, get\nfrom conan.internal.errors import AuthenticationException\nfrom conan.errors import ConanException\nfrom conan.test.utils.file_server import TestFileServer\nfrom conan.test.utils.mocks import ConanFileMock, RedirectedTestOutput\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import redirect_output, TestRequester\nfrom conan.internal.util.files import save, load, chdir, mkdir\n\n\n@mock.patch('ftplib.FTP', autospec=True)\nclass TestFTP:\n\n    def test_ftp_auth(self, ftp_mock):\n        ftp_object = ftp_mock.return_value\n        filename = \"/pub/example/readme2.txt\"\n        with chdir(temp_folder()):  # To not pollute the project\n            ftp_download(None, \"test.rebex.net\", filename, \"demo\", \"password\")\n        ftp_mock.assert_called_with('test.rebex.net')\n        assert ftp_object.login.called\n        ftp_object.cwd.assert_called_with('/pub/example')\n\n    def test_ftp_invalid_path(self, ftp_mock):\n        ftp_object = ftp_mock.return_value\n        ftp_object.cwd.side_effect = Exception(\"550 The system cannot find the file specified.\")\n        with pytest.raises(ConanException) as exc:\n            ftp_download(None, \"test.rebex.net\", \"/path/invalid-file\", \"demo\", \"password\")\n        assert \"550 The system cannot find the file specified.\" in str(exc.value)\n        assert not os.path.exists(\"invalid-file\")\n\n    def test_ftp_invalid_auth(self, ftp_mock):\n        ftp_object = ftp_mock.return_value\n        ftp_object.login.side_effect = Exception(\"530 User cannot log in.\")\n        with pytest.raises(ConanException) as exc:\n            ftp_download(None, \"test.rebex.net\", \"readme.txt\", \"demo\", \"invalid\")\n        assert \"530 User cannot log in.\" in str(exc.value)\n        assert not os.path.exists(\"readme.txt\")\n\n\nclass TestDownload:\n    @pytest.fixture()\n    def _manual(self):\n        file_server = TestFileServer()\n        save(os.path.join(file_server.store, \"manual.html\"), \"this is some content\")\n        conanfile = ConanFileMock()\n        conanfile._conan_helpers.requester = TestRequester({\"file_server\": file_server})\n        return conanfile, file_server\n\n    def test_download(self, _manual):\n        conanfile, file_server = _manual\n        dest = os.path.join(temp_folder(), \"manual.html\")\n        download(conanfile, file_server.fake_url + \"/manual.html\", dest, retry=3, retry_wait=0)\n        content = load(dest)\n        assert content == \"this is some content\"\n\n        # Can re-download\n        download(conanfile, file_server.fake_url + \"/manual.html\", dest, retry=3, retry_wait=0)\n        content = load(dest)\n        assert content == \"this is some content\"\n\n    def test_download_iterate_url(self, _manual):\n        conanfile, file_server = _manual\n        dest = os.path.join(temp_folder(), \"manual.html\")\n        output = RedirectedTestOutput()\n        with redirect_output(output):\n            download(conanfile, [\"invalid\", file_server.fake_url + \"/manual.html\"], dest,\n                     retry=3, retry_wait=0)\n        content = load(dest)\n        assert content == \"this is some content\"\n        assert \"Trying another mirror.\" in str(output)\n\n    def test_download_forbidden(self, _manual):\n        conanfile, file_server = _manual\n        dest = os.path.join(temp_folder(), \"manual.html\")\n        # Not authorized\n        with pytest.raises(AuthenticationException) as exc:\n            download(conanfile, file_server.fake_url + \"/forbidden\", dest)\n        assert \"403 Forbidden\" in str(exc.value)\n\n    def test_download_unauthorized_no_credentials(self, _manual):\n        conanfile, file_server = _manual\n        dest = os.path.join(temp_folder(), \"manual.html\")\n        # Not authorized without credentials\n        with pytest.raises(AuthenticationException) as exc:\n            download(conanfile, file_server.fake_url + \"/basic-auth/manual.html\", dest)\n        assert \"401 Unauthorized\" in str(exc.value)\n        assert \"Not authorized\" in str(exc.value)\n\n    def test_download_unauthorized_literal_none_credentials(self, _manual):\n        conanfile, file_server = _manual\n        dest = os.path.join(temp_folder(), \"manual.html\")\n        # os.getenv('SOME_UNSET_VARIABLE') causes source_credentials.json to contain\n        # \"None\" as a string literal, causing auth to be (\"None\", \"None\") or with\n        # a \"None\" token.\n        auth = (\"None\", \"None\")\n        with pytest.raises(AuthenticationException) as exc:\n            download(conanfile, file_server.fake_url + \"/basic-auth/manual.html\", dest, auth=auth)\n        assert \"401 Unauthorized\" in str(exc.value)\n        assert \"Bad credentials\" in str(exc.value)\n\n    def test_download_authorized(self, _manual):\n        conanfile, file_server = _manual\n        dest = os.path.join(temp_folder(), \"manual.html\")\n        with pytest.raises(AuthenticationException):\n            download(conanfile, file_server.fake_url + \"/basic-auth/manual.html\",\n                     dest, auth=(\"user\", \"wrong\"), retry=0, retry_wait=0)\n\n        # Authorized\n        download(conanfile, file_server.fake_url + \"/basic-auth/manual.html\", dest,\n                 auth=(\"user\", \"password\"), retry=0, retry_wait=0)\n\n        # Authorized using headers\n        download(conanfile, file_server.fake_url + \"/basic-auth/manual.html\", dest,\n                 headers={\"Authorization\": \"Bearer password\"}, retry=0, retry_wait=0)\n\n    def test_download_retries_errors(self):\n        conanfile = ConanFileMock()\n        conanfile._conan_helpers.requester = TestRequester({})\n\n        with pytest.raises(ConanException):\n            output = RedirectedTestOutput()\n            with redirect_output(output):\n                download(conanfile, \"http://fakesomething\", \"path\", retry=2, retry_wait=0.1)\n        assert str(output).count(\"Waiting 0.1 seconds to retry...\") == 2\n\n    def test_download_retries_500_errors(self, _manual):\n        conanfile, file_server = _manual\n        with pytest.raises(ConanException):\n            output = RedirectedTestOutput()\n            with redirect_output(output):\n                download(conanfile, file_server.fake_url + \"/internal_error\", \"path\",\n                         retry=2, retry_wait=0.1)\n        assert str(output).count(\"Waiting 0.1 seconds to retry...\") == 2\n\n    def test_download_no_retries_errors(self):\n        # Not found error will not retry\n        file_server = TestFileServer()\n        conanfile = ConanFileMock()\n        conanfile._conan_helpers.requester = TestRequester({\"file_server\": file_server})\n        file_path = os.path.join(temp_folder(), \"file.txt\")\n        with pytest.raises(ConanException):\n            download(conanfile, file_server.fake_url + \"/manual.html\", file_path,\n                     retry=2, retry_wait=0)\n        assert \"Waiting\" not in str(conanfile.output)\n        assert \"retry\" not in str(conanfile.output)\n\n    def test_download_localfile(self):\n        conanfile = ConanFileMock()\n\n        file_location = os.path.join(temp_folder(), \"file.txt\")\n        save(file_location, \"this is some content\")\n\n        file_location = file_location.lstrip(\"/\")\n        file_url = f\"file:///{file_location}\"\n        file_md5 = \"736db904ad222bf88ee6b8d103fceb8e\"\n\n        dest = os.path.join(temp_folder(), \"downloaded_file.txt\")\n        download(conanfile, file_url, dest, md5=file_md5)\n        content = load(dest)\n        assert \"this is some content\" == content\n\n    def test_download_localfile_notfound(self):\n        conanfile = ConanFileMock()\n\n        file_url = \"file:///path/to/missing/file.txt\"\n        dest = os.path.join(temp_folder(), \"file.txt\")\n\n        with pytest.raises(FileNotFoundError) as exc:\n            download(conanfile, file_url, dest)\n\n        assert \"No such file\" in str(exc.value)\n\n\nclass TestGet:\n\n    @pytest.fixture()\n    def _my_zip(self):\n        tmp_folder = temp_folder()\n        file_path = os.path.join(tmp_folder, \"sample.tar.gz\")\n        test_folder = os.path.join(tmp_folder, \"test_folder\")\n        zipped_file = os.path.join(test_folder, \"myfile.txt\")\n        save(zipped_file, \"myfile contents!\")\n        import tarfile\n        tar_file = tarfile.open(file_path, \"w:gz\")\n        tar_file.add(test_folder, \"test_folder\")\n        tar_file.add(zipped_file, \"test_folder/myfile.txt\")\n        tar_file.close()\n        assert (os.path.exists(file_path))\n\n        file_server = TestFileServer()\n        shutil.copy2(file_path, file_server.store)\n        conanfile = ConanFileMock()\n        conanfile._conan_helpers.requester = TestRequester({\"file_server\": file_server})\n\n        return conanfile, file_server\n\n    def test_get_tgz(self, _my_zip):\n        conanfile, file_server = _my_zip\n        tmp_folder = temp_folder()\n        with chdir(tmp_folder):\n            get(conanfile, file_server.fake_url + \"/sample.tar.gz\", retry=0, retry_wait=0)\n            assert load(\"test_folder/myfile.txt\") == \"myfile contents!\"\n\n    def test_get_tgz_strip_root(self, _my_zip):\n        conanfile, file_server = _my_zip\n        tmp_folder = temp_folder()\n        with chdir(tmp_folder):\n            get(conanfile, file_server.fake_url + \"/sample.tar.gz\", retry=0, retry_wait=0,\n                strip_root=True)\n            assert load(\"myfile.txt\") == \"myfile contents!\"\n\n\nclass TestGetGz:\n    @pytest.fixture()\n    def _my_gz(self):\n        tmp = temp_folder()\n        filepath = os.path.join(tmp, \"test.txt.gz\")\n        import gzip\n        with gzip.open(filepath, \"wb\") as f:\n            f.write(b\"hello world zipped!\")\n\n        file_server = TestFileServer()\n        folder = os.path.join(file_server.store, \"gz\")\n        mkdir(folder)\n        shutil.copy2(filepath, folder)\n        conanfile = ConanFileMock()\n        conanfile._conan_helpers.requester = TestRequester({\"file_server\": file_server})\n        return conanfile, file_server\n\n    def test_get_gunzip(self, _my_gz):\n        conanfile, file_server = _my_gz\n        tmp_folder = temp_folder()\n        with chdir(tmp_folder):\n            get(conanfile, file_server.fake_url + \"/gz/test.txt.gz\", retry=0, retry_wait=0)\n            assert load(\"test.txt\") == \"hello world zipped!\"\n\n    def test_get_gunzip_destination(self, _my_gz):\n        conanfile, file_server = _my_gz\n        tmp_folder = temp_folder()\n        with chdir(tmp_folder):\n            get(conanfile, file_server.fake_url + \"/gz/test.txt.gz\", destination=\"myfile.doc\",\n                retry=0, retry_wait=0)\n            assert load(\"myfile.doc\") == \"hello world zipped!\"\n\n    def test_get_gunzip_destination_subfolder(self, _my_gz):\n        conanfile, file_server = _my_gz\n        tmp_folder = temp_folder()\n        with chdir(tmp_folder):\n            get(conanfile, file_server.fake_url + \"/gz/test.txt.gz\",\n                destination=\"sub/myfile.doc\", retry=0, retry_wait=0)\n            assert load(\"sub/myfile.doc\") == \"hello world zipped!\"\n\n    def test_get_filename_error(self):\n        # Test: File name cannot be deduced from '?file=1'\n        file_server = TestFileServer()\n        conanfile = ConanFileMock()\n        conanfile._conan_helpers.requester = TestRequester({\"file_server\": file_server})\n\n        with pytest.raises(ConanException) as error:\n            get(conanfile, file_server.fake_url + \"?file=1\")\n        assert \"Cannot deduce file name from the url\" in str(error.value)\n"
  },
  {
    "path": "test/unittests/tools/files/test_file_read_and_write.py",
    "content": "# -*- coding: utf-8 -*-\n\n\nimport os\n\nimport pytest\n\nfrom conan.errors import ConanException\nfrom conan.tools.files import replace_in_file, save, load\nfrom conan.test.utils.mocks import ConanFileMock\nfrom conan.test.utils.test_files import temp_folder\n\n\ndef test_save_and_load_encoding():\n    conanfile = ConanFileMock({})\n    tmp = temp_folder()\n    file_path = os.path.join(tmp, \"file.txt\")\n\n    # By default utf-8 is used\n    save(conanfile, file_path, \"你很重，伙計\")\n    contents = load(conanfile, file_path)\n    assert isinstance(contents, str)\n    assert contents == \"你很重，伙計\"\n\n    # And you can specify different encoding\n    save(conanfile, file_path, \"你很重，伙計\", encoding=\"utf-16\")\n    contents = load(conanfile, file_path, encoding=\"utf-16\")\n    assert contents == \"你很重，伙計\"\n\n    save(conanfile, file_path, \"regular contents\")\n    contents = load(conanfile, file_path)\n    assert contents == \"regular contents\"\n\n\ndef test_replace_in_file():\n    conanfile = ConanFileMock({})\n    tmp = temp_folder()\n    file_path = os.path.join(tmp, \"file.txt\")\n\n    # By default utf-8 is used\n    save(conanfile, file_path, \"你很重，伙計\")\n    assert replace_in_file(conanfile, file_path, \"重\", \"0\")\n    contents = load(conanfile, file_path)\n    assert contents == \"你很0，伙計\"\n\n    # Replacing with other encodings is also possible\n    save(conanfile, file_path, \"Ö¼\", encoding=\"cp1252\")\n    assert replace_in_file(conanfile, file_path, \"¼\", \"0\", encoding=\"cp1252\")\n    contents = load(conanfile, file_path, encoding=\"cp1252\")\n    assert contents == \"Ö0\"\n\n    save(conanfile, file_path, \"Ö¼\", encoding=\"ISO-8859-1\")\n    assert replace_in_file(conanfile, file_path, \"¼\", \"0\", encoding=\"ISO-8859-1\")\n    contents = load(conanfile, file_path, encoding=\"ISO-8859-1\")\n    assert contents == \"Ö0\"\n\n    # Replacing utf-16 is also possible but using \"utf-16LE\" (without BOM) to search and replace\n    # otherwise the \"search\" string is not found because it contains also a BOM (header)\n    save(conanfile, file_path, \"你很重，伙計\", encoding=\"utf-16\")\n    replace_in_file(conanfile, file_path, \"重\", \"0\", encoding=\"utf-16\")\n    contents = load(conanfile, file_path, encoding=\"utf-16\")\n    assert contents == \"你很0，伙計\"\n\n    with pytest.raises(ConanException, match=\"didn't find pattern\"):\n        replace_in_file(conanfile, file_path, \"not existing\", \"0\", encoding=\"utf-16\")\n\n    assert not replace_in_file(conanfile, file_path, \"not existing\", \"0\",\n                               encoding=\"utf-16\", strict=False)\n"
  },
  {
    "path": "test/unittests/tools/files/test_patches.py",
    "content": "import os\n\nimport patch_ng\nimport pytest\n\nfrom conan.tools.files import patch, apply_conandata_patches\nfrom conan.errors import ConanException\nfrom conan.test.utils.mocks import ConanFileMock, RedirectedTestOutput\nfrom conan.test.utils.tools import redirect_output\n\n\nclass MockPatchset:\n    filename = None\n    string = None\n    apply_args = None\n\n    def apply(self, root, strip, fuzz):\n        self.apply_args = (root, strip, fuzz)\n        return True\n\n\n@pytest.fixture\ndef mock_patch_ng(monkeypatch):\n    mock = MockPatchset()\n\n    def mock_fromfile(filename):\n        mock.filename = filename\n        return mock\n\n    def mock_fromstring(string):\n        mock.string = string\n        return mock\n\n    monkeypatch.setattr(patch_ng, \"fromfile\", mock_fromfile)\n    monkeypatch.setattr(patch_ng, \"fromstring\", mock_fromstring)\n    return mock\n\n\ndef test_single_patch_file(mock_patch_ng):\n    conanfile = ConanFileMock()\n    conanfile.folders.set_base_source(\"/my_source\")\n    conanfile.folders.set_base_export_sources(\"/my_source\")\n    conanfile.display_name = 'mocked/ref'\n    patch(conanfile, patch_file='patch-file')\n    assert mock_patch_ng.filename.replace('\\\\', '/') == '/my_source/patch-file'\n    assert mock_patch_ng.string is None\n    assert mock_patch_ng.apply_args[0].replace('\\\\', '/') == '/my_source'\n    assert mock_patch_ng.apply_args[1] == 0\n    assert mock_patch_ng.apply_args[2] is False\n\ndef test_single_patch_file_from_forced_build(mock_patch_ng):\n    conanfile = ConanFileMock()\n    conanfile.folders.set_base_source(\"/my_source\")\n    conanfile.folders.set_base_export_sources(\"/my_source\")\n    conanfile.display_name = 'mocked/ref'\n    patch(conanfile, patch_file='/my_build/patch-file')\n    assert mock_patch_ng.filename == '/my_build/patch-file'\n    assert mock_patch_ng.string is None\n    assert mock_patch_ng.apply_args[0].replace('\\\\', '/') == '/my_source'\n    assert mock_patch_ng.apply_args[1] == 0\n    assert mock_patch_ng.apply_args[2] is False\n\n\ndef test_base_path(mock_patch_ng):\n    conanfile = ConanFileMock()\n    conanfile.folders.set_base_source(\"my_source\")\n    conanfile.folders.set_base_export_sources(\"my_source\")\n    conanfile.folders.source = \"src\"  # This not applies to find the patch file but for applying it\n    conanfile.display_name = 'mocked/ref'\n    patch(conanfile, patch_file='patch-file', base_path=\"subfolder\")\n    assert mock_patch_ng.filename.replace('\\\\', '/') == 'my_source/patch-file'\n    assert mock_patch_ng.string is None\n    assert mock_patch_ng.apply_args == (os.path.join(\"my_source\", \"src\", \"subfolder\"), 0, False)\n\n\ndef test_apply_in_build_from_patch_in_source(mock_patch_ng):\n    conanfile = ConanFileMock()\n    conanfile.folders.set_base_source(\"/my_source\")\n    conanfile.folders.set_base_export_sources(\"/my_source\")\n    conanfile.display_name = 'mocked/ref'\n    patch(conanfile, patch_file='patch-file', base_path=\"/my_build/subfolder\")\n    assert mock_patch_ng.filename.replace('\\\\', '/') == '/my_source/patch-file'\n    assert mock_patch_ng.string is None\n    assert mock_patch_ng.apply_args[0] == os.path.join(\"/my_build\", \"subfolder\").replace('\\\\', '/')\n    assert mock_patch_ng.apply_args[1] == 0\n    assert mock_patch_ng.apply_args[2] is False\n\n\ndef test_single_patch_string(mock_patch_ng):\n    conanfile = ConanFileMock()\n    conanfile.folders.set_base_source(\"my_folder\")\n    conanfile.folders.set_base_export_sources(\"my_folder\")\n    conanfile.display_name = 'mocked/ref'\n    output = RedirectedTestOutput()\n    with redirect_output(output):\n        patch(conanfile, patch_string='patch_string')\n    assert mock_patch_ng.string == b'patch_string'\n    assert mock_patch_ng.filename is None\n    assert mock_patch_ng.apply_args == (\"my_folder\", 0, False)\n\n\ndef test_single_patch_arguments(mock_patch_ng):\n    conanfile = ConanFileMock()\n    conanfile.display_name = 'mocked/ref'\n    conanfile.folders.set_base_source(\"/path/to/sources\")\n    conanfile.folders.set_base_export_sources(\"/path/to/sources\")\n    patch(conanfile, patch_file='patch-file', strip=23, fuzz=True)\n    assert mock_patch_ng.filename.replace('\\\\', '/') == '/path/to/sources/patch-file'\n    assert mock_patch_ng.apply_args[0].replace('\\\\', '/') == \"/path/to/sources\"\n    assert mock_patch_ng.apply_args[1] == 23\n    assert mock_patch_ng.apply_args[2] is True\n\n\ndef test_single_patch_type(mock_patch_ng):\n    output = RedirectedTestOutput()\n    with redirect_output(output):\n        conanfile = ConanFileMock()\n        conanfile.display_name = 'mocked/ref'\n        patch(conanfile, patch_file='patch-file', patch_type='patch_type')\n    assert 'mocked/ref: Apply patch (patch_type)\\n' == output.getvalue()\n\n\ndef test_single_patch_description(mock_patch_ng):\n    output = RedirectedTestOutput()\n    with redirect_output(output):\n        conanfile = ConanFileMock()\n        conanfile.display_name = 'mocked/ref'\n        patch(conanfile, patch_file='patch-file', patch_description='patch_description')\n    assert 'mocked/ref: Apply patch (file): patch_description\\n' == output.getvalue()\n\n\ndef test_single_patch_extra_fields(mock_patch_ng):\n    output = RedirectedTestOutput()\n    with redirect_output(output):\n        conanfile = ConanFileMock()\n        conanfile.display_name = 'mocked/ref'\n        patch(conanfile, patch_file='patch-file', patch_type='patch_type',\n              patch_description='patch_description')\n    assert 'mocked/ref: Apply patch (patch_type): patch_description\\n' == output.getvalue()\n\n\ndef test_single_no_patchset(monkeypatch):\n    with pytest.raises(ConanException) as excinfo:\n        monkeypatch.setattr(patch_ng, \"fromfile\", lambda _: None)\n\n        conanfile = ConanFileMock()\n        conanfile.display_name = 'mocked/ref'\n        patch(conanfile, patch_file='patch-file-failed')\n    assert 'Failed to parse patch: patch-file-failed' == str(excinfo.value)\n\n\ndef test_single_apply_fail(monkeypatch):\n    class MockedApply:\n        def apply(self, *args, **kwargs):  # noqa\n            return False\n\n    monkeypatch.setattr(patch_ng, \"fromfile\", lambda _: MockedApply())\n\n    conanfile = ConanFileMock()\n    conanfile.display_name = 'mocked/ref'\n    with pytest.raises(ConanException) as excinfo:\n        patch(conanfile, patch_file='patch-file-failed')\n    assert 'Failed to apply patch: patch-file-failed' == str(excinfo.value)\n\n\ndef test_multiple_no_version(mock_patch_ng):\n    output = RedirectedTestOutput()\n    with redirect_output(output):\n        conanfile = ConanFileMock()\n        conanfile.display_name = 'mocked/ref'\n        conanfile.conan_data = {'patches': [\n            {'patch_file': 'patches/0001-buildflatbuffers-cmake.patch',\n             'base_path': 'source_subfolder', },\n            {'patch_file': 'patches/0002-implicit-copy-constructor.patch',\n             'base_path': 'source_subfolder',\n             'patch_type': 'backport',\n             'patch_source': 'https://github.com/google/flatbuffers/pull/5650',\n             'patch_description': 'Needed to build with modern clang compilers.'}\n        ]}\n        apply_conandata_patches(conanfile)\n    assert 'mocked/ref: Apply patch (file): patches/0001-buildflatbuffers-cmake.patch\\n' \\\n           in output.getvalue()\n    assert 'mocked/ref: Apply patch (backport): Needed to build with modern clang compilers.\\n' \\\n           in output.getvalue()\n\n\ndef test_patch_user(mock_patch_ng):\n    output = RedirectedTestOutput()\n    with redirect_output(output):\n        conanfile = ConanFileMock()\n        conanfile.display_name = 'mocked/ref'\n        conanfile.conan_data = {'patches': [\n            {'patch_user': 'some replace command, the user will handle',\n             'myuserthings': 'other things', },\n        ]}\n        apply_conandata_patches(conanfile)\n        # it doesn't do anything, but it doesn't crash\n\n\ndef test_multiple_with_version(mock_patch_ng):\n    output = RedirectedTestOutput()\n    with redirect_output(output):\n        conanfile = ConanFileMock()\n        conanfile.display_name = 'mocked/ref'\n        conandata_contents = {'patches': {\n            \"1.11.0\": [\n                {'patch_file': 'patches/0001-buildflatbuffers-cmake.patch',\n                 'base_path': 'source_subfolder', },\n                {'patch_file': 'patches/0002-implicit-copy-constructor.patch',\n                 'base_path': 'source_subfolder',\n                 'patch_type': 'backport',\n                 'patch_source': 'https://github.com/google/flatbuffers/pull/5650',\n                 'patch_description': 'Needed to build with modern clang compilers.'}\n            ],\n            \"1.12.0\": [\n                {'patch_file': 'patches/0001-buildflatbuffers-cmake.patch',\n                 'base_path': 'source_subfolder', },\n            ]}}\n\n        conanfile.conan_data = conandata_contents.copy()\n\n        with pytest.raises(AssertionError) as excinfo:\n            apply_conandata_patches(conanfile)\n        assert 'Can only be applied if conanfile.version is already defined' == str(excinfo.value)\n\n        conanfile.version = \"1.2.11\"\n\n        apply_conandata_patches(conanfile)\n        assert len(str(output.getvalue())) == 0\n\n        conanfile.version = \"1.11.0\"\n        apply_conandata_patches(conanfile)\n        assert 'mocked/ref: Apply patch (file): patches/0001-buildflatbuffers-cmake.patch\\n' \\\n               in output.getvalue()\n        assert 'mocked/ref: Apply patch (backport): Needed to build with modern clang compilers.\\n' \\\n               in output.getvalue()\n\n        # Ensure the function is not mutating the `conan_data` structure\n        assert conanfile.conan_data == conandata_contents\n"
  },
  {
    "path": "test/unittests/tools/files/test_rename.py",
    "content": "import os\nimport platform\nimport pytest\n\nfrom conan.tools.files import rename\nfrom conan.test.utils.mocks import ConanFileMock\nfrom conan.test.utils.tools import temp_folder, save_files\n\n\ndef test_rename_file():\n    conanfile = ConanFileMock()\n    tmp = temp_folder()\n    save_files(tmp, {\"file.txt\": \"\"})\n    old_path = os.path.join(tmp, \"file.txt\")\n    new_path = os.path.join(tmp, \"kk.txt\")\n    rename(conanfile, old_path, new_path)\n    assert not os.path.exists(old_path)\n    assert os.path.exists(new_path)\n\n\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Robocopy only exists in Windows\")\ndef test_rename_folder_robocopy():\n    conanfile = ConanFileMock()\n    tmp = temp_folder()\n    old_folder = os.path.join(tmp, \"old_folder\")\n    os.mkdir(old_folder)\n    new_folder = os.path.join(tmp, \"new_folder\")\n    rename(conanfile, old_folder, new_folder)\n    assert not os.path.exists(old_folder)\n    assert os.path.exists(new_folder)\n"
  },
  {
    "path": "test/unittests/tools/files/test_rm.py",
    "content": "import os\nimport pytest\n\n# Check it is importable from tools\nfrom conan.tools.files import rm, chdir\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.internal.util.files import save_files\n\n\ndef test_remove_files_by_mask_recursively():\n    temp_dir = temp_folder()\n\n    with chdir(None, temp_dir):\n        os.makedirs(\"subdir\")\n        os.makedirs(\"dir.pdb\")\n        os.makedirs(os.path.join(\"subdir\", \"deepdir\"))\n\n    save_files(temp_dir, {\"1.txt\": \"\",\n                        \"1.pdb\": \"\",\n                        \"1.pdb1\": \"\",\n                        os.path.join(\"subdir\", \"2.txt\"): \"\",\n                        os.path.join(\"subdir\", \"2.pdb\"): \"\",\n                        os.path.join(\"subdir\", \"2.pdb1\"): \"\",\n                        os.path.join(\"subdir\", \"deepdir\", \"3.txt\"): \"\",\n                        os.path.join(\"subdir\", \"deepdir\", \"3.pdb\"): \"\",\n                        os.path.join(\"subdir\", \"deepdir\", \"3.pdb1\"): \"\"})\n\n    rm(None, \"*.sh\", temp_dir, recursive=True)\n\n    rm(None, \"*.pdb\", temp_dir, recursive=True)\n\n    assert os.path.isdir(os.path.join(temp_dir, \"dir.pdb\"))\n\n    assert os.path.isfile(os.path.join(temp_dir, \"1.txt\"))\n    assert not os.path.isfile(os.path.join(temp_dir, \"1.pdb\"))\n    assert os.path.isfile(os.path.join(temp_dir, \"1.pdb1\"))\n\n    assert os.path.isfile(os.path.join(temp_dir, \"subdir\", \"2.txt\"))\n    assert not os.path.isfile(os.path.join(temp_dir, \"subdir\", \"2.pdb\"))\n    assert os.path.isfile(os.path.join(temp_dir, \"subdir\", \"2.pdb1\"))\n\n    assert os.path.isfile(os.path.join(temp_dir, \"subdir\", \"deepdir\", \"3.txt\"))\n    assert not os.path.isfile(os.path.join(temp_dir, \"subdir\", \"deepdir\", \"3.pdb\"))\n    assert os.path.isfile(os.path.join(temp_dir, \"subdir\", \"deepdir\", \"3.pdb1\"))\n\n    rm(None, \"*.pdb\", temp_dir, recursive=True)\n\n\ndef test_remove_files_by_mask_non_recursively():\n    temp_dir = temp_folder()\n    with chdir(None, temp_dir):\n        os.makedirs(\"subdir\")\n\n    save_files(temp_dir, {\"1.txt\": \"\",\n                        \"1.pdb\": \"\",\n                        \"1.pdb1\": \"\",\n                        os.path.join(\"subdir\", \"2.txt\"): \"\",\n                        os.path.join(\"subdir\", \"2.pdb\"): \"\",\n                        os.path.join(\"subdir\", \"2.pdb1\"): \"\"})\n\n    rm(None, \"*.pdb\", temp_dir)\n    assert not os.path.exists(os.path.join(temp_dir, \"1.pdb\"))\n    assert os.path.exists(os.path.join(temp_dir, \"subdir\", \"2.pdb\"))\n\n    assert os.path.exists(os.path.join(temp_dir, \"1.txt\"))\n    assert os.path.exists(os.path.join(temp_dir, \"subdir\", \"2.txt\"))\n\n\n@pytest.mark.parametrize(\"recursive\", [False, True])\n@pytest.mark.parametrize(\"results\", [\n    [\"*.dll\", (\"foo.dll\",)],\n    [(\"*.dll\",), (\"foo.dll\",)],\n    [[\"*.dll\"], (\"foo.dll\",)],\n    [(\"*.dll\", \"*.lib\"), (\"foo.dll\", \"foo.dll.lib\")],\n])\ndef test_exclude_pattern_from_remove_list(recursive, results):\n    \"\"\" conan.tools.files.rm should not remove files that match the pattern but are excluded\n        by the excludes parameter.\n        It should obey the recursive parameter, only excluding the files in the root folder in case\n        it is False.\n    \"\"\"\n    excludes, expected_files = results\n    temporary_folder = temp_folder()\n    with chdir(None, temporary_folder):\n        os.makedirs(\"subdir\")\n\n    save_files(temporary_folder, {\n        \"1.txt\": \"\",\n        \"1.pdb\": \"\",\n        \"1.pdb1\": \"\",\n        \"foo.dll\": \"\",\n        \"foo.dll.lib\": \"\",\n        os.path.join(\"subdir\", \"2.txt\"): \"\",\n        os.path.join(\"subdir\", \"2.pdb\"): \"\",\n        os.path.join(\"subdir\", \"foo.dll\"): \"\",\n        os.path.join(\"subdir\", \"foo.dll.lib\"): \"\",\n        os.path.join(\"subdir\", \"2.pdb1\"): \"\"})\n\n    rm(None, \"*\", temporary_folder, excludes=excludes, recursive=recursive)\n\n    for it in expected_files:\n        assert os.path.exists(os.path.join(temporary_folder, it))\n    assert not os.path.exists(os.path.join(temporary_folder, \"1.pdb\"))\n\n    # Check the recursive parameter and subfolder\n    condition = (lambda x: not x) if recursive else (lambda x: x)\n    assert condition(os.path.exists(os.path.join(temporary_folder, \"subdir\", \"2.pdb\")))\n    for it in expected_files:\n        assert os.path.exists(os.path.join(temporary_folder, \"subdir\", it))\n"
  },
  {
    "path": "test/unittests/tools/files/test_symlinks.py",
    "content": "import os\nimport platform\n\nimport pytest\n\nfrom conan import tools\nfrom conan.tools.files import mkdir\nfrom conan.test.utils.test_files import temp_folder\n\n\n@pytest.fixture\ndef folders():\n    tmp = temp_folder()\n    files = [\"foo/var/file.txt\"]\n    outside_folder = temp_folder()\n    symlinks = [\n        (os.path.join(tmp, \"foo/var/file.txt\"), \"foo/var/other/absolute.txt\"),  # Absolute link\n        (os.path.join(tmp, \"foo/var\"), \"foo/var/other/other/myfolder\"),  # Absolute link folder\n        (os.path.join(tmp, \"foo/var/file.txt\"), \"foo/absolute.txt\"),  # Absolute link\n        (\"../file.txt\", \"foo/var/other/relative.txt\"),  # Relative link\n        (\"missing.txt\", \"foo/var/other/broken.txt\"),  # Broken link\n        (outside_folder, \"foo/var/other/absolute_outside\"),  # Absolute folder outside the folder\n        (\"../../../../../outside\", \"foo/absolute_outside\"),  # Relative folder outside the folder\n    ]\n    # Create the files and symlinks\n    for path in files:\n        mkdir(None, os.path.dirname(os.path.join(tmp, path)))\n        with open(os.path.join(tmp, path), \"w\") as fl:\n            fl.write(\"foo\")\n\n    for link_dst, linked_file in symlinks:\n        mkdir(None, os.path.dirname(os.path.join(tmp, linked_file)))\n        os.symlink(link_dst, os.path.join(tmp, linked_file))\n    return tmp, outside_folder\n\n\n@pytest.mark.skipif(platform.system() == \"Windows\", reason=\"Symlinks not in Windows\")\ndef test_absolute_to_relative_symlinks(folders):\n    \"\"\"If a symlink is absolute but relative to a file or folder that is contained in\n    the base folder, we can make it relative\"\"\"\n\n    folder, outside_folder = folders\n    # Transform the absolute symlinks to relative\n    tools.files.symlinks.absolute_to_relative_symlinks(None, folder)\n\n    # Check the results\n    linked_to = os.readlink(os.path.join(folder, \"foo/var/other/absolute.txt\")).replace(\"\\\\\", \"/\")\n    assert linked_to == \"../file.txt\"\n\n    linked_to = os.readlink(os.path.join(folder, \"foo/var/other/other/myfolder\")).replace(\"\\\\\", \"/\")\n    assert linked_to == \"../..\"\n\n    linked_to = os.readlink(os.path.join(folder, \"foo/absolute.txt\")).replace(\"\\\\\", \"/\")\n    assert linked_to == \"var/file.txt\"\n\n    linked_to = os.readlink(os.path.join(folder, \"foo/var/other/relative.txt\")).replace(\"\\\\\", \"/\")\n    assert linked_to == \"../file.txt\"\n\n    linked_to = os.readlink(os.path.join(folder, \"foo/var/other/broken.txt\"))\n    assert linked_to == \"missing.txt\"\n\n    linked_to = os.readlink(os.path.join(folder, \"foo/var/other/absolute_outside\"))\n    assert linked_to == outside_folder\n\n\n@pytest.mark.skipif(platform.system() == \"Windows\", reason=\"Symlinks not in Windows\")\ndef test_remove_external_symlinks(folders):\n\n    folder, outside_folder = folders\n    # Remove the external symlinks\n    tools.files.symlinks.remove_external_symlinks(None, folder)\n\n    # Check the results, these are kept the same\n    linked_to = os.readlink(os.path.join(folder, \"foo/var/other/absolute.txt\"))\n    assert linked_to == os.path.join(folder, \"foo/var/file.txt\")\n\n    linked_to = os.readlink(os.path.join(folder, \"foo/var/other/other/myfolder\"))\n    assert linked_to == os.path.join(folder, \"foo/var\")\n\n    linked_to = os.readlink(os.path.join(folder, \"foo/absolute.txt\"))\n    assert linked_to == os.path.join(folder, \"foo/var/file.txt\")\n\n    linked_to = os.readlink(os.path.join(folder, \"foo/var/other/relative.txt\"))\n    assert linked_to == \"../file.txt\"\n\n    linked_to = os.readlink(os.path.join(folder, \"foo/var/other/broken.txt\"))\n    assert linked_to == \"missing.txt\"\n\n    # This one is removed\n    assert not os.path.islink(os.path.join(folder, \"foo/var/other/absolute_outside\"))\n    assert not os.path.exists(os.path.join(folder, \"foo/var/other/absolute_outside\"))\n\n    # This one is removed\n    assert not os.path.islink(os.path.join(folder, \"foo/absolute_outside\"))\n    assert not os.path.exists(os.path.join(folder, \"foo/absolute_outside\"))\n\n\n@pytest.mark.skipif(platform.system() == \"Windows\", reason=\"Symlinks not in Windows\")\ndef test_remove_broken_symlinks(folders):\n    folder, outside_folder = folders\n    # Remove the external symlinks\n    tools.files.symlinks.remove_broken_symlinks(None, folder)\n\n    # Check the results, these are kept the same\n    linked_to = os.readlink(os.path.join(folder, \"foo/var/other/absolute.txt\"))\n    assert linked_to == os.path.join(folder, \"foo/var/file.txt\")\n\n    linked_to = os.readlink(os.path.join(folder, \"foo/var/other/other/myfolder\"))\n    assert linked_to == os.path.join(folder, \"foo/var\")\n\n    linked_to = os.readlink(os.path.join(folder, \"foo/absolute.txt\"))\n    assert linked_to == os.path.join(folder, \"foo/var/file.txt\")\n\n    linked_to = os.readlink(os.path.join(folder, \"foo/var/other/relative.txt\"))\n    assert linked_to == \"../file.txt\"\n\n    # This one is removed\n    assert not os.path.islink(os.path.join(folder, \"foo/var/other/broken.txt\"))\n    assert not os.path.exists(os.path.join(folder, \"foo/var/other/broken.txt\"))\n\n    linked_to = os.readlink(os.path.join(folder, \"foo/var/other/absolute_outside\"))\n    assert linked_to == outside_folder\n\n    # This is broken also so it is also removed\n    assert not os.path.islink(os.path.join(folder, \"foo/absolute_outside\"))\n    assert not os.path.exists(os.path.join(folder, \"foo/absolute_outside\"))\n"
  },
  {
    "path": "test/unittests/tools/files/test_tool_copy.py",
    "content": "from unittest import mock\nimport os\nimport platform\nimport pytest\n\nfrom conan.tools.files import copy\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.internal.util.files import load, save, mkdir, save_files, chdir\n\n\nclass TestToolCopy:\n\n    def test_basic(self):\n        folder1 = temp_folder()\n        sub1 = os.path.join(folder1, \"subdir1\")\n        sub2 = os.path.join(folder1, \"subdir2\")\n        save(os.path.join(sub1, \"file1.txt\"), \"hello1\")\n        save(os.path.join(sub1, \"file2.c\"), \"Hello2\")\n        save(os.path.join(sub1, \"sub1/file1.txt\"), \"Hello1 sub\")\n        save(os.path.join(sub1, \"sub1/file2.c\"), \"Hello2 sub\")\n        save(os.path.join(sub2, \"file1.txt\"), \"2 Hello1\")\n        save(os.path.join(sub2, \"file2.c\"), \"2 Hello2\")\n\n        folder2 = temp_folder()\n        copy(None, \"*.txt\", folder1, os.path.join(folder2, \"texts\"))\n        assert \"hello1\" == load(os.path.join(folder2, \"texts/subdir1/file1.txt\"))\n        assert \"Hello1 sub\" == load(os.path.join(folder2, \"texts/subdir1/sub1/file1.txt\"))\n        assert \"2 Hello1\" == load(os.path.join(folder2, \"texts/subdir2/file1.txt\"))\n        assert ['file1.txt'] == os.listdir(os.path.join(folder2, \"texts/subdir2\"))\n\n        folder2 = temp_folder()\n        copy(None, \"*.txt\", os.path.join(folder1, \"subdir1\"), os.path.join(folder2, \"texts\"))\n        assert \"hello1\" == load(os.path.join(folder2, \"texts/file1.txt\"))\n        assert \"Hello1 sub\" == load(os.path.join(folder2, \"texts/sub1/file1.txt\"))\n        assert \"subdir2\" not in os.listdir(os.path.join(folder2, \"texts\"))\n\n    @pytest.mark.skipif(platform.system() == \"Windows\", reason=\"Requires Symlinks\")\n    def test_symlinks_folder_behavior(self):\n        \"\"\"\n        https://github.com/conan-io/conan/issues/11150\n\n        test.h\n        inc/test2.h\n        gen/test.bin\n        sym/ => gen\n        \"\"\"\n\n        build_folder = temp_folder()\n        test = os.path.join(build_folder, \"test.h\")\n        save(test, \"\")\n        inc_folder = os.path.join(build_folder, \"inc\")\n        mkdir(inc_folder)\n        test2 = os.path.join(inc_folder, \"test2.h\")\n        save(test2, \"\")\n        gen_folder = os.path.join(build_folder, \"gen\")\n        mkdir(gen_folder)\n        binfile = os.path.join(gen_folder, \"test.bin\")\n        save(binfile, \"\")\n        sym_folder = os.path.join(build_folder, \"sym\")\n        os.symlink(gen_folder, sym_folder)\n\n        package_folder = temp_folder()\n        # Pattern with the sym/*.bin won't work, \"sym\" is a file (symlink to folder), not a folder\n        copy(None, \"sym/*.bin\", build_folder, package_folder)\n        assert not os.path.exists(os.path.join(package_folder, \"sym\"))\n\n        # Pattern searches in the \"inc/\" subfolder, \"sym/\" shouldn't be copied\n        copy(None, \"inc/*.h\", build_folder, package_folder)\n        assert not os.path.exists(os.path.join(package_folder, \"sym\")), \\\n            \"The sym file shouldn't exist in package_folder\"\n\n        # Even if there is a test.bin \"inside\" the \"sym/\" (gen/), the \"sym\" file shouldn't be copied\n        # because it is a file, the pattern has to match the file\n        copy(None, \"*.bin\", build_folder, package_folder)\n        assert not os.path.exists(os.path.join(package_folder, \"sym\")), \\\n            \"The sym file shouldn't exist in package_folder\"\n\n        # If the pattern matches the \"sym\" file, it will be copied (as a symlink)\n        copy(None, \"s*\", build_folder, package_folder)\n        assert os.path.exists(os.path.join(package_folder, \"sym\"))\n        assert os.path.islink(os.path.join(package_folder, \"sym\"))\n\n    @pytest.mark.skipif(platform.system() == \"Windows\", reason=\"Requires Symlinks\")\n    def test_linked_relative(self):\n        folder1 = temp_folder()\n        sub1 = os.path.join(folder1, \"foo/other/file\")\n        save(os.path.join(sub1, \"file.txt\"), \"Hello\")\n        sub2 = os.path.join(folder1, \"foo/symlink\")\n        os.symlink(\"other/file\", sub2)  # @UndefinedVariable\n\n        folder2 = temp_folder()\n        copy(None, \"*\", folder1, folder2)\n        symlink = os.path.join(folder2, \"foo\", \"symlink\")\n        assert os.path.islink(symlink)\n        assert load(os.path.join(symlink, \"file.txt\")) == \"Hello\"\n\n    @pytest.mark.skipif(platform.system() == \"Windows\", reason=\"Requires Symlinks\")\n    def test_linked_folder_nested(self):\n        # https://github.com/conan-io/conan/issues/2959\n        folder1 = temp_folder()\n        sub1 = os.path.join(folder1, \"lib/icu/60.2\")\n        sub2 = os.path.join(folder1, \"lib/icu/current\")\n        os.makedirs(sub1)\n        os.symlink(\"60.2\", sub2)  # @UndefinedVariable\n\n        folder2 = temp_folder()\n        copied = copy(None, \"*.cpp\", folder1, folder2)\n        assert copied == []\n\n    @pytest.mark.skipif(platform.system() == \"Windows\", reason=\"Requires Symlinks\")\n    def test_linked_folder_copy_from_linked_folder(self):\n        # https://github.com/conan-io/conan/issues/5114\n        folder1 = temp_folder(path_with_spaces=False)\n        sub_src = os.path.join(folder1, \"sub/src\")\n\n        src = os.path.join(folder1, \"src\")\n        src_dir = os.path.join(folder1, \"src/dir\")\n        src_dir_link = os.path.join(folder1, \"src/dir_link\")\n        src_dir_file = os.path.join(src_dir, \"file.txt\")\n\n        dst = os.path.join(folder1, \"dst\")\n        dst_dir = os.path.join(folder1, \"dst/dir\")\n        dst_dir_link = os.path.join(folder1, \"dst/dir_link\")\n        dst_dir_file = os.path.join(dst_dir, \"file.txt\")\n\n        os.makedirs(dst)\n        os.makedirs(sub_src)\n        # input src folder should be a symlink\n        os.symlink(sub_src, src)\n        # folder, file and folder link to copy\n        os.mkdir(src_dir)\n        save(src_dir_file, \"file\")\n        os.symlink(src_dir, src_dir_link)\n\n        copied = copy(None, \"dir/*\", src, dst)\n\n        # The pattern \"dir/*\" doesn't match to the symlink file \"dir_link\" so it is not copied\n        assert copied == [dst_dir_file]\n        assert not os.path.exists(dst_dir_link)\n\n        # This pattern \"dir*\" match both the symlink \"dir_link\" and the folder \"dir/\"\n        copied = copy(None, \"dir*\", src, dst)\n\n        assert copied == [dst_dir_file, dst_dir_link]\n        assert os.listdir(dst) == os.listdir(src)\n        assert os.path.islink(dst_dir_link)\n\n    def test_excludes(self):\n        folder1 = temp_folder()\n        sub1 = os.path.join(folder1, \"subdir1\")\n        save(os.path.join(sub1, \"file1.txt\"), \"hello1\")\n        save(os.path.join(sub1, \"file2.c\"), \"Hello2\")\n\n        folder2 = temp_folder()\n        copy(None, \"*.*\", folder1, os.path.join(folder2, \"texts\"), excludes=\"*.c\")\n        assert ['file1.txt'] == os.listdir(os.path.join(folder2, \"texts/subdir1\"))\n\n        folder1 = temp_folder()\n        save(os.path.join(folder1, \"MyLib.txt\"), \"\")\n        save(os.path.join(folder1, \"MyLibImpl.txt\"), \"\")\n        save(os.path.join(folder1, \"MyLibTests.txt\"), \"\")\n\n        folder2 = temp_folder()\n        copy(None, \"*.txt\", folder1, folder2, excludes=\"*Test*.txt\")\n        assert {'MyLib.txt', 'MyLibImpl.txt'} == set(os.listdir(folder2))\n\n        folder2 = temp_folder()\n        copy(None, \"*.txt\", folder1, folder2, excludes=(\"*Test*.txt\", \"*Impl*\"))\n        assert ['MyLib.txt'] == os.listdir(folder2)\n\n        folder1 = temp_folder()\n        src_dir = os.path.join(folder1, \"src_dir\")\n        dst_dir = os.path.join(folder1, \"dst_dir\")\n        os.makedirs(src_dir)\n        os.makedirs(dst_dir)\n        save(os.path.join(src_dir, \"file\"), \"nothing\")\n        save(os.path.join(dst_dir, \"file\"), \"nothing\")\n        copy(None, \"*_dir*\", folder1, folder2, excludes=[\"dst_dir\", ])\n        assert os.path.exists(os.path.join(folder2, \"src_dir\"))\n        assert not os.path.exists(os.path.join(folder2, \"dst_dir\"))\n\n    def test_excludes_hidden_files(self):\n        folder1 = temp_folder()\n        save_files(folder1, {\n            \"file1.txt\": \"\",\n            \".hiddenfile\": \"\",\n            \"foo/file2.txt\": \"\",\n            \"foo/.hiddenfile2\": \"\",\n            \".hiddenfolder/file3.txt\": \"\",\n            \"foo/bar/file4.txt\": \"\"\n        })\n\n        folder2 = temp_folder()\n        copy(None, \"*\", folder1, folder2, excludes=(\".*\", \"*/.*\"))\n        assert set(os.listdir(folder2)) == {'file1.txt', 'foo'}\n        assert set(os.listdir(os.path.join(folder2, \"foo\"))) == {'file2.txt', 'bar'}\n        assert not os.path.exists(os.path.join(folder2, \".hiddenfolder\"))\n        assert os.listdir(os.path.join(folder2, \"foo\", \"bar\")) == ['file4.txt']\n\n    def test_excludes_camelcase_folder(self):\n        # https://github.com/conan-io/conan/issues/8153\n        folder1 = temp_folder()\n        save(os.path.join(folder1, \"UPPER.txt\"), \"\")\n        save(os.path.join(folder1, \"lower.txt\"), \"\")\n        sub2 = os.path.join(folder1, \"CamelCaseIgnore\")\n        save(os.path.join(sub2, \"file3.txt\"), \"\")\n\n        folder2 = temp_folder()\n        copy(None, \"*\", folder1, folder2, excludes=[\"CamelCaseIgnore\", \"UPPER.txt\"])\n        assert not os.path.exists(os.path.join(folder2, \"CamelCaseIgnore\"))\n        assert not os.path.exists(os.path.join(folder2, \"UPPER.txt\"))\n        assert os.path.exists(os.path.join(folder2, \"lower.txt\"))\n\n        folder2 = temp_folder()\n        copy(None, \"*\", folder1, folder2)\n        assert os.path.exists(os.path.join(folder2, \"CamelCaseIgnore\"))\n        assert os.path.exists(os.path.join(folder2, \"UPPER.txt\"))\n        assert os.path.exists(os.path.join(folder2, \"lower.txt\"))\n\n    @pytest.mark.skipif(platform.system() == \"Windows\", reason=\"Requires Symlinks\")\n    def test_excludes_symlink_folder(self):\n        # https://github.com/conan-io/conan/issues/18296\n        root_folder = temp_folder(path_with_spaces=False)\n        target_folder = os.path.join(root_folder, \"target_folder\")\n        src_dir = os.path.join(root_folder, \"src_dir\")\n        os.makedirs(src_dir)\n        save(os.path.join(src_dir, \"file\"), \"nothing\")\n        os.symlink(src_dir, os.path.join(root_folder, \"link_dir\"))\n\n        copied = copy(None, \"*_dir*\", root_folder, target_folder, excludes=[\"link_dir\",])\n\n        assert os.path.exists(target_folder) and os.path.isdir(target_folder)\n        assert os.path.exists(os.path.join(target_folder, \"src_dir\", \"file\"))\n        assert not os.path.exists(os.path.join(target_folder, \"link_dir\"))\n        assert sorted(copied) == [os.path.join(target_folder, \"src_dir\", \"file\"),]\n\n    @pytest.mark.skipif(platform.system() == \"Windows\", reason=\"Requires Symlinks\")\n    def test_excludes_symlink_file(self):\n        # https://github.com/conan-io/conan/issues/18296\n        root_folder = temp_folder(path_with_spaces=False)\n        target_folder = os.path.join(root_folder, \"target_folder\")\n        save(os.path.join(root_folder, \"src_file\"), \"nothing\")\n        os.symlink(os.path.join(root_folder, \"src_file\"), os.path.join(root_folder, \"link_file\"))\n\n        copied = copy(None, \"*_file\", root_folder, target_folder, excludes=[\"link_file\", ])\n\n        assert os.path.exists(target_folder) and os.path.isdir(target_folder)\n        assert os.path.exists(os.path.join(target_folder, \"src_file\"))\n        assert not os.path.exists(os.path.join(target_folder, \"link_file\"))\n        assert copied == [os.path.join(target_folder, \"src_file\"),]\n\n    def test_multifolder(self):\n        src_folder1 = temp_folder()\n        src_folder2 = temp_folder()\n        save(os.path.join(src_folder1, \"file1.txt\"), \"hello1\")\n        save(os.path.join(src_folder2, \"file2.txt\"), \"Hello2\")\n\n        dst_folder = temp_folder()\n        copy(None, \"*\", src_folder1, dst_folder)\n        copy(None, \"*\", src_folder2, dst_folder)\n        assert ['file1.txt', 'file2.txt'] == sorted(os.listdir(dst_folder))\n\n    @mock.patch('shutil.copy2')\n    def test_avoid_repeat_copies(self, copy2_mock):\n        src_folders = [temp_folder() for _ in range(2)]\n        for index, src_folder in enumerate(src_folders):\n            save(os.path.join(src_folder, \"sub\", \"file%d.txt\" % index),\n                 \"Hello%d\" % index)\n\n        dst_folder = temp_folder()\n\n        for src_folder in src_folders:\n            copy(None, \"*\", os.path.join(src_folder, \"sub\"), dst_folder)\n\n        assert copy2_mock.call_count == len(src_folders)\n\n    def test_ignore_case(self):\n        src_folder = temp_folder()\n        save(os.path.join(src_folder, \"FooBar.txt\"), \"Hello\")\n\n        dst_folder = temp_folder()\n        copy(None, \"foobar.txt\", src_folder, dst_folder, ignore_case=False)\n        assert [] == os.listdir(dst_folder)\n\n        dst_folder = temp_folder()\n        copy(None, \"FooBar.txt\", src_folder, dst_folder, ignore_case=False)\n        assert [\"FooBar.txt\"] == os.listdir(dst_folder)\n\n        dst_folder = temp_folder()\n        copy(None, \"foobar.txt\", src_folder, dst_folder, ignore_case=True)\n        assert [\"FooBar.txt\"] == os.listdir(dst_folder)\n\n    def test_ignore_case_excludes(self):\n        src_folder = temp_folder()\n        save(os.path.join(src_folder, \"file.h\"), \"\")\n        save(os.path.join(src_folder, \"AttributeStorage.h\"), \"\")\n        save(os.path.join(src_folder, \"sub/file.h\"), \"\")\n        save(os.path.join(src_folder, \"sub/AttributeStorage.h\"), \"\")\n\n        dst_folder = temp_folder()\n        # Exclude pattern will match AttributeStorage\n        copy(None, \"*.h\", src_folder, os.path.join(dst_folder, \"include\"),\n             excludes=\"*Test*\")\n        assert [\"include\"] == os.listdir(dst_folder)\n        assert sorted([\"file.h\", \"sub\"]) == sorted(os.listdir(os.path.join(dst_folder, \"include\")))\n        assert [\"file.h\"] == os.listdir(os.path.join(dst_folder, \"include\", \"sub\"))\n\n        dst_folder = temp_folder()\n        # Exclude pattern will not match AttributeStorage if ignore_case=False\n        copy(None, \"*.h\", src_folder, os.path.join(dst_folder, \"include\"), excludes=\"*Test*\",\n             ignore_case=False)\n        assert [\"include\"] == os.listdir(dst_folder)\n        assert sorted([\"AttributeStorage.h\", \"file.h\", \"sub\"]) == sorted(os.listdir(os.path.join(dst_folder, \"include\")))\n        assert sorted([\"AttributeStorage.h\", \"file.h\"]) == sorted(os.listdir(os.path.join(dst_folder, \"include\", \"sub\")))\n\n    def test_empty_parent_folder_makedirs(self):\n        src_folder = temp_folder()\n        save(os.path.join(src_folder, \"file.h\"), \"\")\n        sources = os.path.join(src_folder, \"src\")\n        os.makedirs(sources)\n        with chdir(sources):\n            copy(None, \"*\", \"..\", dst=\".\")  # This used to crash\n            assert \"file.h\" in os.listdir(sources)\n\n    def test_keep_path_false(self):\n        folder1 = temp_folder()\n        save(os.path.join(folder1, \"file1.txt\"), \"file1\")\n        save(os.path.join(folder1, \"sub1\", \"file2.txt\"), \"file2\")\n        save(os.path.join(folder1, \"sub1\", \"file3.txt\"), \"file3\")\n        save(os.path.join(folder1, \"sub1\", \"sub12\", \"file4.txt\"), \"file4\")\n        save(os.path.join(folder1, \"sub2\", \"file5.txt\"), \"file5\")\n        save(os.path.join(folder1, \"sub2\", \"sub22\", \"file6.txt\"), \"file6\")\n        save(os.path.join(folder1, \"sub2\", \"sub22\", \"sub23\", \"file7.txt\"), \"file7\")\n\n        folder2 = temp_folder()\n        copy(None, \"*.txt\", folder1, folder2, keep_path=False)\n        for file_number in range(1, 8):\n            assert load(os.path.join(folder2, f\"file{file_number}.txt\")) == f\"file{file_number}\"\n"
  },
  {
    "path": "test/unittests/tools/files/test_toolchain.py",
    "content": "import os\nimport textwrap\n\nimport pytest\n\nfrom conan.tools.build import load_toolchain_args, save_toolchain_args, CONAN_TOOLCHAIN_ARGS_FILE, \\\n    CONAN_TOOLCHAIN_ARGS_SECTION\nfrom conan.errors import ConanException\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.internal.util.files import save, load\n\n\ndef test_load_empty_toolchain_args_in_default_dir():\n    folder = temp_folder()\n    os.chdir(folder)\n    save(CONAN_TOOLCHAIN_ARGS_FILE, \"[%s]\" % CONAN_TOOLCHAIN_ARGS_SECTION)\n    config = load_toolchain_args()\n    assert not config\n\n\ndef test_load_toolchain_args_if_it_does_not_exist():\n    folder = temp_folder()\n    os.chdir(folder)\n    with pytest.raises(ConanException):\n        load_toolchain_args()\n\n\ndef test_toolchain_args_with_content_full():\n    folder = temp_folder()\n    content = textwrap.dedent(r\"\"\"\n    [%s]\n    win_path=my\\win\\path\n    command=conan --option \"My Option\"\n    my_regex=([A-Z])\\w+\n    \"\"\" % CONAN_TOOLCHAIN_ARGS_SECTION)\n    save(os.path.join(folder,  CONAN_TOOLCHAIN_ARGS_FILE), content)\n    args = load_toolchain_args(generators_folder=folder)\n    assert args[\"win_path\"] == r'my\\win\\path'\n    assert args[\"command\"] == r'conan --option \"My Option\"'\n    assert args[\"my_regex\"] == r'([A-Z])\\w+'\n\n\ndef test_save_toolchain_args_empty():\n    folder = temp_folder()\n    content = {}\n    save_toolchain_args(content, generators_folder=folder)\n    args = load(os.path.join(folder, CONAN_TOOLCHAIN_ARGS_FILE))\n    assert \"[%s]\" % CONAN_TOOLCHAIN_ARGS_SECTION in args\n\n\ndef test_save_toolchain_args_full():\n    folder = temp_folder()\n    content = {\n        'win_path': r'my\\win\\path',\n        'command': r'conan --option \"My Option\"',\n        'my_regex': r'([A-Z])\\w+'\n    }\n    save_toolchain_args(content, generators_folder=folder)\n    args = load(os.path.join(folder, CONAN_TOOLCHAIN_ARGS_FILE))\n    assert \"[%s]\" % CONAN_TOOLCHAIN_ARGS_SECTION in args\n    assert r'win_path = my\\win\\path' in args\n"
  },
  {
    "path": "test/unittests/tools/files/test_zipping.py",
    "content": "import zipfile\nimport tarfile\nfrom os.path import join, exists\n\nimport pytest\n\nfrom conan.tools.files import unzip\nfrom conan.test.utils.mocks import ConanFileMock\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.internal.util.files import save\nfrom conan.errors import ConanException\n\n\ndef create_example_zip(root_file=True, subfolder=False):\n    tmp_dir = temp_folder()\n    archive = join(tmp_dir, \"zipfile.zip\")\n    zf = zipfile.ZipFile(archive, mode=\"w\")\n    if root_file:\n        foo_txt = join(tmp_dir, \"foo.txt\")\n        save(foo_txt, \"foo-content\")\n        zf.write(foo_txt, \"foo.txt\")\n    if subfolder:\n        src_bar_txt = join(tmp_dir, \"src\", \"bar.txt\")\n        save(src_bar_txt, \"bar-content\")\n        zf.write(src_bar_txt, join(\"src\", \"bar.txt\"))\n    zf.close()\n    return archive\n\n\ndef test_unzip():\n    archive = create_example_zip(subfolder=True)\n    conanfile = ConanFileMock({})\n\n    # Unzip and check permissions are kept\n    dest_dir = temp_folder()\n    unzip(conanfile, archive, dest_dir)\n    assert exists(join(dest_dir, \"foo.txt\"))\n    assert exists(join(dest_dir, \"src\", \"bar.txt\"))\n\n\ndef test_unzip_with_pattern():\n    archive = create_example_zip(subfolder=True)\n    conanfile = ConanFileMock({})\n\n    dest_dir = temp_folder()\n    unzip(conanfile, archive, dest_dir, pattern=\"foo.txt\")\n    assert exists(join(dest_dir, \"foo.txt\"))\n    assert not exists(join(dest_dir, \"src\", \"bar.txt\"))\n\n\ndef test_unzip_with_exclude_pattern():\n    archive = create_example_zip(subfolder=True)\n    conanfile = ConanFileMock({})\n\n    dest_dir = temp_folder()\n    unzip(conanfile, archive, dest_dir, excludes=[\"src/*\"])\n    assert exists(join(dest_dir, \"foo.txt\"))\n    assert not exists(join(dest_dir, \"src\", \"bar.txt\"))\n\n\ndef test_unzip_with_strip_root():\n    archive = create_example_zip(root_file=False, subfolder=True)\n    conanfile = ConanFileMock({})\n\n    dest_dir = temp_folder()\n    unzip(conanfile, archive, dest_dir, strip_root=True)\n    assert exists(join(dest_dir, \"bar.txt\"))\n\n\ndef test_unzip_with_strip_root_fails():\n    archive = create_example_zip(root_file=True, subfolder=True)\n    conanfile = ConanFileMock({})\n\n    dest_dir = temp_folder()\n    with pytest.raises(ConanException) as error:\n        unzip(conanfile, archive, dest_dir, strip_root=True)\n    assert \"The zip file contains more than 1 folder in the root\" in str(error.value)\n\n\ndef test_unzip_with_strip_root_and_pattern():\n    archive = create_example_zip(root_file=True, subfolder=True)\n    conanfile = ConanFileMock({})\n\n    dest_dir = temp_folder()\n    unzip(conanfile, archive, dest_dir, pattern=\"src/*\", strip_root=True)\n    assert exists(join(dest_dir, \"bar.txt\"))\n    assert not exists(join(dest_dir, \"foo.txt\"))\n\n\ndef create_example_tar(root_file=True, subfolder=False):\n    tmp_dir = temp_folder()\n    tar_path = join(tmp_dir, \"file.tgz\")\n    tar = tarfile.open(tar_path, \"w:gz\")\n    if root_file:\n        foo_txt = join(tmp_dir, \"foo.txt\")\n        save(foo_txt, \"foo-content\")\n        tar.add(foo_txt, \"foo.txt\")\n    if subfolder:\n        src_bar_txt = join(tmp_dir, \"src\", \"bar.txt\")\n        save(src_bar_txt, \"bar-content\")\n        tar.add(src_bar_txt, join(\"src\", \"bar.txt\"))\n    tar.close()\n    return tar_path\n\n\ndef test_untargz():\n    import io\n    from unittest.mock import patch\n\n    archive = create_example_tar(subfolder=True)\n    conanfile = ConanFileMock({})\n\n    with patch('sys.stderr', new_callable=io.StringIO) as mock_stderr:\n        # Unzip and check permissions are kept\n        dest_dir = temp_folder()\n        unzip(conanfile, archive, dest_dir)\n        assert exists(join(dest_dir, \"foo.txt\"))\n        assert exists(join(dest_dir, \"src\", \"bar.txt\"))\n\n        stderr_output = mock_stderr.getvalue()\n        assert f\"Uncompressing {archive} to {dest_dir}\" in stderr_output\n\n\ndef test_untargz_with_pattern():\n    archive = create_example_tar(subfolder=True)\n    conanfile = ConanFileMock({})\n\n    dest_dir = temp_folder()\n    unzip(conanfile, archive, dest_dir, pattern=\"foo.txt\")\n    assert exists(join(dest_dir, \"foo.txt\"))\n    assert not exists(join(dest_dir, \"src\", \"bar.txt\"))\n\n\ndef test_untargz_with_exclude_pattern():\n    archive = create_example_tar(subfolder=True)\n    conanfile = ConanFileMock({})\n\n    dest_dir = temp_folder()\n    unzip(conanfile, archive, dest_dir, excludes=[\"src/*\"])\n    assert exists(join(dest_dir, \"foo.txt\"))\n    assert not exists(join(dest_dir, \"src\", \"bar.txt\"))\n\n\ndef test_untargz_with_strip_root():\n    archive = create_example_tar(root_file=False, subfolder=True)\n    conanfile = ConanFileMock({})\n\n    # Unzip and check permissions are kept\n    dest_dir = temp_folder()\n    unzip(conanfile, archive, dest_dir, strip_root=True)\n    assert exists(join(dest_dir, \"bar.txt\"))\n\n\ndef test_untargz_with_strip_root_fails():\n    archive = create_example_tar(root_file=True, subfolder=True)\n    conanfile = ConanFileMock({})\n\n    # Unzip and check permissions are kept\n    dest_dir = temp_folder()\n    with pytest.raises(ConanException) as e:\n        unzip(conanfile, archive, dest_dir, strip_root=True)\n    assert \"Can't untar a tgz containing files in the root with strip_root enabled\" in str(e.value)\n\n\ndef test_untargz_with_strip_root_and_pattern():\n    archive = create_example_tar(root_file=True, subfolder=True)\n    conanfile = ConanFileMock({})\n\n    # Unzip and check permissions are kept\n    dest_dir = temp_folder()\n    unzip(conanfile, archive, dest_dir, pattern=\"src/*\", strip_root=True)\n    assert exists(join(dest_dir, \"bar.txt\"))\n    assert not exists(join(dest_dir, \"foo.txt\"))\n"
  },
  {
    "path": "test/unittests/tools/files_patch_test.py",
    "content": "import os\nfrom textwrap import dedent\n\nimport pytest\n\nfrom conan.internal.loader import ConanFileLoader\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import save, load\n\nbase_conanfile = '''\nfrom conan import ConanFile\nfrom conan.tools.files import patch, replace_in_file\nimport os\n\nclass ConanFileToolsTest(ConanFile):\n    name = \"test\"\n    version = \"1.9.10\"\n'''\n\n\nclass TestToolsFilesPatch:\n\n    @pytest.mark.parametrize(\"strip\", [0, 1])\n    def test_patch_from_file(self, strip):\n        if strip:\n            file_content = base_conanfile + '''\n    def build(self):\n        patch(self, patch_file=\"file.patch\", strip=%s)\n''' % strip\n            patch_content = '''--- %s/text.txt\\t2016-01-25 17:57:11.452848309 +0100\n+++ %s/text_new.txt\\t2016-01-25 17:57:28.839869950 +0100\n@@ -1 +1 @@\n-ONE TWO THREE\n+ONE TWO FOUR''' % (\"old_path\", \"new_path\")\n        else:\n            file_content = base_conanfile + '''\n    def build(self):\n        patch(self, patch_file=\"file.patch\")\n'''\n            patch_content = '''--- text.txt\\t2016-01-25 17:57:11.452848309 +0100\n+++ text_new.txt\\t2016-01-25 17:57:28.839869950 +0100\n@@ -1 +1 @@\n-ONE TWO THREE\n+ONE TWO FOUR'''\n\n        tmp_dir, file_path, text_file = self._save_files(file_content)\n        patch_file = os.path.join(tmp_dir, \"file.patch\")\n        save(patch_file, patch_content)\n        self._build_and_check(tmp_dir, file_path, text_file, \"ONE TWO FOUR\")\n\n    def test_patch_from_str(self):\n        file_content = base_conanfile + '''\n    def build(self):\n        patch_content = \\'''--- text.txt\\t2016-01-25 17:57:11.452848309 +0100\n+++ text_new.txt\\t2016-01-25 17:57:28.839869950 +0100\n@@ -1 +1 @@\n-ONE TWO THREE\n+ONE TWO DOH!\\'''\n        patch(self, patch_string=patch_content)\n\n'''\n        tmp_dir, file_path, text_file = self._save_files(file_content)\n        self._build_and_check(tmp_dir, file_path, text_file, \"ONE TWO DOH!\")\n\n    def test_patch_strip_new(self):\n        conanfile = dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import patch\n            class PatchConan(ConanFile):\n                def source(self):\n                    patch(self, self.source_folder, \"example.patch\", strip=1)\"\"\")\n        patch = dedent(\"\"\"\n            --- /dev/null\n            +++ b/src/newfile\n            @@ -0,0 +0,1 @@\n            +New file!\"\"\")\n\n        client = TestClient()\n        client.save({\"conanfile.py\": conanfile,\n                     \"example.patch\": patch})\n        client.run(\"source .\")\n        assert client.load(\"newfile\") == \"New file!\"\n\n    def test_patch_strip_delete(self):\n        conanfile = dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import patch\n            class PatchConan(ConanFile):\n                def source(self):\n                    patch(self, self.source_folder, \"example.patch\", strip=1)\"\"\")\n        patch = dedent(r\"\"\"\n            --- a\\src\\oldfile\n            +++ b/dev/null\n            @@ -0,1 +0,0 @@\n            -legacy code\"\"\")\n        client = TestClient()\n        client.save({\"conanfile.py\": conanfile,\n                     \"example.patch\": patch,\n                     \"oldfile\": \"legacy code\"})\n        path = os.path.join(client.current_folder, \"oldfile\")\n        assert os.path.exists(path)\n        client.run(\"source .\")\n        assert not os.path.exists(path)\n\n    def test_patch_strip_delete_no_folder(self):\n        conanfile = dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import patch\n            class PatchConan(ConanFile):\n                def source(self):\n                    patch(self, self.source_folder, \"example.patch\", strip=1)\"\"\")\n        patch = dedent(\"\"\"\n            --- a/oldfile\n            +++ b/dev/null\n            @@ -0,1 +0,0 @@\n            -legacy code\"\"\")\n        client = TestClient()\n        client.save({\"conanfile.py\": conanfile,\n                     \"example.patch\": patch,\n                     \"oldfile\": \"legacy code\"})\n        path = os.path.join(client.current_folder, \"oldfile\")\n        assert os.path.exists(path)\n        client.run(\"source .\")\n        assert not os.path.exists(path)\n\n    def test_patch_new_delete(self):\n        conanfile = base_conanfile + '''\n    def build(self):\n        from conan.tools.files import load, save\n        save(self, \"oldfile\", \"legacy code\")\n        assert(os.path.exists(\"oldfile\"))\n        patch_content = \"\"\"--- /dev/null\n+++ b/newfile\n@@ -0,0 +0,3 @@\n+New file!\n+New file!\n+New file!\n--- a/oldfile\n+++ b/dev/null\n@@ -0,1 +0,0 @@\n-legacy code\n\"\"\"\n        patch(self, patch_string=patch_content)\n        self.output.info(\"NEW FILE=%s\" % load(self, \"newfile\"))\n        self.output.info(\"OLD FILE=%s\" % os.path.exists(\"oldfile\"))\n'''\n        client = TestClient()\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --user=user --channel=testing\")\n        assert \"test/1.9.10@user/testing: NEW FILE=New file!\\nNew file!\\nNew file!\\n\" in client.out\n        assert \"test/1.9.10@user/testing: OLD FILE=False\" in client.out\n\n    def test_patch_new_strip(self):\n        conanfile = base_conanfile + '''\n    def build(self):\n        from conan.tools.files import load, save\n        patch_content = \"\"\"--- /dev/null\n+++ b/newfile\n@@ -0,0 +0,3 @@\n+New file!\n+New file!\n+New file!\n\"\"\"\n        patch(self, patch_string=patch_content, strip=1)\n        self.output.info(\"NEW FILE=%s\" % load(self, \"newfile\"))\n'''\n        client = TestClient()\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"create . --user=user --channel=testing\")\n        assert \"test/1.9.10@user/testing: NEW FILE=New file!\\nNew file!\\nNew file!\\n\" in client.out\n\n    def test_error_patch(self):\n        file_content = base_conanfile + '''\n    def build(self):\n        patch_content = \"some corrupted patch\"\n        patch(self, patch_string=patch_content, output=self.output)\n\n'''\n        client = TestClient()\n        client.save({\"conanfile.py\": file_content})\n        client.run(\"install .\")\n        client.run(\"build .\", assert_error=True)\n        assert \"patch_ng: error: no patch data found!\" in client.out\n        assert \"ERROR: conanfile.py (test/1.9.10): Error in build() method, line 12\" in client.out\n        assert \"Failed to parse patch: string\" in client.out\n\n    def test_add_new_file(self):\n        \"\"\" Validate issue #5320\n        \"\"\"\n\n        conanfile = dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import patch\n            import os\n\n            class ConanFileToolsTest(ConanFile):\n                name = \"foobar\"\n                version = \"0.1.0\"\n                exports_sources = \"*\"\n\n                def build(self):\n                    patch(self, patch_file=\"add_files.patch\")\n                    assert os.path.isfile(\"foo.txt\")\n                    assert os.path.isfile(\"bar.txt\")\n        \"\"\")\n        bar = \"no creo en brujas\"\n        patch = dedent(\"\"\"\n            From c66347c66991b6e617d107b505c18b3115624b8a Mon Sep 17 00:00:00 2001\n            From: Uilian Ries <uilianries@gmail.com>\n            Date: Wed, 16 Oct 2019 14:31:34 -0300\n            Subject: [PATCH] add foo\n\n            ---\n             bar.txt | 3 ++-\n             foo.txt | 3 +++\n             2 files changed, 5 insertions(+), 1 deletion(-)\n             create mode 100644 foo.txt\n\n            diff --git a/bar.txt b/bar.txt\n            index 0f4ff3a..0bd3158 100644\n            --- a/bar.txt\n            +++ b/bar.txt\n            @@ -1 +1,2 @@\n            -no creo en brujas\n            +Yo no creo en brujas, pero que las hay, las hay\n            +\n            diff --git a/foo.txt b/foo.txt\n            new file mode 100644\n            index 0000000..91e8c0d\n            --- /dev/null\n            +++ b/foo.txt\n            @@ -0,0 +1,3 @@\n            +For us, there is no spring.\n            +Just the wind that smells fresh before the storm.\n            +\n            --\n            2.23.0\n\n\n        \"\"\")\n\n        client = TestClient()\n        client.save({\"conanfile.py\": conanfile,\n                     \"add_files.patch\": patch,\n                     \"bar.txt\": bar})\n        client.run(\"install .\")\n        client.run(\"build .\")\n        bar_content = client.load(\"bar.txt\")\n        assert dedent(\"\"\"Yo no creo en brujas, pero que las hay, las hay\n                             \"\"\") in bar_content\n        foo_content = client.load(\"foo.txt\")\n        assert dedent(\"\"\"For us, there is no spring.\nJust the wind that smells fresh before the storm.\"\"\") in foo_content\n        assert \"Calling build()\" in client.out\n        assert \"Warning\" not in client.out\n\n    def _save_files(self, file_content):\n        tmp_dir = temp_folder()\n        file_path = os.path.join(tmp_dir, \"conanfile.py\")\n        text_file = os.path.join(tmp_dir, \"text.txt\")\n        save(file_path, file_content)\n        save(text_file, \"ONE TWO THREE\")\n        return tmp_dir, file_path, text_file\n\n    def _build_and_check(self, tmp_dir, file_path, text_file, msg):\n        loader = ConanFileLoader(None)\n        ret = loader.load_consumer(file_path)\n        curdir = os.path.abspath(os.curdir)\n        ret.folders.set_base_source(os.path.dirname(file_path))\n        ret.folders.set_base_export_sources(os.path.dirname(file_path))\n        os.chdir(tmp_dir)\n        try:\n            ret.build()\n        finally:\n            os.chdir(curdir)\n\n        content = load(text_file)\n        assert content == msg\n\n    def test_fuzzy_patch(self):\n        conanfile = dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import patch\n            import os\n\n            class ConanFileToolsTest(ConanFile):\n                name = \"fuzz\"\n                version = \"0.1.0\"\n                exports_sources = \"*\"\n\n                def build(self):\n                    patch(self, patch_file=\"fuzzy.patch\", fuzz=True)\n        \"\"\")\n        source = dedent(\"\"\"X\nY\nZ\"\"\")\n        patch = dedent(\"\"\"diff --git a/Jamroot b/Jamroot\nindex a6981dd..0c08f09 100644\n--- a/Jamroot\n+++ b/Jamroot\n@@ -1,3 +1,4 @@\n X\n YYYY\n+V\n W\"\"\")\n        expected = dedent(\"\"\"X\nY\nV\nZ\"\"\")\n        client = TestClient()\n        client.save({\"conanfile.py\": conanfile,\n                     \"fuzzy.patch\": patch,\n                     \"Jamroot\": source})\n        client.run(\"install .\")\n        client.run(\"build .\")\n        content = client.load(\"Jamroot\")\n        assert expected in content\n"
  },
  {
    "path": "test/unittests/tools/gnu/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/tools/gnu/autotools_test.py",
    "content": "import pytest\nimport os\nfrom unittest.mock import patch\n\nfrom conan.tools.build import save_toolchain_args\nfrom conan.tools.gnu import Autotools\nfrom conan.test.utils.mocks import ConanFileMock, MockSettings\nfrom conan.test.utils.test_files import temp_folder\n\n\n@patch('conan.tools.gnu.autotools.chdir')\ndef test_source_folder_works(chdir_mock):\n    folder = temp_folder()\n    os.chdir(folder)\n    save_toolchain_args({\n        \"configure_args\": \"-foo bar\",\n        \"make_args\": \"\",\n        \"autoreconf_args\": \"-bar foo\"}\n    )\n    conanfile = ConanFileMock()\n    sources = \"/path/to/sources\"\n    conanfile.folders.set_base_source(sources)\n    autotools = Autotools(conanfile)\n    autotools.configure(build_script_folder=\"subfolder\")\n    assert conanfile.command.replace(\"\\\\\", \"/\") == '\"/path/to/sources/subfolder/configure\" -foo bar '\n\n    autotools = Autotools(conanfile)\n    autotools.configure()\n    assert conanfile.command.replace(\"\\\\\", \"/\") == '\"/path/to/sources/configure\" -foo bar '\n\n    autotools.autoreconf(build_script_folder=\"subfolder\")\n    chdir_mock.assert_called_with(autotools,\n                                  os.path.normpath(os.path.join(\"/path/to/sources\", \"subfolder\")))\n\n    autotools.autoreconf()\n    chdir_mock.assert_called_with(autotools, os.path.normpath(\"/path/to/sources\"))\n    assert conanfile.command == 'autoreconf -bar foo'\n\n\n@pytest.mark.parametrize(\"install_strip\", [False, True])\ndef test_install_strip(install_strip):\n    \"\"\"\n    When the configuration `tools.build:install_strip` is set to True,\n    the Autotools install command should invoke the `install-strip` target.\n    \"\"\"\n    folder = temp_folder()\n    os.chdir(folder)\n    save_toolchain_args({})\n    settings = MockSettings({\"build_type\": \"Release\",\n                             \"compiler\": \"gcc\",\n                             \"compiler.version\": \"7\",\n                             \"os\": \"Linux\",\n                             \"arch\": \"x86_64\"})\n    conanfile = ConanFileMock()\n    conanfile.settings = settings\n    conanfile.conf.define(\"tools.build:install_strip\", install_strip)\n    conanfile.folders.generators = \".\"\n\n    autotools = Autotools(conanfile)\n    autotools.install()\n\n    assert ('install-strip' in str(conanfile.command)) == install_strip\n\n\ndef test_configure_arguments():\n    tmp = temp_folder()\n    os.chdir(tmp)\n    save_toolchain_args({\n        \"configure_args\": \"my_configure_args\",\n        \"make_args\": \"my_make_args\"}\n    )\n\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\"os\": \"Linux\"})\n    conanfile.folders.set_base_source(tmp)\n    conanfile.conf.define(\"tools.gnu:make_program\", \"my_make\")\n    conanfile.conf.define(\"tools.build:jobs\", 23)\n\n    ab = Autotools(conanfile)\n    ab.configure()\n    assert \"configure\\\" my_configure_args\" in str(conanfile.command)\n\n    ab = Autotools(conanfile)\n    ab.make()\n    assert \"my_make my_make_args -j23\" == str(conanfile.command)\n\n    # test install target argument\n\n    ab.install()\n    assert 'my_make install my_make_args DESTDIR=None -j23' == str(conanfile.command)\n\n    ab.install(target=\"install_other\")\n    assert 'my_make install_other my_make_args DESTDIR=None -j23' == str(conanfile.command)\n\n\n@pytest.mark.parametrize(\"make_args\", [\"my_make_args\", None])\ndef test_configure_install_arguments(make_args):\n    tmp = temp_folder()\n    os.chdir(tmp)\n\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\"os\": \"Linux\"})\n    conanfile.settings_build = conanfile.settings\n    conanfile.folders.set_base_source(tmp)\n    conanfile.conf.define(\"tools.gnu:make_program\", \"my_make\")\n    conanfile.conf.define(\"tools.build:jobs\", 23)\n    save_toolchain_args({\n        \"configure_args\": \"my_configure_args\",\n        \"make_args\": f\"{make_args or ''}\"}\n    )\n\n    ab = Autotools(conanfile)\n\n    make_args = f\" {make_args}\" if make_args else \"\"\n\n    ab.make(args=[\"-j1\"])\n    assert \"-j23\" not in str(conanfile.command)\n    assert f\"my_make{make_args} -j1\" == str(conanfile.command)\n\n    ab.install(args=[\"-j1\"])\n    assert \"-j23\" not in str(conanfile.command)\n    assert f\"my_make install{make_args} DESTDIR=None -j1\" == str(conanfile.command)\n\n    ab.install(args=[\"DESTDIR=whatever\", \"-j1\"])\n    assert \"-j23\" not in str(conanfile.command)\n    assert f\"my_make install{make_args} DESTDIR=whatever -j1\" == str(conanfile.command)\n\n    ab.install(args=[\"DESTDIR=whatever\", \"-arg1 -j1 -arg2\"])\n    assert \"-j23\" not in str(conanfile.command)\n    assert f\"my_make install{make_args} DESTDIR=whatever -arg1 -j1 -arg2\" == str(conanfile.command)\n\n    # check that we don't detect -j in an argument as number of jobs\n    ab.install(args=[\"DESTDIR=/user/smith-john/what\"])\n    assert f\"my_make install{make_args} DESTDIR=/user/smith-john/what -j23\" == str(conanfile.command)\n\n    # check that we don't detect -j in an argument as number of jobs\n    ab.install(args=[\"DESTDIR=/user/smith-j47/what\"])\n    assert f\"my_make install{make_args} DESTDIR=/user/smith-j47/what -j23\" == str(conanfile.command)\n"
  },
  {
    "path": "test/unittests/tools/gnu/autotools_toolchain_test.py",
    "content": "import os\nimport platform\nfrom unittest.mock import patch, MagicMock\n\nimport pytest\n\nfrom conan.errors import ConanException\nfrom conan.test.utils.mocks import ConanFileMock, MockSettings, MockOptions\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.tools.build import load_toolchain_args\nfrom conan.tools.files import save\nfrom conan.tools.gnu import AutotoolsToolchain\nfrom conan.internal.model.conf import Conf\n\n\ndef test_modify_environment():\n    \"\"\"We can alter the environment generated by the toolchain passing the env to the generate\"\"\"\n    f = temp_folder()\n    os.chdir(f)\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\"os\": \"Linux\", \"arch\": \"x86_64\"})\n    conanfile.settings_build = MockSettings({\"os\": \"Solaris\", \"arch\": \"x86\"})\n    be = AutotoolsToolchain(conanfile)\n    env = be.environment()\n    env.define(\"foo\", \"var\")\n    # We can pass the env to the generate once we adjusted or injected anything\n    be.generate(env)\n\n    with open(\"conanautotoolstoolchain.sh\") as f:\n        content = f.read()\n        assert \"foo\" in content\n\n\ndef test_target_triple():\n    f = temp_folder()\n    os.chdir(f)\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\"os\": \"Linux\", \"arch\": \"x86_64\"})\n    conanfile.settings_build = MockSettings({\"os\": \"Solaris\", \"arch\": \"x86\"})\n    conanfile.conf = Conf()\n    conanfile.conf.define(\"tools.gnu:make_program\", \"my_make\")\n    conanfile.conf.define(\"tools.gnu.make:jobs\", \"23\")\n\n    be = AutotoolsToolchain(conanfile)\n    be.make_args = [\"foo\", \"var\"]\n    be.generate_args()\n    obj = load_toolchain_args()\n    assert \"--host=x86_64-linux-gnu\" in obj[\"configure_args\"]\n    assert \"--build=i686-solaris\" in obj[\"configure_args\"]\n    assert obj[\"make_args\"].replace(\"'\", \"\") == \"foo var\"\n\n\ndef test_invalid_target_triple():\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\"os\": \"Linux\", \"arch\": \"UNKNOWN_ARCH\"})\n    conanfile.settings_build = MockSettings({\"os\": \"Solaris\", \"arch\": \"x86\"})\n    with pytest.raises(ConanException) as excinfo:\n        AutotoolsToolchain(conanfile)\n    assert \"Unknown 'UNKNOWN_ARCH' machine, Conan doesn't know how \" \\\n           \"to translate it to the GNU triplet,\" in str(excinfo)\n\n\ndef test_custom_host_triple():\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\"os\": \"Linux\", \"arch\": \"x86\"})\n    conanfile.settings_build = MockSettings({\"os\": \"Linux\", \"arch\": \"x86_64\"})\n    conanfile.conf.define(\"tools.gnu:host_triplet\", \"i686-pc-linux-gnu\")\n    tc = AutotoolsToolchain(conanfile)\n    tc.generate_args()\n    obj = load_toolchain_args()\n    assert \"--host=i686-pc-linux-gnu\" in obj[\"configure_args\"]\n\n\ndef test_custom_build_triple():\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\"os\": \"Linux\", \"arch\": \"x86\"})\n    conanfile.settings_build = MockSettings({\"os\": \"Linux\", \"arch\": \"x86_64\"})\n    conanfile.conf.define(\"tools.gnu:build_triplet\", \"i686-pc-linux-gnu\")\n    tc = AutotoolsToolchain(conanfile)\n    tc.generate_args()\n    obj = load_toolchain_args()\n    assert \"--build=i686-pc-linux-gnu\" in obj[\"configure_args\"]\n\n\ndef test_cppstd():\n    # Using \"cppstd\" is discarded\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings(\n        {\"build_type\": \"Release\",\n         \"arch\": \"x86\",\n         \"compiler\": \"gcc\",\n         \"compiler.libcxx\": \"libstdc++11\",\n         \"compiler.version\": \"7.1\",\n         \"cppstd\": \"17\"})\n    conanfile.settings_build = MockSettings({\"os\": \"Linux\", \"arch\": \"x86\"})\n    be = AutotoolsToolchain(conanfile)\n    env = be.vars()\n    assert \"-std=c++17\" not in env[\"CXXFLAGS\"]\n\n    # Using \"compiler.cppstd\" works\n    conanfile.settings = MockSettings(\n        {\"build_type\": \"Release\",\n         \"arch\": \"x86\",\n         \"compiler\": \"gcc\",\n         \"compiler.libcxx\": \"libstdc++11\",\n         \"compiler.version\": \"7.1\",\n         \"compiler.cppstd\": \"17\"})\n    be = AutotoolsToolchain(conanfile)\n    env = be.vars()\n    assert \"-std=c++17\" in env[\"CXXFLAGS\"]\n\n    # With visual\n    conanfile.settings = MockSettings(\n        {\"build_type\": \"Release\",\n         \"arch\": \"x86\",\n         \"compiler\": \"msvc\",\n         \"compiler.version\": \"190\",\n         \"compiler.cppstd\": \"17\"})\n    be = AutotoolsToolchain(conanfile)\n    env = be.vars()\n    assert \"/std:c++latest\" in env[\"CXXFLAGS\"]\n\n    # With MSVC\n    conanfile.settings = MockSettings(\n        {\"build_type\": \"Release\",\n         \"arch\": \"x86\",\n         \"compiler\": \"msvc\",\n         \"compiler.version\": \"193\",\n         \"compiler.cppstd\": \"17\"})\n    be = AutotoolsToolchain(conanfile)\n    env = be.vars()\n    assert \"/std:c++17\" in env[\"CXXFLAGS\"]\n\n\ndef test_cstd():\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings(\n        {\"build_type\": \"Release\",\n         \"arch\": \"x86\",\n         \"compiler\": \"gcc\",\n         \"compiler.libcxx\": \"libstdc++11\",\n         \"compiler.version\": \"7.1\",\n         \"compiler.cstd\": \"17\"})\n    conanfile.settings_build = MockSettings({\"os\": \"Linux\", \"arch\": \"x86\"})\n    be = AutotoolsToolchain(conanfile)\n    env = be.vars()\n    assert \"-std=c17\" in env[\"CFLAGS\"]\n\n\ndef test_fpic():\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\"os\": \"Linux\"})\n    conanfile.settings_build = MockSettings({\"os\": \"Linux\"})\n    conanfile.options = MockOptions({\"fPIC\": True})\n    be = AutotoolsToolchain(conanfile)\n    be.vars()\n    assert be.fpic is True\n    assert \"-fPIC\" in be.cxxflags\n\n    conanfile.options = MockOptions({\"fPIC\": False})\n    be = AutotoolsToolchain(conanfile)\n    be.vars()\n    assert be.fpic is False\n    assert \"-fPIC\" not in be.cxxflags\n\n    conanfile.options = MockOptions({\"shared\": False})\n    be = AutotoolsToolchain(conanfile)\n    be.vars()\n    assert be.fpic is None\n    assert \"-fPIC\" not in be.cxxflags\n\n\ndef test_ndebug():\n    conanfile = ConanFileMock()\n    for bt in ['Release', 'RelWithDebInfo', 'MinSizeRel']:\n        conanfile.settings = MockSettings({\"build_type\": bt})\n        conanfile.settings_build = MockSettings({\"os\": \"Linux\", \"arch\": \"x86_64\"})\n        be = AutotoolsToolchain(conanfile)\n        assert be.ndebug == \"NDEBUG\"\n        env = be.vars()\n        assert \"-DNDEBUG\" in env[\"CPPFLAGS\"]\n    for bt in ['Debug', 'DebWithDebInfo']:\n        conanfile.settings = MockSettings({\"build_type\": bt})\n        be = AutotoolsToolchain(conanfile)\n        assert be.ndebug is None\n        env = be.vars()\n        assert \"-DNDEBUG\" not in env[\"CPPFLAGS\"]\n\n\n@pytest.mark.parametrize(\"config\", [\n    (\"gcc\", 'libstdc++', None),\n    (\"clang\", 'libstdc++', '-stdlib=libstdc++'),\n    (\"clang\", 'libstdc++11', '-stdlib=libstdc++'),\n    (\"clang\", 'libc++', '-stdlib=libc++'),\n    (\"apple-clang\", 'libstdc++', '-stdlib=libstdc++'),\n    (\"apple-clang\", 'libc++', '-stdlib=libc++'),\n    (\"sun-cc\", 'libCstd', '-library=Cstd'),\n    (\"sun-cc\", 'libstdcxx', '-library=stdcxx4'),\n    (\"sun-cc\", 'libstlport', '-library=stlport4'),\n    (\"sun-cc\", 'libstdc++', '-library=stdcpp'),\n    (\"qcc\", 'libCstd', '-Y _libCstd'),\n    (\"qcc\", 'libstdcxx', '-Y _libstdcxx'),\n    (\"qcc\", 'libstlport', '-Y _libstlport'),\n    (\"qcc\", 'libstdc++', '-Y _libstdc++'),\n    ])\ndef test_libcxx(config):\n    compiler, libcxx, expected_flag = config\n    conanfile = ConanFileMock()\n    the_os = \"Linux\" if compiler != \"apple-clang\" else \"Macos\"\n    conanfile.settings = MockSettings(\n        {\"os\": the_os,\n         \"build_type\": \"Release\",\n         \"arch\": \"x86\",\n         \"compiler\": compiler,\n         \"compiler.libcxx\": libcxx,\n         \"compiler.version\": \"7.1\",\n         \"compiler.cppstd\": \"17\"})\n    conanfile.settings_build = conanfile.settings\n    be = AutotoolsToolchain(conanfile)\n    assert be.libcxx == expected_flag\n    env = be.vars()\n    if expected_flag:\n        assert expected_flag in env[\"CXXFLAGS\"]\n\n\ndef test_disable_libcxx():\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings(\n        {\"os\": \"Linux\",\n         \"build_type\": \"Release\",\n         \"arch\": \"x86\",\n         \"compiler\": \"clang\",\n         \"compiler.libcxx\": \"libc++\",\n         \"compiler.version\": \"7.1\",\n         \"compiler.cppstd\": \"17\",\n         \"compiler.cstd\": \"99\"})\n    conanfile.settings_build = conanfile.settings\n    # Disable just one\n    conanfile.conf.define(\"tools.gnu:disable_flags\", [\"libcxx\"])\n    be = AutotoolsToolchain(conanfile)\n    assert be.libcxx is None\n    assert be.arch_flag == \"-m32\"\n    assert be.build_type_flags == ['-O3']\n    assert be.cppstd == \"-std=c++17\"\n    assert be.cstd == \"-std=c99\"\n    # Disable two\n    conanfile.conf.define(\"tools.gnu:disable_flags\", [\"libcxx\", \"cppstd\"])\n    be = AutotoolsToolchain(conanfile)\n    assert be.libcxx is None\n    assert be.arch_flag == \"-m32\"\n    assert be.build_type_flags == ['-O3']\n    assert be.cppstd == \"\"\n    assert be.cstd == \"-std=c99\"\n    # Error value\n    conanfile.conf.define(\"tools.gnu:disable_flags\", [\"other\"])\n    try:\n        AutotoolsToolchain(conanfile)\n    except ConanException as e:\n        assert \"tools.gnu:disable_flags value 'other', must be one of:\" in str(e)\n    conanfile.conf.define(\"tools.gnu:disable_flags\",\n                          [\"arch\", \"arch_link\", \"libcxx\", \"build_type\",\n                           \"build_type_link\", \"threads\", \"cppstd\", \"cstd\"])\n    be = AutotoolsToolchain(conanfile)\n    assert be.libcxx is None\n    assert be.arch_flag == \"\"\n    assert be.build_type_flags == []\n    assert be.cppstd == \"\"\n    assert be.cstd == \"\"\n\n\ndef test_cxx11_abi_define():\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings(\n        {\"os\": \"Linux\",\n         \"build_type\": \"Release\",\n         \"arch\": \"x86\",\n         \"compiler\": \"gcc\",\n         \"compiler.libcxx\": \"libstdc++\",\n         \"compiler.version\": \"7.1\",\n         \"compiler.cppstd\": \"17\"})\n    conanfile.settings_build = conanfile.settings\n    be = AutotoolsToolchain(conanfile)\n    assert be.gcc_cxx11_abi == \"_GLIBCXX_USE_CXX11_ABI=0\"\n    env = be.vars()\n    assert \"-D_GLIBCXX_USE_CXX11_ABI=0\" in env[\"CPPFLAGS\"]\n\n    conanfile.settings = MockSettings(\n        {\"os\": \"Linux\",\n         \"build_type\": \"Release\",\n         \"arch\": \"x86\",\n         \"compiler\": \"gcc\",\n         \"compiler.libcxx\": \"libstdc++11\",\n         \"compiler.version\": \"7.1\",\n         \"compiler.cppstd\": \"17\"})\n    be = AutotoolsToolchain(conanfile)\n    env = be.vars()\n    assert be.gcc_cxx11_abi is None\n    assert \"GLIBCXX_USE_CXX11_ABI\" not in env[\"CPPFLAGS\"]\n\n    # Force the GLIBCXX_USE_CXX11_ABI=1 for old distros is direct def f ``gcc_cxx11_abi``\n    be.gcc_cxx11_abi = \"_GLIBCXX_USE_CXX11_ABI=1\"\n    env = be.vars()\n    assert \"-D_GLIBCXX_USE_CXX11_ABI=1\" in env[\"CPPFLAGS\"]\n\n    # Also conf is possible\n    conanfile.conf.define(\"tools.gnu:define_libcxx11_abi\", True)\n    be = AutotoolsToolchain(conanfile)\n    env = be.vars()\n    assert \"-D_GLIBCXX_USE_CXX11_ABI=1\" in env[\"CPPFLAGS\"]\n\n\n@pytest.mark.parametrize(\"config\", [\n    ('x86_64', \"-m64\"),\n    ('x86', \"-m32\")])\ndef test_architecture_flag(config):\n    \"\"\"Architecture flag is set in CXXFLAGS, CFLAGS and LDFLAGS\"\"\"\n    arch, expected = config\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings(\n        {\"build_type\": \"Release\",\n         \"os\": \"Macos\",\n         \"compiler\": \"gcc\",\n         \"arch\": arch})\n    conanfile.settings_build = conanfile.settings\n    be = AutotoolsToolchain(conanfile)\n    assert be.arch_flag == expected\n    env = be.vars()\n    assert expected in env[\"CXXFLAGS\"]\n    assert expected in env[\"CFLAGS\"]\n    assert expected in env[\"LDFLAGS\"]\n    assert \"-debug\" not in env[\"LDFLAGS\"]\n\n\n@pytest.mark.parametrize(\"config\", [\n    (\"gcc\", \"x86_64\", \"\"),\n    (\"emcc\", \"wasm\", \"\"),\n    (\"emcc\", \"wasm64\", \"\"),\n    (\"emcc\", \"asm.js\", \"-sWASM=0\")])\ndef test_architecture_link_flag(config):\n    compiler, arch, expected = config\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings(\n        {\"build_type\": \"Release\",\n         \"os\": \"Emscripten\",\n         \"compiler\": compiler,\n         \"arch\": arch})\n    conanfile.settings_build = conanfile.settings\n    be = AutotoolsToolchain(conanfile)\n    assert be.arch_ld_flag == expected\n    env = be.vars()\n    assert \"\" in env[\"CXXFLAGS\"]\n    assert \"\" in env[\"CFLAGS\"]\n    assert expected in env[\"LDFLAGS\"]\n\n\n@pytest.mark.parametrize(\"compiler\", ['msvc'])\ndef test_build_type_flag(compiler):\n    \"\"\"Architecture flag is set in CXXFLAGS, CFLAGS and LDFLAGS\"\"\"\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings(\n        {\"build_type\": \"Debug\",\n         \"os\": \"Windows\",\n         \"compiler\": compiler,\n         \"arch\": \"x86_64\"})\n    conanfile.settings_build = conanfile.settings\n    be = AutotoolsToolchain(conanfile)\n    assert be.build_type_flags == [\"-Zi\", \"-Ob0\", \"-Od\"]\n    env = be.vars()\n    assert \"-Zi -Ob0 -Od\" in env[\"CXXFLAGS\"]\n    assert \"-Zi -Ob0 -Od\" in env[\"CFLAGS\"]\n    assert \"-Zi -Ob0 -Od\" not in env[\"LDFLAGS\"]\n    assert \"-debug\" in env[\"LDFLAGS\"]\n\n\ndef test_apple_arch_flag():\n    conanfile = ConanFileMock()\n    conanfile.conf.define(\"tools.apple:sdk_path\", \"/path/to/sdk\")\n    conanfile.settings_build = MockSettings(\n        {\"build_type\": \"Debug\",\n         \"os\": \"Macos\",\n         \"arch\": \"x86_64\"})\n    conanfile.settings = MockSettings(\n        {\"build_type\": \"Debug\",\n         \"os\": \"iOS\",\n         \"os.version\": \"14\",\n         \"os.sdk\": \"iphoneos\",\n         \"arch\": \"armv8\"})\n    be = AutotoolsToolchain(conanfile)\n    expected = \"-arch arm64\"\n    assert be.apple_arch_flag == expected\n    env = be.vars()\n    assert expected in env[\"CXXFLAGS\"]\n    assert expected in env[\"CFLAGS\"]\n    assert expected in env[\"LDFLAGS\"]\n\n    # Only set when crossbuilding\n    conanfile = ConanFileMock()\n    conanfile.conf.define(\"tools.apple:sdk_path\", \"/path/to/sdk\")\n    conanfile.settings = MockSettings(\n        {\"build_type\": \"Debug\",\n         \"os\": \"Macos\",\n         \"os.version\": \"14\",\n         \"arch\": \"x86_64\"})\n    conanfile.settings_build = MockSettings({\"os\": \"Macos\", \"arch\": \"x86_64\"})\n    be = AutotoolsToolchain(conanfile)\n    assert be.apple_arch_flag is None\n\n\ndef test_apple_min_os_flag():\n    \"\"\"Even when no cross building it is adjusted because it could target a Mac version\"\"\"\n    conanfile = ConanFileMock()\n    conanfile.conf.define(\"tools.apple:sdk_path\", \"/path/to/sdk\")\n    conanfile.settings = MockSettings(\n        {\"build_type\": \"Debug\",\n         \"os\": \"Macos\",\n         \"os.version\": \"14\",\n         \"arch\": \"armv8\"})\n    conanfile.settings_build = MockSettings({\"os\": \"Macos\", \"arch\": \"armv8\"})\n    be = AutotoolsToolchain(conanfile)\n    expected = \"-mmacosx-version-min=14\"\n    assert be.apple_min_version_flag == expected\n    env = be.vars()\n    assert expected in env[\"CXXFLAGS\"]\n    assert expected in env[\"CFLAGS\"]\n    assert expected in env[\"LDFLAGS\"]\n\n\n@patch(\"conan.tools.gnu.autotoolstoolchain.VirtualBuildEnv\", new=MagicMock(vars={}))\ndef test_crossbuild_from_macos_to_non_apple_os():\n    \"\"\"Check we are not adding Apple-specific flags\n        when the os_build is Macos, but we are targetting\n        a non-Apple OS (e.g. Linux, Android, QNX)\"\"\"\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\"os\": \"Android\", \"arch\": \"armv8\"})\n    conanfile.settings_build = MockSettings({\"os\": \"Macos\", \"arch\": \"armv8\"})\n    be = AutotoolsToolchain(conanfile)\n    assert be.apple_min_version_flag == \"\"\n    assert be.apple_arch_flag is None\n    assert be.apple_isysroot_flag is None\n\n\n@patch(\"conan.tools.gnu.autotoolstoolchain.VirtualBuildEnv\")\ndef test_crossbuild_to_android(build_env_mock):\n    \"\"\"\n    Issue related: https://github.com/conan-io/conan/issues/17441\n    \"\"\"\n    buildvars = MagicMock()\n    # VirtualBuildEnv defines these variables\n    buildvars.vars.return_value = {\"CC\": \"my-clang\", \"CXX\": \"my-clang++\"}\n    build_env_mock.return_value = buildvars\n\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\"os\": \"Android\", \"arch\": \"armv8\"})\n    conanfile.settings_build = MockSettings({\"os\": \"Macos\", \"arch\": \"armv8\"})\n    at = AutotoolsToolchain(conanfile)\n    env_vars = at.vars()\n    assert env_vars.get(\"CC\") is None\n    assert env_vars.get(\"CXX\") is None\n    assert at._host == \"aarch64-linux-android\"\n    assert env_vars.get(\"LD\") is None\n    assert env_vars.get(\"STRIP\") is None\n\n    # Defining the ndk_path too\n    ndk_path = temp_folder()\n    ndk_bin = os.path.join(ndk_path, \"toolchains\", \"llvm\", \"prebuilt\", \"darwin-x86_64\", \"bin\")\n    save(conanfile, os.path.join(ndk_bin, \"ld\"), \"\")\n    conanfile.conf.define(\"tools.android:ndk_path\", ndk_path)\n    at = AutotoolsToolchain(conanfile)\n    env_vars = at.vars()\n    assert env_vars.get(\"CC\") is None\n    assert env_vars.get(\"CXX\") is None\n    assert at._host == \"aarch64-linux-android\"\n    assert env_vars[\"LD\"] == os.path.join(ndk_bin, \"ld\")  # exists\n    assert env_vars[\"STRIP\"] == os.path.join(ndk_bin, \"llvm-strip\")  # does not exist but appears\n\n\ndef test_apple_isysrootflag():\n    \"\"\"Even when no cross building it is adjusted because it could target a Mac version\"\"\"\n    conanfile = ConanFileMock()\n    conanfile.conf.define(\"tools.apple:sdk_path\", \"/path/to/sdk\")\n    conanfile.settings_build = MockSettings(\n        {\"build_type\": \"Debug\",\n         \"os\": \"Macos\",\n         \"arch\": \"x86_64\"})\n    conanfile.settings = MockSettings(\n        {\"build_type\": \"Debug\",\n         \"os\": \"iOS\",\n         \"os.sdk\": \"iphoneos\",\n         \"os.version\": \"14\",\n         \"arch\": \"armv8\"})\n    be = AutotoolsToolchain(conanfile)\n    expected = \"-isysroot /path/to/sdk\"\n    assert be.apple_isysroot_flag == expected\n    env = be.vars()\n    assert expected in env[\"CXXFLAGS\"]\n    assert expected in env[\"CFLAGS\"]\n    assert expected in env[\"LDFLAGS\"]\n\n    # Only set when crossbuilding\n    conanfile = ConanFileMock()\n    conanfile.conf.define(\"tools.apple:sdk_path\", \"/path/to/sdk\")\n    conanfile.settings = MockSettings(\n        {\"build_type\": \"Debug\",\n         \"os\": \"Macos\",\n         \"os.version\": \"14\",\n         \"arch\": \"armv8\"})\n    conanfile.settings_build = MockSettings(\n        {\"build_type\": \"Debug\",\n         \"os\": \"Macos\",\n         \"os.version\": \"14\",\n         \"arch\": \"armv8\"})\n    be = AutotoolsToolchain(conanfile)\n    assert be.apple_isysroot_flag is None\n\n\ndef test_sysrootflag():\n    \"\"\"Even when no cross building it is adjusted because it could target a Mac version\"\"\"\n    conanfile = ConanFileMock()\n    conanfile.conf.define(\"tools.build:sysroot\", \"/path/to/sysroot\")\n    conanfile.settings = MockSettings(\n        {\"build_type\": \"Debug\",\n         \"os\": {\"Darwin\": \"Macos\"}.get(platform.system(), platform.system()),\n         \"arch\": \"x86_64\"})\n    conanfile.settings_build = conanfile.settings\n    be = AutotoolsToolchain(conanfile)\n    expected = \"--sysroot /path/to/sysroot\"\n    assert be.sysroot_flag == expected\n    env = be.vars()\n    assert expected in env[\"CXXFLAGS\"]\n    assert expected in env[\"CFLAGS\"]\n    assert expected in env[\"LDFLAGS\"]\n\n\ndef test_sysrootflag_qnx():\n    \"\"\"Even when no cross building it is adjusted because it could target a Mac version\"\"\"\n    conanfile = ConanFileMock()\n    conanfile.conf.define(\"tools.build:sysroot\", \"/path/to/sysroot\")\n    conanfile.settings = MockSettings(\n        {\"compiler\": \"qcc\",\n         \"build_type\": \"Debug\",\n         \"os\": \"Linux\",\n         \"arch\": \"x86_64\"})\n    conanfile.settings_build = conanfile.settings\n    be = AutotoolsToolchain(conanfile)\n    expected = \"-Wc,-isysroot,/path/to/sysroot\"\n    assert be.sysroot_flag == expected\n\n\ndef test_custom_defines():\n    conanfile = ConanFileMock()\n    conanfile.conf.define(\"tools.apple:sdk_path\", \"/path/to/sdk\")\n    conanfile.settings = MockSettings(\n        {\"build_type\": \"RelWithDebInfo\",\n         \"os\": \"iOS\",\n         \"os.sdk\": \"iphoneos\",\n         \"os.version\": \"14\",\n         \"arch\": \"armv8\"})\n    conanfile.settings_build = MockSettings({\"os\": \"Macos\", \"arch\": \"armv8\"})\n    be = AutotoolsToolchain(conanfile)\n    be.extra_defines = [\"MyDefine1\", \"MyDefine2\"]\n\n    assert \"MyDefine1\" in be.defines\n    assert \"MyDefine2\" in be.defines\n    assert \"NDEBUG\" in be.defines\n\n    env = be.vars()\n    assert \"-DMyDefine1\" in env[\"CPPFLAGS\"]\n    assert \"-DMyDefine2\" in env[\"CPPFLAGS\"]\n    assert \"-DNDEBUG\" in env[\"CPPFLAGS\"]\n\n\ndef test_custom_cxxflags():\n    conanfile = ConanFileMock()\n    conanfile.conf.define(\"tools.apple:sdk_path\", \"/path/to/sdk\")\n    conanfile.settings = MockSettings(\n        {\"build_type\": \"RelWithDebInfo\",\n         \"os\": \"iOS\",\n         \"os.sdk\": \"iphoneos\",\n         \"os.version\": \"14\",\n         \"arch\": \"armv8\"})\n    conanfile.settings_build = MockSettings({\"os\": \"Macos\", \"arch\": \"armv8\"})\n    be = AutotoolsToolchain(conanfile)\n    be.extra_cxxflags = [\"MyFlag1\", \"MyFlag2\"]\n\n    assert \"MyFlag1\" in be.cxxflags\n    assert \"MyFlag2\" in be.cxxflags\n    assert \"-mios-version-min=14\" in be.cxxflags\n    assert \"MyFlag\" not in be.cflags\n    assert \"MyFlag\" not in be.ldflags\n\n    env = be.vars()\n    assert \"MyFlag1\" in env[\"CXXFLAGS\"]\n    assert \"MyFlag2\" in env[\"CXXFLAGS\"]\n    assert \"-mios-version-min=14\" in env[\"CXXFLAGS\"]\n\n    assert \"MyFlag\" not in env[\"CFLAGS\"]\n    assert \"MyFlag\" not in env[\"LDFLAGS\"]\n\n\ndef test_custom_cflags():\n    conanfile = ConanFileMock()\n    conanfile.conf.define(\"tools.apple:sdk_path\", \"/path/to/sdk\")\n    conanfile.settings = MockSettings(\n        {\"build_type\": \"RelWithDebInfo\",\n         \"os\": \"iOS\",\n         \"os.sdk\": \"iphoneos\",\n         \"os.version\": \"14\",\n         \"arch\": \"armv8\"})\n    conanfile.settings_build = MockSettings({\"os\": \"Macos\", \"arch\": \"armv8\"})\n    be = AutotoolsToolchain(conanfile)\n    be.extra_cflags = [\"MyFlag1\", \"MyFlag2\"]\n\n    assert \"MyFlag1\" in be.cflags\n    assert \"MyFlag2\" in be.cflags\n    assert \"-mios-version-min=14\" in be.cflags\n    assert \"MyFlag\" not in be.cxxflags\n    assert \"MyFlag\" not in be.ldflags\n\n    env = be.vars()\n    assert \"MyFlag1\" in env[\"CFLAGS\"]\n    assert \"MyFlag2\" in env[\"CFLAGS\"]\n    assert \"-mios-version-min=14\" in env[\"CFLAGS\"]\n\n    assert \"MyFlag\" not in env[\"CXXFLAGS\"]\n    assert \"MyFlag\" not in env[\"LDFLAGS\"]\n\n\ndef test_custom_ldflags():\n    conanfile = ConanFileMock()\n    conanfile.conf.define(\"tools.apple:sdk_path\", \"/path/to/sdk\")\n    conanfile.settings = MockSettings(\n        {\"build_type\": \"RelWithDebInfo\",\n         \"os\": \"iOS\",\n         \"os.sdk\": \"iphoneos\",\n         \"os.version\": \"14\",\n         \"arch\": \"armv8\"})\n    conanfile.settings_build = MockSettings({\"os\": \"Macos\", \"arch\": \"armv8\"})\n    be = AutotoolsToolchain(conanfile)\n    be.extra_ldflags = [\"MyFlag1\", \"MyFlag2\"]\n\n    assert \"MyFlag1\" in be.ldflags\n    assert \"MyFlag2\" in be.ldflags\n    assert \"-mios-version-min=14\" in be.ldflags\n    assert \"MyFlag\" not in be.cxxflags\n    assert \"MyFlag\" not in be.cflags\n\n    env = be.vars()\n    assert \"MyFlag1\" in env[\"LDFLAGS\"]\n    assert \"MyFlag2\" in env[\"LDFLAGS\"]\n    assert \"-mios-version-min=14\" in env[\"LDFLAGS\"]\n\n    assert \"MyFlag\" not in env[\"CXXFLAGS\"]\n    assert \"MyFlag\" not in env[\"CFLAGS\"]\n\n\ndef test_extra_flags_via_conf():\n    conanfile = ConanFileMock()\n    conanfile.conf.define(\"tools.build:cxxflags\", [\"--flag1\", \"--flag2\"])\n    conanfile.conf.define(\"tools.build:cflags\", [\"--flag3\", \"--flag4\"])\n    conanfile.conf.define(\"tools.build:sharedlinkflags\", [\"--flag5\"])\n    conanfile.conf.define(\"tools.build:exelinkflags\", [\"--flag6\"])\n    conanfile.conf.define(\"tools.build:defines\", [\"DEF1\", \"DEF2\"])\n    conanfile.settings = MockSettings(\n        {\"build_type\": \"RelWithDebInfo\",\n         \"os\": \"iOS\",\n         \"os.sdk\": \"iphoneos\",\n         \"os.version\": \"14\",\n         \"arch\": \"armv8\"})\n    conanfile.settings_build = MockSettings({\"os\": \"iOS\", \"arch\": \"armv8\"})\n    be = AutotoolsToolchain(conanfile)\n    env = be.vars()\n    assert '-DNDEBUG -DDEF1 -DDEF2' in env[\"CPPFLAGS\"]\n    assert '-mios-version-min=14 --flag1 --flag2' in env[\"CXXFLAGS\"]\n    assert '-mios-version-min=14 --flag3 --flag4' in env[\"CFLAGS\"]\n    assert '-mios-version-min=14 --flag5 --flag6' in env[\"LDFLAGS\"]\n\n\ndef test_conf_compiler_executable():\n    conanfile = ConanFileMock()\n    conanfile.conf.define(\"tools.build:compiler_executables\", {\"cpp\": \"C:/my/path/myg++\"})\n    conanfile.conf.define(\"tools.microsoft.bash:subsystem\", \"msys2\")\n    conanfile.win_bash = True\n    conanfile.settings = MockSettings(\n        {\"build_type\": \"Release\",\n         \"os\": \"Windows\"})\n    conanfile.settings_build = conanfile.settings\n    be = AutotoolsToolchain(conanfile)\n    env = be.vars()\n    assert \"/c/my/path/myg++\" == env[\"CXX\"]\n\n\ndef test_autotools_toolchain_conf_extra_configure_args():\n    \"\"\"Validate that tools.gnu:extra_configure_args are passed to configure command only.\n\n       The configure args should be passed as list only.\n    \"\"\"\n    f = temp_folder()\n    os.chdir(f)\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\"os\": \"Linux\", \"arch\": \"x86_64\"})\n    conanfile.conf = Conf()\n    conanfile.conf.define(\"tools.gnu:extra_configure_args\", [\"--foo\", \"--bar\"])\n\n    be = AutotoolsToolchain(conanfile)\n    be.generate_args()\n    obj = load_toolchain_args()\n    assert \"--foo --bar\" in obj[\"configure_args\"]\n    # make sure it does not forward to make\n    assert \"--foo\" not in obj[\"make_args\"]\n"
  },
  {
    "path": "test/unittests/tools/gnu/autotoolschain_test.py",
    "content": "from unittest.mock import patch\n\nimport pytest\n\nfrom conan.tools.build import cmd_args_to_string\nfrom conan.tools.gnu import AutotoolsToolchain\nfrom conan.errors import ConanException\nfrom conan.internal.model.conf import Conf\nfrom conan.test.utils.mocks import ConanFileMock, MockSettings\n\n\n@pytest.fixture()\ndef cross_building_conanfile():\n    settings_build = MockSettings({\"os\": \"Linux\",\n                                   \"arch\": \"x86_64\",\n                                   \"compiler\": \"gcc\",\n                                   \"compiler.version\": \"11\",\n                                   \"compiler.libcxx\": \"libstdc++\",\n                                   \"build_type\": \"Release\"})\n    settings_target = MockSettings({\"os\": \"Android\", \"arch\": \"armv8\"})\n    settings = MockSettings({\"os\": \"Emscripten\", \"arch\": \"wasm\"})\n    conanfile = ConanFileMock()\n    conanfile.settings = settings\n    conanfile.settings_build = settings_build\n    conanfile.settings_target = settings_target\n    return conanfile\n\n\ndef test_get_gnu_triplet_for_cross_building():\n    \"\"\"\n    Testing AutotoolsToolchain and _get_gnu_triplet() function in case of\n    having os=Windows and cross compiling\n    \"\"\"\n    # Issue: https://github.com/conan-io/conan/issues/10139\n    settings = MockSettings({\"build_type\": \"Release\",\n                             \"compiler\": \"gcc\",\n                             \"compiler.version\": \"10.2\",\n                             \"os\": \"Windows\",\n                             \"arch\": \"x86_64\"})\n    conanfile = ConanFileMock()\n    conanfile.settings = settings\n    conanfile.settings_build = MockSettings({\"os\": \"Solaris\", \"arch\": \"x86\"})\n    autotoolschain = AutotoolsToolchain(conanfile)\n    assert autotoolschain._host == \"x86_64-w64-mingw32\"\n    assert autotoolschain._build == \"i686-solaris\"\n\n\ndef test_get_toolchain_cppstd():\n    settings = MockSettings({\"build_type\": \"Release\",\n                             \"compiler\": \"gcc\",\n                             \"compiler.version\": \"9\",\n                             \"compiler.cppstd\": \"20\",\n                             \"os\": \"Linux\",\n                             \"arch\": \"x86_64\"})\n    conanfile = ConanFileMock()\n    conanfile.settings = settings\n    conanfile.settings_build = settings\n    autotoolschain = AutotoolsToolchain(conanfile)\n    assert autotoolschain.cppstd == \"-std=c++2a\"\n    settings.values[\"compiler.version\"] = \"10\"\n    autotoolschain = AutotoolsToolchain(conanfile)\n    assert autotoolschain.cppstd == \"-std=c++20\"\n\n\n@pytest.mark.parametrize(\"runtime, runtime_type, expected\",\n                         [(\"static\", \"Debug\", \"MTd\"),\n                          (\"static\", \"Release\", \"MT\"),\n                          (\"dynamic\", \"Debug\", \"MDd\"),\n                          (\"dynamic\", \"Release\", \"MD\")])\ndef test_msvc_runtime(runtime, runtime_type, expected):\n    \"\"\"\n    Testing AutotoolsToolchain with the msvc compiler adjust the runtime\n    \"\"\"\n    # Issue: https://github.com/conan-io/conan/issues/10139\n    settings = MockSettings({\"build_type\": \"Release\",\n                             \"compiler\": \"msvc\",\n                             \"compiler.runtime\": runtime,\n                             \"compiler.runtime_type\": runtime_type,\n                             \"os\": \"Windows\",\n                             \"arch\": \"x86_64\"})\n    conanfile = ConanFileMock()\n    conanfile.settings = settings\n    conanfile.settings_build = settings\n    autotoolschain = AutotoolsToolchain(conanfile)\n    expected_flag = \"-{}\".format(expected)\n    assert autotoolschain.msvc_runtime_flag == expected_flag\n    env = autotoolschain.environment().vars(conanfile)\n    assert expected_flag in env[\"CFLAGS\"]\n    assert expected_flag in env[\"CXXFLAGS\"]\n\n\n@pytest.mark.parametrize(\"runtime\", [\"MTd\", \"MT\", \"MDd\", \"MD\"])\ndef test_visual_runtime(runtime):\n    \"\"\"\n    Testing AutotoolsToolchain with the msvc compiler adjust the runtime\n    \"\"\"\n    # Issue: https://github.com/conan-io/conan/issues/10139\n    settings = MockSettings({\"build_type\": \"Release\" if \"d\" not in runtime else \"Debug\",\n                             \"compiler\": \"msvc\",\n                             \"compiler.runtime\": \"static\" if \"MT\" in runtime else \"dynamic\",\n                             \"compiler.runtime_type\": \"Release\" if \"d\" not in runtime else \"Debug\",\n                             \"os\": \"Windows\",\n                             \"arch\": \"x86_64\"})\n    conanfile = ConanFileMock()\n    conanfile.settings = settings\n    conanfile.settings_build = settings\n    autotoolschain = AutotoolsToolchain(conanfile)\n    expected_flag = \"-{}\".format(runtime)\n    assert autotoolschain.msvc_runtime_flag == expected_flag\n    env = autotoolschain.environment().vars(conanfile)\n    assert expected_flag in env[\"CFLAGS\"]\n    assert expected_flag in env[\"CXXFLAGS\"]\n\n\ndef test_get_gnu_triplet_for_cross_building_raise_error():\n    \"\"\"\n    Testing AutotoolsToolchain and _get_gnu_triplet() function raises an error in case of\n    having os=Windows, cross compiling and not defined any compiler\n    \"\"\"\n    # Issue: https://github.com/conan-io/conan/issues/10139\n    settings = MockSettings({\"build_type\": \"Release\",\n                             \"os\": \"Windows\",\n                             \"arch\": \"x86_64\"})\n    conanfile = ConanFileMock()\n    conanfile.settings = settings\n    conanfile.settings_build = MockSettings({\"os\": \"Solaris\", \"arch\": \"x86\"})\n    with pytest.raises(ConanException) as conan_error:\n        AutotoolsToolchain(conanfile)\n    msg = \"'compiler' parameter for 'get_gnu_triplet()' is not specified and needed for os=Windows\"\n    assert msg == str(conan_error.value)\n\n\ndef test_compilers_mapping():\n    autotools_mapping = {\"c\": \"CC\", \"cpp\": \"CXX\", \"cuda\": \"NVCC\", \"fortran\": \"FC\"}\n    compilers = {\"c\": \"path_to_c\", \"cpp\": \"path_to_cpp\", \"cuda\": \"path_to_cuda\",\n                 \"fortran\": \"path_to_fortran\"}\n    settings = MockSettings({\"build_type\": \"Release\",\n                             \"os\": \"Windows\",\n                             \"arch\": \"x86_64\",\n                             \"compiler\": \"gcc\"})\n    conanfile = ConanFileMock()\n    conanfile.conf = Conf()\n    conanfile.conf.define(\"tools.build:compiler_executables\", compilers)\n    conanfile.settings = settings\n    autotoolschain = AutotoolsToolchain(conanfile)\n    env = autotoolschain.environment().vars(conanfile)\n    for compiler, env_var in autotools_mapping.items():\n        assert env[env_var] == f\"path_to_{compiler}\"\n\n\ndef test_linker_scripts():\n    conanfile = ConanFileMock()\n    conanfile.conf = Conf()\n    conanfile.conf.define(\"tools.build:linker_scripts\", [\"path_to_first_linker_script\", \"path_to_second_linker_script\"])\n    settings = MockSettings({\"build_type\": \"Release\",\n                             \"os\": \"Windows\",\n                             \"compiler\": \"gcc\",\n                             \"arch\": \"x86_64\"})\n    conanfile.settings = settings\n    autotoolschain = AutotoolsToolchain(conanfile)\n    env = autotoolschain.environment().vars(conanfile)\n    assert \"-T'path_to_first_linker_script'\" in env[\"LDFLAGS\"]\n    assert \"-T'path_to_second_linker_script'\" in env[\"LDFLAGS\"]\n\n\n@patch(\"conan.tools.gnu.autotoolstoolchain.save_toolchain_args\")\ndef test_check_configure_args_overwriting_and_deletion(save_args, cross_building_conanfile):\n    # Issue: https://github.com/conan-io/conan/issues/12642\n    at = AutotoolsToolchain(cross_building_conanfile)\n    at.configure_args.extend([\n        \"--with-cross-build=my_path\",\n        \"--something-host=my_host\"\n    ])\n    at.generate_args()\n    configure_args = save_args.call_args[0][0]['configure_args']\n    assert \"--build=x86_64-linux-gnu\" in configure_args\n    assert \"--host=wasm32-local-emscripten\" in configure_args\n    assert \"--with-cross-build=my_path\" in configure_args\n    assert \"--something-host=my_host\" in configure_args\n    # https://github.com/conan-io/conan/issues/12431\n    at.configure_args.remove(\"--build=x86_64-linux-gnu\")\n    at.configure_args.remove(\"--host=wasm32-local-emscripten\")\n    at.generate_args()\n    configure_args = save_args.call_args[0][0]['configure_args']\n    assert \"--build=x86_64-linux-gnu\" not in configure_args  # removed\n    assert \"--host=wasm32-local-emscripten\" not in configure_args  # removed\n    assert \"--with-cross-build=my_path\" in configure_args\n    assert \"--something-host=my_host\" in configure_args\n\n\ndef test_update_or_prune_any_args(cross_building_conanfile):\n    at = AutotoolsToolchain(cross_building_conanfile)\n    at.configure_args.append(\"--enable-flag1=false\")\n    # Update configure_args\n    at.update_configure_args({\"--prefix\": \"/my/other/prefix\",\n                              \"--build\": None,  # prune value\n                              \"--enable-flag1\": \"\",  # without value\n                              \"-NEW-FLAG\": \"no\"  # new flag\n                              })\n    new_configure_args = cmd_args_to_string(at.configure_args)\n    assert \"--prefix=/my/other/prefix\" in new_configure_args\n    assert \"--build=\" not in new_configure_args  # pruned\n    assert \"--enable-flag1\" in new_configure_args  # flag without value\n    assert \"-NEW-FLAG=no\" in new_configure_args  # new flag\n    # Update autoreconf_args\n    at.update_autoreconf_args({\"--force\": None})\n    new_autoreconf_args = cmd_args_to_string(at.autoreconf_args)\n    assert \"'--force\" not in new_autoreconf_args\n    # Add new value to make_args\n    at.update_make_args({\"--new-complex-flag\": \"new-value\"})\n    new_make_args = cmd_args_to_string(at.make_args)\n    assert \"--new-complex-flag=new-value\" in new_make_args\n\n\ndef test_tricore():\n    settings = MockSettings({\"build_type\": \"Release\",\n                             \"compiler\": \"gcc\",\n                             \"os\": \"baremetal\",\n                             \"arch\": \"tc131\"})\n    conanfile = ConanFileMock()\n    conanfile.settings = settings\n    conanfile.settings_build = settings\n    autotoolschain = AutotoolsToolchain(conanfile)\n    env = autotoolschain.environment().vars(conanfile)\n    assert '-mtc131' in env[\"CFLAGS\"]\n    assert '-mtc131' in env[\"CXXFLAGS\"]\n    assert '-mtc131' in env[\"LDFLAGS\"]\n"
  },
  {
    "path": "test/unittests/tools/gnu/gnudepsflags_test.py",
    "content": "import pytest\nfrom unittest.mock import MagicMock\n\nfrom conan.tools.apple.apple import is_apple_os\nfrom conan.tools.gnu.gnudeps_flags import GnuDepsFlags\nfrom conan.test.utils.mocks import ConanFileMock, MockSettings\n\n\n@pytest.mark.parametrize(\"os_\", [\"Macos\", \"Windows\", \"Linux\"])\ndef test_framework_flags_only_for_apple_os(os_):\n    \"\"\"\n    Testing GnuDepsFlags attributes exclusively for Apple OS, frameworks and framework_paths\n    \"\"\"\n    # Issue: https://github.com/conan-io/conan/issues/10651\n    # Issue: https://github.com/conan-io/conan/issues/10640\n    settings = MockSettings({\"build_type\": \"Release\",\n                             \"compiler\": \"gcc\",\n                             \"compiler.version\": \"10.2\",\n                             \"os\": os_,\n                             \"arch\": \"x86_64\"})\n    conanfile = ConanFileMock()\n    conanfile.settings = settings\n    cpp_info = MagicMock()\n    cpp_info.frameworks = [\"Foundation\"]\n    cpp_info.frameworkdirs = [\"Framework\"]\n    gnudepsflags = GnuDepsFlags(conanfile, cpp_info)\n    expected_framework = []\n    expected_framework_path = []\n    if is_apple_os(conanfile):\n        expected_framework = [\"-framework Foundation\"]\n        expected_framework_path = [\"-F\\\"Framework\\\"\"]\n    assert gnudepsflags.frameworks == expected_framework\n    assert gnudepsflags.framework_paths == expected_framework_path\n"
  },
  {
    "path": "test/unittests/tools/gnu/test_gnutoolchain.py",
    "content": "import os\nfrom unittest.mock import patch, MagicMock\n\nimport pytest\n\nfrom conan.errors import ConanException\nfrom conan.internal.model.conf import Conf\nfrom conan.test.utils.mocks import ConanFileMock, MockSettings\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.tools.build import cmd_args_to_string\nfrom conan.tools.files import save\nfrom conan.tools.gnu import GnuToolchain\n\n\n@pytest.fixture()\ndef cross_building_conanfile():\n    settings_build = MockSettings({\"os\": \"Linux\",\n                                   \"arch\": \"x86_64\",\n                                   \"compiler\": \"gcc\",\n                                   \"compiler.version\": \"11\",\n                                   \"compiler.libcxx\": \"libstdc++\",\n                                   \"build_type\": \"Release\"})\n    settings_target = MockSettings({\"os\": \"Android\", \"arch\": \"armv8\"})\n    settings = MockSettings({\"os\": \"Emscripten\", \"arch\": \"wasm\"})\n    conanfile = ConanFileMock()\n    conanfile.settings = settings\n    conanfile.settings_build = settings_build\n    conanfile.settings_target = settings_target\n    return conanfile\n\n\ndef test_get_gnu_triplet_for_cross_building():\n    \"\"\"\n    Testing AutotoolsToolchainX and _get_gnu_triplet() function in case of\n    having os=Windows and cross compiling\n    \"\"\"\n    # Issue: https://github.com/conan-io/conan/issues/10139\n    settings = MockSettings({\"build_type\": \"Release\",\n                             \"compiler\": \"gcc\",\n                             \"compiler.version\": \"10.2\",\n                             \"os\": \"Windows\",\n                             \"arch\": \"x86_64\"})\n    conanfile = ConanFileMock()\n    conanfile.settings = settings\n    conanfile.settings_build = MockSettings({\"os\": \"Solaris\", \"arch\": \"x86\"})\n    at = GnuToolchain(conanfile)\n    assert at.configure_args[\"--host\"] == \"x86_64-w64-mingw32\"\n    assert at.configure_args[\"--build\"] == \"i686-solaris\"\n\n\ndef test_get_toolchain_cppstd():\n    settings = MockSettings({\"build_type\": \"Release\",\n                             \"compiler\": \"gcc\",\n                             \"compiler.version\": \"9\",\n                             \"compiler.cppstd\": \"20\",\n                             \"os\": \"Linux\",\n                             \"arch\": \"x86_64\"})\n    conanfile = ConanFileMock()\n    conanfile.settings = settings\n    conanfile.settings_build = settings\n    at = GnuToolchain(conanfile)\n    assert at.cppstd == \"-std=c++2a\"\n    settings.values[\"compiler.version\"] = \"10\"\n    at = GnuToolchain(conanfile)\n    assert at.cppstd == \"-std=c++20\"\n\n\n@pytest.mark.parametrize(\"runtime, runtime_type, expected\",\n                         [(\"static\", \"Debug\", \"MTd\"),\n                          (\"static\", \"Release\", \"MT\"),\n                          (\"dynamic\", \"Debug\", \"MDd\"),\n                          (\"dynamic\", \"Release\", \"MD\")])\ndef test_msvc_runtime(runtime, runtime_type, expected):\n    \"\"\"\n    Testing AutotoolsToolchainX with the msvc compiler adjust the runtime\n    \"\"\"\n    # Issue: https://github.com/conan-io/conan/issues/10139\n    settings = MockSettings({\"build_type\": \"Release\",\n                             \"compiler\": \"msvc\",\n                             \"compiler.runtime\": runtime,\n                             \"compiler.runtime_type\": runtime_type,\n                             \"os\": \"Windows\",\n                             \"arch\": \"x86_64\"})\n    conanfile = ConanFileMock()\n    conanfile.settings = settings\n    conanfile.settings_build = settings\n    at = GnuToolchain(conanfile)\n    expected_flag = \"-{}\".format(expected)\n    assert at.msvc_runtime_flag == expected_flag\n    env = at._environment.vars(conanfile)\n    assert expected_flag in env[\"CFLAGS\"]\n    assert expected_flag in env[\"CXXFLAGS\"]\n\n\n@pytest.mark.parametrize(\"runtime\", [\"MTd\", \"MT\", \"MDd\", \"MD\"])\ndef test_visual_runtime(runtime):\n    \"\"\"\n    Testing AutotoolsToolchainX with the msvc compiler adjust the runtime\n    \"\"\"\n    # Issue: https://github.com/conan-io/conan/issues/10139\n    settings = MockSettings({\"build_type\": \"Release\" if \"d\" not in runtime else \"Debug\",\n                             \"compiler\": \"msvc\",\n                             \"compiler.runtime\": \"static\" if \"MT\" in runtime else \"dynamic\",\n                             \"compiler.runtime_type\": \"Release\" if \"d\" not in runtime else \"Debug\",\n                             \"os\": \"Windows\",\n                             \"arch\": \"x86_64\"})\n    conanfile = ConanFileMock()\n    conanfile.settings = settings\n    conanfile.settings_build = settings\n    at = GnuToolchain(conanfile)\n    expected_flag = \"-{}\".format(runtime)\n    assert at.msvc_runtime_flag == expected_flag\n    env = at._environment.vars(conanfile)\n    assert expected_flag in env[\"CFLAGS\"]\n    assert expected_flag in env[\"CXXFLAGS\"]\n\n\ndef test_get_gnu_triplet_for_cross_building_raise_error():\n    \"\"\"\n    Testing AutotoolsToolchainX and _get_gnu_triplet() function raises an error in case of\n    having os=Windows, cross compiling and not defined any compiler\n    \"\"\"\n    # Issue: https://github.com/conan-io/conan/issues/10139\n    settings = MockSettings({\"build_type\": \"Release\",\n                             \"os\": \"Windows\",\n                             \"arch\": \"x86_64\"})\n    conanfile = ConanFileMock()\n    conanfile.settings = settings\n    conanfile.settings_build = MockSettings({\"os\": \"Solaris\", \"arch\": \"x86\"})\n    with pytest.raises(ConanException) as conan_error:\n        GnuToolchain(conanfile)\n    msg = \"'compiler' parameter for 'get_gnu_triplet()' is not specified and needed for os=Windows\"\n    assert msg == str(conan_error.value)\n\n\ndef test_compilers_mapping():\n    autotools_mapping = {\"c\": \"CC\", \"cpp\": \"CXX\", \"cuda\": \"NVCC\", \"fortran\": \"FC\"}\n    compilers = {\"c\": \"path_to_c\", \"cpp\": \"path_to_cpp\", \"cuda\": \"path_to_cuda\",\n                 \"fortran\": \"path_to_fortran\"}\n    settings = MockSettings({\"build_type\": \"Release\",\n                             \"os\": \"Windows\",\n                             \"arch\": \"x86_64\",\n                             \"compiler\": \"gcc\"})\n    conanfile = ConanFileMock()\n    conanfile.conf = Conf()\n    conanfile.conf.define(\"tools.build:compiler_executables\", compilers)\n    conanfile.settings = settings\n    at = GnuToolchain(conanfile)\n    env = at._environment.vars(conanfile)\n    for compiler, env_var in autotools_mapping.items():\n        assert env[env_var] == f\"path_to_{compiler}\"\n\n\ndef test_linker_scripts():\n    conanfile = ConanFileMock()\n    conanfile.conf = Conf()\n    conanfile.conf.define(\"tools.build:linker_scripts\", [\"path_to_first_linker_script\", \"path_to_second_linker_script\"])\n    settings = MockSettings({\"build_type\": \"Release\",\n                             \"os\": \"Windows\",\n                             \"compiler\": \"gcc\",\n                             \"arch\": \"x86_64\"})\n    conanfile.settings = settings\n    at = GnuToolchain(conanfile)\n    env = at._environment.vars(conanfile)\n    assert \"-T'path_to_first_linker_script'\" in env[\"LDFLAGS\"]\n    assert \"-T'path_to_second_linker_script'\" in env[\"LDFLAGS\"]\n\n\ndef test_sysrootflag_qnx():\n    \"\"\"Even when no cross building it is adjusted because it could target a Mac version\"\"\"\n    conanfile = ConanFileMock()\n    conanfile.conf.define(\"tools.build:sysroot\", \"/path/to/sysroot\")\n    conanfile.settings = MockSettings(\n        {\"compiler\": \"qcc\",\n         \"build_type\": \"Debug\",\n         \"os\": \"Linux\",\n         \"arch\": \"x86_64\"})\n    conanfile.settings_build = conanfile.settings\n    be = GnuToolchain(conanfile)\n    expected = \"-Wc,-isysroot,/path/to/sysroot\"\n    assert be.sysroot_flag == expected\n\n\ndef test_update_or_prune_any_args(cross_building_conanfile):\n    # Issue: https://github.com/conan-io/conan/issues/12642\n    at = GnuToolchain(cross_building_conanfile)\n    at.configure_args.update({\n        \"--with-cross-build\": \"my_path\",\n        \"--something-host\": \"my_host\",\n        \"--prefix\": \"/my/other/prefix\"\n    })\n    new_configure_args = cmd_args_to_string(GnuToolchain._dict_to_list(at.configure_args))\n    assert \"--build=x86_64-linux-gnu\" in new_configure_args\n    assert \"--host=wasm32-local-emscripten\" in new_configure_args\n    assert \"--with-cross-build=my_path\" in new_configure_args\n    assert \"--something-host=my_host\" in new_configure_args\n    assert \"--prefix=/my/other/prefix\" in new_configure_args\n    # https://github.com/conan-io/conan/issues/12431\n    at.configure_args.pop(\"--build\")\n    at.configure_args.pop(\"--host\")\n    new_configure_args = cmd_args_to_string(GnuToolchain._dict_to_list(at.configure_args))\n    assert \"--build=x86_64-linux-gnu\" not in new_configure_args  # removed\n    assert \"--host=wasm32-local-emscripten\" not in new_configure_args  # removed\n    assert \"--with-cross-build=my_path\" in new_configure_args\n    assert \"--something-host=my_host\" in new_configure_args\n    # Update autoreconf_args\n    at.autoreconf_args.pop(\"--force\")\n    new_autoreconf_args = cmd_args_to_string(GnuToolchain._dict_to_list(at.autoreconf_args))\n    assert \"'--force\" not in new_autoreconf_args\n    # Add new value to make_args\n    at.make_args.update({\"--new-complex-flag\": \"new-value\"})\n    at.make_args.update({\"--new-empty-flag\": \"\"})\n    at.make_args.update({\"--new-no-value-flag\": None})\n    new_make_args = cmd_args_to_string(GnuToolchain._dict_to_list(at.make_args))\n    assert \"--new-complex-flag=new-value\" in new_make_args\n    assert \"--new-empty-flag=\" in new_make_args\n    assert \"--new-no-value-flag\" in new_make_args and \"--new-no-value-flag=\" not in new_make_args\n\n\n@patch(\"conan.tools.gnu.gnutoolchain.VirtualBuildEnv\")\ndef test_crossbuild_to_android(build_env_mock):\n    \"\"\"\n    Issue related: https://github.com/conan-io/conan/issues/17441\n    \"\"\"\n    buildvars = MagicMock()\n    # VirtualBuildEnv defines these variables\n    buildvars.vars.return_value = {\"CC\": \"my-clang\", \"CXX\": \"my-clang++\"}\n    build_env_mock.return_value = buildvars\n\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\"os\": \"Android\", \"arch\": \"armv8\", \"os.api_level\": \"26r\"})\n    conanfile.settings_build = MockSettings({\"os\": \"Macos\", \"arch\": \"armv8\"})\n    gnutc = GnuToolchain(conanfile)\n    env_vars = gnutc.extra_env.vars(conanfile)\n    assert env_vars.get(\"CC\") is None\n    assert env_vars.get(\"CXX\") is None\n    assert gnutc.triplets_info[\"host\"][\"triplet\"] == \"aarch64-linux-android\"\n    assert env_vars.get(\"LD\") is None\n    assert env_vars.get(\"STRIP\") is None\n\n    # Defining the ndk_path too\n    ndk_path = temp_folder()\n    ndk_bin = os.path.join(ndk_path, \"toolchains\", \"llvm\", \"prebuilt\", \"darwin-x86_64\", \"bin\")\n    save(conanfile, os.path.join(ndk_bin, \"ld\"), \"\")\n    conanfile.conf.define(\"tools.android:ndk_path\", ndk_path)\n    gnutc = GnuToolchain(conanfile)\n    env_vars = gnutc.extra_env.vars(conanfile)\n    assert env_vars.get(\"CC\") is None\n    assert env_vars.get(\"CXX\") is None\n    assert gnutc.triplets_info[\"host\"][\"triplet\"] == \"aarch64-linux-android\"\n    assert env_vars[\"LD\"] == os.path.join(ndk_bin, \"ld\")  # exists\n    assert env_vars[\"STRIP\"] == os.path.join(ndk_bin, \"llvm-strip\")  # does not exist but appears\n\n\ndef test_gnu_toolchain_conf_extra_configure_args():\n    \"\"\" Validate that tools.gnu:extra_configure_args are passed to the configure_args when\n        building with GnuToolchain.\n        The configure args should be passed as a list-like object.\n    \"\"\"\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\"os\": \"Linux\", \"arch\": \"x86_64\"})\n    conanfile.conf = Conf()\n    conanfile.conf.define(\"tools.gnu:extra_configure_args\", [\"--foo\", \"--bar\"])\n\n    tc = GnuToolchain(conanfile)\n    assert tc.configure_args[\"--foo\"] is None\n    assert tc.configure_args[\"--bar\"] is None\n"
  },
  {
    "path": "test/unittests/tools/gnu/test_triplets.py",
    "content": "import pytest\n\nfrom conan.tools.gnu.get_gnu_triplet import _get_gnu_triplet, _get_gnu_os, _get_gnu_arch\nfrom conan.errors import ConanException\n\n\n@pytest.mark.parametrize(\"os_, arch, compiler, expected\", [\n    [\"Linux\", \"x86\", None, \"i686-linux-gnu\"],\n    [\"Linux\", \"x86_64\", None, \"x86_64-linux-gnu\"],\n    [\"Linux\", \"armv6\", None, \"arm-linux-gnueabi\"],\n    [\"Linux\", \"sparc\", None, \"sparc-linux-gnu\"],\n    [\"Linux\", \"sparcv9\", None, \"sparc64-linux-gnu\"],\n    [\"Linux\", \"mips\", None, \"mips-linux-gnu\"],\n    [\"Linux\", \"mips64\", None, \"mips64-linux-gnu\"],\n    [\"Linux\", \"ppc32\", None, \"powerpc-linux-gnu\"],\n    [\"Linux\", \"ppc64\", None, \"powerpc64-linux-gnu\"],\n    [\"Linux\", \"ppc64le\", None, \"powerpc64le-linux-gnu\"],\n    [\"Linux\", \"armv5te\", None, \"arm-linux-gnueabi\"],\n    [\"Linux\", \"arm_whatever\", None, \"arm-linux-gnueabi\"],\n    [\"Linux\", \"armv7hf\", None, \"arm-linux-gnueabihf\"],\n    [\"Linux\", \"armv6\", None, \"arm-linux-gnueabi\"],\n    [\"Linux\", \"armv7\", None, \"arm-linux-gnueabi\"],\n    [\"Linux\", \"armv8_32\", None, \"aarch64-linux-gnu_ilp32\"],\n    [\"Linux\", \"armv5el\", None, \"arm-linux-gnueabi\"],\n    [\"Linux\", \"armv5hf\", None, \"arm-linux-gnueabihf\"],\n    [\"Linux\", \"s390\", None, \"s390-ibm-linux-gnu\"],\n    [\"Linux\", \"s390x\", None, \"s390x-ibm-linux-gnu\"],\n    [\"Android\", \"x86\", None, \"i686-linux-android\"],\n    [\"Android\", \"x86_64\", None, \"x86_64-linux-android\"],\n    [\"Android\", \"armv6\", None, \"arm-linux-androideabi\"],\n    [\"Android\", \"armv7\", None, \"arm-linux-androideabi\"],\n    [\"Android\", \"armv7hf\", None, \"arm-linux-androideabi\"],\n    [\"Android\", \"armv8\", None, \"aarch64-linux-android\"],\n    [\"Windows\", \"x86\", \"msvc\", \"i686-unknown-windows\"],\n    [\"Windows\", \"x86_64\", \"msvc\", \"x86_64-unknown-windows\"],\n    [\"Windows\", \"armv8\", \"msvc\", \"aarch64-unknown-windows\"],\n    [\"Windows\", \"x86\", \"gcc\", \"i686-w64-mingw32\"],\n    [\"Windows\", \"x86_64\", \"gcc\", \"x86_64-w64-mingw32\"],\n    [\"Darwin\", \"x86_64\", None, \"x86_64-apple-darwin\"],\n    [\"Macos\", \"x86\", None, \"i686-apple-darwin\"],\n    [\"iOS\", \"armv7\", None, \"arm-apple-ios\"],\n    [\"iOS\", \"x86\", None, \"i686-apple-ios\"],\n    [\"iOS\", \"x86_64\", None, \"x86_64-apple-ios\"],\n    [\"watchOS\", \"armv7k\", None, \"arm-apple-watchos\"],\n    [\"watchOS\", \"armv8_32\", None, \"aarch64-apple-watchos\"],\n    [\"watchOS\", \"x86\", None, \"i686-apple-watchos\"],\n    [\"watchOS\", \"x86_64\", None, \"x86_64-apple-watchos\"],\n    [\"tvOS\", \"armv8\", None, \"aarch64-apple-tvos\"],\n    [\"tvOS\", \"armv8.3\", None, \"aarch64-apple-tvos\"],\n    [\"tvOS\", \"x86\", None, \"i686-apple-tvos\"],\n    [\"tvOS\", \"x86_64\", None, \"x86_64-apple-tvos\"],\n    [\"Emscripten\", \"asm.js\", None, \"asmjs-local-emscripten\"],\n    [\"Emscripten\", \"wasm\", None, \"wasm32-local-emscripten\"],\n    [\"Emscripten\", \"wasm64\", None, \"wasm64-local-emscripten\"],\n    [\"AIX\", \"ppc32\", None, \"rs6000-ibm-aix\"],\n    [\"AIX\", \"ppc64\", None, \"powerpc-ibm-aix\"],\n    [\"Neutrino\", \"armv7\", None, \"arm-nto-qnx\"],\n    [\"Neutrino\", \"armv8\", None, \"aarch64-nto-qnx\"],\n    [\"Neutrino\", \"sh4le\", None, \"sh4-nto-qnx\"],\n    [\"Neutrino\", \"ppc32be\", None, \"powerpcbe-nto-qnx\"],\n    [\"Linux\", \"e2k-v2\", None, \"e2k-unknown-linux-gnu\"],\n    [\"Linux\", \"e2k-v3\", None, \"e2k-unknown-linux-gnu\"],\n    [\"Linux\", \"e2k-v4\", None, \"e2k-unknown-linux-gnu\"],\n    [\"Linux\", \"e2k-v5\", None, \"e2k-unknown-linux-gnu\"],\n    [\"Linux\", \"e2k-v6\", None, \"e2k-unknown-linux-gnu\"],\n    [\"Linux\", \"e2k-v7\", None, \"e2k-unknown-linux-gnu\"],\n    [\"Linux\", \"riscv32\", None, \"riscv32-linux-gnu\"],\n    [\"Linux\", \"riscv64\", None, \"riscv64-linux-gnu\"],\n])\ndef test_get_gnu_triplet(os_, arch, compiler, expected):\n    info = _get_gnu_triplet(os_, arch, compiler)\n    assert info[\"triplet\"] == expected\n    assert info[\"machine\"] == _get_gnu_arch(os_, arch)\n    assert info[\"system\"] == _get_gnu_os(os_, arch, compiler)\n\n\ndef test_get_gnu_triplet_on_windows_without_compiler():\n    with pytest.raises(ConanException):\n        _get_gnu_triplet(\"Windows\", \"x86\")\n"
  },
  {
    "path": "test/unittests/tools/google/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/tools/google/test_bazel.py",
    "content": "import platform\n\nimport pytest\n\nfrom conan.test.utils.mocks import ConanFileMock\nfrom conan.tools.google import Bazel\nfrom conan.tools.google.bazeldeps import _relativize_path\n\n\n@pytest.mark.skipif(platform.system() == \"Windows\", reason=\"Remove this skip for Conan 2.x\"\n                                                           \"Needs conanfile.commands\")\ndef test_bazel_command_with_empty_config():\n    conanfile = ConanFileMock()\n    bazel = Bazel(conanfile)\n    bazel.build(target='//test:label')\n    # Uncomment Conan 2.x\n    assert 'bazel build //test:label' in conanfile.commands\n\n\n@pytest.mark.skipif(platform.system() == \"Windows\", reason=\"Remove this skip for Conan 2.x.\"\n                                                           \"Needs conanfile.commands\")\ndef test_bazel_command_with_config_values():\n    conanfile = ConanFileMock()\n    conanfile.conf.define(\"tools.google.bazel:configs\", [\"config\", \"config2\"])\n    conanfile.conf.define(\"tools.google.bazel:bazelrc_path\", [\"/path/to/bazelrc\"])\n    bazel = Bazel(conanfile)\n    bazel.build(target='//test:label')\n    commands = conanfile.commands\n    assert \"bazel --bazelrc=/path/to/bazelrc build \" \\\n           \"--config=config --config=config2 //test:label\" in commands\n    assert \"bazel --bazelrc=/path/to/bazelrc clean\" in commands\n\n\n@pytest.mark.parametrize(\"path, pattern, expected\", [\n    (\"\", \"./\", \"\"),\n    (\"./\", \"\", \"./\"),\n    (\"/my/path/\", \"\", \"/my/path/\"),\n    (\"\\\\my\\\\path\\\\\", \"\", \"\\\\my\\\\path\\\\\"),\n    (\"/my/path/absolute\", \".*/path\", \"absolute\"),\n    (\"/my/path/absolute\", \"/my/path\", \"absolute\"),\n    (\"\\\\my\\\\path\\\\absolute\", \"/my/path\", \"absolute\"),\n    (\"/my/./path/absolute/\", \"/my/./path\", \"absolute\"),\n    (\"/my/./path/absolute/\", \"/my/./path/absolute/\", \"./\"),\n    (\"././my/path/absolute/././\", \"./\", \"my/path/absolute\"),\n    (\"C:\\\\my\\\\path\\\\absolute\\\\with\\\\folder\", \"C:\\\\\", \"my/path/absolute/with/folder\"),\n    (\"C:\\\\my\\\\path\\\\absolute\\\\with\\\\folder\", \".*/absolute\", \"with/folder\"),\n    (\"C:\\\\my\\\\path\\\\myabsolute\\\\with\\\\folder\", \".*/absolute\", \"C:\\\\my\\\\path\\\\myabsolute\\\\with\\\\folder\"),\n])\ndef test_bazeldeps_relativize_path(path, pattern, expected):\n    assert _relativize_path(path, pattern) == expected\n"
  },
  {
    "path": "test/unittests/tools/intel/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/tools/intel/test_intel_cc.py",
    "content": "import os\nimport textwrap\n\nimport pytest\nfrom unittest.mock import patch\n\nfrom conan.tools.build.flags import architecture_flag, cppstd_flag\nfrom conan.tools.intel import IntelCC\nfrom conan.errors import ConanException\nfrom conan.internal.model.conf import ConfDefinition\nfrom conan.test.utils.mocks import ConanFileMock, MockSettings\n\n\n@pytest.mark.parametrize(\"os_,arch,expected\", [\n    (\"Windows\", \"x86\", \"/Qm32\"),\n    (\"Windows\", \"x86_64\", \"/Qm64\"),\n    (\"Linux\", \"x86\", \"-m32\"),\n    (\"Linux\", \"x86_64\", \"-m64\")\n])\ndef test_architecture_flag_if_intel_cc(os_, arch, expected):\n    settings = MockSettings({\n        \"compiler\": \"intel-cc\",\n        \"compiler.version\": \"2021.3\",\n        \"compiler.mode\": \"classic\",\n        \"arch\": arch,\n        \"os\": os_\n    })\n    conanfile = ConanFileMock()\n    conanfile.settings = settings\n    flag = architecture_flag(conanfile)\n    assert flag == expected\n\n\n@pytest.mark.parametrize(\"cppstd,flag\", [\n    (\"98\", \"c++98\"),\n    (\"gnu98\", \"gnu++98\"),\n    (\"03\", \"c++03\"),\n    (\"gnu03\", \"gnu++03\"),\n    (\"11\", \"c++11\"),\n    (\"gnu11\", \"gnu++11\"),\n    (\"14\", \"c++14\"),\n    (\"gnu14\", \"gnu++14\"),\n    (\"17\", \"c++17\"),\n    (\"gnu17\", \"gnu++17\"),\n    (\"20\", \"c++20\"),\n    (\"gnu20\", \"gnu++20\"),\n    (\"23\", \"c++2b\"),\n    (\"gnu23\", \"gnu++2b\"),\n])\ndef test_cppstd_flag_if_intel_cc(cppstd, flag):\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\n        \"compiler\": \"intel-cc\",\n        \"compiler.version\": \"2021.3\",\n        \"compiler.mode\": \"classic\",\n        \"arch\": \"x86_64\",\n        \"os\": \"Linux\",\n        \"compiler.cppstd\": cppstd\n    })\n    assert cppstd_flag(conanfile) == \"-std=%s\" % flag\n\n\n@pytest.mark.parametrize(\"mode\", [\"icx\", \"dpcpp\"])\ndef test_macos_not_supported_for_new_compilers(mode):\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\n        \"compiler.version\": \"2021.3\",\n        \"compiler.mode\": mode,\n        \"os\": \"Darwin\"\n    })\n    with pytest.raises(ConanException) as excinfo:\n        IntelCC(conanfile)\n    assert \"macOS* is not supported for the icx/icpx or dpcpp compilers.\" in str(excinfo.value)\n\n\n@pytest.mark.parametrize(\"os_\", [\"Windows\", \"Linux\", \"Darwin\"])\ndef test_error_if_detected_intel_legacy_version(os_):\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\n        \"compiler.version\": \"19.1\",\n        \"compiler.mode\": \"classic\",\n        \"os\": os_\n    })\n    with pytest.raises(ConanException) as excinfo:\n        IntelCC(conanfile)\n    assert \"You have to use 'intel' compiler which is meant for legacy\" in str(excinfo.value)\n\n\n@pytest.mark.parametrize(\"os_\", [\"Windows\", \"Linux\", \"Darwin\"])\ndef test_classic_compiler_supports_every_os(os_):\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\n        \"compiler.version\": \"2021.3\",\n        \"compiler.mode\": \"classic\",\n        \"os\": os_,\n        \"arch\": \"x86_64\"\n    })\n    assert IntelCC(conanfile).arch == \"x86_64\"\n\n\n@pytest.mark.parametrize(\"mode,expected\", [\n    (\"icx\", \"Intel C++ Compiler 2021\"),\n    (\"dpcpp\", \"Intel(R) oneAPI DPC++ Compiler\"),\n    (\"classic\", \"Intel C++ Compiler 19.2\")\n])\ndef test_check_ms_toolsets(mode, expected):\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\n        \"compiler.version\": \"2021.3\",\n        \"compiler.mode\": mode,\n        \"os\": \"Windows\"\n    })\n    assert IntelCC(conanfile).ms_toolset == expected\n\n\ndef test_installation_path_in_conf():\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\n        \"compiler.version\": \"2021.3\",\n        \"compiler.mode\": \"classic\",\n        \"os\": \"Windows\"\n    })\n    fake_path = \"mysuper/path/to/intel/oneapi\"\n    conanfile.conf = ConfDefinition()\n    conanfile.conf.loads(textwrap.dedent(\"\"\"\\\n        tools.intel:installation_path=%s\n    \"\"\" % fake_path))\n    assert IntelCC(conanfile).installation_path == fake_path\n\n\n@pytest.mark.parametrize(\"os_,call_command,setvars_file\", [\n    (\"Windows\", \"call\", \"setvars.bat\"),\n    (\"Linux\", \".\", \"setvars.sh\")\n])\n@patch(\"conan.tools.intel.intel_cc.platform.system\")\ndef test_setvars_command_with_custom_arguments(platform_system, os_, call_command, setvars_file):\n    platform_system.return_value = os_\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\n        \"compiler.version\": \"2021.3\",\n        \"compiler.mode\": \"icx\",\n        \"os\": os_\n    })\n    fake_path = \"mysuper/path/to/intel/oneapi\"\n    args = \"arg1 arg2 --force\"\n    conanfile.conf = ConfDefinition()\n    conanfile.conf.loads(textwrap.dedent(\"\"\"\\\n        tools.intel:installation_path=%s\n        tools.intel:setvars_args=%s\n    \"\"\" % (fake_path, args)))\n    expected = '%s \"%s\" %s' % (call_command, os.path.join(fake_path, setvars_file), args)\n    assert IntelCC(conanfile).command == expected\n"
  },
  {
    "path": "test/unittests/tools/meson/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/tools/meson/test_meson.py",
    "content": "import textwrap\n\nimport pytest\n\nfrom conan.tools.meson import Meson\nfrom conan.internal.model.conf import ConfDefinition\nfrom conan.test.utils.mocks import ConanFileMock, MockSettings\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.tools.meson.helpers import get_apple_subsystem, to_cstd_flag, to_cppstd_flag\n\n\ndef test_meson_build():\n    c = ConfDefinition()\n    c.loads(textwrap.dedent(\"\"\"\\\n        tools.build:jobs=10\n    \"\"\"))\n\n    settings = MockSettings({\"build_type\": \"Release\",\n                             \"compiler\": \"gcc\",\n                             \"compiler.version\": \"7\",\n                             \"os\": \"Linux\",\n                             \"arch\": \"x86_64\"})\n    conanfile = ConanFileMock()\n    conanfile.settings = settings\n    conanfile.display_name = 'test'\n    conanfile.conf = c.get_conanfile_conf(None)\n\n    meson = Meson(conanfile)\n    meson.build()\n\n    assert '-j10' in str(conanfile.command)\n\n\n@pytest.mark.parametrize(\"apple_sdk, subsystem\", [\n    (\"iphoneos\", \"ios\"),\n    (\"iphonesimulator\", \"ios-simulator\"),\n    (\"appletvos\", \"tvos\"),\n    (\"appletvsimulator\", \"tvos-simulator\"),\n    (\"watchos\", \"watchos\"),\n    (\"watchsimulator\", \"watchos-simulator\"),\n    (None, \"macos\")\n])\ndef test_meson_subsystem_helper(apple_sdk, subsystem):\n    assert get_apple_subsystem(apple_sdk) == subsystem\n\n\n@pytest.mark.parametrize(\"cstd, expected\", [\n    (\"gnu23\", \"gnu23\"),\n    (\"23\", \"c23\"),\n    (None, None)\n])\ndef test_meson_to_cstd_flag(cstd, expected):\n    assert to_cstd_flag(ConanFileMock(), cstd) == expected\n\n\n@pytest.mark.parametrize(\"compiler, compiler_version, cppstd, expected\", [\n    (\"gcc\", \"14.0\", \"26\", \"c++26\"),\n    (\"gcc\", \"14.0\", \"gnu26\", \"gnu++26\"),\n    (\"gcc\", \"14.0\", \"gnu23\", \"gnu++23\"),\n    (\"gcc\", \"14.0\", \"23\", \"c++23\"),\n    (\"gcc\", \"15.0\", \"26\", \"c++26\"),\n    (\"msvc\", \"193\", \"23\", \"vc++latest\"),\n    (None, None, \"26\", \"c++26\"),\n    (None, None, None, None)\n])\ndef test_meson_to_cppstd_flag(compiler, compiler_version, cppstd, expected):\n    assert to_cppstd_flag(ConanFileMock(), compiler, compiler_version, cppstd) == expected\n\n\ndef test_meson_install_strip():\n    \"\"\"When the configuration `tools.build:install_strip` is set to True,\n        the Meson install command should include the `--strip` option.\n    \"\"\"\n    c = ConfDefinition()\n    c.loads(\"tools.build:install_strip=True\")\n\n    settings = MockSettings({\"build_type\": \"Release\",\n                             \"compiler\": \"gcc\",\n                             \"compiler.version\": \"7\",\n                             \"os\": \"Linux\",\n                             \"arch\": \"x86_64\"})\n    conanfile = ConanFileMock()\n    conanfile.settings = settings\n    conanfile.conf = c.get_conanfile_conf(None)\n    conanfile.folders.generators = \".\"\n    conanfile.folders.set_base_generators(temp_folder())\n    conanfile.folders.set_base_package(temp_folder())\n\n    meson = Meson(conanfile)\n    meson.install()\n\n    assert '--strip' in str(conanfile.command)\n\ndef test_meson_install_cli_args():\n    \"\"\"When the `cli_args` are provided, the Meson install command should include them.\n    \"\"\"\n    c = ConfDefinition()\n\n    settings = MockSettings({\"build_type\": \"Release\",\n                             \"compiler\": \"gcc\",\n                             \"compiler.version\": \"7\",\n                             \"os\": \"Linux\",\n                             \"arch\": \"x86_64\"})\n    conanfile = ConanFileMock()\n    conanfile.settings = settings\n    conanfile.conf = c.get_conanfile_conf(None)\n    conanfile.folders.generators = \".\"\n    conanfile.folders.set_base_generators(temp_folder())\n    conanfile.folders.set_base_package(temp_folder())\n\n    meson = Meson(conanfile)\n    meson.install(cli_args=[\"--no-rebuild\"])\n\n    assert '--no-rebuild' in str(conanfile.command)\n"
  },
  {
    "path": "test/unittests/tools/microsoft/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/tools/microsoft/conantoolchain.props",
    "content": "<?xml version=\"1.0\" ?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n\t<ImportGroup Label=\"PropertySheets\">\n\t\t<Import Condition=\"'$(Configuration)' == 'Release' And '$(Platform)' == 'x64'\" Project=\"conantoolchain_release_x64.props\"/>\n\t</ImportGroup>\n\t<PropertyGroup Label=\"ConanPackageInfo\">\n\t\t<ConanPackageName/>\n\t\t<ConanPackageVersion/>\n\t</PropertyGroup>\n</Project>"
  },
  {
    "path": "test/unittests/tools/microsoft/conantoolchain_release_x64.props",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemDefinitionGroup>\n    <ClCompile>\n      <PreprocessorDefinitions>\n         ;%(PreprocessorDefinitions)\n      </PreprocessorDefinitions>\n      <RuntimeLibrary></RuntimeLibrary>\n      <LanguageStandard>stdcpp20</LanguageStandard>\n    </ClCompile>\n  </ItemDefinitionGroup>\n  <PropertyGroup Label=\"Configuration\">\n    <PlatformToolset>v143</PlatformToolset>\n  </PropertyGroup>\n</Project>\n"
  },
  {
    "path": "test/unittests/tools/microsoft/test_check_min_vs.py",
    "content": "import pytest\n\nfrom conan.tools.microsoft import check_min_vs\nfrom conan.errors import ConanInvalidConfiguration\nfrom conan.test.utils.mocks import ConanFileMock, MockSettings\n\n\nclass TestCheckMinVS:\n\n    parametrize_vars = \"compiler,version,update,minimum\"\n    valid_parametrize_values = [\n        (\"Visual Studio\", \"15\", None, \"191\"),\n        (\"Visual Studio\", \"16\", None, \"192\"),\n        (\"msvc\", \"193\", None, \"193\"),\n        (\"msvc\", \"193\", None, \"192\"),\n        (\"msvc\", \"193\", \"2\", \"193.1\"),\n    ]\n\n    invalid_parametrize_values = [\n        (\"Visual Studio\", \"15\", None, \"192\"),\n        (\"Visual Studio\", \"16\", None, \"193.1\"),\n        (\"msvc\", \"192\", None, \"193\"),\n        (\"msvc\", \"193\", None, \"193.1\"),\n        (\"msvc\", \"193\", \"1\", \"193.2\"),\n    ]\n\n    @staticmethod\n    def _create_conanfile(compiler, version, update=None):\n        settings = MockSettings({\"compiler\": compiler,\n                                 \"compiler.version\": version,\n                                 \"compiler.update\": update})\n        conanfile = ConanFileMock(settings)\n        return conanfile\n\n    @pytest.mark.parametrize(parametrize_vars, valid_parametrize_values)\n    def test_valid(self, compiler, version, update, minimum):\n        conanfile = self._create_conanfile(compiler, version, update)\n        check_min_vs(conanfile, minimum)\n\n    @pytest.mark.parametrize(parametrize_vars, valid_parametrize_values)\n    def test_valid_nothrows(self, compiler, version, update, minimum):\n        conanfile = self._create_conanfile(compiler, version, update)\n        assert check_min_vs(conanfile, minimum, raise_invalid=False)\n\n    @pytest.mark.parametrize(parametrize_vars, invalid_parametrize_values)\n    def test_invalid(self, compiler, version, update, minimum):\n        conanfile = self._create_conanfile(compiler, version, update)\n        with pytest.raises(ConanInvalidConfiguration):\n            check_min_vs(conanfile, minimum)\n\n    @pytest.mark.parametrize(parametrize_vars, invalid_parametrize_values)\n    def test_invalid_nothrows(self, compiler, version, update, minimum):\n        conanfile = self._create_conanfile(compiler, version, update)\n        assert not check_min_vs(conanfile, minimum, raise_invalid=False)\n"
  },
  {
    "path": "test/unittests/tools/microsoft/test_msbuild.py",
    "content": "import os\n\nimport pytest\n\nfrom conan import ConanFile\nfrom conan.tools.microsoft import MSBuild, MSBuildToolchain, is_msvc, is_msvc_static_runtime\nfrom conan.internal.model.conf import ConfDefinition, Conf\nfrom conan.internal.model.settings import Settings\nfrom conan.test.utils.mocks import MockSettings, ConanFileMock, MockOptions\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.internal.util.files import load\n\n\ndef test_msbuild_targets():\n    c = ConfDefinition()\n    settings = MockSettings({\"build_type\": \"Release\",\n                             \"compiler\": \"gcc\",\n                             \"compiler.version\": \"7\",\n                             \"os\": \"Linux\",\n                             \"arch\": \"x86_64\"})\n    conanfile = ConanFileMock()\n    conanfile.settings = settings\n    conanfile.conf = c.get_conanfile_conf(None)\n\n    msbuild = MSBuild(conanfile)\n    cmd = msbuild.command('project.sln', targets=[\"static\", \"shared\"])\n\n    assert '-target:\"static;shared\"' in cmd\n\n\ndef test_msbuild_cpu_count():\n    c = ConfDefinition()\n    c.loads(\"tools.microsoft.msbuild:max_cpu_count=23\")\n\n    settings = MockSettings({\"build_type\": \"Release\",\n                             \"arch\": \"x86_64\"})\n    conanfile = ConanFileMock()\n    conanfile.settings = settings\n    conanfile.conf = c.get_conanfile_conf(None)\n\n    msbuild = MSBuild(conanfile)\n    cmd = msbuild.command('project.sln')\n    assert 'msbuild.exe \"project.sln\" -p:Configuration=\"Release\" -p:Platform=\"x64\" -m:\"23\"' == cmd\n\n    c.loads(\"tools.microsoft.msbuild:max_cpu_count=0\")\n    conanfile.conf = c.get_conanfile_conf(None)\n    cmd = msbuild.command('project.sln')\n    assert 'msbuild.exe \"project.sln\" -p:Configuration=\"Release\" -p:Platform=\"x64\" -m' == cmd\n\n\ndef test_msbuild_toolset():\n    settings = Settings({\"build_type\": [\"Release\"],\n                         \"compiler\": {\"msvc\": {\"version\": [\"193\"], \"toolset\": [None, \"v142_xp\"]}},\n                         \"os\": [\"Windows\"],\n                         \"arch\": [\"x86_64\"]})\n    conanfile = ConanFile(None)\n    conanfile.conf = Conf()\n    conanfile.settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n    conanfile.settings = settings\n    conanfile.settings.build_type = \"Release\"\n    conanfile.settings.compiler = \"msvc\"\n    conanfile.settings.compiler.version = \"193\"\n    conanfile.settings.os = \"Windows\"\n    conanfile.settings.arch = \"x86_64\"\n\n    msbuild = MSBuildToolchain(conanfile)\n    assert 'v143' in msbuild.toolset\n\n    conanfile.settings.compiler.toolset = \"v142_xp\"\n    msbuild = MSBuildToolchain(conanfile)\n    assert 'v142_xp' in msbuild.toolset\n\n\n@pytest.mark.parametrize(\"mode,expected_toolset\", [\n    (\"icx\", \"Intel C++ Compiler 2021\"),\n    (\"dpcpp\", \"Intel(R) oneAPI DPC++ Compiler\"),\n    (\"classic\", \"Intel C++ Compiler 19.2\")\n])\ndef test_msbuild_toolset_for_intel_cc(mode, expected_toolset):\n    conanfile = ConanFile()\n    conanfile.conf = Conf()\n    conanfile.settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n    conanfile.settings = Settings({\"build_type\": [\"Release\"],\n                                   \"compiler\": {\"intel-cc\": {\"version\": [\"2021.3\"], \"mode\": [mode]},\n                                                \"msvc\": {\"version\": [\"193\"], \"cppstd\": [\"20\"]}},\n                                   \"os\": [\"Windows\"],\n                                   \"arch\": [\"x86_64\"]})\n    conanfile.settings.build_type = \"Release\"\n    conanfile.settings.compiler = \"intel-cc\"\n    conanfile.settings.compiler.version = \"2021.3\"\n    conanfile.settings.compiler.mode = mode\n    conanfile.settings.os = \"Windows\"\n    conanfile.settings.arch = \"x86_64\"\n\n    msbuild = MSBuildToolchain(conanfile)\n    assert expected_toolset == msbuild.toolset\n\n\ndef test_msbuild_standard():\n    test_folder = temp_folder()\n    conanfile = ConanFile()\n    conanfile.folders.set_base_generators(test_folder)\n    conanfile.conf = Conf()\n    conanfile.conf.define(\"tools.microsoft.msbuild:installation_path\", \".\")\n    conanfile.settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n    conanfile.settings = Settings({\"build_type\": [\"Release\"],\n                                   \"compiler\": {\"msvc\": {\"version\": [\"193\"], \"cppstd\": [\"20\"],\n                                                         \"cstd\": [\"17\"]}},\n                                   \"os\": [\"Windows\"],\n                                   \"arch\": [\"x86_64\"]})\n    conanfile.settings_build = conanfile.settings\n    conanfile.settings.build_type = \"Release\"\n    conanfile.settings.compiler = \"msvc\"\n    conanfile.settings.compiler.version = \"193\"\n    conanfile.settings.compiler.cppstd = \"20\"\n    conanfile.settings.compiler.cstd = \"17\"\n    conanfile.settings.os = \"Windows\"\n    conanfile.settings.arch = \"x86_64\"\n\n    msbuild = MSBuildToolchain(conanfile)\n    props_file = os.path.join(test_folder, 'conantoolchain_release_x64.props')\n    msbuild.generate()\n    assert '<LanguageStandard>stdcpp20</LanguageStandard>' in load(props_file)\n    assert '<LanguageStandard_C>stdc17</LanguageStandard_C>' in load(props_file)\n\n\ndef test_resource_compile():\n    test_folder = temp_folder()\n\n    settings = Settings({\"build_type\": [\"Release\"],\n                         \"compiler\": {\"msvc\": {\"version\": [\"193\"], \"cppstd\": [\"20\"]}},\n                         \"os\": [\"Windows\"],\n                         \"arch\": [\"x86_64\"]})\n    conanfile = ConanFile()\n    conanfile.folders.set_base_generators(test_folder)\n    conanfile.conf = Conf()\n    conanfile.conf.define(\"tools.microsoft.msbuild:installation_path\", \".\")\n    conanfile.settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n    conanfile.settings = settings\n    conanfile.settings_build = settings\n    conanfile.settings.build_type = \"Release\"\n    conanfile.settings.compiler = \"msvc\"\n    conanfile.settings.compiler.version = \"193\"\n    conanfile.settings.compiler.cppstd = \"20\"\n    conanfile.settings.os = \"Windows\"\n    conanfile.settings.arch = \"x86_64\"\n\n    msbuild = MSBuildToolchain(conanfile)\n    msbuild.preprocessor_definitions[\"MYTEST\"] = \"MYVALUE\"\n    props_file = os.path.join(test_folder, 'conantoolchain_release_x64.props')\n    msbuild.generate()\n    expected = \"\"\"\n        <ResourceCompile>\n          <PreprocessorDefinitions>\n             MYTEST=MYVALUE;%(PreprocessorDefinitions)\n          </PreprocessorDefinitions>\n        </ResourceCompile>\"\"\"\n\n    props_file = load(props_file)  # Remove all blanks and CR to compare\n    props_file = \"\".join(s.strip() for s in props_file.splitlines())\n    assert \"\".join(s.strip() for s in expected.splitlines()) in props_file\n\n\n@pytest.mark.parametrize(\"mode,expected_toolset\", [\n    (\"icx\", \"Intel C++ Compiler 2021\"),\n    (\"dpcpp\", \"Intel(R) oneAPI DPC++ Compiler\"),\n    (\"classic\", \"Intel C++ Compiler 19.2\")\n])\ndef test_msbuild_and_intel_cc_props(mode, expected_toolset):\n    test_folder = temp_folder()\n    settings = Settings({\"build_type\": [\"Release\"],\n                         \"compiler\": {\"intel-cc\": {\"version\": [\"2021.3\"], \"mode\": [mode]},\n                                      \"msvc\": {\"version\": [\"193\"], \"cppstd\": [\"20\"]}},\n                         \"os\": [\"Windows\"],\n                         \"arch\": [\"x86_64\"]})\n    conanfile = ConanFile()\n    conanfile.folders.set_base_generators(test_folder)\n    conanfile.conf = Conf()\n    conanfile.conf.define(\"tools.intel:installation_path\", \"my/intel/oneapi/path\")\n    conanfile.conf.define(\"tools.microsoft.msbuild:installation_path\", \".\")\n    conanfile.settings = \"os\", \"compiler\", \"build_type\", \"arch\"\n    conanfile.settings = settings\n    conanfile.settings.build_type = \"Release\"\n    conanfile.settings.compiler = \"intel-cc\"\n    conanfile.settings.compiler.version = \"2021.3\"\n    conanfile.settings.compiler.mode = mode\n    conanfile.settings.os = \"Windows\"\n    conanfile.settings.arch = \"x86_64\"\n\n    msbuild = MSBuildToolchain(conanfile)\n    props_file = os.path.join(test_folder, 'conantoolchain_release_x64.props')\n    msbuild.generate()\n    assert '<PlatformToolset>%s</PlatformToolset>' % expected_toolset in load(props_file)\n\n\n@pytest.mark.parametrize(\"compiler,expected\", [\n    (\"msvc\", True),\n    (\"clang\", False)\n])\ndef test_is_msvc(compiler, expected):\n    settings = Settings({\"build_type\": [\"Release\"],\n                         \"compiler\": {compiler: {\"version\": [\"2022\"]}},\n                         \"os\": [\"Windows\"],\n                         \"arch\": [\"x86_64\"]})\n    conanfile = ConanFile()\n    conanfile.settings = settings\n    conanfile.settings.compiler = compiler\n    assert is_msvc(conanfile) == expected\n\n\ndef test_is_msvc_build():\n    settings = Settings({\"build_type\": [\"Release\"],\n                         \"compiler\": [\"gcc\", \"msvc\"],\n                         \"os\": [\"Windows\"],\n                         \"arch\": [\"x86_64\"]})\n    conanfile = ConanFile()\n    conanfile.settings = settings\n    conanfile.settings.compiler = \"gcc\"\n    conanfile.settings_build = conanfile.settings.copy()\n    conanfile.settings_build.compiler = \"msvc\"\n    assert is_msvc(conanfile) is False\n    assert is_msvc(conanfile, build_context=True) is True\n\n\n@pytest.mark.parametrize(\"compiler,shared,runtime,build_type,expected\", [\n    (\"msvc\", True, \"static\", \"Release\", True),\n    (\"msvc\", True, \"static\", \"Debug\", True),\n    (\"clang\", True, None, \"Debug\", False),\n])\ndef test_is_msvc_static_runtime(compiler, shared, runtime, build_type, expected):\n    options = MockOptions({\"shared\": shared})\n    settings = MockSettings({\"build_type\": build_type,\n                             \"arch\": \"x86_64\",\n                             \"compiler\": compiler,\n                             \"compiler.runtime\": runtime,\n                             \"compiler.version\": \"17\",\n                             \"cppstd\": \"17\"})\n    conanfile = ConanFileMock(settings, options)\n    assert is_msvc_static_runtime(conanfile) == expected\n\n\ndef test_msbuildtoolchain_changing_flags_via_attributes():\n    test_folder = temp_folder()\n    settings = Settings({\"build_type\": [\"Release\"],\n                         \"compiler\": {\"msvc\": {\"version\": [\"193\"], \"cppstd\": [\"20\"]}},\n                         \"os\": [\"Windows\"],\n                         \"arch\": [\"x86_64\"]})\n    conanfile = ConanFile()\n    conanfile.settings = settings\n    conanfile.folders.set_base_generators(test_folder)\n    conanfile.conf = Conf()\n    conanfile.conf.define_path(\"tools.microsoft.msbuild:installation_path\", \".\")\n    conanfile.settings_build = settings\n    conanfile.settings.build_type = \"Release\"\n    conanfile.settings.compiler = \"msvc\"\n    conanfile.settings.compiler.version = \"193\"\n    conanfile.settings.compiler.cppstd = \"20\"\n    conanfile.settings.os = \"Windows\"\n    conanfile.settings.arch = \"x86_64\"\n\n    msbuild = MSBuildToolchain(conanfile)\n    msbuild.cxxflags.append(\"/flag1\")\n    msbuild.cflags.append(\"/flag2\")\n    msbuild.ldflags.append(\"/link1\")\n    msbuild.generate()\n    toolchain = load(os.path.join(test_folder, \"conantoolchain_release_x64.props\"))\n\n    expected_cl_compile = \"\"\"\n    <ClCompile>\n      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <AdditionalOptions>/flag1 /flag2 %(AdditionalOptions)</AdditionalOptions>\"\"\"\n    expected_link = \"\"\"\n    <Link>\n      <AdditionalOptions>/link1 %(AdditionalOptions)</AdditionalOptions>\n    </Link>\"\"\"\n    expected_resource_compile = \"\"\"\n    <ResourceCompile>\n      <PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>\n    </ResourceCompile>\"\"\"\n    assert expected_cl_compile in toolchain\n    assert expected_link in toolchain\n    assert expected_resource_compile in toolchain\n"
  },
  {
    "path": "test/unittests/tools/microsoft/test_msvs_toolset.py",
    "content": "import pytest\nfrom conan.tools.microsoft import msvs_toolset\nfrom conan.errors import ConanException\nfrom conan.test.utils.mocks import ConanFileMock, MockSettings\n\n\ndef test_invalid_compiler():\n    \"\"\" When the compiler version is unknown and there is no toolset configured,\n        msvs_toolset must return None\n    \"\"\"\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\"compiler\": \"Visual Studio\",\n                                       \"compiler.version\": \"20220203\"})\n    assert msvs_toolset(conanfile) is None\n\n\n@pytest.mark.parametrize(\"compiler_version,expected_toolset\", [\n    (\"195\", \"v145\"),\n    (\"194\", \"v143\"),\n    (\"193\", \"v143\"),\n    (\"192\", \"v142\"),\n    (\"191\", \"v141\"),\n    (\"190\", \"v140\"),\n    (\"180\", \"v120\"),\n    (\"170\", \"v110\")])\ndef test_msvc_default(compiler_version, expected_toolset):\n    \"\"\" When running msvc as compiler, and there is no toolset configured,\n        msvs_toolset must return a specific version based on the compiler version\n    \"\"\"\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\"compiler\": \"msvc\", \"compiler.version\": compiler_version})\n    assert msvs_toolset(conanfile) == expected_toolset\n\n\n@pytest.mark.parametrize(\"compiler_version,toolset,expected_toolset\", [\n    (\"193\", \"v143_xp\", \"v143_xp\"),\n    (\"192\", \"v142_xp\", \"v142_xp\"),\n    (\"191\", \"v141_xp\", \"v141_xp\"),\n    (\"190\", \"v140_xp\", \"v140_xp\"),\n    (\"180\", \"v120_xp\", \"v120_xp\"),\n    (\"170\", \"v110_xp\", \"v110_xp\")])\ndef test_msvc_custom(compiler_version, toolset, expected_toolset):\n    \"\"\" When running msvc as compiler, and there is a toolset configured,\n        msvs_toolset must return the specified toolset from profile\n    \"\"\"\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\"compiler\": \"msvc\",\n                             \"compiler.version\": compiler_version,\n                             \"compiler.toolset\": toolset})\n    assert msvs_toolset(conanfile) == expected_toolset\n\n\ndef test_intel_cc_old_compiler():\n    \"\"\" When running intel-cc as compiler, and the compiler version configured is older than 2021\n        msvs_toolset must raise an ConanExpection\n    \"\"\"\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\"compiler\": \"intel-cc\", \"compiler.version\": \"19.1\"})\n    with pytest.raises(ConanException) as error:\n        msvs_toolset(conanfile)\n    assert \"You have to use 'intel' compiler\" in str(error.value)\n\n\n@pytest.mark.parametrize(\"compiler_version,compiler_mode,expected_toolset\", [\n    (\"2021.3\", \"classic\", \"Intel C++ Compiler 19.2\"),\n    (\"2021.2\", \"classic\", \"Intel C++ Compiler 19.2\"),\n    (\"2021.1\", \"classic\", \"Intel C++ Compiler 19.2\"),\n    (\"2021.3\", \"icx\", \"Intel C++ Compiler 2021\"),\n    (\"2021.2\", \"icx\", \"Intel C++ Compiler 2021\"),\n    (\"2021.1\", \"icx\", \"Intel C++ Compiler 2021\"),\n    (\"2021.3\", \"dpcpp\", \"Intel(R) oneAPI DPC++ Compiler\"),\n    (\"2021.2\", \"dpcpp\", \"Intel(R) oneAPI DPC++ Compiler\"),\n    (\"2021.1\", \"dpcpp\", \"Intel(R) oneAPI DPC++ Compiler\"),\n    (\"2021.3\", None, \"Intel(R) oneAPI DPC++ Compiler\")])\ndef test_intel_cc_default(compiler_version, compiler_mode, expected_toolset):\n    \"\"\" When running intel-cc as compiler, and there is a proper compiler version configured,\n        and the compiler.mode is configured,\n        msvs_toolset must return a compiler toolset based on compiler.mode\n    \"\"\"\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\"compiler\": \"intel-cc\",\n                                       \"compiler.version\": compiler_version,\n                                       \"compiler.mode\": compiler_mode})\n    assert msvs_toolset(conanfile) == expected_toolset\n\ndef test_clang_platform_toolset():\n    conanfile = ConanFileMock()\n    conanfile.settings = MockSettings({\"compiler\": \"clang\",\n                             \"compiler.version\": \"17\",\n                             \"compiler.runtime\": \"dynamic\"})\n    assert msvs_toolset(conanfile) == \"ClangCl\"\n"
  },
  {
    "path": "test/unittests/tools/microsoft/test_subsystem.py",
    "content": "import textwrap\n\nimport pytest\n\nfrom conan.tools.microsoft import unix_path, unix_path_package_info_legacy\nfrom conan.internal.model.conf import ConfDefinition\nfrom conan.test.utils.mocks import MockSettings, ConanFileMock\n\nexpected_results = [\n    (\"msys2\", '/c/path/to/stuff'),\n    (\"msys\", '/c/path/to/stuff'),\n    (\"cygwin\", '/cygdrive/c/path/to/stuff'),\n    (\"wsl\", '/mnt/c/path/to/stuff'),\n]\n\n\n@pytest.mark.parametrize(\"subsystem, expected_path\", expected_results)\ndef test_unix_path(subsystem, expected_path):\n    c = ConfDefinition()\n    c.loads(textwrap.dedent(\"\"\"\\\n        tools.microsoft.bash:subsystem={}\n        tools.microsoft.bash:active=True\n    \"\"\".format(subsystem)))\n\n    settings = MockSettings({\"os\": \"Windows\"})\n    conanfile = ConanFileMock()\n    conanfile.conf = c.get_conanfile_conf(None)\n    conanfile.settings = settings\n    conanfile.settings_build = settings\n\n    test_path = \"c:/path/to/stuff\"\n    path = unix_path(conanfile, test_path)\n    assert expected_path == path\n\n    package_info_legacy_path = unix_path_package_info_legacy(conanfile, test_path, path_flavor=subsystem)\n    assert package_info_legacy_path == test_path\n"
  },
  {
    "path": "test/unittests/tools/system/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/tools/system/python_manager_test.py",
    "content": "from conan.tools.system import PyEnv\nfrom unittest.mock import patch\nimport pytest\nfrom conan.api.output import ConanOutput, LEVEL_QUIET, LEVEL_ERROR, LEVEL_WARNING, \\\n    LEVEL_STATUS, LEVEL_VERBOSE, LEVEL_DEBUG, LEVEL_TRACE\nfrom conan.errors import ConanException\nfrom conan.internal.model.settings import Settings\nfrom conan.test.utils.mocks import ConanFileMock\n\n\n@patch('shutil.which')\ndef test_pyenv_conf(mock_shutil_which):\n    conanfile = ConanFileMock()\n    conanfile.settings = Settings()\n    conanfile.conf.define(\"tools.system.pyenv:python_interpreter\",\n                          \"/python/interpreter/from/config\")\n\n    def fake_run(command, win_bash=False, subsystem=None, env=None, ignore_errors=False,  # noqa\n                 quiet=False):  # noqa\n        assert \"/python/interpreter/from/config\" in command\n\n    conanfile.run = fake_run\n    PyEnv(conanfile, \"testenv\")\n    mock_shutil_which.assert_not_called()\n\n\n@patch('shutil.which')\ndef test_pyenv_deprecated_conf(mock_shutil_which):\n    conanfile = ConanFileMock()\n    conanfile.settings = Settings()\n    conanfile.conf.define(\"tools.system.pipenv:python_interpreter\",\n                          \"/python/interpreter/from/config\")\n\n    def fake_run(command, win_bash=False, subsystem=None, env=None, ignore_errors=False,  # noqa\n                 quiet=False):  # noqa\n        assert \"/python/interpreter/from/config\" in command\n\n    conanfile.run = fake_run\n    PyEnv(conanfile, \"testenv\")\n    mock_shutil_which.assert_not_called()\n\n\n@patch('shutil.which')\ndef test_pyenv_error_message(mock_shutil_which):\n    conanfile = ConanFileMock()\n    conanfile.settings = Settings()\n    mock_shutil_which.return_value = None\n    with pytest.raises(ConanException) as exc_info:\n        PyEnv(conanfile, \"testenv\")\n    assert (\"install Python system-wide or set the 'tools.system.pyenv:python_interpreter' \"\n            \"conf\") in exc_info.value.args[0]\n\n\ndef test_pyenv_creation_error_message():\n    conanfile = ConanFileMock()\n    conanfile.settings = Settings()\n    conanfile.conf.define(\"tools.system.pyenv:python_interpreter\",\n                          \"/python/interpreter/from/config\")\n\n    def fake_run(command, win_bash=False, subsystem=None, env=None, ignore_errors=False,   # noqa\n                 quiet=False):  # noqa\n        raise ConanException(\"fake error message\")\n    conanfile.run = fake_run\n    with pytest.raises(ConanException) as exc_info:\n        PyEnv(conanfile, \"testenv\")\n    assert \"using '/python/interpreter/from/config': fake error message\" in exc_info.value.args[0]\n\n\n@pytest.mark.parametrize(\"level, expected_pip_flag\", [\n    (LEVEL_QUIET, \"-qqq\"),\n    (LEVEL_ERROR, \"-qq\"),\n    (LEVEL_WARNING, \"-q\"),\n    (LEVEL_STATUS, None),\n    (LEVEL_VERBOSE, \"-v\"),\n    (LEVEL_DEBUG, \"-vv\"),\n    (LEVEL_TRACE, \"-vvv\"),\n])\ndef test_pyenv_pip_verbosity(level, expected_pip_flag):\n    \"\"\"\n    https://github.com/conan-io/conan/issues/19729\n    PyEnv.install() should map Conan verbosity levels to pip's native -q/-v flags.\n    \"\"\"\n    conanfile = ConanFileMock()\n    conanfile.settings = Settings()\n    conanfile.conf.define(\"tools.system.pyenv:python_interpreter\",\n                          \"/python/interpreter/from/config\")\n\n    calls = []\n\n    def fake_run(command, win_bash=False, subsystem=None, env=None, ignore_errors=False,  # noqa\n                 quiet=False):  # noqa\n        calls.append(command)\n\n    conanfile.run = fake_run\n\n    old_level = ConanOutput.get_output_level()\n    try:\n        ConanOutput.set_output_level(level)\n        pyenv = PyEnv(conanfile, f\"testenv_{level}\")\n        calls.clear()\n\n        pyenv.install([\"some_package\"])\n        assert len(calls) == 1\n        assert \"pip install\" in calls[0]\n        if expected_pip_flag:\n            assert f\" {expected_pip_flag} \" in calls[0]\n        else:\n            assert \" -q\" not in calls[0]\n            assert \" -v \" not in calls[0]\n    finally:\n        ConanOutput.set_output_level(old_level)\n"
  },
  {
    "path": "test/unittests/util/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/util/apple_test.py",
    "content": "import pytest\n\nfrom conan.tools.apple.apple import _to_apple_arch, apple_min_version_flag, is_apple_os\nfrom conan.test.utils.mocks import MockSettings, ConanFileMock\n\n\nclass TestApple:\n    @pytest.mark.parametrize(\"os_, version, sdk, subsystem, flag\",\n                             [(\"Macos\", \"10.1\", \"macosx\", None, '-mmacosx-version-min=10.1'),\n                              (\"iOS\", \"10.1\", \"iphoneos\", None, '-mios-version-min=10.1'),\n                              (\"iOS\", \"10.1\", \"iphonesimulator\", None,\n                               '-mios-simulator-version-min=10.1'),\n                              (\"watchOS\", \"10.1\", \"watchos\", None, '-mwatchos-version-min=10.1'),\n                              (\"watchOS\", \"10.1\", \"watchsimulator\", None,\n                               '-mwatchos-simulator-version-min=10.1'),\n                              (\"tvOS\", \"10.1\", \"appletvos\", None, '-mtvos-version-min=10.1'),\n                              (\"tvOS\", \"10.1\", \"appletvsimulator\", None,\n                               '-mtvos-simulator-version-min=10.1'),\n                              (\"Macos\", \"10.1\", \"macosx\", \"catalyst\", '-mios-version-min=10.1'),\n                              (\"Solaris\", \"10.1\", None, None, ''),\n                              (\"Macos\", \"10.1\", None, None, '-mmacosx-version-min=10.1'),\n                              (\"Macos\", None, \"macosx\", None, '')\n                              ])\n    def test_deployment_target_flag_name(self, os_, version, sdk, subsystem, flag):\n        conanfile = ConanFileMock()\n        settings = MockSettings({\"os\": os_,\n                                 \"os.version\": version,\n                                 \"os.sdk\": sdk,\n                                 \"os.subsystem\": subsystem})\n        conanfile.settings = settings\n        assert apple_min_version_flag(conanfile) == flag\n\n    @pytest.mark.parametrize(\"_os, result\",\n                             [(\"Macos\", True), (\"iOS\", True), (\"tvOS\", True), (\"watchOS\", True),\n                              (\"Linux\", False), (\"Windows\", False), (\"Android\", False)])\n    def test_is_apple_os(self, _os, result):\n        conanfile = ConanFileMock()\n        settings = MockSettings({\"os\": _os})\n        conanfile.settings = settings\n        assert is_apple_os(conanfile) == result\n\n    def test_to_apple_arch(self):\n        assert _to_apple_arch('x86') == 'i386'\n        assert _to_apple_arch('x86_64') == 'x86_64'\n        assert _to_apple_arch('armv7') == 'armv7'\n        assert _to_apple_arch('armv7s') == 'armv7s'\n        assert _to_apple_arch('armv7k') == 'armv7k'\n        assert _to_apple_arch('armv8') == 'arm64'\n        assert _to_apple_arch('armv8.3') == 'arm64e'\n        assert _to_apple_arch('armv8_32') == 'arm64_32'\n        assert _to_apple_arch('mips') is None\n        assert _to_apple_arch('mips', default='mips') == 'mips'\n"
  },
  {
    "path": "test/unittests/util/conanfile_tools_test.py",
    "content": "import os\nimport stat\nimport tarfile\nimport textwrap\n\nimport pytest\n\nfrom conan.tools.files import replace_in_file, unzip\nfrom conan.test.utils.mocks import ConanFileMock\n\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient\nfrom conan.internal.util.files import load, save\n\n\nclass TestConanfileTools:\n\n    def test_save_append(self):\n        # https://github.com/conan-io/conan/issues/2841 (regression)\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n            from conan.tools.files import save\n            class Pkg(ConanFile):\n                def source(self):\n                    save(self, \"myfile.txt\", \"Hello\", append=True)\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile,\n                     \"myfile.txt\": \"World\"})\n        client.run(\"source .\")\n        assert \"WorldHello\" == client.load(\"myfile.txt\")\n\n    def test_untar(self):\n        tmp_dir = temp_folder()\n        file_path = os.path.join(tmp_dir, \"example.txt\")\n        save(file_path, \"Hello world!\")\n        tar_path = os.path.join(tmp_dir, \"sample.tar\")\n\n        with tarfile.open(tar_path, \"w\") as tar:\n            tar.add(file_path, \"example.txt\")\n\n        output_dir = os.path.join(tmp_dir, \"output_dir\")\n        unzip(ConanFileMock(), tar_path, output_dir)\n        content = load(os.path.join(output_dir, \"example.txt\"))\n        assert content == \"Hello world!\"\n\n    def test_replace_in_file(self):\n        tmp_dir = temp_folder()\n        text_file = os.path.join(tmp_dir, \"text.txt\")\n        save(text_file, \"ONE TWO THREE\")\n        replace_in_file(ConanFileMock(), text_file, \"ONE TWO THREE\", \"FOUR FIVE SIX\")\n        assert load(text_file) == \"FOUR FIVE SIX\"\n\n    def test_replace_in_file_readonly(self):\n        \"\"\"\n        If we try to replace_in_file a read only file it should raise a PermissionError\n        \"\"\"\n        tmp_dir = temp_folder()\n        text_file = os.path.join(tmp_dir, \"text.txt\")\n        save(text_file, \"ONE TWO THREE\")\n\n        os.chmod(text_file,\n                 os.stat(text_file).st_mode & ~(stat.S_IWRITE | stat.S_IWGRP | stat.S_IWOTH))\n\n        with pytest.raises(PermissionError):\n            replace_in_file(ConanFileMock(), text_file, \"ONE TWO THREE\", \"FOUR FIVE SIX\")\n"
  },
  {
    "path": "test/unittests/util/detect_libc_test.py",
    "content": "import pytest\n\nfrom conan.internal.api.detect.detect_api import _parse_gnu_libc, _parse_musl_libc\n\n\nclass TestDetectLibc:\n    @pytest.mark.parametrize(\"ldd_output,expected_glibc_version\",\n        [\n            [\n                \"\"\"ldd (Debian GLIBC 2.36-9+rpt2+deb12u4) 2.36\nCopyright (C) 2022 Free Software Foundation, Inc.\nThis is free software; see the source for copying conditions.  There is NO\nwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\nWritten by Roland McGrath and Ulrich Drepper.\"\"\",\n                \"2.36\",\n            ],\n            [\n                \"\"\"ldd (Ubuntu GLIBC 2.35-0ubuntu3.6) 2.35\nCopyright (C) 2022 Free Software Foundation, Inc.\nThis is free software; see the source for copying conditions.  There is NO\nwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\nWritten by Roland McGrath and Ulrich Drepper.\"\"\",\n                \"2.35\",\n            ],\n            [\n                \"\"\"ldd (GNU libc) 2.38\nCopyright (C) 2023 Free Software Foundation, Inc.\nThis is free software; see the source for copying conditions.  There is NO\nwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\nWritten by Roland McGrath and Ulrich Drepper.\"\"\",\n                \"2.38\",\n            ],\n            [\n                \"\"\"musl libc (x86_64)\nVersion 1.2.4_git20230717\nDynamic Program Loader\nUsage: /lib/ld-musl-x86_64.so.1 [options] [--] pathname\"\"\",\n                None,\n            ],\n        ]\n    )\n    def test_parse_gnu_libc(self, ldd_output, expected_glibc_version):\n        parsed_glibc_version = _parse_gnu_libc(ldd_output)\n        assert expected_glibc_version == parsed_glibc_version\n\n    @pytest.mark.parametrize(\"ldd_output,expected_musl_libc_version\",\n        [\n            [\n                \"\"\"musl libc (x86_64)\nVersion 1.2.4\nDynamic Program Loader\nUsage: /lib/ld-musl-x86_64.so.1 [options] [--] pathname\"\"\",\n                \"1.2.4\",\n            ],\n            [\n                \"\"\"musl libc (x86_64)\nVersion 1.2.4_git20230717\nDynamic Program Loader\nUsage: /lib/ld-musl-x86_64.so.1 [options] [--] pathname\"\"\",\n                \"1.2.4_git20230717\",\n            ],\n            [\n                \"\"\"ldd (Debian GLIBC 2.36-9+rpt2+deb12u4) 2.36\nCopyright (C) 2022 Free Software Foundation, Inc.\nThis is free software; see the source for copying conditions.  There is NO\nwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\nWritten by Roland McGrath and Ulrich Drepper.\"\"\",\n                None,\n            ],\n            [\n                \"\"\"ldd (GNU libc) 2.38\nCopyright (C) 2023 Free Software Foundation, Inc.\nThis is free software; see the source for copying conditions.  There is NO\nwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\nWritten by Roland McGrath and Ulrich Drepper.\"\"\",\n                None,\n            ],\n        ]\n    )\n    def test_parse_musl_libc(self, ldd_output, expected_musl_libc_version):\n        parsed_musl_libc_version = _parse_musl_libc(ldd_output)\n        assert expected_musl_libc_version == parsed_musl_libc_version\n"
  },
  {
    "path": "test/unittests/util/detect_test.py",
    "content": "from unittest import mock\nfrom unittest.mock import patch\nimport pytest\n\nfrom conan.internal.api.detect.detect_api import detect_suncc_compiler, \\\n    detect_intel_compiler, detect_emcc_compiler, detect_default_compiler\nfrom conan.internal.api.profile.detect import detect_defaults_settings\nfrom conan.internal.model.version import Version\nfrom conan.test.utils.mocks import RedirectedTestOutput\nfrom conan.test.utils.tools import redirect_output\nfrom conan.test.utils.env import environment_update\n\n\nclass TestDetect:\n    @mock.patch(\"platform.machine\", return_value=\"\")\n    def test_detect_empty_arch(self, _):\n        result = detect_defaults_settings()\n        result = dict(result)\n        assert \"arch\" not in result\n\n    @pytest.mark.parametrize(\"processor,bitness,version,expected_arch\", [\n        ['powerpc', '64', '7.1.0.0', 'ppc64'],\n        ['powerpc', '32', '7.1.0.0', 'ppc32'],\n        ['rs6000', None, '4.2.1.0', 'ppc32']\n    ])\n    def test_detect_aix(self, processor, bitness, version, expected_arch):\n        with mock.patch(\"platform.machine\", mock.MagicMock(return_value='XXXXXXXXXXXX')), \\\n                mock.patch(\"platform.processor\", mock.MagicMock(return_value=processor)), \\\n                mock.patch(\"platform.system\", mock.MagicMock(return_value='AIX')), \\\n                mock.patch(\"conan.internal.api.detect.detect_api._get_aix_conf\",\n                           mock.MagicMock(return_value=bitness)), \\\n                mock.patch('subprocess.check_output', mock.MagicMock(return_value=version)):\n            result = detect_defaults_settings()\n            result = dict(result)\n            assert \"AIX\" == result['os']\n            assert expected_arch == result['arch']\n\n    @pytest.mark.parametrize(\"machine,expected_arch\", [\n        ['arm64', 'armv8'],\n        ['i386', 'x86'],\n        ['i686', 'x86'],\n        ['i86pc', 'x86'],\n        ['amd64', 'x86_64'],\n        ['aarch64', 'armv8'],\n        ['sun4v', 'sparc']\n    ])\n    def test_detect_arch(self, machine, expected_arch):\n        with mock.patch(\"platform.machine\", mock.MagicMock(return_value=machine)):\n            result = detect_defaults_settings()\n            result = dict(result)\n            assert expected_arch == result['arch']\n\n    @mock.patch(\"conan.internal.api.detect.detect_api.detect_clang_compiler\",\n                return_value=(\"clang\", Version(\"9\"), \"clang\"))\n    def test_detect_clang_gcc_toolchain(self, _):\n        output = RedirectedTestOutput()\n        with redirect_output(output):\n            with environment_update({\"CC\": \"clang-9 --gcc-toolchain=/usr/lib/gcc/x86_64-linux-gnu\"}):\n                detect_defaults_settings()\n                assert \"CC and CXX: clang-9 --gcc-toolchain\" in output\n\n\n@pytest.mark.parametrize(\"version_return,expected_version\", [\n    [\"cc.exe (Rev3, Built by MSYS2 project) 14.1.0\", \"14.1.0\"],\n    [\"g++ (Conan-Build-gcc--binutils-2.42) 14.1.0\", \"14.1.0\"],\n    [\"gcc.exe (x86_64-posix-seh-rev0, Built by MinGW-Builds project) 15.1.0\", \"15.1.0\"],\n    [\"gcc.exe (x86_64-posix-seh-rev0, Built by MinGW-Builds project) 15.15.0\", \"15.15.0\"],\n    [\"gcc (crosstool-NG 1.27.0) 13.3.0\", \"13.3.0\"],\n    [\"gcc (crosstool-NG 1.27.0) 13.3\", \"13.3\"],\n    [\"gcc (GCC) 4.8.1\", \"4.8.1\"],\n    [\"clang version 18.1.0rc (https://github.com/llvm/llvm-project.git 4612...a09e)\", \"18.1.0\"],\n    [\"cc.exe (Rev3, Built by MSYS2 project) 14.0\", \"14.0\"],\n    [\"clang version 18 (https://github.com/llvm/llvm-project.git 4612...8a09e)\", \"18\"],\n    [\"cc.exe (Rev3, Built by MSYS2 project) 14\", \"14\"],\n    [\"cc.exe 14.2\", \"14.2\"],\n    [\"cc1 14.2\", \"14.2\"],\n])\n@patch(\"conan.internal.api.detect.detect_api.detect_runner\")\ndef test_detect_cc_versioning(detect_runner_mock, version_return, expected_version):\n    detect_runner_mock.return_value = 0, version_return\n    with environment_update({\"CC\": \"/usr/bin/cc\"}):\n        compiler, installed_version, compiler_exe = detect_default_compiler()\n    # Using private _value attribute to compare the str that reaches it, so no space issues arise\n    assert installed_version._value == Version(expected_version)._value\n    assert installed_version == Version(expected_version)\n\n\n@pytest.mark.parametrize(\"function,version_return,expected_version\", [\n    [detect_suncc_compiler, \"Sun C 5.13\", ('sun-cc', Version(\"5.13\"), 'cc')],\n    [detect_intel_compiler, \"Intel C++ Compiler 2025.0\", ('intel-cc', Version(\"2025.0\"), 'icx')],\n    [detect_emcc_compiler,\n     \"emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 4.0.22 (0f3d2e62bccf8e14497ff19e05a1202c51eb0c65)\",\n     ('emcc', Version(\"4.0.22\"), 'emcc')],\n    [detect_emcc_compiler,\n     \"shared:INFO: (Emscripten: Running sanity checks)\\n\" +\n     \"emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 4.0.22 (0f3d2e62bccf8e14497ff19e05a1202c51eb0c65)\",\n     ('emcc', Version(\"4.0.22\"), 'emcc')],\n])\ndef test_detect_compiler(function, version_return, expected_version):\n    \"\"\"\n    :type function: Callable\n    \"\"\"\n    with mock.patch(\"conan.internal.api.detect.detect_api.detect_runner\",\n                    mock.MagicMock(return_value=(0, version_return))):\n        ret = function()\n        assert ret == expected_version\n"
  },
  {
    "path": "test/unittests/util/detected_architecture_test.py",
    "content": "from unittest import mock\nimport pytest\n\nfrom conan.internal.api.detect.detect_api import detect_arch\n\n\nclass TestDetectedArchitecture:\n\n    @pytest.mark.parametrize(\"mocked_machine,expected_arch\", [\n        ['i386', 'x86'],\n        ['i686', 'x86'],\n        ['x86_64', 'x86_64'],\n        ['amd64', 'x86_64'],\n        ['aarch64_be', 'armv8'],\n        ['armv8b', 'armv8'],\n        ['armv7l', 'armv7'],\n        ['armv6l', 'armv6'],\n        ['arm', 'armv6'],\n        ['ppc64le', 'ppc64le'],\n        ['ppc64', 'ppc64'],\n        ['mips', 'mips'],\n        ['mips64', 'mips64'],\n        ['sparc', 'sparc'],\n        ['sparc64', 'sparcv9'],\n        ['s390', 's390'],\n        ['s390x', 's390x'],\n        ['arm64', \"armv8\"],\n        ['aarch64', 'armv8'],\n        ['ARM64', 'armv8'],\n        [\"riscv64\", 'riscv64'],\n        ['riscv32', \"riscv32\"]\n    ])\n    def test_various(self, mocked_machine, expected_arch):\n        with mock.patch(\"platform.machine\", mock.MagicMock(return_value=mocked_machine)):\n            assert expected_arch == detect_arch(), f\"given '{mocked_machine}' expected '{expected_arch}'\"\n\n    def test_aix(self):\n        with mock.patch(\"platform.machine\", mock.MagicMock(return_value='00FB91F44C00')),\\\n                mock.patch(\"platform.processor\", mock.MagicMock(return_value='powerpc')),\\\n                mock.patch(\"platform.system\", mock.MagicMock(return_value='AIX')),\\\n                mock.patch(\"conan.internal.api.detect.detect_api._get_aix_conf\", mock.MagicMock(return_value='32')),\\\n                mock.patch('subprocess.check_output', mock.MagicMock(return_value='7.1.0.0')):\n            assert 'ppc32' == detect_arch()\n\n        with mock.patch(\"platform.machine\", mock.MagicMock(return_value='00FB91F44C00')),\\\n                mock.patch(\"platform.processor\", mock.MagicMock(return_value='powerpc')),\\\n                mock.patch(\"platform.system\", mock.MagicMock(return_value='AIX')),\\\n                mock.patch(\"conan.internal.api.detect.detect_api._get_aix_conf\", mock.MagicMock(return_value='64')),\\\n                mock.patch('subprocess.check_output', mock.MagicMock(return_value='7.1.0.0')):\n            assert 'ppc64' == detect_arch()\n\n    def test_solaris(self):\n        with mock.patch(\"platform.machine\", mock.MagicMock(return_value='sun4v')),\\\n                mock.patch(\"platform.processor\", mock.MagicMock(return_value='sparc')),\\\n                mock.patch(\"platform.system\", mock.MagicMock(return_value='SunOS')),\\\n                mock.patch(\"platform.architecture\", mock.MagicMock(return_value=('64bit', 'ELF'))),\\\n                mock.patch(\"platform.release\", mock.MagicMock(return_value='5.11')):\n            assert 'sparcv9' == detect_arch()\n\n        with mock.patch(\"platform.machine\", mock.MagicMock(return_value='i86pc')),\\\n                mock.patch(\"platform.processor\", mock.MagicMock(return_value='i386')),\\\n                mock.patch(\"platform.system\", mock.MagicMock(return_value='SunOS')),\\\n                mock.patch(\"platform.architecture\", mock.MagicMock(return_value=('64bit', 'ELF'))),\\\n                mock.patch(\"platform.release\", mock.MagicMock(return_value='5.11')):\n            assert 'x86_64' == detect_arch()\n\n    @pytest.mark.parametrize(\"processor,expected_arch\", [\n        [\"E1C+\", \"e2k-v4\"],\n        [\"E2C+\", \"e2k-v2\"],\n        [\"E2C+DSP\", \"e2k-v2\"],\n        [\"E2C3\", \"e2k-v6\"],\n        [\"E2S\", \"e2k-v3\"],\n        [\"E8C\", \"e2k-v4\"],\n        [\"E8C2\", \"e2k-v5\"],\n        [\"E12C\", \"e2k-v6\"],\n        [\"E16C\", \"e2k-v6\"],\n        [\"E32C\", \"e2k-v7\"]\n    ])\n    def test_e2k(self, processor, expected_arch):\n        with mock.patch(\"platform.machine\", mock.MagicMock(return_value='e2k')), \\\n                mock.patch(\"platform.processor\", mock.MagicMock(return_value=processor)):\n            assert expected_arch == detect_arch()\n"
  },
  {
    "path": "test/unittests/util/file_hashes_test.py",
    "content": "import os\nimport pytest\n\nfrom conan.tools.files import check_md5, check_sha1, check_sha256\nfrom conan.errors import ConanException\nfrom conan.test.utils.mocks import ConanFileMock\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.internal.util.files import save\n\n\nclass TestHashes:\n\n    def test_md5(self):\n        folder = temp_folder()\n        filepath = os.path.join(folder, \"file.txt\")\n        file_content = \"a file\"\n        save(filepath, file_content)\n\n        check_md5(ConanFileMock(), filepath, \"d6d0c756fb8abfb33e652a20e85b70bc\")\n        check_sha1(ConanFileMock(), filepath, \"eb599ec83d383f0f25691c184f656d40384f9435\")\n        check_sha256(ConanFileMock(), filepath, \"7365d029861e32c521f8089b00a6fb32daf0615025b69b599d1ce53501b845c2\")\n\n        with pytest.raises(ConanException, match=\"md5 hash failed for 'file.txt' file.\"):\n            check_md5(ConanFileMock(), filepath, \"invalid\")\n\n        with pytest.raises(ConanException, match=\"sha1 hash failed for 'file.txt' file.\"):\n            check_sha1(ConanFileMock(), filepath, \"invalid\")\n\n        with pytest.raises(ConanException, match=\"sha256 hash failed for 'file.txt' file.\"):\n            check_sha256(ConanFileMock(), filepath, \"invalid\")\n"
  },
  {
    "path": "test/unittests/util/files/__init__.py",
    "content": ""
  },
  {
    "path": "test/unittests/util/files/strip_root_extract_test.py",
    "content": "import os\nimport platform\nimport tarfile\nimport zipfile\n\nimport pytest\nimport sys\n\nfrom conan.internal.api.uploader import gzopen_without_timestamps\nfrom conan.tools.files import load\nfrom conan.tools.files.files import untargz, unzip\nfrom conan.errors import ConanException\nfrom conan.internal.model.manifest import gather_files\nfrom conan.test.utils.mocks import ConanFileMock\nfrom conan.test.utils.mocks import RedirectedTestOutput\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import redirect_output\nfrom conan.internal.util.files import chdir, save\nfrom conan.internal.util.files import rmdir\n\n\nclass TestZipExtractPlain:\n\n    @staticmethod\n    def _zipdir(path, zipfilename, folder_entry=None):\n        with zipfile.ZipFile(zipfilename, 'w', zipfile.ZIP_DEFLATED) as z:\n            if folder_entry:\n                zif = zipfile.ZipInfo(folder_entry + \"/\")\n                z.writestr(zif, \"\")\n\n            for root, _, files in os.walk(path):\n                for f in files:\n                    file_path = os.path.join(root, f)\n                    if file_path == zipfilename:\n                        continue\n                    relpath = os.path.relpath(file_path, path)\n                    z.write(file_path, relpath)\n\n    def test_plain_zip(self):\n        tmp_folder = temp_folder()\n        with chdir(tmp_folder):\n            ori_files_dir = os.path.join(tmp_folder, \"subfolder-1.2.3\")\n            file1 = os.path.join(ori_files_dir, \"file1\")\n            file2 = os.path.join(ori_files_dir, \"folder\", \"file2\")\n            file3 = os.path.join(ori_files_dir, \"file3\")\n\n            save(file1, \"\")\n            save(file2, \"\")\n            save(file3, \"\")\n\n        zip_file = os.path.join(tmp_folder, \"myzip.zip\")\n        # Zip with a \"folder_entry\" in the zip (not only for the files)\n        self._zipdir(tmp_folder, zip_file, folder_entry=\"subfolder-1.2.3\")\n\n        # ZIP unzipped regularly\n        extract_folder = temp_folder()\n        output = RedirectedTestOutput()\n        with redirect_output(output):\n            unzip(ConanFileMock(), zip_file, destination=extract_folder, strip_root=False)\n        assert \"ERROR: Error extract\" not in output\n        assert os.path.exists(os.path.join(extract_folder, \"subfolder-1.2.3\"))\n        assert os.path.exists(os.path.join(extract_folder, \"subfolder-1.2.3\", \"file1\"))\n        assert os.path.exists(os.path.join(extract_folder, \"subfolder-1.2.3\", \"folder\",\n                                           \"file2\"))\n        assert os.path.exists(os.path.join(extract_folder, \"subfolder-1.2.3\", \"file3\"))\n\n        # Extract without the subfolder\n        extract_folder = temp_folder()\n        output = RedirectedTestOutput()\n        with redirect_output(output):\n            unzip(ConanFileMock(), zip_file, destination=extract_folder, strip_root=True)\n        assert \"ERROR: Error extract\" not in output\n        assert not os.path.exists(os.path.join(extract_folder, \"subfolder-1.2.3\"))\n        assert os.path.exists(os.path.join(extract_folder, \"file1\"))\n        assert os.path.exists(os.path.join(extract_folder, \"folder\", \"file2\"))\n        assert os.path.exists(os.path.join(extract_folder, \"file3\"))\n\n    def test_invalid_flat(self):\n        tmp_folder = temp_folder()\n        with chdir(tmp_folder):\n            # Not a single dir containing everything\n            file1 = os.path.join(tmp_folder, \"subfolder-1.2.3\", \"folder2\", \"file1\")\n            file2 = os.path.join(tmp_folder, \"other-1.2.3\", \"folder\", \"file2\")\n\n            save(file1, \"\")\n            save(file2, \"\")\n\n        zip_folder = temp_folder()\n        zip_file = os.path.join(zip_folder, \"file.zip\")\n        self._zipdir(tmp_folder, zip_file)\n\n        # Extract without the subfolder\n        extract_folder = temp_folder()\n        with pytest.raises(ConanException) as e:\n            unzip(ConanFileMock(), zip_file, destination=extract_folder, strip_root=True)\n        assert \"The zip file contains more than 1 folder in the root\" in str(e)\n\n    def test_invalid_flat_single_file(self):\n        tmp_folder = temp_folder()\n        with chdir(tmp_folder):\n            save(\"file1\", \"contentsfile1\")\n\n        zip_folder = temp_folder()\n        zip_file = os.path.join(zip_folder, \"file.zip\")\n        self._zipdir(tmp_folder, zip_file)\n\n        # Extract without the subfolder\n        extract_folder = temp_folder()\n        with pytest.raises(ConanException) as e:\n            unzip(ConanFileMock(), zip_file, destination=extract_folder, strip_root=True)\n        assert \"The zip file contains a file in the root\" in str(e)\n\n\nclass TestTarExtractPlain:\n\n    @staticmethod\n    def _compress_folder(folder, tgz_path, folder_entry=None):\n        # Create a tar.gz file with the files in the folder and an additional TarInfo entry\n        # for the folder_entry (the gather files doesn't return empty dirs)\n        with open(tgz_path, \"wb\") as tgz_handle:\n            tgz = gzopen_without_timestamps(\"name\", fileobj=tgz_handle)\n            if folder_entry:\n                # Create an empty folder in the tgz file\n                t = tarfile.TarInfo(folder_entry)\n                t.mode = 488\n                t.type = tarfile.DIRTYPE\n                tgz.addfile(t)\n            files, _ = gather_files(folder)\n            for filename, abs_path in files.items():\n                info = tarfile.TarInfo(name=filename)\n                with open(os.path.join(folder, filename), 'rb') as file_handler:\n                    tgz.addfile(tarinfo=info, fileobj=file_handler)\n            tgz.close()\n\n    def test_linkame_striproot_folder(self):\n        tmp_folder = temp_folder()\n        other_tmp_folder = temp_folder()\n        save(os.path.join(other_tmp_folder, \"foo.txt\"), \"\")\n        tgz_path = os.path.join(tmp_folder, \"foo.tgz\")\n\n        with open(tgz_path, \"wb\") as tgz_handle:\n            tgz = gzopen_without_timestamps(\"name\", fileobj=tgz_handle)\n\n            # Regular file\n            info = tarfile.TarInfo(name=\"common/foo.txt\")\n            info.name = \"common/subfolder/foo.txt\"\n            info.path = \"common/subfolder/foo.txt\"\n            with open(os.path.join(other_tmp_folder, \"foo.txt\"), 'rb') as file_handler:\n                tgz.addfile(tarinfo=info, fileobj=file_handler)\n\n            # A hardlink to the regular file\n            info = tarfile.TarInfo(name=\"common/foo.txt\")\n            info.linkname = \"common/subfolder/foo.txt\"\n            info.linkpath = \"common/subfolder/foo.txt\"\n            info.name = \"common/subfolder/bar/foo.txt\"\n            info.path = \"common/subfolder/bar/foo.txt\"\n            info.type = b'1'  # This indicates a hardlink to the tgz file \"common/subfolder/foo.txt\"\n            tgz.addfile(tarinfo=info, fileobj=None)\n            tgz.close()\n\n        assert not os.path.exists(os.path.join(tmp_folder, \"subfolder\", \"foo.txt\"))\n        assert not os.path.exists(os.path.join(tmp_folder, \"subfolder\", \"bar\", \"foo.txt\"))\n        untargz(tgz_path, destination=tmp_folder, strip_root=True)\n        assert os.path.exists(os.path.join(tmp_folder, \"subfolder\", \"foo.txt\"))\n        assert os.path.exists(os.path.join(tmp_folder, \"subfolder\", \"bar\", \"foo.txt\"))\n\n        # Check develop2 public unzip\n        rmdir(os.path.join(tmp_folder, \"subfolder\"))\n        assert not os.path.exists(os.path.join(tmp_folder, \"subfolder\", \"foo.txt\"))\n        assert not os.path.exists(os.path.join(tmp_folder, \"subfolder\", \"bar\", \"foo.txt\"))\n        unzip(ConanFileMock(), tgz_path, destination=tmp_folder, strip_root=True)\n        assert os.path.exists(os.path.join(tmp_folder, \"subfolder\", \"foo.txt\"))\n        assert os.path.exists(os.path.join(tmp_folder, \"subfolder\", \"bar\", \"foo.txt\"))\n\n    def test_plain_tgz(self):\n\n        tmp_folder = temp_folder()\n        with chdir(tmp_folder):\n            # Create a couple of files\n            ori_files_dir = os.path.join(tmp_folder, \"subfolder-1.2.3\")\n            file1 = os.path.join(ori_files_dir, \"file1\")\n            file2 = os.path.join(ori_files_dir, \"folder\", \"file2\")\n            file3 = os.path.join(ori_files_dir, \"file3\")\n\n            save(file1, \"\")\n            save(file2, \"\")\n            save(file3, \"\")\n\n        tgz_folder = temp_folder()\n        tgz_file = os.path.join(tgz_folder, \"file.tar.gz\")\n        self._compress_folder(tmp_folder, tgz_file, folder_entry=\"subfolder-1.2.3\")\n\n        # Tgz unzipped regularly\n        extract_folder = temp_folder()\n        untargz(tgz_file, destination=extract_folder, strip_root=False)\n        assert os.path.exists(os.path.join(extract_folder, \"subfolder-1.2.3\"))\n        assert os.path.exists(os.path.join(extract_folder, \"subfolder-1.2.3\", \"file1\"))\n        assert os.path.exists(os.path.join(extract_folder, \"subfolder-1.2.3\", \"folder\",\n                                           \"file2\"))\n        assert os.path.exists(os.path.join(extract_folder, \"subfolder-1.2.3\", \"file3\"))\n\n        # Extract without the subfolder\n        extract_folder = temp_folder()\n        untargz(tgz_file, destination=extract_folder, strip_root=True)\n        assert not os.path.exists(os.path.join(extract_folder, \"subfolder-1.2.3\"))\n        assert os.path.exists(os.path.join(extract_folder, \"file1\"))\n        assert os.path.exists(os.path.join(extract_folder, \"folder\", \"file2\"))\n        assert os.path.exists(os.path.join(extract_folder, \"file3\"))\n\n    def test_plain_tgz_common_base(self):\n\n        tmp_folder = temp_folder()\n        with chdir(tmp_folder):\n            # Create a couple of files\n            ori_files_dir = os.path.join(tmp_folder, \"subfolder-1.2.3\")\n            file1 = os.path.join(ori_files_dir, \"folder\", \"file1\")\n            file2 = os.path.join(ori_files_dir, \"folder\", \"file2\")\n            file3 = os.path.join(ori_files_dir, \"folder\", \"file3\")\n\n            save(file1, \"\")\n            save(file2, \"\")\n            save(file3, \"\")\n\n        tgz_folder = temp_folder()\n        tgz_file = os.path.join(tgz_folder, \"file.tar.gz\")\n        self._compress_folder(tmp_folder, tgz_file)\n\n        # Tgz unzipped regularly\n        extract_folder = temp_folder()\n        untargz(tgz_file, destination=extract_folder, strip_root=True)\n        assert not os.path.exists(os.path.join(extract_folder, \"subfolder-1.2.3\"))\n        assert os.path.exists(os.path.join(extract_folder, \"folder\", \"file1\"))\n        assert os.path.exists(os.path.join(extract_folder, \"folder\", \"file2\"))\n        assert os.path.exists(os.path.join(extract_folder, \"folder\", \"file3\"))\n\n    def test_invalid_flat(self):\n        tmp_folder = temp_folder()\n        with chdir(tmp_folder):\n            # Not a single dir containing everything\n            file1 = os.path.join(tmp_folder, \"subfolder-1.2.3\", \"folder2\", \"file1\")\n            file2 = os.path.join(tmp_folder, \"other-1.2.3\", \"folder\", \"file2\")\n\n            save(file1, \"\")\n            save(file2, \"\")\n\n        tgz_folder = temp_folder()\n        tgz_file = os.path.join(tgz_folder, \"file.tar.gz\")\n        self._compress_folder(tmp_folder, tgz_file)\n\n        extract_folder = temp_folder()\n        with pytest.raises(ConanException) as e:\n            untargz(tgz_file, destination=extract_folder, strip_root=True)\n        assert \"The tgz file contains more than 1 folder in the root\" in str(e)\n\n    def test_invalid_flat_single_file(self):\n        tmp_folder = temp_folder()\n        with chdir(tmp_folder):\n            save(\"file1\", \"contentsfile1\")\n\n        zip_folder = temp_folder()\n        tgz_file = os.path.join(zip_folder, \"file.tar.gz\")\n        self._compress_folder(tmp_folder, tgz_file)\n\n        # Extract without the subfolder\n        extract_folder = temp_folder()\n        with pytest.raises(ConanException) as e:\n            unzip(ConanFileMock(), tgz_file, destination=extract_folder, strip_root=True)\n        assert \"Can't untar a tgz containing files in the root with strip_root enabled\" in str(e)\n\n    def test_invalid_flat_multiple_file(self):\n        tmp_folder = temp_folder()\n        with chdir(tmp_folder):\n            save(\"file1\", \"contentsfile1\")\n            save(\"file2\", \"contentsfile2\")\n\n        zip_folder = temp_folder()\n        tgz_file = os.path.join(zip_folder, \"file.tar.gz\")\n        self._compress_folder(tmp_folder, tgz_file)\n\n        # Extract without the subfolder\n        extract_folder = temp_folder()\n        with pytest.raises(ConanException) as e:\n            unzip(ConanFileMock(), tgz_file, destination=extract_folder, strip_root=True)\n        assert \"Can't untar a tgz containing files in the root with strip_root enabled\" in str(e)\n\n\ndef _compress_root_folder(folder, tgz_path, root_folder_name=\"root\"):\n    \"\"\"\n    Compress the whole folder adding withing the tar file also the folders. For instance:\n\n    $ tar -tf '/tmp/folder/file.tar.gz'\n    root/\n    root/parent/\n    root/parent/bin/\n    root/parent/bin/file1\n    root/parent/bin/file2\n    \"\"\"\n    with open(tgz_path, \"wb\") as tgz_handle:\n        tgz = gzopen_without_timestamps(\"name\", fileobj=tgz_handle)\n        files, _ = gather_files(folder)\n        tgz.add(root_folder_name, arcname=os.path.basename(root_folder_name))\n        tgz.close()\n\n\ndef test_decompressing_folders_with_different_modes():\n    \"\"\"\n    When compressed folders come with restrictive permissions, untar() function should not\n    raise a PermissionError.\n\n    Issue related: https://github.com/conan-io/conan/issues/17987\n    \"\"\"\n    tmp_folder = temp_folder()\n    tgz_folder = temp_folder()\n    tgz_file = os.path.join(tgz_folder, \"file.tar.gz\")\n    with chdir(tmp_folder):\n        save(\"root/parent/bin/file1\", \"contentsfile1\")\n        save(\"root/parent/bin/file2\", \"contentsfile2\")\n        os.chmod(os.path.join(\"root\", \"parent\"), mode=0o555)\n        os.chmod(os.path.join(\"root\", \"parent\", \"bin\"), mode=0o700)\n        _compress_root_folder(tmp_folder, tgz_file, root_folder_name=\"root\")\n\n    # Tgz unzipped regularly\n    extract_folder = temp_folder()\n    # Do not raise any PermissionError\n    untargz(tgz_file, destination=extract_folder, strip_root=True)\n\n\n@pytest.mark.skipif(sys.version_info < (3, 13, 4), reason=\"requires Python 3.13.4 or higher\")\n@pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows\")\ndef test_decompressing_using_long_path_prefix():\n    \"\"\"\n    If we use the \"\\\\?\\\" prefix, untar() function should not\n    raise an OSError: [WinError 123] error.\n\n    Issue related: https://github.com/conan-io/conan/issues/18574\n    \"\"\"\n    tmp_folder = temp_folder()\n    tgz_folder = temp_folder()\n    tgz_file = os.path.join(tgz_folder, \"file.tar.gz\")\n    with chdir(tmp_folder):\n        save(\"root/parent/bin/file1\", \"contentsfile1\")\n        save(\"root/parent/bin/file2\", \"contentsfile2\")\n        _compress_root_folder(tmp_folder, tgz_file, root_folder_name=\"root\")\n\n    # Tgz unzipped regularly\n    extract_folder = f\"\\\\\\\\?\\\\{temp_folder()}\"\n    # Do not raise any OSError: [WinError 123]\n    untargz(tgz_file, destination=extract_folder, strip_root=True)\n    assert \"contentsfile1\" in load(ConanFileMock(), os.path.join(extract_folder, \"parent\", \"bin\", \"file1\"))\n    assert \"contentsfile2\" in load(ConanFileMock(), os.path.join(extract_folder, \"parent\", \"bin\", \"file2\"))\n    untargz(tgz_file, destination=extract_folder, strip_root=False)\n    assert \"contentsfile1\" in load(ConanFileMock(), os.path.join(extract_folder, \"root\", \"parent\", \"bin\", \"file1\"))\n    assert \"contentsfile2\" in load(ConanFileMock(), os.path.join(extract_folder, \"root\", \"parent\", \"bin\", \"file2\"))\n"
  },
  {
    "path": "test/unittests/util/files/tar_extract_test.py",
    "content": "import os\nimport platform\nimport tarfile\nimport pytest\n\nfrom conan.internal.api.uploader import gzopen_without_timestamps\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.internal.util.files import tar_extract, save, gather_files, chdir\n\n\nclass TestTarExtract:\n\n    @pytest.fixture\n    def setup_files(self):\n        tmp_folder = temp_folder()\n        with chdir(tmp_folder):\n            # Create a couple of files\n            ori_files_dir = os.path.join(tmp_folder, \"ori\")\n            file1 = os.path.join(ori_files_dir, \"file1\")\n            file2 = os.path.join(ori_files_dir, \"folder\", \"file2\")\n            save(file1, \"\")\n            save(file2, \"\")\n\n            # Create a tar.gz file with the above files\n            tgz_file = os.path.join(tmp_folder, \"file.tar.gz\")\n            with open(tgz_file, \"wb\") as tgz_handle:\n                tgz = gzopen_without_timestamps(\"name\", fileobj=tgz_handle)\n\n                files, _ = gather_files(ori_files_dir)\n                for filename, abs_path in files.items():\n                    info = tarfile.TarInfo(name=filename)\n                    with open(file1, 'rb') as file_handler:\n                        tgz.addfile(tarinfo=info, fileobj=file_handler)\n                tgz.close()\n        return tmp_folder, tgz_file\n\n    @pytest.mark.skipif(platform.system() == \"Windows\", reason=\"Requires Linux or Mac\")\n    def test_link_folder(self, setup_files):\n        # If there is a linked folder in the current directory that matches one file in the tar.\n        # https://github.com/conan-io/conan/issues/4959\n        tmp_folder, tgz_file = setup_files\n\n        # Once unpackaged, this is the content of the destination directory\n        def check_files(dest_dir):\n            d = sorted(os.listdir(dest_dir))\n            assert d == [\"file1\", \"folder\"]\n            d_folder = os.listdir(os.path.join(dest_dir, \"folder\"))\n            assert d_folder == [\"file2\"]\n\n        working_dir = temp_folder()\n        with chdir(working_dir):\n            # Unpack and check\n            destination_dir = os.path.join(tmp_folder, \"dest\")\n            with open(tgz_file, 'rb') as file_handler:\n                tar_extract(file_handler, destination_dir)\n            check_files(destination_dir)\n\n            # Unpack and check (now we have a symlinked local folder)\n            os.symlink(temp_folder(), \"folder\")\n            destination_dir = os.path.join(tmp_folder, \"dest2\")\n            with open(tgz_file, 'rb') as file_handler:\n                tar_extract(file_handler, destination_dir)\n            check_files(destination_dir)\n"
  },
  {
    "path": "test/unittests/util/files/test_copy_compat.py",
    "content": "import pytest\n\nfrom conan.internal.util.files import copytree_compat\n\n\n@pytest.fixture\ndef source_dest_folders(tmp_path):\n    source_folder = tmp_path / \"source\"\n    dest_folder = tmp_path / \"dest\"\n    source_folder.mkdir()\n    dest_folder.mkdir()\n    test_file = source_folder / \"test_file.txt\"\n    test_file.write_text(\"Test content\")\n    return source_folder, dest_folder\n\n\ndef test_copytree_compat(source_dest_folders):\n    source_folder, dest_folder = source_dest_folders\n    copytree_compat(str(source_folder), str(dest_folder))\n    assert (dest_folder / \"test_file.txt\").exists()\n"
  },
  {
    "path": "test/unittests/util/files/test_dirty.py",
    "content": "import os\nimport pytest\n\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.internal.util.files import set_dirty, clean_dirty, set_dirty_context_manager, _DIRTY_FOLDER\n\n\nclass TestDirty:\n\n    @pytest.fixture\n    def setup_dirty(self):\n        \"\"\" Create temporary folder to save dirty state\n        \"\"\"\n        tempfolder = temp_folder()\n        dirty_folder = tempfolder + _DIRTY_FOLDER\n        return tempfolder, dirty_folder\n\n    def test_set_dirty(self, setup_dirty):\n        \"\"\" Dirty flag must be created by set_dirty\n        \"\"\"\n        folder, dirty_folder = setup_dirty\n        set_dirty(folder)\n        assert os.path.exists(dirty_folder)\n\n    def test_clean_dirty(self, setup_dirty):\n        \"\"\" Dirty flag must be cleaned by clean_dirty\n        \"\"\"\n        folder, dirty_folder = setup_dirty\n        set_dirty(folder)\n        assert os.path.exists(dirty_folder)\n        clean_dirty(folder)\n        assert not os.path.exists(dirty_folder)\n\n    def test_set_dirty_context(self, setup_dirty):\n        \"\"\" Dirty context must remove lock before exiting\n        \"\"\"\n        folder, dirty_folder = setup_dirty\n        with set_dirty_context_manager(folder):\n            assert os.path.exists(dirty_folder)\n        assert not os.path.exists(dirty_folder)\n\n    def test_interrupted_dirty_context(self, setup_dirty):\n        \"\"\" Broken context must preserve dirty state\n\n            Raise an exception in middle of context. By default,\n            dirty file is not removed.\n        \"\"\"\n        folder, dirty_folder = setup_dirty\n        try:\n            with set_dirty_context_manager(folder):\n                assert os.path.exists(dirty_folder)\n                raise RuntimeError()\n        except RuntimeError:\n            pass\n        assert os.path.exists(dirty_folder)\n"
  },
  {
    "path": "test/unittests/util/files/test_remove.py",
    "content": "import os\nimport stat\nimport pytest\n\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.internal.util.files import remove, save\n\n\nclass TestRemove:\n\n    @pytest.fixture\n    def setup_file(self):\n        file = os.path.join(temp_folder(), 'file.txt')\n        save(file, \"some content\")\n        return file\n\n    def test_remove(self, setup_file):\n        remove(setup_file)\n        assert not os.path.exists(setup_file)\n        assert os.path.exists(os.path.dirname(setup_file))\n\n    def test_remove_readonly(self, setup_file):\n        os.chmod(setup_file, stat.S_IREAD | stat.S_IRGRP | stat.S_IROTH)\n        with pytest.raises((IOError, OSError)):\n            save(setup_file, \"change the content\")\n        remove(setup_file)\n        assert not os.path.exists(setup_file)\n        assert os.path.exists(os.path.dirname(setup_file))\n\n    def test_remove_folder(self, setup_file):\n        dirname = os.path.dirname(setup_file)\n        with pytest.raises(AssertionError):\n            remove(dirname)\n        assert os.path.exists(dirname)\n"
  },
  {
    "path": "test/unittests/util/files_extract_wildcard_test.py",
    "content": "import os\nimport tarfile\nimport zipfile\nfrom unittest import TestCase\n\nfrom conan.tools.files import unzip\nfrom conan.test.utils.mocks import ConanFileMock\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.internal.util.files import save_files\n\n\ndef create_archive(archive, root, relative_file_paths):\n    \"\"\" Create an archive with given file paths relative to given root.\"\"\"\n    extension = os.path.basename(archive).split(os.extsep, 1)[1]\n    if extension == \"zip\":\n        with zipfile.ZipFile(archive, mode=\"w\") as z:\n            for file_ in relative_file_paths:\n                z.write(os.path.join(root, file_), arcname=file_)\n    else:\n        # Treat any other extension except \"tar.gz\" as a normal \"tar\"\n        mode = \"gz\" if extension == \"tar.gz\" else \"\"\n        with tarfile.open(archive, mode=\"w:%s\" % mode) as t:\n            for file_ in relative_file_paths:\n                t.add(os.path.join(root, file_), arcname=file_)\n    return archive\n\n\nclass FilesExtractPatternTest(TestCase):\n\n    def test_patterns(self):\n        # Test setup\n        src_dir = temp_folder()\n        files = {\n            \"foo/file.cpp\": \"code\",\n            \"foo/bar/file.txt\": \"text\",\n            \"foo/bar/file.cpp\": \"more code\",\n            \"foo/bar/baz/file.txt\": \"more text\"\n        }\n        matches = {\n            \"*.cpp\": [\"foo/file.cpp\",\n                      \"foo/bar/file.cpp\"],\n            \"*.txt\": [\"foo/bar/file.txt\",\n                      \"foo/bar/baz/file.txt\"],\n            \"foo/bar/*\": [\"foo/bar/file.txt\",\n                          \"foo/bar/file.cpp\",\n                          \"foo/bar/baz/file.txt\"],\n            \"foo/bar/baz/*\": [\"foo/bar/baz/file.txt\"],\n            \"*\": [\"foo/file.cpp\",\n                  \"foo/bar/file.txt\",\n                  \"foo/bar/file.cpp\",\n                  \"foo/bar/baz/file.txt\"],\n            \"nothing\": []\n        }\n        save_files(src_dir, files)\n\n        for extension in [\"zip\", \"tar\", \"tar.gz\"]:\n            # GIVEN an archive with files inside\n            archive_dir = temp_folder()\n            archive = os.path.join(archive_dir, \"archive.%s\" % extension)\n            create_archive(archive, src_dir, files)\n\n            for (pattern, paths) in matches.items():\n                # WHEN a pattern is used for file extraction\n                dst_dir = temp_folder()\n                unzip(ConanFileMock(), archive, dst_dir, pattern=pattern)\n\n                # THEN only and all files matching the pattern are extracted\n                actual = set()\n                expected = set(map(lambda x: os.path.join(dst_dir, *x.split(\"/\")), paths))\n                for extracted_dir, _, extracted_files in os.walk(dst_dir):\n                    actual.update(map(lambda x: os.path.join(extracted_dir, x),\n                                      extracted_files))\n\n                self.assertSetEqual(expected, actual)\n"
  },
  {
    "path": "test/unittests/util/local_db_test.py",
    "content": "import os\n\nfrom conan.internal.api.remotes.localdb import LocalDB\nfrom conan.test.utils.test_files import temp_folder\n\n\ndef test_localdb():\n    tmp_dir = temp_folder()\n    db_file = os.path.join(tmp_dir, \"dbfile\")\n    localdb = LocalDB(db_file)\n\n    # Test write and read login\n    user, token, access_token = localdb.get_login(\"myurl1\")\n    assert user is None\n    assert token is None\n    assert access_token is None\n\n    localdb.store(\"pepe\", \"token\", \"access_token\", \"myurl1\")\n    user, token, access_token = localdb.get_login(\"myurl1\")\n    assert user == \"pepe\"\n    assert token == \"token\"\n    assert access_token == \"access_token\"\n    assert \"pepe\" == localdb.get_username(\"myurl1\")\n"
  },
  {
    "path": "test/unittests/util/output_test.py",
    "content": "import os\nimport textwrap\nimport zipfile\n\nfrom conan.tools.files import unzip\nfrom conan.test.utils.mocks import RedirectedTestOutput, ConanFileMock\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import TestClient, redirect_output\nfrom conan.internal.util.files import load, save\n\n\nclass TestOutput:\n\n    def test_error(self):\n        client = TestClient()\n        conanfile = textwrap.dedent(\"\"\"\n            from conan import ConanFile\n\n            class PkgConan(ConanFile):\n                def source(self):\n                   self.output.info(\"TEXT ÑÜíóúéáàèòù абвгдежзийкл 做戏之说  ENDTEXT\")\n            \"\"\")\n        client.save({\"conanfile.py\": conanfile})\n        client.run(\"install .\")\n        client.run(\"source .\")\n        assert \"TEXT\" in client.out\n        assert \"ENDTEXT\" in client.out\n\n    def test_unzip_output(self):\n        tmp_dir = temp_folder()\n        file_path = os.path.join(tmp_dir, \"example.txt\")\n        save(file_path, \"Hello world!\")\n\n        zip_path = os.path.join(tmp_dir, 'example.zip')\n        zipf = zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED)\n        for root, _, files in os.walk(tmp_dir):\n            for f in files:\n                zipf.write(os.path.join(root, f), f)\n        zipf.close()\n\n        output_dir = os.path.join(tmp_dir, \"output_dir\")\n        captured_output = RedirectedTestOutput()\n        with redirect_output(captured_output):\n            unzip(ConanFileMock(), zip_path, output_dir)\n\n        output = captured_output.getvalue()\n        assert \"Unzipping\" in output\n        content = load(os.path.join(output_dir, \"example.txt\"))\n        assert content == \"Hello world!\"\n"
  },
  {
    "path": "test/unittests/util/test_encrypt.py",
    "content": "import uuid\n\nimport pytest\n\nfrom conan.internal.api.remotes import encrypt\n\n\ndef test_encryp_basic():\n    key = str(uuid.uuid4())\n    message = 'simple data ascii string'\n\n    data = encrypt.encode(message, key)\n    assert isinstance(data, str)\n\n    decoded = encrypt.decode(data, key)\n    assert message == decoded\n\n\ndef test_encrypt_unicode():\n    key = str(uuid.uuid4())\n    message_enc = b'espa\\xc3\\xb1a\\xe2\\x82\\xac$'  # Conan codebase allows only ASCII source files\n    message = message_enc.decode('utf-8')\n\n    data = encrypt.encode(message, key)\n    assert isinstance(data, str)\n\n    decoded = encrypt.decode(data, key)\n    assert message == decoded\n\n\ndef test_key_unicode():\n    key = b'espa\\xc3\\xb1a\\xe2\\x82\\xac$'.decode('utf-8')  # codebase allows only ASCII files\n    message = 'the message'\n\n    data = encrypt.encode(message, key)\n    assert isinstance(data, str)\n\n    decoded = encrypt.decode(data, key)\n    assert message == decoded\n\n\ndef test_key_empty():\n    # Empty keys, or keys with only non-ascii chars are not allowed\n    with pytest.raises(AssertionError):\n        encrypt.encode('message', '')\n\n    with pytest.raises(AssertionError):\n        encrypt.encode('message', b'\\xc3\\xb1\\xe2\\x82\\xac'.decode('utf-8'))\n"
  },
  {
    "path": "test/unittests/util/tools_test.py",
    "content": "import os\nimport platform\nimport subprocess\n\nimport pytest\n\nfrom conan.tools.files import replace_in_file, collect_libs\nfrom conan.internal.model.cpp_info import CppInfo\nfrom conan.internal.model.layout import Infos\nfrom conan.test.utils.mocks import ConanFileMock, RedirectedTestOutput\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.test.utils.tools import redirect_output\nfrom conan.test.utils.env import environment_update\nfrom conan.internal.util.files import load, md5, save\nfrom conan.internal.util.runners import check_output_runner\n\n\ndef test_replace_in_file():\n    text = u'J\\xe2nis\\xa7'\n    tmp_folder = temp_folder()\n\n    win_file = os.path.join(tmp_folder, \"win_encoding.txt\")\n    text = text.encode(\"Windows-1252\", \"ignore\")\n    with open(win_file, \"wb\") as handler:\n        handler.write(text)\n    replace_in_file(ConanFileMock(), win_file, \"nis\", \"nus\", encoding=\"Windows-1252\")\n\n    content = load(win_file, encoding=\"Windows-1252\")\n    assert \"nis\" not in  content\n    assert \"nus\" in content\n\n\nclass TestToolsTest:\n\n    def test_load_save(self):\n        folder = temp_folder()\n        path = os.path.join(folder, \"file\")\n        save(path, u\"äüïöñç\")\n        content = load(path)\n        assert content == u\"äüïöñç\"\n\n    def test_md5(self):\n        result = md5(u\"äüïöñç\")\n        assert \"dfcc3d74aa447280a7ecfdb98da55174\" == result\n\n    def test_environment_nested(self):\n        with environment_update({\"A\": \"1\", \"Z\": \"40\"}):\n            with environment_update({\"A\": \"1\", \"B\": \"2\"}):\n                with environment_update({\"A\": \"2\", \"B\": \"2\"}):\n                    assert os.getenv(\"A\") == \"2\"\n                    assert os.getenv(\"B\") == \"2\"\n                    assert os.getenv(\"Z\") == \"40\"\n                assert os.getenv(\"A\") == \"1\"\n                assert os.getenv(\"B\",) == \"2\"\n            assert os.getenv(\"A\",) == \"1\"\n            assert os.getenv(\"Z\") == \"40\"\n\n        assert os.getenv(\"A\") is None\n        assert os.getenv(\"B\") is None\n        assert os.getenv(\"Z\") is None\n\n    def test_check_output_runner(self):\n        payload = \"hello world\"\n        output = check_output_runner(\"echo {}\".format(payload), stderr=subprocess.STDOUT)\n        assert payload in str(output)\n\n\nclass TestCollectLib:\n\n    def test_collect_libs(self):\n        output = RedirectedTestOutput()\n        with (redirect_output(output)):\n            conanfile = ConanFileMock()\n            # Without package_folder\n            result = collect_libs(conanfile)\n            assert []  == result\n\n            # Default behavior\n            conanfile.folders.set_base_package(temp_folder())\n            mylib_path = os.path.join(conanfile.package_folder, \"lib\", \"mylib.lib\")\n            save(mylib_path, \"\")\n            conanfile.cpp = Infos()\n            result = collect_libs(conanfile)\n            assert [\"mylib\"]  == result\n\n            # Custom folder\n            customlib_path = os.path.join(conanfile.package_folder, \"custom_folder\", \"customlib.lib\")\n            save(customlib_path, \"\")\n            result = collect_libs(conanfile, folder=\"custom_folder\")\n            assert [\"customlib\"]  == result\n\n            # Custom folder doesn't exist\n            result = collect_libs(conanfile, folder=\"fake_folder\")\n            assert []  == result\n            assert \"Lib folder doesn't exist, can't collect libraries:\" in output.getvalue()\n            output.clear()\n\n            # Use cpp_info.libdirs\n            conanfile.cpp_info.libdirs = [\"lib\", \"custom_folder\"]\n            result = collect_libs(conanfile)\n            assert [\"customlib\", \"mylib\"]  == result\n\n            # Custom folder with multiple libdirs should only collect from custom folder\n            assert [\"lib\", \"custom_folder\"] == conanfile.cpp_info.libdirs\n            result = collect_libs(conanfile, folder=\"custom_folder\")\n            assert [\"customlib\"]  == result\n\n            # Warn same lib different folders\n            conanfile = ConanFileMock()\n            conanfile.folders.set_base_package(temp_folder())\n            conanfile.cpp = Infos()\n            custom_mylib_path = os.path.join(conanfile.package_folder, \"custom_folder\", \"mylib.lib\")\n            lib_mylib_path = os.path.join(conanfile.package_folder, \"lib\", \"mylib.lib\")\n            save(custom_mylib_path, \"\")\n            save(lib_mylib_path, \"\")\n            conanfile.cpp_info.libdirs = [\"lib\", \"custom_folder\"]\n\n            output.clear()\n            result = collect_libs(conanfile)\n            assert [\"mylib\"]  == result\n\n            # Warn lib folder does not exist with correct result\n            conanfile = ConanFileMock()\n            conanfile.folders.set_base_package(temp_folder())\n            conanfile.cpp = Infos()\n            lib_mylib_path = os.path.join(conanfile.package_folder, \"lib\", \"mylib.lib\")\n            save(lib_mylib_path, \"\")\n            no_folder_path = os.path.join(conanfile.package_folder, \"no_folder\")\n            conanfile.cpp_info.libdirs = [\"no_folder\", \"lib\"]  # 'no_folder' does NOT exist\n            output.clear()\n            result = collect_libs(conanfile)\n            assert [\"mylib\"]  == result\n            assert (\"WARN: Lib folder doesn't exist, \"\n                    \"can't collect libraries: %s\") % no_folder_path in output.getvalue()\n\n    @pytest.mark.skipif(platform.system() == \"Windows\", reason=\"Needs symlinks support\")\n    def test_collect_libs_symlinks(self):\n        # Keep only the shortest lib name per group of symlinks\n        conanfile = ConanFileMock()\n        conanfile.folders.set_base_package(temp_folder())\n        conanfile.cpp_info = CppInfo(set_defaults=True)\n        version_mylib_path = os.path.join(conanfile.package_folder, \"lib\", \"libmylib.1.0.0.dylib\")\n        soversion_mylib_path = os.path.join(conanfile.package_folder, \"lib\", \"libmylib.1.dylib\")\n        lib_mylib_path = os.path.join(conanfile.package_folder, \"lib\", \"libmylib.dylib\")\n        lib_mylib2_path = os.path.join(conanfile.package_folder, \"lib\", \"libmylib.2.dylib\")\n        lib_mylib3_path = os.path.join(conanfile.package_folder, \"custom_folder\", \"libmylib.3.dylib\")\n        save(version_mylib_path, \"\")\n        os.symlink(version_mylib_path, soversion_mylib_path)\n        os.symlink(soversion_mylib_path, lib_mylib_path)\n        save(lib_mylib2_path, \"\")\n        save(lib_mylib3_path, \"\")\n        conanfile.cpp_info.libdirs = [\"lib\", \"custom_folder\"]\n        result = collect_libs(conanfile)\n        assert [\"mylib\", \"mylib.2\", \"mylib.3\"]  == result\n\n    def test_self_collect_libs(self):\n        output = RedirectedTestOutput()\n        with redirect_output(output):\n            conanfile = ConanFileMock()\n            # Without package_folder\n            result = collect_libs(conanfile)\n            assert []  == result\n\n            # Default behavior\n            conanfile.folders.set_base_package(temp_folder())\n            mylib_path = os.path.join(conanfile.package_folder, \"lib\", \"mylib.lib\")\n            save(mylib_path, \"\")\n            conanfile.cpp = Infos()\n            result = collect_libs(conanfile)\n            assert [\"mylib\"]  == result\n\n            # Custom folder\n            customlib_path = os.path.join(conanfile.package_folder, \"custom_folder\", \"customlib.lib\")\n            save(customlib_path, \"\")\n            result = collect_libs(conanfile, folder=\"custom_folder\")\n            assert [\"customlib\"]  == result\n\n            # Custom folder doesn't exist\n            output.clear()\n            result = collect_libs(conanfile, folder=\"fake_folder\")\n            assert []  == result\n            assert \"Lib folder doesn't exist, can't collect libraries:\" in output.getvalue()\n\n            # Use cpp_info.libdirs\n            conanfile.cpp_info.libdirs = [\"lib\", \"custom_folder\"]\n            result = collect_libs(conanfile)\n            assert [\"customlib\", \"mylib\"]  == result\n\n            # Custom folder with multiple libdirs should only collect from custom folder\n            assert [\"lib\", \"custom_folder\"] == conanfile.cpp_info.libdirs\n            result = collect_libs(conanfile, folder=\"custom_folder\")\n            assert [\"customlib\"]  == result\n\n            # Warn same lib different folders\n            conanfile = ConanFileMock()\n            conanfile.folders.set_base_package(temp_folder())\n            conanfile.cpp = Infos()\n            custom_mylib_path = os.path.join(conanfile.package_folder, \"custom_folder\", \"mylib.lib\")\n            lib_mylib_path = os.path.join(conanfile.package_folder, \"lib\", \"mylib.lib\")\n            save(custom_mylib_path, \"\")\n            save(lib_mylib_path, \"\")\n            conanfile.cpp_info.libdirs = [\"lib\", \"custom_folder\"]\n            output.clear()\n            result = collect_libs(conanfile)\n            assert [\"mylib\"]  == result\n\n            # Warn lib folder does not exist with correct result\n            conanfile = ConanFileMock()\n            conanfile.folders.set_base_package(temp_folder())\n            conanfile.cpp = Infos()\n            lib_mylib_path = os.path.join(conanfile.package_folder, \"lib\", \"mylib.lib\")\n            save(lib_mylib_path, \"\")\n            no_folder_path = os.path.join(conanfile.package_folder, \"no_folder\")\n            conanfile.cpp_info.libdirs = [\"no_folder\", \"lib\"]  # 'no_folder' does NOT exist\n            output.clear()\n            result = collect_libs(conanfile)\n            assert [\"mylib\"]  == result\n            assert (\"WARN: Lib folder doesn't exist, \"\n                    \"can't collect libraries: %s\" % no_folder_path in output.getvalue())\n\n    @pytest.mark.skipif(platform.system() == \"Windows\", reason=\"Needs symlinks support\")\n    def test_self_collect_libs_symlinks(self):\n        # Keep only the shortest lib name per group of symlinks\n        conanfile = ConanFileMock()\n        conanfile.folders.set_base_package(temp_folder())\n        conanfile.cpp_info = CppInfo(set_defaults=True)\n        version_mylib_path = os.path.join(conanfile.package_folder, \"lib\", \"libmylib.1.0.0.dylib\")\n        soversion_mylib_path = os.path.join(conanfile.package_folder, \"lib\", \"libmylib.1.dylib\")\n        lib_mylib_path = os.path.join(conanfile.package_folder, \"lib\", \"libmylib.dylib\")\n        lib_mylib2_path = os.path.join(conanfile.package_folder, \"lib\", \"libmylib.2.dylib\")\n        lib_mylib3_path = os.path.join(conanfile.package_folder, \"custom_folder\", \"libmylib.3.dylib\")\n        save(version_mylib_path, \"\")\n        os.symlink(version_mylib_path, soversion_mylib_path)\n        os.symlink(soversion_mylib_path, lib_mylib_path)\n        save(lib_mylib2_path, \"\")\n        save(lib_mylib3_path, \"\")\n        conanfile.cpp_info.libdirs = [\"lib\", \"custom_folder\"]\n        result = collect_libs(conanfile)\n        assert [\"mylib\", \"mylib.2\", \"mylib.3\"]  == result\n"
  },
  {
    "path": "test/unittests/util/unix_path_test.py",
    "content": "import os\nimport platform\nimport pytest\n\nfrom conan.tools.microsoft.subsystems import subsystem_path\nfrom conan.internal.subsystems import get_cased_path\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.internal.util.files import mkdir\n\n\nclass TestGetCasedPath:\n    @pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows\")\n    def test_case_existing(self):\n        folder = get_cased_path(temp_folder())\n        p1 = os.path.join(folder, \"MyFolder\", \"Subfolder\")\n        mkdir(p1)\n\n        assert p1 == get_cased_path(p1)  # Idempotent\n        assert p1 == get_cased_path(os.path.join(folder, \"myfolder\", \"subfolder\"))\n\n    def test_case_not_existing(self):\n        current_dir = get_cased_path(os.getcwd())\n        non_existing_path = os.path.join(current_dir, \"this\", \"Path\", \"does\", \"NOT\", \"Exists\")\n        p = get_cased_path(non_existing_path)  # If not exists from the root, returns as is\n        assert p == non_existing_path\n\n    @pytest.mark.skipif(platform.system() != \"Windows\", reason=\"Requires Windows\")\n    def test_case_partial_exists(self):\n        folder = get_cased_path(temp_folder())\n        p1 = os.path.join(folder, \"MyFolder\", \"Subfolder\")\n        mkdir(p1)\n\n        non_existing_path = os.path.join(folder, \"myfolder\", \"subfolder\", \"not-existing\")\n        # The first part of the path will be properly cased.\n        assert os.path.join(p1, \"not-existing\") == get_cased_path(non_existing_path)\n\n\nclass TestUnixPath:\n\n    def test_none(self):\n        assert None == subsystem_path(None, path=None)\n\n    def test_msys_path(self):\n        assert '/c/windows/system32' == subsystem_path(\"msys2\", 'C:\\\\Windows\\\\System32')\n\n    def test_cygwin_path(self):\n        assert '/cygdrive/c/windows/system32' == subsystem_path(\"cygwin\",\n                                                               'C:\\\\Windows\\\\System32')\n\n        # another drive\n        assert '/cygdrive/d/work' == subsystem_path(\"cygwin\", \"D:\\\\work\")\n\n        # path inside the cygwin\n        assert '/home/.conan' == subsystem_path(\"cygwin\", '/home/.conan')\n        assert '/dev/null' == subsystem_path(\"cygwin\", '/dev/null')\n\n        # relative paths\n        assert './configure' == subsystem_path(\"cygwin\", './configure')\n        assert '../configure' == subsystem_path(\"cygwin\", '../configure')\n        assert 'source_subfolder/configure' == subsystem_path(\"cygwin\", 'source_subfolder/configure')\n\n        assert './configure' == subsystem_path(\"cygwin\", '.\\\\configure')\n        assert '../configure' == subsystem_path(\"cygwin\", '..\\\\configure')\n        assert 'source_subfolder/configure' == subsystem_path(\"cygwin\", 'source_subfolder\\\\configure')\n\n        # already with cygdrive\n        assert '/cygdrive/c/conan' == subsystem_path(\"cygwin\", '/cygdrive/c/conan')\n\n        # UNC (file share)\n        assert '//server/share' == subsystem_path(\"cygwin\", \"\\\\\\\\SERVER\\\\Share\")\n\n        # long path\n        assert '/cygdrive/c/windows/system32' == subsystem_path(\"cygwin\", '\\\\\\\\?\\\\C:\\\\Windows\\\\System32')\n\n    def test_wsl_path(self):\n        assert '/mnt/c/Windows/System32' == subsystem_path(\"wsl\", 'C:\\\\Windows\\\\System32')\n"
  },
  {
    "path": "test/unittests/util/xz_test.py",
    "content": "import os\nimport tarfile\n\nfrom conan.tools.files import unzip\nfrom conan.test.utils.mocks import ConanFileMock\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.internal.util.files import load, save\n\n\ndef test_unzip_can_xz():\n    tmp_dir = temp_folder()\n    file_path = os.path.join(tmp_dir, \"a_file.txt\")\n    save(file_path, \"my content!\")\n    txz = os.path.join(tmp_dir, \"sample.tar.xz\")\n    with tarfile.open(txz, \"w:xz\") as tar:\n        tar.add(file_path, \"a_file.txt\")\n\n    dest_folder = temp_folder()\n    unzip(ConanFileMock(), txz, dest_folder)\n    content = load(os.path.join(dest_folder, \"a_file.txt\"))\n    assert content == \"my content!\"\n\n\ndef test_unzip_can_gz():\n    tmp_dir = temp_folder()\n    file_path = os.path.join(tmp_dir, \"a_file.txt\")\n    save(file_path, \"my content!\")\n    gz = os.path.join(tmp_dir, \"sample.tar.gz\")\n    with tarfile.open(gz, \"w:gz\") as tar:\n        tar.add(file_path, \"a_file.txt\")\n\n    dest_folder = temp_folder()\n    unzip(ConanFileMock(), gz, dest_folder)\n    content = load(os.path.join(dest_folder, \"a_file.txt\"))\n    assert content == \"my content!\"\n"
  },
  {
    "path": "test/unittests/util/zip_permissions_test.py",
    "content": "import os\nimport platform\nimport stat\nimport zipfile\nfrom os.path import basename\nfrom unittest import TestCase\n\nfrom conan.tools.files import unzip\nfrom conan.test.utils.mocks import ConanFileMock\nfrom conan.test.utils.test_files import temp_folder\nfrom conan.internal.util.files import save\n\n\nclass ZipPermissionsTest(TestCase):\n\n    def test_permissions(self):\n        if platform.system() != \"Windows\":\n            for keep_permissions in [True, False]:\n                for perm_set in [stat.S_IRWXU, stat.S_IRUSR]:\n                    tmp_dir = temp_folder()\n                    file_path = os.path.join(tmp_dir, \"a_file.txt\")\n                    save(file_path, \"contents\")\n                    os.chmod(file_path, perm_set)\n                    zf = zipfile.ZipFile(os.path.join(tmp_dir, 'zipfile.zip'), mode='w')\n                    zf.write(file_path, basename(file_path))\n                    zf.close()\n\n                    # Unzip and check permissions are kept\n                    dest_dir = temp_folder()\n                    unzip(ConanFileMock(), os.path.join(tmp_dir, 'zipfile.zip'), dest_dir,\n                          keep_permissions=keep_permissions)\n\n                    dest_file = os.path.join(dest_dir, \"a_file.txt\")\n                    if keep_permissions:\n                        self.assertEqual(stat.S_IMODE(os.stat(dest_file).st_mode), perm_set)\n                    else:\n                        self.assertNotEqual(stat.S_IMODE(os.stat(dest_file).st_mode), perm_set)\n"
  }
]